282 lines
8.5 KiB
C++
282 lines
8.5 KiB
C++
#include "NDS.h"
|
|
#include "NDSCart.h"
|
|
#include "GBACart.h"
|
|
#include "DSi.h"
|
|
#include "ARM.h"
|
|
#include "SPI.h"
|
|
|
|
#include "dthumb.h"
|
|
|
|
#include <waterboxcore.h>
|
|
|
|
void (*InputCallback)() = nullptr;
|
|
|
|
ECL_EXPORT void SetInputCallback(void (*callback)())
|
|
{
|
|
InputCallback = callback;
|
|
}
|
|
|
|
void (*ReadCallback)(u32) = nullptr;
|
|
void (*WriteCallback)(u32) = nullptr;
|
|
void (*ExecuteCallback)(u32) = nullptr;
|
|
|
|
ECL_EXPORT void SetMemoryCallback(u32 which, void (*callback)(u32 addr))
|
|
{
|
|
switch (which)
|
|
{
|
|
case 0: ReadCallback = callback; break;
|
|
case 1: WriteCallback = callback; break;
|
|
case 2: ExecuteCallback = callback; break;
|
|
}
|
|
}
|
|
|
|
TraceMask_t TraceMask = TRACE_NONE;
|
|
static void (*TraceCallback)(TraceMask_t, u32, u32*, char*, u32) = nullptr;
|
|
|
|
ECL_EXPORT void SetTraceCallback(void (*callback)(TraceMask_t mask, u32 opcode, u32* regs, char* disasm, u32 cyclesOff), TraceMask_t mask)
|
|
{
|
|
TraceCallback = callback;
|
|
TraceMask = callback ? mask : TRACE_NONE;
|
|
}
|
|
|
|
ECL_EXPORT void GetDisassembly(TraceMask_t type, u32 opcode, char* ret)
|
|
{
|
|
static char disasm[DTHUMB_STRING_LENGTH];
|
|
|
|
memset(disasm, 0, sizeof disasm);
|
|
switch (type)
|
|
{
|
|
case TRACE_ARM7_THUMB: Disassemble_thumb(opcode, disasm, ARMv4T); break;
|
|
case TRACE_ARM7_ARM: Disassemble_arm(opcode, disasm, ARMv4T); break;
|
|
case TRACE_ARM9_THUMB: Disassemble_thumb(opcode, disasm, ARMv5TE); break;
|
|
case TRACE_ARM9_ARM: Disassemble_arm(opcode, disasm, ARMv5TE); break;
|
|
default: __builtin_unreachable();
|
|
}
|
|
|
|
memcpy(ret, disasm, DTHUMB_STRING_LENGTH);
|
|
}
|
|
|
|
void TraceTrampoline(TraceMask_t type, u32* regs, u32 opcode)
|
|
{
|
|
static char disasm[DTHUMB_STRING_LENGTH];
|
|
|
|
memset(disasm, 0, sizeof(disasm));
|
|
switch (type)
|
|
{
|
|
case TRACE_ARM7_THUMB: Disassemble_thumb(opcode, disasm, ARMv4T); break;
|
|
case TRACE_ARM7_ARM: Disassemble_arm(opcode, disasm, ARMv4T); break;
|
|
case TRACE_ARM9_THUMB: Disassemble_thumb(opcode, disasm, ARMv5TE); break;
|
|
case TRACE_ARM9_ARM: Disassemble_arm(opcode, disasm, ARMv5TE); break;
|
|
default: __builtin_unreachable();
|
|
}
|
|
|
|
TraceCallback(type, opcode, regs, disasm, NDS::GetSysClockCycles(2));
|
|
}
|
|
|
|
ECL_EXPORT void GetRegs(u32* regs)
|
|
{
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
*regs++ = NDS::ARM9->R[i];
|
|
}
|
|
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
*regs++ = NDS::ARM7->R[i];
|
|
}
|
|
}
|
|
|
|
ECL_EXPORT void SetReg(s32 ncpu, s32 index, s32 val)
|
|
{
|
|
if (ncpu)
|
|
{
|
|
NDS::ARM7->R[index] = val;
|
|
}
|
|
else
|
|
{
|
|
NDS::ARM9->R[index] = val;
|
|
}
|
|
}
|
|
|
|
/* excerpted from gbatek
|
|
|
|
NDS9 Memory Map
|
|
|
|
00000000h Instruction TCM (32KB) (not moveable) (mirror-able to 1000000h)
|
|
0xxxx000h Data TCM (16KB) (moveable)
|
|
02000000h Main Memory (4MB)
|
|
03000000h Shared WRAM (0KB, 16KB, or 32KB can be allocated to ARM9)
|
|
04000000h ARM9-I/O Ports
|
|
05000000h Standard Palettes (2KB) (Engine A BG/OBJ, Engine B BG/OBJ)
|
|
06000000h VRAM - Engine A, BG VRAM (max 512KB)
|
|
06200000h VRAM - Engine B, BG VRAM (max 128KB)
|
|
06400000h VRAM - Engine A, OBJ VRAM (max 256KB)
|
|
06600000h VRAM - Engine B, OBJ VRAM (max 128KB)
|
|
06800000h VRAM - "LCDC"-allocated (max 656KB)
|
|
07000000h OAM (2KB) (Engine A, Engine B)
|
|
08000000h GBA Slot ROM (max 32MB)
|
|
0A000000h GBA Slot RAM (max 64KB)
|
|
FFFF0000h ARM9-BIOS (32KB) (only 3K used)
|
|
|
|
NDS7 Memory Map
|
|
|
|
00000000h ARM7-BIOS (16KB)
|
|
02000000h Main Memory (4MB)
|
|
03000000h Shared WRAM (0KB, 16KB, or 32KB can be allocated to ARM7)
|
|
03800000h ARM7-WRAM (64KB)
|
|
04000000h ARM7-I/O Ports
|
|
04800000h Wireless Communications Wait State 0 (8KB RAM at 4804000h)
|
|
04808000h Wireless Communications Wait State 1 (I/O Ports at 4808000h)
|
|
06000000h VRAM allocated as Work RAM to ARM7 (max 256K)
|
|
08000000h GBA Slot ROM (max 32MB)
|
|
0A000000h GBA Slot RAM (max 64KB)
|
|
|
|
Further Memory (not mapped to ARM9/ARM7 bus)
|
|
|
|
3D Engine Polygon RAM (52KBx2)
|
|
3D Engine Vertex RAM (72KBx2)
|
|
Firmware (256KB) (built-in serial flash memory)
|
|
GBA-BIOS (16KB) (not used in NDS mode)
|
|
NDS Slot ROM (serial 8bit-bus, max 4GB with default protocol)
|
|
NDS Slot FLASH/EEPROM/FRAM (serial 1bit-bus)
|
|
|
|
*/
|
|
|
|
template<bool arm9>
|
|
static bool SafeToPeek(u32 addr)
|
|
{
|
|
if (arm9)
|
|
{
|
|
switch (addr)
|
|
{
|
|
case 0x04000130:
|
|
case 0x04000131:
|
|
case 0x04000600:
|
|
case 0x04000601:
|
|
case 0x04000602:
|
|
case 0x04000603:
|
|
return false;
|
|
}
|
|
}
|
|
else // arm7
|
|
{
|
|
if (addr >= 0x04800000 && addr <= 0x04810000)
|
|
{
|
|
if (addr & 1) addr--;
|
|
addr &= 0x7FFE;
|
|
if (addr == 0x044 || addr == 0x060)
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static void ARM9Access(u8* buffer, s64 address, s64 count, bool write)
|
|
{
|
|
if (write)
|
|
{
|
|
void (*Write)(u32, u8) = NDS::ConsoleType == 1 ? DSi::ARM9Write8 : NDS::ARM9Write8;
|
|
while (count--)
|
|
{
|
|
if (address < NDS::ARM9->ITCMSize)
|
|
{
|
|
NDS::ARM9->ITCM[address++ & (ITCMPhysicalSize - 1)] = *buffer++;
|
|
}
|
|
else if ((address & NDS::ARM9->DTCMMask) == NDS::ARM9->DTCMBase)
|
|
{
|
|
NDS::ARM9->DTCM[address++ & (DTCMPhysicalSize - 1)] = *buffer++;
|
|
}
|
|
else
|
|
{
|
|
Write(address++, *buffer++);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
u8 (*Read)(u32) = NDS::ConsoleType == 1 ? DSi::ARM9Read8 : NDS::ARM9Read8;
|
|
while (count--)
|
|
{
|
|
if (address < NDS::ARM9->ITCMSize)
|
|
{
|
|
*buffer++ = NDS::ARM9->ITCM[address & (ITCMPhysicalSize - 1)];
|
|
}
|
|
else if ((address & NDS::ARM9->DTCMMask) == NDS::ARM9->DTCMBase)
|
|
{
|
|
*buffer++ = NDS::ARM9->DTCM[address & (DTCMPhysicalSize - 1)];
|
|
}
|
|
else
|
|
{
|
|
*buffer++ = SafeToPeek<true>(address) ? Read(address) : 0;
|
|
}
|
|
|
|
address++;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void ARM7Access(u8* buffer, s64 address, s64 count, bool write)
|
|
{
|
|
if (write)
|
|
{
|
|
void (*Write)(u32, u8) = NDS::ConsoleType == 1 ? DSi::ARM7Write8 : NDS::ARM7Write8;
|
|
while (count--)
|
|
Write(address++, *buffer++);
|
|
}
|
|
else
|
|
{
|
|
u8 (*Read)(u32) = NDS::ConsoleType == 1 ? DSi::ARM7Read8 : NDS::ARM7Read8;
|
|
while (count--)
|
|
*buffer++ = SafeToPeek<true>(address) ? Read(address) : 0, address++;
|
|
}
|
|
}
|
|
|
|
ECL_EXPORT void GetMemoryAreas(MemoryArea *m)
|
|
{
|
|
int i = 0;
|
|
#define ADD_MEMORY_DOMAIN(name, data, size, flags) do \
|
|
{ \
|
|
m[i].Data = (void*)data; \
|
|
m[i].Name = name; \
|
|
m[i].Size = size; \
|
|
m[i].Flags = flags; \
|
|
i++; \
|
|
} while (0)
|
|
|
|
ADD_MEMORY_DOMAIN("Main RAM", NDS::MainRAM, NDS::ConsoleType == 1 ? NDS::MainRAMMaxSize : NDS::MainRAMMaxSize / 4, MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_PRIMARY);
|
|
ADD_MEMORY_DOMAIN("Shared WRAM", NDS::SharedWRAM, NDS::SharedWRAMSize, MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE);
|
|
ADD_MEMORY_DOMAIN("ARM7 WRAM", NDS::ARM7WRAM, NDS::ARM7WRAMSize, MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE);
|
|
|
|
if (NDSCart::Cart)
|
|
{
|
|
ADD_MEMORY_DOMAIN("SRAM", NDSCart::GetSaveMemory(), NDSCart::GetSaveMemoryLength(), MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE);
|
|
ADD_MEMORY_DOMAIN("ROM", NDSCart::Cart->GetROM(), NDSCart::Cart->GetROMLength(), MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE);
|
|
}
|
|
|
|
if (GBACart::Cart)
|
|
{
|
|
ADD_MEMORY_DOMAIN("GBA SRAM", GBACart::GetSaveMemory(), GBACart::GetSaveMemoryLength(), MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE);
|
|
ADD_MEMORY_DOMAIN("GBA ROM", GBACart::Cart->GetROM(), GBACart::Cart->GetROMLength(), MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE);
|
|
}
|
|
|
|
ADD_MEMORY_DOMAIN("Instruction TCM", NDS::ARM9->ITCM, ITCMPhysicalSize, MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE);
|
|
ADD_MEMORY_DOMAIN("Data TCM", NDS::ARM9->DTCM, DTCMPhysicalSize, MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE);
|
|
|
|
ADD_MEMORY_DOMAIN("ARM9 BIOS", NDS::ARM9BIOS, sizeof(NDS::ARM9BIOS), MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE);
|
|
ADD_MEMORY_DOMAIN("ARM7 BIOS", NDS::ARM7BIOS, sizeof(NDS::ARM7BIOS), MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE);
|
|
|
|
ADD_MEMORY_DOMAIN("Firmware", SPI_Firmware::GetFirmware()->Buffer(), SPI_Firmware::GetFirmware()->Length(), MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE);
|
|
|
|
if (NDS::ConsoleType == 1)
|
|
{
|
|
ADD_MEMORY_DOMAIN("ARM9i BIOS", DSi::ARM9iBIOS, sizeof(DSi::ARM9iBIOS), MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE);
|
|
ADD_MEMORY_DOMAIN("ARM7i BIOS", DSi::ARM7iBIOS, sizeof(DSi::ARM7iBIOS), MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE);
|
|
}
|
|
|
|
ADD_MEMORY_DOMAIN("ARM9 System Bus", ARM9Access, 1ull << 32, MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_FUNCTIONHOOK);
|
|
ADD_MEMORY_DOMAIN("ARM7 System Bus", ARM7Access, 1ull << 32, MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_FUNCTIONHOOK);
|
|
|
|
// fixme: include more shit
|
|
}
|