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