int main(int argc, char* argv[]) { struct sigaction sa; sa.sa_flags = SA_SIGINFO | SA_NODEFER; sigemptyset(&sa.sa_mask); sa.sa_sigaction = handler; sigaction(SIGSEGV, &sa, NULL); sigaction(SIGABRT, &sa, NULL); sigaction(SIGILL, &sa, NULL); sigaction(SIGINT, &sa, NULL); sigaction(SIGFPE, &sa, NULL); printf("R4300 Recompiler\n\n"); #ifndef TEST printf("Opening %s\n",argv[1]); #endif FILE *fPtr; uint32_t romlength = 0U; #ifndef TEST if (argc <= 1) fPtr = fopen("m64p_test_rom.v64", "rb"); else fPtr = fopen(argv[1], "rb"); if (fPtr == NULL) return 2; fseek(fPtr, 0L, SEEK_END); romlength = ftell(fPtr); fseek(fPtr, 0L, SEEK_SET); #else romlength = 2000U; #endif if (mmap((uint32_t*)(MMAP_BASE) , MMAP_BASE_SIZE + romlength , PROT_READ|PROT_WRITE|PROT_EXEC , MAP_PRIVATE| MAP_FIXED | MAP_ANONYMOUS , -1 , 0 ) != (uint32_t*)(MMAP_BASE)) { printf("Could not mmap\n"); return 1; } if (mmap((uint32_t*)(MMAP_PIF_BOOT_ROM) , 4096 , PROT_READ|PROT_WRITE|PROT_EXEC , MAP_PRIVATE| MAP_FIXED | MAP_ANONYMOUS , -1 , 0 ) != (uint32_t*)(MMAP_PIF_BOOT_ROM)) { printf("Could not mmap PIF area\n"); return 1; } #ifdef TEST //Generate helper functions GenerateCodeSegmentData(romlength); //Start testing Translation_Test(&segmentData); #else unsigned char imagetype; m64p_rom_header ROM_HEADER; if (fread((uint32_t*)ROM_ADDRESS , 1, romlength, fPtr) != romlength) { printf("could not read ROM\n"); return 3; } swap_rom((unsigned char*)ROM_ADDRESS, &imagetype, romlength); memcpy(&ROM_HEADER, (uint32_t*)ROM_ADDRESS, sizeof(m64p_rom_header)); ROM_PARAMS.systemtype = rom_country_code_to_system_type(ROM_HEADER.Country_code); printf("Name: %s\n", ROM_HEADER.Name); printf("Rom size: %ld bytes (or %ld Mb or %ld Megabits)\n", romlength, romlength/1024/1024, romlength/1024/1024*8); printf("ClockRate = %x\n", sl(ROM_HEADER.ClockRate)); printf("Version: %x\n", sl(ROM_HEADER.Release)); printf("PC = 0x%x\n\n", sl((unsigned int)ROM_HEADER.PC)); int x; #if 1 for (x=0; x< romlength/4; x++) *((uint32_t*)ROM_ADDRESS + x) = sl(*((uint32_t*)ROM_ADDRESS + x)); #endif #if 0 for (x=0x40/4; x< 200; x++ ) { mips_print((uint32_t)((uint32_t*)ROM_ADDRESS + x), *((uint32_t*)ROM_ADDRESS + x)); } printf("----------------------------\n"); #endif //Find all code where we don't know which registers are used #if 0 printf("Unknown register usage on these instructions:\n\n"); for (x=0x40/4; x< romlength/4; x++ ) { uint32_t temp; if (ops_regs_input(((uint32_t*)ROM_ADDRESS)[x],&temp,&temp,&temp) == 2 || ops_regs_output(((uint32_t*)ROM_ADDRESS)[x],&temp,&temp,&temp) == 2) mips_print((uint32_t*)ROM_ADDRESS + x, ((uint32_t*)ROM_ADDRESS)[x]); } printf("----------------------------\n"); #endif GenerateCodeSegmentData(romlength); #if 0 printf("MIPS Address Length Regs-cpu fpu sp used Next Block type 2=end,3=br\n"); nextCodeSeg = segmentData->StaticSegments; int count =0; while (nextCodeSeg != NULL && count < 20) { count++; if (nextCodeSeg->MIPSReturnRegister) { printf("0x%08X 0x%08X %5d 0x%08X %08X %03X %2d r%d\n", (uint32_t)nextCodeSeg->MIPScode, (uint32_t)(nextCodeSeg->MIPScode+nextCodeSeg->MIPScodeLen), nextCodeSeg->MIPScodeLen, nextCodeSeg->MIPSRegistersUsed[0], nextCodeSeg->MIPSRegistersUsed[1], nextCodeSeg->MIPSRegistersUsed[2], nextCodeSeg->MIPSRegistersUsedCount, nextCodeSeg->MIPSReturnRegister); } else { printf("0x%08X 0x%08X %5d 0x%08X %08X %02X %2d 0x%08X %d\n", (uint32_t)nextCodeSeg->MIPScode, (uint32_t)(nextCodeSeg->MIPScode+nextCodeSeg->MIPScodeLen), nextCodeSeg->MIPScodeLen, nextCodeSeg->MIPSRegistersUsed[0], nextCodeSeg->MIPSRegistersUsed[1], nextCodeSeg->MIPSRegistersUsed[2], nextCodeSeg->MIPSRegistersUsedCount, (uint32_t)nextCodeSeg->MIPSnextInstructionIndex, nextCodeSeg->Type); } nextCodeSeg = nextCodeSeg->next; } printf("----------------------------\n"); #endif printf("%d code segments generated\n", segmentData.count); printf("&segmentData.dbgCurrentSegment = 0x%08x\n", (uint32_t)&segmentData.dbgCurrentSegment); // Instruction Counts for input ROM #if 0 code_seg_t* nextCodeSeg; uint32_t ins_count[sizeof_mips_op_t]; uint32_t ins_count_total=0; memset(ins_count,0,sizeof(ins_count)); nextCodeSeg = segmentData.StaticSegments; while (nextCodeSeg) { for (x=0; x < nextCodeSeg->MIPScodeLen; x++) { ins_count[STRIP(ops_type(*(nextCodeSeg->MIPScode + x)))] ++; ins_count_total++; } nextCodeSeg = nextCodeSeg->next; } for (x=0; x < sizeof_mips_op_t; x++) { if (ins_count[x]) { printf("%-9s %7d (%2.2f%%)\n",Instruction_ascii[x], ins_count[x], (double)ins_count[x] * 100 / ins_count_total); } } printf("----------------------------\n"); #endif r4300_reset_hard(); r4300_reset_soft(); printf("\nFinished processing ROM\n"); #endif while (Debugger_start(&segmentData, NULL, NULL)); // Clean up Recompiler freeCodeSegmentData(); munmap((uint32_t*)MMAP_BASE, MMAP_BASE_SIZE + romlength); munmap((uint32_t*)MMAP_PIF_BOOT_ROM, 4096); printf("\nEND\n"); return 0; }
m64p_error open_rom(const unsigned char* romimage, unsigned int size) { md5_state_t state; md5_byte_t digest[16]; romdatabase_entry* entry; char buffer[256]; unsigned char imagetype; int i; /* check input requirements */ if (g_rom != NULL) { DebugMessage(M64MSG_ERROR, "open_rom(): previous ROM image was not freed"); return M64ERR_INTERNAL; } if (romimage == NULL || !is_valid_rom(romimage)) { DebugMessage(M64MSG_ERROR, "open_rom(): not a valid ROM image"); return M64ERR_INPUT_INVALID; } /* Clear Byte-swapped flag, since ROM is now deleted. */ g_MemHasBeenBSwapped = 0; /* allocate new buffer for ROM and copy into this buffer */ g_rom_size = size; g_rom = (unsigned char *) malloc(size); if (g_rom == NULL) return M64ERR_NO_MEMORY; swap_copy_rom(g_rom, romimage, size, &imagetype); memcpy(&ROM_HEADER, g_rom, sizeof(m64p_rom_header)); /* Calculate MD5 hash */ md5_init(&state); md5_append(&state, (const md5_byte_t*)g_rom, g_rom_size); md5_finish(&state, digest); for ( i = 0; i < 16; ++i ) sprintf(buffer+i*2, "%02X", digest[i]); buffer[32] = '\0'; strcpy(ROM_SETTINGS.MD5, buffer); /* add some useful properties to ROM_PARAMS */ ROM_PARAMS.systemtype = rom_country_code_to_system_type(ROM_HEADER.Country_code); ROM_PARAMS.countperop = COUNT_PER_OP_DEFAULT; ROM_PARAMS.vitiming = ALTERNATE_VI_TIMING_DEFAULT; ROM_PARAMS.countperscanline = DEFAULT_COUNT_PER_SCANLINE; ROM_PARAMS.cheats = NULL; memcpy(ROM_PARAMS.headername, ROM_HEADER.Name, 20); ROM_PARAMS.headername[20] = '\0'; trim(ROM_PARAMS.headername); /* Remove trailing whitespace from ROM name. */ /* Look up this ROM in the .ini file and fill in goodname, etc */ if ((entry=ini_search_by_md5(digest)) != NULL || (entry=ini_search_by_crc(sl(ROM_HEADER.CRC1),sl(ROM_HEADER.CRC2))) != NULL) { strncpy(ROM_SETTINGS.goodname, entry->goodname, 255); ROM_SETTINGS.goodname[255] = '\0'; ROM_SETTINGS.savetype = entry->savetype; ROM_SETTINGS.status = entry->status; ROM_SETTINGS.players = entry->players; ROM_SETTINGS.rumble = entry->rumble; ROM_PARAMS.countperop = entry->countperop; ROM_PARAMS.vitiming = entry->alternate_vi_timing; ROM_PARAMS.countperscanline = entry->count_per_scanline; ROM_PARAMS.cheats = entry->cheats; } else { strcpy(ROM_SETTINGS.goodname, ROM_PARAMS.headername); strcat(ROM_SETTINGS.goodname, " (unknown rom)"); ROM_SETTINGS.savetype = NONE; ROM_SETTINGS.status = 0; ROM_SETTINGS.players = 0; ROM_SETTINGS.rumble = 0; ROM_PARAMS.countperop = COUNT_PER_OP_DEFAULT; ROM_PARAMS.vitiming = ALTERNATE_VI_TIMING_DEFAULT; ROM_PARAMS.countperscanline = DEFAULT_COUNT_PER_SCANLINE; ROM_PARAMS.cheats = NULL; } /* print out a bunch of info about the ROM */ DebugMessage(M64MSG_INFO, "Goodname: %s", ROM_SETTINGS.goodname); DebugMessage(M64MSG_INFO, "Name: %s", ROM_HEADER.Name); imagestring(imagetype, buffer); DebugMessage(M64MSG_INFO, "MD5: %s", ROM_SETTINGS.MD5); DebugMessage(M64MSG_INFO, "CRC: %08" PRIX32 " %08" PRIX32, sl(ROM_HEADER.CRC1), sl(ROM_HEADER.CRC2)); DebugMessage(M64MSG_INFO, "Imagetype: %s", buffer); DebugMessage(M64MSG_INFO, "Rom size: %d bytes (or %d Mb or %d Megabits)", g_rom_size, g_rom_size/1024/1024, g_rom_size/1024/1024*8); DebugMessage(M64MSG_VERBOSE, "ClockRate = %" PRIX32, sl(ROM_HEADER.ClockRate)); DebugMessage(M64MSG_INFO, "Version: %" PRIX32, sl(ROM_HEADER.Release)); if(sl(ROM_HEADER.Manufacturer_ID) == 'N') DebugMessage(M64MSG_INFO, "Manufacturer: Nintendo"); else DebugMessage(M64MSG_INFO, "Manufacturer: %" PRIX32, sl(ROM_HEADER.Manufacturer_ID)); DebugMessage(M64MSG_VERBOSE, "Cartridge_ID: %" PRIX16, ROM_HEADER.Cartridge_ID); countrycodestring(ROM_HEADER.Country_code, buffer); DebugMessage(M64MSG_INFO, "Country: %s", buffer); DebugMessage(M64MSG_VERBOSE, "PC = %" PRIX32, sl(ROM_HEADER.PC)); DebugMessage(M64MSG_VERBOSE, "Save type: %d", ROM_SETTINGS.savetype); //Prepare Hack for GOLDENEYE isGoldeneyeRom = 0; if(strcmp(ROM_PARAMS.headername, "GOLDENEYE") == 0) isGoldeneyeRom = 1; return M64ERR_SUCCESS; }
m64p_error open_rom(const unsigned char* romimage, unsigned int size) { md5_state_t state; md5_byte_t digest[16]; romdatabase_entry* entry; char buffer[256]; unsigned char imagetype; int i; m64p_handle CoreSection = NULL; /* check input requirements */ if (rom != NULL) { DebugMessage(M64MSG_ERROR, "open_rom(): previous ROM image was not freed"); return M64ERR_INTERNAL; } if (romimage == NULL || !is_valid_rom(romimage)) { DebugMessage(M64MSG_ERROR, "open_rom(): not a valid ROM image"); return M64ERR_INPUT_INVALID; } /* Clear Byte-swapped flag, since ROM is now deleted. */ g_MemHasBeenBSwapped = 0; /* allocate new buffer for ROM and copy into this buffer */ rom_size = size; rom = (unsigned char *) malloc(size); if (rom == NULL) return M64ERR_NO_MEMORY; memcpy(rom, romimage, size); swap_rom(rom, &imagetype, rom_size); memcpy(&ROM_HEADER, rom, sizeof(m64p_rom_header)); /* Calculate MD5 hash */ md5_init(&state); md5_append(&state, (const md5_byte_t*)rom, rom_size); md5_finish(&state, digest); for ( i = 0; i < 16; ++i ) sprintf(buffer+i*2, "%02X", digest[i]); buffer[32] = '\0'; strcpy(ROM_SETTINGS.MD5, buffer); /* add some useful properties to ROM_PARAMS */ ROM_PARAMS.systemtype = rom_country_code_to_system_type(ROM_HEADER.Country_code); ROM_PARAMS.vilimit = rom_system_type_to_vi_limit(ROM_PARAMS.systemtype); ROM_PARAMS.aidacrate = rom_system_type_to_ai_dac_rate(ROM_PARAMS.systemtype); memcpy(ROM_PARAMS.headername, ROM_HEADER.Name, 20); ROM_PARAMS.headername[20] = '\0'; trim(ROM_PARAMS.headername); /* Remove trailing whitespace from ROM name. */ /* Look up this ROM in the .ini file and fill in goodname, etc */ /* if ((entry=ini_search_by_md5(digest)) != NULL || (entry=ini_search_by_crc(sl(ROM_HEADER.CRC1),sl(ROM_HEADER.CRC2))) != NULL) { strncpy(ROM_SETTINGS.goodname, entry->goodname, 255); ROM_SETTINGS.goodname[255] = '\0'; ROM_SETTINGS.savetype = entry->savetype; ROM_SETTINGS.status = entry->status; ROM_SETTINGS.players = entry->players; ROM_SETTINGS.rumble = entry->rumble; } else { strcpy(ROM_SETTINGS.goodname, ROM_PARAMS.headername); strcat(ROM_SETTINGS.goodname, " (unknown rom)"); ROM_SETTINGS.savetype = NONE; ROM_SETTINGS.status = 0; ROM_SETTINGS.players = 0; ROM_SETTINGS.rumble = 0; } */ strcpy(ROM_SETTINGS.goodname, ROM_PARAMS.headername); strcat(ROM_SETTINGS.goodname, " (unknown rom)"); ROM_SETTINGS.savetype = 0; if (ConfigOpenSection("Core", &CoreSection) == M64ERR_SUCCESS) { ConfigSetDefaultInt(CoreSection, "SaveType", NONE, "The savetype for the game"); ROM_SETTINGS.savetype = ConfigGetParamInt(CoreSection, "SaveType"); } ROM_SETTINGS.status = 0; ROM_SETTINGS.players = 0; ROM_SETTINGS.rumble = 0; /* print out a bunch of info about the ROM */ DebugMessage(M64MSG_INFO, "Goodname: %s", ROM_SETTINGS.goodname); DebugMessage(M64MSG_INFO, "Name: %s", ROM_HEADER.Name); imagestring(imagetype, buffer); DebugMessage(M64MSG_INFO, "MD5: %s", ROM_SETTINGS.MD5); DebugMessage(M64MSG_INFO, "CRC: %x %x", sl(ROM_HEADER.CRC1), sl(ROM_HEADER.CRC2)); DebugMessage(M64MSG_INFO, "Imagetype: %s", buffer); DebugMessage(M64MSG_INFO, "Rom size: %d bytes (or %d Mb or %d Megabits)", rom_size, rom_size/1024/1024, rom_size/1024/1024*8); DebugMessage(M64MSG_VERBOSE, "ClockRate = %x", sl(ROM_HEADER.ClockRate)); DebugMessage(M64MSG_INFO, "Version: %x", sl(ROM_HEADER.Release)); if(sl(ROM_HEADER.Manufacturer_ID) == 'N') DebugMessage(M64MSG_INFO, "Manufacturer: Nintendo"); else DebugMessage(M64MSG_INFO, "Manufacturer: %x", sl(ROM_HEADER.Manufacturer_ID)); DebugMessage(M64MSG_VERBOSE, "Cartridge_ID: %x", ROM_HEADER.Cartridge_ID); countrycodestring(ROM_HEADER.Country_code, buffer); DebugMessage(M64MSG_INFO, "Country: %s", buffer); DebugMessage(M64MSG_VERBOSE, "PC = %x", sl((unsigned int)ROM_HEADER.PC)); DebugMessage(M64MSG_VERBOSE, "Save type: %d", ROM_SETTINGS.savetype); //Prepare Hack for GOLDENEYE isGoldeneyeRom = 0; if(strcmp(ROM_PARAMS.headername, "GOLDENEYE") == 0) isGoldeneyeRom = 1; return M64ERR_SUCCESS; }