DS Video: Start hooking up software renderer

This commit is contained in:
Vicki Pfau 2017-02-21 16:11:32 -08:00
parent 9f31a1cc2c
commit 5ad7092567
5 changed files with 135 additions and 62 deletions

View File

@ -12,6 +12,7 @@ CXX_GUARD_START
#include <mgba/core/log.h> #include <mgba/core/log.h>
#include <mgba/core/timing.h> #include <mgba/core/timing.h>
#include <mgba/internal/gba/video.h>
mLOG_DECLARE_CATEGORY(DS_VIDEO); mLOG_DECLARE_CATEGORY(DS_VIDEO);
@ -29,6 +30,11 @@ enum {
DS_VIDEO_TOTAL_LENGTH = DS_VIDEO_HORIZONTAL_LENGTH * DS_VIDEO_VERTICAL_TOTAL_PIXELS, DS_VIDEO_TOTAL_LENGTH = DS_VIDEO_HORIZONTAL_LENGTH * DS_VIDEO_VERTICAL_TOTAL_PIXELS,
}; };
union DSOAM {
union GBAOAM oam[2];
uint16_t raw[1024];
};
struct DSVideoRenderer { struct DSVideoRenderer {
void (*init)(struct DSVideoRenderer* renderer); void (*init)(struct DSVideoRenderer* renderer);
void (*reset)(struct DSVideoRenderer* renderer); void (*reset)(struct DSVideoRenderer* renderer);
@ -41,7 +47,9 @@ struct DSVideoRenderer {
void (*getPixels)(struct DSVideoRenderer* renderer, size_t* stride, const void** pixels); void (*getPixels)(struct DSVideoRenderer* renderer, size_t* stride, const void** pixels);
void (*putPixels)(struct DSVideoRenderer* renderer, size_t stride, const void* pixels); void (*putPixels)(struct DSVideoRenderer* renderer, size_t stride, const void* pixels);
uint16_t* palette;
uint16_t* vram; uint16_t* vram;
union DSOAM* oam;
}; };
struct DS; struct DS;
@ -54,7 +62,9 @@ struct DSVideo {
// VCOUNT // VCOUNT
int vcount; int vcount;
uint16_t palette[1024];
uint16_t* vram; uint16_t* vram;
union DSOAM oam;
int32_t frameCounter; int32_t frameCounter;
int frameskip; int frameskip;

View File

@ -386,71 +386,77 @@ 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) {
switch (address) { if (address <= DS9_REG_A_BLDY && (address > DS_REG_VCOUNT || address == DS9_REG_A_DISPCNT_LO || address == DS9_REG_B_DISPCNT_LO)) {
// VRAM control value = ds->video.renderer->writeVideoRegister(ds->video.renderer, address, value);
case DS9_REG_VRAMCNT_A: } 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)) {
case DS9_REG_VRAMCNT_C: value = ds->video.renderer->writeVideoRegister(ds->video.renderer, address, value);
case DS9_REG_VRAMCNT_E: } else {
value &= 0x9F9F; switch (address) {
DSVideoConfigureVRAM(&ds->memory, address - DS9_REG_VRAMCNT_A, value & 0xFF); // VRAM control
DSVideoConfigureVRAM(&ds->memory, address - DS9_REG_VRAMCNT_A + 1, value >> 8); case DS9_REG_VRAMCNT_A:
break; case DS9_REG_VRAMCNT_C:
case DS9_REG_VRAMCNT_G: case DS9_REG_VRAMCNT_E:
value &= 0x9F03; value &= 0x9F9F;
DSVideoConfigureVRAM(&ds->memory, 6, value & 0xFF); DSVideoConfigureVRAM(&ds->memory, address - DS9_REG_VRAMCNT_A, value & 0xFF);
DSConfigureWRAM(&ds->memory, value >> 8); DSVideoConfigureVRAM(&ds->memory, address - DS9_REG_VRAMCNT_A + 1, value >> 8);
break; break;
case DS9_REG_VRAMCNT_H: case DS9_REG_VRAMCNT_G:
value &= 0x9F9F; value &= 0x9F03;
DSVideoConfigureVRAM(&ds->memory, 7, value & 0xFF); DSVideoConfigureVRAM(&ds->memory, 6, value & 0xFF);
DSVideoConfigureVRAM(&ds->memory, 8, value >> 8); DSConfigureWRAM(&ds->memory, value >> 8);
break; break;
case DS9_REG_VRAMCNT_H:
value &= 0x9F9F;
DSVideoConfigureVRAM(&ds->memory, 7, value & 0xFF);
DSVideoConfigureVRAM(&ds->memory, 8, value >> 8);
break;
case DS9_REG_EXMEMCNT: case DS9_REG_EXMEMCNT:
value &= 0xE8FF; value &= 0xE8FF;
DSConfigureExternalMemory(ds, value); DSConfigureExternalMemory(ds, value);
break; break;
// Math // Math
case DS9_REG_DIVCNT: case DS9_REG_DIVCNT:
value = _scheduleDiv(ds, value); value = _scheduleDiv(ds, value);
break; break;
case DS9_REG_DIV_NUMER_0: case DS9_REG_DIV_NUMER_0:
case DS9_REG_DIV_NUMER_1: case DS9_REG_DIV_NUMER_1:
case DS9_REG_DIV_NUMER_2: case DS9_REG_DIV_NUMER_2:
case DS9_REG_DIV_NUMER_3: case DS9_REG_DIV_NUMER_3:
case DS9_REG_DIV_DENOM_0: case DS9_REG_DIV_DENOM_0:
case DS9_REG_DIV_DENOM_1: case DS9_REG_DIV_DENOM_1:
case DS9_REG_DIV_DENOM_2: case DS9_REG_DIV_DENOM_2:
case DS9_REG_DIV_DENOM_3: case DS9_REG_DIV_DENOM_3:
ds->memory.io9[DS9_REG_DIVCNT >> 1] = _scheduleDiv(ds, ds->memory.io9[DS9_REG_DIVCNT >> 1]); ds->memory.io9[DS9_REG_DIVCNT >> 1] = _scheduleDiv(ds, ds->memory.io9[DS9_REG_DIVCNT >> 1]);
break; break;
case DS9_REG_SQRTCNT: case DS9_REG_SQRTCNT:
value = _scheduleSqrt(ds, value); value = _scheduleSqrt(ds, value);
break; break;
case DS9_REG_SQRT_PARAM_0: case DS9_REG_SQRT_PARAM_0:
case DS9_REG_SQRT_PARAM_1: case DS9_REG_SQRT_PARAM_1:
case DS9_REG_SQRT_PARAM_2: case DS9_REG_SQRT_PARAM_2:
case DS9_REG_SQRT_PARAM_3: case DS9_REG_SQRT_PARAM_3:
ds->memory.io9[DS9_REG_SQRTCNT >> 1] = _scheduleSqrt(ds, ds->memory.io9[DS9_REG_SQRTCNT >> 1]); ds->memory.io9[DS9_REG_SQRTCNT >> 1] = _scheduleSqrt(ds, ds->memory.io9[DS9_REG_SQRTCNT >> 1]);
break; break;
default: default:
{ {
uint32_t v2 = DSIOWrite(&ds->ds9, address, value); uint32_t v2 = DSIOWrite(&ds->ds9, address, value);
if (v2 & 0x10000) { if (v2 & 0x10000) {
value = v2; value = v2;
break; break;
} else if (v2 & 0x20000) { } else if (v2 & 0x20000) {
return;
}
}
mLOG(DS_IO, STUB, "Stub DS9 I/O register write: %06X:%04X", address, value);
if (address >= DS7_REG_MAX) {
mLOG(DS_IO, GAME_ERROR, "Write to unused DS9 I/O register: %06X:%04X", address, value);
return; return;
} }
break;
} }
mLOG(DS_IO, STUB, "Stub DS9 I/O register write: %06X:%04X", address, value);
if (address >= DS7_REG_MAX) {
mLOG(DS_IO, GAME_ERROR, "Write to unused DS9 I/O register: %06X:%04X", address, value);
return;
}
break;
} }
ds->memory.io9[address >> 1] = value; ds->memory.io9[address >> 1] = value;
} }

