peter1138@2847: /* $Id$ */ peter1138@2847: egladil@8461: #define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_3 egladil@8461: #include egladil@8461: bjarni@2188: #include bjarni@2188: bjarni@3127: #include bjarni@3127: #include bjarni@3127: #include bjarni@3127: #include bjarni@3127: #include bjarni@3127: #include "../../stdafx.h" tron@3130: #include "../../macros.h" bjarni@3127: bjarni@3127: #ifndef CPU_SUBTYPE_POWERPC_970 bjarni@3127: #define CPU_SUBTYPE_POWERPC_970 ((cpu_subtype_t) 100) bjarni@3127: #endif bjarni@3127: bjarni@2188: /* bjarni@2188: * This file contains objective C bjarni@2188: * Apple uses objective C instead of plain C to interact with OS specific/native functions bjarni@2188: * bjarni@2188: * Note: TrueLight's crosscompiler can handle this, but it likely needs a manual modification for each change in this file. bjarni@2188: * To insure that the crosscompiler still works, let him try any changes before they are committed bjarni@2188: */ bjarni@2188: rubidium@5838: void ToggleFullScreen(bool fs); rubidium@5838: rubidium@6573: static char *GetOSString() bjarni@3127: { bjarni@3127: static char buffer[175]; tron@3130: const char* CPU; bjarni@3127: char OS[20]; bjarni@3127: char newgrf[125]; tron@3130: long sysVersion; tron@3130: extern const char _openttd_revision[]; bjarni@3127: bjarni@3127: // get the hardware info bjarni@3127: host_basic_info_data_t hostInfo; bjarni@3127: mach_msg_type_number_t infoCount; bjarni@3127: bjarni@3127: infoCount = HOST_BASIC_INFO_COUNT; tron@3130: host_info( tron@3130: mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo, &infoCount tron@3130: ); bjarni@3127: bjarni@3127: // replace the hardware info with strings, that tells a bit more than just an int bjarni@3127: switch (hostInfo.cpu_subtype) { tron@3130: #ifdef __POWERPC__ tron@3130: case CPU_SUBTYPE_POWERPC_750: CPU = "G3"; break; bjarni@3127: case CPU_SUBTYPE_POWERPC_7400: tron@3130: case CPU_SUBTYPE_POWERPC_7450: CPU = "G4"; break; tron@3130: case CPU_SUBTYPE_POWERPC_970: CPU = "G5"; break; tron@3130: default: CPU = "Unknown PPC"; break; tron@3130: #else tron@3130: /* it looks odd to have a switch for two cases, but it leaves room for easy tron@3130: * expansion. Odds are that Apple will some day use newer CPUs than i686 tron@3130: */ tron@3130: case CPU_SUBTYPE_PENTPRO: CPU = "i686"; break; tron@3130: default: CPU = "Unknown Intel"; break; tron@3130: #endif bjarni@3127: } bjarni@3127: bjarni@3127: // get the version of OSX tron@3130: if (Gestalt(gestaltSystemVersion, &sysVersion) != noErr) { tron@3130: sprintf(OS, "Undetected"); bjarni@3127: } else { tron@3130: int majorHiNib = GB(sysVersion, 12, 4); tron@3130: int majorLoNib = GB(sysVersion, 8, 4); tron@3130: int minorNib = GB(sysVersion, 4, 4); tron@3130: int bugNib = GB(sysVersion, 0, 4); bjarni@3127: bjarni@3127: sprintf(OS, "%d%d.%d.%d", majorHiNib, majorLoNib, minorNib, bugNib); bjarni@3127: } bjarni@3127: bjarni@3127: // make a list of used newgrf files rubidium@5838: /* if (_first_grffile != NULL) { tron@3130: char* n = newgrf; tron@3130: const GRFFile* file; bjarni@3127: bjarni@3127: for (file = _first_grffile; file != NULL; file = file->next) { tron@3130: n = strecpy(n, " ", lastof(newgrf)); tron@3130: n = strecpy(n, file->filename, lastof(newgrf)); bjarni@3127: } rubidium@5838: } else {*/ bjarni@3127: sprintf(newgrf, "none"); rubidium@5838: // } tron@3130: tron@3130: snprintf( tron@3130: buffer, lengthof(buffer), tron@3130: "Please add this info: (tip: copy-paste works)\n" tron@3130: "CPU: %s, OSX: %s, OpenTTD version: %s\n" tron@3130: "NewGRF files:%s", tron@3130: CPU, OS, _openttd_revision, newgrf tron@3130: ); bjarni@3127: return buffer; bjarni@3127: } bjarni@3127: truelight@2827: truelight@2827: #ifdef WITH_SDL truelight@2827: tron@3130: void ShowMacDialog(const char* title, const char* message, const char* buttonLabel) bjarni@2188: { bjarni@2188: NSRunAlertPanel([NSString stringWithCString: title], [NSString stringWithCString: message], [NSString stringWithCString: buttonLabel], nil, nil); bjarni@2188: } bjarni@2188: truelight@2827: #elif defined WITH_COCOA truelight@2827: tron@3130: void CocoaDialog(const char* title, const char* message, const char* buttonLabel); truelight@2827: tron@3130: void ShowMacDialog(const char* title, const char* message, const char* buttonLabel) truelight@2827: { truelight@2827: CocoaDialog(title, message, buttonLabel); truelight@2827: } truelight@2827: truelight@2827: truelight@2827: #else truelight@2827: tron@3130: void ShowMacDialog(const char* title, const char* message, const char* buttonLabel) truelight@2827: { truelight@2827: fprintf(stderr, "%s: %s\n", title, message); truelight@2827: } truelight@2827: truelight@2827: #endif truelight@2827: tron@3130: void ShowMacAssertDialog(const char* function, const char* file, const int line, const char* expression) bjarni@2223: { tron@3130: const char* buffer = tron@3130: [[NSString stringWithFormat:@ tron@3130: "An assertion has failed and OpenTTD must quit.\n" tron@3130: "%s in %s (line %d)\n" tron@3130: "\"%s\"\n" tron@3130: "\n" tron@3130: "You should report this error the OpenTTD developers if you think you found a bug.\n" tron@3130: "\n" tron@3130: "%s", tron@3130: function, file, line, expression, GetOSString()] cString tron@3130: ]; bjarni@2223: NSLog(@"%s", buffer); bjarni@3127: ToggleFullScreen(0); tron@3130: ShowMacDialog("Assertion Failed", buffer, "Quit"); bjarni@2736: bjarni@2223: // abort so that a debugger has a chance to notice bjarni@2223: abort(); bjarni@2223: } bjarni@3127: bjarni@3127: bjarni@3127: void ShowMacErrorDialog(const char *error) bjarni@3127: { tron@3130: const char* buffer = tron@3130: [[NSString stringWithFormat:@ tron@3130: "Please update to the newest version of OpenTTD\n" tron@3130: "If the problem presists, please report this to\n" tron@3130: "http://bugs.openttd.org\n" tron@3130: "\n" tron@3130: "%s", tron@3130: GetOSString()] cString tron@3130: ]; bjarni@3127: ToggleFullScreen(0); tron@3130: ShowMacDialog(error, buffer, "Quit"); bjarni@3127: abort(); bjarni@3127: } bjarni@7931: bjarni@7931: bjarni@7931: /** Determine the current user's locale. */ bjarni@7931: const char *GetCurrentLocale(const char *) bjarni@7931: { bjarni@7931: static char retbuf[32] = { '\0' }; bjarni@7931: NSUserDefaults* defs = [NSUserDefaults standardUserDefaults]; bjarni@7931: NSArray* languages = [defs objectForKey:@"AppleLanguages"]; bjarni@7931: NSString* preferredLang = [languages objectAtIndex:0]; bjarni@7931: /* preferredLang is either 2 or 5 characters long ("xx" or "xx_YY"). */ bjarni@8480: bjarni@8480: /* MacOS 10.3.9 can't handle encoding:NSASCIIStringEncoding bjarni@8480: * we will completely disable compiling it for such old targets to avoid a warning */ bjarni@8480: #if (MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_3) bjarni@8480: /* Note: MAC_OS_X_VERSION_MAX_ALLOWED is the current OSX version/SDK by default */ egladil@8461: if (MacOSVersionIsAtLeast(10, 4, 0)) { egladil@8461: [ preferredLang getCString:retbuf maxLength:32 encoding:NSASCIIStringEncoding ]; egladil@8461: } else { bjarni@8480: #else bjarni@8480: /* 10.3.9 needs to start the { too */ bjarni@8480: { bjarni@8480: #endif egladil@8461: [ preferredLang getCString:retbuf maxLength:32 ]; egladil@8461: } bjarni@7931: return retbuf; bjarni@7931: } egladil@8461: egladil@8461: egladil@8461: /* egladil@8461: * This will only give an accurate result for versions before OS X 10.8 since it uses bcd encoding egladil@8461: * for the minor and bugfix version numbers and a scheme of representing all numbers from 9 and up egladil@8461: * with 9. This means we can't tell OS X 10.9 from 10.9 or 10.11. Please use GetMacOSVersionMajor() egladil@8461: * and GetMacOSVersionMinor() instead. egladil@8461: */ egladil@8461: static long GetMacOSVersion() egladil@8461: { egladil@8461: static long sysVersion = -1; egladil@8461: egladil@8461: if (sysVersion != -1) return sysVersion; egladil@8461: egladil@8461: if (Gestalt(gestaltSystemVersion, &sysVersion) != noErr) sysVersion = -1; egladil@8461: return sysVersion; egladil@8461: } egladil@8461: egladil@8461: long GetMacOSVersionMajor() egladil@8461: { egladil@8461: static long sysVersion = -1; egladil@8461: egladil@8461: if (sysVersion != -1) return sysVersion; egladil@8461: egladil@8461: sysVersion = GetMacOSVersion(); egladil@8461: if (sysVersion == -1) return -1; egladil@8461: egladil@8461: if (sysVersion >= 0x1040) { egladil@8461: if (Gestalt(gestaltSystemVersionMajor, &sysVersion) != noErr) sysVersion = -1; egladil@8461: } else { egladil@8461: sysVersion = GB(sysVersion, 12, 4) * 10 + GB(sysVersion, 8, 4); egladil@8461: } egladil@8461: egladil@8461: return sysVersion; egladil@8461: } egladil@8461: egladil@8461: long GetMacOSVersionMinor() egladil@8461: { egladil@8461: static long sysVersion = -1; egladil@8461: egladil@8461: if (sysVersion != -1) return sysVersion; egladil@8461: egladil@8461: sysVersion = GetMacOSVersion(); egladil@8461: if (sysVersion == -1) return -1; egladil@8461: egladil@8461: if (sysVersion >= 0x1040) { egladil@8461: if (Gestalt(gestaltSystemVersionMinor, &sysVersion) != noErr) sysVersion = -1; egladil@8461: } else { egladil@8461: sysVersion = GB(sysVersion, 4, 4); egladil@8461: } egladil@8461: egladil@8461: return sysVersion; egladil@8461: } egladil@8461: egladil@8461: long GetMacOSVersionBugfix() egladil@8461: { egladil@8461: static long sysVersion = -1; egladil@8461: egladil@8461: if (sysVersion != -1) return sysVersion; egladil@8461: egladil@8461: sysVersion = GetMacOSVersion(); egladil@8461: if (sysVersion == -1) return -1; egladil@8461: egladil@8461: if (sysVersion >= 0x1040) { egladil@8461: if (Gestalt(gestaltSystemVersionBugFix, &sysVersion) != noErr) sysVersion = -1; egladil@8461: } else { egladil@8461: sysVersion = GB(sysVersion, 0, 4); egladil@8461: } egladil@8461: egladil@8461: return sysVersion; egladil@8461: }