all repos — mgba @ 3b93e762ae248f80d2a19b7e3e39721304e7adad

mGBA Game Boy Advance Emulator

GB Video: Clean up OBJ parsing outside of renderer
Vicki Pfau vi@endrift.com
Sun, 11 Oct 2020 23:56:51 -0700
commit

3b93e762ae248f80d2a19b7e3e39721304e7adad

parent

7a9e1e4600f0bba80a7734c6d0c3504b4495485d

M include/mgba/internal/gb/renderers/proxy.hinclude/mgba/internal/gb/renderers/proxy.h

@@ -17,9 +17,6 @@ struct GBVideoProxyRenderer {

struct GBVideoRenderer d; struct GBVideoRenderer* backend; struct mVideoLogger* logger; - - struct GBObj objThisLine[40]; - size_t oamMax; }; void GBVideoProxyRendererCreate(struct GBVideoProxyRenderer* renderer, struct GBVideoRenderer* backend);
M include/mgba/internal/gb/renderers/software.hinclude/mgba/internal/gb/renderers/software.h

@@ -40,6 +40,9 @@

GBRegisterLCDC lcdc; enum GBModel model; + struct GBObj obj[10]; + int objMax; + int16_t objOffsetX; int16_t objOffsetY; int16_t offsetScx;
M include/mgba/internal/gb/video.hinclude/mgba/internal/gb/video.h

@@ -77,7 +77,7 @@ void (*writeSGBPacket)(struct GBVideoRenderer* renderer, uint8_t* data);

void (*writeVRAM)(struct GBVideoRenderer* renderer, uint16_t address); void (*writePalette)(struct GBVideoRenderer* renderer, int index, uint16_t value); void (*writeOAM)(struct GBVideoRenderer* renderer, uint16_t oam); - void (*drawRange)(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj* objOnLine, size_t nObj); + void (*drawRange)(struct GBVideoRenderer* renderer, int startX, int endX, int y); void (*finishScanline)(struct GBVideoRenderer* renderer, int y); void (*finishFrame)(struct GBVideoRenderer* renderer); void (*enableSGBBorder)(struct GBVideoRenderer* renderer, bool enable);

@@ -139,7 +139,6 @@ uint8_t* vramBank;

int vramCurrentBank; union GBOAM oam; - struct GBObj objThisLine[10]; int objMax; int bcpIndex;
M src/gb/extra/proxy.csrc/gb/extra/proxy.c

@@ -19,7 +19,7 @@ static void GBVideoProxyRendererWriteSGBPacket(struct GBVideoRenderer* renderer, uint8_t* data);

static void GBVideoProxyRendererWriteVRAM(struct GBVideoRenderer* renderer, uint16_t address); static void GBVideoProxyRendererWriteOAM(struct GBVideoRenderer* renderer, uint16_t oam); static void GBVideoProxyRendererWritePalette(struct GBVideoRenderer* renderer, int address, uint16_t value); -static void GBVideoProxyRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj* obj, size_t oamMax); +static void GBVideoProxyRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y); static void GBVideoProxyRendererFinishScanline(struct GBVideoRenderer* renderer, int y); static void GBVideoProxyRendererFinishFrame(struct GBVideoRenderer* renderer); static void GBVideoProxyRendererEnableSGBBorder(struct GBVideoRenderer* renderer, bool enable);

@@ -68,8 +68,6 @@ static void _reset(struct GBVideoProxyRenderer* proxyRenderer) {

memcpy(proxyRenderer->logger->oam, &proxyRenderer->d.oam->raw, GB_SIZE_OAM); memcpy(proxyRenderer->logger->vram, proxyRenderer->d.vram, GB_SIZE_VRAM); - proxyRenderer->oamMax = 0; - mVideoLoggerRendererReset(proxyRenderer->logger); }

@@ -117,6 +115,7 @@

