DS Video: Start hooking up GBA video

This commit is contained in:
Vicki Pfau 2017-02-21 18:45:16 -08:00
parent 5ad7092567
commit e0518fdf30
7 changed files with 239 additions and 21 deletions

View File

@ -19,6 +19,9 @@ struct DSVideoSoftwareRenderer {
struct GBAVideoSoftwareRenderer engA; struct GBAVideoSoftwareRenderer engA;
struct GBAVideoSoftwareRenderer engB; struct GBAVideoSoftwareRenderer engB;
DSRegisterDISPCNT dispcntA;
DSRegisterDISPCNT dispcntB;
color_t* outputBuffer; color_t* outputBuffer;
int outputBufferStride; int outputBufferStride;

View File

@ -35,12 +35,32 @@ union DSOAM {
uint16_t raw[1024]; uint16_t raw[1024];
}; };
DECL_BITFIELD(DSRegisterDISPCNT, uint32_t);
DECL_BITS(DSRegisterDISPCNT, Mode, 0, 3);
DECL_BIT(DSRegisterDISPCNT, 3D, 3);
DECL_BIT(DSRegisterDISPCNT, TileObjMapping, 4);
DECL_BIT(DSRegisterDISPCNT, BitmapObj2D, 5);
DECL_BIT(DSRegisterDISPCNT, BitmapObjMapping, 6);
DECL_BIT(DSRegisterDISPCNT, ForcedBlank, 7);
DECL_BIT(DSRegisterDISPCNT, Bg0Enable, 8);
DECL_BIT(DSRegisterDISPCNT, Bg1Enable, 9);
DECL_BIT(DSRegisterDISPCNT, Bg2Enable, 10);
DECL_BIT(DSRegisterDISPCNT, Bg3Enable, 11);
DECL_BIT(DSRegisterDISPCNT, ObjEnable, 12);
DECL_BIT(DSRegisterDISPCNT, Win0Enable, 13);
DECL_BIT(DSRegisterDISPCNT, Win1Enable, 14);
DECL_BIT(DSRegisterDISPCNT, ObjwinEnable, 15);
DECL_BITS(DSRegisterDISPCNT, DispMode, 16, 2);
DECL_BITS(DSRegisterDISPCNT, VRAMBlock, 18, 2);
// TODO
struct DSVideoRenderer { struct DSVideoRenderer {
void (*init)(struct DSVideoRenderer* renderer); void (*init)(struct DSVideoRenderer* renderer);
void (*reset)(struct DSVideoRenderer* renderer); void (*reset)(struct DSVideoRenderer* renderer);
void (*deinit)(struct DSVideoRenderer* renderer); void (*deinit)(struct DSVideoRenderer* renderer);
uint16_t (*writeVideoRegister)(struct DSVideoRenderer* renderer, uint32_t address, uint16_t value); uint16_t (*writeVideoRegister)(struct DSVideoRenderer* renderer, uint32_t address, uint16_t value);
void (*writePalette)(struct DSVideoRenderer* renderer, uint32_t address, uint16_t value);
void (*drawScanline)(struct DSVideoRenderer* renderer, int y); void (*drawScanline)(struct DSVideoRenderer* renderer, int y);
void (*finishFrame)(struct DSVideoRenderer* renderer); void (*finishFrame)(struct DSVideoRenderer* renderer);
@ -49,6 +69,10 @@ struct DSVideoRenderer {
uint16_t* palette; uint16_t* palette;
uint16_t* vram; uint16_t* vram;
uint16_t* vramABG[32];
uint16_t* vramAOBJ[32];
uint16_t* vramBBG[32];
uint16_t* vramBOBJ[32];
union DSOAM* oam; union DSOAM* oam;
}; };
@ -64,6 +88,10 @@ struct DSVideo {
uint16_t palette[1024]; uint16_t palette[1024];
uint16_t* vram; uint16_t* vram;
uint16_t* vramABG[32];
uint16_t* vramAOBJ[32];
uint16_t* vramBBG[32];
uint16_t* vramBOBJ[32];
union DSOAM oam; union DSOAM oam;
int32_t frameCounter; int32_t frameCounter;
@ -80,7 +108,7 @@ struct DSCommon;
void DSVideoWriteDISPSTAT(struct DSCommon* dscore, uint16_t value); void DSVideoWriteDISPSTAT(struct DSCommon* dscore, uint16_t value);
struct DSMemory; struct DSMemory;
void DSVideoConfigureVRAM(struct DSMemory* memory, int index, uint8_t value); void DSVideoConfigureVRAM(struct DS* ds, int index, uint8_t value);
CXX_GUARD_START CXX_GUARD_START

View File

@ -386,9 +386,9 @@ void DS9IOInit(struct DS* ds) {
} }
void DS9IOWrite(struct DS* ds, uint32_t address, uint16_t value) { void DS9IOWrite(struct DS* ds, uint32_t address, uint16_t value) {
if (address <= DS9_REG_A_BLDY && (address > DS_REG_VCOUNT || address == DS9_REG_A_DISPCNT_LO || address == DS9_REG_B_DISPCNT_LO)) { if (address <= DS9_REG_A_BLDY && (address > DS_REG_VCOUNT || address == DS9_REG_A_DISPCNT_LO || address == DS9_REG_A_DISPCNT_HI)) {
value = ds->video.renderer->writeVideoRegister(ds->video.renderer, address, value); value = ds->video.renderer->writeVideoRegister(ds->video.renderer, address, value);
} else if (address >= DS9_REG_B_DISPCNT_LO && address <= DS9_REG_B_BLDY && (address == DS9_REG_B_DISPCNT_LO || address == DS9_REG_B_DISPCNT_LO)) { } else if (address >= DS9_REG_B_DISPCNT_LO && address <= DS9_REG_B_BLDY) {
value = ds->video.renderer->writeVideoRegister(ds->video.renderer, address, value); value = ds->video.renderer->writeVideoRegister(ds->video.renderer, address, value);
} else { } else {
switch (address) { switch (address) {
@ -397,18 +397,18 @@ void DS9IOWrite(struct DS* ds, uint32_t address, uint16_t value) {
case DS9_REG_VRAMCNT_C: case DS9_REG_VRAMCNT_C:
case DS9_REG_VRAMCNT_E: case DS9_REG_VRAMCNT_E:
value &= 0x9F9F; value &= 0x9F9F;
DSVideoConfigureVRAM(&ds->memory, address - DS9_REG_VRAMCNT_A, value & 0xFF); DSVideoConfigureVRAM(ds, address - DS9_REG_VRAMCNT_A, value & 0xFF);
DSVideoConfigureVRAM(&ds->memory, address - DS9_REG_VRAMCNT_A + 1, value >> 8); DSVideoConfigureVRAM(ds, address - DS9_REG_VRAMCNT_A + 1, value >> 8);
break; break;
case DS9_REG_VRAMCNT_G: case DS9_REG_VRAMCNT_G:
value &= 0x9F03; value &= 0x9F03;
DSVideoConfigureVRAM(&ds->memory, 6, value & 0xFF); DSVideoConfigureVRAM(ds, 6, value & 0xFF);
DSConfigureWRAM(&ds->memory, value >> 8); DSConfigureWRAM(&ds->memory, value >> 8);
break; break;
case DS9_REG_VRAMCNT_H: case DS9_REG_VRAMCNT_H:
value &= 0x9F9F; value &= 0x9F9F;
DSVideoConfigureVRAM(&ds->memory, 7, value & 0xFF); DSVideoConfigureVRAM(ds, 7, value & 0xFF);
DSVideoConfigureVRAM(&ds->memory, 8, value >> 8); DSVideoConfigureVRAM(ds, 8, value >> 8);
break; break;
case DS9_REG_EXMEMCNT: case DS9_REG_EXMEMCNT:

View File

@ -181,15 +181,15 @@ void DSMemoryReset(struct DS* ds) {
ds->ds7.memory.slot1Access = true; ds->ds7.memory.slot1Access = true;
ds->ds9.memory.slot1Access = false; ds->ds9.memory.slot1Access = false;
DSVideoConfigureVRAM(&ds->memory, 0, 0); DSVideoConfigureVRAM(ds, 0, 0);
DSVideoConfigureVRAM(&ds->memory, 1, 0); DSVideoConfigureVRAM(ds, 1, 0);
DSVideoConfigureVRAM(&ds->memory, 2, 0); DSVideoConfigureVRAM(ds, 2, 0);
DSVideoConfigureVRAM(&ds->memory, 3, 0); DSVideoConfigureVRAM(ds, 3, 0);
DSVideoConfigureVRAM(&ds->memory, 4, 0); DSVideoConfigureVRAM(ds, 4, 0);
DSVideoConfigureVRAM(&ds->memory, 5, 0); DSVideoConfigureVRAM(ds, 5, 0);
DSVideoConfigureVRAM(&ds->memory, 6, 0); DSVideoConfigureVRAM(ds, 6, 0);
DSVideoConfigureVRAM(&ds->memory, 7, 0); DSVideoConfigureVRAM(ds, 7, 0);
DSVideoConfigureVRAM(&ds->memory, 8, 0); DSVideoConfigureVRAM(ds, 8, 0);
DSConfigureWRAM(&ds->memory, 3); DSConfigureWRAM(&ds->memory, 3);
if (!ds->memory.wram || !ds->memory.wram7 || !ds->memory.ram || !ds->memory.itcm || !ds->memory.dtcm) { if (!ds->memory.wram || !ds->memory.wram7 || !ds->memory.ram || !ds->memory.itcm || !ds->memory.dtcm) {
@ -940,6 +940,8 @@ void DS9Store32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycle
break; break;
case DS9_REGION_PALETTE_RAM: case DS9_REGION_PALETTE_RAM:
STORE_32(value, address & (DS9_SIZE_PALETTE_RAM - 4), ds->video.palette); STORE_32(value, address & (DS9_SIZE_PALETTE_RAM - 4), ds->video.palette);
ds->video.renderer->writePalette(ds->video.renderer, (address & (DS9_SIZE_PALETTE_RAM - 4)) + 2, value >> 16);
ds->video.renderer->writePalette(ds->video.renderer, address & (DS9_SIZE_PALETTE_RAM - 4), value);
break; break;
case DS_REGION_VRAM: { case DS_REGION_VRAM: {
unsigned mask = _selectVRAM(memory, address >> DS_VRAM_OFFSET); unsigned mask = _selectVRAM(memory, address >> DS_VRAM_OFFSET);
@ -1006,6 +1008,7 @@ void DS9Store16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycle
break; break;
case DS9_REGION_PALETTE_RAM: case DS9_REGION_PALETTE_RAM:
STORE_16(value, address & (DS9_SIZE_PALETTE_RAM - 2), ds->video.palette); STORE_16(value, address & (DS9_SIZE_PALETTE_RAM - 2), ds->video.palette);
ds->video.renderer->writePalette(ds->video.renderer, address & (DS9_SIZE_PALETTE_RAM - 2), value);
break; break;
case DS_REGION_VRAM: { case DS_REGION_VRAM: {
unsigned mask = _selectVRAM(memory, address >> DS_VRAM_OFFSET); unsigned mask = _selectVRAM(memory, address >> DS_VRAM_OFFSET);
@ -1228,7 +1231,9 @@ uint32_t DS9StoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum
}); });
break; break;
case DS9_REGION_PALETTE_RAM: case DS9_REGION_PALETTE_RAM:
STM_LOOP(STORE_32(value, address & (DS9_SIZE_PALETTE_RAM - 1), ds->video.palette)); STM_LOOP(STORE_32(value, address & (DS9_SIZE_PALETTE_RAM - 1), ds->video.palette);
ds->video.renderer->writePalette(ds->video.renderer, (address & (DS9_SIZE_PALETTE_RAM - 4)) + 2, value >> 16);
ds->video.renderer->writePalette(ds->video.renderer, address & (DS9_SIZE_PALETTE_RAM - 4), value));
break; break;
case DS_REGION_VRAM: case DS_REGION_VRAM:
STM_LOOP(unsigned mask = _selectVRAM(memory, address >> DS_VRAM_OFFSET); STM_LOOP(unsigned mask = _selectVRAM(memory, address >> DS_VRAM_OFFSET);

View File

@ -5,10 +5,14 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <mgba/internal/ds/renderers/software.h> #include <mgba/internal/ds/renderers/software.h>
#include <mgba/internal/arm/macros.h>
#include <mgba/internal/ds/io.h>
static void DSVideoSoftwareRendererInit(struct DSVideoRenderer* renderer); static void DSVideoSoftwareRendererInit(struct DSVideoRenderer* renderer);
static void DSVideoSoftwareRendererDeinit(struct DSVideoRenderer* renderer); static void DSVideoSoftwareRendererDeinit(struct DSVideoRenderer* renderer);
static void DSVideoSoftwareRendererReset(struct DSVideoRenderer* renderer); static void DSVideoSoftwareRendererReset(struct DSVideoRenderer* renderer);
static uint16_t DSVideoSoftwareRendererWriteVideoRegister(struct DSVideoRenderer* renderer, uint32_t address, uint16_t value); static uint16_t DSVideoSoftwareRendererWriteVideoRegister(struct DSVideoRenderer* renderer, uint32_t address, uint16_t value);
static void DSVideoSoftwareRendererWritePalette(struct DSVideoRenderer* renderer, uint32_t address, uint16_t value);
static void DSVideoSoftwareRendererDrawScanline(struct DSVideoRenderer* renderer, int y); static void DSVideoSoftwareRendererDrawScanline(struct DSVideoRenderer* renderer, int y);
static void DSVideoSoftwareRendererFinishFrame(struct DSVideoRenderer* renderer); static void DSVideoSoftwareRendererFinishFrame(struct DSVideoRenderer* renderer);
static void DSVideoSoftwareRendererGetPixels(struct DSVideoRenderer* renderer, size_t* stride, const void** pixels); static void DSVideoSoftwareRendererGetPixels(struct DSVideoRenderer* renderer, size_t* stride, const void** pixels);
@ -19,6 +23,7 @@ void DSVideoSoftwareRendererCreate(struct DSVideoSoftwareRenderer* renderer) {
renderer->d.reset = DSVideoSoftwareRendererReset; renderer->d.reset = DSVideoSoftwareRendererReset;
renderer->d.deinit = DSVideoSoftwareRendererDeinit; renderer->d.deinit = DSVideoSoftwareRendererDeinit;
renderer->d.writeVideoRegister = DSVideoSoftwareRendererWriteVideoRegister; renderer->d.writeVideoRegister = DSVideoSoftwareRendererWriteVideoRegister;
renderer->d.writePalette = DSVideoSoftwareRendererWritePalette;
renderer->d.drawScanline = DSVideoSoftwareRendererDrawScanline; renderer->d.drawScanline = DSVideoSoftwareRendererDrawScanline;
renderer->d.finishFrame = DSVideoSoftwareRendererFinishFrame; renderer->d.finishFrame = DSVideoSoftwareRendererFinishFrame;
renderer->d.getPixels = DSVideoSoftwareRendererGetPixels; renderer->d.getPixels = DSVideoSoftwareRendererGetPixels;
@ -55,17 +60,155 @@ static void DSVideoSoftwareRendererDeinit(struct DSVideoRenderer* renderer) {
} }
static uint16_t DSVideoSoftwareRendererWriteVideoRegister(struct DSVideoRenderer* renderer, uint32_t address, uint16_t value) { static uint16_t DSVideoSoftwareRendererWriteVideoRegister(struct DSVideoRenderer* renderer, uint32_t address, uint16_t value) {
struct DSVideoSoftwareRenderer* softwareRenderer = (struct DSVideoSoftwareRenderer*) renderer;
if (address <= DS9_REG_A_BLDY) {
value = softwareRenderer->engA.d.writeVideoRegister(&softwareRenderer->engA.d, address, value);
} else if (address >= DS9_REG_B_DISPCNT_LO && address <= DS9_REG_B_BLDY) {
value = softwareRenderer->engB.d.writeVideoRegister(&softwareRenderer->engB.d, address & 0xFF, value);
} else {
mLOG(DS_VIDEO, STUB, "Stub video register write: %04X:%04X", address, value); mLOG(DS_VIDEO, STUB, "Stub video register write: %04X:%04X", address, value);
}
switch (address) {
case DS9_REG_A_DISPCNT_LO:
softwareRenderer->dispcntA &= 0xFFFF0000;
softwareRenderer->dispcntA |= value;
break;
case DS9_REG_A_DISPCNT_HI:
softwareRenderer->dispcntA &= 0x0000FFFF;
softwareRenderer->dispcntA |= value << 16;
break;
case DS9_REG_B_DISPCNT_LO:
softwareRenderer->dispcntB &= 0xFFFF0000;
softwareRenderer->dispcntB |= value;
break;
case DS9_REG_B_DISPCNT_HI:
softwareRenderer->dispcntB &= 0x0000FFFF;
softwareRenderer->dispcntB |= value << 16;
break;
}
return value; return value;
} }
static void DSVideoSoftwareRendererWritePalette(struct DSVideoRenderer* renderer, uint32_t address, uint16_t value) {
struct DSVideoSoftwareRenderer* softwareRenderer = (struct DSVideoSoftwareRenderer*) renderer;
if (address < 0x200) {
softwareRenderer->engA.d.writePalette(&softwareRenderer->engA.d, address & 0x1FF, value);
} else {
softwareRenderer->engB.d.writePalette(&softwareRenderer->engB.d, address & 0x1FF, value);
}
}
static void _drawScanlineA(struct DSVideoSoftwareRenderer* softwareRenderer, int y) {
memcpy(softwareRenderer->engA.d.vramBG, softwareRenderer->d.vramABG, sizeof(softwareRenderer->engA.d.vramBG));
memcpy(softwareRenderer->engA.d.vramOBJ, softwareRenderer->d.vramAOBJ, sizeof(softwareRenderer->engA.d.vramOBJ));
color_t* row = &softwareRenderer->engA.outputBuffer[softwareRenderer->outputBufferStride * y];
int x;
switch (DSRegisterDISPCNTGetDispMode(softwareRenderer->dispcntA)) {
case 0:
for (x = 0; x < DS_VIDEO_HORIZONTAL_PIXELS; ++x) {
row[x] = GBA_COLOR_WHITE;
}
return;
case 1:
softwareRenderer->engA.d.drawScanline(&softwareRenderer->engA.d, y);
return;
case 2: {
uint16_t* vram = &softwareRenderer->d.vram[0x10000 * DSRegisterDISPCNTGetVRAMBlock(softwareRenderer->dispcntA)];
for (x = 0; x < DS_VIDEO_HORIZONTAL_PIXELS; ++x) {
color_t color;
LOAD_16(color, (x + y * DS_VIDEO_HORIZONTAL_PIXELS) * 2, vram);
#ifndef COLOR_16_BIT
unsigned color32 = 0;
color32 |= (color << 9) & 0xF80000;
color32 |= (color << 3) & 0xF8;
color32 |= (color << 6) & 0xF800;
color32 |= (color32 >> 5) & 0x070707;
color = color32;
#elif COLOR_5_6_5
uint16_t color16 = 0;
color16 |= (color & 0x001F) << 11;
color16 |= (color & 0x03E0) << 1;
color16 |= (color & 0x7C00) >> 10;
color = color16;
#endif
softwareRenderer->row[x] = color;
}
break;
}
case 3:
break;
}
#ifdef COLOR_16_BIT
#if defined(__ARM_NEON) && !defined(__APPLE__)
_to16Bit(row, softwareRenderer->row, DS_VIDEO_HORIZONTAL_PIXELS);
#else
for (x = 0; x < DS_VIDEO_HORIZONTAL_PIXELS; ++x) {
row[x] = softwareRenderer->row[x];
}
#endif
#else
memcpy(row, softwareRenderer->row, DS_VIDEO_HORIZONTAL_PIXELS * sizeof(*row));
#endif
}
static void _drawScanlineB(struct DSVideoSoftwareRenderer* softwareRenderer, int y) {
memcpy(softwareRenderer->engB.d.vramBG, softwareRenderer->d.vramBBG, sizeof(softwareRenderer->engB.d.vramBG));
memcpy(softwareRenderer->engB.d.vramOBJ, softwareRenderer->d.vramBOBJ, sizeof(softwareRenderer->engB.d.vramOBJ));
color_t* row = &softwareRenderer->engB.outputBuffer[softwareRenderer->outputBufferStride * y];
int x;
switch (DSRegisterDISPCNTGetDispMode(softwareRenderer->dispcntB)) {
case 0:
for (x = 0; x < DS_VIDEO_HORIZONTAL_PIXELS; ++x) {
row[x] = GBA_COLOR_WHITE;
}
return;
case 1:
softwareRenderer->engB.d.drawScanline(&softwareRenderer->engB.d, y);
return;
}
#ifdef COLOR_16_BIT
#if defined(__ARM_NEON) && !defined(__APPLE__)
_to16Bit(row, softwareRenderer->row, DS_VIDEO_HORIZONTAL_PIXELS);
#else
for (x = 0; x < DS_VIDEO_HORIZONTAL_PIXELS; ++x) {
row[x] = softwareRenderer->row[x];
}
#endif
#else
memcpy(row, softwareRenderer->row, DS_VIDEO_HORIZONTAL_PIXELS * sizeof(*row));
#endif
}
static void DSVideoSoftwareRendererDrawScanline(struct DSVideoRenderer* renderer, int y) { static void DSVideoSoftwareRendererDrawScanline(struct DSVideoRenderer* renderer, int y) {
struct DSVideoSoftwareRenderer* softwareRenderer = (struct DSVideoSoftwareRenderer*) renderer;
softwareRenderer->engA.outputBuffer = softwareRenderer->outputBuffer;
softwareRenderer->engB.outputBuffer = &softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * DS_VIDEO_VERTICAL_PIXELS];
softwareRenderer->engA.outputBufferStride = softwareRenderer->outputBufferStride;
softwareRenderer->engB.outputBufferStride = softwareRenderer->outputBufferStride;
_drawScanlineA(softwareRenderer, y);
_drawScanlineB(softwareRenderer, y);
} }
static void DSVideoSoftwareRendererFinishFrame(struct DSVideoRenderer* renderer) { static void DSVideoSoftwareRendererFinishFrame(struct DSVideoRenderer* renderer) {
struct DSVideoSoftwareRenderer* softwareRenderer = (struct DSVideoSoftwareRenderer*) renderer;
softwareRenderer->engA.d.finishFrame(&softwareRenderer->engA.d);
softwareRenderer->engB.d.finishFrame(&softwareRenderer->engB.d);
} }
static void DSVideoSoftwareRendererGetPixels(struct DSVideoRenderer* renderer, size_t* stride, const void** pixels) { static void DSVideoSoftwareRendererGetPixels(struct DSVideoRenderer* renderer, size_t* stride, const void** pixels) {
struct DSVideoSoftwareRenderer* softwareRenderer = (struct DSVideoSoftwareRenderer*) renderer;
#ifdef COLOR_16_BIT
#error Not yet supported
#else
*stride = softwareRenderer->outputBufferStride;
*pixels = softwareRenderer->outputBuffer;
#endif
} }
static void DSVideoSoftwareRendererPutPixels(struct DSVideoRenderer* renderer, size_t stride, const void* pixels) { static void DSVideoSoftwareRendererPutPixels(struct DSVideoRenderer* renderer, size_t stride, const void* pixels) {

View File

@ -18,6 +18,7 @@ static void DSVideoDummyRendererInit(struct DSVideoRenderer* renderer);
static void DSVideoDummyRendererReset(struct DSVideoRenderer* renderer); static void DSVideoDummyRendererReset(struct DSVideoRenderer* renderer);
static void DSVideoDummyRendererDeinit(struct DSVideoRenderer* renderer); static void DSVideoDummyRendererDeinit(struct DSVideoRenderer* renderer);
static uint16_t DSVideoDummyRendererWriteVideoRegister(struct DSVideoRenderer* renderer, uint32_t address, uint16_t value); static uint16_t DSVideoDummyRendererWriteVideoRegister(struct DSVideoRenderer* renderer, uint32_t address, uint16_t value);
static void DSVideoDummyRendererWritePalette(struct DSVideoRenderer* renderer, uint32_t address, uint16_t value);
static void DSVideoDummyRendererDrawScanline(struct DSVideoRenderer* renderer, int y); static void DSVideoDummyRendererDrawScanline(struct DSVideoRenderer* renderer, int y);
static void DSVideoDummyRendererFinishFrame(struct DSVideoRenderer* renderer); static void DSVideoDummyRendererFinishFrame(struct DSVideoRenderer* renderer);
static void DSVideoDummyRendererGetPixels(struct DSVideoRenderer* renderer, size_t* stride, const void** pixels); static void DSVideoDummyRendererGetPixels(struct DSVideoRenderer* renderer, size_t* stride, const void** pixels);
@ -102,6 +103,7 @@ static struct DSVideoRenderer dummyRenderer = {
.reset = DSVideoDummyRendererReset, .reset = DSVideoDummyRendererReset,
.deinit = DSVideoDummyRendererDeinit, .deinit = DSVideoDummyRendererDeinit,
.writeVideoRegister = DSVideoDummyRendererWriteVideoRegister, .writeVideoRegister = DSVideoDummyRendererWriteVideoRegister,
.writePalette = DSVideoDummyRendererWritePalette,
.drawScanline = DSVideoDummyRendererDrawScanline, .drawScanline = DSVideoDummyRendererDrawScanline,
.finishFrame = DSVideoDummyRendererFinishFrame, .finishFrame = DSVideoDummyRendererFinishFrame,
.getPixels = DSVideoDummyRendererGetPixels, .getPixels = DSVideoDummyRendererGetPixels,
@ -160,6 +162,10 @@ void DSVideoAssociateRenderer(struct DSVideo* video, struct DSVideoRenderer* ren
video->renderer = renderer; video->renderer = renderer;
renderer->palette = video->palette; renderer->palette = video->palette;
renderer->vram = video->vram; renderer->vram = video->vram;
memcpy(renderer->vramABG, video->vramABG, sizeof(renderer->vramABG));
memcpy(renderer->vramAOBJ, video->vramAOBJ, sizeof(renderer->vramAOBJ));
memcpy(renderer->vramBBG, video->vramBBG, sizeof(renderer->vramBBG));
memcpy(renderer->vramBOBJ, video->vramBOBJ, sizeof(renderer->vramBOBJ));
renderer->oam = &video->oam; renderer->oam = &video->oam;
video->renderer->init(video->renderer); video->renderer->init(video->renderer);
} }
@ -292,7 +298,8 @@ void DSVideoWriteDISPSTAT(struct DSCommon* dscore, uint16_t value) {
// TODO: Does a VCounter IRQ trigger on write? // TODO: Does a VCounter IRQ trigger on write?
} }
void DSVideoConfigureVRAM(struct DSMemory* memory, int index, uint8_t value) { void DSVideoConfigureVRAM(struct DS* ds, int index, uint8_t value) {
struct DSMemory* memory = &ds->memory;
struct DSVRAMBankInfo info = _vramInfo[index][value & 0x7]; struct DSVRAMBankInfo info = _vramInfo[index][value & 0x7];
memset(&memory->vramMirror[index], 0, sizeof(memory->vramMirror[index])); memset(&memory->vramMirror[index], 0, sizeof(memory->vramMirror[index]));
memset(&memory->vramMode[index], 0, sizeof(memory->vramMode[index])); memset(&memory->vramMode[index], 0, sizeof(memory->vramMode[index]));
@ -308,6 +315,32 @@ void DSVideoConfigureVRAM(struct DSMemory* memory, int index, uint8_t value) {
memory->vramMirror[index][i + j] = 1 << index; memory->vramMirror[index][i + j] = 1 << index;
} }
} }
switch (info.mode) {
case 0:
for (i = 0; i < size; ++i) {
ds->video.vramABG[offset + i] = &memory->vramBank[index][i << (DS_VRAM_OFFSET - 1)];
ds->video.renderer->vramABG[offset + i] = ds->video.vramABG[offset + i];
}
break;
case 1:
for (i = 0; i < size; ++i) {
ds->video.vramBBG[offset + i] = &memory->vramBank[index][i << (DS_VRAM_OFFSET - 1)];
ds->video.renderer->vramBBG[offset + i] = ds->video.vramBBG[offset + i];
}
break;
case 2:
for (i = 0; i < size; ++i) {
ds->video.vramAOBJ[offset + i] = &memory->vramBank[index][i << (DS_VRAM_OFFSET - 1)];
ds->video.renderer->vramAOBJ[offset + i] = ds->video.vramAOBJ[offset + i];
}
break;
case 3:
for (i = 0; i < size; ++i) {
ds->video.vramBOBJ[offset + i] = &memory->vramBank[index][i << (DS_VRAM_OFFSET - 1)];
ds->video.renderer->vramBOBJ[offset + i] = ds->video.vramBOBJ[offset + i];
}
break;
}
} }
static void DSVideoDummyRendererInit(struct DSVideoRenderer* renderer) { static void DSVideoDummyRendererInit(struct DSVideoRenderer* renderer) {
@ -330,6 +363,12 @@ static uint16_t DSVideoDummyRendererWriteVideoRegister(struct DSVideoRenderer* r
return value; return value;
} }
static void DSVideoDummyRendererWritePalette(struct DSVideoRenderer* renderer, uint32_t address, uint16_t value) {
UNUSED(value);
UNUSED(address);
UNUSED(value);
}
static void DSVideoDummyRendererDrawScanline(struct DSVideoRenderer* renderer, int y) { static void DSVideoDummyRendererDrawScanline(struct DSVideoRenderer* renderer, int y) {
UNUSED(renderer); UNUSED(renderer);
UNUSED(y); UNUSED(y);

View File

@ -108,7 +108,7 @@ int main(int argc, char** argv) {
free(perfOpts.savestate); free(perfOpts.savestate);
} }
_outputBuffer = malloc(256 * 256 * 4); _outputBuffer = malloc(256 * 384 * 4);
if (perfOpts.csv) { if (perfOpts.csv) {
puts("game_code,frames,duration,renderer"); puts("game_code,frames,duration,renderer");
} }