From 3b93e762ae248f80d2a19b7e3e39721304e7adad Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 11 Oct 2020 23:56:51 -0700 Subject: [PATCH] GB Video: Clean up OBJ parsing outside of renderer --- include/mgba/internal/gb/renderers/proxy.h | 3 -- include/mgba/internal/gb/renderers/software.h | 3 ++ include/mgba/internal/gb/video.h | 3 +- src/gb/extra/proxy.c | 18 ++++----- src/gb/renderers/software.c | 37 ++++++++++++++++--- src/gb/video.c | 12 +----- 6 files changed, 45 insertions(+), 31 deletions(-) diff --git a/include/mgba/internal/gb/renderers/proxy.h b/include/mgba/internal/gb/renderers/proxy.h index 244c5e39b..bde4e2ddb 100644 --- a/include/mgba/internal/gb/renderers/proxy.h +++ b/include/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); diff --git a/include/mgba/internal/gb/renderers/software.h b/include/mgba/internal/gb/renderers/software.h index fe4b1ff98..11e107f6d 100644 --- a/include/mgba/internal/gb/renderers/software.h +++ b/include/mgba/internal/gb/renderers/software.h @@ -40,6 +40,9 @@ struct GBVideoSoftwareRenderer { GBRegisterLCDC lcdc; enum GBModel model; + struct GBObj obj[10]; + int objMax; + int16_t objOffsetX; int16_t objOffsetY; int16_t offsetScx; diff --git a/include/mgba/internal/gb/video.h b/include/mgba/internal/gb/video.h index 13473776a..cd5a1e8d1 100644 --- a/include/mgba/internal/gb/video.h +++ b/include/mgba/internal/gb/video.h @@ -77,7 +77,7 @@ struct GBVideoRenderer { 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 @@ struct GBVideo { int vramCurrentBank; union GBOAM oam; - struct GBObj objThisLine[10]; int objMax; int bcpIndex; diff --git a/src/gb/extra/proxy.c b/src/gb/extra/proxy.c index f7b21cbda..24758cd2a 100644 --- a/src/gb/extra/proxy.c +++ b/src/gb/extra/proxy.c @@ -19,7 +19,7 @@ static void GBVideoProxyRendererWriteSGBPacket(struct GBVideoRenderer* renderer, 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 @@ void GBVideoProxyRendererDeinit(struct GBVideoRenderer* renderer) { 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 @@ static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerD 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 @@ static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerD 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 @@ void GBVideoProxyRendererWriteOAM(struct GBVideoRenderer* renderer, uint16_t oam 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); } diff --git a/src/gb/renderers/software.c b/src/gb/renderers/software.c index 637bae496..f6c4f9818 100644 --- a/src/gb/renderers/software.c +++ b/src/gb/renderers/software.c @@ -18,7 +18,7 @@ static void GBVideoSoftwareRendererWriteSGBPacket(struct GBVideoRenderer* render 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 @@ static void GBVideoSoftwareRendererWriteOAM(struct GBVideoRenderer* renderer, ui // 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 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i } 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); } } diff --git a/src/gb/video.c b/src/gb/video.c index 6c207297d..8bf173797 100644 --- a/src/gb/video.c +++ b/src/gb/video.c @@ -403,26 +403,18 @@ void _updateFrameCount(struct mTiming* timing, void* context, uint32_t cyclesLat } 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 @@ void GBVideoProcessDots(struct GBVideo* video, uint32_t cyclesLate) { 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); } }