diff --git a/include/mgba/internal/gb/renderers/cache-set.h b/include/mgba/internal/gb/renderers/cache-set.h index 3ee63716c..f11bdf45f 100644 --- a/include/mgba/internal/gb/renderers/cache-set.h +++ b/include/mgba/internal/gb/renderers/cache-set.h @@ -16,6 +16,8 @@ struct mCacheSet; void GBVideoCacheInit(struct mCacheSet* cache); void GBVideoCacheAssociate(struct mCacheSet* cache, struct GBVideo* video); +void GBVideoCacheWriteVideoRegister(struct mCacheSet* cache, uint16_t address, uint8_t value); + CXX_GUARD_END #endif diff --git a/src/gb/core.c b/src/gb/core.c index 8fe75a084..21bc25995 100644 --- a/src/gb/core.c +++ b/src/gb/core.c @@ -26,8 +26,8 @@ static const struct mCoreChannelInfo _GBVideoLayers[] = { { 0, "bg", "Background", NULL }, - { 1, "obj", "Objects", NULL }, - { 2, "win", "Window", NULL }, + { 1, "bgwin", "Window", NULL }, + { 2, "obj", "Objects", NULL }, }; static const struct mCoreChannelInfo _GBAudioChannels[] = { diff --git a/src/gb/renderers/cache-set.c b/src/gb/renderers/cache-set.c index a2f34992b..07327ab7f 100644 --- a/src/gb/renderers/cache-set.c +++ b/src/gb/renderers/cache-set.c @@ -6,16 +6,23 @@ #include #include +#include +#include #include void GBVideoCacheInit(struct mCacheSet* cache) { - mCacheSetInit(cache, 0, 1); + mCacheSetInit(cache, 2, 1); mTileCacheConfiguration config = 0; config = mTileCacheSystemInfoSetPaletteBPP(config, 1); // 2^(2^1) = 4 entries config = mTileCacheSystemInfoSetPaletteCount(config, 4); // 16 palettes config = mTileCacheSystemInfoSetMaxTiles(config, 1024); mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, 0)); mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 0), config, 0, 0); + + mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 0)); + mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 1)); + mMapCacheSetGetPointer(&cache->maps, 0)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0); + mMapCacheSetGetPointer(&cache->maps, 1)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0); } void GBVideoCacheAssociate(struct mCacheSet* cache, struct GBVideo* video) { @@ -25,4 +32,102 @@ void GBVideoCacheAssociate(struct mCacheSet* cache, struct GBVideo* video) { for (i = 0; i < 64; ++i) { mCacheSetWritePalette(cache, i, mColorFrom555(video->palette[i])); } + mMapCacheSystemInfo sysconfig = mMapCacheSystemInfoSetPaletteCount(0, 0); + if (video->p->model >= GB_MODEL_CGB) { + sysconfig = mMapCacheSystemInfoSetPaletteCount(0, 2); + } + mMapCacheConfigureSystem(mMapCacheSetGetPointer(&cache->maps, 0), sysconfig); + mMapCacheConfigureSystem(mMapCacheSetGetPointer(&cache->maps, 1), sysconfig); + + GBVideoCacheWriteVideoRegister(cache, REG_LCDC, video->p->memory.io[REG_LCDC]); +} + +static void mapParserDMG0(struct mMapCache* cache, struct mMapCacheEntry* entry, void* vram) { + UNUSED(cache); + int map = *(uint8_t*) vram; + entry->tileId = map; + entry->flags = mMapCacheEntryFlagsClearHMirror(entry->flags); + entry->flags = mMapCacheEntryFlagsClearVMirror(entry->flags); + entry->flags = mMapCacheEntryFlagsSetPaletteId(entry->flags, 0); +} + +static void mapParserDMG1(struct mMapCache* cache, struct mMapCacheEntry* entry, void* vram) { + UNUSED(cache); + int map = *(int8_t*) vram; + entry->tileId = map + 128; + entry->flags = mMapCacheEntryFlagsClearHMirror(entry->flags); + entry->flags = mMapCacheEntryFlagsClearVMirror(entry->flags); + entry->flags = mMapCacheEntryFlagsSetPaletteId(entry->flags, 0); +} + +static void mapParserCGB0(struct mMapCache* cache, struct mMapCacheEntry* entry, void* vram) { + UNUSED(cache); + int map = *(uint8_t*) vram; + uint8_t attr = ((uint8_t*) vram)[0x2000]; + entry->tileId = map + GBObjAttributesGetBank(attr) * 512; + entry->flags = mMapCacheEntryFlagsSetHMirror(entry->flags, GBObjAttributesGetXFlip(attr)); + entry->flags = mMapCacheEntryFlagsSetVMirror(entry->flags, GBObjAttributesGetYFlip(attr)); + entry->flags = mMapCacheEntryFlagsSetPaletteId(entry->flags, GBObjAttributesGetCGBPalette(attr)); +} + +static void mapParserCGB1(struct mMapCache* cache, struct mMapCacheEntry* entry, void* vram) { + UNUSED(cache); + int map = *(int8_t*) vram; + uint8_t attr = ((uint8_t*) vram)[0x2000]; + entry->tileId = map + 128 + GBObjAttributesGetBank(attr) * 512; + entry->flags = mMapCacheEntryFlagsSetHMirror(entry->flags, GBObjAttributesGetXFlip(attr)); + entry->flags = mMapCacheEntryFlagsSetVMirror(entry->flags, GBObjAttributesGetYFlip(attr)); + entry->flags = mMapCacheEntryFlagsSetPaletteId(entry->flags, GBObjAttributesGetCGBPalette(attr)); +} + +void GBVideoCacheWriteVideoRegister(struct mCacheSet* cache, uint16_t address, uint8_t value) { + if (address != REG_LCDC) { + return; + } + struct mMapCache* map = mMapCacheSetGetPointer(&cache->maps, 0); + struct mMapCache* window = mMapCacheSetGetPointer(&cache->maps, 1); + + mMapCacheSystemInfo sysconfig = mMapCacheSystemInfoIsPaletteCount(map->sysConfig); + int tileStart = 0; + int mapStart = GB_BASE_MAP; + int windowStart = GB_BASE_MAP; + if (GBRegisterLCDCIsTileMap(value)) { + mapStart += GB_SIZE_MAP; + } + if (GBRegisterLCDCIsWindowTileMap(value)) { + windowStart += GB_SIZE_MAP; + } + if (GBRegisterLCDCIsTileData(value)) { + if (!sysconfig) { + map->mapParser = mapParserDMG0; + window->mapParser = mapParserDMG0; + } else { + map->mapParser = mapParserCGB0; + window->mapParser = mapParserCGB0; + } + } else { + if (!sysconfig) { + map->mapParser = mapParserDMG1; + window->mapParser = mapParserDMG1; + } else { + map->mapParser = mapParserCGB1; + window->mapParser = mapParserCGB1; + } + tileStart = 0x80; + } + map->tileStart = tileStart; + window->tileStart = tileStart; + if (sysconfig) { + sysconfig = mMapCacheSystemInfoSetMaxTiles(sysconfig, 896); + } else { + sysconfig = mMapCacheSystemInfoSetMaxTiles(sysconfig, 384); + } + sysconfig = mMapCacheSystemInfoSetPaletteBPP(sysconfig, 1); + sysconfig = mMapCacheSystemInfoSetMapAlign(sysconfig, 0); + sysconfig = mMapCacheSystemInfoSetTilesHigh(sysconfig, 5); + sysconfig = mMapCacheSystemInfoSetTilesWide(sysconfig, 5); + mMapCacheConfigureSystem(map, sysconfig); + mMapCacheConfigureSystem(window, sysconfig); + mMapCacheConfigureMap(map, mapStart); + mMapCacheConfigureMap(window, windowStart); } diff --git a/src/gb/renderers/software.c b/src/gb/renderers/software.c index 0e34b22f1..0c3526960 100644 --- a/src/gb/renderers/software.c +++ b/src/gb/renderers/software.c @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -194,6 +195,9 @@ static void GBVideoSoftwareRendererDeinit(struct GBVideoRenderer* renderer) { static uint8_t GBVideoSoftwareRendererWriteVideoRegister(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value) { struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer; + if (renderer->cache) { + GBVideoCacheWriteVideoRegister(renderer->cache, address, value); + } switch (address) { case REG_LCDC: softwareRenderer->lcdc = value; diff --git a/src/gb/video.c b/src/gb/video.c index d79ce6873..fea78d19b 100644 --- a/src/gb/video.c +++ b/src/gb/video.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -693,8 +694,9 @@ static void GBVideoDummyRendererDeinit(struct GBVideoRenderer* renderer) { } static uint8_t GBVideoDummyRendererWriteVideoRegister(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value) { - UNUSED(renderer); - UNUSED(address); + if (renderer->cache) { + GBVideoCacheWriteVideoRegister(renderer->cache, address, value); + } return value; } diff --git a/src/platform/qt/MapView.cpp b/src/platform/qt/MapView.cpp index b303a2c82..ec2342c11 100644 --- a/src/platform/qt/MapView.cpp +++ b/src/platform/qt/MapView.cpp @@ -72,7 +72,6 @@ void MapView::selectMap(int map) { updateTiles(true); } -#ifdef M_CORE_GBA void MapView::updateTilesGBA(bool force) { QImage bg; { @@ -98,10 +97,10 @@ void MapView::updateTilesGBA(bool force) { } m_ui.map->setPixmap(map); } -#endif #ifdef M_CORE_GB void MapView::updateTilesGB(bool force) { + updateTilesGBA(force); } #endif