mirror of https://github.com/mgba-emu/mgba.git
DS Video: Add extended BG palettes
This commit is contained in:
parent
242e3c6ec5
commit
a9ca1221f2
|
@ -27,6 +27,11 @@ struct DSVideoSoftwareRenderer {
|
||||||
int outputBufferStride;
|
int outputBufferStride;
|
||||||
|
|
||||||
uint32_t row[DS_VIDEO_HORIZONTAL_PIXELS];
|
uint32_t row[DS_VIDEO_HORIZONTAL_PIXELS];
|
||||||
|
|
||||||
|
color_t extPaletteA[16384];
|
||||||
|
color_t extPaletteB[16384];
|
||||||
|
color_t variantPaletteA[16384];
|
||||||
|
color_t variantPaletteB[16384];
|
||||||
};
|
};
|
||||||
|
|
||||||
void DSVideoSoftwareRendererCreate(struct DSVideoSoftwareRenderer* renderer);
|
void DSVideoSoftwareRendererCreate(struct DSVideoSoftwareRenderer* renderer);
|
||||||
|
|
|
@ -57,11 +57,15 @@ DECL_BITS(DSRegisterDISPCNT, TileBoundary, 20, 2);
|
||||||
DECL_BITS(DSRegisterDISPCNT, CharBase, 24, 3);
|
DECL_BITS(DSRegisterDISPCNT, CharBase, 24, 3);
|
||||||
DECL_BITS(DSRegisterDISPCNT, ScreenBase, 27, 3);
|
DECL_BITS(DSRegisterDISPCNT, ScreenBase, 27, 3);
|
||||||
// TODO
|
// TODO
|
||||||
|
DECL_BIT(DSRegisterDISPCNT, BgExtPalette, 30);
|
||||||
|
DECL_BIT(DSRegisterDISPCNT, ObjExtPalette, 31);
|
||||||
|
|
||||||
DECL_BITFIELD(DSRegisterPOWCNT1, uint16_t);
|
DECL_BITFIELD(DSRegisterPOWCNT1, uint16_t);
|
||||||
// TODO
|
// TODO
|
||||||
DECL_BIT(DSRegisterPOWCNT1, Swap, 15);
|
DECL_BIT(DSRegisterPOWCNT1, Swap, 15);
|
||||||
|
|
||||||
|
DECL_BIT(GBARegisterBGCNT, ExtPaletteSlot, 13);
|
||||||
|
|
||||||
struct DSVideoRenderer {
|
struct DSVideoRenderer {
|
||||||
void (*init)(struct DSVideoRenderer* renderer);
|
void (*init)(struct DSVideoRenderer* renderer);
|
||||||
void (*reset)(struct DSVideoRenderer* renderer);
|
void (*reset)(struct DSVideoRenderer* renderer);
|
||||||
|
@ -70,6 +74,7 @@ struct DSVideoRenderer {
|
||||||
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 (*writePalette)(struct DSVideoRenderer* renderer, uint32_t address, uint16_t value);
|
||||||
void (*writeOAM)(struct DSVideoRenderer* renderer, uint32_t oam);
|
void (*writeOAM)(struct DSVideoRenderer* renderer, uint32_t oam);
|
||||||
|
void (*invalidateExtPal)(struct DSVideoRenderer* renderer, bool obj, bool engB, int slot);
|
||||||
void (*drawScanline)(struct DSVideoRenderer* renderer, int y);
|
void (*drawScanline)(struct DSVideoRenderer* renderer, int y);
|
||||||
void (*finishFrame)(struct DSVideoRenderer* renderer);
|
void (*finishFrame)(struct DSVideoRenderer* renderer);
|
||||||
|
|
||||||
|
@ -80,8 +85,12 @@ struct DSVideoRenderer {
|
||||||
uint16_t* vram;
|
uint16_t* vram;
|
||||||
uint16_t* vramABG[32];
|
uint16_t* vramABG[32];
|
||||||
uint16_t* vramAOBJ[32];
|
uint16_t* vramAOBJ[32];
|
||||||
|
uint16_t* vramABGExtPal[4];
|
||||||
|
uint16_t* vramAOBJExtPal[4];
|
||||||
uint16_t* vramBBG[32];
|
uint16_t* vramBBG[32];
|
||||||
uint16_t* vramBOBJ[32];
|
uint16_t* vramBOBJ[32];
|
||||||
|
uint16_t* vramBBGExtPal[4];
|
||||||
|
uint16_t* vramBOBJExtPal[4];
|
||||||
union DSOAM* oam;
|
union DSOAM* oam;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -99,8 +108,12 @@ struct DSVideo {
|
||||||
uint16_t* vram;
|
uint16_t* vram;
|
||||||
uint16_t* vramABG[32];
|
uint16_t* vramABG[32];
|
||||||
uint16_t* vramAOBJ[32];
|
uint16_t* vramAOBJ[32];
|
||||||
|
uint16_t* vramABGExtPal[4];
|
||||||
|
uint16_t* vramAOBJExtPal[4];
|
||||||
uint16_t* vramBBG[32];
|
uint16_t* vramBBG[32];
|
||||||
uint16_t* vramBOBJ[32];
|
uint16_t* vramBOBJ[32];
|
||||||
|
uint16_t* vramBBGExtPal[4];
|
||||||
|
uint16_t* vramBOBJExtPal[4];
|
||||||
union DSOAM oam;
|
union DSOAM oam;
|
||||||
|
|
||||||
int32_t frameCounter;
|
int32_t frameCounter;
|
||||||
|
@ -117,7 +130,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 DS* ds, int index, uint8_t value);
|
void DSVideoConfigureVRAM(struct DS* ds, int index, uint8_t value, uint8_t oldValue);
|
||||||
|
|
||||||
CXX_GUARD_START
|
CXX_GUARD_START
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,8 @@ struct GBAVideoSoftwareBackground {
|
||||||
int16_t dmy;
|
int16_t dmy;
|
||||||
int32_t sx;
|
int32_t sx;
|
||||||
int32_t sy;
|
int32_t sy;
|
||||||
|
color_t* extPalette;
|
||||||
|
color_t* variantPalette;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum BlendEffect {
|
enum BlendEffect {
|
||||||
|
@ -116,7 +118,7 @@ struct GBAVideoSoftwareRenderer {
|
||||||
|
|
||||||
uint32_t* temporaryBuffer;
|
uint32_t* temporaryBuffer;
|
||||||
|
|
||||||
GBARegisterDISPCNT dispcnt;
|
uint32_t dispcnt;
|
||||||
|
|
||||||
uint32_t row[256];
|
uint32_t row[256];
|
||||||
uint32_t spriteLayer[256];
|
uint32_t spriteLayer[256];
|
||||||
|
|
14
src/ds/io.c
14
src/ds/io.c
|
@ -424,24 +424,28 @@ void DS9IOWrite(struct DS* ds, uint32_t address, uint16_t value) {
|
||||||
} else if (address >= DS9_REG_B_DISPCNT_LO && address <= DS9_REG_B_BLDY) {
|
} 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 {
|
||||||
|
uint16_t oldValue;
|
||||||
switch (address) {
|
switch (address) {
|
||||||
// VRAM control
|
// VRAM control
|
||||||
case DS9_REG_VRAMCNT_A:
|
case DS9_REG_VRAMCNT_A:
|
||||||
case DS9_REG_VRAMCNT_C:
|
case DS9_REG_VRAMCNT_C:
|
||||||
case DS9_REG_VRAMCNT_E:
|
case DS9_REG_VRAMCNT_E:
|
||||||
|
oldValue = ds->memory.io9[address >> 1];
|
||||||
value &= 0x9F9F;
|
value &= 0x9F9F;
|
||||||
DSVideoConfigureVRAM(ds, address - DS9_REG_VRAMCNT_A, value & 0xFF);
|
DSVideoConfigureVRAM(ds, address - DS9_REG_VRAMCNT_A, value & 0xFF, oldValue & 0xFF);
|
||||||
DSVideoConfigureVRAM(ds, address - DS9_REG_VRAMCNT_A + 1, value >> 8);
|
DSVideoConfigureVRAM(ds, address - DS9_REG_VRAMCNT_A + 1, value >> 8, oldValue >> 8);
|
||||||
break;
|
break;
|
||||||
case DS9_REG_VRAMCNT_G:
|
case DS9_REG_VRAMCNT_G:
|
||||||
|
oldValue = ds->memory.io9[address >> 1];
|
||||||
value &= 0x9F03;
|
value &= 0x9F03;
|
||||||
DSVideoConfigureVRAM(ds, 6, value & 0xFF);
|
DSVideoConfigureVRAM(ds, 6, value & 0xFF, oldValue & 0xFF);
|
||||||
DSConfigureWRAM(&ds->memory, value >> 8);
|
DSConfigureWRAM(&ds->memory, value >> 8);
|
||||||
break;
|
break;
|
||||||
case DS9_REG_VRAMCNT_H:
|
case DS9_REG_VRAMCNT_H:
|
||||||
|
oldValue = ds->memory.io9[address >> 1];
|
||||||
value &= 0x9F9F;
|
value &= 0x9F9F;
|
||||||
DSVideoConfigureVRAM(ds, 7, value & 0xFF);
|
DSVideoConfigureVRAM(ds, 7, value & 0xFF, oldValue & 0xFF);
|
||||||
DSVideoConfigureVRAM(ds, 8, value >> 8);
|
DSVideoConfigureVRAM(ds, 8, value >> 8, oldValue >> 8);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DS9_REG_EXMEMCNT:
|
case DS9_REG_EXMEMCNT:
|
||||||
|
|
|
@ -202,15 +202,15 @@ void DSMemoryReset(struct DS* ds) {
|
||||||
DSSPIReset(ds);
|
DSSPIReset(ds);
|
||||||
DSSlot1Reset(ds);
|
DSSlot1Reset(ds);
|
||||||
|
|
||||||
DSVideoConfigureVRAM(ds, 0, 0);
|
DSVideoConfigureVRAM(ds, 0, 0, 1);
|
||||||
DSVideoConfigureVRAM(ds, 1, 0);
|
DSVideoConfigureVRAM(ds, 1, 0, 1);
|
||||||
DSVideoConfigureVRAM(ds, 2, 0);
|
DSVideoConfigureVRAM(ds, 2, 0, 1);
|
||||||
DSVideoConfigureVRAM(ds, 3, 0);
|
DSVideoConfigureVRAM(ds, 3, 0, 1);
|
||||||
DSVideoConfigureVRAM(ds, 4, 0);
|
DSVideoConfigureVRAM(ds, 4, 0, 1);
|
||||||
DSVideoConfigureVRAM(ds, 5, 0);
|
DSVideoConfigureVRAM(ds, 5, 0, 1);
|
||||||
DSVideoConfigureVRAM(ds, 6, 0);
|
DSVideoConfigureVRAM(ds, 6, 0, 1);
|
||||||
DSVideoConfigureVRAM(ds, 7, 0);
|
DSVideoConfigureVRAM(ds, 7, 0, 1);
|
||||||
DSVideoConfigureVRAM(ds, 8, 0);
|
DSVideoConfigureVRAM(ds, 8, 0, 1);
|
||||||
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) {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* 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 "gba/renderers/software-private.h"
|
||||||
|
|
||||||
#include <mgba/internal/arm/macros.h>
|
#include <mgba/internal/arm/macros.h>
|
||||||
#include <mgba/internal/ds/io.h>
|
#include <mgba/internal/ds/io.h>
|
||||||
|
@ -14,11 +15,61 @@ 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 DSVideoSoftwareRendererWritePalette(struct DSVideoRenderer* renderer, uint32_t address, uint16_t value);
|
||||||
static void DSVideoSoftwareRendererWriteOAM(struct DSVideoRenderer* renderer, uint32_t oam);
|
static void DSVideoSoftwareRendererWriteOAM(struct DSVideoRenderer* renderer, uint32_t oam);
|
||||||
|
static void DSVideoSoftwareRendererInvalidateExtPal(struct DSVideoRenderer* renderer, bool obj, bool engB, int slot);
|
||||||
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);
|
||||||
static void DSVideoSoftwareRendererPutPixels(struct DSVideoRenderer* renderer, size_t stride, const void* pixels);
|
static void DSVideoSoftwareRendererPutPixels(struct DSVideoRenderer* renderer, size_t stride, const void* pixels);
|
||||||
|
|
||||||
|
static bool _regenerateExtPalette(struct DSVideoSoftwareRenderer* renderer, bool engB, int slot) {
|
||||||
|
color_t* palette;
|
||||||
|
color_t* variantPalette;
|
||||||
|
struct GBAVideoSoftwareRenderer* softwareRenderer;
|
||||||
|
uint16_t* vram;
|
||||||
|
if (!engB) {
|
||||||
|
palette = &renderer->extPaletteA[slot * 4096];
|
||||||
|
variantPalette = &renderer->variantPaletteA[slot * 4096];
|
||||||
|
softwareRenderer = &renderer->engA;
|
||||||
|
vram = renderer->d.vramABGExtPal[slot];
|
||||||
|
} else {
|
||||||
|
palette = &renderer->extPaletteB[slot * 4096];
|
||||||
|
variantPalette = &renderer->variantPaletteB[slot * 4096];
|
||||||
|
softwareRenderer = &renderer->engB;
|
||||||
|
vram = renderer->d.vramBBGExtPal[slot];
|
||||||
|
}
|
||||||
|
if (!vram) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 4096; ++i) {
|
||||||
|
uint16_t value = vram[i];
|
||||||
|
#ifdef COLOR_16_BIT
|
||||||
|
#ifdef COLOR_5_6_5
|
||||||
|
unsigned color = 0;
|
||||||
|
color |= (value & 0x001F) << 11;
|
||||||
|
color |= (value & 0x03E0) << 1;
|
||||||
|
color |= (value & 0x7C00) >> 10;
|
||||||
|
#else
|
||||||
|
unsigned color = value;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
unsigned color = 0;
|
||||||
|
color |= (value << 3) & 0xF8;
|
||||||
|
color |= (value << 6) & 0xF800;
|
||||||
|
color |= (value << 9) & 0xF80000;
|
||||||
|
color |= (color >> 5) & 0x070707;
|
||||||
|
#endif
|
||||||
|
palette[i] = color;
|
||||||
|
if (softwareRenderer->blendEffect == BLEND_BRIGHTEN) {
|
||||||
|
variantPalette[i] = _brighten(color, softwareRenderer->bldy);
|
||||||
|
} else if (softwareRenderer->blendEffect == BLEND_DARKEN) {
|
||||||
|
variantPalette[i] = _darken(color, softwareRenderer->bldy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DSVideoSoftwareRendererCreate(struct DSVideoSoftwareRenderer* renderer) {
|
void DSVideoSoftwareRendererCreate(struct DSVideoSoftwareRenderer* renderer) {
|
||||||
renderer->d.init = DSVideoSoftwareRendererInit;
|
renderer->d.init = DSVideoSoftwareRendererInit;
|
||||||
renderer->d.reset = DSVideoSoftwareRendererReset;
|
renderer->d.reset = DSVideoSoftwareRendererReset;
|
||||||
|
@ -26,6 +77,7 @@ void DSVideoSoftwareRendererCreate(struct DSVideoSoftwareRenderer* renderer) {
|
||||||
renderer->d.writeVideoRegister = DSVideoSoftwareRendererWriteVideoRegister;
|
renderer->d.writeVideoRegister = DSVideoSoftwareRendererWriteVideoRegister;
|
||||||
renderer->d.writePalette = DSVideoSoftwareRendererWritePalette;
|
renderer->d.writePalette = DSVideoSoftwareRendererWritePalette;
|
||||||
renderer->d.writeOAM = DSVideoSoftwareRendererWriteOAM;
|
renderer->d.writeOAM = DSVideoSoftwareRendererWriteOAM;
|
||||||
|
renderer->d.invalidateExtPal = DSVideoSoftwareRendererInvalidateExtPal;
|
||||||
renderer->d.drawScanline = DSVideoSoftwareRendererDrawScanline;
|
renderer->d.drawScanline = DSVideoSoftwareRendererDrawScanline;
|
||||||
renderer->d.finishFrame = DSVideoSoftwareRendererFinishFrame;
|
renderer->d.finishFrame = DSVideoSoftwareRendererFinishFrame;
|
||||||
renderer->d.getPixels = DSVideoSoftwareRendererGetPixels;
|
renderer->d.getPixels = DSVideoSoftwareRendererGetPixels;
|
||||||
|
@ -75,6 +127,25 @@ static void DSVideoSoftwareRendererUpdateDISPCNTA(struct DSVideoSoftwareRenderer
|
||||||
fakeDispcnt = GBARegisterDISPCNTFillObjCharacterMapping(fakeDispcnt);
|
fakeDispcnt = GBARegisterDISPCNTFillObjCharacterMapping(fakeDispcnt);
|
||||||
}
|
}
|
||||||
softwareRenderer->engA.d.writeVideoRegister(&softwareRenderer->engA.d, DS9_REG_A_DISPCNT_LO, fakeDispcnt);
|
softwareRenderer->engA.d.writeVideoRegister(&softwareRenderer->engA.d, DS9_REG_A_DISPCNT_LO, fakeDispcnt);
|
||||||
|
softwareRenderer->engA.dispcnt |= softwareRenderer->dispcntA & 0xFFFF000;
|
||||||
|
if (DSRegisterDISPCNTIsBgExtPalette(softwareRenderer->dispcntA)) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
// TODO: Regenerate on change
|
||||||
|
int slot = i;
|
||||||
|
if (i < 2 && GBARegisterBGCNTIsExtPaletteSlot(softwareRenderer->engA.bg[i].control)) {
|
||||||
|
slot += 2;
|
||||||
|
}
|
||||||
|
if (softwareRenderer->engA.bg[i].extPalette != &softwareRenderer->extPaletteA[slot * 4096] && _regenerateExtPalette(softwareRenderer, false, slot)) {
|
||||||
|
softwareRenderer->engA.bg[i].extPalette = &softwareRenderer->extPaletteA[slot * 4096];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
softwareRenderer->engA.bg[0].extPalette = NULL;
|
||||||
|
softwareRenderer->engA.bg[1].extPalette = NULL;
|
||||||
|
softwareRenderer->engA.bg[2].extPalette = NULL;
|
||||||
|
softwareRenderer->engA.bg[3].extPalette = NULL;
|
||||||
|
}
|
||||||
uint32_t charBase = DSRegisterDISPCNTGetCharBase(softwareRenderer->dispcntA) << 16;
|
uint32_t charBase = DSRegisterDISPCNTGetCharBase(softwareRenderer->dispcntA) << 16;
|
||||||
uint32_t screenBase = DSRegisterDISPCNTGetScreenBase(softwareRenderer->dispcntA) << 16;
|
uint32_t screenBase = DSRegisterDISPCNTGetScreenBase(softwareRenderer->dispcntA) << 16;
|
||||||
softwareRenderer->engA.d.writeVideoRegister(&softwareRenderer->engA.d, DS9_REG_A_BG0CNT, softwareRenderer->engA.bg[0].control);
|
softwareRenderer->engA.d.writeVideoRegister(&softwareRenderer->engA.d, DS9_REG_A_BG0CNT, softwareRenderer->engA.bg[0].control);
|
||||||
|
@ -96,6 +167,7 @@ static void DSVideoSoftwareRendererUpdateDISPCNTA(struct DSVideoSoftwareRenderer
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DSVideoSoftwareRendererUpdateDISPCNTB(struct DSVideoSoftwareRenderer* softwareRenderer) {
|
static void DSVideoSoftwareRendererUpdateDISPCNTB(struct DSVideoSoftwareRenderer* softwareRenderer) {
|
||||||
|
// TODO: Share code with DISPCNTA
|
||||||
uint16_t fakeDispcnt = softwareRenderer->dispcntB & 0xFF87;
|
uint16_t fakeDispcnt = softwareRenderer->dispcntB & 0xFF87;
|
||||||
if (!DSRegisterDISPCNTIsTileObjMapping(softwareRenderer->dispcntB)) {
|
if (!DSRegisterDISPCNTIsTileObjMapping(softwareRenderer->dispcntB)) {
|
||||||
softwareRenderer->engB.tileStride = 0x20;
|
softwareRenderer->engB.tileStride = 0x20;
|
||||||
|
@ -104,6 +176,25 @@ static void DSVideoSoftwareRendererUpdateDISPCNTB(struct DSVideoSoftwareRenderer
|
||||||
fakeDispcnt = GBARegisterDISPCNTFillObjCharacterMapping(fakeDispcnt);
|
fakeDispcnt = GBARegisterDISPCNTFillObjCharacterMapping(fakeDispcnt);
|
||||||
}
|
}
|
||||||
softwareRenderer->engB.d.writeVideoRegister(&softwareRenderer->engB.d, DS9_REG_A_DISPCNT_LO, fakeDispcnt);
|
softwareRenderer->engB.d.writeVideoRegister(&softwareRenderer->engB.d, DS9_REG_A_DISPCNT_LO, fakeDispcnt);
|
||||||
|
softwareRenderer->engB.dispcnt |= softwareRenderer->dispcntB & 0xFFFF000;
|
||||||
|
if (DSRegisterDISPCNTIsBgExtPalette(softwareRenderer->dispcntB)) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
// TODO: Regenerate on change
|
||||||
|
int slot = i;
|
||||||
|
if (i < 2 && GBARegisterBGCNTIsExtPaletteSlot(softwareRenderer->engB.bg[i].control)) {
|
||||||
|
slot += 2;
|
||||||
|
}
|
||||||
|
if (softwareRenderer->engB.bg[i].extPalette != &softwareRenderer->extPaletteB[slot * 4096] && _regenerateExtPalette(softwareRenderer, true, slot)) {
|
||||||
|
softwareRenderer->engB.bg[i].extPalette = &softwareRenderer->extPaletteB[slot * 4096];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
softwareRenderer->engA.bg[0].extPalette = NULL;
|
||||||
|
softwareRenderer->engA.bg[1].extPalette = NULL;
|
||||||
|
softwareRenderer->engA.bg[2].extPalette = NULL;
|
||||||
|
softwareRenderer->engA.bg[3].extPalette = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
@ -161,6 +252,89 @@ static void DSVideoSoftwareRendererWriteOAM(struct DSVideoRenderer* renderer, ui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void DSVideoSoftwareRendererInvalidateExtPal(struct DSVideoRenderer* renderer, bool obj, bool engB, int slot) {
|
||||||
|
struct DSVideoSoftwareRenderer* softwareRenderer = (struct DSVideoSoftwareRenderer*) renderer;
|
||||||
|
_regenerateExtPalette(softwareRenderer, engB, slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DSVideoSoftwareRendererDrawGBAScanline(struct GBAVideoRenderer* renderer, int y) {
|
||||||
|
struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer;
|
||||||
|
|
||||||
|
color_t* row = &softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * y];
|
||||||
|
if (GBARegisterDISPCNTIsForcedBlank(softwareRenderer->dispcnt)) {
|
||||||
|
int x;
|
||||||
|
for (x = 0; x < softwareRenderer->masterEnd; ++x) {
|
||||||
|
row[x] = GBA_COLOR_WHITE;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GBAVideoSoftwareRendererPreprocessBuffer(softwareRenderer, y);
|
||||||
|
int spriteLayers = GBAVideoSoftwareRendererPreprocessSpriteLayer(softwareRenderer, y);
|
||||||
|
|
||||||
|
int w;
|
||||||
|
unsigned priority;
|
||||||
|
for (priority = 0; priority < 4; ++priority) {
|
||||||
|
softwareRenderer->end = 0;
|
||||||
|
for (w = 0; w < softwareRenderer->nWindows; ++w) {
|
||||||
|
softwareRenderer->start = softwareRenderer->end;
|
||||||
|
softwareRenderer->end = softwareRenderer->windows[w].endX;
|
||||||
|
softwareRenderer->currentWindow = softwareRenderer->windows[w].control;
|
||||||
|
if (spriteLayers & (1 << priority)) {
|
||||||
|
GBAVideoSoftwareRendererPostprocessSprite(softwareRenderer, priority);
|
||||||
|
}
|
||||||
|
if (TEST_LAYER_ENABLED(0)) {
|
||||||
|
GBAVideoSoftwareRendererDrawBackgroundMode0(softwareRenderer, &softwareRenderer->bg[0], y);
|
||||||
|
}
|
||||||
|
if (TEST_LAYER_ENABLED(1)) {
|
||||||
|
GBAVideoSoftwareRendererDrawBackgroundMode0(softwareRenderer, &softwareRenderer->bg[1], y);
|
||||||
|
}
|
||||||
|
if (TEST_LAYER_ENABLED(2)) {
|
||||||
|
switch (GBARegisterDISPCNTGetMode(softwareRenderer->dispcnt)) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
case 3:
|
||||||
|
GBAVideoSoftwareRendererDrawBackgroundMode0(softwareRenderer, &softwareRenderer->bg[2], y);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
case 4:
|
||||||
|
GBAVideoSoftwareRendererDrawBackgroundMode2(softwareRenderer, &softwareRenderer->bg[2], y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (TEST_LAYER_ENABLED(3)) {
|
||||||
|
switch (GBARegisterDISPCNTGetMode(softwareRenderer->dispcnt)) {
|
||||||
|
case 0:
|
||||||
|
GBAVideoSoftwareRendererDrawBackgroundMode0(softwareRenderer, &softwareRenderer->bg[3], y);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
GBAVideoSoftwareRendererDrawBackgroundMode2(softwareRenderer, &softwareRenderer->bg[3], y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
softwareRenderer->bg[2].sx += softwareRenderer->bg[2].dmx;
|
||||||
|
softwareRenderer->bg[2].sy += softwareRenderer->bg[2].dmy;
|
||||||
|
softwareRenderer->bg[3].sx += softwareRenderer->bg[3].dmx;
|
||||||
|
softwareRenderer->bg[3].sy += softwareRenderer->bg[3].dmy;
|
||||||
|
|
||||||
|
GBAVideoSoftwareRendererPostprocessBuffer(softwareRenderer);
|
||||||
|
|
||||||
|
#ifdef COLOR_16_BIT
|
||||||
|
#if defined(__ARM_NEON) && !defined(__APPLE__)
|
||||||
|
_to16Bit(row, softwareRenderer->row, softwareRenderer->masterEnd);
|
||||||
|
#else
|
||||||
|
for (x = 0; x < softwareRenderer->masterEnd; ++x) {
|
||||||
|
row[x] = softwareRenderer->row[x];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
memcpy(row, softwareRenderer->row, softwareRenderer->masterEnd * sizeof(*row));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void _drawScanlineA(struct DSVideoSoftwareRenderer* softwareRenderer, int y) {
|
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.vramBG, softwareRenderer->d.vramABG, sizeof(softwareRenderer->engA.d.vramBG));
|
||||||
memcpy(softwareRenderer->engA.d.vramOBJ, softwareRenderer->d.vramAOBJ, sizeof(softwareRenderer->engA.d.vramOBJ));
|
memcpy(softwareRenderer->engA.d.vramOBJ, softwareRenderer->d.vramAOBJ, sizeof(softwareRenderer->engA.d.vramOBJ));
|
||||||
|
@ -174,7 +348,7 @@ static void _drawScanlineA(struct DSVideoSoftwareRenderer* softwareRenderer, int
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case 1:
|
case 1:
|
||||||
softwareRenderer->engA.d.drawScanline(&softwareRenderer->engA.d, y);
|
DSVideoSoftwareRendererDrawGBAScanline(&softwareRenderer->engA.d, y);
|
||||||
return;
|
return;
|
||||||
case 2: {
|
case 2: {
|
||||||
uint16_t* vram = &softwareRenderer->d.vram[0x10000 * DSRegisterDISPCNTGetVRAMBlock(softwareRenderer->dispcntA)];
|
uint16_t* vram = &softwareRenderer->d.vram[0x10000 * DSRegisterDISPCNTGetVRAMBlock(softwareRenderer->dispcntA)];
|
||||||
|
@ -229,7 +403,7 @@ static void _drawScanlineB(struct DSVideoSoftwareRenderer* softwareRenderer, int
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case 1:
|
case 1:
|
||||||
softwareRenderer->engB.d.drawScanline(&softwareRenderer->engB.d, y);
|
DSVideoSoftwareRendererDrawGBAScanline(&softwareRenderer->engB.d, y);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
203
src/ds/video.c
203
src/ds/video.c
|
@ -20,6 +20,7 @@ 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 DSVideoDummyRendererWritePalette(struct DSVideoRenderer* renderer, uint32_t address, uint16_t value);
|
||||||
static void DSVideoDummyRendererWriteOAM(struct DSVideoRenderer* renderer, uint32_t oam);
|
static void DSVideoDummyRendererWriteOAM(struct DSVideoRenderer* renderer, uint32_t oam);
|
||||||
|
static void DSVideoDummyRendererInvalidateExtPal(struct DSVideoRenderer* renderer, bool obj, bool engB, int slot);
|
||||||
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);
|
||||||
|
@ -42,60 +43,86 @@ static const uint32_t _vramSize[9] = {
|
||||||
0x04000
|
0x04000
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum DSVRAMBankMode {
|
||||||
|
MODE_A_BG = 0,
|
||||||
|
MODE_B_BG = 1,
|
||||||
|
MODE_A_OBJ = 2,
|
||||||
|
MODE_B_OBJ = 3,
|
||||||
|
MODE_LCDC,
|
||||||
|
MODE_7_VRAM,
|
||||||
|
MODE_A_BG_EXT_PAL,
|
||||||
|
MODE_B_BG_EXT_PAL,
|
||||||
|
MODE_A_OBJ_EXT_PAL,
|
||||||
|
MODE_B_OBJ_EXT_PAL,
|
||||||
|
MODE_3D_TEX,
|
||||||
|
MODE_3D_TEX_PAL,
|
||||||
|
};
|
||||||
|
|
||||||
const struct DSVRAMBankInfo {
|
const struct DSVRAMBankInfo {
|
||||||
int base;
|
int base;
|
||||||
uint32_t mirrorSize;
|
uint32_t mirrorSize;
|
||||||
int mode;
|
enum DSVRAMBankMode mode;
|
||||||
int offset[4];
|
int offset[4];
|
||||||
} _vramInfo[9][8] = {
|
} _vramInfo[9][8] = {
|
||||||
{ // A
|
{ // A
|
||||||
{ 0x000, 0x40, 4 }, // LCDC
|
{ 0x000, 0x40, MODE_LCDC },
|
||||||
{ 0x000, 0x20, 0, { 0x00, 0x08, 0x10, 0x18 } }, // A-BG
|
{ 0x000, 0x20, MODE_A_BG, { 0x00, 0x08, 0x10, 0x18 } },
|
||||||
{ 0x000, 0x10, 2, { 0x00, 0x08, 0x80, 0x80 } }, // A-OBJ
|
{ 0x000, 0x10, MODE_A_OBJ, { 0x00, 0x08, 0x80, 0x80 } },
|
||||||
|
{ 0x000, 0x10, MODE_3D_TEX, { 0x00, 0x01, 0x02, 0x03 } },
|
||||||
},
|
},
|
||||||
{ // B
|
{ // B
|
||||||
{ 0x008, 0x40, 4 }, // LCDC
|
{ 0x008, 0x40, MODE_LCDC },
|
||||||
{ 0x000, 0x20, 0, { 0x00, 0x08, 0x10, 0x18 } }, // A-BG
|
{ 0x000, 0x20, MODE_A_BG, { 0x00, 0x08, 0x10, 0x18 } },
|
||||||
{ 0x000, 0x10, 2, { 0x00, 0x08, 0x80, 0x80 } }, // A-OBJ
|
{ 0x000, 0x10, MODE_A_OBJ, { 0x00, 0x08, 0x80, 0x80 } },
|
||||||
|
{ 0x000, 0x10, MODE_3D_TEX, { 0x00, 0x01, 0x02, 0x03 } },
|
||||||
},
|
},
|
||||||
{ // C
|
{ // C
|
||||||
{ 0x010, 0x40, 4 }, // LCDC
|
{ 0x010, 0x40, MODE_LCDC },
|
||||||
{ 0x000, 0x20, 0, { 0x00, 0x08, 0x10, 0x18 } }, // A-BG
|
{ 0x000, 0x20, MODE_A_BG, { 0x00, 0x08, 0x10, 0x18 } },
|
||||||
{ 0x000, 0x40, 5, { 0x00, 0x08, 0x80, 0x80 } }, // 7-VRAM
|
{ 0x000, 0x40, MODE_7_VRAM, { 0x00, 0x08, 0x80, 0x80 } },
|
||||||
{},
|
{ 0x000, 0x10, MODE_3D_TEX, { 0x00, 0x01, 0x02, 0x03 } },
|
||||||
{ 0x000, 0x08, 1 }, // B-BG
|
{ 0x000, 0x08, MODE_B_BG },
|
||||||
},
|
},
|
||||||
{ // D
|
{ // D
|
||||||
{ 0x018, 0x40, 4 }, // LCDC
|
{ 0x018, 0x40, MODE_LCDC },
|
||||||
{ 0x000, 0x20, 0, { 0x00, 0x08, 0x10, 0x18 } }, // A-BG
|
{ 0x000, 0x20, MODE_A_BG, { 0x00, 0x08, 0x10, 0x18 } },
|
||||||
{ 0x000, 0x40, 8, { 0x00, 0x08, 0x80, 0x80 } }, // 7-VRAM
|
{ 0x000, 0x40, MODE_7_VRAM, { 0x00, 0x08, 0x80, 0x80 } },
|
||||||
{},
|
{ 0x000, 0x10, MODE_3D_TEX, { 0x00, 0x01, 0x02, 0x03 } },
|
||||||
{ 0x000, 0x08, 3 }, // B-OBJ
|
{ 0x000, 0x08, MODE_B_OBJ },
|
||||||
},
|
},
|
||||||
{ // E
|
{ // E
|
||||||
{ 0x020, 0x40, 4 }, // LCDC
|
{ 0x020, 0x40, MODE_LCDC },
|
||||||
{ 0x000, 0x20, 0 }, // A-BG
|
{ 0x000, 0x20, MODE_A_BG },
|
||||||
{ 0x000, 0x10, 2 }, // A-OBJ
|
{ 0x000, 0x10, MODE_A_OBJ },
|
||||||
|
{ 0x000, 0x04, MODE_3D_TEX_PAL },
|
||||||
|
{ 0x000, 0x04, MODE_A_BG_EXT_PAL },
|
||||||
},
|
},
|
||||||
{ // F
|
{ // F
|
||||||
{ 0x024, 0x40, 4 }, // LCDC
|
{ 0x024, 0x40, MODE_LCDC },
|
||||||
{ 0x000, 0x20, 0, { 0x00, 0x01, 0x04, 0x05 } }, // A-BG
|
{ 0x000, 0x20, MODE_A_BG, { 0x00, 0x01, 0x04, 0x05 } },
|
||||||
{ 0x000, 0x10, 2, { 0x00, 0x01, 0x04, 0x05 } }, // A-OBJ
|
{ 0x000, 0x10, MODE_A_OBJ, { 0x00, 0x01, 0x04, 0x05 } },
|
||||||
|
{ 0x000, 0x01, MODE_3D_TEX_PAL, { 0x00, 0x01, 0x04, 0x05 } },
|
||||||
|
{ 0x000, 0x02, MODE_A_BG_EXT_PAL, { 0x00, 0x02, 0x00, 0x02 } },
|
||||||
|
{ 0x000, 0x01, MODE_A_OBJ_EXT_PAL},
|
||||||
},
|
},
|
||||||
{ // G
|
{ // G
|
||||||
{ 0x025, 0x40, 4 }, // LCDC
|
{ 0x025, 0x40, MODE_LCDC },
|
||||||
{ 0x000, 0x20, 0 }, // A-BG
|
{ 0x000, 0x20, MODE_A_BG, { 0x00, 0x01, 0x04, 0x05 } },
|
||||||
{ 0x000, 0x10, 2 }, // A-OBJ
|
{ 0x000, 0x10, MODE_A_OBJ, { 0x00, 0x01, 0x04, 0x05 } },
|
||||||
|
{ 0x000, 0x01, MODE_3D_TEX_PAL, { 0x00, 0x01, 0x04, 0x05 } },
|
||||||
|
{ 0x000, 0x02, MODE_A_BG_EXT_PAL, { 0x00, 0x02, 0x00, 0x02 } },
|
||||||
|
{ 0x000, 0x01, MODE_A_OBJ_EXT_PAL},
|
||||||
},
|
},
|
||||||
{ // H
|
{ // H
|
||||||
{ 0x026, 0x40, 4 }, // LCDC
|
{ 0x026, 0x40, MODE_LCDC },
|
||||||
{ 0x000, 0x04, 1 }, // B-BG
|
{ 0x000, 0x04, MODE_B_BG },
|
||||||
{ 0x000, 0x10, 2 }, // A-OBJ
|
{ 0x000, 0x04, MODE_B_BG_EXT_PAL },
|
||||||
},
|
},
|
||||||
{ // I
|
{ // I
|
||||||
{ 0x028, 0x40, 4 }, // LCDC
|
{ 0x028, 0x40, MODE_LCDC },
|
||||||
{ 0x002, 0x04, 1 }, // B-BG
|
{ 0x002, 0x04, MODE_B_BG },
|
||||||
{ 0x000, 0x01, 3 }, // B-OBJ
|
{ 0x000, 0x01, MODE_B_OBJ },
|
||||||
|
{ 0x000, 0x01, MODE_B_OBJ_EXT_PAL },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -166,8 +193,12 @@ void DSVideoAssociateRenderer(struct DSVideo* video, struct DSVideoRenderer* ren
|
||||||
renderer->vram = video->vram;
|
renderer->vram = video->vram;
|
||||||
memcpy(renderer->vramABG, video->vramABG, sizeof(renderer->vramABG));
|
memcpy(renderer->vramABG, video->vramABG, sizeof(renderer->vramABG));
|
||||||
memcpy(renderer->vramAOBJ, video->vramAOBJ, sizeof(renderer->vramAOBJ));
|
memcpy(renderer->vramAOBJ, video->vramAOBJ, sizeof(renderer->vramAOBJ));
|
||||||
|
memcpy(renderer->vramABGExtPal, video->vramABGExtPal, sizeof(renderer->vramABGExtPal));
|
||||||
|
memcpy(renderer->vramAOBJExtPal, video->vramAOBJExtPal, sizeof(renderer->vramAOBJExtPal));
|
||||||
memcpy(renderer->vramBBG, video->vramBBG, sizeof(renderer->vramBBG));
|
memcpy(renderer->vramBBG, video->vramBBG, sizeof(renderer->vramBBG));
|
||||||
memcpy(renderer->vramBOBJ, video->vramBOBJ, sizeof(renderer->vramBOBJ));
|
memcpy(renderer->vramBOBJ, video->vramBOBJ, sizeof(renderer->vramBOBJ));
|
||||||
|
memcpy(renderer->vramBBGExtPal, video->vramBBGExtPal, sizeof(renderer->vramBBGExtPal));
|
||||||
|
memcpy(renderer->vramBOBJExtPal, video->vramBOBJExtPal, sizeof(renderer->vramBOBJExtPal));
|
||||||
renderer->oam = &video->oam;
|
renderer->oam = &video->oam;
|
||||||
video->renderer->init(video->renderer);
|
video->renderer->init(video->renderer);
|
||||||
}
|
}
|
||||||
|
@ -300,18 +331,83 @@ 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 DS* ds, int index, uint8_t value) {
|
void DSVideoConfigureVRAM(struct DS* ds, int index, uint8_t value, uint8_t oldValue) {
|
||||||
struct DSMemory* memory = &ds->memory;
|
struct DSMemory* memory = &ds->memory;
|
||||||
|
if (value == oldValue) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint32_t i, j;
|
||||||
|
uint32_t size = _vramSize[index] >> DS_VRAM_OFFSET;
|
||||||
|
struct DSVRAMBankInfo oldInfo = _vramInfo[index][oldValue & 0x7];
|
||||||
|
uint32_t offset = oldInfo.base + oldInfo.offset[(oldValue >> 3) & 3];
|
||||||
|
switch (oldInfo.mode) {
|
||||||
|
case MODE_A_BG:
|
||||||
|
for (i = 0; i < size; ++i) {
|
||||||
|
if (ds->video.vramABG[offset + i] == &memory->vramBank[index][i << (DS_VRAM_OFFSET - 1)]) {
|
||||||
|
ds->video.vramABG[offset + i] = NULL;
|
||||||
|
ds->video.renderer->vramABG[offset + i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MODE_B_BG:
|
||||||
|
for (i = 0; i < size; ++i) {
|
||||||
|
if (ds->video.vramBBG[offset + i] == &memory->vramBank[index][i << (DS_VRAM_OFFSET - 1)]) {
|
||||||
|
ds->video.vramBBG[offset + i] = NULL;
|
||||||
|
ds->video.renderer->vramBBG[offset + i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MODE_A_OBJ:
|
||||||
|
for (i = 0; i < size; ++i) {
|
||||||
|
if (ds->video.vramAOBJ[offset + i] == &memory->vramBank[index][i << (DS_VRAM_OFFSET - 1)]) {
|
||||||
|
ds->video.vramAOBJ[offset + i] = NULL;
|
||||||
|
ds->video.renderer->vramAOBJ[offset + i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MODE_B_OBJ:
|
||||||
|
for (i = 0; i < size; ++i) {
|
||||||
|
if (ds->video.vramBOBJ[offset + i] == &memory->vramBank[index][i << (DS_VRAM_OFFSET - 1)]) {
|
||||||
|
ds->video.vramBOBJ[offset + i] = NULL;
|
||||||
|
ds->video.renderer->vramBOBJ[offset + i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MODE_A_BG_EXT_PAL:
|
||||||
|
for (i = 0; i < oldInfo.mirrorSize; ++i) {
|
||||||
|
if (ds->video.vramABGExtPal[offset + i] == &memory->vramBank[index][i << 12]) {
|
||||||
|
ds->video.vramABGExtPal[offset + i] = NULL;
|
||||||
|
ds->video.renderer->vramABGExtPal[offset + i] = NULL;
|
||||||
|
ds->video.renderer->invalidateExtPal(ds->video.renderer, false, false, offset + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MODE_B_BG_EXT_PAL:
|
||||||
|
for (i = 0; i < oldInfo.mirrorSize; ++i) {
|
||||||
|
if (ds->video.vramBBGExtPal[offset + i] == &memory->vramBank[index][i << 12]) {
|
||||||
|
ds->video.vramBBGExtPal[offset + i] = NULL;
|
||||||
|
ds->video.renderer->vramBBGExtPal[offset + i] = NULL;
|
||||||
|
ds->video.renderer->invalidateExtPal(ds->video.renderer, false, true, offset + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MODE_7_VRAM:
|
||||||
|
for (i = 0; i < size; i += 16) {
|
||||||
|
ds->memory.vram7[(offset + i) >> 4] = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MODE_LCDC:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
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]));
|
||||||
if (!(value & 0x80) || !info.mirrorSize) {
|
if (!(value & 0x80) || !info.mirrorSize) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint32_t size = _vramSize[index] >> DS_VRAM_OFFSET;
|
offset = info.base + info.offset[(value >> 3) & 3];
|
||||||
uint32_t i, j;
|
if (info.mode <= MODE_LCDC) {
|
||||||
uint32_t offset = info.base + info.offset[(value >> 3) & 3];
|
|
||||||
if (info.mode < 4) {
|
|
||||||
memory->vramMode[index][info.mode] = 0xFFFF;
|
memory->vramMode[index][info.mode] = 0xFFFF;
|
||||||
for (j = offset; j < 0x40; j += info.mirrorSize) {
|
for (j = offset; j < 0x40; j += info.mirrorSize) {
|
||||||
for (i = 0; i < size; ++i) {
|
for (i = 0; i < size; ++i) {
|
||||||
|
@ -320,35 +416,51 @@ void DSVideoConfigureVRAM(struct DS* ds, int index, uint8_t value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (info.mode) {
|
switch (info.mode) {
|
||||||
case 0:
|
case MODE_A_BG:
|
||||||
for (i = 0; i < size; ++i) {
|
for (i = 0; i < size; ++i) {
|
||||||
ds->video.vramABG[offset + i] = &memory->vramBank[index][i << (DS_VRAM_OFFSET - 1)];
|
ds->video.vramABG[offset + i] = &memory->vramBank[index][i << (DS_VRAM_OFFSET - 1)];
|
||||||
ds->video.renderer->vramABG[offset + i] = ds->video.vramABG[offset + i];
|
ds->video.renderer->vramABG[offset + i] = ds->video.vramABG[offset + i];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case MODE_B_BG:
|
||||||
for (i = 0; i < size; ++i) {
|
for (i = 0; i < size; ++i) {
|
||||||
ds->video.vramBBG[offset + i] = &memory->vramBank[index][i << (DS_VRAM_OFFSET - 1)];
|
ds->video.vramBBG[offset + i] = &memory->vramBank[index][i << (DS_VRAM_OFFSET - 1)];
|
||||||
ds->video.renderer->vramBBG[offset + i] = ds->video.vramBBG[offset + i];
|
ds->video.renderer->vramBBG[offset + i] = ds->video.vramBBG[offset + i];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case MODE_A_OBJ:
|
||||||
for (i = 0; i < size; ++i) {
|
for (i = 0; i < size; ++i) {
|
||||||
ds->video.vramAOBJ[offset + i] = &memory->vramBank[index][i << (DS_VRAM_OFFSET - 1)];
|
ds->video.vramAOBJ[offset + i] = &memory->vramBank[index][i << (DS_VRAM_OFFSET - 1)];
|
||||||
ds->video.renderer->vramAOBJ[offset + i] = ds->video.vramAOBJ[offset + i];
|
ds->video.renderer->vramAOBJ[offset + i] = ds->video.vramAOBJ[offset + i];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case MODE_B_OBJ:
|
||||||
for (i = 0; i < size; ++i) {
|
for (i = 0; i < size; ++i) {
|
||||||
ds->video.vramBOBJ[offset + i] = &memory->vramBank[index][i << (DS_VRAM_OFFSET - 1)];
|
ds->video.vramBOBJ[offset + i] = &memory->vramBank[index][i << (DS_VRAM_OFFSET - 1)];
|
||||||
ds->video.renderer->vramBOBJ[offset + i] = ds->video.vramBOBJ[offset + i];
|
ds->video.renderer->vramBOBJ[offset + i] = ds->video.vramBOBJ[offset + i];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 5:
|
case MODE_A_BG_EXT_PAL:
|
||||||
|
for (i = 0; i < info.mirrorSize; ++i) {
|
||||||
|
ds->video.vramABGExtPal[offset + i] = &memory->vramBank[index][i << 12];
|
||||||
|
ds->video.renderer->vramABGExtPal[offset + i] = ds->video.vramABGExtPal[offset + i];
|
||||||
|
ds->video.renderer->invalidateExtPal(ds->video.renderer, false, false, offset + i);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MODE_B_BG_EXT_PAL:
|
||||||
|
for (i = 0; i < info.mirrorSize; ++i) {
|
||||||
|
ds->video.vramBBGExtPal[offset + i] = &memory->vramBank[index][i << 12];
|
||||||
|
ds->video.renderer->vramBBGExtPal[offset + i] = ds->video.vramBBGExtPal[offset + i];
|
||||||
|
ds->video.renderer->invalidateExtPal(ds->video.renderer, false, true, offset + i);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MODE_7_VRAM:
|
||||||
for (i = 0; i < size; i += 16) {
|
for (i = 0; i < size; i += 16) {
|
||||||
ds->memory.vram7[(offset + i) >> 4] = &memory->vramBank[index][i << (DS_VRAM_OFFSET - 5)];
|
ds->memory.vram7[(offset + i) >> 4] = &memory->vramBank[index][i << (DS_VRAM_OFFSET - 5)];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case MODE_LCDC:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,6 +497,13 @@ static void DSVideoDummyRendererWriteOAM(struct DSVideoRenderer* renderer, uint3
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void DSVideoDummyRendererInvalidateExtPal(struct DSVideoRenderer* renderer, bool obj, bool engB, int slot) {
|
||||||
|
UNUSED(renderer);
|
||||||
|
UNUSED(obj);
|
||||||
|
UNUSED(engB);
|
||||||
|
// Nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
static void DSVideoDummyRendererDrawScanline(struct DSVideoRenderer* renderer, int y) {
|
static void DSVideoDummyRendererDrawScanline(struct DSVideoRenderer* renderer, int y) {
|
||||||
UNUSED(renderer);
|
UNUSED(renderer);
|
||||||
UNUSED(y);
|
UNUSED(y);
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
} \
|
} \
|
||||||
screenBase = background->screenBase + yBase + (xBase >> 2); \
|
screenBase = background->screenBase + yBase + (xBase >> 2); \
|
||||||
uint16_t* screenBlock = renderer->d.vramBG[screenBase >> VRAM_BLOCK_OFFSET]; \
|
uint16_t* screenBlock = renderer->d.vramBG[screenBase >> VRAM_BLOCK_OFFSET]; \
|
||||||
|
if (UNLIKELY(!screenBlock)) { \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
LOAD_16(mapData, screenBase & VRAM_BLOCK_MASK, screenBlock); \
|
LOAD_16(mapData, screenBase & VRAM_BLOCK_MASK, screenBlock); \
|
||||||
localY = inY & 0x7; \
|
localY = inY & 0x7; \
|
||||||
if (GBA_TEXT_MAP_VFLIP(mapData)) { \
|
if (GBA_TEXT_MAP_VFLIP(mapData)) { \
|
||||||
|
@ -361,6 +364,195 @@
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define DRAW_BACKGROUND_MODE_0_TILE_SUFFIX_256Ext(BLEND, OBJWIN) \
|
||||||
|
paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 8; \
|
||||||
|
palette = &mainPalette[paletteData]; \
|
||||||
|
charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \
|
||||||
|
vram = renderer->d.vramBG[charBase >> VRAM_BLOCK_OFFSET]; \
|
||||||
|
int end2 = end - 4; \
|
||||||
|
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
|
||||||
|
int shift = inX & 0x3; \
|
||||||
|
if (LIKELY(vram)) { \
|
||||||
|
if (end2 > outX) { \
|
||||||
|
LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \
|
||||||
|
tileData >>= 8 * shift; \
|
||||||
|
shift = 0; \
|
||||||
|
for (; outX < end2; ++outX, ++pixel) { \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
if (LIKELY(vram)) { \
|
||||||
|
LOAD_32(tileData, (charBase + 4) & VRAM_BLOCK_MASK, vram); \
|
||||||
|
tileData >>= 8 * shift; \
|
||||||
|
for (; outX < end; ++outX, ++pixel) { \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} else { \
|
||||||
|
int start = outX; \
|
||||||
|
outX = end - 1; \
|
||||||
|
pixel = &renderer->row[outX]; \
|
||||||
|
if (LIKELY(vram)) { \
|
||||||
|
if (end2 > start) { \
|
||||||
|
LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \
|
||||||
|
for (; outX >= end2; --outX, --pixel) { \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
|
||||||
|
} \
|
||||||
|
charBase += 4; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
if (LIKELY(vram)) { \
|
||||||
|
LOAD_32(tileData, charBase, vram); \
|
||||||
|
for (; outX >= renderer->start; --outX, --pixel) { \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
outX = end; \
|
||||||
|
pixel = &renderer->row[outX]; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DRAW_BACKGROUND_MODE_0_TILE_PREFIX_256Ext(BLEND, OBJWIN) \
|
||||||
|
charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \
|
||||||
|
vram = renderer->d.vramBG[charBase >> VRAM_BLOCK_OFFSET]; \
|
||||||
|
if (UNLIKELY(!vram)) { \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 8; \
|
||||||
|
palette = &mainPalette[paletteData]; \
|
||||||
|
int end = mod8 - 4; \
|
||||||
|
pixel = &renderer->row[outX]; \
|
||||||
|
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
|
||||||
|
if (end > 0) { \
|
||||||
|
LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \
|
||||||
|
for (; outX < renderer->end - end; ++outX, ++pixel) { \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
|
||||||
|
} \
|
||||||
|
charBase += 4; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \
|
||||||
|
for (; outX < renderer->end; ++outX, ++pixel) { \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
|
||||||
|
} \
|
||||||
|
} else { \
|
||||||
|
int shift = (8 - mod8) & 0x3; \
|
||||||
|
int start = outX; \
|
||||||
|
outX = renderer->end - 1; \
|
||||||
|
pixel = &renderer->row[outX]; \
|
||||||
|
if (end > 0) { \
|
||||||
|
LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \
|
||||||
|
tileData >>= 8 * shift; \
|
||||||
|
for (; outX >= start + 4; --outX, --pixel) { \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
|
||||||
|
} \
|
||||||
|
shift = 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
LOAD_32(tileData, (charBase + 4) & VRAM_BLOCK_MASK, vram); \
|
||||||
|
tileData >>= 8 * shift; \
|
||||||
|
for (; outX >= start; --outX, --pixel) { \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
|
||||||
|
} \
|
||||||
|
/* Needed for consistency checks */ \
|
||||||
|
if (VIDEO_CHECKS) { \
|
||||||
|
outX = renderer->end; \
|
||||||
|
pixel = &renderer->row[outX]; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DRAW_BACKGROUND_MODE_0_TILES_256Ext(BLEND, OBJWIN) \
|
||||||
|
for (; tileX < tileEnd; ++tileX) { \
|
||||||
|
BACKGROUND_TEXT_SELECT_CHARACTER; \
|
||||||
|
paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 8; \
|
||||||
|
palette = &mainPalette[paletteData]; \
|
||||||
|
charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \
|
||||||
|
vram = renderer->d.vramBG[charBase >> VRAM_BLOCK_OFFSET]; \
|
||||||
|
if (UNLIKELY(!vram)) { \
|
||||||
|
pixel += 8; \
|
||||||
|
continue; \
|
||||||
|
} \
|
||||||
|
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
|
||||||
|
LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \
|
||||||
|
if (tileData) { \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 1); \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 2); \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 3); \
|
||||||
|
} \
|
||||||
|
pixel += 4; \
|
||||||
|
LOAD_32(tileData, (charBase + 4) & VRAM_BLOCK_MASK, vram); \
|
||||||
|
if (tileData) { \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 1); \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 2); \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 3); \
|
||||||
|
} \
|
||||||
|
pixel += 4; \
|
||||||
|
} else { \
|
||||||
|
LOAD_32(tileData, (charBase + 4) & VRAM_BLOCK_MASK, vram); \
|
||||||
|
if (tileData) { \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 3); \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 2); \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 1); \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
|
||||||
|
} \
|
||||||
|
pixel += 4; \
|
||||||
|
LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \
|
||||||
|
if (tileData) { \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 3); \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 2); \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 1); \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
|
||||||
|
} \
|
||||||
|
pixel += 4; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DRAW_BACKGROUND_MODE_0_MOSAIC_256Ext(BLEND, OBJWIN) \
|
||||||
|
for (; tileX < tileEnd; ++tileX) { \
|
||||||
|
BACKGROUND_TEXT_SELECT_CHARACTER; \
|
||||||
|
charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \
|
||||||
|
vram = renderer->d.vramBG[charBase >> VRAM_BLOCK_OFFSET]; \
|
||||||
|
tileData = carryData; \
|
||||||
|
for (x = 0; x < 8; ++x) { \
|
||||||
|
if (!mosaicWait) { \
|
||||||
|
if (UNLIKELY(!vram)) { \
|
||||||
|
carryData = 0; \
|
||||||
|
} else { \
|
||||||
|
paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 8; \
|
||||||
|
palette = &mainPalette[paletteData]; \
|
||||||
|
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
|
||||||
|
if (x >= 4) { \
|
||||||
|
LOAD_32(tileData, (charBase + 4) & VRAM_BLOCK_MASK, vram); \
|
||||||
|
tileData >>= (x - 4) * 8; \
|
||||||
|
} else { \
|
||||||
|
LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \
|
||||||
|
tileData >>= x * 8; \
|
||||||
|
} \
|
||||||
|
} else { \
|
||||||
|
if (x >= 4) { \
|
||||||
|
LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \
|
||||||
|
tileData >>= (7 - x) * 8; \
|
||||||
|
} else { \
|
||||||
|
LOAD_32(tileData, (charBase + 4) & VRAM_BLOCK_MASK, vram); \
|
||||||
|
tileData >>= (3 - x) * 8; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
tileData &= 0xFF; \
|
||||||
|
carryData = tileData; \
|
||||||
|
} \
|
||||||
|
mosaicWait = mosaicH; \
|
||||||
|
} \
|
||||||
|
tileData |= tileData << 8; \
|
||||||
|
--mosaicWait; \
|
||||||
|
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
|
||||||
|
++pixel; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
#define DRAW_BACKGROUND_MODE_0(BPP, BLEND, OBJWIN) \
|
#define DRAW_BACKGROUND_MODE_0(BPP, BLEND, OBJWIN) \
|
||||||
uint32_t* pixel = &renderer->row[outX]; \
|
uint32_t* pixel = &renderer->row[outX]; \
|
||||||
if (background->mosaic && GBAMosaicControlGetBgH(renderer->mosaic)) { \
|
if (background->mosaic && GBAMosaicControlGetBgH(renderer->mosaic)) { \
|
||||||
|
@ -460,9 +652,18 @@ void GBAVideoSoftwareRendererDrawBackgroundMode0(struct GBAVideoSoftwareRenderer
|
||||||
uint32_t screenBase;
|
uint32_t screenBase;
|
||||||
uint32_t charBase;
|
uint32_t charBase;
|
||||||
int variant = background->target1 && GBAWindowControlIsBlendEnable(renderer->currentWindow.packed) && (renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN);
|
int variant = background->target1 && GBAWindowControlIsBlendEnable(renderer->currentWindow.packed) && (renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN);
|
||||||
color_t* mainPalette = renderer->normalPalette;
|
color_t* mainPalette;
|
||||||
if (variant) {
|
if (background->multipalette && background->extPalette) {
|
||||||
mainPalette = renderer->variantPalette;
|
mainPalette = background->extPalette;
|
||||||
|
// TODO
|
||||||
|
/*if (variant) {
|
||||||
|
mainPalette = background->variantPalette;
|
||||||
|
}*/
|
||||||
|
} else {
|
||||||
|
mainPalette = renderer->normalPalette;
|
||||||
|
if (variant) {
|
||||||
|
mainPalette = renderer->variantPalette;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
color_t* palette = mainPalette;
|
color_t* palette = mainPalette;
|
||||||
PREPARE_OBJWIN;
|
PREPARE_OBJWIN;
|
||||||
|
@ -481,28 +682,36 @@ void GBAVideoSoftwareRendererDrawBackgroundMode0(struct GBAVideoSoftwareRenderer
|
||||||
if (!(flags & FLAG_TARGET_2)) {
|
if (!(flags & FLAG_TARGET_2)) {
|
||||||
if (!background->multipalette) {
|
if (!background->multipalette) {
|
||||||
DRAW_BACKGROUND_MODE_0(16, NoBlend, NO_OBJWIN);
|
DRAW_BACKGROUND_MODE_0(16, NoBlend, NO_OBJWIN);
|
||||||
} else {
|
} else if (!background->extPalette) {
|
||||||
DRAW_BACKGROUND_MODE_0(256, NoBlend, NO_OBJWIN);
|
DRAW_BACKGROUND_MODE_0(256, NoBlend, NO_OBJWIN);
|
||||||
|
} else {
|
||||||
|
DRAW_BACKGROUND_MODE_0(256Ext, NoBlend, NO_OBJWIN);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!background->multipalette) {
|
if (!background->multipalette) {
|
||||||
DRAW_BACKGROUND_MODE_0(16, Blend, NO_OBJWIN);
|
DRAW_BACKGROUND_MODE_0(16, Blend, NO_OBJWIN);
|
||||||
} else {
|
} else if (!background->extPalette) {
|
||||||
DRAW_BACKGROUND_MODE_0(256, Blend, NO_OBJWIN);
|
DRAW_BACKGROUND_MODE_0(256, Blend, NO_OBJWIN);
|
||||||
|
} else {
|
||||||
|
DRAW_BACKGROUND_MODE_0(256Ext, Blend, NO_OBJWIN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!(flags & FLAG_TARGET_2)) {
|
if (!(flags & FLAG_TARGET_2)) {
|
||||||
if (!background->multipalette) {
|
if (!background->multipalette) {
|
||||||
DRAW_BACKGROUND_MODE_0(16, NoBlend, OBJWIN);
|
DRAW_BACKGROUND_MODE_0(16, NoBlend, OBJWIN);
|
||||||
} else {
|
} else if (!background->extPalette) {
|
||||||
DRAW_BACKGROUND_MODE_0(256, NoBlend, OBJWIN);
|
DRAW_BACKGROUND_MODE_0(256, NoBlend, OBJWIN);
|
||||||
|
} else {
|
||||||
|
DRAW_BACKGROUND_MODE_0(256Ext, NoBlend, OBJWIN);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!background->multipalette) {
|
if (!background->multipalette) {
|
||||||
DRAW_BACKGROUND_MODE_0(16, Blend, OBJWIN);
|
DRAW_BACKGROUND_MODE_0(16, Blend, OBJWIN);
|
||||||
} else {
|
} else if (!background->extPalette) {
|
||||||
DRAW_BACKGROUND_MODE_0(256, Blend, OBJWIN);
|
DRAW_BACKGROUND_MODE_0(256, Blend, OBJWIN);
|
||||||
|
} else {
|
||||||
|
DRAW_BACKGROUND_MODE_0(256Ext, Blend, OBJWIN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,6 +135,8 @@ static void GBAVideoSoftwareRendererReset(struct GBAVideoRenderer* renderer) {
|
||||||
bg->dmy = 256;
|
bg->dmy = 256;
|
||||||
bg->sx = 0;
|
bg->sx = 0;
|
||||||
bg->sy = 0;
|
bg->sy = 0;
|
||||||
|
bg->extPalette = NULL;
|
||||||
|
bg->variantPalette = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue