doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
DOOMController.mm
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 // -*- mode: objc -*-
30 #import "../../idlib/precompiled.h"
31 #import "DOOMController.h"
32 
33 #import <unistd.h>
34 #import <pthread.h>
35 
36 #import <Foundation/Foundation.h>
37 #import <Carbon/Carbon.h>
38 #import <AppKit/AppKit.h>
39 #import <OpenGL/gl.h>
40 
41 #import "macosx_common.h"
42 #import "macosx_local.h"
43 #import "macosx_sys.h"
44 
45 #import <fenv.h>
46 #import <sys/ucontext.h>
47 #import <mach/thread_status.h>
48 
49 #define MAX_KEYS 256
50 
51 static idStr savepath;
52 
53 extern bool key_overstrikeMode;
54 
55 #define TEST_FPU_EXCEPTIONS \
56 FPU_EXCEPTION_INVALID_OPERATION | \
57 FPU_EXCEPTION_DENORMALIZED_OPERAND | \
58 FPU_EXCEPTION_DIVIDE_BY_ZERO | \
59 /* FPU_EXCEPTION_NUMERIC_OVERFLOW | */ \
60 /* FPU_EXCEPTION_NUMERIC_UNDERFLOW | */ \
61 /* FPU_EXCEPTION_INEXACT_RESULT | */ \
62 0
63 
64 #define kRegKey @"RegCode"
65 
66 static const ControlID kRegCode1EditText = { 'RegC', 1 };
67 
69 {
70  char prefRegCode1[256];
71  bool okPressed;
72  WindowRef window;
73  ControlRef regCode1EditText;
74 };
75 
76 static OSErr DoRegCodeDialog( char* ioRegCode1 );
77 
78 
80 - (void)quakeMain;
82 - (BOOL)checkOS;
83 @end
84 
85 @implementation DOOMController
86 
87 /*
88 + (void)initialize;
89 {
90  static bool initialized = NO;
91 
92  [super initialize];
93  if ( initialized ) {
94  return;
95  }
96  initialized = YES;
97 }
98 */
99 
100 #define MAX_ARGC 1024
101 
102 - (void)applicationDidFinishLaunching:(NSNotification *)notification;
103 {
104  NS_DURING {
105  NSAssert(sizeof(bool) == 1, @"sizeof(bool) should equal 1 byte");
106  [self quakeMain];
107  } NS_HANDLER {
108  Sys_Error( (const char *)[ [ localException reason ] cString ] );
109  } NS_ENDHANDLER;
110  Sys_Quit();
111 }
112 
113 - (void)applicationWillHide:(NSNotification *)notification;
114 {
116 }
117 
118 - (void)applicationWillUnhide:(NSNotification *)notification;
119 {
120  Sys_InitInput();
121 }
122 
123 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
124 {
125  common->Quit();
126  return NSTerminateLater; // we never reach this
127 }
128 
129 #if 0
130 // Actions
131 
132 - (IBAction)paste:(id)sender;
133 {
134  int shiftWasDown, insertWasDown;
135  unsigned int currentTime;
136 
137  currentTime = Sys_Milliseconds();
138  // Save the original keyboard state
139  shiftWasDown = keys[K_SHIFT].down;
140  insertWasDown = keys[K_INS].down;
141  // Fake a Shift-Insert keyboard event
142  keys[K_SHIFT].down = true;
143  Posix_QueEvent(currentTime, SE_KEY, K_INS, true, 0, NULL);
144  Posix_QueEvent(currentTime, SE_KEY, K_INS, false, 0, NULL);
145  // Restore the original keyboard state
146  keys[K_SHIFT].down = shiftWasDown;
147  keys[K_INS].down = insertWasDown;
148 }
149 
150 extern void CL_Quit_f(void);
151 //extern void SetProgramPath(const char *path);
152 
153 
154 - (IBAction)requestTerminate:(id)sender;
155 {
156  //osxQuit();
157  common->Quit();
158 }
159 
160 - (void)showBanner;
161 {
162  static bool hasShownBanner = NO;
163 
164  if (!hasShownBanner) {
165  //cvar_t *showBanner;
166 
167  hasShownBanner = YES;
168  //showBanner = Cvar_Get("cl_showBanner", "1", 0);
169  //if ( showBanner->integer != 0 ) {
170  if ( true ) {
171  NSPanel *splashPanel;
172  NSImage *bannerImage;
173  NSRect bannerRect;
174  NSImageView *bannerImageView;
175 
176  bannerImage = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForImageResource:@"banner.jpg"]];
177  bannerRect = NSMakeRect(0.0, 0.0, [bannerImage size].width, [bannerImage size].height);
178 
179  splashPanel = [[NSPanel alloc] initWithContentRect:bannerRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
180 
181  bannerImageView = [[NSImageView alloc] initWithFrame:bannerRect];
182  [bannerImageView setImage:bannerImage];
183  [splashPanel setContentView:bannerImageView];
184  [bannerImageView release];
185 
186  [splashPanel center];
187  [splashPanel setHasShadow:YES];
188  [splashPanel orderFront: nil];
189  [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.5]];
190  [splashPanel close];
191 
192  [bannerImage release];
193  }
194  }
195 }
196 
197 // Services
198 
199 - (void)connectToServer:(NSPasteboard *)pasteboard userData:(NSString *)data error:(NSString **)error;
200 {
201  NSArray *pasteboardTypes;
202 
203  pasteboardTypes = [pasteboard types];
204  if ([pasteboardTypes containsObject:NSStringPboardType]) {
205  NSString *requestedServer;
206 
207  requestedServer = [pasteboard stringForType:NSStringPboardType];
208  if (requestedServer) {
209  Cbuf_AddText( va( "connect %s\n", [requestedServer cString]));
210  return;
211  }
212  }
213  *error = @"Unable to connect to server: could not find string on pasteboard";
214 }
215 
216 - (void)performCommand:(NSPasteboard *)pasteboard userData:(NSString *)data error:(NSString **)error;
217 {
218  NSArray *pasteboardTypes;
219 
220  pasteboardTypes = [pasteboard types];
221  if ([pasteboardTypes containsObject:NSStringPboardType]) {
222  NSString *requestedCommand;
223 
224  requestedCommand = [pasteboard stringForType:NSStringPboardType];
225  if (requestedCommand) {
226  Cbuf_AddText(va("%s\n", [requestedCommand cString]));
227  return;
228  }
229  }
230  *error = @"Unable to perform command: could not find string on pasteboard";
231 }
232 
233 #endif // commented out all the banners and actions
234 
235 @end
236 
237 @implementation DOOMController (Private)
238 
240 {
241  NSAutoreleasePool *pool;
242  int argc = 0;
243  const char *argv[MAX_ARGC];
244  NSProcessInfo *processInfo;
245  NSArray *arguments;
246  unsigned int argumentIndex, argumentCount;
247  //const char *cddir;
248  //NSFileManager *defaultManager;
249  //bool tryAgain;
250 
251  pool = [[NSAutoreleasePool alloc] init];
252 
253  [NSApp setServicesProvider:self];
254 
255  processInfo = [NSProcessInfo processInfo];
256  arguments = [processInfo arguments];
257  argumentCount = [arguments count];
258  for (argumentIndex = 0; argumentIndex < argumentCount; argumentIndex++) {
259  argv[argc++] = strdup([[arguments objectAtIndex:argumentIndex] cString]);
260  }
261  if (![[NSFileManager defaultManager] changeCurrentDirectoryPath:[[NSBundle mainBundle] resourcePath]]) {
262  Sys_Error("Could not access application resources");
263  }
264  //cddir = macosx_scanForLibraryDirectory();
265  /*
266  do {
267  tryAgain = NO;
268  defaultManager = [NSFileManager defaultManager];
269  if (![defaultManager fileExistsAtPath:@"./base/default.cfg"] && (!cddir || *cddir == '\0' || ![defaultManager fileExistsAtPath:[NSString stringWithFormat:@"%s/baseq3/pak0.pk3", cddir]])) {
270  NSString *message;
271 
272  if (!cddir || *cddir == '\0') {
273  message = [NSString stringWithFormat:@"Could not find DOOM levels."];
274  } else if (![defaultManager fileExistsAtPath:[NSString stringWithFormat:@"%s", cddir]]) {
275  message = [NSString stringWithFormat:@"Could not find DOOM levels: '%s' does not exist.", cddir];
276  } else {
277  message = [NSString stringWithFormat:@"Could not find DOOM levels: '%s' is not a complete DOOM installation.", cddir];
278  }
279  switch (NSRunAlertPanel(@"DOOM", @"%@", @"Quit", @"Find...", nil, message)) {
280  case NSAlertDefaultReturn:
281  default:
282  Sys_Quit();
283  break;
284  case NSAlertAlternateReturn:
285  tryAgain = YES;
286  break;
287  }
288  if (tryAgain) {
289  NSOpenPanel *openPanel;
290  int result;
291 
292  openPanel = [NSOpenPanel openPanel];
293  [openPanel setAllowsMultipleSelection:NO];
294  [openPanel setCanChooseDirectories:YES];
295  [openPanel setCanChooseFiles:NO];
296  result = [openPanel runModalForDirectory:nil file:nil];
297  if (result == NSOKButton) {
298  NSArray *filenames;
299 
300  filenames = [openPanel filenames];
301  if ([filenames count] == 1) {
302  NSString *cdPath;
303 
304  cdPath = [filenames objectAtIndex:0];
305  [[NSUserDefaults standardUserDefaults] setObject:cdPath forKey:@"CDPath"];
306  cddir = strdup([cdPath cString]);
307  }
308  }
309  }
310  }
311  } while (tryAgain);
312  */
313 /*
314  if (cddir && *cddir != '\0') {
315  SetProgramPath([[[NSString stringWithCString:cddir] stringByAppendingPathComponent:@"/x"] cString]);
316  }
317 */
318 
319  //Sys_FPU_EnableExceptions( TEST_FPU_EXCEPTIONS );
320 
321  Posix_EarlyInit( );
322 
323 #ifndef _DEBUG
324  if ( [self checkOS] == FALSE) {
325  common->Quit();
326  }
327 
328  if ( [self checkDVD] == FALSE) {
329  common->Quit();
330  }
331 #endif
332 
333  // need strncmp, can't use idlib before init
334 #undef strncmp
335  // Finder passes the process serial number as only argument after the program path
336  // nuke it if we see it
337  if ( argc > 1 && strncmp( argv[ 1 ], "-psn", 4 ) ) {
338  common->Init( argc-1, &argv[1], NULL );
339  } else {
340  common->Init( 0, NULL, NULL );
341  }
342 
343  Posix_LateInit( );
344 
345  [NSApp activateIgnoringOtherApps:YES];
346 
347  while (1) {
348 #ifdef OMNI_TIMER
349  OTPeriodicTimerReset();
350  OTNodeStart(RootNode);
351 #endif
352 
353  // maintain exceptions in case system calls are turning them off (is that needed)
354  //Sys_FPU_EnableExceptions( TEST_FPU_EXCEPTIONS );
355 
356  common->Frame();
357 
358  // We should think about doing this less frequently than every frame
359  [pool release];
360  pool = [[NSAutoreleasePool alloc] init];
361 #ifdef OMNI_TIMER
362  OTNodeStop(RootNode);
363 #endif
364  }
365 
366  [pool release];
367 }
368 
370 {
371  BOOL retval;
372  NSString *cdKey;
373  NSUserDefaults *userDefaults;
374 
375  userDefaults = [NSUserDefaults standardUserDefaults];
376  cdKey = [userDefaults stringForKey:kRegKey];
377 
378  retval = TRUE;
379  if ( cdKey == nil || [cdKey length] == 0 ) {
380  char regCode[256];
381  if ( DoRegCodeDialog( regCode ) != noErr ) {
382  retval = FALSE;
383  }
384  else {
385  [userDefaults setObject:[NSString stringWithCString: regCode] forKey:kRegKey];
386  [userDefaults synchronize];
387  }
388  }
389  return retval;
390 }
391 
393 {
394  OSErr err;
395  long gestaltOSVersion;
396  err = Gestalt(gestaltSystemVersion, &gestaltOSVersion);
397  if ( err || gestaltOSVersion < 0x1038 ) {
398  NSBundle *thisBundle = [ NSBundle mainBundle ];
399  NSString *messsage = [ thisBundle localizedStringForKey:@"InsufficientOS" value:@"No translation" table:nil ];
400  NSRunAlertPanel(@GAME_NAME, messsage, nil, nil, nil);
401  return FALSE;
402  }
403  return TRUE;
404 }
405 
406 - (BOOL)checkDVD
407 {
408  return TRUE;
409 }
410 
411 @end
412 
413 /*
414 ==============
415 Sys_EXEPath
416 ==============
417 */
418 const char *Sys_EXEPath( void ) {
419  static char exepath[ 1024 ];
420  strncpy( exepath, [ [ [ NSBundle mainBundle ] bundlePath ] cString ], 1024 );
421  return exepath;
422 }
423 
424 /*
425  ==========
426  Sys_DefaultSavePath
427  ==========
428  */
429 const char *Sys_DefaultSavePath(void) {
430 #if defined( ID_DEMO_BUILD )
431  sprintf( savepath, "%s/Library/Application Support/Doom 3 Demo", [NSHomeDirectory() cString] );
432 #else
433  sprintf( savepath, "%s/Library/Application Support/Doom 3", [NSHomeDirectory() cString] );
434 #endif
435  return savepath.c_str();
436 }
437 
438 /*
439 ==========
440 Sys_DefaultBasePath
441 ==========
442 */
443 const char *Sys_DefaultBasePath(void) {
444  static char basepath[ 1024 ];
445  strncpy( basepath, [ [ [ NSBundle mainBundle ] bundlePath ] cString ], 1024 );
446  char *snap = strrchr( basepath, '/' );
447  if ( snap ) {
448  *snap = '\0';
449  }
450  return basepath;
451 }
452 
453 /*
454 ===============
455 Sys_Shutdown
456 ===============
457 */
458 void Sys_Shutdown( void ) {
459  savepath.Clear();
460  Posix_Shutdown();
461 }
462 
463 
464 /*
465 ===============
466 Sys_GetProcessorId
467 ===============
468 */
470  int cpuid = CPUID_GENERIC;
471 #if defined(__ppc__)
472  cpuid |= CPUID_ALTIVEC;
473 #elif defined(__i386__)
475 #endif
476  return static_cast<cpuid_t>(cpuid);
477 }
478 
479 /*
480 ===============
481 Sys_GetProcessorString
482 ===============
483 */
484 const char *Sys_GetProcessorString( void ) {
485 #if defined(__ppc__)
486  return "ppc CPU with AltiVec extensions";
487 #elif defined(__i386__)
488  return "x86 CPU with MMX/SSE/SSE2/SSE3 extensions";
489 #else
490  #error
491  return NULL;
492 #endif
493 }
494 
495 /*
496 ===============
497 Sys_FPU_EnableExceptions
498 http://developer.apple.com/documentation/mac/PPCNumerics/PPCNumerics-154.html
499 http://developer.apple.com/documentation/Performance/Conceptual/Mac_OSX_Numerics/Mac_OSX_Numerics.pdf
500 ===============
501 */
502 
503 #define fegetenvd(x) asm volatile( "mffs %0" : "=f" (x) );
504 #define fesetenvd(x) asm volatile( "mtfsf 255,%0" : : "f" (x) );
505 enum {
512 };
513 
514 typedef union {
515  struct {
516  unsigned long hi;
517  unsigned long lo;
518  } i;
519  double d;
520 } hexdouble;
521 
522 static int exception_mask = 0;
523 
524 void Sys_FPU_EnableExceptions( int exceptions ) {
525 #if 0
527  // clear the flag before enabling the exception
528  asm( "mtfsb0 2" );
529  asm( "mtfsb0 7" );
530  asm( "mtfsb0 8" );
531  asm( "mtfsb0 9" );
532  asm( "mtfsb0 10" );
533  asm( "mtfsb0 11" );
534  asm( "mtfsb0 12" );
535  asm( "mtfsb0 21" );
536  asm( "mtfsb0 22" );
537  asm( "mtfsb0 23" );
538  // enable
539  asm( "mtfsb1 24" );
540  } else {
541  asm( "mtfsb0 24" );
542  }
543  if ( exceptions & FPU_EXCEPTION_DIVIDE_BY_ZERO ) {
544  asm( "mtfsb0 5" );
545  asm( "mtfsb1 27" );
546  } else {
547  asm( "mtfsb0 27" );
548  }
549  if ( exceptions & FPU_EXCEPTION_NUMERIC_OVERFLOW ) {
550  asm( "mtfsb0 3" );
551  asm( "mtfsb1 25" );
552  } else {
553  asm( "mtfsb0 25" );
554  }
555  if ( exceptions & FPU_EXCEPTION_NUMERIC_UNDERFLOW ) {
556  asm( "mtfsb0 4" );
557  asm( "mtfsb1 26" );
558  } else {
559  asm( "mtfsb0 26" );
560  }
561  if ( exceptions & FPU_EXCEPTION_INEXACT_RESULT ) {
562  asm( "mtfsb0 6" );
563  asm( "mtfsb0 13" );
564  asm( "mtfsb0 14" );
565  asm( "mtfsb1 28" );
566  } else {
567  asm( "mtfsb0 28" );
568  }
569 #elif defined(__ppc__)
570  hexdouble t;
571  exception_mask = 0;
573  exception_mask |= FE_ENABLE_INVALID;
574  }
575  if ( exceptions & FPU_EXCEPTION_DIVIDE_BY_ZERO ) {
576  exception_mask |= FE_ENABLE_DIVBYZERO;
577  }
578  if ( exceptions & FPU_EXCEPTION_NUMERIC_OVERFLOW ) {
579  exception_mask |= FE_ENABLE_OVERFLOW;
580  }
581  if ( exceptions & FPU_EXCEPTION_NUMERIC_UNDERFLOW ) {
582  exception_mask |= FE_ENABLE_UNDERFLOW;
583  }
584  if ( exceptions & FPU_EXCEPTION_INEXACT_RESULT ) {
585  exception_mask |= FE_ENABLE_INVALID;
586  }
587  Sys_Printf( "Sys_FPUEnableExceptions: 0x%x\n", exception_mask );
588  // clear the exception flags
589  feclearexcept( FE_ALL_EXCEPT );
590  // set the enable flags on the exceptions we want
591  fegetenvd( t.d );
592  t.i.lo &= ~FE_ENABLE_ALL_EXCEPT;
593  t.i.lo |= exception_mask;
594  fesetenvd( t.d );
595  Sys_Printf( "done\n" );
596 #endif
597 }
598 
599 /*
600 ===============
601 Sys_FPE_handler
602 ===============
603 */
604 void Sys_FPE_handler( int signum, siginfo_t *info, void *context ) {
605 #if defined(__ppc__)
606  int ret;
607  ppc_float_state_t *fs;
608  ppc_thread_state_t *ss;
609 
610  fs = &( (struct ucontext *)context )->uc_mcontext->fs;
611  ss = &( (struct ucontext *)context )->uc_mcontext->ss;
612 
613  Sys_Printf( "FPE at 0x%x:\n", info->si_addr );
614 
615  ret = fetestexcept( FE_ALL_EXCEPT );
616  if ( ret & FE_INEXACT ) {
617  Sys_Printf( "FE_INEXACT " );
618  }
619  if ( ret & FE_DIVBYZERO ) {
620  Sys_Printf( "FE_DIVBYZERO " );
621  }
622  if ( ret & FE_UNDERFLOW ) {
623  Sys_Printf( "FE_UNDERFLOW " );
624  }
625  if ( ret & FE_OVERFLOW ) {
626  Sys_Printf( "FE_OVERFLOW " );
627  }
628  if ( ret & FE_INVALID ) {
629  Sys_Printf( "FE_INVALID " );
630  }
631  Sys_Printf( "\n" );
632  // clear the exception flags
633  feclearexcept( FE_ALL_EXCEPT );
634  // re-arm
635  fs->fpscr &= exception_mask;
636  ss->srr0 += 4;
637 #endif
638 }
639 
640 /*
641 ===============
642 Sys_GetClockTicks
643 ===============
644 */
645 double Sys_GetClockTicks( void ) {
646  // NOTE that this only affects idTimer atm, which is only used for performance timing during developement
647 #warning FIXME: implement Sys_GetClockTicks
648  return 0.0;
649 }
650 
651 /*
652 ===============
653 Sys_ClockTicksPerSecond
654 ===============
655 */
657  // Our strategy is to query both Gestalt & IOKit and then take the larger of the two values.
658 
659  long gestaltSpeed, ioKitSpeed = -1;
660 
661  // GESTALT
662 
663  // gestaltProcClkSpeedMHz available in 10.3 needs to be used because CPU speeds have now
664  // exceeded the signed long that Gestalt returns.
665  long osVers;
666  OSErr err;
667  Gestalt(gestaltSystemVersion, &osVers);
668  if (osVers >= 0x1030)
669  err = Gestalt(gestaltProcClkSpeedMHz, &gestaltSpeed);
670  else
671  {
672  err = Gestalt(gestaltProcClkSpeed, &gestaltSpeed);
673  if (err == noErr)
674  gestaltSpeed = gestaltSpeed / 1000000;
675  }
676 
677  // IO KIT
678 
679  mach_port_t masterPort;
680  CFMutableDictionaryRef matchDict = nil;
681  io_iterator_t itThis;
682  io_service_t service = nil;
683 
684  if (IOMasterPort(MACH_PORT_NULL, &masterPort))
685  goto bail;
686 
687  matchDict = IOServiceNameMatching("cpus");
688  if (IOServiceGetMatchingServices(masterPort, matchDict, &itThis))
689  goto bail;
690 
691  service = IOIteratorNext(itThis);
692  while(service)
693  {
694  io_service_t ioCpu = NULL;
695  if (IORegistryEntryGetChildEntry(service, kIODeviceTreePlane, &ioCpu))
696  goto bail;
697 
698  if (ioCpu)
699  {
700  CFDataRef data = (CFDataRef)IORegistryEntryCreateCFProperty(ioCpu, CFSTR("clock-frequency"),kCFAllocatorDefault,0);
701  if (data)
702  ioKitSpeed = *((unsigned long*)CFDataGetBytePtr(data)) / 1000000;
703  }
704  service = IOIteratorNext(itThis);
705  }
706 
707  // Return the larger value
708 
709 bail:
710  return ( ioKitSpeed > gestaltSpeed ? ioKitSpeed : gestaltSpeed ) * 1000000.f;
711 }
712 
713 /*
714 ================
715 Sys_GetSystemRam
716 returns in megabytes
717 ================
718 */
719 int Sys_GetSystemRam( void ) {
720  long ramSize;
721 
722  if ( Gestalt( gestaltPhysicalRAMSize, &ramSize ) == noErr ) {
723  return ramSize / (1024*1024);
724  }
725  else
726  return 1024;
727 }
728 
729 /*
730 ================
731 Sys_GetVideoRam
732 returns in megabytes
733 ================
734 */
735 int Sys_GetVideoRam( void ) {
736  unsigned int i;
737  CFTypeRef typeCode;
738  long vramStorage = 64;
739  const short MAXDISPLAYS = 8;
740  CGDisplayCount displayCount;
741  io_service_t dspPorts[MAXDISPLAYS];
742  CGDirectDisplayID displays[MAXDISPLAYS];
743 
744  CGGetOnlineDisplayList( MAXDISPLAYS, displays, &displayCount );
745 
746  for ( i = 0; i < displayCount; i++ ) {
747  if ( Sys_DisplayToUse() == displays[i] ) {
748  dspPorts[i] = CGDisplayIOServicePort(displays[i]);
749  typeCode = IORegistryEntryCreateCFProperty( dspPorts[i], CFSTR("IOFBMemorySize"), kCFAllocatorDefault, kNilOptions );
750  if( typeCode && CFGetTypeID( typeCode ) == CFNumberGetTypeID() ) {
751  CFNumberGetValue( ( CFNumberRef )typeCode, kCFNumberSInt32Type, &vramStorage );
752  vramStorage /= (1024*1024);
753  }
754  }
755  }
756 
757  return vramStorage;
758 }
759 
760 bool OSX_GetCPUIdentification( int& cpuId, bool& oldArchitecture )
761 {
762  long cpu;
763  Gestalt(gestaltNativeCPUtype, &cpu);
764 
765  cpuId = cpu;
766  oldArchitecture = cpuId < gestaltCPU970;
767  return true;
768 }
769 
770 void OSX_GetVideoCard( int& outVendorId, int& outDeviceId )
771 {
772  kern_return_t err;
773  mach_port_t masterPort;
774  io_iterator_t itThis;
775  io_service_t service;
776 
777  outVendorId = -1;
778  outDeviceId = -1;
779 
780  // Get a mach port for us and check for errors
781  err = IOMasterPort(MACH_PORT_NULL, &masterPort);
782  if(err)
783  return;
784  // Grab all the PCI devices out of the registry
785  err = IOServiceGetMatchingServices(masterPort, IOServiceMatching("IOPCIDevice"), &itThis);
786  if(err)
787  return;
788 
789  // Yank everything out of the iterator
790  // We could walk through all devices and try to determine the best card. But for now,
791  // we'll just look at the first card.
792  while(1)
793  {
794  service = IOIteratorNext(itThis);
795  io_name_t dName;
796 
797  // Make sure we have a valid service
798  if(service)
799  {
800  // Get the classcode so we know what we're looking at
801  CFDataRef classCode = (CFDataRef)IORegistryEntryCreateCFProperty(service,CFSTR("class-code"),kCFAllocatorDefault,0);
802  // Only accept devices that are
803  // PCI Spec - 0x00030000 is a display device
804  if((*(UInt32*)CFDataGetBytePtr(classCode) & 0x00ff0000) == 0x00030000)
805  {
806  // Get the name of the service (hw)
807  IORegistryEntryGetName(service, dName);
808 
809  CFDataRef vendorID, deviceID;
810 
811  // Get the information for the device we've selected from the list
812  vendorID = (CFDataRef)IORegistryEntryCreateCFProperty(service, CFSTR("vendor-id"),kCFAllocatorDefault,0);
813  deviceID = (CFDataRef)IORegistryEntryCreateCFProperty(service, CFSTR("device-id"),kCFAllocatorDefault,0);
814 
815  outVendorId = *((long*)CFDataGetBytePtr(vendorID));
816  outDeviceId = *((long*)CFDataGetBytePtr(deviceID));
817 
818  CFRelease(vendorID);
819  CFRelease(deviceID);
820  }
821  CFRelease(classCode);
822 
823  // Stop after finding the first device
824  if (outVendorId != -1)
825  break;
826  }
827  else
828  break;
829  }
830 }
831 
832 /*
833 ===============
834 main
835 ===============
836 */
837 int main( int argc, const char *argv[] ) {
838  return NSApplicationMain( argc, argv );
839 }
840 
841 
842 #pragma mark -
843 
844 
845 bool FormatRegCode(const char* inRegCode, char* outRegCode)
846 {
847  // Clean up the reg code. Remove spaces. Accept only numbers/letters.
848  char* dst = outRegCode;
849  const char* src = inRegCode;
850  while (*src)
851  {
852  if (isalnum(*src))
853  *dst++ = *src;
854  else if (*src != ' ')
855  return false;
856  src++;
857  }
858  *dst = 0;
859 
860  // Reg codes are 18 characters in length
861  return strlen(outRegCode) == 18;
862 }
863 
864 /*
865  ===============
866  RegCodeHandler
867  ===============
868  */
869 static pascal OSStatus RegCodeHandler( EventHandlerCallRef inHandler, EventRef inEvent, void* inUserData )
870 {
871 #pragma unused( inHandler )
872 #if 1
873  // FIXME: the CD key API has changed for startup check support and expansion pack key support
874  return noErr;
875 #else
876  HICommand cmd;
877  OSStatus result = eventNotHandledErr;
878  RegCodeInfo* regCodeInfo = (RegCodeInfo*)inUserData;
879 
880  GetEventParameter( inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof( cmd ), NULL, &cmd );
881 
882  switch ( cmd.commandID ) {
883  case kHICommandOK:
884  bool fValid;
885  Size actualSize;
886  char cntrl[256];
887  char doomKey[256];
888  char strippedKey[256];
889 
890  fValid = false;
891  strippedKey[0] = doomKey[0] = NULL;
892  GetControlData ( regCodeInfo->regCode1EditText, kControlEntireControl, kControlEditTextTextTag, 256, cntrl, &actualSize );
893  cntrl[actualSize] = NULL;
894  if ( FormatRegCode( cntrl, strippedKey ) ) {
895  strncat( doomKey, strippedKey, 16 );
896  strcat( doomKey, " " );
897  strncat( doomKey, strippedKey + 16, 2 );
898  fValid = session->CheckKey( doomKey );
899  }
900  if ( fValid ) {
901  strcpy( regCodeInfo->prefRegCode1, doomKey );
902  session->SetCDKey( doomKey );
903  }
904  else {
905  unsigned char theError[512];
906  unsigned char theExplanation[512];
907  CFStringRef theErrorStr = CFCopyLocalizedString( CFSTR("DVD_KEY_ERROR"), "" );
908  CFStringRef theExplanationStr = CFCopyLocalizedString( CFSTR("DVD_KEY_EXPLANATION"), "" );
909  c2pstrcpy( theError, CFStringGetCStringPtr( theErrorStr, kCFStringEncodingMacRoman ) );
910  c2pstrcpy( theExplanation, CFStringGetCStringPtr( theExplanationStr, kCFStringEncodingMacRoman ) );
911 
912  StandardAlert(kAlertStopAlert, theError, theExplanation, NULL, NULL);
913 
914  // Highlight the invalid reg code
915  ClearKeyboardFocus(regCodeInfo->window);
916  SetKeyboardFocus( regCodeInfo->window, regCodeInfo->regCode1EditText, kControlEditTextPart );
917  ControlEditTextSelectionRec sel = {0, 32000};
918  SetControlData (regCodeInfo->regCode1EditText, kControlEntireControl, kControlEditTextSelectionTag, sizeof(sel), &sel);
919  break;
920  }
921 
922  regCodeInfo->okPressed = true;
923  QuitAppModalLoopForWindow( regCodeInfo->window );
924  result = noErr;
925 
926  break;
927 
928  case kHICommandCancel:
929  regCodeInfo->okPressed = false;
930  QuitAppModalLoopForWindow( regCodeInfo->window );
931  result = noErr;
932  break;
933 
934  }
935  return result;
936 #endif
937 }
938 
939 /*
940  ===============
941  DoRegCodeDialog
942  ===============
943  */
944 static OSErr DoRegCodeDialog( char* ioRegCode1 )
945 {
946  OSErr err;
947  RegCodeInfo regCodeInfo;
948  memset(&regCodeInfo, 0, sizeof(regCodeInfo));
949 
950  IBNibRef aslNib;
951  CFBundleRef theBundle = CFBundleGetMainBundle();
952  err = CreateNibReferenceWithCFBundle( theBundle, CFSTR("ASLCore"), &aslNib );
953  err = ::CreateWindowFromNib( aslNib, CFSTR("Reg Code Sheet"), &regCodeInfo.window );
954  if (err != noErr)
955  return err;
956 
957  GetControlByID( regCodeInfo.window, &kRegCode1EditText, &regCodeInfo.regCode1EditText );
958  assert( regCodeInfo.regCode1EditText );
959  SetKeyboardFocus( regCodeInfo.window, regCodeInfo.regCode1EditText, kControlEditTextPart );
960  ControlEditTextSelectionRec sel = {0, 32000};
961  SetControlData (regCodeInfo.regCode1EditText, kControlEntireControl, kControlEditTextSelectionTag, sizeof(sel), &sel);
962 
963  EventTypeSpec cmdEvent = { kEventClassCommand, kEventCommandProcess };
964  EventHandlerUPP handler = NewEventHandlerUPP( RegCodeHandler );
965  InstallWindowEventHandler( regCodeInfo.window, handler, 1, &cmdEvent, &regCodeInfo, NULL );
966 
967  RepositionWindow( regCodeInfo.window, NULL, kWindowAlertPositionOnMainScreen );
968  ShowWindow( regCodeInfo.window );
969 
970  RunAppModalLoopForWindow( regCodeInfo.window );
971 
972  DisposeWindow( regCodeInfo.window );
973 
974  if (regCodeInfo.okPressed) {
975  strcpy(ioRegCode1, regCodeInfo.prefRegCode1);
976  }
977 
978  return regCodeInfo.okPressed ? (OSErr)noErr : (OSErr)userCanceledErr;
979 }
980 
981 /*
982 =================
983 Sys_AsyncThread
984 =================
985 */
986 void Sys_AsyncThread( void ) {
987  while ( 1 ) {
988  usleep( 16666 );
989  common->Async();
991  pthread_testcancel();
992  }
993 }
994 
995 
996 #if defined(__ppc__)
997 
998 /*
999  ================
1000  Sys_FPU_SetDAZ
1001  ================
1002  */
1003 void Sys_FPU_SetDAZ( bool enable ) {
1004 }
1005 
1006 /*
1007  ================
1008  Sys_FPU_SetFTZ
1009  ================
1010  */
1011 void Sys_FPU_SetFTZ( bool enable ) {
1012 }
1013 
1014 
1015 #elif defined(__i386__)
1016 
1017 #include <xmmintrin.h>
1018 
1019 /*
1020  ================
1021  Sys_FPU_SetDAZ
1022  ================
1023  */
1024 void Sys_FPU_SetDAZ( bool enable ) {
1025  uint32_t dwData;
1026  uint32_t enable_l = (uint32_t) enable;
1027 
1028  enable_l = enable_l & 1;
1029  enable_l = enable_l << 6;
1030  dwData = _mm_getcsr(); // store MXCSR to dwData
1031  dwData = dwData & 0xffbf;
1032  dwData = dwData | enable_l;
1033  _mm_setcsr(dwData); // load MXCSR with dwData
1034 }
1035 
1036 /*
1037  ================
1038  Sys_FPU_SetFTZ
1039  ================
1040  */
1041 void Sys_FPU_SetFTZ( bool enable ) {
1042 
1043  uint32_t dwData;
1044  uint32_t enable_l = (uint32_t) enable;
1045 
1046  enable_l = enable_l & 1;
1047  enable_l = enable_l << 15;
1048  dwData = _mm_getcsr(); // store MXCSR to dwData
1049  dwData = dwData & 0x7fff;
1050  dwData = dwData | enable_l;
1051  _mm_setcsr(dwData); // load MXCSR with dwData
1052 }
1053 
1054 #endif
GetControlByID(prefInfo.window,&kFullscreenBtn,&prefInfo.fullscreenBtn)
const char * Sys_EXEPath(void)
int Sys_GetSystemRam(void)
assert(prefInfo.fullscreenBtn)
void OSX_GetVideoCard(int &outVendorId, int &outDeviceId)
#define fesetenvd(x)
#define GAME_NAME
Definition: Licensee.h:37
const char * Sys_DefaultBasePath(void)
void Sys_ShutdownInput(void)
Definition: dedicated.cpp:41
void Sys_Printf(const char *msg,...)
double Sys_ClockTicksPerSecond(void)
int Sys_Milliseconds(void)
CGDirectDisplayID Sys_DisplayToUse(void)
bool OSX_GetCPUIdentification(int &cpuId, bool &oldArchitecture)
const char * Sys_GetProcessorString(void)
void Sys_FPU_SetDAZ(bool enable)
Definition: main.cpp:475
GLuint src
Definition: glext.h:5390
cpuid_t Sys_GetProcessorId(void)
int i
Definition: process.py:33
#define BOOL
Definition: mprintf.c:71
Boolean result
virtual void Async(void)=0
CFBundleRef theBundle
void Sys_Quit(void)
Definition: macosx_sys.mm:173
virtual void Frame(void)=0
InstallWindowEventHandler(prefInfo.window, handler, 1,&cmdEvent,&prefInfo, NULL)
int main(int argc, const char *argv[])
struct hexdouble::@104 i
GLuint dst
Definition: glext.h:5285
void Sys_InitInput(void)
Definition: dedicated.cpp:39
Definition: KeyInput.h:73
void Sys_AsyncThread(void)
ControlRef regCode1EditText
bool key_overstrikeMode
Definition: KeyInput.cpp:195
void Posix_EarlyInit(void)
Definition: posix_main.cpp:538
idCommon * common
Definition: Common.cpp:206
#define NULL
Definition: Lib.h:88
cpuid_t
Definition: sys_public.h:142
void Posix_Shutdown(void)
Definition: posix_main.cpp:376
WindowRef window
void Clear(void)
Definition: Str.h:724
mach_port_t masterPort
Definition: showcursor.c:9
GLenum GLsizei width
Definition: glext.h:2846
bool down
Definition: KeyInput.cpp:189
#define context
Definition: getdate.c:236
int Sys_GetVideoRam(void)
bool FormatRegCode(const char *inRegCode, char *outRegCode)
GLenum GLsizei GLsizei height
Definition: glext.h:2856
#define fegetenvd(x)
char * strdup(char *s1)
Definition: main.c:183
virtual bool CheckKey(const char *key, bool netConnect, bool offline_valid[2])=0
unsigned long lo
void Sys_Shutdown(void)
EventTypeSpec cmdEvent
static WindowRef ValidModeCallbackProc inCallback OSStatus err
void Posix_QueEvent(sysEventType_t type, int value, int value2, int ptrLength, void *ptr)
Definition: posix_main.cpp:275
void Sys_TriggerEvent(int index)
GLsizeiptr size
Definition: glext.h:3112
char prefRegCode1[256]
idKey * keys
Definition: KeyInput.cpp:196
Definition: Str.h:116
double Sys_GetClockTicks(void)
GLsizei const GLcharARB const GLint * length
Definition: glext.h:3599
typedef void(APIENTRYP PFNGLBLENDCOLORPROC)(GLclampf red
const char * c_str(void) const
Definition: Str.h:487
#define FALSE
Definition: mprintf.c:70
IBNibRef aslNib
void Sys_Error(const char *error,...)
Definition: macosx_sys.mm:156
void Sys_FPE_handler(int signum, siginfo_t *info, void *context)
#define strncmp
Definition: Str.h:42
void Sys_FPU_SetFTZ(bool enable)
Definition: main.cpp:498
virtual void Quit(void)=0
#define TRUE
Definition: mprintf.c:69
void Sys_FPU_EnableExceptions(int exceptions)
EventHandlerUPP handler
idSession * session
Definition: Session.cpp:48
char * va(const char *fmt,...)
Definition: Str.cpp:1568
RepositionWindow(prefInfo.window, NULL, kWindowAlertPositionOnMainScreen)
unsigned long hi
int sprintf(idStr &string, const char *fmt,...)
Definition: Str.cpp:1528
virtual void Init(int argc, const char **argv, const char *cmdline)=0
const char * Sys_DefaultSavePath(void)
void Posix_LateInit(void)
Definition: posix_main.cpp:552
GLdouble GLdouble t
Definition: glext.h:2943