GB Video: Clean up OBJ parsing outside of renderer

This commit is contained in:
Vicki Pfau 2020-10-11 23:56:51 -07:00
parent 7a9e1e4600
commit 3b93e762ae
6 changed files with 45 additions and 31 deletions

View File

@ -17,9 +17,6 @@ struct GBVideoProxyRenderer {
struct GBVideoRenderer d; struct GBVideoRenderer d;
struct GBVideoRenderer* backend; struct GBVideoRenderer* backend;
struct mVideoLogger* logger; struct mVideoLogger* logger;
struct GBObj objThisLine[40];
size_t oamMax;
}; };
void GBVideoProxyRendererCreate(struct GBVideoProxyRenderer* renderer, struct GBVideoRenderer* backend); void GBVideoProxyRendererCreate(struct GBVideoProxyRenderer* renderer, struct GBVideoRenderer* backend);

View File

@ -40,6 +40,9 @@ struct GBVideoSoftwareRenderer {
GBRegisterLCDC lcdc; GBRegisterLCDC lcdc;
enum GBModel model; enum GBModel model;
struct GBObj obj[10];
int objMax;
int16_t objOffsetX; int16_t objOffsetX;
int16_t objOffsetY; int16_t objOffsetY;
int16_t offsetScx; int16_t offsetScx;

View File

@ -77,7 +77,7 @@ struct GBVideoRenderer {
void (*writeVRAM)(struct GBVideoRenderer* renderer, uint16_t address); void (*writeVRAM)(struct GBVideoRenderer* renderer, uint16_t address);
void (*writePalette)(struct GBVideoRenderer* renderer, int index, uint16_t value); void (*writePalette)(struct GBVideoRenderer* renderer, int index, uint16_t value);
void (*writeOAM)(struct GBVideoRenderer* renderer, uint16_t oam); 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 (*finishScanline)(struct GBVideoRenderer* renderer, int y);
void (*finishFrame)(struct GBVideoRenderer* renderer); void (*finishFrame)(struct GBVideoRenderer* renderer);
void (*enableSGBBorder)(struct GBVideoRenderer* renderer, bool enable); void (*enableSGBBorder)(struct GBVideoRenderer* renderer, bool enable);
@ -139,7 +139,6 @@ struct GBVideo {
int vramCurrentBank; int vramCurrentBank;
union GBOAM oam; union GBOAM oam;
struct GBObj objThisLine[10];
int objMax; int objMax;
int bcpIndex; int bcpIndex;

View File

@ -19,7 +19,7 @@ static void GBVideoProxyRendererWriteSGBPacket(struct GBVideoRenderer* renderer,
static void GBVideoProxyRendererWriteVRAM(struct GBVideoRenderer* renderer, uint16_t address); static void GBVideoProxyRendererWriteVRAM(struct GBVideoRenderer* renderer, uint16_t address);
static void GBVideoProxyRendererWriteOAM(struct GBVideoRenderer* renderer, uint16_t oam); static void GBVideoProxyRendererWriteOAM(struct GBVideoRenderer* renderer, uint16_t oam);
static void GBVideoProxyRendererWritePalette(struct GBVideoRenderer* renderer, int address, uint16_t value); 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 GBVideoProxyRendererFinishScanline(struct GBVideoRenderer* renderer, int y);
static void GBVideoProxyRendererFinishFrame(struct GBVideoRenderer* renderer); static void GBVideoProxyRendererFinishFrame(struct GBVideoRenderer* renderer);
static void GBVideoProxyRendererEnableSGBBorder(struct GBVideoRenderer* renderer, bool enable); 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->oam, &proxyRenderer->d.oam->raw, GB_SIZE_OAM);
memcpy(proxyRenderer->logger->vram, proxyRenderer->d.vram, GB_SIZE_VRAM); memcpy(proxyRenderer->logger->vram, proxyRenderer->d.vram, GB_SIZE_VRAM);
proxyRenderer->oamMax = 0;
mVideoLoggerRendererReset(proxyRenderer->logger); mVideoLoggerRendererReset(proxyRenderer->logger);
} }
@ -117,6 +115,7 @@ void GBVideoProxyRendererDeinit(struct GBVideoRenderer* renderer) {
static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerDirtyInfo* item) { static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerDirtyInfo* item) {
struct GBVideoProxyRenderer* proxyRenderer = logger->context; struct GBVideoProxyRenderer* proxyRenderer = logger->context;
uint8_t sgbPacket[16]; uint8_t sgbPacket[16];
struct GBObj legacyBuffer[40];
switch (item->type) { switch (item->type) {
case DIRTY_REGISTER: case DIRTY_REGISTER:
proxyRenderer->backend->writeVideoRegister(proxyRenderer->backend, item->address, item->value); proxyRenderer->backend->writeVideoRegister(proxyRenderer->backend, item->address, item->value);
@ -145,7 +144,7 @@ static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerD
break; break;
case DIRTY_RANGE: case DIRTY_RANGE:
if (item->value < item->value2 && item->value2 <= GB_VIDEO_HORIZONTAL_PIXELS && item->address < GB_VIDEO_VERTICAL_PIXELS) { 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; break;
case DIRTY_FRAME: case DIRTY_FRAME:
@ -154,12 +153,10 @@ static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerD
case DIRTY_BUFFER: case DIRTY_BUFFER:
switch (item->address) { switch (item->address) {
case BUFFER_OAM: case BUFFER_OAM:
proxyRenderer->oamMax = item->value2 / sizeof(struct GBObj); if (item->value2 / sizeof(struct GBObj) > 40) {
if (proxyRenderer->oamMax > 40) {
proxyRenderer->oamMax = 0;
return false; return false;
} }
logger->readData(logger, &proxyRenderer->objThisLine, item->value2, true); logger->readData(logger, legacyBuffer, item->value2, true);
break; break;
case BUFFER_SGB: case BUFFER_SGB:
logger->readData(logger, sgbPacket, 16, true); 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]); 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; struct GBVideoProxyRenderer* proxyRenderer = (struct GBVideoProxyRenderer*) renderer;
if (!proxyRenderer->logger->block) { 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); mVideoLoggerRendererDrawRange(proxyRenderer->logger, startX, endX, y);
} }

View File

@ -18,7 +18,7 @@ static void GBVideoSoftwareRendererWriteSGBPacket(struct GBVideoRenderer* render
static void GBVideoSoftwareRendererWritePalette(struct GBVideoRenderer* renderer, int index, uint16_t value); static void GBVideoSoftwareRendererWritePalette(struct GBVideoRenderer* renderer, int index, uint16_t value);
static void GBVideoSoftwareRendererWriteVRAM(struct GBVideoRenderer* renderer, uint16_t address); static void GBVideoSoftwareRendererWriteVRAM(struct GBVideoRenderer* renderer, uint16_t address);
static void GBVideoSoftwareRendererWriteOAM(struct GBVideoRenderer* renderer, uint16_t oam); 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 GBVideoSoftwareRendererFinishScanline(struct GBVideoRenderer* renderer, int y);
static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer); static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer);
static void GBVideoSoftwareRendererEnableSGBBorder(struct GBVideoRenderer* renderer, bool enable); static void GBVideoSoftwareRendererEnableSGBBorder(struct GBVideoRenderer* renderer, bool enable);
@ -499,7 +499,31 @@ static void GBVideoSoftwareRendererWriteOAM(struct GBVideoRenderer* renderer, ui
// Nothing to do // 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; struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer;
softwareRenderer->lastY = y; softwareRenderer->lastY = y;
softwareRenderer->lastX = endX; softwareRenderer->lastX = endX;
@ -536,9 +560,12 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
} }
if (GBRegisterLCDCIsObjEnable(softwareRenderer->lcdc) && !softwareRenderer->d.disableOBJ) { if (GBRegisterLCDCIsObjEnable(softwareRenderer->lcdc) && !softwareRenderer->d.disableOBJ) {
size_t i; if (startX == 0) {
for (i = 0; i < oamMax; ++i) { _cleanOAM(softwareRenderer, y);
GBVideoSoftwareRendererDrawObj(softwareRenderer, &obj[i], startX, endX, y); }
int i;
for (i = 0; i < softwareRenderer->objMax; ++i) {
GBVideoSoftwareRendererDrawObj(softwareRenderer, &softwareRenderer->obj[i], startX, endX, y);
} }
} }

View File

@ -403,26 +403,18 @@ void _updateFrameCount(struct mTiming* timing, void* context, uint32_t cyclesLat
} }
static void _cleanOAM(struct GBVideo* video, int y) { static void _cleanOAM(struct GBVideo* video, int y) {
// TODO: GBC differences
// TODO: Optimize
video->objMax = 0;
int spriteHeight = 8; int spriteHeight = 8;
if (GBRegisterLCDCIsObjSize(video->p->memory.io[REG_LCDC])) { if (GBRegisterLCDCIsObjSize(video->p->memory.io[REG_LCDC])) {
spriteHeight = 16; spriteHeight = 16;
} }
int o = 0; int o = 0;
int i; int i;
for (i = 0; i < 40; ++i) { for (i = 0; i < 40 && o < 10; ++i) {
uint8_t oy = video->oam.obj[i].y; uint8_t oy = video->oam.obj[i].y;
if (y < oy - 16 || y >= oy - 16 + spriteHeight) { if (y < oy - 16 || y >= oy - 16 + spriteHeight) {
continue; continue;
} }
// TODO: Sort
video->objThisLine[o] = video->oam.obj[i];
++o; ++o;
if (o == 10) {
break;
}
} }
video->objMax = o; video->objMax = o;
} }
@ -442,7 +434,7 @@ void GBVideoProcessDots(struct GBVideo* video, uint32_t cyclesLate) {
oldX = 0; oldX = 0;
} }
if (video->frameskipCounter <= 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);
} }
} }