mirror of https://github.com/mgba-emu/mgba.git
DS Video: Start hooking up software renderer
This commit is contained in:
parent
9f31a1cc2c
commit
5ad7092567
|
@ -12,6 +12,7 @@ CXX_GUARD_START
|
|||
|
||||
#include <mgba/core/log.h>
|
||||
#include <mgba/core/timing.h>
|
||||
#include <mgba/internal/gba/video.h>
|
||||
|
||||
mLOG_DECLARE_CATEGORY(DS_VIDEO);
|
||||
|
||||
|
@ -29,6 +30,11 @@ enum {
|
|||
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 {
|
||||
void (*init)(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 (*putPixels)(struct DSVideoRenderer* renderer, size_t stride, const void* pixels);
|
||||
|
||||
uint16_t* palette;
|
||||
uint16_t* vram;
|
||||
union DSOAM* oam;
|
||||
};
|
||||
|
||||
struct DS;
|
||||
|
@ -54,7 +62,9 @@ struct DSVideo {
|
|||
// VCOUNT
|
||||
int vcount;
|
||||
|
||||
uint16_t palette[1024];
|
||||
uint16_t* vram;
|
||||
union DSOAM oam;
|
||||
|
||||
int32_t frameCounter;
|
||||
int frameskip;
|
||||
|
|
124
src/ds/io.c
124
src/ds/io.c
|
@ -386,71 +386,77 @@ void DS9IOInit(struct DS* ds) {
|
|||
}
|
||||
|
||||
void DS9IOWrite(struct DS* ds, uint32_t address, uint16_t value) {
|
||||
switch (address) {
|
||||
// VRAM control
|
||||
case DS9_REG_VRAMCNT_A:
|
||||
case DS9_REG_VRAMCNT_C:
|
||||
case DS9_REG_VRAMCNT_E:
|
||||
value &= 0x9F9F;
|
||||
DSVideoConfigureVRAM(&ds->memory, address - DS9_REG_VRAMCNT_A, value & 0xFF);
|
||||
DSVideoConfigureVRAM(&ds->memory, address - DS9_REG_VRAMCNT_A + 1, value >> 8);
|
||||
break;
|
||||
case DS9_REG_VRAMCNT_G:
|
||||
value &= 0x9F03;
|
||||
DSVideoConfigureVRAM(&ds->memory, 6, value & 0xFF);
|
||||
DSConfigureWRAM(&ds->memory, value >> 8);
|
||||
break;
|
||||
case DS9_REG_VRAMCNT_H:
|
||||
value &= 0x9F9F;
|
||||
DSVideoConfigureVRAM(&ds->memory, 7, value & 0xFF);
|
||||
DSVideoConfigureVRAM(&ds->memory, 8, value >> 8);
|
||||
break;
|
||||
if (address <= DS9_REG_A_BLDY && (address > DS_REG_VCOUNT || address == DS9_REG_A_DISPCNT_LO || address == DS9_REG_B_DISPCNT_LO)) {
|
||||
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)) {
|
||||
value = ds->video.renderer->writeVideoRegister(ds->video.renderer, address, value);
|
||||
} else {
|
||||
switch (address) {
|
||||
// VRAM control
|
||||
case DS9_REG_VRAMCNT_A:
|
||||
case DS9_REG_VRAMCNT_C:
|
||||
case DS9_REG_VRAMCNT_E:
|
||||
value &= 0x9F9F;
|
||||
DSVideoConfigureVRAM(&ds->memory, address - DS9_REG_VRAMCNT_A, value & 0xFF);
|
||||
DSVideoConfigureVRAM(&ds->memory, address - DS9_REG_VRAMCNT_A + 1, value >> 8);
|
||||
break;
|
||||
case DS9_REG_VRAMCNT_G:
|
||||
value &= 0x9F03;
|
||||
DSVideoConfigureVRAM(&ds->memory, 6, value & 0xFF);
|
||||
DSConfigureWRAM(&ds->memory, value >> 8);
|
||||
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:
|
||||
value &= 0xE8FF;
|
||||
DSConfigureExternalMemory(ds, value);
|
||||
break;
|
||||
case DS9_REG_EXMEMCNT:
|
||||
value &= 0xE8FF;
|
||||
DSConfigureExternalMemory(ds, value);
|
||||
break;
|
||||
|
||||
// Math
|
||||
case DS9_REG_DIVCNT:
|
||||
value = _scheduleDiv(ds, value);
|
||||
break;
|
||||
case DS9_REG_DIV_NUMER_0:
|
||||
case DS9_REG_DIV_NUMER_1:
|
||||
case DS9_REG_DIV_NUMER_2:
|
||||
case DS9_REG_DIV_NUMER_3:
|
||||
case DS9_REG_DIV_DENOM_0:
|
||||
case DS9_REG_DIV_DENOM_1:
|
||||
case DS9_REG_DIV_DENOM_2:
|
||||
case DS9_REG_DIV_DENOM_3:
|
||||
ds->memory.io9[DS9_REG_DIVCNT >> 1] = _scheduleDiv(ds, ds->memory.io9[DS9_REG_DIVCNT >> 1]);
|
||||
break;
|
||||
case DS9_REG_SQRTCNT:
|
||||
value = _scheduleSqrt(ds, value);
|
||||
break;
|
||||
case DS9_REG_SQRT_PARAM_0:
|
||||
case DS9_REG_SQRT_PARAM_1:
|
||||
case DS9_REG_SQRT_PARAM_2:
|
||||
case DS9_REG_SQRT_PARAM_3:
|
||||
ds->memory.io9[DS9_REG_SQRTCNT >> 1] = _scheduleSqrt(ds, ds->memory.io9[DS9_REG_SQRTCNT >> 1]);
|
||||
break;
|
||||
// Math
|
||||
case DS9_REG_DIVCNT:
|
||||
value = _scheduleDiv(ds, value);
|
||||
break;
|
||||
case DS9_REG_DIV_NUMER_0:
|
||||
case DS9_REG_DIV_NUMER_1:
|
||||
case DS9_REG_DIV_NUMER_2:
|
||||
case DS9_REG_DIV_NUMER_3:
|
||||
case DS9_REG_DIV_DENOM_0:
|
||||
case DS9_REG_DIV_DENOM_1:
|
||||
case DS9_REG_DIV_DENOM_2:
|
||||
case DS9_REG_DIV_DENOM_3:
|
||||
ds->memory.io9[DS9_REG_DIVCNT >> 1] = _scheduleDiv(ds, ds->memory.io9[DS9_REG_DIVCNT >> 1]);
|
||||
break;
|
||||
case DS9_REG_SQRTCNT:
|
||||
value = _scheduleSqrt(ds, value);
|
||||
break;
|
||||
case DS9_REG_SQRT_PARAM_0:
|
||||
case DS9_REG_SQRT_PARAM_1:
|
||||
case DS9_REG_SQRT_PARAM_2:
|
||||
case DS9_REG_SQRT_PARAM_3:
|
||||
ds->memory.io9[DS9_REG_SQRTCNT >> 1] = _scheduleSqrt(ds, ds->memory.io9[DS9_REG_SQRTCNT >> 1]);
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
uint32_t v2 = DSIOWrite(&ds->ds9, address, value);
|
||||
if (v2 & 0x10000) {
|
||||
value = v2;
|
||||
break;
|
||||
} else if (v2 & 0x20000) {
|
||||
default:
|
||||
{
|
||||
uint32_t v2 = DSIOWrite(&ds->ds9, address, value);
|
||||
if (v2 & 0x10000) {
|
||||
value = v2;
|
||||
break;
|
||||
} 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
struct DS* ds = (struct DS*) cpu->master;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
@ -733,6 +730,9 @@ uint32_t DS9Load32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
|||
case DS_REGION_IO:
|
||||
value = DS9IORead32(ds, address & 0x00FFFFFC);
|
||||
break;
|
||||
case DS9_REGION_PALETTE_RAM:
|
||||
LOAD_32(value, address & (DS9_SIZE_PALETTE_RAM - 4), ds->video.palette);
|
||||
break;
|
||||
case DS_REGION_VRAM: {
|
||||
unsigned mask = _selectVRAM(memory, address >> DS_VRAM_OFFSET);
|
||||
int i = 0;
|
||||
|
@ -745,6 +745,9 @@ uint32_t DS9Load32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case DS9_REGION_OAM:
|
||||
LOAD_32(value, address & (DS9_SIZE_OAM - 4), ds->video.oam.raw);
|
||||
break;
|
||||
case DS9_REGION_BIOS:
|
||||
// TODO: Fix undersized BIOS
|
||||
// TODO: Fix masking
|
||||
|
@ -803,6 +806,9 @@ uint32_t DS9Load16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
|||
case DS_REGION_IO:
|
||||
value = DS9IORead(ds, address & DS_OFFSET_MASK);
|
||||
break;
|
||||
case DS9_REGION_PALETTE_RAM:
|
||||
LOAD_16(value, address & (DS9_SIZE_PALETTE_RAM - 2), ds->video.palette);
|
||||
break;
|
||||
case DS_REGION_VRAM: {
|
||||
unsigned mask = _selectVRAM(memory, address >> DS_VRAM_OFFSET);
|
||||
int i = 0;
|
||||
|
@ -815,6 +821,9 @@ uint32_t DS9Load16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case DS9_REGION_OAM:
|
||||
LOAD_16(value, address & (DS9_SIZE_OAM - 2), ds->video.oam.raw);
|
||||
break;
|
||||
case DS9_REGION_BIOS:
|
||||
// TODO: Fix undersized BIOS
|
||||
// TODO: Fix masking
|
||||
|
@ -929,6 +938,9 @@ void DS9Store32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycle
|
|||
case DS_REGION_IO:
|
||||
DS9IOWrite32(ds, address & DS_OFFSET_MASK, value);
|
||||
break;
|
||||
case DS9_REGION_PALETTE_RAM:
|
||||
STORE_32(value, address & (DS9_SIZE_PALETTE_RAM - 4), ds->video.palette);
|
||||
break;
|
||||
case DS_REGION_VRAM: {
|
||||
unsigned mask = _selectVRAM(memory, address >> DS_VRAM_OFFSET);
|
||||
int i = 0;
|
||||
|
@ -939,6 +951,9 @@ void DS9Store32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycle
|
|||
}
|
||||
break;
|
||||
}
|
||||
case DS9_REGION_OAM:
|
||||
STORE_32(value, address & (DS9_SIZE_OAM - 4), ds->video.oam.raw);
|
||||
break;
|
||||
default:
|
||||
if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {
|
||||
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:
|
||||
DS9IOWrite(ds, address & DS_OFFSET_MASK, value);
|
||||
break;
|
||||
case DS9_REGION_PALETTE_RAM:
|
||||
STORE_16(value, address & (DS9_SIZE_PALETTE_RAM - 2), ds->video.palette);
|
||||
break;
|
||||
case DS_REGION_VRAM: {
|
||||
unsigned mask = _selectVRAM(memory, address >> DS_VRAM_OFFSET);
|
||||
int i = 0;
|
||||
|
@ -999,6 +1017,9 @@ void DS9Store16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycle
|
|||
}
|
||||
break;
|
||||
}
|
||||
case DS9_REGION_OAM:
|
||||
STORE_16(value, address & (DS9_SIZE_OAM - 2), ds->video.oam.raw);
|
||||
break;
|
||||
default:
|
||||
if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {
|
||||
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:
|
||||
LDM_LOOP(value = DS9IORead32(ds, address));
|
||||
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:
|
||||
LDM_LOOP(unsigned mask = _selectVRAM(memory, address >> DS_VRAM_OFFSET);
|
||||
value = 0;
|
||||
|
@ -1126,6 +1150,9 @@ uint32_t DS9LoadMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum L
|
|||
}
|
||||
});
|
||||
break;
|
||||
case DS9_REGION_OAM:
|
||||
LDM_LOOP(LOAD_32(value, address & (DS9_SIZE_OAM - 1), ds->video.oam.raw));
|
||||
break;
|
||||
default:
|
||||
LDM_LOOP(if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {
|
||||
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);
|
||||
});
|
||||
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:
|
||||
STM_LOOP(unsigned mask = _selectVRAM(memory, address >> DS_VRAM_OFFSET);
|
||||
int i = 0;
|
||||
|
@ -1209,6 +1239,9 @@ uint32_t DS9StoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum
|
|||
}
|
||||
});
|
||||
break;
|
||||
case DS9_REGION_OAM:
|
||||
STM_LOOP(STORE_32(value, address & (DS9_SIZE_OAM - 1), ds->video.oam.raw));
|
||||
break;
|
||||
default:
|
||||
STM_LOOP(if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {
|
||||
STORE_32(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm);
|
||||
|
|
|
@ -18,22 +18,44 @@ void DSVideoSoftwareRendererCreate(struct DSVideoSoftwareRenderer* renderer) {
|
|||
renderer->d.init = DSVideoSoftwareRendererInit;
|
||||
renderer->d.reset = DSVideoSoftwareRendererReset;
|
||||
renderer->d.deinit = DSVideoSoftwareRendererDeinit;
|
||||
renderer->d.writeVideoRegister = DSVideoSoftwareRendererWriteVideoRegister;
|
||||
renderer->d.drawScanline = DSVideoSoftwareRendererDrawScanline;
|
||||
renderer->d.finishFrame = DSVideoSoftwareRendererFinishFrame;
|
||||
renderer->d.getPixels = DSVideoSoftwareRendererGetPixels;
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
mLOG(DS_VIDEO, STUB, "Stub video register write: %04X:%04X", address, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
|
|
@ -158,7 +158,9 @@ void DSVideoReset(struct DSVideo* video) {
|
|||
void DSVideoAssociateRenderer(struct DSVideo* video, struct DSVideoRenderer* renderer) {
|
||||
video->renderer->deinit(video->renderer);
|
||||
video->renderer = renderer;
|
||||
renderer->palette = video->palette;
|
||||
renderer->vram = video->vram;
|
||||
renderer->oam = &video->oam;
|
||||
video->renderer->init(video->renderer);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue