diff --git a/include/mgba/internal/ds/ds.h b/include/mgba/internal/ds/ds.h index 534d4be45..6eba5ae9f 100644 --- a/include/mgba/internal/ds/ds.h +++ b/include/mgba/internal/ds/ds.h @@ -14,6 +14,7 @@ CXX_GUARD_START #include #include +#include #include #include #include @@ -78,6 +79,7 @@ struct DS { struct DSCommon ds9; struct DSMemory memory; struct DSVideo video; + struct DSGX gx; struct mCoreSync* sync; struct mTimingEvent slice; diff --git a/include/mgba/internal/ds/gx.h b/include/mgba/internal/ds/gx.h new file mode 100644 index 000000000..ce974cd71 --- /dev/null +++ b/include/mgba/internal/ds/gx.h @@ -0,0 +1,87 @@ +/* Copyright (c) 2013-2017 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_GX_H +#define DS_GX_H + +#include + +CXX_GUARD_START + +#include +#include +#include + +mLOG_DECLARE_CATEGORY(DS_GX); + +enum DSGXCommand { + DS_GX_CMD_NOP = 0, + DS_GX_CMD_MTX_MODE = 0x10, + DS_GX_CMD_MTX_PUSH = 0x11, + DS_GX_CMD_MTX_POP = 0x12, + DS_GX_CMD_MTX_STORE = 0x13, + DS_GX_CMD_MTX_RESTORE = 0x14, + DS_GX_CMD_MTX_IDENTITY = 0x15, + DS_GX_CMD_MTX_LOAD_4x4 = 0x16, + DS_GX_CMD_MTX_LOAD_4x3 = 0x17, + DS_GX_CMD_MTX_MULT_4x4 = 0x18, + DS_GX_CMD_MTX_MULT_4x3 = 0x19, + DS_GX_CMD_MTX_MULT_3x3 = 0x1A, + DS_GX_CMD_MTX_SCALE = 0x1B, + DS_GX_CMD_MTX_TRANS = 0x1C, + DS_GX_CMD_COLOR = 0x20, + DS_GX_CMD_NORMAL = 0x21, + DS_GX_CMD_TEXCOORD = 0x22, + DS_GX_CMD_VTX_16 = 0x23, + DS_GX_CMD_VTX_10 = 0x24, + DS_GX_CMD_VTX_XY = 0x25, + DS_GX_CMD_VTX_XZ = 0x26, + DS_GX_CMD_VTX_YZ = 0x27, + DS_GX_CMD_VTX_DIFF = 0x28, + DS_GX_CMD_POLYGON_ATTR = 0x29, + DS_GX_CMD_TEXIMAGE_PARAM = 0x2A, + DS_GX_CMD_PLTT_BASE = 0x2B, + DS_GX_CMD_DIF_AMB = 0x30, + DS_GX_CMD_SPE_EMI = 0x31, + DS_GX_CMD_LIGHT_VECTOR = 0x32, + DS_GX_CMD_LIGHT_COLOR = 0x33, + DS_GX_CMD_SHININESS = 0x34, + DS_GX_CMD_BEGIN_VTXS = 0x40, + DS_GX_CMD_END_VTXS = 0x41, + DS_GX_CMD_SWAP_BUFFERS = 0x50, + DS_GX_CMD_VIEWPORT = 0x60, + DS_GX_CMD_BOX_TEST = 0x70, + DS_GX_CMD_POS_TEST = 0x71, + DS_GX_CMD_VEC_TEST = 0x72, + + DS_GX_CMD_MAX +}; + +#pragma pack(push, 1) +struct DSGXEntry { + uint8_t command; + uint8_t params[4]; +}; +#pragma pack(pop) + +struct DS; +struct DSGX { + struct DS* p; + struct DSGXEntry pipe[4]; + struct CircleBuffer fifo; + + struct mTimingEvent fifoEvent; +}; + +void DSGXInit(struct DSGX*); +void DSGXDeinit(struct DSGX*); +void DSGXReset(struct DSGX*); + +uint16_t DSGXWriteRegister(struct DSGX*, uint32_t address, uint16_t value); +uint32_t DSGXWriteRegister32(struct DSGX*, uint32_t address, uint32_t value); + +CXX_GUARD_END + +#endif diff --git a/include/mgba/internal/ds/io.h b/include/mgba/internal/ds/io.h index 87cc4eceb..2ca1fda0b 100644 --- a/include/mgba/internal/ds/io.h +++ b/include/mgba/internal/ds/io.h @@ -166,7 +166,6 @@ enum DS9IORegisters { DS9_REG_A_BLDCNT = 0x050, DS9_REG_A_BLDALPHA = 0x052, DS9_REG_A_BLDY = 0x054, - DS9_REG_DISP3DCNT = 0x060, DS9_REG_DISPCAPCNT_LO = 0x064, DS9_REG_DISPCAPCNT_HI = 0x066, DS9_REG_DISP_MMEM_FIFO_LO = 0x068, @@ -256,6 +255,173 @@ enum DS9IORegisters { DS9_REG_SQRT_PARAM_2 = 0x2BC, DS9_REG_SQRT_PARAM_3 = 0x2BE, + // GX + DS9_REG_DISP3DCNT = 0x060, + DS9_REG_RDLINES_COUNT = 0x320, + DS9_REG_EDGE_COLOR_0 = 0x330, + DS9_REG_EDGE_COLOR_1 = 0x332, + DS9_REG_EDGE_COLOR_2 = 0x334, + DS9_REG_EDGE_COLOR_3 = 0x336, + DS9_REG_EDGE_COLOR_4 = 0x338, + DS9_REG_EDGE_COLOR_5 = 0x33A, + DS9_REG_EDGE_COLOR_6 = 0x33C, + DS9_REG_EDGE_COLOR_7 = 0x33E, + DS9_REG_ALPHA_TEST_REF = 0x340, + DS9_REG_CLEAR_COLOR_LO = 0x350, + DS9_REG_CLEAR_COLOR_HI = 0x352, + DS9_REG_CLEAR_DEPTH = 0x354, + DS9_REG_CLRIMAGE_OFFSET = 0x356, + DS9_REG_FOG_COLOR_LO = 0x358, + DS9_REG_FOG_COLOR_HI = 0x35A, + DS9_REG_FOG_OFFSET = 0x35C, + DS9_REG_FOG_TABLE_0 = 0x360, + DS9_REG_FOG_TABLE_1 = 0x362, + DS9_REG_FOG_TABLE_2 = 0x364, + DS9_REG_FOG_TABLE_3 = 0x366, + DS9_REG_FOG_TABLE_4 = 0x368, + DS9_REG_FOG_TABLE_5 = 0x36A, + DS9_REG_FOG_TABLE_6 = 0x36C, + DS9_REG_FOG_TABLE_7 = 0x36E, + DS9_REG_FOG_TABLE_8 = 0x370, + DS9_REG_FOG_TABLE_9 = 0x372, + DS9_REG_FOG_TABLE_A = 0x374, + DS9_REG_FOG_TABLE_B = 0x376, + DS9_REG_FOG_TABLE_C = 0x378, + DS9_REG_FOG_TABLE_D = 0x37A, + DS9_REG_FOG_TABLE_E = 0x37C, + DS9_REG_FOG_TABLE_F = 0x37E, + DS9_REG_TOON_TABLE_00 = 0x380, + DS9_REG_TOON_TABLE_01 = 0x382, + DS9_REG_TOON_TABLE_02 = 0x384, + DS9_REG_TOON_TABLE_03 = 0x386, + DS9_REG_TOON_TABLE_04 = 0x388, + DS9_REG_TOON_TABLE_05 = 0x38A, + DS9_REG_TOON_TABLE_06 = 0x38C, + DS9_REG_TOON_TABLE_07 = 0x38E, + DS9_REG_TOON_TABLE_08 = 0x390, + DS9_REG_TOON_TABLE_09 = 0x392, + DS9_REG_TOON_TABLE_0A = 0x394, + DS9_REG_TOON_TABLE_0B = 0x396, + DS9_REG_TOON_TABLE_0C = 0x398, + DS9_REG_TOON_TABLE_0D = 0x39A, + DS9_REG_TOON_TABLE_0E = 0x39C, + DS9_REG_TOON_TABLE_0F = 0x39E, + DS9_REG_TOON_TABLE_10 = 0x3A0, + DS9_REG_TOON_TABLE_11 = 0x3A2, + DS9_REG_TOON_TABLE_12 = 0x3A4, + DS9_REG_TOON_TABLE_13 = 0x3A6, + DS9_REG_TOON_TABLE_14 = 0x3A8, + DS9_REG_TOON_TABLE_15 = 0x3AA, + DS9_REG_TOON_TABLE_16 = 0x3AC, + DS9_REG_TOON_TABLE_17 = 0x3AE, + DS9_REG_TOON_TABLE_18 = 0x3B0, + DS9_REG_TOON_TABLE_19 = 0x3B2, + DS9_REG_TOON_TABLE_1A = 0x3B4, + DS9_REG_TOON_TABLE_1B = 0x3B6, + DS9_REG_TOON_TABLE_1C = 0x3B8, + DS9_REG_TOON_TABLE_1D = 0x3BA, + DS9_REG_TOON_TABLE_1E = 0x3BC, + DS9_REG_TOON_TABLE_1F = 0x3BE, + DS9_REG_GXFIFO_00 = 0x400, + DS9_REG_GXFIFO_01 = 0x402, + DS9_REG_GXFIFO_02 = 0x404, + DS9_REG_GXFIFO_03 = 0x406, + DS9_REG_GXFIFO_04 = 0x408, + DS9_REG_GXFIFO_05 = 0x40A, + DS9_REG_GXFIFO_06 = 0x40C, + DS9_REG_GXFIFO_07 = 0x40E, + DS9_REG_GXFIFO_08 = 0x410, + DS9_REG_GXFIFO_09 = 0x412, + DS9_REG_GXFIFO_0A = 0x414, + DS9_REG_GXFIFO_0B = 0x416, + DS9_REG_GXFIFO_0C = 0x418, + DS9_REG_GXFIFO_0D = 0x41A, + DS9_REG_GXFIFO_0E = 0x41C, + DS9_REG_GXFIFO_0F = 0x41E, + DS9_REG_GXFIFO_10 = 0x420, + DS9_REG_GXFIFO_11 = 0x422, + DS9_REG_GXFIFO_12 = 0x424, + DS9_REG_GXFIFO_13 = 0x426, + DS9_REG_GXFIFO_14 = 0x428, + DS9_REG_GXFIFO_15 = 0x42A, + DS9_REG_GXFIFO_16 = 0x42C, + DS9_REG_GXFIFO_17 = 0x42E, + DS9_REG_GXFIFO_18 = 0x430, + DS9_REG_GXFIFO_19 = 0x432, + DS9_REG_GXFIFO_1A = 0x434, + DS9_REG_GXFIFO_1B = 0x436, + DS9_REG_GXFIFO_1C = 0x438, + DS9_REG_GXFIFO_1D = 0x43A, + DS9_REG_GXFIFO_1E = 0x43C, + DS9_REG_GXFIFO_1F = 0x43E, + DS9_REG_GXSTAT_LO = 0x600, + DS9_REG_GXSTAT_HI = 0x602, + DS9_REG_RAM_COUNT_LO = 0x604, + DS9_REG_RAM_COUNT_HI = 0x606, + DS9_REG_DISP_1DOT_DEPTH = 0x610, + DS9_REG_POS_RESULT_0 = 0x620, + DS9_REG_POS_RESULT_1 = 0x622, + DS9_REG_POS_RESULT_2 = 0x624, + DS9_REG_POS_RESULT_3 = 0x626, + DS9_REG_POS_RESULT_4 = 0x628, + DS9_REG_POS_RESULT_5 = 0x62A, + DS9_REG_POS_RESULT_6 = 0x62C, + DS9_REG_POS_RESULT_7 = 0x62E, + DS9_REG_VEC_RESULT_0 = 0x630, + DS9_REG_VEC_RESULT_1 = 0x632, + DS9_REG_VEC_RESULT_2 = 0x634, + DS9_REG_CLIPMTX_RESULT_00 = 0x640, + DS9_REG_CLIPMTX_RESULT_01 = 0x642, + DS9_REG_CLIPMTX_RESULT_02 = 0x644, + DS9_REG_CLIPMTX_RESULT_03 = 0x646, + DS9_REG_CLIPMTX_RESULT_04 = 0x648, + DS9_REG_CLIPMTX_RESULT_05 = 0x64A, + DS9_REG_CLIPMTX_RESULT_06 = 0x64C, + DS9_REG_CLIPMTX_RESULT_07 = 0x64E, + DS9_REG_CLIPMTX_RESULT_08 = 0x650, + DS9_REG_CLIPMTX_RESULT_09 = 0x652, + DS9_REG_CLIPMTX_RESULT_0A = 0x654, + DS9_REG_CLIPMTX_RESULT_0B = 0x656, + DS9_REG_CLIPMTX_RESULT_0C = 0x658, + DS9_REG_CLIPMTX_RESULT_0D = 0x65A, + DS9_REG_CLIPMTX_RESULT_0E = 0x65C, + DS9_REG_CLIPMTX_RESULT_0F = 0x65E, + DS9_REG_CLIPMTX_RESULT_10 = 0x660, + DS9_REG_CLIPMTX_RESULT_11 = 0x662, + DS9_REG_CLIPMTX_RESULT_12 = 0x664, + DS9_REG_CLIPMTX_RESULT_13 = 0x666, + DS9_REG_CLIPMTX_RESULT_14 = 0x668, + DS9_REG_CLIPMTX_RESULT_15 = 0x66A, + DS9_REG_CLIPMTX_RESULT_16 = 0x66C, + DS9_REG_CLIPMTX_RESULT_17 = 0x66E, + DS9_REG_CLIPMTX_RESULT_18 = 0x670, + DS9_REG_CLIPMTX_RESULT_19 = 0x672, + DS9_REG_CLIPMTX_RESULT_1A = 0x674, + DS9_REG_CLIPMTX_RESULT_1B = 0x676, + DS9_REG_CLIPMTX_RESULT_1C = 0x678, + DS9_REG_CLIPMTX_RESULT_1D = 0x67A, + DS9_REG_CLIPMTX_RESULT_1E = 0x67C, + DS9_REG_CLIPMTX_RESULT_1F = 0x67E, + DS9_REG_VECMTX_RESULT_00 = 0x680, + DS9_REG_VECMTX_RESULT_01 = 0x682, + DS9_REG_VECMTX_RESULT_02 = 0x684, + DS9_REG_VECMTX_RESULT_03 = 0x686, + DS9_REG_VECMTX_RESULT_04 = 0x688, + DS9_REG_VECMTX_RESULT_05 = 0x68A, + DS9_REG_VECMTX_RESULT_06 = 0x68C, + DS9_REG_VECMTX_RESULT_07 = 0x68E, + DS9_REG_VECMTX_RESULT_08 = 0x690, + DS9_REG_VECMTX_RESULT_09 = 0x692, + DS9_REG_VECMTX_RESULT_0A = 0x694, + DS9_REG_VECMTX_RESULT_0B = 0x696, + DS9_REG_VECMTX_RESULT_0C = 0x698, + DS9_REG_VECMTX_RESULT_0D = 0x69A, + DS9_REG_VECMTX_RESULT_0E = 0x69C, + DS9_REG_VECMTX_RESULT_0F = 0x69E, + DS9_REG_VECMTX_RESULT_10 = 0x6A0, + DS9_REG_VECMTX_RESULT_11 = 0x6A2, + DS9_REG_VECMTX_RESULT_12 = 0x6A4, + DS9_REG_MAX = 0x106E, DS9_REG_POWCNT1 = 0x304, diff --git a/src/ds/ds.c b/src/ds/ds.c index 4e2b864db..7fbdf9481 100644 --- a/src/ds/ds.c +++ b/src/ds/ds.c @@ -196,6 +196,9 @@ static void DSInit(void* cpu, struct mCPUComponent* component) { DSVideoInit(&ds->video); ds->video.p = ds; + DSGXInit(&ds->gx); + ds->gx.p = ds; + ds->ds7.springIRQ = 0; ds->ds9.springIRQ = 0; DSTimerInit(ds); @@ -234,6 +237,7 @@ void DSDestroy(struct DS* ds) { CircleBufferDeinit(&ds->ds9.fifo); DSUnloadROM(ds); DSMemoryDeinit(ds); + DSGXDeinit(&ds->gx); mTimingDeinit(&ds->ds7.timing); mTimingDeinit(&ds->ds9.timing); } @@ -318,6 +322,7 @@ void DS9Reset(struct ARMCore* cpu) { mTimingClear(&ds->ds9.timing); CircleBufferInit(&ds->ds9.fifo, 64); DSVideoReset(&ds->video); + DSGXReset(&ds->gx); DSDMAReset(&ds->ds9); DS9IOInit(ds); diff --git a/src/ds/gx.c b/src/ds/gx.c new file mode 100644 index 000000000..afcd2b159 --- /dev/null +++ b/src/ds/gx.c @@ -0,0 +1,104 @@ +/* Copyright (c) 2013-2017 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 + +#include + +mLOG_DEFINE_CATEGORY(DS_GX, "DS GX"); + +#define DS_GX_FIFO_SIZE 256 + +static const int32_t _gxCommandCycleBase[DS_GX_CMD_MAX] = { + [DS_GX_CMD_NOP] = 0, + [DS_GX_CMD_MTX_MODE] = 2, + [DS_GX_CMD_MTX_PUSH] = 34, + [DS_GX_CMD_MTX_POP] = 72, + [DS_GX_CMD_MTX_STORE] = 34, + [DS_GX_CMD_MTX_RESTORE] = 72, + [DS_GX_CMD_MTX_IDENTITY] = 38, + [DS_GX_CMD_MTX_LOAD_4x4] = 68, + [DS_GX_CMD_MTX_LOAD_4x3] = 60, + [DS_GX_CMD_MTX_MULT_4x4] = 70, + [DS_GX_CMD_MTX_MULT_4x3] = 62, + [DS_GX_CMD_MTX_MULT_3x3] = 56, + [DS_GX_CMD_MTX_SCALE] = 44, + [DS_GX_CMD_MTX_TRANS] = 44, + [DS_GX_CMD_COLOR] = 2, + [DS_GX_CMD_NORMAL] = 18, + [DS_GX_CMD_TEXCOORD] = 2, + [DS_GX_CMD_VTX_16] = 18, + [DS_GX_CMD_VTX_10] = 16, + [DS_GX_CMD_VTX_XY] = 16, + [DS_GX_CMD_VTX_XZ] = 16, + [DS_GX_CMD_VTX_YZ] = 16, + [DS_GX_CMD_VTX_DIFF] = 16, + [DS_GX_CMD_POLYGON_ATTR] = 2, + [DS_GX_CMD_TEXIMAGE_PARAM] = 2, + [DS_GX_CMD_PLTT_BASE] = 2, + [DS_GX_CMD_DIF_AMB] = 8, + [DS_GX_CMD_SPE_EMI] = 8, + [DS_GX_CMD_LIGHT_VECTOR] = 12, + [DS_GX_CMD_LIGHT_COLOR] = 2, + [DS_GX_CMD_SHININESS] = 64, + [DS_GX_CMD_BEGIN_VTXS] = 2, + [DS_GX_CMD_END_VTXS] = 2, + [DS_GX_CMD_SWAP_BUFFERS] = 784, + [DS_GX_CMD_VIEWPORT] = 2, + [DS_GX_CMD_BOX_TEST] = 206, + [DS_GX_CMD_POS_TEST] = 18, + [DS_GX_CMD_VEC_TEST] = 10, +}; + +void DSGXInit(struct DSGX* gx) { + CircleBufferInit(&gx->fifo, sizeof(struct DSGXEntry) * DS_GX_FIFO_SIZE); +} + +void DSGXDeinit(struct DSGX* gx) { + CircleBufferDeinit(&gx->fifo); +} + +void DSGXReset(struct DSGX* gx) { + CircleBufferClear(&gx->fifo); +} + +uint16_t DSGXWriteRegister(struct DSGX* gx, uint32_t address, uint16_t value) { + switch (address) { + case DS9_REG_DISP3DCNT: + case DS9_REG_GXSTAT_LO: + case DS9_REG_GXSTAT_HI: + mLOG(DS_GX, STUB, "Unimplemented GX write %03X:%04X", address, value); + break; + default: + if (address < DS9_REG_GXFIFO_00) { + mLOG(DS_GX, STUB, "Unimplemented GX write %03X:%04X", address, value); + } else if (address < DS9_REG_GXSTAT_LO) { + mLOG(DS_GX, STUB, "Unimplemented FIFO write %03X:%04X", address, value); + } else { + mLOG(DS_GX, STUB, "Unimplemented GX write %03X:%04X", address, value); + } + break; + } + return value; +} + +uint32_t DSGXWriteRegister32(struct DSGX* gx, uint32_t address, uint32_t value) { + switch (address) { + case DS9_REG_DISP3DCNT: + case DS9_REG_GXSTAT_LO: + mLOG(DS_GX, STUB, "Unimplemented GX write %03X:%04X", address, value); + break; + default: + if (address < DS9_REG_GXFIFO_00) { + mLOG(DS_GX, STUB, "Unimplemented GX write %03X:%04X", address, value); + } else if (address < DS9_REG_GXSTAT_LO) { + mLOG(DS_GX, STUB, "Unimplemented FIFO write %03X:%04X", address, value); + } else { + mLOG(DS_GX, STUB, "Unimplemented GX write %03X:%04X", address, value); + } + break; + } + return value; +} diff --git a/src/ds/io.c b/src/ds/io.c index 56d0cb982..1bfaf9103 100644 --- a/src/ds/io.c +++ b/src/ds/io.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -415,6 +416,7 @@ void DS9IOInit(struct DS* ds) { memset(ds->memory.io9, 0, sizeof(ds->memory.io9)); ds->memory.io9[DS_REG_IPCFIFOCNT >> 1] = 0x0101; ds->memory.io9[DS_REG_POSTFLG >> 1] = 0x0001; + ds->memory.io9[DS9_REG_GXSTAT_HI >> 1] = 0x0600; DS9IOWrite(ds, DS9_REG_VRAMCNT_G, 0x0300); } @@ -423,6 +425,8 @@ void DS9IOWrite(struct DS* ds, uint32_t address, uint16_t value) { value = ds->video.renderer->writeVideoRegister(ds->video.renderer, address, value); } else if (address >= DS9_REG_B_DISPCNT_LO && address <= DS9_REG_B_BLDY) { value = ds->video.renderer->writeVideoRegister(ds->video.renderer, address, value); + } else if ((address >= DS9_REG_RDLINES_COUNT && address <= DS9_REG_VECMTX_RESULT_12) || address == DS9_REG_DISP3DCNT) { + value = DSGXWriteRegister(&ds->gx, address, value); } else { uint16_t oldValue; switch (address) { @@ -514,37 +518,41 @@ void DS9IOWrite8(struct DS* ds, uint32_t address, uint8_t value) { } void DS9IOWrite32(struct DS* ds, uint32_t address, uint32_t value) { - switch (address) { - case DS_REG_DMA0SAD_LO: - case DS_REG_DMA1SAD_LO: - case DS_REG_DMA2SAD_LO: - case DS_REG_DMA3SAD_LO: - case DS_REG_DMA0DAD_LO: - case DS_REG_DMA1DAD_LO: - case DS_REG_DMA2DAD_LO: - case DS_REG_DMA3DAD_LO: - case DS_REG_IPCFIFOSEND_LO: - case DS_REG_IE_LO: - value = DSIOWrite32(&ds->ds9, address, value); - break; + if ((address >= DS9_REG_RDLINES_COUNT && address <= DS9_REG_VECMTX_RESULT_12) || address == DS9_REG_DISP3DCNT) { + value = DSGXWriteRegister32(&ds->gx, address, value); + } else { + switch (address) { + case DS_REG_DMA0SAD_LO: + case DS_REG_DMA1SAD_LO: + case DS_REG_DMA2SAD_LO: + case DS_REG_DMA3SAD_LO: + case DS_REG_DMA0DAD_LO: + case DS_REG_DMA1DAD_LO: + case DS_REG_DMA2DAD_LO: + case DS_REG_DMA3DAD_LO: + case DS_REG_IPCFIFOSEND_LO: + case DS_REG_IE_LO: + value = DSIOWrite32(&ds->ds9, address, value); + break; - case DS_REG_DMA0CNT_LO: - DS9DMAWriteCNT(&ds->ds9, 0, value); - break; - case DS_REG_DMA1CNT_LO: - DS9DMAWriteCNT(&ds->ds9, 1, value); - break; - case DS_REG_DMA2CNT_LO: - DS9DMAWriteCNT(&ds->ds9, 2, value); - break; - case DS_REG_DMA3CNT_LO: - DS9DMAWriteCNT(&ds->ds9, 3, value); - break; + case DS_REG_DMA0CNT_LO: + DS9DMAWriteCNT(&ds->ds9, 0, value); + break; + case DS_REG_DMA1CNT_LO: + DS9DMAWriteCNT(&ds->ds9, 1, value); + break; + case DS_REG_DMA2CNT_LO: + DS9DMAWriteCNT(&ds->ds9, 2, value); + break; + case DS_REG_DMA3CNT_LO: + DS9DMAWriteCNT(&ds->ds9, 3, value); + break; - default: - DS9IOWrite(ds, address, value & 0xFFFF); - DS9IOWrite(ds, address | 2, value >> 16); - return; + default: + DS9IOWrite(ds, address, value & 0xFFFF); + DS9IOWrite(ds, address | 2, value >> 16); + return; + } } ds->ds9.memory.io[address >> 1] = value; ds->ds9.memory.io[(address >> 1) + 1] = value >> 16; @@ -608,6 +616,8 @@ uint16_t DS9IORead(struct DS* ds, uint32_t address) { case DS9_REG_SQRT_RESULT_LO: case DS9_REG_SQRT_RESULT_HI: case DS_REG_POSTFLG: + case DS9_REG_GXSTAT_LO: + case DS9_REG_GXSTAT_HI: // Handled transparently by the registers break; case DS_REG_AUXSPICNT: