/* Copyright (c) 2013-2017 Jeffrey Pfau * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include void GBVideoCacheInit(struct mCacheSet* cache) { 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) { mCacheSetAssignVRAM(cache, video->vram); video->renderer->cache = cache; size_t i; 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; sysconfig = mMapCacheSystemInfoSetMacroTileSize(sysconfig, 5); 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); }