From 9a404ca6d4020fa77c61d4cd210b924b06deaf94 Mon Sep 17 00:00:00 2001 From: Pierre Bourdon Date: Sat, 16 Mar 2013 23:54:55 +0100 Subject: [PATCH] Ship by default a free DSP ROM that can handle most games with LLE At the end of July 2011, LM published a free DSP ROM that works with games using the Zelda UCode. His ROM only has the code to handle UCode loading and a few utility functions, the rest is missing. This includes the four large sound mixing functions used by the AX UCode and the DROM containing coefficients used for polyphase resampling in AX. This is an improved, updated version of this ROM, which changes the following: - We now have a free DROM that works for polyphase resampling by "emulating" linear interpolation. The coefficients contained in the DROM are normally a list of { c1, c2, c3, c4 } which are used to interpolate a sample value from four previous samples: out_sample = prev1 * c1 + prev2 * c2 + prev3 * c3 + prev4 * c4 The coefficients are chosen depending on the fractional part of the current position (basically, our position between the previous and the next sample). We can use this fact to generate (c1, c2, c3, c4) for each possible fractional part so that: out_sample = prev3 * curr_pos + prev4 * (1 - curr_pos) Which is the formula for linear interpolation between prev3 and prev4. Linear interpolation is not as good as polyphase resampling but it still works very well and I couldn't really hear any difference between the two. If someone wants to generate real polyphase filter coefficients, they are welcome to submit a patch. - The IROM now contains the 4 mixing functions used by the AX UCode: mix_add, mix_add_two, mix_add_ramp, mix_add_ramp_two. They are large, inlined functions (probably for performance reasons) in the official DSP IROM, our version prefers to use a loop. This *should* be more performant with our DSP JIT implementation, but I did not benchmark that. Because the new DSP ROM is working just as well as the official ROM in 95% of cases, it is now shipped by default with Dolphin and will be used with DSPLLE if you don't have an official DSP ROM in User/GC. It will still display a panic alert at every boot to notice you that you are using a non official DSP ROM made by us, which is not perfect. Games using the CARD, IPL or GBA UCodes are still broken. I don't know what games this actually impacts, but this is a very small proportion compared to what works. --- Data/Sys/GC/dsp_coef.bin | Bin 0 -> 4096 bytes Data/Sys/GC/dsp_rom.bin | Bin 0 -> 8192 bytes Source/Core/Core/Src/DSP/DSPCore.cpp | 61 +- Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp | 8 +- docs/DSP/dsp_rom_v0.1.rar | Bin 2118 -> 0 bytes docs/DSP/free_dsp_rom/dsp_rom.ds | 1169 +++++++++++++++++++++ docs/DSP/free_dsp_rom/dsp_rom_readme.txt | 28 + 7 files changed, 1238 insertions(+), 28 deletions(-) create mode 100644 Data/Sys/GC/dsp_coef.bin create mode 100644 Data/Sys/GC/dsp_rom.bin delete mode 100644 docs/DSP/dsp_rom_v0.1.rar create mode 100644 docs/DSP/free_dsp_rom/dsp_rom.ds create mode 100644 docs/DSP/free_dsp_rom/dsp_rom_readme.txt diff --git a/Data/Sys/GC/dsp_coef.bin b/Data/Sys/GC/dsp_coef.bin new file mode 100644 index 0000000000000000000000000000000000000000..a276f2cede1a8e6936b4526f9621a391ca6b9515 GIT binary patch literal 4096 zcmeIz)mD&E6h+}l34*jBNOwwicXufuDXny;kFGEuL;rJezWX)y8Vlg}pV#kALiB}D zeI`tw2-im<^nrJJPo&-vrMJA-8>01^7`@_yUJ|Pp#OXQldPahtlBg#n=`qRri;wz~ z6g?tU5Ba1Ar0G8Cy2oeTB|~?})E{K&HrcvGj&72x8|3La`MO4dey31ZDbf{+b(s?V zMyYjVutPNR;|q@y(J2rW8Hs}9ko zgS6`a9okQ)_R*!ibZZYi+D)%^(WjmCYX<|`&Y-q2q^%5V3nSXhs5UXCjf`sp6I#!t z)-k2EOlu7@TFtChF{fXc*Gd+&f<-N7Nz3@ErF_#8mbI7_En-y*`K|@5X+G}fjtn#O^C;!smL(iDE`M}BEC$C|{6CUU9?oM}Ag8pnmk za;YD<(ipBanj3x3twwRDk=*M$9yEeS4d+S2c-Bx}G~~7MZ!hS7t~mt#5BmRh2toft d?L)Bt!T!G;La_h;_WoP;;0qE668P^D_zP_)!utRK literal 0 HcmV?d00001 diff --git a/Data/Sys/GC/dsp_rom.bin b/Data/Sys/GC/dsp_rom.bin new file mode 100644 index 0000000000000000000000000000000000000000..54e03da7c7a620df76054e8422f645a3c0b97da1 GIT binary patch literal 8192 zcmeIzy-UMD7zXgiBSKx2F4dUBWQwz6A*;Apm#*rd)KPE|ha%U~#YOOAaM0R6p^M-m z3HU`3KSsA8_%R8tLd|)(k|k@FmcE(Zdk&7|mwWGU2#F&Hg|65t{6*h;sDb&SgiuN} zTO)O_V`1s!Mn<@mlAVhjngP=@uAaF|(pE2>)9HPZwtK0k)7K<@>8+j9X`s^!x61+n zb|w~B=tjCe6(v=7SO7!iWfo#UpMAu(;|!7P;9Wl9Lq6kEKH^J0D1-9kMD`D3e(e`y z+~D)P!cXFny<;1LYnEMvR!9q&#k^BD%vE#w2j+AeOE`eFYgIR4&)Dn3xL26pSkXOm z8CR-fMu$-$y-#RN0{tvdQ}?OqOo literal 0 HcmV?d00001 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 dc12816b22ea8461a3a04a93cbd8bd8194222f53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2118 zcmZ9Mc{J2*AI5*#HHOA0Z9++iA+kh&mQ2iyEk$L^$bP(KELmd+BaO8% zk7;|1B^o3#Bq=3j!Q}ZI` z{&9-dyc1G@_ktrkV?Hw7Y=-7J5u4QFlcpm^L3+!4hw)9C|CGQPx|8JJP2msY+ z0wN$`#q82O4rx&WErg0L)e)l^InCyuT|;B<9BDRrwd9$s84zRM{4p+elLga{OZO$C z-i!n(#erV6g4HMMMiV9Y1>Q4Qp6?q+W98W!m}cHiZT5;Z=>SWd4HQKtud;p3MYuv z-C$sLTSY{fsZn?Xwy`De=fUF=UTJ^KDK<4wL zrPL0y5o_Ndxh`rDj|FgRn-k&;}yf-iX8Gx%BP~W(if_- zzYT1aKhm`6@{gS_M@>eNpCmgJ33B?oG}bV-koq7OCfcEku5HN&57%`j(P!Yi*Li>ce zz|gKs;;nbugxf!T&=e{)?1Ru8hj~3g(sgDQ7FFR{F(>%|T zqAwRpyVIh|n2!k&j<`pt&1d!#SX1cDW#q-K;o~6A`4-Z=%wU2I*B~mV&Dy#LL}j~; zhL!5J_l>wVkUdGY2*&td#Y&pgrS$ffP|+bW7L<+oG}SqMbh7>R5&El9c#2@aO1UaO zcyfFJSIK?lrDS@=h=WNW>B=Fq2-=vlTi4iXvtYwp1&ypxTcP0xaCB2cVvg=xr^WAg zOKq!dW|JfDg^WkJ{}7vp1v}-T%|g#e_p|2g=4CXqJB;;wbX$jAe4z4-2Gr=8r9dyV z>6lE&+Ufc#i2$L|#jzTAwg3KF;b@)2DO~TTFXmMkw=d5cUo55fqq^JH*RH|O)QaEd zJ9ToVQrXJUgX#_+4W4r>r|1AYijV$<%6*KwPVMy2tY#n~B2+8I0 zWKiE2Sz>$1TH&91NPDQ(h_&G%^o@#2U&E1y>=5Vb&SqZ{mf0PJt&q4#4Z zyH{OSXTl8sw`V&Kg4=MVWL7m>POHpBN>#(nx#s)H%VxUNQ0+6r7vC3el4amI5C4aaxAcj z0jv22#|EZ&JkEB)^sM&ne~b%OEANG7-7Yyy#SNof+1v?33pDZX?6;oCa2*8}hhb7r zjj#=jKUQ8jkYv$IIUA7grsNCb-7Jcp{wGh**d9XY<|_*Hx-cD_n>I8j^ewYg`}|CxR1*ZdWIhHfOF&ky_;tK#&> 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