static void dump_unknown_task(struct hle_t* hle, unsigned int sum) { char filename[256]; uint32_t ucode = *dmem_u32(hle, TASK_UCODE); uint32_t ucode_data = *dmem_u32(hle, TASK_UCODE_DATA); uint32_t data_ptr = *dmem_u32(hle, TASK_DATA_PTR); sprintf(&filename[0], "task_%x.log", sum); dump_task(hle, filename); /* dump ucode_boot */ sprintf(&filename[0], "ucode_boot_%x.bin", sum); dump_binary(hle, filename, (void*)dram_u32(hle, *dmem_u32(hle, TASK_UCODE_BOOT)), *dmem_u32(hle, TASK_UCODE_BOOT_SIZE)); /* dump ucode */ if (ucode != 0) { sprintf(&filename[0], "ucode_%x.bin", sum); dump_binary(hle, filename, (void*)dram_u32(hle, ucode), 0xf80); } /* dump ucode_data */ if (ucode_data != 0) { sprintf(&filename[0], "ucode_data_%x.bin", sum); dump_binary(hle, filename, (void*)dram_u32(hle, ucode_data), *dmem_u32(hle, TASK_UCODE_DATA_SIZE)); } /* dump data */ if (data_ptr != 0) { sprintf(&filename[0], "data_%x.bin", sum); dump_binary(hle, filename, (void*)dram_u32(hle, data_ptr), *dmem_u32(hle, TASK_DATA_SIZE)); } }
static void handle_unknown_task(unsigned int sum) { char filename[256]; uint32_t ucode = *dmem_u32(TASK_UCODE); uint32_t ucode_data = *dmem_u32(TASK_UCODE_DATA); uint32_t data_ptr = *dmem_u32(TASK_DATA_PTR); DebugMessage(M64MSG_WARNING, "unknown OSTask: sum %x PC:%x", sum, *rsp.SP_PC_REG); sprintf(&filename[0], "task_%x.log", sum); dump_task(filename); /* dump ucode_boot */ sprintf(&filename[0], "ucode_boot_%x.bin", sum); dump_binary(filename, (void*)dram_u32(*dmem_u32(TASK_UCODE_BOOT)), *dmem_u32(TASK_UCODE_BOOT_SIZE)); /* dump ucode */ if (ucode != 0) { sprintf(&filename[0], "ucode_%x.bin", sum); dump_binary(filename, (void*)dram_u32(ucode), 0xf80); } /* dump ucode_data */ if (ucode_data != 0) { sprintf(&filename[0], "ucode_data_%x.bin", sum); dump_binary(filename, (void*)dram_u32(ucode_data), *dmem_u32(TASK_UCODE_DATA_SIZE)); } /* dump data */ if (data_ptr != 0) { sprintf(&filename[0], "data_%x.bin", sum); dump_binary(filename, (void*)dram_u32(data_ptr), *dmem_u32(TASK_DATA_SIZE)); } }
static void normal_task_dispatching(void) { const uint32_t sum = sum_bytes((void*)dram_u32(*dmem_u32(TASK_UCODE)), min(*dmem_u32(TASK_UCODE_SIZE), 0xf80) >> 1); switch (sum) { /* StoreVe12: found in Zelda Ocarina of Time [misleading task->type == 4] */ case 0x278: /* Nothing to emulate */ return; /* GFX: Twintris [misleading task->type == 0] */ case 0x212ee: if (FORWARD_GFX) { forward_gfx_task(); return; } break; /* JPEG: found in Pokemon Stadium J */ case 0x2c85a: jpeg_decode_PS0(); return; /* JPEG: found in Zelda Ocarina of Time, Pokemon Stadium 1, Pokemon Stadium 2 */ case 0x2caa6: jpeg_decode_PS(); return; /* JPEG: found in Ogre Battle, Bottom of the 9th */ case 0x130de: case 0x278b0: jpeg_decode_OB(); return; } handle_unknown_task(sum); }
static void handle_unknown_task(uint32_t sum) { #if 0 char filename[256]; uint32_t ucode = *dmem_u32(TASK_UCODE); uint32_t ucode_data = *dmem_u32(TASK_UCODE_DATA); uint32_t data_ptr = *dmem_u32(TASK_DATA_PTR); RSP_DEBUG_MESSAGE(M64MSG_WARNING, "unknown OSTask: sum %x PC:%x", sum, *rspInfo.SP_PC_REG); sprintf(&filename[0], "task_%x.log", sum); dump_task(filename); // dump ucode_boot sprintf(&filename[0], "ucode_boot_%x.bin", sum); dump_binary(filename, (void*)dram_u32(*dmem_u32(TASK_UCODE_BOOT)), *dmem_u32(TASK_UCODE_BOOT_SIZE)); // dump ucode if (ucode != 0) { sprintf(&filename[0], "ucode_%x.bin", sum); dump_binary(filename, (void*)dram_u32(ucode), 0xf80); } // dump ucode_data if (ucode_data != 0) { sprintf(&filename[0], "ucode_data_%x.bin", sum); dump_binary(filename, (void*)dram_u32(ucode_data), *dmem_u32(TASK_UCODE_DATA_SIZE)); } // dump data if (data_ptr != 0) { sprintf(&filename[0], "data_%x.bin", sum); dump_binary(filename, (void*)dram_u32(data_ptr), *dmem_u32(TASK_DATA_SIZE)); } #endif }
static void normal_task_dispatching(struct hle_t* hle) { const unsigned int sum = sum_bytes((void*)dram_u32(hle, *dmem_u32(hle, TASK_UCODE)), min(*dmem_u32(hle, TASK_UCODE_SIZE), 0xf80) >> 1); switch (sum) { /* StoreVe12: found in Zelda Ocarina of Time [misleading task->type == 4] */ case 0x278: /* Nothing to emulate */ return; /* GFX: Twintris [misleading task->type == 0] */ case 0x212ee: if (FORWARD_GFX) { forward_gfx_task(hle); return; } break; /* JPEG: found in Pokemon Stadium J */ case 0x2c85a: jpeg_decode_PS0(hle); return; /* JPEG: found in Zelda Ocarina of Time, Pokemon Stadium 1, Pokemon Stadium 2 */ case 0x2caa6: jpeg_decode_PS(hle); return; /* JPEG: found in Ogre Battle, Bottom of the 9th */ case 0x130de: case 0x278b0: jpeg_decode_OB(hle); return; } HleWarnMessage(hle->user_defined, "unknown OSTask: sum: %x PC:%x", sum, *hle->sp_pc); }
void CHle::normal_task_dispatching(void) { const unsigned int sum = sum_bytes((const uint8_t *)dram_u32(this, *dmem_u32(this, TASK_UCODE)), min(*dmem_u32(this, TASK_UCODE_SIZE), 0xf80) >> 1); switch (sum) { /* StoreVe12: found in Zelda Ocarina of Time [misleading task->type == 4] */ case 0x278: /* Nothing to emulate */ return; /* GFX: Twintris [misleading task->type == 0] */ case 0x212ee: if (m_ForwardGFX) { m_ProcessDList(); return; } break; /* JPEG: found in Pokemon Stadium J */ case 0x2c85a: jpeg_decode_PS0(this); return; /* JPEG: found in Zelda Ocarina of Time, Pokemon Stadium 1, Pokemon Stadium 2 */ case 0x2caa6: jpeg_decode_PS(this); return; /* JPEG: found in Ogre Battle, Bottom of the 9th */ case 0x130de: case 0x278b0: jpeg_decode_OB(this); return; } WarnMessage("unknown OSTask: sum: %x PC:%x", sum, *m_sp_pc); #ifdef ENABLE_TASK_DUMP dump_unknown_task(this, sum); #endif }
static bool try_fast_audio_dispatching(struct hle_t* hle) { uint32_t v; /* identify audio ucode by using the content of ucode_data */ uint32_t ucode_data = *dmem_u32(hle, TASK_UCODE_DATA); if (*dram_u32(hle, ucode_data) == 0x00000001) { if (*dram_u32(hle, ucode_data + 0x30) == 0xf0000f00) { v = *dram_u32(hle, ucode_data + 0x28); switch(v) { case 0x1e24138c: /* audio ABI (most common) */ alist_process_audio(hle); return true; case 0x1dc8138c: /* GoldenEye */ alist_process_audio_ge(hle); return true; case 0x1e3c1390: /* BlastCorp, DiddyKongRacing */ alist_process_audio_bc(hle); return true; default: HleWarnMessage(hle->user_defined, "ABI1 identification regression: v=%08x", v); } } else { v = *dram_u32(hle, ucode_data + 0x10); switch(v) { case 0x11181350: /* MarioKart, WaveRace (E) */ alist_process_nead_mk(hle); return true; case 0x111812e0: /* StarFox (J) */ alist_process_nead_sfj(hle); return true; case 0x110412ac: /* WaveRace (J RevB) */ alist_process_nead_wrjb(hle); return true; case 0x110412cc: /* StarFox/LylatWars (except J) */ alist_process_nead_sf(hle); return true; case 0x1cd01250: /* FZeroX */ alist_process_nead_fz(hle); return true; case 0x1f08122c: /* YoshisStory */ alist_process_nead_ys(hle); return true; case 0x1f38122c: /* 1080° Snowboarding */ alist_process_nead_1080(hle); return true; case 0x1f681230: /* Zelda OoT / Zelda MM (J, J RevA) */ alist_process_nead_oot(hle); return true; case 0x1f801250: /* Zelda MM (except J, J RevA, E Beta), PokemonStadium 2 */ alist_process_nead_mm(hle); return true; case 0x109411f8: /* Zelda MM (E Beta) */ alist_process_nead_mmb(hle); return true; case 0x1eac11b8: /* AnimalCrossing */ alist_process_nead_ac(hle); return true; case 0x00010010: /* MusyX v2 (IndianaJones, BattleForNaboo) */ musyx_v2_task(hle); return true; default: HleWarnMessage(hle->user_defined, "ABI2 identification regression: v=%08x", v); } } } else { v = *dram_u32(hle, ucode_data + 0x10); switch(v) { /* -- MusyX v1 -- Star Wars: Rogue Squadron Resident Evil 2 Polaris SnoCross 007: The World Is Not Enough Rugrats In Paris NBA ShowTime Hydro Thunder Tarzan Gauntlet Legends Rush 2049 */ case 0x00000001: musyx_v1_task(hle); return true; /* NAUDIO (many games) */ case 0x0000127c: alist_process_naudio(hle); return true; /* Banjo Kazooie */ case 0x00001280: alist_process_naudio_bk(hle); return true; /* Donkey Kong 64 */ case 0x1c58126c: alist_process_naudio_dk(hle); return true; /* Banjo Tooie * Jet Force Gemini * Mickey's SpeedWay USA * Perfect Dark */ case 0x1ae8143c: alist_process_naudio_mp3(hle); return true; case 0x1ab0140c: /* Conker's Bad Fur Day */ alist_process_naudio_cbfd(hle); return true; default: HleWarnMessage(hle->user_defined, "ABI3 identification regression: v=%08x", v); } } return false; }
bool CHle::try_fast_audio_dispatching(void) { /* identify audio ucode by using the content of ucode_data */ uint32_t ucode_data = *dmem_u32(this, TASK_UCODE_DATA); uint32_t v; if (*dram_u32(this, ucode_data) == 0x00000001) { if (*dram_u32(this, ucode_data + 0x30) == 0xf0000f00) { v = *dram_u32(this, ucode_data + 0x28); switch (v) { case 0x1e24138c: /* audio ABI (most common) */ alist_process_audio(this); return true; case 0x1dc8138c: /* GoldenEye */ alist_process_audio_ge(this); return true; case 0x1e3c1390: /* BlastCorp, DiddyKongRacing */ alist_process_audio_bc(this); return true; default: WarnMessage("ABI1 identification regression: v=%08x", v); } } else { v = *dram_u32(this, ucode_data + 0x10); switch (v) { case 0x11181350: /* MarioKart, WaveRace (E) */ alist_process_nead_mk(this); return true; case 0x111812e0: /* StarFox (J) */ alist_process_nead_sfj(this); return true; case 0x110412ac: /* WaveRace (J RevB) */ alist_process_nead_wrjb(this); return true; case 0x110412cc: /* StarFox/LylatWars (except J) */ alist_process_nead_sf(this); return true; case 0x1cd01250: /* FZeroX */ alist_process_nead_fz(this); return true; case 0x1f08122c: /* YoshisStory */ alist_process_nead_ys(this); return true; case 0x1f38122c: /* 1080° Snowboarding */ alist_process_nead_1080(this); return true; case 0x1f681230: /* Zelda OoT / Zelda MM (J, J RevA) */ alist_process_nead_oot(this); return true; case 0x1f801250: /* Zelda MM (except J, J RevA, E Beta), PokemonStadium 2 */ alist_process_nead_mm(this); return true; case 0x109411f8: /* Zelda MM (E Beta) */ alist_process_nead_mmb(this); return true; case 0x1eac11b8: /* AnimalCrossing */ alist_process_nead_ac(this); return true; case 0x00010010: /* MusyX v2 (IndianaJones, BattleForNaboo) */ musyx_v2_task(this); return true; default: WarnMessage("ABI2 identification regression: v=%08x", v); } } } else { v = *dram_u32(this, ucode_data + 0x10); switch (v) { case 0x00000001: /* MusyX v1 RogueSquadron, ResidentEvil2, PolarisSnoCross, TheWorldIsNotEnough, RugratsInParis, NBAShowTime, HydroThunder, Tarzan, GauntletLegend, Rush2049 */ musyx_v1_task(this); return true; case 0x0000127c: /* naudio (many games) */ alist_process_naudio(this); return true; case 0x00001280: /* BanjoKazooie */ alist_process_naudio_bk(this); return true; case 0x1c58126c: /* DonkeyKong */ alist_process_naudio_dk(this); return true; case 0x1ae8143c: /* BanjoTooie, JetForceGemini, MickeySpeedWayUSA, PerfectDark */ alist_process_naudio_mp3(this); return true; case 0x1ab0140c: /* ConkerBadFurDay */ alist_process_naudio_cbfd(this); return true; default: WarnMessage("ABI3 identification regression: v=%08x", v); } } return false; }
void dram_store_u32(const uint32_t* src, uint32_t address, size_t count) { /* Optimization for uint32_t */ memcpy(dram_u32(address), src, count * sizeof(uint32_t)); }
void dram_load_u32(uint32_t* dst, uint32_t address, size_t count) { /* Optimization for uint32_t */ memcpy(dst, dram_u32(address), count * sizeof(uint32_t)); }