diff --git a/Data/Sys/GC/dsp_coef.bin b/Data/Sys/GC/dsp_coef.bin new file mode 100644 index 0000000000..a276f2cede Binary files /dev/null and b/Data/Sys/GC/dsp_coef.bin differ diff --git a/Data/Sys/GC/dsp_rom.bin b/Data/Sys/GC/dsp_rom.bin new file mode 100644 index 0000000000..54e03da7c7 Binary files /dev/null and b/Data/Sys/GC/dsp_rom.bin differ diff --git a/Source/Core/Core/Src/DSP/DSPCore.cpp b/Source/Core/Core/Src/DSP/DSPCore.cpp index 972eb53858..2594a27eef 100644 --- a/Source/Core/Core/Src/DSP/DSPCore.cpp +++ b/Source/Core/Core/Src/DSP/DSPCore.cpp @@ -77,37 +77,50 @@ static bool LoadRom(const char *fname, int size_in_words, u16 *rom) // Returns false iff the hash fails and the user hits "Yes" static bool VerifyRoms(const char *irom_filename, const char *coef_filename) { - static const u32 hash[] = { 0x66f334fe, 0xf3b93527 }; - static const u32 hash_mini[] = { 0x9c8f593c, 0x10000001 }; - static const int size[] = { DSP_IROM_BYTE_SIZE, DSP_COEF_BYTE_SIZE }; - const u16 *data[] = { g_dsp.irom, g_dsp.coef }; - u32 h = 0; - u8 count = 0; - - for (int i = 0; i < 2; i++) + struct DspRomHashes { - h = HashAdler32((u8*)data[i], size[i]); + u32 hash_irom; // dsp_rom.bin + u32 hash_drom; // dsp_coef.bin + } KNOWN_ROMS[] = { + // Official Nintendo ROM + { 0x66f334fe, 0xf3b93527 }, - if (h == hash_mini[i]) - { - count++; - } - else if (h != hash[i]) - { - if (AskYesNoT("%s has an incorrect hash.\n" - "Would you like to stop now to fix the problem?\n" - "If you select \"No\", audio will be garbled.", - (i == 0) ? irom_filename : coef_filename)) - return false; - } + // LM1234 replacement ROM (Zelda UCode only) + { 0x9c8f593c, 0x10000001 }, + + // delroth's improvement on LM1234 replacement ROM (Zelda and AX only, + // IPL/Card/GBA still broken) + { 0xd9907f71, 0xb019c2fb } + }; + + u32 hash_irom = HashAdler32((u8*)g_dsp.irom, DSP_IROM_BYTE_SIZE); + u32 hash_drom = HashAdler32((u8*)g_dsp.coef, DSP_COEF_BYTE_SIZE); + int rom_idx = -1; + + for (u32 i = 0; i < sizeof (KNOWN_ROMS) / sizeof (KNOWN_ROMS[0]); ++i) + { + DspRomHashes& rom = KNOWN_ROMS[i]; + if (hash_irom == rom.hash_irom && hash_drom == rom.hash_drom) + rom_idx = i; } - if (count == 2) + if (rom_idx < 0) { - PanicAlertT("You are using free dsp roms made by Dolphin Team.\n" - "Only Zelda ucode games will work correctly with them.\n"); + if (AskYesNoT("Your DSP ROMs have incorrect hashes.\n" + "Would you like to stop now to fix the problem?\n" + "If you select \"No\", audio might be garbled.")) + return false; } + if (rom_idx == 1) + PanicAlertT("You are using an old free DSP ROM made by the Dolphin Team.\n" + "Only games using the Zelda UCode will work correctly.\n"); + + if (rom_idx == 2) + PanicAlertT("You are using a free DSP ROM made by the Dolphin Team.\n" + "All Wii games will work correctly, and most GC games should " + "also work fine, but the GBA/IPL/CARD UCodes will not work.\n"); + return true; } diff --git a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp index 2cbf39f457..0b1dfe524d 100644 --- a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp +++ b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp @@ -144,13 +144,13 @@ bool DSPLLE::Initialize(void *hWnd, bool bWii, bool bDSPThread) m_bDSPThread = bDSPThread; m_InitMixer = false; - std::string irom_file = File::GetSysDirectory() + GC_SYS_DIR DIR_SEP DSP_IROM; - std::string coef_file = File::GetSysDirectory() + GC_SYS_DIR DIR_SEP DSP_COEF; + std::string irom_file = File::GetUserPath(D_GCUSER_IDX) + DSP_IROM; + std::string coef_file = File::GetUserPath(D_GCUSER_IDX) + DSP_COEF; if (!File::Exists(irom_file)) - irom_file = File::GetUserPath(D_GCUSER_IDX) + DSP_IROM; + irom_file = File::GetSysDirectory() + GC_SYS_DIR DIR_SEP DSP_IROM; if (!File::Exists(coef_file)) - coef_file = File::GetUserPath(D_GCUSER_IDX) + DSP_COEF; + coef_file = File::GetSysDirectory() + GC_SYS_DIR DIR_SEP DSP_COEF; if (!DSPCore_Init(irom_file.c_str(), coef_file.c_str(), AudioCommon::UseJIT())) return false; diff --git a/docs/DSP/dsp_rom_v0.1.rar b/docs/DSP/dsp_rom_v0.1.rar deleted file mode 100644 index dc12816b22..0000000000 Binary files a/docs/DSP/dsp_rom_v0.1.rar and /dev/null differ diff --git a/docs/DSP/free_dsp_rom/dsp_rom.ds b/docs/DSP/free_dsp_rom/dsp_rom.ds new file mode 100644 index 0000000000..bf1ee0c60f --- /dev/null +++ b/docs/DSP/free_dsp_rom/dsp_rom.ds @@ -0,0 +1,1169 @@ +IROM_BASE: equ 0x8000 + +lri $CR, #0x00ff +lri $SR, #0x2000 +si @DMBH, #0x8071 +si @DMBL, #0xfeed + +mainloop: + clr $ACC1 + clr $ACC0 + call wait_for_cpu_mbox+#IROM_BASE + +;mmem-addr +param1: + lr $AC1.M, @CMBL + lri $AC0.M, #0xa001 + cmp + jnz param2+#IROM_BASE + call wait_for_cpu_mbox+#IROM_BASE + lr $IX0, @CMBH + lr $IX1, @CMBL + jmp mainloop+#IROM_BASE + +;iram-addr +param2: + lri $AC0.M, #0xc002 + cmp + jnz param3+#IROM_BASE + call wait_for_cpu_mbox+#IROM_BASE + lr $IX2, @CMBL + jmp mainloop+#IROM_BASE + +;iram-length +param3: + lri $AC0.M, #0xa002 + cmp + jnz param4+#IROM_BASE + call wait_for_cpu_mbox+#IROM_BASE + lr $IX3, @CMBL + jmp mainloop+#IROM_BASE + +;dram-length +param4: + lri $AC0.M, #0xb002 + cmp + jnz param5+#IROM_BASE + call wait_for_cpu_mbox+#IROM_BASE + lr $AX0.L, @CMBL + jmp mainloop+#IROM_BASE + +;iram-start-addr +param5: + lri $AC0.M, #0xd001 + cmp + jnz mainloop+#IROM_BASE + call wait_for_cpu_mbox+#IROM_BASE + lr $AR0, @CMBL + jmp 0x80b5 + +wait_for_dsp_mbox: + lrs $AC0.M, @DMBH + andcf $AC0.M, #0x8000 + jlz wait_for_dsp_mbox+#IROM_BASE + ret + +wait_for_cpu_mbox: + lrs $AC0.M, @CMBH + andcf $AC0.M, #0x8000 + jlnz wait_for_cpu_mbox+#IROM_BASE + ret + +wait_dma: + lrs $AC0.M, @DSCR + andcf $AC0.M, #0x0004 + jlz wait_dma+#IROM_BASE + ret + +bootucode: + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + +sub_80b5: + set16 + clr $ACC1 + clr $ACC0 + lris $AC0.M, #0x2 + sr @DSCR, $AC0.M + sr @DSMAH, $IX0 + sr @DSMAL, $IX1 + sr @DSPA, $IX2 + sr @DSBL, $IX3 + call wait_dma+#IROM_BASE + jmpr $AR0 + + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + +; 80e7 +; Args: +; AR0 points to the 32 input 1 samples (s16) +; AR1 points to the volume data (init1, delta1, init2, delta2) +; AR2 points to the already mixed samples for output 1 (s32) +; AR3 points to where the output 1 should be stored (s32) +; IX0 points to the 32 input 2 samples (s16) +; IX1 points to where the output 2 should be stored (s32) +; +; Returns: +; AX0.L is the value of the last sample from input 1 +; AX1.H is the value of the last sample from input 2 +mix_two_add: + call mix_add+#IROM_BASE + iar $AR1 + mrr $AR0, $IX0 + mrr $AR2, $IX1 + mrr $AR3, $IX1 + mrr $IX0, $AX0.L + call mix_add+#IROM_BASE + mrr $AX1.H, $AX0.L + mrr $AX0.L, $IX0 + ret + + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + +; 81f9 +; Args: +; AR0 points to the 32 input samples (s16) +; AR1 points to the volume data (init, delta) +; AR2 points to the already mixed samples (s32) +; AR3 points to where the output should be stored (s32) +; +; Returns: +; AX0.L is the value of the last sample +; AX1.H is the first address after the output +mix_add: + lrri $AX1.L, @$AR1 + bloopi #32, ____mix_add_end_loop+#IROM_BASE + lrri $AC0.M, @$AR2 + lrri $AC0.L, @$AR2 + lsl16 $ACC0 + lrri $AX0.H, @$AR0 + mulx $AX0.H, $AX1.L + addp $ACC0 + asr16 $ACC0 + srri @$AR3, $AC0.M +____mix_add_end_loop: + srri @$AR3, $AC0.L + movp $ACC0 + mrr $AX0.L, $AC0.M + mrr $AX1.H, $AR3 + ret + + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + +; 8282 +mix_two_add_ramp: + call mix_add_ramp+#IROM_BASE + mrr $AR0, $IX0 + mrr $AR2, $IX1 + mrr $IX1, $AX0.L + call mix_add_ramp+#IROM_BASE + mrr $AX1.H, $AX0.L + mrr $AX0.L, $IX1 + ret + + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + +; 845d +mix_add_ramp: + clr $ACC0 + clr $ACC1 + lrri $AC0.L, @$AR1 + lrrd $AC1.L, @$AR1 + mrr $IX2, $AR3 + + bloopi #32, ____mix_add_ramp_end_ramp+#IROM_BASE + srri @$AR3, $AC0.L +____mix_add_ramp_end_ramp: + add $ACC0, $ACC1 + + srri @$AR1, $AC0.L + iar $AR1 + mrr $IX3, $AR1 + mrr $AR1, $IX2 + mrr $AR3, $AR2 + + bloopi #32, ____mix_add_ramp_end_loop+#IROM_BASE + lrri $AC0.M, @$AR2 + lrri $AC0.L, @$AR2 + lsl16 $ACC0 + lrri $AX0.H, @$AR0 + lrri $AX1.L, @$AR1 + mulx $AX0.H, $AX1.L + addp $ACC0 + asr16 $ACC0 + srri @$AR3, $AC0.M +____mix_add_ramp_end_loop: + srri @$AR3, $AC0.L + movp $ACC0 + mrr $AX0.L, $AC0.M + mrr $AX1.H, $AR3 + mrr $AR1, $IX3 + mrr $AR3, $IX2 + ret diff --git a/docs/DSP/free_dsp_rom/dsp_rom_readme.txt b/docs/DSP/free_dsp_rom/dsp_rom_readme.txt new file mode 100644 index 0000000000..bcaa2eee43 --- /dev/null +++ b/docs/DSP/free_dsp_rom/dsp_rom_readme.txt @@ -0,0 +1,28 @@ +Legal GC/WII DSP IROM replacement (v0.2) +------------------------------------------------------- + +- coef: crafted to use a linear interpolation when resampling (instead of + having a real 4 TAP FIR filter) +- irom: added all the mixing functions, some functions not used by AX/Zelda are + still missing + +Should work with all AX, AXWii and Zelda UCode games. Card/IPL/GBA are most +likely still broken with it and require a real DSP ROM. + +delroth +16/march/2013 + +Legal GC/WII DSP IROM replacement (v0.1) +------------------------------------------------------- +- coef: fake (zeroes) +- irom: reversed and rewrote ucode loading/reset part, everything else is missing + +Good enough for Zelda ucode games (and maybe some AX too): +- WII: SMG 1/2, Pikmin 1/2 WII, Zelda TP WII, Donkey Kong Jungle Beat (WII), ... +- GC: Mario Kart Double Dash, Luigi Mansion, Super Mario Sunshine, Pikmin 1/2, Zelda WW, Zelda TP, ... + +Basically... If game is not using coef and irom mixing functions it will work ok. +Dolphin emulator will report wrong CRCs, but it will work ok with mentioned games. + +LM +31/july/2011