DS: A little more skeleton

This commit is contained in:
Jeffrey Pfau 2016-06-01 19:14:18 -07:00
parent 290d5b77dd
commit 3cf9446ba1
8 changed files with 837 additions and 4 deletions

View File

@ -842,6 +842,7 @@ if(NOT QUIET)
message(STATUS "Platforms:")
message(STATUS " Game Boy Advance: ${M_CORE_GBA}")
message(STATUS " Game Boy: ${M_CORE_GB}")
message(STATUS " DS: ${M_CORE_DS}")
message(STATUS "Features:")
message(STATUS " Debuggers: ${USE_DEBUGGERS}")
message(STATUS " CLI debugger: ${USE_EDITLINE}")

11
src/ds/bios.c Normal file
View File

@ -0,0 +1,11 @@
/* Copyright (c) 2013-2016 Jeffrey Pfau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "bios.h"
mLOG_DEFINE_CATEGORY(DS_BIOS, "DS BIOS");
const uint32_t DS7_BIOS_CHECKSUM = 0x1280F0D5;
const uint32_t DS9_BIOS_CHECKSUM = 0x2AB23573;

24
src/ds/bios.h Normal file
View File

@ -0,0 +1,24 @@
/* Copyright (c) 2013-2016 Jeffrey Pfau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef DS_BIOS_H
#define DS_BIOS_H
#include "util/common.h"
#include "core/log.h"
mLOG_DECLARE_CATEGORY(DS_BIOS);
struct ARMCore;
void DS7Swi16(struct ARMCore* cpu, int immediate);
void DS7Swi32(struct ARMCore* cpu, int immediate);
void DS9Swi16(struct ARMCore* cpu, int immediate);
void DS9Swi32(struct ARMCore* cpu, int immediate);
extern const uint32_t DS7_BIOS_CHECKSUM;
extern const uint32_t DS9_BIOS_CHECKSUM;
#endif

View File

@ -91,6 +91,14 @@ static void _DSCoreSetSync(struct mCore* core, struct mCoreSync* sync) {
}
static void _DSCoreLoadConfig(struct mCore* core, const struct mCoreConfig* config) {
struct DS* ds = core->board;
struct VFile* bios = NULL;
if (core->opts.useBios && core->opts.bios) {
bios = VFileOpen(core->opts.bios, O_RDONLY);
}
if (bios) {
DSLoadBIOS(ds, bios);
}
}
static void _DSCoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) {
@ -124,7 +132,8 @@ static bool _DSCoreLoadROM(struct mCore* core, struct VFile* vf) {
}
static bool _DSCoreLoadBIOS(struct mCore* core, struct VFile* vf, int type) {
return false;
UNUSED(type);
return DSLoadBIOS(core->board, vf);
}
static bool _DSCoreLoadSave(struct mCore* core, struct VFile* vf) {

View File

@ -8,11 +8,11 @@
#include "arm/decoder.h"
#include "arm/debugger/debugger.h"
#include "arm/isa-inlines.h"
#include "ds/bios.h"
#include "util/crc32.h"
#include "util/memory.h"
#include "util/math.h"
#include "util/patch.h"
#include "util/vfs.h"
mLOG_DEFINE_CATEGORY(DS, "DS");
@ -67,8 +67,11 @@ static void DSInit(void* cpu, struct mCPUComponent* component) {
}
ds->arm9 = cpu;
ds->arm9->cp15.r1.c0 = ARMControlRegFillVE(0);
DS7InterruptHandlerInit(&ds->arm7->irqh);
DS9InterruptHandlerInit(&ds->arm9->irqh);
DSMemoryInit(ds);
ds->video.p = ds;
@ -92,6 +95,7 @@ void DSUnloadROM(struct DS* ds) {
void DSDestroy(struct DS* ds) {
DSUnloadROM(ds);
DSMemoryDeinit(ds);
}
void DS7InterruptHandlerInit(struct ARMInterruptHandler* irqh) {
@ -134,6 +138,9 @@ void DS9Reset(struct ARMCore* cpu) {
cpu->gprs[ARM_SP] = DS9_SP_BASE_SVC;
ARMSetPrivilegeMode(cpu, MODE_SYSTEM);
cpu->gprs[ARM_SP] = DS9_SP_BASE;
struct DS* ds = (struct DS*) cpu->master;
DSMemoryReset(ds);
}
static void DSProcessEvents(struct ARMCore* cpu) {
@ -198,6 +205,35 @@ bool DSIsROM(struct VFile* vf) {
return memcmp(signature, DS_ROM_MAGIC, sizeof(signature)) == 0;
}
bool DSLoadBIOS(struct DS* ds, struct VFile* vf) {
size_t size = vf->size(vf);
void* data = NULL;
uint32_t crc;
if (size == DS7_SIZE_BIOS) {
data = vf->map(vf, size, MAP_READ);
} else if (size == 0x1000) {
data = vf->map(vf, size, MAP_READ);
}
if (!data) {
return false;
}
crc = doCrc32(data, size);
if (crc == DS7_BIOS_CHECKSUM) {
ds->bios7Vf = vf;
ds->memory.bios7 = data;
mLOG(DS, INFO, "Official DS ARM7 BIOS detected");
} else if (crc == DS9_BIOS_CHECKSUM) {
ds->bios9Vf = vf;
ds->memory.bios9 = data;
mLOG(DS, INFO, "Official DS ARM9 BIOS detected");
} else {
mLOG(DS, WARN, "BIOS checksum incorrect");
vf->unmap(vf, data, size);
return false;
}
return true;
}
void DSGetGameCode(struct DS* ds, char* out) {
memset(out, 0, 8);
if (!ds->romVf) {

View File

@ -11,6 +11,7 @@
#include "arm/arm.h"
#include "core/log.h"
#include "ds/memory.h"
#include "ds/video.h"
extern const uint32_t DS_ARM946ES_FREQUENCY;
@ -54,6 +55,7 @@ struct DS {
struct ARMCore* arm7;
struct ARMCore* arm9;
struct DSMemory memory;
struct DSVideo video;
struct mCoreSync* sync;
@ -63,13 +65,15 @@ struct DS {
int springIRQ7;
int springIRQ9;
uint32_t biosChecksum;
uint32_t bios7Checksum;
uint32_t bios9Checksum;
int* keySource;
struct mRTCSource* rtcSource;
struct mRumble* rumble;
uint32_t romCrc32;
struct VFile* romVf;
struct VFile* bios7Vf;
struct VFile* bios9Vf;
struct mKeyCallback* keyCallback;
};
@ -121,6 +125,8 @@ bool DSLoadROM(struct DS* ds, struct VFile* vf);
void DSUnloadROM(struct DS* ds);
void DSApplyPatch(struct DS* ds, struct Patch* patch);
bool DSLoadBIOS(struct DS* ds, struct VFile* vf);
bool DSIsROM(struct VFile* vf);
void DSGetGameCode(struct DS* ds, char* out);
void DSGetGameTitle(struct DS* ds, char* out);

583
src/ds/memory.c Normal file
View File

@ -0,0 +1,583 @@
/* Copyright (c) 2013-2016 Jeffrey Pfau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "memory.h"
#include "ds/ds.h"
#include "util/math.h"
mLOG_DEFINE_CATEGORY(DS_MEM, "DS Memory");
#define LDM_LOOP(LDM) \
for (i = 0; i < 16; i += 4) { \
if (UNLIKELY(mask & (1 << i))) { \
LDM; \
cpu->gprs[i] = value; \
++wait; \
address += 4; \
} \
if (UNLIKELY(mask & (2 << i))) { \
LDM; \
cpu->gprs[i + 1] = value; \
++wait; \
address += 4; \
} \
if (UNLIKELY(mask & (4 << i))) { \
LDM; \
cpu->gprs[i + 2] = value; \
++wait; \
address += 4; \
} \
if (UNLIKELY(mask & (8 << i))) { \
LDM; \
cpu->gprs[i + 3] = value; \
++wait; \
address += 4; \
} \
}
#define STM_LOOP(STM) \
for (i = 0; i < 16; i += 4) { \
if (UNLIKELY(mask & (1 << i))) { \
value = cpu->gprs[i]; \
STM; \
++wait; \
address += 4; \
} \
if (UNLIKELY(mask & (2 << i))) { \
value = cpu->gprs[i + 1]; \
STM; \
++wait; \
address += 4; \
} \
if (UNLIKELY(mask & (4 << i))) { \
value = cpu->gprs[i + 2]; \
STM; \
++wait; \
address += 4; \
} \
if (UNLIKELY(mask & (8 << i))) { \
value = cpu->gprs[i + 3]; \
STM; \
++wait; \
address += 4; \
} \
}
static uint32_t _deadbeef[1] = { 0xE710B710 }; // Illegal instruction on both ARM and Thumb
static void DS7SetActiveRegion(struct ARMCore* cpu, uint32_t region);
static void DS9SetActiveRegion(struct ARMCore* cpu, uint32_t region);
static int32_t DSMemoryStall(struct ARMCore* cpu, int32_t wait);
static const int DMA_OFFSET[] = { 1, -1, 0, 1 };
void DSMemoryInit(struct DS* ds) {
struct ARMCore* arm7 = ds->arm7;
arm7->memory.load32 = DS7Load32;
arm7->memory.load16 = DS7Load16;
arm7->memory.load8 = DS7Load8;
arm7->memory.loadMultiple = DS7LoadMultiple;
arm7->memory.store32 = DS7Store32;
arm7->memory.store16 = DS7Store16;
arm7->memory.store8 = DS7Store8;
arm7->memory.storeMultiple = DS7StoreMultiple;
arm7->memory.stall = DSMemoryStall;
struct ARMCore* arm9 = ds->arm9;
arm9->memory.load32 = DS9Load32;
arm9->memory.load16 = DS9Load16;
arm9->memory.load8 = DS9Load8;
arm9->memory.loadMultiple = DS9LoadMultiple;
arm9->memory.store32 = DS9Store32;
arm9->memory.store16 = DS9Store16;
arm9->memory.store8 = DS9Store8;
arm9->memory.storeMultiple = DS9StoreMultiple;
arm9->memory.stall = DSMemoryStall;
ds->memory.bios7 = NULL;
ds->memory.bios9 = NULL;
ds->memory.wram = NULL;
ds->memory.ram = NULL;
ds->memory.rom = NULL;
ds->memory.activeRegion7 = -1;
ds->memory.activeRegion9 = -1;
arm7->memory.activeRegion = 0;
arm7->memory.activeMask = 0;
arm7->memory.setActiveRegion = DS7SetActiveRegion;
arm7->memory.activeSeqCycles32 = 0;
arm7->memory.activeSeqCycles16 = 0;
arm7->memory.activeNonseqCycles32 = 0;
arm7->memory.activeNonseqCycles16 = 0;
arm9->memory.activeRegion = 0;
arm9->memory.activeMask = 0;
arm9->memory.setActiveRegion = DS9SetActiveRegion;
arm9->memory.activeSeqCycles32 = 0;
arm9->memory.activeSeqCycles16 = 0;
arm9->memory.activeNonseqCycles32 = 0;
arm9->memory.activeNonseqCycles16 = 0;
}
void DSMemoryDeinit(struct DS* ds) {
mappedMemoryFree(ds->memory.wram, DS_SIZE_WORKING_RAM);
mappedMemoryFree(ds->memory.ram, DS_SIZE_RAM);
}
void DSMemoryReset(struct DS* ds) {
if (ds->memory.wram) {
mappedMemoryFree(ds->memory.wram, DS_SIZE_WORKING_RAM);
}
ds->memory.wram = anonymousMemoryMap(DS_SIZE_WORKING_RAM);
if (ds->memory.ram) {
mappedMemoryFree(ds->memory.ram, DS_SIZE_RAM);
}
ds->memory.ram = anonymousMemoryMap(DS_SIZE_RAM);
memset(ds->memory.dma7, 0, sizeof(ds->memory.dma7));
memset(ds->memory.dma9, 0, sizeof(ds->memory.dma9));
ds->memory.activeDMA7 = -1;
ds->memory.activeDMA9 = -1;
ds->memory.nextDMA = INT_MAX;
ds->memory.eventDiff = 0;
if (!ds->memory.wram || !ds->memory.ram) {
DSMemoryDeinit(ds);
mLOG(DS_MEM, FATAL, "Could not map memory");
}
}
static void DS7SetActiveRegion(struct ARMCore* cpu, uint32_t address) {
struct DS* ds = (struct DS*) cpu->master;
struct DSMemory* memory = &ds->memory;
int newRegion = address >> DS_BASE_OFFSET;
memory->activeRegion7 = newRegion;
switch (newRegion) {
case DS7_REGION_BIOS:
cpu->memory.activeRegion = memory->bios7;
cpu->memory.activeMask = DS7_SIZE_BIOS - 1;
break;
default:
mLOG(DS_MEM, FATAL, "Jumped to invalid address: %08X", address);
return;
}
}
uint32_t DS7Load32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
struct DS* ds = (struct DS*) cpu->master;
struct DSMemory* memory = &ds->memory;
uint32_t value = 0;
int wait = 0;
switch (address >> DS_BASE_OFFSET) {
default:
break;
}
if (cycleCounter) {
wait += 2;
*cycleCounter += wait;
}
// Unaligned 32-bit loads are "rotated" so they make some semblance of sense
int rotate = (address & 3) << 3;
return ROR(value, rotate);
}
uint32_t DS7Load16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
struct DS* ds = (struct DS*) cpu->master;
struct DSMemory* memory = &ds->memory;
uint32_t value = 0;
int wait = 0;
switch (address >> DS_BASE_OFFSET) {
default:
break;
}
if (cycleCounter) {
wait += 2;
*cycleCounter += wait;
}
// Unaligned 16-bit loads are "unpredictable", TODO: See what DS does
int rotate = (address & 1) << 3;
return ROR(value, rotate);
}
uint32_t DS7Load8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
struct DS* ds = (struct DS*) cpu->master;
struct DSMemory* memory = &ds->memory;
uint32_t value = 0;
int wait = 0;
switch (address >> DS_BASE_OFFSET) {
default:
break;
}
if (cycleCounter) {
wait += 2;
*cycleCounter += wait;
}
return value;
}
void DS7Store32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter) {
struct DS* ds = (struct DS*) cpu->master;
struct DSMemory* memory = &ds->memory;
int wait = 0;
switch (address >> DS_BASE_OFFSET) {
break;
}
if (cycleCounter) {
++wait;
*cycleCounter += wait;
}
}
void DS7Store16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter) {
struct DS* ds = (struct DS*) cpu->master;
struct DSMemory* memory = &ds->memory;
int wait = 0;
switch (address >> DS_BASE_OFFSET) {
default:
break;
}
if (cycleCounter) {
++wait;
*cycleCounter += wait;
}
}
void DS7Store8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter) {
struct DS* ds = (struct DS*) cpu->master;
struct DSMemory* memory = &ds->memory;
int wait = 0;
switch (address >> DS_BASE_OFFSET) {
default:
break;
}
if (cycleCounter) {
++wait;
*cycleCounter += wait;
}
}
uint32_t DS7LoadMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
struct DS* ds = (struct DS*) cpu->master;
struct DSMemory* memory = &ds->memory;
uint32_t value;
int wait = 0;
int i;
int offset = 4;
int popcount = 0;
if (direction & LSM_D) {
offset = -4;
popcount = popcount32(mask);
address -= (popcount << 2) - 4;
}
if (direction & LSM_B) {
address += offset;
}
uint32_t addressMisalign = address & 0x3;
address &= 0xFFFFFFFC;
switch (address >> DS_BASE_OFFSET) {
default:
break;
}
if (cycleCounter) {
++wait;
*cycleCounter += wait;
}
if (direction & LSM_B) {
address -= offset;
}
if (direction & LSM_D) {
address -= (popcount << 2) + 4;
}
return address | addressMisalign;
}
uint32_t DS7StoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
struct DS* ds = (struct ds*) cpu->master;
struct DSMemory* memory = &ds->memory;
uint32_t value;
int wait = 0;
int i;
int offset = 4;
int popcount = 0;
if (direction & LSM_D) {
offset = -4;
popcount = popcount32(mask);
address -= (popcount << 2) - 4;
}
if (direction & LSM_B) {
address += offset;
}
uint32_t addressMisalign = address & 0x3;
address &= 0xFFFFFFFC;
switch (address >> DS_BASE_OFFSET) {
default:
break;
}
if (cycleCounter) {
*cycleCounter += wait;
}
if (direction & LSM_B) {
address -= offset;
}
if (direction & LSM_D) {
address -= (popcount << 2) + 4;
}
return address | addressMisalign;
}
static void DS9SetActiveRegion(struct ARMCore* cpu, uint32_t address) {
struct DS* ds = (struct DS*) cpu->master;
struct DSMemory* memory = &ds->memory;
int newRegion = address >> DS_BASE_OFFSET;
memory->activeRegion7 = newRegion;
switch (newRegion) {
case DS9_REGION_BIOS:
// TODO: Mask properly
if (memory->bios9) {
cpu->memory.activeRegion = memory->bios9;
cpu->memory.activeMask = DS9_SIZE_BIOS - 1;
} else {
cpu->memory.activeRegion = _deadbeef;
cpu->memory.activeMask = 0;
}
break;
default:
mLOG(DS_MEM, FATAL, "Jumped to invalid address: %08X", address);
return;
}
}
uint32_t DS9Load32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
struct DS* ds = (struct DS*) cpu->master;
struct DSMemory* memory = &ds->memory;
uint32_t value = 0;
int wait = 0;
switch (address >> DS_BASE_OFFSET) {
default:
break;
}
if (cycleCounter) {
wait += 2;
*cycleCounter += wait;
}
// Unaligned 32-bit loads are "rotated" so they make some semblance of sense
int rotate = (address & 3) << 3;
return ROR(value, rotate);
}
uint32_t DS9Load16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
struct DS* ds = (struct DS*) cpu->master;
struct DSMemory* memory = &ds->memory;
uint32_t value = 0;
int wait = 0;
switch (address >> DS_BASE_OFFSET) {
default:
break;
}
if (cycleCounter) {
wait += 2;
*cycleCounter += wait;
}
// Unaligned 16-bit loads are "unpredictable", TODO: See what DS does
int rotate = (address & 1) << 3;
return ROR(value, rotate);
}
uint32_t DS9Load8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
struct DS* ds = (struct DS*) cpu->master;
struct DSMemory* memory = &ds->memory;
uint32_t value = 0;
int wait = 0;
switch (address >> DS_BASE_OFFSET) {
default:
break;
}
if (cycleCounter) {
wait += 2;
*cycleCounter += wait;
}
return value;
}
void DS9Store32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter) {
struct DS* ds = (struct DS*) cpu->master;
struct DSMemory* memory = &ds->memory;
int wait = 0;
switch (address >> DS_BASE_OFFSET) {
break;
}
if (cycleCounter) {
++wait;
*cycleCounter += wait;
}
}
void DS9Store16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter) {
struct DS* ds = (struct DS*) cpu->master;
struct DSMemory* memory = &ds->memory;
int wait = 0;
switch (address >> DS_BASE_OFFSET) {
default:
break;
}
if (cycleCounter) {
++wait;
*cycleCounter += wait;
}
}
void DS9Store8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter) {
struct DS* ds = (struct DS*) cpu->master;
struct DSMemory* memory = &ds->memory;
int wait = 0;
switch (address >> DS_BASE_OFFSET) {
default:
break;
}
if (cycleCounter) {
++wait;
*cycleCounter += wait;
}
}
uint32_t DS9LoadMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
struct DS* ds = (struct DS*) cpu->master;
struct DSMemory* memory = &ds->memory;
uint32_t value;
int wait = 0;
int i;
int offset = 4;
int popcount = 0;
if (direction & LSM_D) {
offset = -4;
popcount = popcount32(mask);
address -= (popcount << 2) - 4;
}
if (direction & LSM_B) {
address += offset;
}
uint32_t addressMisalign = address & 0x3;
address &= 0xFFFFFFFC;
switch (address >> DS_BASE_OFFSET) {
default:
break;
}
if (cycleCounter) {
++wait;
*cycleCounter += wait;
}
if (direction & LSM_B) {
address -= offset;
}
if (direction & LSM_D) {
address -= (popcount << 2) + 4;
}
return address | addressMisalign;
}
uint32_t DS9StoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
struct DS* ds = (struct ds*) cpu->master;
struct DSMemory* memory = &ds->memory;
uint32_t value;
int wait = 0;
int i;
int offset = 4;
int popcount = 0;
if (direction & LSM_D) {
offset = -4;
popcount = popcount32(mask);
address -= (popcount << 2) - 4;
}
if (direction & LSM_B) {
address += offset;
}
uint32_t addressMisalign = address & 0x3;
address &= 0xFFFFFFFC;
switch (address >> DS_BASE_OFFSET) {
default:
break;
}
if (cycleCounter) {
*cycleCounter += wait;
}
if (direction & LSM_B) {
address -= offset;
}
if (direction & LSM_D) {
address -= (popcount << 2) + 4;
}
return address | addressMisalign;
}
int32_t DSMemoryStall(struct ARMCore* cpu, int32_t wait) {
return wait;
}

163
src/ds/memory.h Normal file
View File

@ -0,0 +1,163 @@
/* Copyright (c) 2013-2016 Jeffrey Pfau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef DS_MEMORY_H
#define DS_MEMORY_H
#include "util/common.h"
#include "arm/arm.h"
#include "core/log.h"
enum DSMemoryRegion {
DS7_REGION_BIOS = 0x0,
DS9_REGION_ITCM = 0x0,
DS_REGION_RAM = 0x2,
DS_REGION_WORKING_RAM = 0x3,
DS_REGION_IO = 0x4,
DS9_REGION_PALETTE_RAM = 0x5,
DS_REGION_VRAM = 0x6,
DS9_REGION_OAM = 0x7,
DS_REGION_SLOT2 = 0x8,
DS_REGION_SLOT2_EX = 0x9,
DS_REGION_SLOT2_SRAM = 0xA,
DS9_REGION_BIOS = 0xFF,
};
enum DSMemoryBase {
DS7_BASE_BIOS = 0x00000000,
DS9_BASE_ITCM = 0x00000000,
DS_BASE_RAM = 0x02000000,
DS_BASE_WORKING_RAM = 0x03000000,
DS_BASE_IO = 0x04000000,
DS9_BASE_PALETTE_RAM = 0x05000000,
DS_BASE_VRAM = 0x06000000,
DS9_BASE_OAM = 0x07000000,
DS_BASE_SLOT2 = 0x08000000,
DS_BASE_SLOT2_EX = 0x09000000,
DS9_BASE_BIOS = 0xFFFF0000,
};
enum {
DS7_SIZE_BIOS = 0x00004000,
DS9_SIZE_BIOS = 0x00008000,
DS_SIZE_RAM = 0x00400000,
DS_SIZE_WORKING_RAM = 0x00008000,
DS9_SIZE_PALETTE_RAM = 0x00000800,
DS9_SIZE_OAM = 0x00000800,
DS_SIZE_SLOT2 = 0x02000000,
DS_SIZE_SLOT2_SRAM = 0x00010000,
};
enum {
DS_OFFSET_MASK = 0x00FFFFFF,
DS_BASE_OFFSET = 24
};
enum DSDMAControl {
DS_DMA_INCREMENT = 0,
DS_DMA_DECREMENT = 1,
DS_DMA_FIXED = 2,
DS_DMA_INCREMENT_RELOAD = 3
};
enum DSDMATiming {
DS_DMA_TIMING_NOW = 0,
DS_DMA_TIMING_VBLANK = 1,
DS_DMA_TIMING_HBLANK = 2,
DS7_DMA_TIMING_SLOT1 = 2,
DS_DMA_TIMING_DISPLAY_START = 3,
DS7_DMA_TIMING_CUSTOM = 3,
DS_DMA_TIMING_MEMORY_DISPLAY = 4,
DS9_DMA_TIMING_SLOT1 = 5,
DS_DMA_TIMING_SLOT2 = 6,
DS_DMA_TIMING_GEOM_FIFO = 7,
};
mLOG_DECLARE_CATEGORY(DS_MEM);
DECL_BITFIELD(DSDMARegister, uint16_t);
DECL_BITS(DSDMARegister, DestControl, 5, 2);
DECL_BITS(DSDMARegister, SrcControl, 7, 2);
DECL_BIT(DSDMARegister, Repeat, 9);
DECL_BIT(DSDMARegister, Width, 10);
DECL_BITS(DSDMARegister, Timing7, 12, 2);
DECL_BITS(DSDMARegister, Timing9, 11, 3);
DECL_BIT(DSDMARegister, DoIRQ, 14);
DECL_BIT(DSDMARegister, Enable, 15);
struct DSDMA {
DSDMARegister reg;
uint32_t source;
uint32_t dest;
int32_t count;
uint32_t nextSource;
uint32_t nextDest;
int32_t nextCount;
int32_t nextEvent;
};
struct DSMemory {
uint32_t* bios7;
uint32_t* bios9;
uint32_t* ram;
uint32_t* wram;
uint32_t* rom;
size_t romSize;
char waitstatesSeq32[256];
char waitstatesSeq16[256];
char waitstatesNonseq32[256];
char waitstatesNonseq16[256];
char waitstatesPrefetchSeq32[16];
char waitstatesPrefetchSeq16[16];
char waitstatesPrefetchNonseq32[16];
char waitstatesPrefetchNonseq16[16];
int activeRegion7;
int activeRegion9;
struct DSDMA dma7[4];
struct DSDMA dma9[4];
int activeDMA7;
int activeDMA9;
int32_t nextDMA;
int32_t eventDiff;
};
struct DS;
void DSMemoryInit(struct DS* ds);
void DSMemoryDeinit(struct DS* ds);
void DSMemoryReset(struct DS* ds);
uint32_t DS7Load32(struct ARMCore* cpu, uint32_t address, int* cycleCounter);
uint32_t DS7Load16(struct ARMCore* cpu, uint32_t address, int* cycleCounter);
uint32_t DS7Load8(struct ARMCore* cpu, uint32_t address, int* cycleCounter);
void DS7Store32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter);
void DS7Store16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter);
void DS7Store8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter);
uint32_t DS7LoadMultiple(struct ARMCore*, uint32_t baseAddress, int mask, enum LSMDirection direction,
int* cycleCounter);
uint32_t DS7StoreMultiple(struct ARMCore*, uint32_t baseAddress, int mask, enum LSMDirection direction,
int* cycleCounter);
uint32_t DS9Load32(struct ARMCore* cpu, uint32_t address, int* cycleCounter);
uint32_t DS9Load16(struct ARMCore* cpu, uint32_t address, int* cycleCounter);
uint32_t DS9Load8(struct ARMCore* cpu, uint32_t address, int* cycleCounter);
void DS9Store32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter);
void DS9Store16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter);
void DS9Store8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter);
uint32_t DS9LoadMultiple(struct ARMCore*, uint32_t baseAddress, int mask, enum LSMDirection direction,
int* cycleCounter);
uint32_t DS9StoreMultiple(struct ARMCore*, uint32_t baseAddress, int mask, enum LSMDirection direction,
int* cycleCounter);
#endif