diff --git a/src/hookcrc32/Makefile b/src/hookcrc32/Makefile new file mode 100644 index 0000000..4a2e6f4 --- /dev/null +++ b/src/hookcrc32/Makefile @@ -0,0 +1,17 @@ +CC=gcc -m32 +CFLAGS = -g -O0 -fPIC -m32 -Wall -Werror -Wno-unused-variable -Wno-unused-function +LD = g++ -m32 +LDFLAGS = -Wl,-z,defs -rdynamic -static-libstdc++ -static-libgcc -lc -ldl -lGL -lglut -lX11 -lm -lpthread -shared -nostdlib + +BUILD = build + +OBJS := $(patsubst %.c,%.o,$(wildcard *.c)) + +all: hookcrc32.so + +hookcrc32.so: $(OBJS) + $(LD) $(OBJS) $(LDFLAGS) $(CFLAGS) -o hookcrc32.so + rm -f *.o + +clean: + rm -f hookcrc32.so diff --git a/src/hookcrc32/hookcrc32.c b/src/hookcrc32/hookcrc32.c new file mode 100644 index 0000000..4181782 --- /dev/null +++ b/src/hookcrc32/hookcrc32.c @@ -0,0 +1,95 @@ +#define _GNU_SOURCE +#include +#include +#include +#include + +static struct { + ElfW(Addr) start, end; +} *segments; +static int n; +static int (*real_main)(int argc,char **argv); + +uint32_t __crc32(const char *s,size_t n) { + uint32_t crc=0xFFFFFFFF; + + for(size_t i=0;i>=1; + if(b) crc=crc^0xEDB88320; + ch>>=1; + } + } + return ~crc; +} + +static int callback(struct dl_phdr_info *info, size_t size, void *data) { + /*n = info->dlpi_phnum; + segments = malloc(n * sizeof *segments); + for(int i = 0; i < n; ++i) { + segments[i].start = info->dlpi_addr + info->dlpi_phdr[i].p_vaddr; + segments[i].end = info->dlpi_addr + info->dlpi_phdr[i].p_vaddr + info->dlpi_phdr[i].p_memsz; + } + char *type; + int p_type; + printf("Name: \"%s\" (%d segments)\n", info->dlpi_name, info->dlpi_phnum); + for (int j = 0; j < info->dlpi_phnum; j++) { + p_type = info->dlpi_phdr[j].p_type; + type = (p_type == PT_LOAD) ? "PT_LOAD" : + (p_type == PT_DYNAMIC) ? "PT_DYNAMIC" : + (p_type == PT_INTERP) ? "PT_INTERP" : + (p_type == PT_NOTE) ? "PT_NOTE" : + (p_type == PT_INTERP) ? "PT_INTERP" : + (p_type == PT_PHDR) ? "PT_PHDR" : + (p_type == PT_TLS) ? "PT_TLS" : + (p_type == PT_GNU_EH_FRAME) ? "PT_GNU_EH_FRAME" : + (p_type == PT_GNU_STACK) ? "PT_GNU_STACK" : + (p_type == PT_GNU_RELRO) ? "PT_GNU_RELRO" : NULL; + + printf(" %2d: [%14p; memsz:0x%7x; size:0x%7x] flags: 0x%x; ", j, + (void *) (info->dlpi_addr + info->dlpi_phdr[j].p_vaddr), + info->dlpi_phdr[j].p_memsz, info->dlpi_phdr[j].p_filesz ,info->dlpi_phdr[j].p_flags); + if (type != NULL) + printf("%s\n", type); + else + printf("[other (0x%x)]\n", p_type);*/ + if((info->dlpi_phnum >= 3) && (info->dlpi_phdr[2].p_type == PT_LOAD) && (info->dlpi_phdr[2].p_flags == 5)) + { + // printf("Aca voy a dumpear el codigo:\n"); + //FILE *file = fopen("dump.bin","w+b"); + + //fwrite((void *)(info->dlpi_addr + info->dlpi_phdr[2].p_vaddr)+10,128,1,file); + //fclose(file); + int crc = 0; + crc = __crc32((void *)(info->dlpi_addr + info->dlpi_phdr[2].p_vaddr+10),128); + printf("Crc32: 0x%x\n",crc); + } + //} + return 1; +} + +__attribute__((__constructor__)) +static void setup(void) { + dl_iterate_phdr(callback, NULL); + //real_main = dlsym(RTLD_NEXT, "main"); + exit(0); +} + +__attribute__((__destructor__)) +static void teardown(void) { + free(segments); +} +/* +__attribute__((__noinline__)) +int main(int argc,char **argv) { + ElfW(Addr) addr = (ElfW(Addr))__builtin_extract_return_addr(__builtin_return_address(0)); + for(int i = 0; i < n; ++i) { + if(addr >= segments[i].start && addr < segments[i].end) { + // Do Nothing + return 0; + } + } + return real_main(argc, argv); +}*/ \ No newline at end of file diff --git a/src/libkswapapi/libkswapapi.o b/src/libkswapapi/libkswapapi.o deleted file mode 100644 index d480686..0000000 Binary files a/src/libkswapapi/libkswapapi.o and /dev/null differ diff --git a/src/lindbergh/config.c b/src/lindbergh/config.c index e77aff2..bd0bc31 100644 --- a/src/lindbergh/config.c +++ b/src/lindbergh/config.c @@ -28,7 +28,7 @@ static char *getNextToken(char *buffer, char *seperator, char **saveptr) return token; } -static int detectGame() +static int detectGame(uint32_t elf_crc) { // For a better way of doing this, we should look for strings inside the game @@ -36,19 +36,25 @@ static int detectGame() // strings %s | grep "RIDE TURN TEST" && strings %s | grep "PLEASE SHOOT GRID" // shows you its hotd4S for example - if (strstr(program_invocation_name, "segaboot")) + if (elf_crc == 0x93ea7e11) { - config.game = SEGABOOT; + config.game = SEGABOOT_2_4; return 0; } - if (strstr(program_invocation_name, "hod4")) + if (elf_crc == 0xbc0c9ffa) { config.game = THE_HOUSE_OF_THE_DEAD_4; return 0; } - if (strstr(program_invocation_name, "Jennifer")) + if (elf_crc == 0x7235bda8) + { + config.game = THE_HOUSE_OF_THE_DEAD_4_TEST; + return 0; + } + + if (elf_crc == 0x6d055308) { config.game = OUTRUN; config.emulateDriveboard = 1; @@ -56,7 +62,7 @@ static int detectGame() return 0; } - if (strstr(program_invocation_name, "JenTest")) + if (elf_crc == 0xffdccaaa) { config.game = OUTRUN_TEST; config.emulateDriveboard = 1; @@ -64,33 +70,43 @@ static int detectGame() return 0; } - if (strstr(program_invocation_name, "lgj")) + if (elf_crc == 0xd4726d61) { config.game = LETS_GO_JUNGLE; return 0; } - if (strstr(program_invocation_name, "abc1080")) + if (elf_crc == 0xcc02de7d) { - config.game = ABC; + config.game = ABC_2006; return 0; } - if (strstr(program_invocation_name, "drive")) + if (elf_crc == 0x152530dd) + { + config.game = ABC_2007; + return 0; + } + + if (elf_crc == 0xfb096f81) { config.game = SRTV; + config.emulateDriveboard = 1; + config.emulateMotionboard = 1; return 0; } - if (strstr(program_invocation_name, "dsr")) + if (elf_crc == 0xb05d9bbe) { config.game = RTUNED; + config.emulateDriveboard = 1; + config.emulateMotionboard = 1; return 0; } - - if (strstr(program_invocation_name, "vf5")) + + if (elf_crc == 0xc4b7e89) { - config.game = VF5; + config.game = VT3; return 0; } @@ -112,16 +128,19 @@ char *getGameName() return "Outrun 2 SP"; case THE_HOUSE_OF_THE_DEAD_4: return "The House of the Dead 4"; + case THE_HOUSE_OF_THE_DEAD_4_TEST: + return "The House of the Dead 4 - Test Menu"; case LETS_GO_JUNGLE: return "Let's Go Jungle! Lost on the Island of Spice"; - case ABC: + case ABC_2006: + case ABC_2007: return "After Burner Climax"; case SRTV: return "SEGA Race TV"; case RTUNED: return "R-Tuned Ultimate Street Racing"; - case VF5: - return "Virtua Fighter 5"; + case VT3: + return "Virtua Tennis 3"; default: return "Unknown Game"; } @@ -187,7 +206,7 @@ int readConfig(FILE *configFile, EmulatorConfig *config) return 0; } -int initConfig() +int initConfig(uint32_t elf_crc) { config.emulateRideboard = 0; config.emulateDriveboard = 0; @@ -203,17 +222,20 @@ int initConfig() strcpy(config.rideboardPath, "none"); config.width = 1024; config.height = 768; - - if (detectGame() != 0) + if (detectGame(elf_crc) != 0) { - printf("Warning: Unsure what game this is, using default configuration values\n"); + printf("Warning: Unsure what game this is, using default configuration values.\n"); + } + else + { + printf("Game Detected: %s\n", getGameName()); } configFile = fopen(CONFIG_PATH, "r"); if (configFile == NULL) { - printf("Warning: Cannot open %s, using default values\n", CONFIG_PATH); + printf("Warning: Cannot open %s, using default values.\n", CONFIG_PATH); return 1; } diff --git a/src/lindbergh/config.h b/src/lindbergh/config.h index 6aa1784..ce1645d 100644 --- a/src/lindbergh/config.h +++ b/src/lindbergh/config.h @@ -9,13 +9,15 @@ typedef enum SEGABOOT_2_4, SEGABOOT_2_6, THE_HOUSE_OF_THE_DEAD_4, + THE_HOUSE_OF_THE_DEAD_4_TEST, OUTRUN, OUTRUN_TEST, LETS_GO_JUNGLE, - ABC, + ABC_2006, + ABC_2007, SRTV, RTUNED, - VF5 + VT3 } Game; typedef enum diff --git a/src/lindbergh/hook.c b/src/lindbergh/hook.c index ab9529d..610a0c4 100644 --- a/src/lindbergh/hook.c +++ b/src/lindbergh/hook.c @@ -1,3 +1,5 @@ +#define _GNU_SOURCE +#include #include #include #include @@ -13,6 +15,7 @@ #include #include #include +#include #include "hook.h" @@ -38,19 +41,33 @@ int hooks[5] = {-1, -1, -1, -1}; FILE *fileHooks[2] = {NULL, NULL}; int fileRead[2] = {0, 0}; +uint32_t elf_crc = 0; + +cpuvendor cpu_vendor = {0}; + +static int callback(struct dl_phdr_info *info, size_t size, void *data); uint16_t basePortAddress = 0xFFFF; +/** + * Signal handler for the SIGSEGV signal, which is triggered when a process tries to access an illegal memory location. + * @param signal + * @param info + * @param ptr + */ static void handleSegfault(int signal, siginfo_t *info, void *ptr) { ucontext_t *ctx = ptr; + // Get the address of the instruction causing the segfault uint8_t *code = (uint8_t *)ctx->uc_mcontext.gregs[REG_EIP]; + printf("Code: 0x%08x - Port: 0x%08x\n", *code, (ctx->uc_mcontext.gregs[REG_EDX] & 0xFFFF)); switch (*code) { case 0xED: { + // Get the port number from the EDX register uint16_t port = ctx->uc_mcontext.gregs[REG_EDX] & 0xFFFF; // The first port called is usually random, but everything after that @@ -60,9 +77,11 @@ static void handleSegfault(int signal, siginfo_t *info, void *ptr) if (basePortAddress == 0xFFFF) basePortAddress = port; + // Adjust the port number if necessary if (port > 0x38) port = port - basePortAddress; + // Call the security board input function with the port number and data securityBoardIn(port, (uint32_t *)&(ctx->uc_mcontext.gregs[REG_EAX])); ctx->uc_mcontext.gregs[REG_EIP]++; @@ -70,15 +89,17 @@ static void handleSegfault(int signal, siginfo_t *info, void *ptr) } break; - case 0xE7: // OUT IMMIDIATE + case 0xE7: // OUT IMMEDIATE { + // Increment the instruction pointer by two to skip over this instruction ctx->uc_mcontext.gregs[REG_EIP] += 2; return; } break; - case 0xE6: // OUT IMMIDIATE + case 0xE6: // OUT IMMEDIATE { + // Increment the instruction pointer by two to skip over this instruction ctx->uc_mcontext.gregs[REG_EIP] += 2; return; } @@ -108,9 +129,14 @@ static void handleSegfault(int signal, siginfo_t *info, void *ptr) } } + void __attribute__((constructor)) hook_init() { printf("SEGA Lindbergh Loader\nRobert Dilley 2022\nNot for public consumption\n\n"); + // Get offsets of the Game's ELF and calculate CRC32. + dl_iterate_phdr(callback, NULL); + // Get CPU ID + getCPUID(); // Implement SIGSEGV handler struct sigaction act; @@ -118,9 +144,9 @@ void __attribute__((constructor)) hook_init() act.sa_flags = SA_SIGINFO; sigaction(SIGSEGV, &act, NULL); - initConfig(); + initConfig(elf_crc); - if (initPatch() != 0) + if(initPatch() != 0) exit(1); if (initEeprom() != 0) @@ -206,18 +232,30 @@ int open64(const char *pathname, int flags) return open(pathname, flags); } - - FILE *fopen(const char *restrict pathname, const char *restrict mode) { FILE *(*_fopen)(const char *restrict pathname, const char *restrict mode) = dlsym(RTLD_NEXT, "fopen"); - // printf("fopen %s\n", pathname); if (strcmp(pathname, "/root/lindbergrc") == 0) { return _fopen("lindbergrc", mode); } + if (strcmp(pathname, "/usr/lib/boot/logo.tga") == 0) + { + return _fopen("logo.tga", mode); + } + + if (strcmp(pathname, "/usr/lib/boot/LucidaConsole_12.tga") == 0) + { + return _fopen("LucidaConsole_12.tga", mode); + } + + if (strcmp(pathname, "/usr/lib/boot/LucidaConsole_12.abc") == 0) + { + return _fopen("LucidaConsole_12.abc", mode); + } + if (strcmp(pathname, "/proc/cpuinfo") == 0) { fileRead[CPUINFO] = 0; @@ -242,6 +280,25 @@ FILE *fopen64(const char *pathname, const char *mode) return fileHooks[OSRELEASE]; } + if (strcmp(pathname, "/usr/lib/boot/logo_red.tga") == 0) + { + return _fopen64("logo_red.tga", mode); + } + + if (strcmp(pathname, "/usr/lib/boot/logo.tga") == 0) + { + return _fopen64("logo.tga", mode); + } + + if (strcmp(pathname, "/usr/lib/boot/SEGA_KakuGothic-DB-Roman_12.tga") == 0) + { + return _fopen64("SEGA_KakuGothic-DB-Roman_12.tga", mode); + } + + if (strcmp(pathname, "/usr/lib/boot/SEGA_KakuGothic-DB-Roman_12.abc") == 0) + { + return _fopen64("SEGA_KakuGothic-DB-Roman_12.abc", mode); + } return _fopen64(pathname, mode); } @@ -465,7 +522,7 @@ float powf(float base, float exponent) return (float)pow((double)base, (double)exponent); } -/** This might be required for some games +/* int sem_wait(sem_t *sem) { int (*original_sem_wait)(sem_t * sem) = dlsym(RTLD_NEXT, "sem_wait"); @@ -476,6 +533,10 @@ int sem_wait(sem_t *sem) /** * Hook function used by Harley Davidson to change IPs to localhost * Currently does nothing. + * @param sockfd + * @param addr + * @param addrlen + * @return */ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { @@ -491,6 +552,45 @@ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) return _connect(sockfd, addr, addrlen); } +/** + * Function to calculate CRC32 checksum in memory. +*/ +uint32_t get_crc32(const char *s,size_t n) +{ + uint32_t crc=0xFFFFFFFF; + + for(size_t i=0;i>=1; + if(b) crc=crc^0xEDB88320; + ch>>=1; + } + } + return ~crc; +} + +/** + * Callback function to get the offset and size of the execution program in memory of the ELF we hook to. +*/ +static int callback(struct dl_phdr_info *info, size_t size, void *data) +{ + if((info->dlpi_phnum >= 3) && (info->dlpi_phdr[2].p_type == PT_LOAD) && (info->dlpi_phdr[2].p_flags == 5)) + { + elf_crc = get_crc32((void *)(info->dlpi_addr + info->dlpi_phdr[2].p_vaddr+10),128); + } + return 1; +} + +void getCPUID() +{ + unsigned eax; + eax = 0; + __get_cpuid(0, &eax, &cpu_vendor.ebx, &cpu_vendor.ecx, &cpu_vendor.edx); + printf("CPU Vendor: %.4s%.4s%.4s\n", (const char*)&cpu_vendor.ebx,(const char*)&cpu_vendor.edx,(const char*)&cpu_vendor.ecx); +} + /** * Stop the game changing the DISPLAY environment variable */ diff --git a/src/lindbergh/hook.h b/src/lindbergh/hook.h index e69de29..36e0d2a 100644 --- a/src/lindbergh/hook.h +++ b/src/lindbergh/hook.h @@ -0,0 +1,9 @@ +uint32_t get_crc32(const char *s,size_t n); +void getCPUID(); +typedef struct +{ + unsigned ebx; + unsigned edx; + unsigned ecx; +}cpuvendor; + diff --git a/src/lindbergh/patch.c b/src/lindbergh/patch.c index 6d5beaa..05b6478 100644 --- a/src/lindbergh/patch.c +++ b/src/lindbergh/patch.c @@ -5,6 +5,9 @@ #include "patch.h" #include "config.h" +#include "hook.h" + +extern cpuvendor cpu_vendor; static void setVariable(uint32_t address, uint32_t value) { @@ -14,7 +17,7 @@ static void setVariable(uint32_t address, uint32_t value) void *toModify = (void *)(address - (address % pagesize)); - int prot = mprotect(toModify, pagesize, PROT_WRITE); + int prot = mprotect(toModify, pagesize, PROT_EXEC | PROT_WRITE); if (prot != 0) { printf("Error: Cannot unprotect memory region to change variable (%d)\n", prot); @@ -70,75 +73,116 @@ int initPatch() switch (game) { - case RTUNED: - { - detourFunction(0x08366846, amDongleInit); - detourFunction(0x08365301, amDongleIsAvailable); - detourFunction(0x08365cf7, amDongleUpdate); - } - break; - - case SRTV: - { - detourFunction(0x084d5b40, amDongleInit); - detourFunction(0x084d45f9, amDongleIsAvailable); - detourFunction(0x084d4fef, amDongleUpdate); - } - break; - - case ABC: - { - detourFunction(0x081e3424, amDongleInit); - detourFunction(0x081e3772, amDongleIsAvailable); - detourFunction(0x081e369e, amDongleUpdate); - } - break; - case OUTRUN: - { - setVariable(0x0893a24c, 2); // amBackupDebugLevel - setVariable(0x0893a260, 2); // amCreditDebugLevel - setVariable(0x0893a4b8, 2); // amDipswDebugLevel - setVariable(0x0893a4bc, 2); // amDongleDebugLevel - setVariable(0x0893a4c0, 2); // amEepromDebugLevel - setVariable(0x0893a4c4, 2); // amHwmonitorDebugLevel - setVariable(0x0893a4c8, 2); // amJvsDebugLevel - setVariable(0x0893a4cc, 2); // amLibDebugLevel - setVariable(0x0893a4d0, 2); // amMiscDebugLevel - setVariable(0x0893a4d4, 2); // amOsinfoDebugLevel - setVariable(0x0893a4d8, 2); // amSysDataDebugLevel - setVariable(0x0893a4e0, 2); // bcLibDebugLevel - detourFunction(0x08190e80, amDongleInit); - detourFunction(0x08191201, amDongleIsAvailable); - detourFunction(0x08191125, amDongleUpdate); - } - break; + case RTUNED: + { + detourFunction(0x08366846, amDongleInit); + detourFunction(0x08365301, amDongleIsAvailable); + detourFunction(0x08365cf7, amDongleUpdate); + } + break; - case THE_HOUSE_OF_THE_DEAD_4: - { - setVariable(0x0a737c60, 2); // amBackupDebugLevel - setVariable(0x0a737c64, 2); // amChunkDataDebugLevel - setVariable(0x0a737c80, 2); // amCreditDebugLevel - setVariable(0x0a737ed8, 2); // amDipswDebugLevel - setVariable(0x0a737edc, 2); // amDiskDebugLevel - setVariable(0x0a737ee0, 2); // amDongleDebugLevel - setVariable(0x0a737ee4, 2); // amEepromDebugLevel - setVariable(0x0a737ee8, 2); // amHmDebugLevel - setVariable(0x0a737ef0, 2); // amJvsDebugLevel - setVariable(0x0a737f14, 2); // amLibDebugLevel - setVariable(0x0a737f18, 2); // amMiscDebugLevel - setVariable(0x0a737f1c, 2); // amSysDataDebugLevel - setVariable(0x0a737f20, 2); // bcLibDebugLevel - setVariable(0x0a737f24, 0x0FFFFFFF); // s_logMask - detourFunction(0x08320178, amDongleInit); - detourFunction(0x08320459, amDongleIsAvailable); - detourFunction(0x083203c0, amDongleUpdate); - } - break; + case SRTV: + { + detourFunction(0x084d5b40, amDongleInit); + detourFunction(0x084d45f9, amDongleIsAvailable); + detourFunction(0x084d4fef, amDongleUpdate); + } + break; + case ABC_2006: + { + setVariable(0x0a0a37e4, 2); // amBackupDebugLevel + setVariable(0x0a0a3800, 2); // amCreditDebugLevel + setVariable(0x0a0a3a58, 2); // amDipswDebugLevel + setVariable(0x0a0a3a5c, 2); // amDongleDebugLevel + setVariable(0x0a0a3a60, 2); // amEepromDebugLevel + setVariable(0x0a0a3a64, 2); // amHwmonitorDebugLevel + setVariable(0x0a0a3a68, 2); // amJvsDebugLevel + setVariable(0x0a0a3a6c, 2); // amLibDebugLevel + setVariable(0x0a0a3a70, 2); // amMiscDebugLevel + setVariable(0x0a0a3a74, 2); // amOsinfoDebugLevel + setVariable(0x0a0a3a78, 2); // amSysDataDebugLevel + setVariable(0x0a0a3a80, 2); // bcLibDebugLevel + detourFunction(0x081e4980, amDongleInit); + detourFunction(0x081e4cce, amDongleIsAvailable); + detourFunction(0x081e4bfa, amDongleUpdate); + } + break; + case ABC_2007: + { + setVariable(0x0a0a0d24, 2); // amBackupDebugLevel + setVariable(0x0a0a0d40, 2); // amCreditDebugLevel + setVariable(0x0a0a0f98, 2); // amDipswDebugLevel + setVariable(0x0a0a0f9c, 2); // amDongleDebugLevel + setVariable(0x0a0a0fa0, 2); // amEepromDebugLevel + setVariable(0x0a0a0fa4, 2); // amHwmonitorDebugLevel + setVariable(0x0a0a0fa8, 2); // amJvsDebugLevel + setVariable(0x0a0a0fac, 2); // amLibDebugLevel + setVariable(0x0a0a0fb0, 2); // amMiscDebugLevel + setVariable(0x0a0a0fb4, 2); // amOsinfoDebugLevel + setVariable(0x0a0a0fb8, 2); // amSysDataDebugLevel + setVariable(0x0a0a0fc0, 2); // bcLibDebugLevel + detourFunction(0x081e3424, amDongleInit); + detourFunction(0x081e3772, amDongleIsAvailable); + detourFunction(0x081e369e, amDongleUpdate); + } + break; + case OUTRUN: + { + setVariable(0x0893a24c, 2); // amBackupDebugLevel + setVariable(0x0893a260, 2); // amCreditDebugLevel + setVariable(0x0893a4b8, 2); // amDipswDebugLevel + setVariable(0x0893a4bc, 2); // amDongleDebugLevel + setVariable(0x0893a4c0, 2); // amEepromDebugLevel + setVariable(0x0893a4c4, 2); // amHwmonitorDebugLevel + setVariable(0x0893a4c8, 2); // amJvsDebugLevel + setVariable(0x0893a4cc, 2); // amLibDebugLevel + setVariable(0x0893a4d0, 2); // amMiscDebugLevel + setVariable(0x0893a4d4, 2); // amOsinfoDebugLevel + setVariable(0x0893a4d8, 2); // amSysDataDebugLevel + setVariable(0x0893a4e0, 2); // bcLibDebugLevel + detourFunction(0x08190e80, amDongleInit); + detourFunction(0x08191201, amDongleIsAvailable); + detourFunction(0x08191125, amDongleUpdate); + } + break; - default: - // Don't do any patches for random games + case THE_HOUSE_OF_THE_DEAD_4: + { + setVariable(0x0a737c60, 2); // amBackupDebugLevel + setVariable(0x0a737c64, 2); // amChunkDataDebugLevel + setVariable(0x0a737c80, 2); // amCreditDebugLevel + setVariable(0x0a737ed8, 2); // amDipswDebugLevel + setVariable(0x0a737edc, 2); // amDiskDebugLevel + setVariable(0x0a737ee0, 2); // amDongleDebugLevel + setVariable(0x0a737ee4, 2); // amEepromDebugLevel + setVariable(0x0a737ee8, 2); // amHmDebugLevel + setVariable(0x0a737ef0, 2); // amJvsDebugLevel + setVariable(0x0a737f14, 2); // amLibDebugLevel + setVariable(0x0a737f18, 2); // amMiscDebugLevel + setVariable(0x0a737f1c, 2); // amSysDataDebugLevel + setVariable(0x0a737f20, 2); // bcLibDebugLevel + setVariable(0x0a737f24, 0x0FFFFFFF); // s_logMask + detourFunction(0x08320178, amDongleInit); + detourFunction(0x08320459, amDongleIsAvailable); + detourFunction(0x083203c0, amDongleUpdate); + setVariable(0x0837d6aa, cpu_vendor.ebx); + setVariable(0x0837d6ba, cpu_vendor.edx); + setVariable(0x0837d6c5, cpu_vendor.ecx); + } + break; + case THE_HOUSE_OF_THE_DEAD_4_TEST: + { + detourFunction(0x080677a0, amDongleInit); + detourFunction(0x08067a81, amDongleIsAvailable); + detourFunction(0x080679e8, amDongleUpdate); + setVariable(0x0807217a, cpu_vendor.ebx); + setVariable(0x0807218a, cpu_vendor.edx); + setVariable(0x08072195, cpu_vendor.ecx); + } + break; + default: + // Don't do any patches for random games break; } - return 0; -} +} \ No newline at end of file