View File

@ -526,8 +526,6 @@ void DS7Store8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCo
} \ } \
} }
uint32_t DS7LoadMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) { uint32_t DS7LoadMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
struct DS* ds = (struct DS*) cpu->master; struct DS* ds = (struct DS*) cpu->master;
struct DSMemory* memory = &ds->memory; struct DSMemory* memory = &ds->memory;
@ -590,7 +588,6 @@ uint32_t DS7LoadMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum L
return address | addressMisalign; return address | addressMisalign;
} }
uint32_t DS7StoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) { uint32_t DS7StoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
struct DS* ds = (struct DS*) cpu->master; struct DS* ds = (struct DS*) cpu->master;
struct DSMemory* memory = &ds->memory; struct DSMemory* memory = &ds->memory;
@ -733,6 +730,9 @@ uint32_t DS9Load32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
case DS_REGION_IO: case DS_REGION_IO:
value = DS9IORead32(ds, address & 0x00FFFFFC); value = DS9IORead32(ds, address & 0x00FFFFFC);
break; break;
case DS9_REGION_PALETTE_RAM:
LOAD_32(value, address & (DS9_SIZE_PALETTE_RAM - 4), ds->video.palette);
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);
int i = 0; int i = 0;
@ -745,6 +745,9 @@ uint32_t DS9Load32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
} }
break; break;
} }
case DS9_REGION_OAM:
LOAD_32(value, address & (DS9_SIZE_OAM - 4), ds->video.oam.raw);
break;
case DS9_REGION_BIOS: case DS9_REGION_BIOS:
// TODO: Fix undersized BIOS // TODO: Fix undersized BIOS
// TODO: Fix masking // TODO: Fix masking
@ -803,6 +806,9 @@ uint32_t DS9Load16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
case DS_REGION_IO: case DS_REGION_IO:
value = DS9IORead(ds, address & DS_OFFSET_MASK); value = DS9IORead(ds, address & DS_OFFSET_MASK);
break; break;
case DS9_REGION_PALETTE_RAM:
LOAD_16(value, address & (DS9_SIZE_PALETTE_RAM - 2), ds->video.palette);
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);
int i = 0; int i = 0;
@ -815,6 +821,9 @@ uint32_t DS9Load16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
} }
break; break;
} }
case DS9_REGION_OAM:
LOAD_16(value, address & (DS9_SIZE_OAM - 2), ds->video.oam.raw);
break;
case DS9_REGION_BIOS: case DS9_REGION_BIOS:
// TODO: Fix undersized BIOS // TODO: Fix undersized BIOS
// TODO: Fix masking // TODO: Fix masking
@ -929,6 +938,9 @@ void DS9Store32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycle
case DS_REGION_IO: case DS_REGION_IO:
DS9IOWrite32(ds, address & DS_OFFSET_MASK, value); DS9IOWrite32(ds, address & DS_OFFSET_MASK, value);
break; break;
case DS9_REGION_PALETTE_RAM:
STORE_32(value, address & (DS9_SIZE_PALETTE_RAM - 4), ds->video.palette);
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);
int i = 0; int i = 0;
@ -939,6 +951,9 @@ void DS9Store32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycle
} }
break; break;
} }
case DS9_REGION_OAM:
STORE_32(value, address & (DS9_SIZE_OAM - 4), ds->video.oam.raw);
break;
default: default:
if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {
STORE_32(value, address & (DS9_SIZE_DTCM - 4), memory->dtcm); STORE_32(value, address & (DS9_SIZE_DTCM - 4), memory->dtcm);
@ -989,6 +1004,9 @@ void DS9Store16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycle
case DS_REGION_IO: case DS_REGION_IO:
DS9IOWrite(ds, address & DS_OFFSET_MASK, value); DS9IOWrite(ds, address & DS_OFFSET_MASK, value);
break; break;
case DS9_REGION_PALETTE_RAM:
STORE_16(value, address & (DS9_SIZE_PALETTE_RAM - 2), ds->video.palette);
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);
int i = 0; int i = 0;
@ -999,6 +1017,9 @@ void DS9Store16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycle
} }
break; break;
} }
case DS9_REGION_OAM:
STORE_16(value, address & (DS9_SIZE_OAM - 2), ds->video.oam.raw);
break;
default: default:
if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {
STORE_16(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm); STORE_16(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm);
@ -1114,6 +1135,9 @@ uint32_t DS9LoadMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum L
case DS_REGION_IO: case DS_REGION_IO:
LDM_LOOP(value = DS9IORead32(ds, address)); LDM_LOOP(value = DS9IORead32(ds, address));
break; break;
case DS9_REGION_PALETTE_RAM:
LDM_LOOP(LOAD_32(value, address & (DS9_SIZE_PALETTE_RAM - 1), ds->video.palette));
break;
case DS_REGION_VRAM: case DS_REGION_VRAM:
LDM_LOOP(unsigned mask = _selectVRAM(memory, address >> DS_VRAM_OFFSET); LDM_LOOP(unsigned mask = _selectVRAM(memory, address >> DS_VRAM_OFFSET);
value = 0; value = 0;
@ -1126,6 +1150,9 @@ uint32_t DS9LoadMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum L
} }
}); });
break; break;
case DS9_REGION_OAM:
LDM_LOOP(LOAD_32(value, address & (DS9_SIZE_OAM - 1), ds->video.oam.raw));
break;
default: default:
LDM_LOOP(if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { LDM_LOOP(if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {
LOAD_32(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm); LOAD_32(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm);
@ -1200,6 +1227,9 @@ uint32_t DS9StoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum
mLOG(DS_MEM, STUB, "Unimplemented DS9 STM: %08X", address); mLOG(DS_MEM, STUB, "Unimplemented DS9 STM: %08X", address);
}); });
break; break;
case DS9_REGION_PALETTE_RAM:
STM_LOOP(STORE_32(value, address & (DS9_SIZE_PALETTE_RAM - 1), ds->video.palette));
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);
int i = 0; int i = 0;
@ -1209,6 +1239,9 @@ uint32_t DS9StoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum
} }
}); });
break; break;
case DS9_REGION_OAM:
STM_LOOP(STORE_32(value, address & (DS9_SIZE_OAM - 1), ds->video.oam.raw));
break;
default: default:
STM_LOOP(if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { STM_LOOP(if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {
STORE_32(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm); STORE_32(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm);

View File

@ -18,22 +18,44 @@ void DSVideoSoftwareRendererCreate(struct DSVideoSoftwareRenderer* renderer) {
renderer->d.init = DSVideoSoftwareRendererInit; renderer->d.init = DSVideoSoftwareRendererInit;
renderer->d.reset = DSVideoSoftwareRendererReset; renderer->d.reset = DSVideoSoftwareRendererReset;
renderer->d.deinit = DSVideoSoftwareRendererDeinit; renderer->d.deinit = DSVideoSoftwareRendererDeinit;
renderer->d.writeVideoRegister = DSVideoSoftwareRendererWriteVideoRegister;
renderer->d.drawScanline = DSVideoSoftwareRendererDrawScanline; renderer->d.drawScanline = DSVideoSoftwareRendererDrawScanline;
renderer->d.finishFrame = DSVideoSoftwareRendererFinishFrame; renderer->d.finishFrame = DSVideoSoftwareRendererFinishFrame;
renderer->d.getPixels = DSVideoSoftwareRendererGetPixels; renderer->d.getPixels = DSVideoSoftwareRendererGetPixels;
renderer->d.putPixels = DSVideoSoftwareRendererPutPixels; renderer->d.putPixels = DSVideoSoftwareRendererPutPixels;
renderer->engA.d.cache = NULL;
GBAVideoSoftwareRendererCreate(&renderer->engA);
renderer->engB.d.cache = NULL;
GBAVideoSoftwareRendererCreate(&renderer->engB);
} }
static void DSVideoSoftwareRendererInit(struct DSVideoRenderer* renderer) { static void DSVideoSoftwareRendererInit(struct DSVideoRenderer* renderer) {
struct DSVideoSoftwareRenderer* softwareRenderer = (struct DSVideoSoftwareRenderer*) renderer;
softwareRenderer->engA.d.palette = &renderer->palette[0];
softwareRenderer->engA.d.oam = &renderer->oam->oam[0];
// TODO: VRAM
softwareRenderer->engB.d.palette = &renderer->palette[512];
softwareRenderer->engB.d.oam = &renderer->oam->oam[1];
// TODO: VRAM
DSVideoSoftwareRendererReset(renderer);
} }
static void DSVideoSoftwareRendererReset(struct DSVideoRenderer* renderer) { static void DSVideoSoftwareRendererReset(struct DSVideoRenderer* renderer) {
struct DSVideoSoftwareRenderer* softwareRenderer = (struct DSVideoSoftwareRenderer*) renderer;
softwareRenderer->engA.d.reset(&softwareRenderer->engA.d);
softwareRenderer->engB.d.reset(&softwareRenderer->engB.d);
} }
static void DSVideoSoftwareRendererDeinit(struct DSVideoRenderer* renderer) { static void DSVideoSoftwareRendererDeinit(struct DSVideoRenderer* renderer) {
struct DSVideoSoftwareRenderer* softwareRenderer = (struct DSVideoSoftwareRenderer*) renderer;
softwareRenderer->engA.d.deinit(&softwareRenderer->engA.d);
softwareRenderer->engB.d.deinit(&softwareRenderer->engB.d);
} }
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) {
mLOG(DS_VIDEO, STUB, "Stub video register write: %04X:%04X", address, value);
return value; return value;
} }

View File

@ -158,7 +158,9 @@ void DSVideoReset(struct DSVideo* video) {
void DSVideoAssociateRenderer(struct DSVideo* video, struct DSVideoRenderer* renderer) { void DSVideoAssociateRenderer(struct DSVideo* video, struct DSVideoRenderer* renderer) {
video->renderer->deinit(video->renderer); video->renderer->deinit(video->renderer);
video->renderer = renderer; video->renderer = renderer;
renderer->palette = video->palette;
renderer->vram = video->vram; renderer->vram = video->vram;
renderer->oam = &video->oam;
video->renderer->init(video->renderer); video->renderer->init(video->renderer);
} }