mirror of https://github.com/mgba-emu/mgba.git
GB Video: Optimize renderer
This commit is contained in:
parent
e6e535e39a
commit
94ff4f7c4e
|
@ -275,6 +275,7 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
|
||||||
case REG_BGP:
|
case REG_BGP:
|
||||||
case REG_OBP0:
|
case REG_OBP0:
|
||||||
case REG_OBP1:
|
case REG_OBP1:
|
||||||
|
GBVideoProcessDots(&gb->video);
|
||||||
value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
|
value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
|
||||||
break;
|
break;
|
||||||
case REG_STAT:
|
case REG_STAT:
|
||||||
|
|
|
@ -12,13 +12,14 @@ static void GBVideoSoftwareRendererInit(struct GBVideoRenderer* renderer);
|
||||||
static void GBVideoSoftwareRendererDeinit(struct GBVideoRenderer* renderer);
|
static void GBVideoSoftwareRendererDeinit(struct GBVideoRenderer* renderer);
|
||||||
static void GBVideoSoftwareRendererReset(struct GBVideoRenderer* renderer);
|
static void GBVideoSoftwareRendererReset(struct GBVideoRenderer* renderer);
|
||||||
static uint8_t GBVideoSoftwareRendererWriteVideoRegister(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value);
|
static uint8_t GBVideoSoftwareRendererWriteVideoRegister(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value);
|
||||||
static void GBVideoSoftwareRendererDrawDot(struct GBVideoRenderer* renderer, int x, int y, struct GBObj** obj, size_t oamMax);
|
static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj** obj, size_t oamMax);
|
||||||
|
static void GBVideoSoftwareRendererFinishScanline(struct GBVideoRenderer* renderer, int y);
|
||||||
static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer);
|
static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer);
|
||||||
static void GBVideoSoftwareRendererGetPixels(struct GBVideoRenderer* renderer, unsigned* stride, const void** pixels);
|
static void GBVideoSoftwareRendererGetPixels(struct GBVideoRenderer* renderer, unsigned* stride, const void** pixels);
|
||||||
static void GBVideoSoftwareRendererPutPixels(struct GBVideoRenderer* renderer, unsigned stride, void* pixels);
|
static void GBVideoSoftwareRendererPutPixels(struct GBVideoRenderer* renderer, unsigned stride, void* pixels);
|
||||||
|
|
||||||
static void GBVideoSoftwareRendererDrawBackground(struct GBVideoSoftwareRenderer* renderer, uint8_t* maps, int x, int y, int sx, int sy);
|
static void GBVideoSoftwareRendererDrawBackground(struct GBVideoSoftwareRenderer* renderer, uint8_t* maps, int startX, int endX, int y, int sx, int sy);
|
||||||
static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* renderer, struct GBObj* obj, int x, int y);
|
static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* renderer, struct GBObj* obj, int startX, int endX, int y);
|
||||||
|
|
||||||
#ifdef COLOR_16_BIT
|
#ifdef COLOR_16_BIT
|
||||||
#ifdef COLOR_5_6_5
|
#ifdef COLOR_5_6_5
|
||||||
|
@ -35,7 +36,8 @@ void GBVideoSoftwareRendererCreate(struct GBVideoSoftwareRenderer* renderer) {
|
||||||
renderer->d.reset = GBVideoSoftwareRendererReset;
|
renderer->d.reset = GBVideoSoftwareRendererReset;
|
||||||
renderer->d.deinit = GBVideoSoftwareRendererDeinit;
|
renderer->d.deinit = GBVideoSoftwareRendererDeinit;
|
||||||
renderer->d.writeVideoRegister = GBVideoSoftwareRendererWriteVideoRegister;
|
renderer->d.writeVideoRegister = GBVideoSoftwareRendererWriteVideoRegister;
|
||||||
renderer->d.drawDot = GBVideoSoftwareRendererDrawDot;
|
renderer->d.drawRange = GBVideoSoftwareRendererDrawRange;
|
||||||
|
renderer->d.finishScanline = GBVideoSoftwareRendererFinishScanline;
|
||||||
renderer->d.finishFrame = GBVideoSoftwareRendererFinishFrame;
|
renderer->d.finishFrame = GBVideoSoftwareRendererFinishFrame;
|
||||||
renderer->d.getPixels = 0;
|
renderer->d.getPixels = 0;
|
||||||
renderer->d.putPixels = 0;
|
renderer->d.putPixels = 0;
|
||||||
|
@ -112,38 +114,48 @@ static uint8_t GBVideoSoftwareRendererWriteVideoRegister(struct GBVideoRenderer*
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GBVideoSoftwareRendererDrawDot(struct GBVideoRenderer* renderer, int x, int y, struct GBObj** obj, size_t oamMax) {
|
static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj** obj, size_t oamMax) {
|
||||||
struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer;
|
struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer;
|
||||||
uint8_t* maps = &softwareRenderer->d.vram[GB_BASE_MAP];
|
uint8_t* maps = &softwareRenderer->d.vram[GB_BASE_MAP];
|
||||||
if (GBRegisterLCDCIsTileMap(softwareRenderer->lcdc)) {
|
if (GBRegisterLCDCIsTileMap(softwareRenderer->lcdc)) {
|
||||||
maps += GB_SIZE_MAP;
|
maps += GB_SIZE_MAP;
|
||||||
}
|
}
|
||||||
if (GBRegisterLCDCIsBgEnable(softwareRenderer->lcdc)) {
|
if (GBRegisterLCDCIsBgEnable(softwareRenderer->lcdc)) {
|
||||||
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, x, y, softwareRenderer->scx, softwareRenderer->scy);
|
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, endX, y, softwareRenderer->scx, softwareRenderer->scy);
|
||||||
|
|
||||||
if (GBRegisterLCDCIsWindow(softwareRenderer->lcdc) && softwareRenderer->wy <= y && x >= softwareRenderer->wx - 7) {
|
if (GBRegisterLCDCIsWindow(softwareRenderer->lcdc) && softwareRenderer->wy <= y && startX >= softwareRenderer->wx - 7) {
|
||||||
maps = &softwareRenderer->d.vram[GB_BASE_MAP];
|
maps = &softwareRenderer->d.vram[GB_BASE_MAP];
|
||||||
if (GBRegisterLCDCIsWindowTileMap(softwareRenderer->lcdc)) {
|
if (GBRegisterLCDCIsWindowTileMap(softwareRenderer->lcdc)) {
|
||||||
maps += GB_SIZE_MAP;
|
maps += GB_SIZE_MAP;
|
||||||
}
|
}
|
||||||
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, x, y, 7 - softwareRenderer->wx, (softwareRenderer->currentWy - y) - softwareRenderer->wy);
|
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, endX, y, 7 - softwareRenderer->wx, (softwareRenderer->currentWy - y) - softwareRenderer->wy);
|
||||||
if (x == 159) { // TODO: Find a better way to do this
|
|
||||||
++softwareRenderer->currentWy;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
int x;
|
||||||
|
for (x = startX; x < endX; ++x) {
|
||||||
softwareRenderer->row[x] = 0;
|
softwareRenderer->row[x] = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (GBRegisterLCDCIsObjEnable(softwareRenderer->lcdc)) {
|
if (GBRegisterLCDCIsObjEnable(softwareRenderer->lcdc)) {
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < oamMax; ++i) {
|
for (i = 0; i < oamMax; ++i) {
|
||||||
GBVideoSoftwareRendererDrawObj(softwareRenderer, obj[i], x, y);
|
GBVideoSoftwareRendererDrawObj(softwareRenderer, obj[i], startX, endX, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
color_t* row = &softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * y];
|
color_t* row = &softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * y];
|
||||||
|
int x;
|
||||||
|
for (x = startX; x < endX; ++x) {
|
||||||
row[x] = softwareRenderer->palette[softwareRenderer->row[x]];
|
row[x] = softwareRenderer->palette[softwareRenderer->row[x]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GBVideoSoftwareRendererFinishScanline(struct GBVideoRenderer* renderer, int y) {
|
||||||
|
struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer;
|
||||||
|
if (GBRegisterLCDCIsBgEnable(softwareRenderer->lcdc) && GBRegisterLCDCIsWindow(softwareRenderer->lcdc) && softwareRenderer->wy <= y && softwareRenderer->wx - 7 < GB_VIDEO_HORIZONTAL_PIXELS) {
|
||||||
|
++softwareRenderer->currentWy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer) {
|
static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer) {
|
||||||
|
@ -156,13 +168,15 @@ static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer)
|
||||||
softwareRenderer->currentWy = 0;
|
softwareRenderer->currentWy = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GBVideoSoftwareRendererDrawBackground(struct GBVideoSoftwareRenderer* renderer, uint8_t* maps, int x, int y, int sx, int sy) {
|
static void GBVideoSoftwareRendererDrawBackground(struct GBVideoSoftwareRenderer* renderer, uint8_t* maps, int startX, int endX, int y, int sx, int sy) {
|
||||||
uint8_t* data = renderer->d.vram;
|
uint8_t* data = renderer->d.vram;
|
||||||
if (!GBRegisterLCDCIsTileData(renderer->lcdc)) {
|
if (!GBRegisterLCDCIsTileData(renderer->lcdc)) {
|
||||||
data += 0x1000;
|
data += 0x1000;
|
||||||
}
|
}
|
||||||
int topY = (((y + sy) >> 3) & 0x1F) * 0x20;
|
int topY = (((y + sy) >> 3) & 0x1F) * 0x20;
|
||||||
int bottomY = (y + sy) & 7;
|
int bottomY = (y + sy) & 7;
|
||||||
|
int x;
|
||||||
|
for (x = startX; x < endX; ++x) {
|
||||||
int topX = ((x + sx) >> 3) & 0x1F;
|
int topX = ((x + sx) >> 3) & 0x1F;
|
||||||
int bottomX = 7 - ((x + sx) & 7);
|
int bottomX = 7 - ((x + sx) & 7);
|
||||||
int bgTile;
|
int bgTile;
|
||||||
|
@ -176,9 +190,20 @@ static void GBVideoSoftwareRendererDrawBackground(struct GBVideoSoftwareRenderer
|
||||||
tileDataUpper >>= bottomX;
|
tileDataUpper >>= bottomX;
|
||||||
tileDataLower >>= bottomX;
|
tileDataLower >>= bottomX;
|
||||||
renderer->row[x] = ((tileDataUpper & 1) << 1) | (tileDataLower & 1);
|
renderer->row[x] = ((tileDataUpper & 1) << 1) | (tileDataLower & 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* renderer, struct GBObj* obj, int x, int y) {
|
static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* renderer, struct GBObj* obj, int startX, int endX, int y) {
|
||||||
|
int ix = obj->x - 8;
|
||||||
|
if (endX < ix || startX >= ix + 8) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (obj->x < endX) {
|
||||||
|
endX = obj->x;
|
||||||
|
}
|
||||||
|
if (obj->x - 8 > startX) {
|
||||||
|
startX = obj->x - 8;
|
||||||
|
}
|
||||||
uint8_t* data = renderer->d.vram;
|
uint8_t* data = renderer->d.vram;
|
||||||
int tileOffset = 0;
|
int tileOffset = 0;
|
||||||
int bottomY;
|
int bottomY;
|
||||||
|
@ -193,17 +218,11 @@ static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* rende
|
||||||
++tileOffset;
|
++tileOffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int end = GB_VIDEO_HORIZONTAL_PIXELS;
|
|
||||||
if (obj->x < end) {
|
|
||||||
end = obj->x;
|
|
||||||
}
|
|
||||||
int ix = obj->x - 8;
|
|
||||||
if (x < ix || x >= ix + 8) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint8_t mask = GBObjAttributesIsPriority(obj->attr) ? 0 : 0x20;
|
uint8_t mask = GBObjAttributesIsPriority(obj->attr) ? 0 : 0x20;
|
||||||
int p = (GBObjAttributesGetPalette(obj->attr) + 8) * 4;
|
int p = (GBObjAttributesGetPalette(obj->attr) + 8) * 4;
|
||||||
int bottomX;
|
int bottomX;
|
||||||
|
int x;
|
||||||
|
for (x = startX; x < endX; ++x) {
|
||||||
if (GBObjAttributesIsXFlip(obj->attr)) {
|
if (GBObjAttributesIsXFlip(obj->attr)) {
|
||||||
bottomX = (x - obj->x) & 7;
|
bottomX = (x - obj->x) & 7;
|
||||||
} else {
|
} else {
|
||||||
|
@ -218,4 +237,5 @@ static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* rende
|
||||||
if (((tileDataUpper | tileDataLower) & 1) && current <= mask) {
|
if (((tileDataUpper | tileDataLower) & 1) && current <= mask) {
|
||||||
renderer->row[x] = p | ((tileDataUpper & 1) << 1) | (tileDataLower & 1);
|
renderer->row[x] = p | ((tileDataUpper & 1) << 1) | (tileDataLower & 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,8 @@ static void GBVideoDummyRendererInit(struct GBVideoRenderer* renderer);
|
||||||
static void GBVideoDummyRendererReset(struct GBVideoRenderer* renderer);
|
static void GBVideoDummyRendererReset(struct GBVideoRenderer* renderer);
|
||||||
static void GBVideoDummyRendererDeinit(struct GBVideoRenderer* renderer);
|
static void GBVideoDummyRendererDeinit(struct GBVideoRenderer* renderer);
|
||||||
static uint8_t GBVideoDummyRendererWriteVideoRegister(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value);
|
static uint8_t GBVideoDummyRendererWriteVideoRegister(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value);
|
||||||
static void GBVideoDummyRendererDrawDot(struct GBVideoRenderer* renderer, int x, int y, struct GBObj** obj, size_t oamMax);
|
static void GBVideoDummyRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj** obj, size_t oamMax);
|
||||||
|
static void GBVideoDummyRendererFinishScanline(struct GBVideoRenderer* renderer, int y);
|
||||||
static void GBVideoDummyRendererFinishFrame(struct GBVideoRenderer* renderer);
|
static void GBVideoDummyRendererFinishFrame(struct GBVideoRenderer* renderer);
|
||||||
static void GBVideoDummyRendererGetPixels(struct GBVideoRenderer* renderer, unsigned* stride, const void** pixels);
|
static void GBVideoDummyRendererGetPixels(struct GBVideoRenderer* renderer, unsigned* stride, const void** pixels);
|
||||||
|
|
||||||
|
@ -27,7 +28,8 @@ static struct GBVideoRenderer dummyRenderer = {
|
||||||
.reset = GBVideoDummyRendererReset,
|
.reset = GBVideoDummyRendererReset,
|
||||||
.deinit = GBVideoDummyRendererDeinit,
|
.deinit = GBVideoDummyRendererDeinit,
|
||||||
.writeVideoRegister = GBVideoDummyRendererWriteVideoRegister,
|
.writeVideoRegister = GBVideoDummyRendererWriteVideoRegister,
|
||||||
.drawDot = GBVideoDummyRendererDrawDot,
|
.drawRange = GBVideoDummyRendererDrawRange,
|
||||||
|
.finishScanline = GBVideoDummyRendererFinishScanline,
|
||||||
.finishFrame = GBVideoDummyRendererFinishFrame,
|
.finishFrame = GBVideoDummyRendererFinishFrame,
|
||||||
.getPixels = GBVideoDummyRendererGetPixels
|
.getPixels = GBVideoDummyRendererGetPixels
|
||||||
};
|
};
|
||||||
|
@ -47,7 +49,7 @@ void GBVideoReset(struct GBVideo* video) {
|
||||||
video->eventDiff = 0;
|
video->eventDiff = 0;
|
||||||
|
|
||||||
video->nextMode = INT_MAX;
|
video->nextMode = INT_MAX;
|
||||||
video->nextDot = INT_MAX;
|
video->dotCounter = INT_MIN;
|
||||||
|
|
||||||
video->frameCounter = 0;
|
video->frameCounter = 0;
|
||||||
video->frameskipCounter = 0;
|
video->frameskipCounter = 0;
|
||||||
|
@ -84,22 +86,14 @@ int32_t GBVideoProcessEvents(struct GBVideo* video, int32_t cycles) {
|
||||||
if (video->nextEvent <= 0) {
|
if (video->nextEvent <= 0) {
|
||||||
if (video->nextEvent != INT_MAX) {
|
if (video->nextEvent != INT_MAX) {
|
||||||
video->nextMode -= video->eventDiff;
|
video->nextMode -= video->eventDiff;
|
||||||
video->nextDot -= video->eventDiff;
|
|
||||||
}
|
}
|
||||||
video->nextEvent = INT_MAX;
|
video->nextEvent = INT_MAX;
|
||||||
if (video->nextDot <= 0) {
|
GBVideoProcessDots(video);
|
||||||
video->renderer->drawDot(video->renderer, video->x, video->ly, video->objThisLine, video->objMax);
|
|
||||||
++video->x;
|
|
||||||
if (video->x < GB_VIDEO_HORIZONTAL_PIXELS) {
|
|
||||||
video->nextDot = 1;
|
|
||||||
} else {
|
|
||||||
video->nextDot = INT_MAX;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (video->nextMode <= 0) {
|
if (video->nextMode <= 0) {
|
||||||
int lyc = video->p->memory.io[REG_LYC];
|
int lyc = video->p->memory.io[REG_LYC];
|
||||||
switch (video->mode) {
|
switch (video->mode) {
|
||||||
case 0:
|
case 0:
|
||||||
|
video->renderer->finishScanline(video->renderer, video->ly);
|
||||||
++video->ly;
|
++video->ly;
|
||||||
video->p->memory.io[REG_LY] = video->ly;
|
video->p->memory.io[REG_LY] = video->ly;
|
||||||
video->stat = GBRegisterSTATSetLYC(video->stat, lyc == video->ly);
|
video->stat = GBRegisterSTATSetLYC(video->stat, lyc == video->ly);
|
||||||
|
@ -157,8 +151,8 @@ int32_t GBVideoProcessEvents(struct GBVideo* video, int32_t cycles) {
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
_cleanOAM(video, video->ly);
|
_cleanOAM(video, video->ly);
|
||||||
video->nextDot = 1;
|
video->dotCounter = 0;
|
||||||
video->nextEvent = video->nextDot;
|
video->nextEvent = GB_VIDEO_HORIZONTAL_LENGTH;
|
||||||
video->x = 0;
|
video->x = 0;
|
||||||
video->nextMode = GB_VIDEO_MODE_3_LENGTH_BASE + video->objMax * 8;
|
video->nextMode = GB_VIDEO_MODE_3_LENGTH_BASE + video->objMax * 8;
|
||||||
video->mode = 3;
|
video->mode = 3;
|
||||||
|
@ -175,9 +169,6 @@ int32_t GBVideoProcessEvents(struct GBVideo* video, int32_t cycles) {
|
||||||
video->stat = GBRegisterSTATSetMode(video->stat, video->mode);
|
video->stat = GBRegisterSTATSetMode(video->stat, video->mode);
|
||||||
video->p->memory.io[REG_STAT] = video->stat;
|
video->p->memory.io[REG_STAT] = video->stat;
|
||||||
}
|
}
|
||||||
if (video->nextDot < video->nextEvent) {
|
|
||||||
video->nextEvent = video->nextDot;
|
|
||||||
}
|
|
||||||
if (video->nextMode < video->nextEvent) {
|
if (video->nextMode < video->nextEvent) {
|
||||||
video->nextEvent = video->nextMode;
|
video->nextEvent = video->nextMode;
|
||||||
}
|
}
|
||||||
|
@ -211,6 +202,21 @@ static void _cleanOAM(struct GBVideo* video, int y) {
|
||||||
video->objMax = o;
|
video->objMax = o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GBVideoProcessDots(struct GBVideo* video) {
|
||||||
|
if (video->mode != 3 || video->dotCounter < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int oldX = video->x;
|
||||||
|
video->x = video->dotCounter + video->eventDiff + video->p->cpu->cycles;
|
||||||
|
if (video->x > GB_VIDEO_HORIZONTAL_PIXELS) {
|
||||||
|
video->x = GB_VIDEO_HORIZONTAL_PIXELS;
|
||||||
|
}
|
||||||
|
if (video->x == GB_VIDEO_HORIZONTAL_PIXELS) {
|
||||||
|
video->dotCounter = INT_MIN;
|
||||||
|
}
|
||||||
|
video->renderer->drawRange(video->renderer, oldX, video->x, video->ly, video->objThisLine, video->objMax);
|
||||||
|
}
|
||||||
|
|
||||||
void GBVideoWriteLCDC(struct GBVideo* video, GBRegisterLCDC value) {
|
void GBVideoWriteLCDC(struct GBVideo* video, GBRegisterLCDC value) {
|
||||||
if (!GBRegisterLCDCIsEnable(video->p->memory.io[REG_LCDC]) && GBRegisterLCDCIsEnable(value)) {
|
if (!GBRegisterLCDCIsEnable(video->p->memory.io[REG_LCDC]) && GBRegisterLCDCIsEnable(value)) {
|
||||||
video->mode = 2;
|
video->mode = 2;
|
||||||
|
@ -264,15 +270,22 @@ static uint8_t GBVideoDummyRendererWriteVideoRegister(struct GBVideoRenderer* re
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GBVideoDummyRendererDrawDot(struct GBVideoRenderer* renderer, int x, int y, struct GBObj** obj, size_t oamMax) {
|
static void GBVideoDummyRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj** obj, size_t oamMax) {
|
||||||
UNUSED(renderer);
|
UNUSED(renderer);
|
||||||
UNUSED(x);
|
UNUSED(endX);
|
||||||
|
UNUSED(startX);
|
||||||
UNUSED(y);
|
UNUSED(y);
|
||||||
UNUSED(obj);
|
UNUSED(obj);
|
||||||
UNUSED(oamMax);
|
UNUSED(oamMax);
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void GBVideoDummyRendererFinishScanline(struct GBVideoRenderer* renderer, int y) {
|
||||||
|
UNUSED(renderer);
|
||||||
|
UNUSED(y);
|
||||||
|
// Nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
static void GBVideoDummyRendererFinishFrame(struct GBVideoRenderer* renderer) {
|
static void GBVideoDummyRendererFinishFrame(struct GBVideoRenderer* renderer) {
|
||||||
UNUSED(renderer);
|
UNUSED(renderer);
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
|
|
|
@ -17,8 +17,8 @@ enum {
|
||||||
GB_VIDEO_VERTICAL_TOTAL_PIXELS = GB_VIDEO_VERTICAL_PIXELS + GB_VIDEO_VBLANK_PIXELS,
|
GB_VIDEO_VERTICAL_TOTAL_PIXELS = GB_VIDEO_VERTICAL_PIXELS + GB_VIDEO_VBLANK_PIXELS,
|
||||||
|
|
||||||
// TODO: Figure out exact lengths
|
// TODO: Figure out exact lengths
|
||||||
GB_VIDEO_MODE_2_LENGTH = 84,
|
GB_VIDEO_MODE_2_LENGTH = 85,
|
||||||
GB_VIDEO_MODE_3_LENGTH_BASE = 168,
|
GB_VIDEO_MODE_3_LENGTH_BASE = 167,
|
||||||
GB_VIDEO_MODE_0_LENGTH_BASE = 204,
|
GB_VIDEO_MODE_0_LENGTH_BASE = 204,
|
||||||
|
|
||||||
GB_VIDEO_HORIZONTAL_LENGTH = GB_VIDEO_MODE_0_LENGTH_BASE + GB_VIDEO_MODE_2_LENGTH + GB_VIDEO_MODE_3_LENGTH_BASE,
|
GB_VIDEO_HORIZONTAL_LENGTH = GB_VIDEO_MODE_0_LENGTH_BASE + GB_VIDEO_MODE_2_LENGTH + GB_VIDEO_MODE_3_LENGTH_BASE,
|
||||||
|
@ -54,7 +54,8 @@ struct GBVideoRenderer {
|
||||||
void (*deinit)(struct GBVideoRenderer* renderer);
|
void (*deinit)(struct GBVideoRenderer* renderer);
|
||||||
|
|
||||||
uint8_t (*writeVideoRegister)(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value);
|
uint8_t (*writeVideoRegister)(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value);
|
||||||
void (*drawDot)(struct GBVideoRenderer* renderer, int x, int y, struct GBObj** objOnLine, size_t nObj);
|
void (*drawRange)(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj** objOnLine, size_t nObj);
|
||||||
|
void (*finishScanline)(struct GBVideoRenderer* renderer, int y);
|
||||||
void (*finishFrame)(struct GBVideoRenderer* renderer);
|
void (*finishFrame)(struct GBVideoRenderer* renderer);
|
||||||
|
|
||||||
void (*getPixels)(struct GBVideoRenderer* renderer, unsigned* stride, const void** pixels);
|
void (*getPixels)(struct GBVideoRenderer* renderer, unsigned* stride, const void** pixels);
|
||||||
|
@ -96,7 +97,7 @@ struct GBVideo {
|
||||||
int32_t eventDiff;
|
int32_t eventDiff;
|
||||||
|
|
||||||
int32_t nextMode;
|
int32_t nextMode;
|
||||||
int32_t nextDot;
|
int32_t dotCounter;
|
||||||
|
|
||||||
uint8_t* vram;
|
uint8_t* vram;
|
||||||
uint8_t* vramBank;
|
uint8_t* vramBank;
|
||||||
|
@ -115,6 +116,7 @@ void GBVideoReset(struct GBVideo* video);
|
||||||
void GBVideoDeinit(struct GBVideo* video);
|
void GBVideoDeinit(struct GBVideo* video);
|
||||||
void GBVideoAssociateRenderer(struct GBVideo* video, struct GBVideoRenderer* renderer);
|
void GBVideoAssociateRenderer(struct GBVideo* video, struct GBVideoRenderer* renderer);
|
||||||
int32_t GBVideoProcessEvents(struct GBVideo* video, int32_t cycles);
|
int32_t GBVideoProcessEvents(struct GBVideo* video, int32_t cycles);
|
||||||
|
void GBVideoProcessDots(struct GBVideo* video);
|
||||||
|
|
||||||
void GBVideoWriteLCDC(struct GBVideo* video, GBRegisterLCDC value);
|
void GBVideoWriteLCDC(struct GBVideo* video, GBRegisterLCDC value);
|
||||||
void GBVideoWriteSTAT(struct GBVideo* video, GBRegisterSTAT value);
|
void GBVideoWriteSTAT(struct GBVideo* video, GBRegisterSTAT value);
|
||||||
|
|
Loading…
Reference in New Issue