1 // Copyright 2008 Dolphin Emulator Project
2 // Copyright 2004 Duddie & Tratax
3 // Licensed under GPLv2+
4 // Refer to the license.txt file included.
5 
6 #include "Core/DSP/DSPCore.h"
7 
8 #include <algorithm>
9 #include <array>
10 #include <memory>
11 #include <type_traits>
12 
13 #include "Common/CommonTypes.h"
14 #include "Common/Event.h"
15 #include "Common/Hash.h"
16 #include "Common/MemoryUtil.h"
17 #include "Common/MsgHandler.h"
18 
19 #include "Core/DSP/DSPAccelerator.h"
20 #include "Core/DSP/DSPAnalyzer.h"
21 #include "Core/DSP/DSPHWInterface.h"
22 #include "Core/DSP/DSPHost.h"
23 #include "Core/DSP/Interpreter/DSPIntUtil.h"
24 #include "Core/DSP/Interpreter/DSPInterpreter.h"
25 #include "Core/DSP/Jit/DSPEmitterBase.h"
26 
27 namespace DSP
28 {
29 SDSP g_dsp;
30 DSPBreakpoints g_dsp_breakpoints;
31 static State core_state = State::Stopped;
32 bool g_init_hax = false;
33 std::unique_ptr<JIT::DSPEmitter> g_dsp_jit;
34 std::unique_ptr<DSPCaptureLogger> g_dsp_cap;
35 static Common::Event step_event;
36 
37 // Returns false if the hash fails and the user hits "Yes"
VerifyRoms()38 static bool VerifyRoms()
39 {
40   struct DspRomHashes
41   {
42     u32 hash_irom;  // dsp_rom.bin
43     u32 hash_drom;  // dsp_coef.bin
44   };
45 
46   static const std::array<DspRomHashes, 6> known_roms = {{
47       // Official Nintendo ROM
48       {0x66f334fe, 0xf3b93527},
49 
50       // LM1234 replacement ROM (Zelda UCode only)
51       {0x9c8f593c, 0x10000001},
52 
53       // delroth's improvement on LM1234 replacement ROM (Zelda and AX only,
54       // IPL/Card/GBA still broken)
55       {0xd9907f71, 0xb019c2fb},
56 
57       // above with improved resampling coefficients
58       {0xd9907f71, 0xdb6880c1},
59 
60       // above with support for GBA ucode
61       {0x3aa4a793, 0xa4a575f5},
62 
63       // above with fix to skip bootucode_ax when running from ROM entrypoint
64       {0x128ea7a2, 0xa4a575f5},
65   }};
66 
67   const u32 hash_irom = Common::HashAdler32(reinterpret_cast<u8*>(g_dsp.irom), DSP_IROM_BYTE_SIZE);
68   const u32 hash_drom = Common::HashAdler32(reinterpret_cast<u8*>(g_dsp.coef), DSP_COEF_BYTE_SIZE);
69   int rom_idx = -1;
70 
71   for (size_t i = 0; i < known_roms.size(); ++i)
72   {
73     const DspRomHashes& rom = known_roms[i];
74     if (hash_irom == rom.hash_irom && hash_drom == rom.hash_drom)
75       rom_idx = static_cast<int>(i);
76   }
77 
78   if (rom_idx < 0)
79   {
80     if (AskYesNoT("Your DSP ROMs have incorrect hashes.\n"
81                   "Would you like to stop now to fix the problem?\n"
82                   "If you select \"No\", audio might be garbled."))
83       return false;
84   }
85 
86   if (rom_idx == 1)
87   {
88     Host::OSD_AddMessage("You are using an old free DSP ROM made by the Dolphin Team.", 6000);
89     Host::OSD_AddMessage("Only games using the Zelda UCode will work correctly.", 6000);
90   }
91   else if (rom_idx == 2 || rom_idx == 3)
92   {
93     Host::OSD_AddMessage("You are using a free DSP ROM made by the Dolphin Team.", 8000);
94     Host::OSD_AddMessage("All Wii games will work correctly, and most GameCube games", 8000);
95     Host::OSD_AddMessage("should also work fine, but the GBA/CARD UCodes will not work.", 8000);
96   }
97   else if (rom_idx == 4)
98   {
99     Host::OSD_AddMessage("You are using a free DSP ROM made by the Dolphin Team.", 8000);
100     Host::OSD_AddMessage("All Wii games will work correctly, and most GameCube games", 8000);
101     Host::OSD_AddMessage("should also work fine, but the CARD UCode will not work.", 8000);
102   }
103 
104   return true;
105 }
106 
DSPCore_FreeMemoryPages()107 static void DSPCore_FreeMemoryPages()
108 {
109   Common::FreeMemoryPages(g_dsp.irom, DSP_IROM_BYTE_SIZE);
110   Common::FreeMemoryPages(g_dsp.iram, DSP_IRAM_BYTE_SIZE);
111   Common::FreeMemoryPages(g_dsp.dram, DSP_DRAM_BYTE_SIZE);
112   Common::FreeMemoryPages(g_dsp.coef, DSP_COEF_BYTE_SIZE);
113   g_dsp.irom = g_dsp.iram = g_dsp.dram = g_dsp.coef = nullptr;
114 }
115 
116 class LLEAccelerator final : public Accelerator
117 {
118 protected:
ReadMemory(u32 address)119   u8 ReadMemory(u32 address) override { return Host::ReadHostMemory(address); }
WriteMemory(u32 address,u8 value)120   void WriteMemory(u32 address, u8 value) override { Host::WriteHostMemory(value, address); }
OnEndException()121   void OnEndException() override { DSPCore_SetException(ExceptionType::AcceleratorOverflow); }
122 };
123 
DSPCore_Init(const DSPInitOptions & opts)124 bool DSPCore_Init(const DSPInitOptions& opts)
125 {
126   g_dsp.step_counter = 0;
127   g_init_hax = false;
128 
129   g_dsp.accelerator = std::make_unique<LLEAccelerator>();
130 
131   g_dsp.irom = static_cast<u16*>(Common::AllocateMemoryPages(DSP_IROM_BYTE_SIZE));
132   g_dsp.iram = static_cast<u16*>(Common::AllocateMemoryPages(DSP_IRAM_BYTE_SIZE));
133   g_dsp.dram = static_cast<u16*>(Common::AllocateMemoryPages(DSP_DRAM_BYTE_SIZE));
134   g_dsp.coef = static_cast<u16*>(Common::AllocateMemoryPages(DSP_COEF_BYTE_SIZE));
135 
136   memcpy(g_dsp.irom, opts.irom_contents.data(), DSP_IROM_BYTE_SIZE);
137   memcpy(g_dsp.coef, opts.coef_contents.data(), DSP_COEF_BYTE_SIZE);
138 
139   // Try to load real ROM contents.
140   if (!VerifyRoms())
141   {
142     DSPCore_FreeMemoryPages();
143     return false;
144   }
145 
146   memset(&g_dsp.r, 0, sizeof(g_dsp.r));
147 
148   std::fill(std::begin(g_dsp.reg_stack_ptrs), std::end(g_dsp.reg_stack_ptrs), 0);
149 
150   for (auto& stack : g_dsp.reg_stacks)
151     std::fill(std::begin(stack), std::end(stack), 0);
152 
153   // Fill IRAM with HALT opcodes.
154   std::fill(g_dsp.iram, g_dsp.iram + DSP_IRAM_SIZE, 0x0021);
155 
156   // Just zero out DRAM.
157   std::fill(g_dsp.dram, g_dsp.dram + DSP_DRAM_SIZE, 0);
158 
159   // Copied from a real console after the custom UCode has been loaded.
160   // These are the indexing wrapping registers.
161   std::fill(std::begin(g_dsp.r.wr), std::end(g_dsp.r.wr), 0xffff);
162 
163   g_dsp.r.sr |= SR_INT_ENABLE;
164   g_dsp.r.sr |= SR_EXT_INT_ENABLE;
165 
166   g_dsp.cr = 0x804;
167   gdsp_ifx_init();
168   // Mostly keep IRAM write protected. We unprotect only when DMA-ing
169   // in new ucodes.
170   Common::WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
171 
172   // Initialize JIT, if necessary
173   if (opts.core_type == DSPInitOptions::CoreType::JIT64)
174     g_dsp_jit = JIT::CreateDSPEmitter();
175 
176   g_dsp_cap.reset(opts.capture_logger);
177 
178   core_state = State::Running;
179   return true;
180 }
181 
DSPCore_Shutdown()182 void DSPCore_Shutdown()
183 {
184   if (core_state == State::Stopped)
185     return;
186 
187   core_state = State::Stopped;
188 
189   g_dsp_jit.reset();
190 
191   DSPCore_FreeMemoryPages();
192 
193   g_dsp_cap.reset();
194 }
195 
DSPCore_Reset()196 void DSPCore_Reset()
197 {
198   g_dsp.pc = DSP_RESET_VECTOR;
199 
200   std::fill(std::begin(g_dsp.r.wr), std::end(g_dsp.r.wr), 0xffff);
201 
202   Analyzer::Analyze();
203 }
204 
DSPCore_SetException(ExceptionType exception)205 void DSPCore_SetException(ExceptionType exception)
206 {
207   g_dsp.exceptions |= 1 << static_cast<std::underlying_type_t<ExceptionType>>(exception);
208 }
209 
210 // Notify that an external interrupt is pending (used by thread mode)
DSPCore_SetExternalInterrupt(bool val)211 void DSPCore_SetExternalInterrupt(bool val)
212 {
213   g_dsp.external_interrupt_waiting = val;
214 }
215 
216 // Coming from the CPU
DSPCore_CheckExternalInterrupt()217 void DSPCore_CheckExternalInterrupt()
218 {
219   if (!Interpreter::dsp_SR_is_flag_set(SR_EXT_INT_ENABLE))
220     return;
221 
222   // Signal the SPU about new mail
223   DSPCore_SetException(ExceptionType::ExternalInterrupt);
224 
225   g_dsp.cr &= ~CR_EXTERNAL_INT;
226 }
227 
DSPCore_CheckExceptions()228 void DSPCore_CheckExceptions()
229 {
230   // Early out to skip the loop in the common case.
231   if (g_dsp.exceptions == 0)
232     return;
233 
234   for (int i = 7; i > 0; i--)
235   {
236     // Seems exp int are not masked by sr_int_enable
237     if (g_dsp.exceptions & (1 << i))
238     {
239       if (Interpreter::dsp_SR_is_flag_set(SR_INT_ENABLE) ||
240           i == static_cast<int>(ExceptionType::ExternalInterrupt))
241       {
242         // store pc and sr until RTI
243         dsp_reg_store_stack(StackRegister::Call, g_dsp.pc);
244         dsp_reg_store_stack(StackRegister::Data, g_dsp.r.sr);
245 
246         g_dsp.pc = i * 2;
247         g_dsp.exceptions &= ~(1 << i);
248         if (i == 7)
249           g_dsp.r.sr &= ~SR_EXT_INT_ENABLE;
250         else
251           g_dsp.r.sr &= ~SR_INT_ENABLE;
252         break;
253       }
254       else
255       {
256 #if defined(_DEBUG) || defined(DEBUGFAST)
257         ERROR_LOG(DSPLLE, "Firing exception %d failed", i);
258 #endif
259       }
260     }
261   }
262 }
263 
264 // Delegate to JIT or interpreter as appropriate.
265 // Handle state changes and stepping.
DSPCore_RunCycles(int cycles)266 int DSPCore_RunCycles(int cycles)
267 {
268   if (g_dsp_jit)
269   {
270     return g_dsp_jit->RunCycles(static_cast<u16>(cycles));
271   }
272 
273   while (cycles > 0)
274   {
275     switch (core_state)
276     {
277     case State::Running:
278 // Seems to slow things down
279 #if defined(_DEBUG) || defined(DEBUGFAST)
280       cycles = Interpreter::RunCyclesDebug(cycles);
281 #else
282       cycles = Interpreter::RunCycles(cycles);
283 #endif
284       break;
285 
286     case State::Stepping:
287       step_event.Wait();
288       if (core_state != State::Stepping)
289         continue;
290 
291       Interpreter::Step();
292       cycles--;
293 
294       Host::UpdateDebugger();
295       break;
296     case State::Stopped:
297       break;
298     }
299   }
300   return cycles;
301 }
302 
DSPCore_SetState(State new_state)303 void DSPCore_SetState(State new_state)
304 {
305   core_state = new_state;
306 
307   // kick the event, in case we are waiting
308   if (new_state == State::Running)
309     step_event.Set();
310 
311   Host::UpdateDebugger();
312 }
313 
DSPCore_GetState()314 State DSPCore_GetState()
315 {
316   return core_state;
317 }
318 
DSPCore_Step()319 void DSPCore_Step()
320 {
321   if (core_state == State::Stepping)
322     step_event.Set();
323 }
324 
DSPCore_ReadRegister(size_t reg)325 u16 DSPCore_ReadRegister(size_t reg)
326 {
327   switch (reg)
328   {
329   case DSP_REG_AR0:
330   case DSP_REG_AR1:
331   case DSP_REG_AR2:
332   case DSP_REG_AR3:
333     return g_dsp.r.ar[reg - DSP_REG_AR0];
334   case DSP_REG_IX0:
335   case DSP_REG_IX1:
336   case DSP_REG_IX2:
337   case DSP_REG_IX3:
338     return g_dsp.r.ix[reg - DSP_REG_IX0];
339   case DSP_REG_WR0:
340   case DSP_REG_WR1:
341   case DSP_REG_WR2:
342   case DSP_REG_WR3:
343     return g_dsp.r.wr[reg - DSP_REG_WR0];
344   case DSP_REG_ST0:
345   case DSP_REG_ST1:
346   case DSP_REG_ST2:
347   case DSP_REG_ST3:
348     return g_dsp.r.st[reg - DSP_REG_ST0];
349   case DSP_REG_ACH0:
350   case DSP_REG_ACH1:
351     return g_dsp.r.ac[reg - DSP_REG_ACH0].h;
352   case DSP_REG_CR:
353     return g_dsp.r.cr;
354   case DSP_REG_SR:
355     return g_dsp.r.sr;
356   case DSP_REG_PRODL:
357     return g_dsp.r.prod.l;
358   case DSP_REG_PRODM:
359     return g_dsp.r.prod.m;
360   case DSP_REG_PRODH:
361     return g_dsp.r.prod.h;
362   case DSP_REG_PRODM2:
363     return g_dsp.r.prod.m2;
364   case DSP_REG_AXL0:
365   case DSP_REG_AXL1:
366     return g_dsp.r.ax[reg - DSP_REG_AXL0].l;
367   case DSP_REG_AXH0:
368   case DSP_REG_AXH1:
369     return g_dsp.r.ax[reg - DSP_REG_AXH0].h;
370   case DSP_REG_ACL0:
371   case DSP_REG_ACL1:
372     return g_dsp.r.ac[reg - DSP_REG_ACL0].l;
373   case DSP_REG_ACM0:
374   case DSP_REG_ACM1:
375     return g_dsp.r.ac[reg - DSP_REG_ACM0].m;
376   default:
377     ASSERT_MSG(DSP_CORE, 0, "cannot happen");
378     return 0;
379   }
380 }
381 
DSPCore_WriteRegister(size_t reg,u16 val)382 void DSPCore_WriteRegister(size_t reg, u16 val)
383 {
384   switch (reg)
385   {
386   case DSP_REG_AR0:
387   case DSP_REG_AR1:
388   case DSP_REG_AR2:
389   case DSP_REG_AR3:
390     g_dsp.r.ar[reg - DSP_REG_AR0] = val;
391     break;
392   case DSP_REG_IX0:
393   case DSP_REG_IX1:
394   case DSP_REG_IX2:
395   case DSP_REG_IX3:
396     g_dsp.r.ix[reg - DSP_REG_IX0] = val;
397     break;
398   case DSP_REG_WR0:
399   case DSP_REG_WR1:
400   case DSP_REG_WR2:
401   case DSP_REG_WR3:
402     g_dsp.r.wr[reg - DSP_REG_WR0] = val;
403     break;
404   case DSP_REG_ST0:
405   case DSP_REG_ST1:
406   case DSP_REG_ST2:
407   case DSP_REG_ST3:
408     g_dsp.r.st[reg - DSP_REG_ST0] = val;
409     break;
410   case DSP_REG_ACH0:
411   case DSP_REG_ACH1:
412     g_dsp.r.ac[reg - DSP_REG_ACH0].h = val;
413     break;
414   case DSP_REG_CR:
415     g_dsp.r.cr = val;
416     break;
417   case DSP_REG_SR:
418     g_dsp.r.sr = val;
419     break;
420   case DSP_REG_PRODL:
421     g_dsp.r.prod.l = val;
422     break;
423   case DSP_REG_PRODM:
424     g_dsp.r.prod.m = val;
425     break;
426   case DSP_REG_PRODH:
427     g_dsp.r.prod.h = val;
428     break;
429   case DSP_REG_PRODM2:
430     g_dsp.r.prod.m2 = val;
431     break;
432   case DSP_REG_AXL0:
433   case DSP_REG_AXL1:
434     g_dsp.r.ax[reg - DSP_REG_AXL0].l = val;
435     break;
436   case DSP_REG_AXH0:
437   case DSP_REG_AXH1:
438     g_dsp.r.ax[reg - DSP_REG_AXH0].h = val;
439     break;
440   case DSP_REG_ACL0:
441   case DSP_REG_ACL1:
442     g_dsp.r.ac[reg - DSP_REG_ACL0].l = val;
443     break;
444   case DSP_REG_ACM0:
445   case DSP_REG_ACM1:
446     g_dsp.r.ac[reg - DSP_REG_ACM0].m = val;
447     break;
448   }
449 }
450 }  // namespace DSP
451