DS: Start DS core

This commit is contained in:
Jeffrey Pfau 2016-06-01 01:29:11 -07:00
parent 4ac4733cfd
commit e75cb6f7b4
10 changed files with 984 additions and 0 deletions

View File

@ -17,6 +17,7 @@ set(USE_LIBZIP ON CACHE BOOL "Whether or not to enable LIBZIP support")
set(USE_MAGICK ON CACHE BOOL "Whether or not to enable ImageMagick support")
set(M_CORE_GBA ON CACHE BOOL "Build Game Boy Advance core")
set(M_CORE_GB ON CACHE BOOL "Build Game Boy core")
set(M_CORE_DS ON CACHE BOOL "Build DS core")
set(USE_LZMA ON CACHE BOOL "Whether or not to enable 7-Zip support")
set(BUILD_QT ON CACHE BOOL "Build Qt frontend")
set(BUILD_SDL ON CACHE BOOL "Build SDL frontend")
@ -43,6 +44,7 @@ file(GLOB GBA_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gba/*.c)
file(GLOB GBA_TEST_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gba/test/*.c)
file(GLOB GB_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gb/*.c)
file(GLOB GB_TEST_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gb/test/*.c)
file(GLOB DS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/ds/*.c)
file(GLOB GBA_CHEATS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gba/cheats/*.c)
file(GLOB GBA_RR_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gba/rr/*.c)
file(GLOB CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/core/*.c)
@ -62,6 +64,7 @@ source_group("LR35902 core" FILES ${LR35902_SRC})
source_group("GBA board" FILES ${GBA_SRC} ${GBA_RENDERER_SRC} ${SIO_SRC})
source_group("GBA extra" FILES ${GBA_CHEATS_SRC} ${GBA_RR_SRC})
source_group("GB board" FILES ${GB_SRC})
source_group("DS board" FILES ${DS_SRC})
source_group("Utilities" FILES ${UTIL_SRC})
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/src)
@ -373,6 +376,19 @@ endif()
if(USE_EDITLINE)
list(APPEND FEATURES EDITLINE)
list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/debugger/cli-debugger.c)
list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/debugger/parser.c)
if(M_CORE_GBA)
list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/arm/debugger/cli-debugger.c)
list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gba/extra/cli.c)
endif()
if(M_CORE_GB)
list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/lr35902/debugger/cli-debugger.c)
endif()
if(M_CORE_DS)
list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/arm/debugger/cli-debugger.c)
list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/ds/extra/cli.c)
endif()
include_directories(AFTER ${LIBEDIT_INCLUDE_DIRS})
link_directories(${LIBEDIT_LIBRARY_DIRS})
set(DEBUGGER_LIB ${LIBEDIT_LIBRARIES})
@ -585,6 +601,15 @@ foreach(FEATURE IN LISTS FEATURES)
list(APPEND FEATURE_DEFINES "USE_${FEATURE}")
endforeach()
if(M_CORE_DS)
add_definitions(-DM_CORE_DS)
list(APPEND CORE_SRC
${ARM_SRC}
${CMAKE_CURRENT_SOURCE_DIR}/src/arm/debugger/debugger.c
${CMAKE_CURRENT_SOURCE_DIR}/src/arm/debugger/memory-debugger.c
${DS_SRC})
endif()
source_group("Virtual files" FILES ${CORE_VFS_SRC} ${VFS_SRC})
source_group("Extra features" FILES ${FEATURE_SRC})
source_group("Third-party code" FILES ${THIRD_PARTY_SRC})

View File

@ -17,6 +17,10 @@
#include "gba/core.h"
#include "gba/gba.h"
#endif
#ifdef M_CORE_DS
#include "ds/core.h"
#include "ds/ds.h"
#endif
static struct mCoreFilter {
bool (*filter)(struct VFile*);
@ -28,6 +32,9 @@ static struct mCoreFilter {
#endif
#ifdef M_CORE_GB
{ GBIsROM, GBCoreCreate, PLATFORM_GB },
#endif
#ifdef M_CORE_DS
{ DSIsROM, DSCoreCreate, PLATFORM_DS },
#endif
{ 0, 0, PLATFORM_NONE }
};

View File

@ -28,6 +28,9 @@ enum mPlatform {
#ifdef M_CORE_GB
PLATFORM_GB,
#endif
#ifdef M_CORE_DS
PLATFORM_DS,
#endif
};
struct mRTCSource;

403
src/ds/core.c Normal file
View File

@ -0,0 +1,403 @@
/* 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 "core.h"
#include "core/cheats.h"
#include "core/core.h"
#include "core/log.h"
#include "arm/debugger/debugger.h"
#include "ds/ds.h"
#include "ds/extra/cli.h"
#include "util/memory.h"
#include "util/patch.h"
#include "util/vfs.h"
struct DSCore {
struct mCore d;
struct ARMCore* arm7;
int keys;
struct mCPUComponent* components[CPU_COMPONENT_MAX];
struct mDebuggerPlatform* debuggerPlatform;
struct mCheatDevice* cheatDevice;
};
static bool _DSCoreInit(struct mCore* core) {
struct DSCore* dscore = (struct DSCore*) core;
struct ARMCore* arm7 = anonymousMemoryMap(sizeof(struct ARMCore));
struct ARMCore* arm9 = anonymousMemoryMap(sizeof(struct ARMCore));
struct DS* ds = anonymousMemoryMap(sizeof(struct DS));
if (!arm7 || !arm9 || !ds) {
free(arm7);
free(arm9);
free(ds);
return false;
}
core->cpu = arm9;
core->board = ds;
core->debugger = NULL;
dscore->arm7 = arm7;
dscore->debuggerPlatform = NULL;
dscore->cheatDevice = NULL;
DSCreate(ds);
memset(dscore->components, 0, sizeof(dscore->components));
ARMSetComponents(arm7, &ds->d, CPU_COMPONENT_MAX, dscore->components);
ARMSetComponents(arm9, &ds->d, CPU_COMPONENT_MAX, dscore->components);
ARMInit(arm7);
ARMInit(arm9);
dscore->keys = 0;
ds->keySource = &dscore->keys;
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
mDirectorySetInit(&core->dirs);
#endif
return true;
}
static void _DSCoreDeinit(struct mCore* core) {
struct DSCore* dscore = (struct DSCore*) core;
ARMDeinit(core->cpu);
ARMDeinit(dscore->arm7);
DSDestroy(core->board);
mappedMemoryFree(core->cpu, sizeof(struct ARMCore));
mappedMemoryFree(dscore->arm7, sizeof(struct ARMCore));
mappedMemoryFree(core->board, sizeof(struct DS));
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
mDirectorySetDeinit(&core->dirs);
#endif
free(dscore->debuggerPlatform);
if (dscore->cheatDevice) {
mCheatDeviceDestroy(dscore->cheatDevice);
}
free(dscore->cheatDevice);
free(core);
}
static enum mPlatform _DSCorePlatform(struct mCore* core) {
UNUSED(core);
return PLATFORM_DS;
}
static void _DSCoreSetSync(struct mCore* core, struct mCoreSync* sync) {
struct DS* ds = core->board;
ds->sync = sync;
}
static void _DSCoreLoadConfig(struct mCore* core, const struct mCoreConfig* config) {
}
static void _DSCoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) {
UNUSED(core);
*width = DS_VIDEO_HORIZONTAL_PIXELS;
*height = DS_VIDEO_VERTICAL_PIXELS;
}
static void _DSCoreSetVideoBuffer(struct mCore* core, color_t* buffer, size_t stride) {
}
static void _DSCoreGetVideoBuffer(struct mCore* core, color_t** buffer, size_t* stride) {
}
static struct blip_t* _DSCoreGetAudioChannel(struct mCore* core, int ch) {
return NULL;
}
static void _DSCoreSetAudioBufferSize(struct mCore* core, size_t samples) {
}
static size_t _DSCoreGetAudioBufferSize(struct mCore* core) {
return 2048;
}
static void _DSCoreSetAVStream(struct mCore* core, struct mAVStream* stream) {
}
static bool _DSCoreLoadROM(struct mCore* core, struct VFile* vf) {
return DSLoadROM(core->board, vf);
}
static bool _DSCoreLoadBIOS(struct mCore* core, struct VFile* vf, int type) {
return false;
}
static bool _DSCoreLoadSave(struct mCore* core, struct VFile* vf) {
return false;
}
static bool _DSCoreLoadPatch(struct mCore* core, struct VFile* vf) {
return false;
}
static void _DSCoreUnloadROM(struct mCore* core) {
return DSUnloadROM(core->board);
}
static void _DSCoreReset(struct mCore* core) {
struct DSCore* dscore = (struct DSCore*) core;
struct DS* ds = (struct DS*) core->board;
ARMReset(ds->arm7);
ARMReset(ds->arm9);
}
static void _DSCoreRunFrame(struct mCore* core) {
struct DS* ds = core->board;
int32_t frameCounter = ds->video.frameCounter;
while (ds->video.frameCounter == frameCounter) {
ARMRunLoop(core->cpu);
}
}
static void _DSCoreRunLoop(struct mCore* core) {
ARMRunLoop(core->cpu);
}
static void _DSCoreStep(struct mCore* core) {
ARMRun(core->cpu);
}
static size_t _DSCoreStateSize(struct mCore* core) {
UNUSED(core);
return 0;
}
static bool _DSCoreLoadState(struct mCore* core, const void* state) {
return false;
}
static bool _DSCoreSaveState(struct mCore* core, void* state) {
return false;
}
static void _DSCoreSetKeys(struct mCore* core, uint32_t keys) {
struct DSCore* dscore = (struct DSCore*) core;
dscore->keys = keys;
}
static void _DSCoreAddKeys(struct mCore* core, uint32_t keys) {
struct DSCore* dscore = (struct DSCore*) core;
dscore->keys |= keys;
}
static void _DSCoreClearKeys(struct mCore* core, uint32_t keys) {
struct DSCore* dscore = (struct DSCore*) core;
dscore->keys &= ~keys;
}
static int32_t _DSCoreFrameCounter(struct mCore* core) {
struct DS* ds = core->board;
return ds->video.frameCounter;
}
static int32_t _DSCoreFrameCycles(struct mCore* core) {
UNUSED(core);
return DS_VIDEO_TOTAL_LENGTH;
}
static int32_t _DSCoreFrequency(struct mCore* core) {
UNUSED(core);
return DS_ARM946ES_FREQUENCY;
}
static void _DSCoreGetGameTitle(struct mCore* core, char* title) {
DSGetGameTitle(core->board, title);
}
static void _DSCoreGetGameCode(struct mCore* core, char* title) {
DSGetGameCode(core->board, title);
}
static void _DSCoreSetRTC(struct mCore* core, struct mRTCSource* rtc) {
struct DS* ds = core->board;
ds->rtcSource = rtc;
}
static void _DSCoreSetRotation(struct mCore* core, struct mRotationSource* rotation) {
}
static void _DSCoreSetRumble(struct mCore* core, struct mRumble* rumble) {
struct DS* ds = core->board;
ds->rumble = rumble;
}
static uint32_t _DSCoreBusRead8(struct mCore* core, uint32_t address) {
struct ARMCore* cpu = core->cpu;
return cpu->memory.load8(cpu, address, 0);
}
static uint32_t _DSCoreBusRead16(struct mCore* core, uint32_t address) {
struct ARMCore* cpu = core->cpu;
return cpu->memory.load16(cpu, address, 0);
}
static uint32_t _DSCoreBusRead32(struct mCore* core, uint32_t address) {
struct ARMCore* cpu = core->cpu;
return cpu->memory.load32(cpu, address, 0);
}
static void _DSCoreBusWrite8(struct mCore* core, uint32_t address, uint8_t value) {
struct ARMCore* cpu = core->cpu;
cpu->memory.store8(cpu, address, value, 0);
}
static void _DSCoreBusWrite16(struct mCore* core, uint32_t address, uint16_t value) {
struct ARMCore* cpu = core->cpu;
cpu->memory.store16(cpu, address, value, 0);
}
static void _DSCoreBusWrite32(struct mCore* core, uint32_t address, uint32_t value) {
struct ARMCore* cpu = core->cpu;
cpu->memory.store32(cpu, address, value, 0);
}
static uint32_t _DSCoreRawRead8(struct mCore* core, uint32_t address) {
return 0;
}
static uint32_t _DSCoreRawRead16(struct mCore* core, uint32_t address) {
return 0;
}
static uint32_t _DSCoreRawRead32(struct mCore* core, uint32_t address) {
return 0;
}
static void _DSCoreRawWrite8(struct mCore* core, uint32_t address, uint8_t value) {
}
static void _DSCoreRawWrite16(struct mCore* core, uint32_t address, uint16_t value) {
}
static void _DSCoreRawWrite32(struct mCore* core, uint32_t address, uint32_t value) {
}
static bool _DSCoreSupportsDebuggerType(struct mCore* core, enum mDebuggerType type) {
UNUSED(core);
switch (type) {
#ifdef USE_CLI_DEBUGGER
case DEBUGGER_CLI:
return true;
#endif
#ifdef USE_GDB_STUB
case DEBUGGER_GDB:
return true;
#endif
default:
return false;
}
}
static struct mDebuggerPlatform* _DSCoreDebuggerPlatform(struct mCore* core) {
struct DSCore* dscore = (struct DSCore*) core;
if (!dscore->debuggerPlatform) {
dscore->debuggerPlatform = ARMDebuggerPlatformCreate();
}
return dscore->debuggerPlatform;
}
static struct CLIDebuggerSystem* _DSCoreCliDebuggerSystem(struct mCore* core) {
#ifdef USE_CLI_DEBUGGER
return &DSCLIDebuggerCreate(core)->d;
#else
UNUSED(core);
return NULL;
#endif
}
static void _DSCoreAttachDebugger(struct mCore* core, struct mDebugger* debugger) {
if (core->debugger) {
DSDetachDebugger(core->board);
}
DSAttachDebugger(core->board, debugger);
core->debugger = debugger;
}
static void _DSCoreDetachDebugger(struct mCore* core) {
DSDetachDebugger(core->board);
core->debugger = NULL;
}
static struct mCheatDevice* _DSCoreCheatDevice(struct mCore* core) {
return NULL;
}
static size_t _DSCoreSavedataClone(struct mCore* core, void** sram) {
return 0;
}
static bool _DSCoreSavedataLoad(struct mCore* core, const void* sram, size_t size) {
return false;
}
struct mCore* DSCoreCreate(void) {
struct DSCore* dscore = malloc(sizeof(*dscore));
struct mCore* core = &dscore->d;
memset(&core->opts, 0, sizeof(core->opts));
core->cpu = NULL;
core->board = NULL;
core->debugger = NULL;
core->init = _DSCoreInit;
core->deinit = _DSCoreDeinit;
core->platform = _DSCorePlatform;
core->setSync = _DSCoreSetSync;
core->loadConfig = _DSCoreLoadConfig;
core->desiredVideoDimensions = _DSCoreDesiredVideoDimensions;
core->setVideoBuffer = _DSCoreSetVideoBuffer;
core->getVideoBuffer = _DSCoreGetVideoBuffer;
core->getAudioChannel = _DSCoreGetAudioChannel;
core->setAudioBufferSize = _DSCoreSetAudioBufferSize;
core->getAudioBufferSize = _DSCoreGetAudioBufferSize;
core->setAVStream = _DSCoreSetAVStream;
core->isROM = DSIsROM;
core->loadROM = _DSCoreLoadROM;
core->loadBIOS = _DSCoreLoadBIOS;
core->loadSave = _DSCoreLoadSave;
core->loadPatch = _DSCoreLoadPatch;
core->unloadROM = _DSCoreUnloadROM;
core->reset = _DSCoreReset;
core->runFrame = _DSCoreRunFrame;
core->runLoop = _DSCoreRunLoop;
core->step = _DSCoreStep;
core->stateSize = _DSCoreStateSize;
core->loadState = _DSCoreLoadState;
core->saveState = _DSCoreSaveState;
core->setKeys = _DSCoreSetKeys;
core->addKeys = _DSCoreAddKeys;
core->clearKeys = _DSCoreClearKeys;
core->frameCounter = _DSCoreFrameCounter;
core->frameCycles = _DSCoreFrameCycles;
core->frequency = _DSCoreFrequency;
core->getGameTitle = _DSCoreGetGameTitle;
core->getGameCode = _DSCoreGetGameCode;
core->setRTC = _DSCoreSetRTC;
core->setRotation = _DSCoreSetRotation;
core->setRumble = _DSCoreSetRumble;
core->busRead8 = _DSCoreBusRead8;
core->busRead16 = _DSCoreBusRead16;
core->busRead32 = _DSCoreBusRead32;
core->busWrite8 = _DSCoreBusWrite8;
core->busWrite16 = _DSCoreBusWrite16;
core->busWrite32 = _DSCoreBusWrite32;
core->rawRead8 = _DSCoreRawRead8;
core->rawRead16 = _DSCoreRawRead16;
core->rawRead32 = _DSCoreRawRead32;
core->rawWrite8 = _DSCoreRawWrite8;
core->rawWrite16 = _DSCoreRawWrite16;
core->rawWrite32 = _DSCoreRawWrite32;
core->supportsDebuggerType = _DSCoreSupportsDebuggerType;
core->debuggerPlatform = _DSCoreDebuggerPlatform;
core->cliDebuggerSystem = _DSCoreCliDebuggerSystem;
core->attachDebugger = _DSCoreAttachDebugger;
core->detachDebugger = _DSCoreDetachDebugger;
core->cheatDevice = _DSCoreCheatDevice;
core->savedataClone = _DSCoreSavedataClone;
core->savedataLoad = _DSCoreSavedataLoad;
return core;
}

12
src/ds/core.h Normal file
View File

@ -0,0 +1,12 @@
/* 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_CORE_H
#define DS_CORE_H
struct mCore;
struct mCore* DSCoreCreate(void);
#endif

267
src/ds/ds.c Normal file
View File

@ -0,0 +1,267 @@
/* 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 "ds.h"
#include "arm/decoder.h"
#include "arm/debugger/debugger.h"
#include "arm/isa-inlines.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");
const uint32_t DS_ARM946ES_FREQUENCY = 0x1FF61FE;
const uint32_t DS_ARM7TDMI_FREQUENCY = 0xFFB0FF;
const uint32_t DS_COMPONENT_MAGIC = 0x1FF61FE;
static const size_t DS_ROM_MAGIC_OFFSET = 0x15C;
static const uint8_t DS_ROM_MAGIC[] = { 0x56, 0xCF };
enum {
DS7_SP_BASE = 0x380FD80,
DS7_SP_BASE_IRQ = 0x380FF80,
DS7_SP_BASE_SVC = 0x380FFC0,
DS9_SP_BASE = 0x3002F7C,
DS9_SP_BASE_IRQ = 0x3003F80,
DS9_SP_BASE_SVC = 0x3003FC0,
};
static void DSInit(void* cpu, struct mCPUComponent* component);
static void DS7Reset(struct ARMCore* cpu);
static void DS7InterruptHandlerInit(struct ARMInterruptHandler* irqh);
static void DS9Reset(struct ARMCore* cpu);
static void DS9InterruptHandlerInit(struct ARMInterruptHandler* irqh);
static void DSProcessEvents(struct ARMCore* cpu);
static void DSHitStub(struct ARMCore* cpu, uint32_t opcode);
static void DSIllegal(struct ARMCore* cpu, uint32_t opcode);
static void DSBreakpoint(struct ARMCore* cpu, int immediate);
void DSCreate(struct DS* ds) {
ds->d.id = DS_COMPONENT_MAGIC;
ds->d.init = DSInit;
ds->d.deinit = NULL;
ds->arm7 = NULL;
ds->arm9 = NULL;
}
static void DSInit(void* cpu, struct mCPUComponent* component) {
struct DS* ds = (struct DS*) component;
struct ARMCore* core = cpu;
if (!ds->arm7) {
// The ARM7 must get initialized first
ds->arm7 = core;
ds->debugger = 0;
ds->sync = 0;
return;
}
ds->arm9 = cpu;
DS7InterruptHandlerInit(&ds->arm7->irqh);
DS9InterruptHandlerInit(&ds->arm9->irqh);
ds->video.p = ds;
ds->springIRQ7 = 0;
ds->springIRQ9 = 0;
ds->keySource = NULL;
ds->rtcSource = NULL;
ds->rumble = NULL;
ds->romVf = NULL;
ds->keyCallback = NULL;
}
void DSUnloadROM(struct DS* ds) {
if (ds->romVf) {
ds->romVf->close(ds->romVf);
ds->romVf = NULL;
}
}
void DSDestroy(struct DS* ds) {
DSUnloadROM(ds);
}
void DS7InterruptHandlerInit(struct ARMInterruptHandler* irqh) {
irqh->reset = DS7Reset;
irqh->processEvents = DSProcessEvents;
irqh->swi16 = NULL;
irqh->swi32 = NULL;
irqh->hitIllegal = DSIllegal;
irqh->readCPSR = NULL;
irqh->hitStub = DSHitStub;
irqh->bkpt16 = DSBreakpoint;
irqh->bkpt32 = DSBreakpoint;
}
void DS9InterruptHandlerInit(struct ARMInterruptHandler* irqh) {
irqh->reset = DS9Reset;
irqh->processEvents = DSProcessEvents;
irqh->swi16 = NULL;
irqh->swi32 = NULL;
irqh->hitIllegal = DSIllegal;
irqh->readCPSR = NULL;
irqh->hitStub = DSHitStub;
irqh->bkpt16 = DSBreakpoint;
irqh->bkpt32 = DSBreakpoint;
}
void DS7Reset(struct ARMCore* cpu) {
ARMSetPrivilegeMode(cpu, MODE_IRQ);
cpu->gprs[ARM_SP] = DS7_SP_BASE_IRQ;
ARMSetPrivilegeMode(cpu, MODE_SUPERVISOR);
cpu->gprs[ARM_SP] = DS7_SP_BASE_SVC;
ARMSetPrivilegeMode(cpu, MODE_SYSTEM);
cpu->gprs[ARM_SP] = DS7_SP_BASE;
}
void DS9Reset(struct ARMCore* cpu) {
ARMSetPrivilegeMode(cpu, MODE_IRQ);
cpu->gprs[ARM_SP] = DS9_SP_BASE_IRQ;
ARMSetPrivilegeMode(cpu, MODE_SUPERVISOR);
cpu->gprs[ARM_SP] = DS9_SP_BASE_SVC;
ARMSetPrivilegeMode(cpu, MODE_SYSTEM);
cpu->gprs[ARM_SP] = DS9_SP_BASE;
}
static void DSProcessEvents(struct ARMCore* cpu) {
struct DS* ds = (struct DS*) cpu->master;
if (ds->springIRQ7) {
ARMRaiseIRQ(cpu);
ds->springIRQ7 = 0;
}
do {
int32_t cycles = cpu->nextEvent;
int32_t nextEvent = INT_MAX;
#ifndef NDEBUG
if (cycles < 0) {
mLOG(DS, FATAL, "Negative cycles passed: %i", cycles);
}
#endif
cpu->cycles -= cycles;
cpu->nextEvent = nextEvent;
if (cpu->halted) {
cpu->cycles = cpu->nextEvent;
}
} while (cpu->cycles >= cpu->nextEvent);
}
void DSAttachDebugger(struct DS* ds, struct mDebugger* debugger) {
ds->debugger = (struct ARMDebugger*) debugger->platform;
ds->arm7->components[CPU_COMPONENT_DEBUGGER] = &debugger->d;
ds->arm9->components[CPU_COMPONENT_DEBUGGER] = &debugger->d;
ARMHotplugAttach(ds->arm7, CPU_COMPONENT_DEBUGGER);
ARMHotplugAttach(ds->arm9, CPU_COMPONENT_DEBUGGER);
}
void DSDetachDebugger(struct DS* ds) {
ds->debugger = NULL;
ARMHotplugDetach(ds->arm7, CPU_COMPONENT_DEBUGGER);
ARMHotplugDetach(ds->arm9, CPU_COMPONENT_DEBUGGER);
ds->arm7->components[CPU_COMPONENT_DEBUGGER] = NULL;
ds->arm9->components[CPU_COMPONENT_DEBUGGER] = NULL;
}
bool DSLoadROM(struct DS* ds, struct VFile* vf) {
DSUnloadROM(ds);
ds->romVf = vf;
// TODO: Checksum?
// TODO: error check
return true;
}
bool DSIsROM(struct VFile* vf) {
if (vf->seek(vf, DS_ROM_MAGIC_OFFSET, SEEK_SET) < 0) {
return false;
}
uint8_t signature[sizeof(DS_ROM_MAGIC)];
if (vf->read(vf, &signature, sizeof(signature)) != sizeof(signature)) {
return false;
}
return memcmp(signature, DS_ROM_MAGIC, sizeof(signature)) == 0;
}
void DSGetGameCode(struct DS* ds, char* out) {
memset(out, 0, 8);
if (!ds->romVf) {
return;
}
struct DSCartridge* cart = ds->romVf->map(ds->romVf, sizeof(*cart), MAP_READ);
memcpy(out, "NTR-", 4);
memcpy(&out[4], &cart->id, 4);
ds->romVf->unmap(ds->romVf, cart, sizeof(*cart));
}
void DSGetGameTitle(struct DS* ds, char* out) {
memset(out, 0, 12);
if (!ds->romVf) {
return;
}
struct DSCartridge* cart = ds->romVf->map(ds->romVf, sizeof(*cart), MAP_READ);
memcpy(out, &cart->title, 4);
ds->romVf->unmap(ds->romVf, cart, sizeof(*cart));
}
void DSHitStub(struct ARMCore* cpu, uint32_t opcode) {
struct DS* ds = (struct DS*) cpu->master;
if (ds->debugger) {
struct mDebuggerEntryInfo info = {
.address = _ARMPCAddress(cpu),
.opcode = opcode
};
mDebuggerEnter(ds->debugger->d.p, DEBUGGER_ENTER_ILLEGAL_OP, &info);
}
// TODO: More sensible category?
mLOG(DS, ERROR, "Stub opcode: %08x", opcode);
}
void DSIllegal(struct ARMCore* cpu, uint32_t opcode) {
struct DS* ds = (struct DS*) cpu->master;
if (ds->debugger) {
struct mDebuggerEntryInfo info = {
.address = _ARMPCAddress(cpu),
.opcode = opcode
};
mDebuggerEnter(ds->debugger->d.p, DEBUGGER_ENTER_ILLEGAL_OP, &info);
} else {
ARMRaiseUndefined(cpu);
}
}
void DSBreakpoint(struct ARMCore* cpu, int immediate) {
struct DS* ds = (struct DS*) cpu->master;
if (immediate >= CPU_COMPONENT_MAX) {
return;
}
switch (immediate) {
case CPU_COMPONENT_DEBUGGER:
if (ds->debugger) {
struct mDebuggerEntryInfo info = {
.address = _ARMPCAddress(cpu)
};
mDebuggerEnter(ds->debugger->d.p, DEBUGGER_ENTER_BREAKPOINT, &info);
}
break;
default:
break;
}
}

128
src/ds/ds.h Normal file
View File

@ -0,0 +1,128 @@
/* 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_H
#define DS_H
#include "util/common.h"
#include "arm/arm.h"
#include "core/log.h"
#include "ds/video.h"
extern const uint32_t DS_ARM946ES_FREQUENCY;
extern const uint32_t DS_ARM7TDMI_FREQUENCY;
enum DSIRQ {
DS_IRQ_VBLANK = 0x0,
DS_IRQ_HBLANK = 0x1,
DS_IRQ_VCOUNTER = 0x2,
DS_IRQ_TIMER0 = 0x3,
DS_IRQ_TIMER1 = 0x4,
DS_IRQ_TIMER2 = 0x5,
DS_IRQ_TIMER3 = 0x6,
DS_IRQ_SIO = 0x7,
DS_IRQ_DMA0 = 0x8,
DS_IRQ_DMA1 = 0x9,
DS_IRQ_DMA2 = 0xA,
DS_IRQ_DMA3 = 0xB,
DS_IRQ_KEYPAD = 0xC,
DS_IRQ_SLOT2 = 0xD,
DS_IRQ_IPC_SYNC = 0x10,
DS_IRQ_IPC_EMPTY = 0x11,
DS_IRQ_IPC_NOT_EMPTY = 0x12,
DS_IRQ_SLOT1_TRANS = 0x13,
DS_IRQ_SLOT1 = 0x14,
DS_IRQ_GEOM_FIFO = 0x15,
DS_IRQ_LID = 0x16,
DS_IRQ_SPI = 0x17,
DS_IRQ_WIFI = 0x18,
};
struct DS;
struct Patch;
struct VFile;
struct mDebugger;
mLOG_DECLARE_CATEGORY(DS);
struct DS {
struct mCPUComponent d;
struct ARMCore* arm7;
struct ARMCore* arm9;
struct DSVideo video;
struct mCoreSync* sync;
struct ARMDebugger* debugger;
int springIRQ7;
int springIRQ9;
uint32_t biosChecksum;
int* keySource;
struct mRTCSource* rtcSource;
struct mRumble* rumble;
uint32_t romCrc32;
struct VFile* romVf;
struct mKeyCallback* keyCallback;
};
struct DSCartridge {
char title[12];
uint32_t id;
uint16_t maker;
uint8_t type;
uint8_t encryptionSeed;
uint8_t size;
uint8_t reserved[8];
uint8_t region;
uint8_t version;
uint8_t autostart;
uint32_t arm9Offset;
uint32_t arm9Entry;
uint32_t arm9Base;
uint32_t arm9Size;
uint32_t arm7Offset;
uint32_t arm7Entry;
uint32_t arm7Base;
uint32_t arm7Size;
uint32_t fntOffset;
uint32_t fntSize;
uint32_t fatOffset;
uint32_t fatSize;
uint32_t arm9FileOverlayOffset;
uint32_t arm9FileOverlaySize;
uint32_t arm7FileOverlayOffset;
uint32_t arm7FileOverlaySize;
uint32_t busTiming;
uint32_t busKEY1Timing;
uint32_t iconOffset;
uint16_t secureAreaCrc16;
uint16_t secureAreaDelay;
// TODO: Fill in more
// And ROM data...
};
void DSCreate(struct DS* ds);
void DSDestroy(struct DS* ds);
void DSAttachDebugger(struct DS* ds, struct mDebugger* debugger);
void DSDetachDebugger(struct DS* ds);
bool DSLoadROM(struct DS* ds, struct VFile* vf);
void DSUnloadROM(struct DS* ds);
void DSApplyPatch(struct DS* ds, struct Patch* patch);
bool DSIsROM(struct VFile* vf);
void DSGetGameCode(struct DS* ds, char* out);
void DSGetGameTitle(struct DS* ds, char* out);
#endif

62
src/ds/extra/cli.c Normal file
View File

@ -0,0 +1,62 @@
/* Copyright (c) 2013-2015 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 "cli.h"
#include "arm/debugger/cli-debugger.h"
#ifdef USE_CLI_DEBUGGER
static void _DSCLIDebuggerInit(struct CLIDebuggerSystem*);
static bool _DSCLIDebuggerCustom(struct CLIDebuggerSystem*);
static uint32_t _DSCLIDebuggerLookupIdentifier(struct CLIDebuggerSystem*, const char* name, struct CLIDebugVector* dv);
static void _frame(struct CLIDebugger*, struct CLIDebugVector*);
struct CLIDebuggerCommandSummary _DSCLIDebuggerCommands[] = {
{ "frame", _frame, 0, "Frame advance" },
{ 0, 0, 0, 0 }
};
struct DSCLIDebugger* DSCLIDebuggerCreate(struct mCore* core) {
struct DSCLIDebugger* debugger = malloc(sizeof(struct DSCLIDebugger));
ARMCLIDebuggerCreate(&debugger->d);
debugger->d.init = _DSCLIDebuggerInit;
debugger->d.deinit = NULL;
debugger->d.custom = _DSCLIDebuggerCustom;
debugger->d.lookupIdentifier = _DSCLIDebuggerLookupIdentifier;
debugger->d.name = "DS";
debugger->d.commands = _DSCLIDebuggerCommands;
debugger->core = core;
return debugger;
}
static void _DSCLIDebuggerInit(struct CLIDebuggerSystem* debugger) {
struct DSCLIDebugger* dsDebugger = (struct DSCLIDebugger*) debugger;
dsDebugger->frameAdvance = false;
}
static bool _DSCLIDebuggerCustom(struct CLIDebuggerSystem* debugger) {
return false;
}
static uint32_t _DSCLIDebuggerLookupIdentifier(struct CLIDebuggerSystem* debugger, const char* name, struct CLIDebugVector* dv) {
UNUSED(debugger);
dv->type = CLIDV_ERROR_TYPE;
return 0;
}
static void _frame(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
UNUSED(dv);
debugger->d.state = DEBUGGER_CUSTOM;
struct DSCLIDebugger* dsDebugger = (struct DSCLIDebugger*) debugger->system;
dsDebugger->frameAdvance = true;
}
#endif

26
src/ds/extra/cli.h Normal file
View File

@ -0,0 +1,26 @@
/* 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_CLI_H
#define DS_CLI_H
#ifdef USE_CLI_DEBUGGER
#include "debugger/cli-debugger.h"
struct mCore;
struct DSCLIDebugger {
struct CLIDebuggerSystem d;
struct mCore* core;
bool frameAdvance;
bool inVblank;
};
struct DSCLIDebugger* DSCLIDebuggerCreate(struct mCore*);
#endif
#endif

51
src/ds/video.h Normal file
View File

@ -0,0 +1,51 @@
/* 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_VIDEO_H
#define DS_VIDEO_H
#include "util/common.h"
#include "core/log.h"
mLOG_DECLARE_CATEGORY(DS_VIDEO);
enum {
DS_VIDEO_HORIZONTAL_PIXELS = 256,
DS_VIDEO_HBLANK_PIXELS = 99,
DS_VIDEO_HORIZONTAL_LENGTH = (DS_VIDEO_HORIZONTAL_PIXELS + DS_VIDEO_HBLANK_PIXELS) * 6,
DS_VIDEO_VERTICAL_PIXELS = 192,
DS_VIDEO_VBLANK_PIXELS = 71,
DS_VIDEO_VERTICAL_TOTAL_PIXELS = DS_VIDEO_VERTICAL_PIXELS + DS_VIDEO_VBLANK_PIXELS,
DS_VIDEO_TOTAL_LENGTH = DS_VIDEO_HORIZONTAL_LENGTH * DS_VIDEO_VERTICAL_TOTAL_PIXELS,
};
struct DS;
struct DSVideo {
struct DS* p;
// VCOUNT
int vcount;
int32_t nextHblank;
int32_t nextEvent;
int32_t eventDiff;
int32_t nextHblankIRQ;
int32_t nextVblankIRQ;
int32_t nextVcounterIRQ;
int32_t frameCounter;
int frameskip;
int frameskipCounter;
};
void DSVideoInit(struct DSVideo* video);
void DSVideoReset(struct DSVideo* video);
void DSVideoDeinit(struct DSVideo* video);
#endif