static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerDirtyInfo* item) { struct GBVideoProxyRenderer* proxyRenderer = logger->context; uint8_t sgbPacket[16]; + struct GBObj legacyBuffer[40]; switch (item->type) { case DIRTY_REGISTER: proxyRenderer->backend->writeVideoRegister(proxyRenderer->backend, item->address, item->value);

@@ -145,7 +144,7 @@ }

break; case DIRTY_RANGE: if (item->value < item->value2 && item->value2 <= GB_VIDEO_HORIZONTAL_PIXELS && item->address < GB_VIDEO_VERTICAL_PIXELS) { - proxyRenderer->backend->drawRange(proxyRenderer->backend, item->value, item->value2, item->address, proxyRenderer->objThisLine, proxyRenderer->oamMax); + proxyRenderer->backend->drawRange(proxyRenderer->backend, item->value, item->value2, item->address); } break; case DIRTY_FRAME:

@@ -154,12 +153,10 @@ break;

case DIRTY_BUFFER: switch (item->address) { case BUFFER_OAM: - proxyRenderer->oamMax = item->value2 / sizeof(struct GBObj); - if (proxyRenderer->oamMax > 40) { - proxyRenderer->oamMax = 0; + if (item->value2 / sizeof(struct GBObj) > 40) { return false; } - logger->readData(logger, &proxyRenderer->objThisLine, item->value2, true); + logger->readData(logger, legacyBuffer, item->value2, true); break; case BUFFER_SGB: logger->readData(logger, sgbPacket, 16, true);

@@ -228,12 +225,11 @@ }

mVideoLoggerRendererWriteOAM(proxyRenderer->logger, oam, ((uint8_t*) proxyRenderer->d.oam->raw)[oam]); } -void GBVideoProxyRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj* obj, size_t oamMax) { +void GBVideoProxyRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y) { struct GBVideoProxyRenderer* proxyRenderer = (struct GBVideoProxyRenderer*) renderer; if (!proxyRenderer->logger->block) { - proxyRenderer->backend->drawRange(proxyRenderer->backend, startX, endX, y, obj, oamMax); + proxyRenderer->backend->drawRange(proxyRenderer->backend, startX, endX, y); } - mVideoLoggerWriteBuffer(proxyRenderer->logger, BUFFER_OAM, 0, oamMax * sizeof(*obj), obj); mVideoLoggerRendererDrawRange(proxyRenderer->logger, startX, endX, y); }
M src/gb/renderers/software.csrc/gb/renderers/software.c

@@ -18,7 +18,7 @@ static void GBVideoSoftwareRendererWriteSGBPacket(struct GBVideoRenderer* renderer, uint8_t* data);

static void GBVideoSoftwareRendererWritePalette(struct GBVideoRenderer* renderer, int index, uint16_t value); static void GBVideoSoftwareRendererWriteVRAM(struct GBVideoRenderer* renderer, uint16_t address); static void GBVideoSoftwareRendererWriteOAM(struct GBVideoRenderer* renderer, uint16_t oam); -static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj* obj, size_t oamMax); +static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y); static void GBVideoSoftwareRendererFinishScanline(struct GBVideoRenderer* renderer, int y); static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer); static void GBVideoSoftwareRendererEnableSGBBorder(struct GBVideoRenderer* renderer, bool enable);

@@ -499,7 +499,31 @@ UNUSED(oam);

// Nothing to do } -static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj* obj, size_t oamMax) { +static void _cleanOAM(struct GBVideoSoftwareRenderer* renderer, int y) { + // TODO: GBC differences + // TODO: Optimize + int spriteHeight = 8; + if (GBRegisterLCDCIsObjSize(renderer->lcdc)) { + spriteHeight = 16; + } + int o = 0; + int i; + for (i = 0; i < 40 && o < 10; ++i) { + uint8_t oy = renderer->d.oam->obj[i].y; + if (y < oy - 16 || y >= oy - 16 + spriteHeight) { + continue; + } + // TODO: Sort + renderer->obj[o] = renderer->d.oam->obj[i]; + ++o; + if (o == 10) { + break; + } + } + renderer->objMax = o; +} + +static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y) { struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer; softwareRenderer->lastY = y; softwareRenderer->lastX = endX;

@@ -536,9 +560,12 @@ memset(&softwareRenderer->row[startX], 0, endX - startX);

} if (GBRegisterLCDCIsObjEnable(softwareRenderer->lcdc) && !softwareRenderer->d.disableOBJ) { - size_t i; - for (i = 0; i < oamMax; ++i) { - GBVideoSoftwareRendererDrawObj(softwareRenderer, &obj[i], startX, endX, y); + if (startX == 0) { + _cleanOAM(softwareRenderer, y); + } + int i; + for (i = 0; i < softwareRenderer->objMax; ++i) { + GBVideoSoftwareRendererDrawObj(softwareRenderer, &softwareRenderer->obj[i], startX, endX, y); } }
M src/gb/video.csrc/gb/video.c

@@ -403,26 +403,18 @@ GBFrameStarted(video->p);

} static void _cleanOAM(struct GBVideo* video, int y) { - // TODO: GBC differences - // TODO: Optimize - video->objMax = 0; int spriteHeight = 8; if (GBRegisterLCDCIsObjSize(video->p->memory.io[REG_LCDC])) { spriteHeight = 16; } int o = 0; int i; - for (i = 0; i < 40; ++i) { + for (i = 0; i < 40 && o < 10; ++i) { uint8_t oy = video->oam.obj[i].y; if (y < oy - 16 || y >= oy - 16 + spriteHeight) { continue; } - // TODO: Sort - video->objThisLine[o] = video->oam.obj[i]; ++o; - if (o == 10) { - break; - } } video->objMax = o; }

@@ -442,7 +434,7 @@ if (oldX < 0) {

oldX = 0; } if (video->frameskipCounter <= 0) { - video->renderer->drawRange(video->renderer, oldX, video->x, video->ly, video->objThisLine, video->objMax); + video->renderer->drawRange(video->renderer, oldX, video->x, video->ly); } }