+static char basic_lcase(char c)
+{
+ if ('A' <= c && c <= 'Z')
+ return c - 'A' + 'a';
+ return c;
+}
+
+static int cdidcmp(const char *id1, const char *id2)
+{
+ while (*id1 != 0 && *id2 != 0) {
+ if (*id1 == '_') { id1++; continue; }
+ if (*id2 == '_') { id2++; continue; }
+ if (basic_lcase(*id1) != basic_lcase(*id2))
+ break;
+ id1++;
+ id2++;
+ }
+
+ return *id1 - *id2;
+}
+
+static void parse_cwcheat(void)
+{
+ char line[256], buf[256], name[256], *p;
+ int newcheat = 1;
+ u32 a, v;
+ FILE *f;
+
+ f = fopen("cheatpops.db", "r");
+ if (f == NULL)
+ return;
+
+ /* find the game */
+ while (fgets(line, sizeof(line), f)) {
+ if (sscanf(line, "_S %63s", buf) != 1)
+ continue;
+ if (cdidcmp(buf, CdromId) == 0)
+ break;
+ }
+
+ if (feof(f))
+ goto out;
+
+ SysPrintf("cwcheat section found for %s\n", CdromId);
+ while (fgets(line, sizeof(line), f))
+ {
+ p = line + strlen(line);
+ for (p--; p >= line && (*p == '\r' || *p == '\n' || *p == ' '); p--)
+ *p = 0;
+ if (*p == 0 || *p == '#' || *p == ';')
+ continue;
+
+ if (strncmp(line, "_S", 2) == 0)
+ break;
+ if (strncmp(line, "_G", 2) == 0) {
+ SysPrintf(" cwcheat game name: '%s'\n", line + 3);
+ continue;
+ }
+ if (strncmp(line, "_C0", 3) == 0) {
+ if (!newcheat && Cheats[NumCheats - 1].n == 0) {
+ SysPrintf("cheat '%s' failed to parse\n", name);
+ free(Cheats[NumCheats - 1].Descr);
+ NumCheats--;
+ }
+ snprintf(name, sizeof(name), "%s", line + 4);
+ newcheat = 1;
+ continue;
+ }
+ if (sscanf(line, "_L %x %x", &a, &v) != 2) {
+ SysPrintf("line failed to parse: '%s'\n", line);
+ continue;
+ }
+
+ if (newcheat) {
+ if (NumCheats >= NumCheatsAllocated) {
+ NumCheatsAllocated += 16;
+ Cheats = realloc(Cheats, sizeof(Cheat) *
+ NumCheatsAllocated);
+ if (Cheats == NULL)
+ break;
+ }
+ Cheats[NumCheats].Descr = strdup(name);
+ Cheats[NumCheats].Enabled = 0;
+ Cheats[NumCheats].WasEnabled = 0;
+ Cheats[NumCheats].First = NumCodes;
+ Cheats[NumCheats].n = 0;
+ NumCheats++;
+ newcheat = 0;
+ }
+
+ if (NumCodes >= NumCodesAllocated) {
+ NumCodesAllocated += 16;
+ CheatCodes = realloc(CheatCodes, sizeof(CheatCode) *
+ NumCodesAllocated);
+ if (CheatCodes == NULL)
+ break;
+ }
+ CheatCodes[NumCodes].Addr = a;
+ CheatCodes[NumCodes].Val = v;
+ NumCodes++;
+ Cheats[NumCheats - 1].n++;
+ }
+
+out:
+ fclose(f);
+}
+
+void emu_on_new_cd(int show_hud_msg)
+{
+ ClearAllCheats();
+ parse_cwcheat();
+
+ if (Config.HLE) {
+ SysPrintf("note: running with HLE BIOS, expect compatibility problems\n");
+ SysPrintf("----------------------------------------------------------\n");
+ }
+ if (Config.TurboCD)
+ SysPrintf("note: TurboCD is enabled, this breaks games\n");
+
+ if (show_hud_msg) {
+ if (check_unsatisfied_libcrypt())
+ snprintf(hud_msg, sizeof(hud_msg),
+ "LibCrypt protected game with missing SBI detected");
+ else
+ snprintf(hud_msg, sizeof(hud_msg), BOOT_MSG);
+ hud_new_msg = 3;
+ }
+}
+
+static void log_wrong_cpu(void)
+{
+#if DO_CPU_CHECKS
+ __builtin_cpu_init();
+ #define CHECK_CPU(name) if (!__builtin_cpu_supports(name)) \
+ SysPrintf("ERROR: compiled for " name ", which is unsupported by the CPU\n")
+#ifdef __SSE2__
+ CHECK_CPU("sse2");
+#endif
+#ifdef __SSSE3__
+ CHECK_CPU("ssse3");
+#endif
+#ifdef __SSE4_1__
+ CHECK_CPU("sse4.1");
+#endif
+#endif // DO_CPU_CHECKS
+}
+
+#define MKSTR2(x) #x
+#define MKSTR(x) MKSTR2(x)
+static const char *get_build_info(void)
+{
+ return " ("
+#ifdef __VERSION__
+ "cc " __VERSION__ " "
+#endif
+#if defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ == 8
+ "64bit "
+#elif defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ == 4
+ "32bit "
+#endif
+#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ "be "
+#endif
+#if defined(__PIC__) || defined(__pic__)
+ "pic "
+#endif
+#if defined(__aarch64__)
+ "arm64"
+#elif defined(__arm__)
+ "arm"
+#endif
+#ifdef __ARM_ARCH
+ "v" MKSTR(__ARM_ARCH) " "
+#endif
+#if defined(__AVX__)
+ "avx "
+#elif defined(__SSSE3__)
+ "ssse3 "
+#elif defined(__ARM_NEON) || defined(__ARM_NEON__)
+ "neon "
+#endif
+#if defined(LIGHTREC)
+ "lightrec "
+#elif !defined(DRC_DISABLE)
+ "ari64 "
+#endif
+ "gpu=" MKSTR(BUILTIN_GPU)
+ ")";
+}
+
+int emu_core_preinit(void)