diff --git a/include/mgba/core/cache-set.h b/include/mgba/core/cache-set.h new file mode 100644 index 000000000..8fed166a9 --- /dev/null +++ b/include/mgba/core/cache-set.h @@ -0,0 +1,35 @@ +/* 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/. */ +#ifndef M_CACHE_SET_H +#define M_CACHE_SET_H + +#include + +CXX_GUARD_START + +#include +#include +#include + +DECLARE_VECTOR(mMapCacheSet, struct mMapCache); +DECLARE_VECTOR(mTileCacheSet, struct mTileCache); + +struct mCacheSet { + struct mMapCacheSet maps; + struct mTileCacheSet tiles; +}; + +void mCacheSetInit(struct mCacheSet*, size_t nMaps, size_t nTiles); +void mCacheSetDeinit(struct mCacheSet*); + +void mCacheSetAssignVRAM(struct mCacheSet*, void* vram); + +void mCacheSetWriteVRAM(struct mCacheSet*, uint32_t address); +void mCacheSetWritePalette(struct mCacheSet*, uint32_t entry, color_t color); + +CXX_GUARD_END + +#endif diff --git a/include/mgba/core/interface.h b/include/mgba/core/interface.h index 053b5b1d1..e5c9dde18 100644 --- a/include/mgba/core/interface.h +++ b/include/mgba/core/interface.h @@ -47,10 +47,7 @@ static inline color_t mColorFrom555(uint16_t value) { color_t color = value; #endif #else - color_t color = 0; - color |= (value << 3) & 0xF8; - color |= (value << 6) & 0xF800; - color |= (value << 9) & 0xF80000; + color_t color = M_RGB5_TO_BGR8(value); color |= (color >> 5) & 0x070707; #endif return color; diff --git a/include/mgba/core/map-cache.h b/include/mgba/core/map-cache.h new file mode 100644 index 000000000..60a380f00 --- /dev/null +++ b/include/mgba/core/map-cache.h @@ -0,0 +1,71 @@ +/* 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/. */ +#ifndef M_MAP_CACHE_H +#define M_MAP_CACHE_H + +#include + +CXX_GUARD_START + +#include + +DECL_BITFIELD(mMapCacheConfiguration, uint32_t); +DECL_BIT(mMapCacheConfiguration, ShouldStore, 0); + +DECL_BITFIELD(mMapCacheSystemInfo, uint32_t); +DECL_BITS(mMapCacheSystemInfo, PaletteBPP, 0, 2); +DECL_BITS(mMapCacheSystemInfo, PaletteCount, 2, 4); +DECL_BITS(mMapCacheSystemInfo, TilesWide, 8, 4); +DECL_BITS(mMapCacheSystemInfo, TilesHigh, 12, 4); +DECL_BITS(mMapCacheSystemInfo, MaxTiles, 16, 13); +DECL_BITS(mMapCacheSystemInfo, MapAlign, 29, 2); + +DECL_BITFIELD(mMapCacheEntryFlags, uint16_t); +DECL_BITS(mMapCacheEntryFlags, PaletteId, 0, 4); +DECL_BIT(mMapCacheEntryFlags, VramClean, 4); +DECL_BIT(mMapCacheEntryFlags, HMirror, 5); +DECL_BIT(mMapCacheEntryFlags, VMirror, 6); + +struct mMapCacheEntry { + uint32_t vramVersion; + uint16_t tileId; + mMapCacheEntryFlags flags; +}; + +struct mTileCache; +struct mTileCacheEntry; +struct mMapCache { + color_t* cache; + struct mTileCache* tileCache; + struct mTileCacheEntry* tileEntries; + struct mMapCacheEntry* status; + + uint8_t* vram; + + uint32_t mapStart; + uint32_t mapSize; + + uint32_t tileStart; + + mMapCacheConfiguration config; + mMapCacheSystemInfo sysConfig; + + void (*mapParser)(struct mMapCache*, struct mMapCacheEntry* entry, void* vram); +}; + +void mMapCacheInit(struct mMapCache* cache); +void mMapCacheDeinit(struct mMapCache* cache); +void mMapCacheConfigure(struct mMapCache* cache, mMapCacheConfiguration config); +void mMapCacheConfigureSystem(struct mMapCache* cache, mMapCacheSystemInfo config); +void mMapCacheConfigureMap(struct mMapCache* cache, uint32_t mapStart); +void mMapCacheWriteVRAM(struct mMapCache* cache, uint32_t address); + +bool mMapCacheCheckTile(struct mMapCache* cache, const struct mMapCacheEntry* entry, unsigned x, unsigned y); +void mMapCacheCleanTile(struct mMapCache* cache, struct mMapCacheEntry* entry, unsigned x, unsigned y); + +CXX_GUARD_END + +#endif diff --git a/include/mgba/core/tile-cache.h b/include/mgba/core/tile-cache.h index 540705af9..f8600b3ad 100644 --- a/include/mgba/core/tile-cache.h +++ b/include/mgba/core/tile-cache.h @@ -10,14 +10,14 @@ CXX_GUARD_START +#include + DECL_BITFIELD(mTileCacheConfiguration, uint32_t); DECL_BIT(mTileCacheConfiguration, ShouldStore, 0); DECL_BITFIELD(mTileCacheSystemInfo, uint32_t); -DECL_BITS(mTileCacheSystemInfo, Palette0BPP, 0, 2); -DECL_BITS(mTileCacheSystemInfo, Palette0Count, 2, 4); -DECL_BITS(mTileCacheSystemInfo, Palette1BPP, 8, 2); -DECL_BITS(mTileCacheSystemInfo, Palette1Count, 10, 4); +DECL_BITS(mTileCacheSystemInfo, PaletteBPP, 0, 2); +DECL_BITS(mTileCacheSystemInfo, PaletteCount, 2, 4); DECL_BITS(mTileCacheSystemInfo, MaxTiles, 16, 13); struct mTileCacheEntry { @@ -25,24 +25,22 @@ struct mTileCacheEntry { uint32_t vramVersion; uint8_t vramClean; uint8_t paletteId; - uint8_t activePalette; - uint8_t padding; + uint16_t padding; }; struct mTileCache { - uint16_t* cache; + color_t* cache; struct mTileCacheEntry* status; - uint32_t* globalPaletteVersion[2]; + uint32_t* globalPaletteVersion; - int activePalette; - unsigned entries; - unsigned count; + uint32_t tileBase; + uint32_t paletteBase; unsigned entriesPerTile; unsigned bpp; uint16_t* vram; - uint16_t* palette; - uint16_t temporaryTile[64]; + color_t* palette; + color_t temporaryTile[64]; mTileCacheConfiguration config; mTileCacheSystemInfo sysConfig; @@ -51,15 +49,14 @@ struct mTileCache { void mTileCacheInit(struct mTileCache* cache); void mTileCacheDeinit(struct mTileCache* cache); void mTileCacheConfigure(struct mTileCache* cache, mTileCacheConfiguration config); -void mTileCacheConfigureSystem(struct mTileCache* cache, mTileCacheSystemInfo config); +void mTileCacheConfigureSystem(struct mTileCache* cache, mTileCacheSystemInfo config, uint32_t tileBase, uint32_t paletteBase); void mTileCacheWriteVRAM(struct mTileCache* cache, uint32_t address); -void mTileCacheWritePalette(struct mTileCache* cache, uint32_t address); -void mTileCacheSetPalette(struct mTileCache* cache, int palette); +void mTileCacheWritePalette(struct mTileCache* cache, uint32_t entry, color_t color); -const uint16_t* mTileCacheGetTile(struct mTileCache* cache, unsigned tileId, unsigned paletteId); -const uint16_t* mTileCacheGetTileIfDirty(struct mTileCache* cache, struct mTileCacheEntry* entry, unsigned tileId, unsigned paletteId); -const uint8_t* mTileCacheGetRawTile(struct mTileCache* cache, unsigned tileId); -const uint16_t* mTileCacheGetPalette(struct mTileCache* cache, unsigned paletteId); +const color_t* mTileCacheGetTile(struct mTileCache* cache, unsigned tileId, unsigned paletteId); +const color_t* mTileCacheGetTileIfDirty(struct mTileCache* cache, struct mTileCacheEntry* entry, unsigned tileId, unsigned paletteId); +const color_t* mTileCacheGetPalette(struct mTileCache* cache, unsigned paletteId); +const uint16_t* mTileCacheGetVRAM(struct mTileCache* cache, unsigned tileId); CXX_GUARD_END diff --git a/include/mgba/internal/gb/renderers/tile-cache.h b/include/mgba/internal/gb/renderers/cache-set.h similarity index 71% rename from include/mgba/internal/gb/renderers/tile-cache.h rename to include/mgba/internal/gb/renderers/cache-set.h index 1b739ca46..3ee63716c 100644 --- a/include/mgba/internal/gb/renderers/tile-cache.h +++ b/include/mgba/internal/gb/renderers/cache-set.h @@ -11,10 +11,10 @@ CXX_GUARD_START struct GBVideo; -struct mTileCache; +struct mCacheSet; -void GBVideoTileCacheInit(struct mTileCache* cache); -void GBVideoTileCacheAssociate(struct mTileCache* cache, struct GBVideo* video); +void GBVideoCacheInit(struct mCacheSet* cache); +void GBVideoCacheAssociate(struct mCacheSet* cache, struct GBVideo* video); CXX_GUARD_END diff --git a/include/mgba/internal/gb/video.h b/include/mgba/internal/gb/video.h index d44ff2298..f5e958caf 100644 --- a/include/mgba/internal/gb/video.h +++ b/include/mgba/internal/gb/video.h @@ -65,7 +65,7 @@ union GBOAM { uint8_t raw[160]; }; -struct mTileCache; +struct mCacheSet; struct GBVideoRenderer { void (*init)(struct GBVideoRenderer* renderer, enum GBModel model, bool borders); void (*deinit)(struct GBVideoRenderer* renderer); @@ -84,7 +84,7 @@ struct GBVideoRenderer { uint8_t* vram; union GBOAM* oam; - struct mTileCache* cache; + struct mCacheSet* cache; uint8_t* sgbCharRam; uint8_t* sgbMapRam; diff --git a/include/mgba/internal/gba/renderers/tile-cache.h b/include/mgba/internal/gba/renderers/cache-set.h similarity index 53% rename from include/mgba/internal/gba/renderers/tile-cache.h rename to include/mgba/internal/gba/renderers/cache-set.h index 3e2143f35..3ad4f6196 100644 --- a/include/mgba/internal/gba/renderers/tile-cache.h +++ b/include/mgba/internal/gba/renderers/cache-set.h @@ -3,18 +3,19 @@ * 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/. */ -#ifndef GBA_TILE_CACHE_H -#define GBA_TILE_CACHE_H +#ifndef GBA_CACHE_SET_H +#define GBA_CACHE_SET_H #include CXX_GUARD_START struct GBAVideo; -struct mTileCache; +struct mCacheSet; -void GBAVideoTileCacheInit(struct mTileCache* cache); -void GBAVideoTileCacheAssociate(struct mTileCache* cache, struct GBAVideo* video); +void GBAVideoCacheInit(struct mCacheSet* cache); +void GBAVideoCacheAssociate(struct mCacheSet* cache, struct GBAVideo* video); +void GBAVideoCacheWriteVideoRegister(struct mCacheSet* cache, uint32_t address, uint16_t value); CXX_GUARD_END diff --git a/include/mgba/internal/gba/video.h b/include/mgba/internal/gba/video.h index 3a1aa14e8..265cb89aa 100644 --- a/include/mgba/internal/gba/video.h +++ b/include/mgba/internal/gba/video.h @@ -164,7 +164,7 @@ struct GBAVideoRenderer { uint16_t* palette; uint16_t* vram; union GBAOAM* oam; - struct mTileCache* cache; + struct mCacheSet* cache; bool disableBG[4]; bool disableOBJ; diff --git a/src/core/cache-set.c b/src/core/cache-set.c new file mode 100644 index 000000000..7561981e3 --- /dev/null +++ b/src/core/cache-set.c @@ -0,0 +1,62 @@ +/* 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 + +DEFINE_VECTOR(mMapCacheSet, struct mMapCache); +DEFINE_VECTOR(mTileCacheSet, struct mTileCache); + +void mCacheSetInit(struct mCacheSet* cache, size_t nMaps, size_t nTiles) { + mMapCacheSetInit(&cache->maps, nMaps); + mMapCacheSetResize(&cache->maps, nMaps); + mTileCacheSetInit(&cache->tiles, nTiles); + mTileCacheSetResize(&cache->tiles, nTiles); + + size_t i; + for (i = 0; i < nMaps; ++i) { + mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, i)); + } + for (i = 0; i < nTiles; ++i) { + mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, i)); + } +} + +void mCacheSetDeinit(struct mCacheSet* cache) { + size_t i; + for (i = 0; i < mMapCacheSetSize(&cache->maps); ++i) { + mMapCacheDeinit(mMapCacheSetGetPointer(&cache->maps, i)); + } + for (i = 0; i < mTileCacheSetSize(&cache->tiles); ++i) { + mTileCacheDeinit(mTileCacheSetGetPointer(&cache->tiles, i)); + } +} + +void mCacheSetAssignVRAM(struct mCacheSet* cache, void* vram) { + size_t i; + for (i = 0; i < mMapCacheSetSize(&cache->maps); ++i) { + mMapCacheSetGetPointer(&cache->maps, i)->vram = vram; + } + for (i = 0; i < mTileCacheSetSize(&cache->tiles); ++i) { + struct mTileCache* tileCache = mTileCacheSetGetPointer(&cache->tiles, i); + tileCache->vram = (void*) ((uintptr_t) vram + tileCache->tileBase); + } +} + +void mCacheSetWriteVRAM(struct mCacheSet* cache, uint32_t address) { + size_t i; + for (i = 0; i < mMapCacheSetSize(&cache->maps); ++i) { + mMapCacheWriteVRAM(mMapCacheSetGetPointer(&cache->maps, i), address); + } + for (i = 0; i < mTileCacheSetSize(&cache->tiles); ++i) { + mTileCacheWriteVRAM(mTileCacheSetGetPointer(&cache->tiles, i), address); + } +} + +void mCacheSetWritePalette(struct mCacheSet* cache, uint32_t entry, color_t color) { + size_t i; + for (i = 0; i < mTileCacheSetSize(&cache->tiles); ++i) { + mTileCacheWritePalette(mTileCacheSetGetPointer(&cache->tiles, i), entry, color); + } +} diff --git a/src/core/map-cache.c b/src/core/map-cache.c new file mode 100644 index 000000000..4646609dc --- /dev/null +++ b/src/core/map-cache.c @@ -0,0 +1,96 @@ +/* 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 + +void mMapCacheInit(struct mMapCache* cache) { + // TODO: Reconfigurable cache for space savings + cache->cache = NULL; + cache->config = mMapCacheConfigurationFillShouldStore(0); + cache->status = NULL; +} + +static void _freeCache(struct mMapCache* cache) { + size_t tiles = (1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig)) * (1 << mMapCacheSystemInfoGetTilesHigh(cache->sysConfig)); + mappedMemoryFree(cache->cache, 8 * 8 * sizeof(color_t) * tiles); + mappedMemoryFree(cache->status, tiles * sizeof(*cache->status)); + cache->cache = NULL; + cache->status = NULL; +} + +static void _redoCacheSize(struct mMapCache* cache) { + if (!mMapCacheConfigurationIsShouldStore(cache->config)) { + return; + } + + size_t tiles = (1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig)) * (1 << mMapCacheSystemInfoGetTilesHigh(cache->sysConfig)); + cache->cache = anonymousMemoryMap(8 * 8 * sizeof(color_t) * tiles); + cache->status = anonymousMemoryMap(tiles * sizeof(*cache->status)); +} + +void mMapCacheConfigure(struct mMapCache* cache, mMapCacheConfiguration config) { + _freeCache(cache); + cache->config = config; + _redoCacheSize(cache); +} + +void mMapCacheConfigureSystem(struct mMapCache* cache, mMapCacheSystemInfo config) { + _freeCache(cache); + cache->sysConfig = config; + _redoCacheSize(cache); + + size_t mapSize = (1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig)) * (1 << mMapCacheSystemInfoGetTilesHigh(cache->sysConfig)); + cache->mapSize = mapSize << mMapCacheSystemInfoGetMapAlign(cache->sysConfig); +} + +void mMapCacheConfigureMap(struct mMapCache* cache, uint32_t mapStart) { + size_t tiles = (1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig)) * (1 << mMapCacheSystemInfoGetTilesHigh(cache->sysConfig)); + memset(cache->status, 0, tiles * sizeof(*cache->status)); + cache->mapStart = mapStart; +} + +void mMapCacheDeinit(struct mMapCache* cache) { + _freeCache(cache); +} + +void mMapCacheWriteVRAM(struct mMapCache* cache, uint32_t address) { + if (address >= cache->mapStart && address < cache->mapStart + cache->mapSize) { + address >>= mMapCacheSystemInfoGetMapAlign(cache->sysConfig); + ++cache->status[address].vramVersion; + cache->status[address].flags = mMapCacheEntryFlagsClearVramClean(cache->status[address].flags); + } +} + +bool mMapCacheCheckTile(struct mMapCache* cache, const struct mMapCacheEntry* entry, unsigned x, unsigned y) { + size_t location = (1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig)) * y + x; + const struct mMapCacheEntry* status = &cache->status[location]; + return memcmp(status, &entry[location], sizeof(*entry)) == 0; +} + +void mMapCacheCleanTile(struct mMapCache* cache, struct mMapCacheEntry* entry, unsigned x, unsigned y) { + size_t location = (1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig)) * y + x; + struct mMapCacheEntry* status = &cache->status[location]; + status->flags = mMapCacheEntryFlagsFillVramClean(status->flags); + int align = mMapCacheSystemInfoGetMapAlign(cache->sysConfig); + cache->mapParser(cache, status, &cache->vram[(location << align) + cache->mapStart]); + + int bytesPerPixel = 1 << mMapCacheSystemInfoGetPaletteBPP(cache->sysConfig); + size_t stride = bytesPerPixel * (1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig)); + color_t* mapOut = &cache->cache[(y * stride + x) * 8]; + const color_t* tile = mTileCacheGetTileIfDirty(cache->tileCache, cache->tileEntries, status->tileId + cache->tileStart, mMapCacheEntryFlagsGetPaletteId(status->flags)); + memcpy(mapOut, tile, sizeof(color_t) * 8); + memcpy(&mapOut[stride], &tile[0x08], sizeof(color_t) * 8); + memcpy(&mapOut[stride * 2], &tile[0x10], sizeof(color_t) * 8); + memcpy(&mapOut[stride * 3], &tile[0x18], sizeof(color_t) * 8); + memcpy(&mapOut[stride * 4], &tile[0x20], sizeof(color_t) * 8); + memcpy(&mapOut[stride * 5], &tile[0x28], sizeof(color_t) * 8); + memcpy(&mapOut[stride * 6], &tile[0x30], sizeof(color_t) * 8); + memcpy(&mapOut[stride * 7], &tile[0x38], sizeof(color_t) * 8); + + entry[location] = *status; +} diff --git a/src/core/tile-cache.c b/src/core/tile-cache.c index 3c34a8d86..ffb1cf565 100644 --- a/src/core/tile-cache.c +++ b/src/core/tile-cache.c @@ -12,60 +12,42 @@ void mTileCacheInit(struct mTileCache* cache) { cache->cache = NULL; cache->config = mTileCacheConfigurationFillShouldStore(0); cache->status = NULL; - cache->activePalette = 0; - memset(cache->globalPaletteVersion, 0, sizeof(cache->globalPaletteVersion)); + cache->globalPaletteVersion = NULL; + cache->palette = NULL; } static void _freeCache(struct mTileCache* cache) { - unsigned count0; - count0 = 1 << mTileCacheSystemInfoGetPalette0Count(cache->sysConfig); - unsigned count1; - count1 = 1 << mTileCacheSystemInfoGetPalette1Count(cache->sysConfig); + unsigned size = 1 << mTileCacheSystemInfoGetPaletteCount(cache->sysConfig); unsigned tiles = mTileCacheSystemInfoGetMaxTiles(cache->sysConfig); - unsigned size = count0 > count1 ? count0 : count1; if (cache->cache) { - mappedMemoryFree(cache->cache, 8 * 8 * 2 * tiles * size); + mappedMemoryFree(cache->cache, 8 * 8 * sizeof(color_t) * tiles * size); cache->cache = NULL; } if (cache->status) { mappedMemoryFree(cache->status, tiles * size * sizeof(*cache->status)); cache->status = NULL; } - free(cache->globalPaletteVersion[0]); - free(cache->globalPaletteVersion[1]); - memset(cache->globalPaletteVersion, 0, sizeof(cache->globalPaletteVersion)); + free(cache->globalPaletteVersion); + cache->globalPaletteVersion = NULL; + free(cache->palette); + cache->palette = NULL; } static void _redoCacheSize(struct mTileCache* cache) { if (!mTileCacheConfigurationIsShouldStore(cache->config)) { return; } - unsigned count0 = mTileCacheSystemInfoGetPalette0Count(cache->sysConfig); - unsigned bpp0 = mTileCacheSystemInfoGetPalette0BPP(cache->sysConfig); - bpp0 = 1 << (1 << bpp0); - if (count0) { - count0 = 1 << count0; - } - unsigned count1 = mTileCacheSystemInfoGetPalette1Count(cache->sysConfig); - unsigned bpp1 = mTileCacheSystemInfoGetPalette1BPP(cache->sysConfig); - bpp1 = 1 << (1 << bpp1); - if (count1) { - count1 = 1 << count1; - } - unsigned size = count0 > count1 ? count0 : count1; - if (!size) { - return; - } + unsigned size = mTileCacheSystemInfoGetPaletteCount(cache->sysConfig); + unsigned bpp = mTileCacheSystemInfoGetPaletteBPP(cache->sysConfig); + cache->bpp = bpp; + bpp = 1 << (1 << bpp); + size = 1 << size; cache->entriesPerTile = size; unsigned tiles = mTileCacheSystemInfoGetMaxTiles(cache->sysConfig); - cache->cache = anonymousMemoryMap(8 * 8 * 2 * tiles * size); + cache->cache = anonymousMemoryMap(8 * 8 * sizeof(color_t) * tiles * size); cache->status = anonymousMemoryMap(tiles * size * sizeof(*cache->status)); - if (count0) { - cache->globalPaletteVersion[0] = malloc(count0 * bpp0 * sizeof(*cache->globalPaletteVersion[0])); - } - if (count1) { - cache->globalPaletteVersion[1] = malloc(count1 * bpp1 * sizeof(*cache->globalPaletteVersion[1])); - } + cache->globalPaletteVersion = malloc(size * sizeof(*cache->globalPaletteVersion)); + cache->palette = malloc(size * bpp * sizeof(*cache->palette)); } void mTileCacheConfigure(struct mTileCache* cache, mTileCacheConfiguration config) { @@ -74,9 +56,11 @@ void mTileCacheConfigure(struct mTileCache* cache, mTileCacheConfiguration confi _redoCacheSize(cache); } -void mTileCacheConfigureSystem(struct mTileCache* cache, mTileCacheSystemInfo config) { +void mTileCacheConfigureSystem(struct mTileCache* cache, mTileCacheSystemInfo config, uint32_t tileBase, uint32_t paletteBase) { _freeCache(cache); cache->sysConfig = config; + cache->tileBase = tileBase; + cache->paletteBase = paletteBase; _redoCacheSize(cache); } @@ -85,40 +69,41 @@ void mTileCacheDeinit(struct mTileCache* cache) { } void mTileCacheWriteVRAM(struct mTileCache* cache, uint32_t address) { + if (address < cache->tileBase) { + return; + } + address -= cache->tileBase; unsigned bpp = cache->bpp + 3; unsigned count = cache->entriesPerTile; + address >>= bpp; + if (address >= mTileCacheSystemInfoGetMaxTiles(cache->sysConfig)) { + return; + } size_t i; for (i = 0; i < count; ++i) { - cache->status[(address >> bpp) * count + i].vramClean = 0; - ++cache->status[(address >> bpp) * count + i].vramVersion; + cache->status[address * count + i].vramClean = 0; + ++cache->status[address * count + i].vramVersion; } } -void mTileCacheWritePalette(struct mTileCache* cache, uint32_t address) { - if (cache->globalPaletteVersion[0]) { - ++cache->globalPaletteVersion[0][address >> 1]; +void mTileCacheWritePalette(struct mTileCache* cache, uint32_t entry, color_t color) { + if (entry < cache->paletteBase) { + return; } - if (cache->globalPaletteVersion[1]) { - ++cache->globalPaletteVersion[1][address >> 1]; + entry -= cache->paletteBase; + unsigned maxEntry = (1 << (1 << cache->bpp)) * cache->entriesPerTile; + if (entry >= maxEntry) { + return; } + cache->palette[entry] = color; + entry >>= (1 << mTileCacheSystemInfoGetPaletteBPP(cache->sysConfig)); + ++cache->globalPaletteVersion[entry]; } -void mTileCacheSetPalette(struct mTileCache* cache, int palette) { - cache->activePalette = palette; - if (palette == 0) { - cache->bpp = mTileCacheSystemInfoGetPalette0BPP(cache->sysConfig); - cache->count = 1 << mTileCacheSystemInfoGetPalette0Count(cache->sysConfig); - } else { - cache->bpp = mTileCacheSystemInfoGetPalette1BPP(cache->sysConfig); - cache->count = 1 << mTileCacheSystemInfoGetPalette1Count(cache->sysConfig); - } - cache->entries = 1 << (1 << cache->bpp); -} - -static void _regenerateTile4(struct mTileCache* cache, uint16_t* tile, unsigned tileId, unsigned paletteId) { +static void _regenerateTile4(struct mTileCache* cache, color_t* tile, unsigned tileId, unsigned paletteId) { uint8_t* start = (uint8_t*) &cache->vram[tileId << 3]; paletteId <<= 2; - uint16_t* palette = &cache->palette[paletteId]; + color_t* palette = &cache->palette[paletteId]; int i; for (i = 0; i < 8; ++i) { uint8_t tileDataLower = start[0]; @@ -126,87 +111,87 @@ static void _regenerateTile4(struct mTileCache* cache, uint16_t* tile, unsigned start += 2; int pixel; pixel = ((tileDataUpper & 128) >> 6) | ((tileDataLower & 128) >> 7); - tile[0] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF; + tile[0] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel]; pixel = ((tileDataUpper & 64) >> 5) | ((tileDataLower & 64) >> 6); - tile[1] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF; + tile[1] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel]; pixel = ((tileDataUpper & 32) >> 4) | ((tileDataLower & 32) >> 5); - tile[2] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF; + tile[2] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel]; pixel = ((tileDataUpper & 16) >> 3) | ((tileDataLower & 16) >> 4); - tile[3] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF; + tile[3] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel]; pixel = ((tileDataUpper & 8) >> 2) | ((tileDataLower & 8) >> 3); - tile[4] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF; + tile[4] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel]; pixel = ((tileDataUpper & 4) >> 1) | ((tileDataLower & 4) >> 2); - tile[5] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF; + tile[5] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel]; pixel = (tileDataUpper & 2) | ((tileDataLower & 2) >> 1); - tile[6] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF; + tile[6] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel]; pixel = ((tileDataUpper & 1) << 1) | (tileDataLower & 1); - tile[7] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF; + tile[7] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel]; tile += 8; } } -static void _regenerateTile16(struct mTileCache* cache, uint16_t* tile, unsigned tileId, unsigned paletteId) { +static void _regenerateTile16(struct mTileCache* cache, color_t* tile, unsigned tileId, unsigned paletteId) { uint32_t* start = (uint32_t*) &cache->vram[tileId << 4]; paletteId <<= 4; - uint16_t* palette = &cache->palette[paletteId]; + color_t* palette = &cache->palette[paletteId]; int i; for (i = 0; i < 8; ++i) { uint32_t line = *start; ++start; int pixel; pixel = line & 0xF; - tile[0] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF; + tile[0] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel]; pixel = (line >> 4) & 0xF; - tile[1] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF; + tile[1] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel]; pixel = (line >> 8) & 0xF; - tile[2] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF; + tile[2] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel]; pixel = (line >> 12) & 0xF; - tile[3] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF; + tile[3] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel]; pixel = (line >> 16) & 0xF; - tile[4] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF; + tile[4] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel]; pixel = (line >> 20) & 0xF; - tile[5] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF; + tile[5] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel]; pixel = (line >> 24) & 0xF; - tile[6] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF; + tile[6] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel]; pixel = (line >> 28) & 0xF; - tile[7] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF; + tile[7] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel]; tile += 8; } } -static void _regenerateTile256(struct mTileCache* cache, uint16_t* tile, unsigned tileId, unsigned paletteId) { +static void _regenerateTile256(struct mTileCache* cache, color_t* tile, unsigned tileId, unsigned paletteId) { uint32_t* start = (uint32_t*) &cache->vram[tileId << 5]; paletteId <<= 8; - uint16_t* palette = &cache->palette[paletteId]; + color_t* palette = &cache->palette[paletteId]; int i; for (i = 0; i < 8; ++i) { uint32_t line = *start; ++start; int pixel; pixel = line & 0xFF; - tile[0] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF; + tile[0] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel]; pixel = (line >> 8) & 0xFF; - tile[1] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF; + tile[1] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel]; pixel = (line >> 16) & 0xFF; - tile[2] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF; + tile[2] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel]; pixel = (line >> 24) & 0xFF; - tile[3] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF; + tile[3] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel]; line = *start; ++start; pixel = line & 0xFF; - tile[4] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF; + tile[4] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel]; pixel = (line >> 8) & 0xFF; - tile[5] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF; + tile[5] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel]; pixel = (line >> 16) & 0xFF; - tile[6] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF; + tile[6] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel]; pixel = (line >> 24) & 0xFF; - tile[7] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF; + tile[7] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel]; tile += 8; } } -static inline uint16_t* _tileLookup(struct mTileCache* cache, unsigned tileId, unsigned paletteId) { +static inline color_t* _tileLookup(struct mTileCache* cache, unsigned tileId, unsigned paletteId) { if (mTileCacheConfigurationIsShouldStore(cache->config)) { unsigned tiles = mTileCacheSystemInfoGetMaxTiles(cache->sysConfig); return &cache->cache[(tileId + paletteId * tiles) << 6]; @@ -215,19 +200,17 @@ static inline uint16_t* _tileLookup(struct mTileCache* cache, unsigned tileId, u } } -const uint16_t* mTileCacheGetTile(struct mTileCache* cache, unsigned tileId, unsigned paletteId) { - unsigned cPaletteId = cache->activePalette; +const color_t* mTileCacheGetTile(struct mTileCache* cache, unsigned tileId, unsigned paletteId) { unsigned count = cache->entriesPerTile; unsigned bpp = cache->bpp; struct mTileCacheEntry* status = &cache->status[tileId * count + paletteId]; struct mTileCacheEntry desiredStatus = { - .paletteVersion = cache->globalPaletteVersion[cPaletteId][paletteId], + .paletteVersion = cache->globalPaletteVersion[paletteId], .vramVersion = status->vramVersion, .vramClean = 1, - .paletteId = paletteId, - .activePalette = cPaletteId + .paletteId = paletteId }; - uint16_t* tile = _tileLookup(cache, tileId, paletteId); + color_t* tile = _tileLookup(cache, tileId, paletteId); if (!mTileCacheConfigurationIsShouldStore(cache->config) || memcmp(status, &desiredStatus, sizeof(*status))) { switch (bpp) { case 0: @@ -247,19 +230,17 @@ const uint16_t* mTileCacheGetTile(struct mTileCache* cache, unsigned tileId, uns return tile; } -const uint16_t* mTileCacheGetTileIfDirty(struct mTileCache* cache, struct mTileCacheEntry* entry, unsigned tileId, unsigned paletteId) { - unsigned cPaletteId = cache->activePalette; +const color_t* mTileCacheGetTileIfDirty(struct mTileCache* cache, struct mTileCacheEntry* entry, unsigned tileId, unsigned paletteId) { unsigned count = cache->entriesPerTile; unsigned bpp = cache->bpp; struct mTileCacheEntry* status = &cache->status[tileId * count + paletteId]; struct mTileCacheEntry desiredStatus = { - .paletteVersion = cache->globalPaletteVersion[cPaletteId][paletteId], + .paletteVersion = cache->globalPaletteVersion[paletteId], .vramVersion = status->vramVersion, .vramClean = 1, - .paletteId = paletteId, - .activePalette = cPaletteId + .paletteId = paletteId }; - uint16_t* tile = NULL; + color_t* tile = NULL; if (memcmp(status, &desiredStatus, sizeof(*status))) { tile = _tileLookup(cache, tileId, paletteId); switch (bpp) { @@ -284,26 +265,10 @@ const uint16_t* mTileCacheGetTileIfDirty(struct mTileCache* cache, struct mTileC return tile; } -const uint8_t* mTileCacheGetRawTile(struct mTileCache* cache, unsigned tileId) { - unsigned bpp = cache->bpp; - switch (bpp) { - case 0: - return NULL; - default: - return (uint8_t*) &cache->vram[tileId << (2 + bpp)]; - } +const color_t* mTileCacheGetPalette(struct mTileCache* cache, unsigned paletteId) { + return &cache->palette[paletteId << (1 << cache->bpp)]; } -const uint16_t* mTileCacheGetPalette(struct mTileCache* cache, unsigned paletteId) { - unsigned bpp = cache->bpp; - switch (bpp) { - default: - return NULL; - case 1: - return &cache->palette[paletteId << 2]; - case 2: - return &cache->palette[paletteId << 4]; - case 3: - return &cache->palette[paletteId << 8]; - } +const uint16_t* mTileCacheGetVRAM(struct mTileCache* cache, unsigned tileId) { + return &cache->vram[tileId << (cache->bpp + 2)]; } diff --git a/src/gb/extra/proxy.c b/src/gb/extra/proxy.c index 9dc1d8fb3..eb2c29e79 100644 --- a/src/gb/extra/proxy.c +++ b/src/gb/extra/proxy.c @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include -#include +#include #include #include @@ -203,7 +203,7 @@ void GBVideoProxyRendererWriteVRAM(struct GBVideoRenderer* renderer, uint16_t ad proxyRenderer->backend->writeVRAM(proxyRenderer->backend, address); } if (renderer->cache) { - mTileCacheWriteVRAM(renderer->cache, address); + mCacheSetWriteVRAM(renderer->cache, address); } } @@ -214,7 +214,7 @@ void GBVideoProxyRendererWritePalette(struct GBVideoRenderer* renderer, int addr proxyRenderer->backend->writePalette(proxyRenderer->backend, address, value); } if (renderer->cache) { - mTileCacheWritePalette(renderer->cache, address); + mCacheSetWritePalette(renderer->cache, address, mColorFrom555(value)); } } diff --git a/src/gb/renderers/cache-set.c b/src/gb/renderers/cache-set.c new file mode 100644 index 000000000..a2f34992b --- /dev/null +++ b/src/gb/renderers/cache-set.c @@ -0,0 +1,28 @@ +/* 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 + +void GBVideoCacheInit(struct mCacheSet* cache) { + mCacheSetInit(cache, 0, 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); +} + +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])); + } +} diff --git a/src/gb/renderers/software.c b/src/gb/renderers/software.c index a5f28b133..0e34b22f1 100644 --- a/src/gb/renderers/software.c +++ b/src/gb/renderers/software.c @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include -#include +#include #include #include #include @@ -284,13 +284,13 @@ static void GBVideoSoftwareRendererWritePalette(struct GBVideoRenderer* renderer color_t color = mColorFrom555(value); softwareRenderer->palette[index] = color; if (renderer->cache) { - mTileCacheWritePalette(renderer->cache, index << 1); + mCacheSetWritePalette(renderer->cache, index, color); } } static void GBVideoSoftwareRendererWriteVRAM(struct GBVideoRenderer* renderer, uint16_t address) { if (renderer->cache) { - mTileCacheWriteVRAM(renderer->cache, address); + mCacheSetWriteVRAM(renderer->cache, address); } } diff --git a/src/gb/renderers/tile-cache.c b/src/gb/renderers/tile-cache.c deleted file mode 100644 index 4780649b8..000000000 --- a/src/gb/renderers/tile-cache.c +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright (c) 2013-2016 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 - -void GBVideoTileCacheInit(struct mTileCache* cache) { - mTileCacheInit(cache); - mTileCacheConfiguration config = 0; - config = mTileCacheSystemInfoSetPalette0BPP(config, 1); // 2^(2^2) = 4 entries - config = mTileCacheSystemInfoSetPalette0Count(config, 4); // 16 palettes - config = mTileCacheSystemInfoSetPalette1BPP(config, 0); // Disable - config = mTileCacheSystemInfoSetPalette1Count(config, 0); // Disable - config = mTileCacheSystemInfoSetMaxTiles(config, 1024); - mTileCacheConfigureSystem(cache, config); -} - -void GBVideoTileCacheAssociate(struct mTileCache* cache, struct GBVideo* video) { - cache->vram = (uint16_t*) video->vram; - cache->palette = video->palette; - video->renderer->cache = cache; -} diff --git a/src/gb/video.c b/src/gb/video.c index f98a6c77b..d79ce6873 100644 --- a/src/gb/video.c +++ b/src/gb/video.c @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include #include @@ -705,7 +705,7 @@ static void GBVideoDummyRendererWriteSGBPacket(struct GBVideoRenderer* renderer, static void GBVideoDummyRendererWriteVRAM(struct GBVideoRenderer* renderer, uint16_t address) { if (renderer->cache) { - mTileCacheWriteVRAM(renderer->cache, address); + mCacheSetWriteVRAM(renderer->cache, address); } } @@ -716,9 +716,8 @@ static void GBVideoDummyRendererWriteOAM(struct GBVideoRenderer* renderer, uint1 } static void GBVideoDummyRendererWritePalette(struct GBVideoRenderer* renderer, int index, uint16_t value) { - UNUSED(value); if (renderer->cache) { - mTileCacheWritePalette(renderer->cache, index << 1); + mCacheSetWritePalette(renderer->cache, index, mColorFrom555(value)); } } diff --git a/src/gba/extra/proxy.c b/src/gba/extra/proxy.c index e75da94c4..da38540a3 100644 --- a/src/gba/extra/proxy.c +++ b/src/gba/extra/proxy.c @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include -#include +#include #include #include @@ -206,7 +206,7 @@ void GBAVideoProxyRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t proxyRenderer->backend->writeVRAM(proxyRenderer->backend, address); } if (renderer->cache) { - mTileCacheWriteVRAM(renderer->cache, address); + mCacheSetWriteVRAM(renderer->cache, address); } } @@ -217,7 +217,7 @@ void GBAVideoProxyRendererWritePalette(struct GBAVideoRenderer* renderer, uint32 proxyRenderer->backend->writePalette(proxyRenderer->backend, address, value); } if (renderer->cache) { - mTileCacheWritePalette(renderer->cache, address); + mCacheSetWritePalette(renderer->cache, address >> 1, mColorFrom555(value)); } } diff --git a/src/gba/renderers/cache-set.c b/src/gba/renderers/cache-set.c new file mode 100644 index 000000000..dd236225b --- /dev/null +++ b/src/gba/renderers/cache-set.c @@ -0,0 +1,158 @@ +/* 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 GBAVideoCacheInit(struct mCacheSet* cache) { + mCacheSetInit(cache, 4, 4); + mTileCacheSystemInfo sysconfig = 0; + mTileCacheConfiguration config = mTileCacheConfigurationFillShouldStore(0); + sysconfig = mTileCacheSystemInfoSetPaletteBPP(sysconfig, 2); // 2^(2^2) = 16 entries + sysconfig = mTileCacheSystemInfoSetPaletteCount(sysconfig, 4); // 16 palettes + sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 2048); + mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, 0)); + mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 0), config); + mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 0), sysconfig, 0, 0); + sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 1024); + mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, 2)); + mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 2), config); + mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 2), sysconfig, 0x10000, 0x100); + + sysconfig = mTileCacheSystemInfoSetPaletteBPP(sysconfig, 3); // 2^(2^3) = 256 entries + sysconfig = mTileCacheSystemInfoSetPaletteCount(sysconfig, 0); // 1 palettes + sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 2048); + mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, 1)); + mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 1), config); + mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 1), sysconfig, 0, 0); + sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 1024); + mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, 3)); + mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 3), config); + mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 3), sysconfig, 0x10000, 0x100); + + mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 0)); + mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 1)); + mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 2)); + mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 3)); +} + +void GBAVideoCacheAssociate(struct mCacheSet* cache, struct GBAVideo* video) { + mCacheSetAssignVRAM(cache, video->vram); + video->renderer->cache = cache; + size_t i; + for (i = 0; i < SIZE_PALETTE_RAM / 2; ++i) { + mCacheSetWritePalette(cache, i, mColorFrom555(video->palette[i])); + } +} + +static void mapParser0(struct mMapCache* cache, struct mMapCacheEntry* entry, void* vram) { + UNUSED(cache); + uint16_t map = *(uint16_t*) vram; + entry->tileId = GBA_TEXT_MAP_TILE(map); + entry->flags = mMapCacheEntryFlagsSetHMirror(entry->flags, GBA_TEXT_MAP_HFLIP(map)); + entry->flags = mMapCacheEntryFlagsSetHMirror(entry->flags, GBA_TEXT_MAP_VFLIP(map)); + entry->flags = mMapCacheEntryFlagsSetPaletteId(entry->flags, GBA_TEXT_MAP_PALETTE(map)); +} + +static void mapParser2(struct mMapCache* cache, struct mMapCacheEntry* entry, void* vram) { + UNUSED(cache); + entry->tileId = *(uint8_t*) vram; + entry->flags = mMapCacheEntryFlagsClearHMirror(entry->flags); + entry->flags = mMapCacheEntryFlagsClearHMirror(entry->flags); + entry->flags = mMapCacheEntryFlagsClearPaletteId(entry->flags); +} + +static void GBAVideoCacheWriteDISPCNT(struct mCacheSet* cache, uint16_t value) { + switch (GBARegisterDISPCNTGetMode(value)) { + case 0: + default: + mMapCacheSetGetPointer(&cache->maps, 0)->mapParser = mapParser0; + mMapCacheSetGetPointer(&cache->maps, 1)->mapParser = mapParser0; + mMapCacheSetGetPointer(&cache->maps, 2)->mapParser = mapParser0; + mMapCacheSetGetPointer(&cache->maps, 3)->mapParser = mapParser0; + + mMapCacheSetGetPointer(&cache->maps, 0)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0); + mMapCacheSetGetPointer(&cache->maps, 1)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0); + mMapCacheSetGetPointer(&cache->maps, 2)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0); + mMapCacheSetGetPointer(&cache->maps, 3)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0); + break; + case 1: + case 2: + mMapCacheSetGetPointer(&cache->maps, 0)->mapParser = mapParser0; + mMapCacheSetGetPointer(&cache->maps, 1)->mapParser = mapParser0; + mMapCacheSetGetPointer(&cache->maps, 2)->mapParser = mapParser2; + mMapCacheSetGetPointer(&cache->maps, 3)->mapParser = mapParser2; + + mMapCacheSetGetPointer(&cache->maps, 0)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 1); + mMapCacheSetGetPointer(&cache->maps, 1)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 1); + mMapCacheSetGetPointer(&cache->maps, 2)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 1); + mMapCacheSetGetPointer(&cache->maps, 3)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 1); + break; + } +} + +static void GBAVideoCacheWriteBGCNT(struct mCacheSet* cache, size_t bg, uint16_t value) { + struct mMapCache* map = mMapCacheSetGetPointer(&cache->maps, bg); + + int tileStart = GBARegisterBGCNTGetCharBase(value) * 128; + bool p = GBARegisterBGCNTGet256Color(value); + mMapCacheConfigureMap(map, GBARegisterBGCNTGetScreenBase(value) << 11); + int size = GBARegisterBGCNTGetSize(value); + int tilesWide = 0; + int tilesHigh = 0; + mMapCacheSystemInfo sysconfig = 0; + if (map->mapParser == mapParser0) { + sysconfig = mMapCacheSystemInfoSetPaletteBPP(sysconfig, 2 + p); + sysconfig = mMapCacheSystemInfoSetPaletteCount(sysconfig, 4 * !p); + sysconfig = mMapCacheSystemInfoSetMaxTiles(sysconfig, 512); + sysconfig = mMapCacheSystemInfoSetMapAlign(sysconfig, 1); + tilesWide = 5; + tilesHigh = 5; + if (size & 1) { + ++tilesWide; + } + if (size & 2) { + ++tilesHigh; + } + map->tileStart = tileStart * 2; + } else if (map->mapParser == mapParser2) { + sysconfig = mMapCacheSystemInfoSetPaletteBPP(sysconfig, 3); + sysconfig = mMapCacheSystemInfoSetPaletteCount(sysconfig, 0); + sysconfig = mMapCacheSystemInfoSetMaxTiles(sysconfig, 256); + sysconfig = mMapCacheSystemInfoSetMapAlign(sysconfig, 0); + + tilesHigh = 4 + size; + tilesWide = 4 + size; + map->tileStart = tileStart; + } + sysconfig = mMapCacheSystemInfoSetTilesHigh(sysconfig, tilesHigh); + sysconfig = mMapCacheSystemInfoSetTilesWide(sysconfig, tilesWide); + mMapCacheConfigureSystem(map, sysconfig); +} + +void GBAVideoCacheWriteVideoRegister(struct mCacheSet* cache, uint32_t address, uint16_t value) { + switch (address) { + case REG_DISPCNT: + GBAVideoCacheWriteDISPCNT(cache, value); + break; + case REG_BG0CNT: + GBAVideoCacheWriteBGCNT(cache, 0, value); + break; + case REG_BG1CNT: + GBAVideoCacheWriteBGCNT(cache, 1, value); + break; + case REG_BG2CNT: + GBAVideoCacheWriteBGCNT(cache, 2, value); + break; + case REG_BG3CNT: + GBAVideoCacheWriteBGCNT(cache, 3, value); + break; + + } +} diff --git a/src/gba/renderers/tile-cache.c b/src/gba/renderers/tile-cache.c deleted file mode 100644 index 20e24849a..000000000 --- a/src/gba/renderers/tile-cache.c +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright (c) 2013-2016 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 - -void GBAVideoTileCacheInit(struct mTileCache* cache) { - mTileCacheInit(cache); - mTileCacheConfiguration config = 0; - config = mTileCacheSystemInfoSetPalette0BPP(config, 2); // 2^(2^2) = 16 entries - config = mTileCacheSystemInfoSetPalette0Count(config, 5); // 32 palettes - config = mTileCacheSystemInfoSetPalette1BPP(config, 3); // 2^(2^3) = 256 entries - config = mTileCacheSystemInfoSetPalette1Count(config, 1); // 2 palettes - config = mTileCacheSystemInfoSetMaxTiles(config, 3072); - mTileCacheConfigureSystem(cache, config); -} - -void GBAVideoTileCacheAssociate(struct mTileCache* cache, struct GBAVideo* video) { - cache->vram = video->vram; - cache->palette = video->palette; - video->renderer->cache = cache; -} diff --git a/src/gba/renderers/video-software.c b/src/gba/renderers/video-software.c index ab1552500..bd8afc88e 100644 --- a/src/gba/renderers/video-software.c +++ b/src/gba/renderers/video-software.c @@ -5,9 +5,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "gba/renderers/software-private.h" -#include +#include #include #include +#include #include #include @@ -149,6 +150,10 @@ static void GBAVideoSoftwareRendererDeinit(struct GBAVideoRenderer* renderer) { static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value) { struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer; + if (renderer->cache) { + GBAVideoCacheWriteVideoRegister(renderer->cache, address, value); + } + switch (address) { case REG_DISPCNT: softwareRenderer->dispcnt = value; @@ -381,7 +386,7 @@ static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRender static void GBAVideoSoftwareRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t address) { struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer; if (renderer->cache) { - mTileCacheWriteVRAM(renderer->cache, address); + mCacheSetWriteVRAM(renderer->cache, address); } memset(softwareRenderer->scanlineDirty, 0xFFFFFFFF, sizeof(softwareRenderer->scanlineDirty)); } @@ -403,7 +408,7 @@ static void GBAVideoSoftwareRendererWritePalette(struct GBAVideoRenderer* render softwareRenderer->variantPalette[address >> 1] = _darken(color, softwareRenderer->bldy); } if (renderer->cache) { - mTileCacheWritePalette(renderer->cache, address); + mCacheSetWritePalette(renderer->cache, address >> 1, color); } memset(softwareRenderer->scanlineDirty, 0xFFFFFFFF, sizeof(softwareRenderer->scanlineDirty)); } diff --git a/src/gba/video.c b/src/gba/video.c index 87af353d1..96ee7f269 100644 --- a/src/gba/video.c +++ b/src/gba/video.c @@ -6,11 +6,12 @@ #include #include -#include +#include #include #include #include #include +#include #include #include @@ -214,7 +215,9 @@ static void GBAVideoDummyRendererDeinit(struct GBAVideoRenderer* renderer) { } static uint16_t GBAVideoDummyRendererWriteVideoRegister(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value) { - UNUSED(renderer); + if (renderer->cache) { + GBAVideoCacheWriteVideoRegister(renderer->cache, address, value); + } switch (address) { case REG_BG0CNT: case REG_BG1CNT: @@ -252,14 +255,13 @@ static uint16_t GBAVideoDummyRendererWriteVideoRegister(struct GBAVideoRenderer* static void GBAVideoDummyRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t address) { if (renderer->cache) { - mTileCacheWriteVRAM(renderer->cache, address); + mCacheSetWriteVRAM(renderer->cache, address); } } static void GBAVideoDummyRendererWritePalette(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value) { - UNUSED(value); if (renderer->cache) { - mTileCacheWritePalette(renderer->cache, address); + mCacheSetWritePalette(renderer->cache, address >> 1, mColorFrom555(value)); } } diff --git a/src/platform/python/_builder.h b/src/platform/python/_builder.h index 2dc4f7b5a..9476a37dc 100644 --- a/src/platform/python/_builder.h +++ b/src/platform/python/_builder.h @@ -31,7 +31,7 @@ void free(void*); #include #include -#include +#include #include #include @@ -49,13 +49,13 @@ void free(void*); #include #include #include -#include +#include #endif #ifdef M_CORE_GB #include #include #include -#include +#include #endif #ifdef USE_DEBUGGERS #include diff --git a/src/platform/python/_builder.py b/src/platform/python/_builder.py index 669473e90..abb7ac305 100644 --- a/src/platform/python/_builder.py +++ b/src/platform/python/_builder.py @@ -24,17 +24,17 @@ ffi.set_source("mgba._pylib", """ #include #include #include -#include +#include #include #include #include #include #include #include -#include +#include #include #include -#include +#include #include #include diff --git a/src/platform/qt/AssetTile.cpp b/src/platform/qt/AssetTile.cpp index c82ffe424..452829f85 100644 --- a/src/platform/qt/AssetTile.cpp +++ b/src/platform/qt/AssetTile.cpp @@ -41,7 +41,7 @@ AssetTile::AssetTile(QWidget* parent) } void AssetTile::setController(std::shared_ptr controller) { - m_tileCache = controller->tileCache(); + m_cacheSet = controller->graphicCaches(); switch (controller->platform()) { #ifdef M_CORE_GBA case PLATFORM_GBA: @@ -70,39 +70,32 @@ void AssetTile::setPalette(int palette) { selectIndex(m_index); } -void AssetTile::setPaletteSet(int palette, int boundary, int max) { - m_index = m_index * (1 + m_paletteSet) / (1 + palette); - if (m_index >= max) { - m_index = max - 1; - } +void AssetTile::setBoundary(int boundary, int set0, int set1) { m_boundary = boundary; - m_paletteSet = palette; - selectIndex(m_index); + m_tileCaches[0] = mTileCacheSetGetPointer(&m_cacheSet->tiles, set0); + m_tileCaches[1] = mTileCacheSetGetPointer(&m_cacheSet->tiles, set1); } void AssetTile::selectIndex(int index) { m_index = index; - const uint16_t* data; + const color_t* data; + mTileCache* tileCache = m_tileCaches[index >= m_boundary]; - mTileCacheSetPalette(m_tileCache, m_paletteSet); - unsigned bpp = 8 << m_tileCache->bpp; - int dispIndex = index; + unsigned bpp = 8 << tileCache->bpp; int paletteId = m_paletteId; int base = m_addressBase; if (index >= m_boundary) { base = m_boundaryBase; - // XXX: Do this better -#ifdef M_CORE_GBA - if (m_boundaryBase == (BASE_VRAM | 0x10000)) { - paletteId += m_tileCache->count / 2; - } -#endif - dispIndex -= m_boundary; + index -= m_boundary; } - data = mTileCacheGetTile(m_tileCache, index, paletteId); - m_ui.tileId->setText(QString::number(dispIndex * (1 + m_paletteSet))); + int dispIndex = index; + if (m_addressWidth == 4 && index >= m_boundary / 2) { + dispIndex -= m_boundary / 2; + } + data = mTileCacheGetTile(tileCache, index, paletteId); + m_ui.tileId->setText(QString::number(dispIndex)); m_ui.address->setText(tr("%0%1%2") - .arg(m_addressWidth == 4 ? index >= m_boundary : 0) + .arg(m_addressWidth == 4 ? index >= m_boundary / 2 : 0) .arg(m_addressWidth == 4 ? ":" : "x") .arg(dispIndex * bpp | base, m_addressWidth, 16, QChar('0'))); for (int i = 0; i < 64; ++i) { @@ -112,24 +105,18 @@ void AssetTile::selectIndex(int index) { } void AssetTile::selectColor(int index) { - const uint16_t* data; - mTileCacheSetPalette(m_tileCache, m_paletteSet); - unsigned bpp = 8 << m_tileCache->bpp; + const color_t* data; + mTileCache* tileCache = m_tileCaches[m_index >= m_boundary]; + unsigned bpp = 8 << tileCache->bpp; int paletteId = m_paletteId; - // XXX: Do this better -#ifdef M_CORE_GBA - if (m_index >= m_boundary && m_boundaryBase == (BASE_VRAM | 0x10000)) { - paletteId += m_tileCache->count / 2; - } -#endif - data = mTileCacheGetTile(m_tileCache, m_index, m_paletteId); - uint16_t color = data[index]; + data = mTileCacheGetTile(tileCache, m_index, m_paletteId); + color_t color = data[index]; m_ui.color->setColor(0, color); m_ui.color->update(); - uint32_t r = M_R5(color); - uint32_t g = M_G5(color); - uint32_t b = M_B5(color); + uint32_t r = color & 0xF8; + uint32_t g = (color >> 8) & 0xF8; + uint32_t b = (color >> 16) & 0xF8; m_ui.r->setText(tr("0x%0 (%1)").arg(r, 2, 16, QChar('0')).arg(r, 2, 10, QChar('0'))); m_ui.g->setText(tr("0x%0 (%1)").arg(g, 2, 16, QChar('0')).arg(g, 2, 10, QChar('0'))); m_ui.b->setText(tr("0x%0 (%1)").arg(b, 2, 16, QChar('0')).arg(b, 2, 10, QChar('0'))); diff --git a/src/platform/qt/AssetTile.h b/src/platform/qt/AssetTile.h index 742a8e85f..dbe6acf57 100644 --- a/src/platform/qt/AssetTile.h +++ b/src/platform/qt/AssetTile.h @@ -9,7 +9,7 @@ #include -#include +#include namespace QGBA { @@ -24,16 +24,16 @@ public: public slots: void setPalette(int); - void setPaletteSet(int, int boundary, int max); + void setBoundary(int boundary, int set0, int set1); void selectIndex(int); void selectColor(int); private: Ui::AssetTile m_ui; - mTileCache* m_tileCache; + mCacheSet* m_cacheSet; + mTileCache* m_tileCaches[2]; int m_paletteId = 0; - int m_paletteSet = 0; int m_index = 0; int m_addressWidth; diff --git a/src/platform/qt/AssetView.cpp b/src/platform/qt/AssetView.cpp index 5ad124ad4..2f48cce32 100644 --- a/src/platform/qt/AssetView.cpp +++ b/src/platform/qt/AssetView.cpp @@ -13,7 +13,7 @@ using namespace QGBA; AssetView::AssetView(std::shared_ptr controller, QWidget* parent) : QWidget(parent) - , m_tileCache(controller->tileCache()) + , m_cacheSet(controller->graphicCaches()) , m_controller(controller) { m_updateTimer.setSingleShot(true); @@ -55,8 +55,8 @@ void AssetView::showEvent(QShowEvent*) { updateTiles(true); } -void AssetView::compositeTile(unsigned tileId, void* buffer, size_t stride, size_t x, size_t y, int depth) { - const uint8_t* tile = mTileCacheGetRawTile(m_tileCache, tileId); +void AssetView::compositeTile(const void* tBuffer, void* buffer, size_t stride, size_t x, size_t y, int depth) { + const uint8_t* tile = static_cast(tBuffer); uint8_t* pixels = static_cast(buffer); size_t base = stride * y + x; switch (depth) { diff --git a/src/platform/qt/AssetView.h b/src/platform/qt/AssetView.h index ed837cd5f..a95483c5e 100644 --- a/src/platform/qt/AssetView.h +++ b/src/platform/qt/AssetView.h @@ -8,7 +8,7 @@ #include #include -#include +#include #include @@ -22,7 +22,7 @@ Q_OBJECT public: AssetView(std::shared_ptr controller, QWidget* parent = nullptr); - void compositeTile(unsigned tileId, void* image, size_t stride, size_t x, size_t y, int depth = 8); + static void compositeTile(const void* tile, void* image, size_t stride, size_t x, size_t y, int depth = 8); protected slots: void updateTiles(); @@ -39,7 +39,7 @@ protected: void resizeEvent(QResizeEvent*) override; void showEvent(QShowEvent*) override; - mTileCache* const m_tileCache; + mCacheSet* const m_cacheSet; private: std::shared_ptr m_controller; diff --git a/src/platform/qt/CoreController.cpp b/src/platform/qt/CoreController.cpp index 7c4b837f0..d7020a2d5 100644 --- a/src/platform/qt/CoreController.cpp +++ b/src/platform/qt/CoreController.cpp @@ -18,12 +18,12 @@ #include #ifdef M_CORE_GBA #include -#include +#include #include #endif #ifdef M_CORE_GB #include -#include +#include #endif #include #include @@ -186,9 +186,9 @@ CoreController::~CoreController() { stop(); disconnect(); - if (m_tileCache) { - mTileCacheDeinit(m_tileCache.get()); - m_tileCache.reset(); + if (m_cacheSet) { + mCacheSetDeinit(m_cacheSet.get()); + m_cacheSet.reset(); } mCoreThreadJoin(&m_threadContext); @@ -268,36 +268,34 @@ void CoreController::clearMultiplayerController() { m_multiplayer = nullptr; } -mTileCache* CoreController::tileCache() { - if (m_tileCache) { - return m_tileCache.get(); +mCacheSet* CoreController::graphicCaches() { + if (m_cacheSet) { + return m_cacheSet.get(); } Interrupter interrupter(this); switch (platform()) { #ifdef M_CORE_GBA case PLATFORM_GBA: { GBA* gba = static_cast(m_threadContext.core->board); - m_tileCache = std::make_unique(); - GBAVideoTileCacheInit(m_tileCache.get()); - GBAVideoTileCacheAssociate(m_tileCache.get(), &gba->video); - mTileCacheSetPalette(m_tileCache.get(), 0); + m_cacheSet = std::make_unique(); + GBAVideoCacheInit(m_cacheSet.get()); + GBAVideoCacheAssociate(m_cacheSet.get(), &gba->video); break; } #endif #ifdef M_CORE_GB case PLATFORM_GB: { GB* gb = static_cast(m_threadContext.core->board); - m_tileCache = std::make_unique(); - GBVideoTileCacheInit(m_tileCache.get()); - GBVideoTileCacheAssociate(m_tileCache.get(), &gb->video); - mTileCacheSetPalette(m_tileCache.get(), 0); + m_cacheSet = std::make_unique(); + GBVideoCacheInit(m_cacheSet.get()); + GBVideoCacheAssociate(m_cacheSet.get(), &gb->video); break; } #endif default: return nullptr; } - return m_tileCache.get(); + return m_cacheSet.get(); } void CoreController::setOverride(std::unique_ptr override) { diff --git a/src/platform/qt/CoreController.h b/src/platform/qt/CoreController.h index 1bbde57a7..c426aa483 100644 --- a/src/platform/qt/CoreController.h +++ b/src/platform/qt/CoreController.h @@ -19,7 +19,7 @@ #include #include #include -#include +#include #ifdef M_CORE_GB #include @@ -78,7 +78,7 @@ public: void clearMultiplayerController(); MultiplayerController* multiplayerController() { return m_multiplayer; } - mTileCache* tileCache(); + mCacheSet* graphicCaches(); int stateSlot() const { return m_stateSlot; } void setOverride(std::unique_ptr override); @@ -173,7 +173,7 @@ private: QByteArray* m_activeBuffer; QByteArray* m_completeBuffer = nullptr; - std::unique_ptr m_tileCache; + std::unique_ptr m_cacheSet; std::unique_ptr m_override; QList> m_resetActions; diff --git a/src/platform/qt/ObjView.cpp b/src/platform/qt/ObjView.cpp index 7201b80bc..99220b543 100644 --- a/src/platform/qt/ObjView.cpp +++ b/src/platform/qt/ObjView.cpp @@ -64,7 +64,7 @@ void ObjView::selectObj(int obj) { void ObjView::translateIndex(int index) { unsigned x = index % m_objInfo.width; unsigned y = index / m_objInfo.width; - m_ui.tile->selectIndex(x + y * m_objInfo.stride + m_tileOffset); + m_ui.tile->selectIndex(x + y * m_objInfo.stride + m_tileOffset + m_boundary); } #ifdef M_CORE_GBA @@ -87,19 +87,19 @@ void ObjView::updateTilesGBA(bool force) { unsigned bits; if (GBAObjAttributesAIs256Color(obj->a)) { m_ui.palette->setText("256-color"); - paletteSet = 1; + paletteSet = 3; + m_ui.tile->setBoundary(1024, 1, 3); m_ui.tile->setPalette(0); - m_ui.tile->setPaletteSet(1, 1024, 1536); - palette = 1; - tile = tile / 2 + 1024; + m_boundary = 1024; + palette = 0; + tile /= 2; bits = 8; } else { m_ui.palette->setText(QString::number(palette)); - paletteSet = 0; + paletteSet = 2; + m_ui.tile->setBoundary(2048, 0, 2); m_ui.tile->setPalette(palette); - m_ui.tile->setPaletteSet(0, 2048, 3072); - palette += 16; - tile += 2048; + m_boundary = 2048; bits = 4; } ObjInfo newInfo{ @@ -120,16 +120,16 @@ void ObjView::updateTilesGBA(bool force) { }; m_objInfo = newInfo; m_tileOffset = tile; - mTileCacheSetPalette(m_tileCache, paletteSet); + mTileCache* tileCache = mTileCacheSetGetPointer(&m_cacheSet->tiles, paletteSet); int i = 0; for (int y = 0; y < height / 8; ++y) { for (int x = 0; x < width / 8; ++x, ++i, ++tile, ++tileBase) { - const uint16_t* data = mTileCacheGetTileIfDirty(m_tileCache, &m_tileStatus[32 * tileBase], tile, palette); + const color_t* data = mTileCacheGetTileIfDirty(tileCache, &m_tileStatus[16 * tileBase], tile, palette); if (data) { m_ui.tiles->setTile(i, data); } else if (force) { - m_ui.tiles->setTile(i, mTileCacheGetTile(m_tileCache, tile, palette)); + m_ui.tiles->setTile(i, mTileCacheGetTile(tileCache, tile, palette)); } } tile += newInfo.stride - width / 8; @@ -178,6 +178,7 @@ void ObjView::updateTilesGB(bool force) { const GB* gb = static_cast(m_controller->thread()->core->board); const GBObj* obj = &gb->video.oam.obj[m_objId]; + mTileCache* tileCache = mTileCacheSetGetPointer(&m_cacheSet->tiles, 0); unsigned width = 8; unsigned height = 8; GBRegisterLCDC lcdc = gb->memory.io[REG_LCDC]; @@ -186,6 +187,7 @@ void ObjView::updateTilesGB(bool force) { } unsigned tile = obj->tile; m_ui.tiles->setTileCount(width * height / 64); + m_ui.tile->setBoundary(1024, 0, 0); m_ui.tiles->setMinimumSize(QSize(width, height) * m_ui.magnification->value()); m_ui.tiles->resize(QSize(width, height) * m_ui.magnification->value()); unsigned palette = 0; @@ -214,18 +216,17 @@ void ObjView::updateTilesGB(bool force) { } m_objInfo = newInfo; m_tileOffset = tile; + m_boundary = 1024; int i = 0; - mTileCacheSetPalette(m_tileCache, 0); m_ui.tile->setPalette(palette); - m_ui.tile->setPaletteSet(0, 512, 1024); for (int y = 0; y < height / 8; ++y, ++i) { unsigned t = tile + i; - const uint16_t* data = mTileCacheGetTileIfDirty(m_tileCache, &m_tileStatus[16 * t], t, palette); + const color_t* data = mTileCacheGetTileIfDirty(tileCache, &m_tileStatus[8 * t], t, palette); if (data) { m_ui.tiles->setTile(i, data); } else if (force) { - m_ui.tiles->setTile(i, mTileCacheGetTile(m_tileCache, t, palette)); + m_ui.tiles->setTile(i, mTileCacheGetTile(tileCache, t, palette)); } } @@ -257,21 +258,17 @@ void ObjView::exportObj() { } CoreController::Interrupter interrupter(m_controller); - mTileCacheSetPalette(m_tileCache, m_objInfo.paletteSet); png_structp png = PNGWriteOpen(vf); png_infop info = PNGWriteHeader8(png, m_objInfo.width * 8, m_objInfo.height * 8); - const uint16_t* rawPalette = mTileCacheGetPalette(m_tileCache, m_objInfo.paletteId); + mTileCache* tileCache = mTileCacheSetGetPointer(&m_cacheSet->tiles, m_objInfo.paletteSet); + const color_t* rawPalette = mTileCacheGetPalette(tileCache, m_objInfo.paletteId); unsigned colors = 1 << m_objInfo.bits; uint32_t palette[256]; - for (unsigned c = 0; c < colors && c < 256; ++c) { - uint16_t color = rawPalette[c]; - palette[c] = M_R8(rawPalette[c]); - palette[c] |= M_G8(rawPalette[c]) << 8; - palette[c] |= M_B8(rawPalette[c]) << 16; - if (c) { - palette[c] |= 0xFF000000; - } + + palette[0] = rawPalette[0]; + for (unsigned c = 1; c < colors && c < 256; ++c) { + palette[c] = rawPalette[c] | 0xFF000000; } PNGWritePalette(png, info, palette, colors); @@ -279,7 +276,7 @@ void ObjView::exportObj() { unsigned t = m_objInfo.tile; for (int y = 0; y < m_objInfo.height; ++y) { for (int x = 0; x < m_objInfo.width; ++x, ++t) { - compositeTile(t, static_cast(buffer), m_objInfo.width * 8, x * 8, y * 8, m_objInfo.bits); + compositeTile(static_cast(mTileCacheGetVRAM(tileCache, t)), reinterpret_cast(buffer), m_objInfo.width * 8, x * 8, y * 8, m_objInfo.bits); } t += m_objInfo.stride - m_objInfo.width; } diff --git a/src/platform/qt/ObjView.h b/src/platform/qt/ObjView.h index f5b628fb1..41677ca92 100644 --- a/src/platform/qt/ObjView.h +++ b/src/platform/qt/ObjView.h @@ -56,6 +56,7 @@ private: } m_objInfo = {}; int m_tileOffset; + int m_boundary; }; } diff --git a/src/platform/qt/Swatch.cpp b/src/platform/qt/Swatch.cpp index 111245413..366b981bb 100644 --- a/src/platform/qt/Swatch.cpp +++ b/src/platform/qt/Swatch.cpp @@ -42,6 +42,14 @@ void Swatch::setColor(int index, uint16_t color) { updateFill(index); } +void Swatch::setColor(int index, uint32_t color) { + m_colors[index].setRgb( + (color >> 0) & 0xFF, + (color >> 8) & 0xFF, + (color >> 16) & 0xFF); + updateFill(index); +} + void Swatch::paintEvent(QPaintEvent* event) { QPainter painter(this); painter.drawPixmap(QPoint(), m_backing); diff --git a/src/platform/qt/Swatch.h b/src/platform/qt/Swatch.h index 971a620b5..c92010d99 100644 --- a/src/platform/qt/Swatch.h +++ b/src/platform/qt/Swatch.h @@ -22,6 +22,7 @@ public: public slots: void setColor(int index, uint16_t); + void setColor(int index, uint32_t); signals: void indexPressed(int index); diff --git a/src/platform/qt/TilePainter.cpp b/src/platform/qt/TilePainter.cpp index a2d99d4af..454530a7c 100644 --- a/src/platform/qt/TilePainter.cpp +++ b/src/platform/qt/TilePainter.cpp @@ -40,14 +40,15 @@ void TilePainter::mousePressEvent(QMouseEvent* event) { emit indexPressed(y * (width() / m_size) + x); } -void TilePainter::setTile(int index, const uint16_t* data) { +void TilePainter::setTile(int index, const color_t* data) { QPainter painter(&m_backing); int w = width() / m_size; int x = index % w; int y = index / w; QRect r(x * m_size, y * m_size, m_size, m_size); - QImage tile(reinterpret_cast(data), 8, 8, QImage::Format_RGB555); - painter.drawImage(r, tile.rgbSwapped()); + QImage tile(reinterpret_cast(data), 8, 8, QImage::Format_ARGB32); + tile = tile.convertToFormat(QImage::Format_RGB32).rgbSwapped(); + painter.drawImage(r, tile); update(r); } diff --git a/src/platform/qt/TilePainter.h b/src/platform/qt/TilePainter.h index 532db6565..7cd4c30bb 100644 --- a/src/platform/qt/TilePainter.h +++ b/src/platform/qt/TilePainter.h @@ -9,6 +9,8 @@ #include #include +#include + namespace QGBA { class TilePainter : public QWidget { @@ -18,7 +20,7 @@ public: TilePainter(QWidget* parent = nullptr); public slots: - void setTile(int index, const uint16_t*); + void setTile(int index, const color_t*); void setTileCount(int tiles); void setTileMagnification(int mag); diff --git a/src/platform/qt/TileView.cpp b/src/platform/qt/TileView.cpp index be8df4b15..2f7a3e4b4 100644 --- a/src/platform/qt/TileView.cpp +++ b/src/platform/qt/TileView.cpp @@ -27,38 +27,30 @@ TileView::TileView(std::shared_ptr controller, QWidget* parent) connect(m_ui.tiles, &TilePainter::indexPressed, m_ui.tile, &AssetTile::selectIndex); connect(m_ui.paletteId, &QAbstractSlider::valueChanged, this, &TileView::updatePalette); - int max = 1024; - int boundary = 1024; switch (m_controller->platform()) { #ifdef M_CORE_GBA case PLATFORM_GBA: - max = 3072; - boundary = 2048; + m_ui.tile->setBoundary(2048, 0, 2); break; #endif #ifdef M_CORE_GB case PLATFORM_GB: - max = 1024; - boundary = 512; m_ui.palette256->setEnabled(false); + m_ui.tile->setBoundary(1024, 0, 0); break; #endif default: return; } - m_ui.tile->setPaletteSet(0, boundary, max); connect(m_ui.palette256, &QAbstractButton::toggled, [this](bool selected) { if (selected) { m_ui.paletteId->setValue(0); } - int max = 1024; - int boundary = 1024; switch (m_controller->platform()) { #ifdef M_CORE_GBA case PLATFORM_GBA: - max = 3072 >> selected; - boundary = 2048 >> selected; + m_ui.tile->setBoundary(2048 >> selected, selected, selected + 2); break; #endif #ifdef M_CORE_GB @@ -68,7 +60,6 @@ TileView::TileView(std::shared_ptr controller, QWidget* parent) default: break; } - m_ui.tile->setPaletteSet(selected, boundary, max); updateTiles(true); }); connect(m_ui.magnification, static_cast(&QSpinBox::valueChanged), [this]() { @@ -80,40 +71,42 @@ TileView::TileView(std::shared_ptr controller, QWidget* parent) void TileView::updateTilesGBA(bool force) { if (m_ui.palette256->isChecked()) { m_ui.tiles->setTileCount(1536); - mTileCacheSetPalette(m_tileCache, 1); + mTileCache* cache = mTileCacheSetGetPointer(&m_cacheSet->tiles, 1); for (int i = 0; i < 1024; ++i) { - const uint16_t* data = mTileCacheGetTileIfDirty(m_tileCache, &m_tileStatus[32 * i], i, 0); + const color_t* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[16 * i], i, 0); if (data) { m_ui.tiles->setTile(i, data); } else if (force) { - m_ui.tiles->setTile(i, mTileCacheGetTile(m_tileCache, i, 0)); + m_ui.tiles->setTile(i, mTileCacheGetTile(cache, i, 0)); } } + cache = mTileCacheSetGetPointer(&m_cacheSet->tiles, 3); for (int i = 1024; i < 1536; ++i) { - const uint16_t* data = mTileCacheGetTileIfDirty(m_tileCache, &m_tileStatus[32 * i], i, 1); + const color_t* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[16 * i], i - 1024, 0); if (data) { m_ui.tiles->setTile(i, data); } else if (force) { - m_ui.tiles->setTile(i, mTileCacheGetTile(m_tileCache, i, 1)); + m_ui.tiles->setTile(i, mTileCacheGetTile(cache, i - 1024, 0)); } } } else { + mTileCache* cache = mTileCacheSetGetPointer(&m_cacheSet->tiles, 0); m_ui.tiles->setTileCount(3072); - mTileCacheSetPalette(m_tileCache, 0); for (int i = 0; i < 2048; ++i) { - const uint16_t* data = mTileCacheGetTileIfDirty(m_tileCache, &m_tileStatus[32 * i], i, m_paletteId); + const color_t* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[16 * i], i, m_paletteId); if (data) { m_ui.tiles->setTile(i, data); } else if (force) { - m_ui.tiles->setTile(i, mTileCacheGetTile(m_tileCache, i, m_paletteId)); + m_ui.tiles->setTile(i, mTileCacheGetTile(cache, i, m_paletteId)); } } + cache = mTileCacheSetGetPointer(&m_cacheSet->tiles, 2); for (int i = 2048; i < 3072; ++i) { - const uint16_t* data = mTileCacheGetTileIfDirty(m_tileCache, &m_tileStatus[32 * i], i, m_paletteId + 16); + const color_t* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[16 * i], i - 2048, m_paletteId); if (data) { m_ui.tiles->setTile(i, data); } else if (force) { - m_ui.tiles->setTile(i, mTileCacheGetTile(m_tileCache, i, m_paletteId + 16)); + m_ui.tiles->setTile(i, mTileCacheGetTile(cache, i - 2048, m_paletteId)); } } } @@ -125,13 +118,13 @@ void TileView::updateTilesGB(bool force) { const GB* gb = static_cast(m_controller->thread()->core->board); int count = gb->model >= GB_MODEL_CGB ? 1024 : 512; m_ui.tiles->setTileCount(count); - mTileCacheSetPalette(m_tileCache, 0); + mTileCache* cache = mTileCacheSetGetPointer(&m_cacheSet->tiles, 0); for (int i = 0; i < count; ++i) { - const uint16_t* data = mTileCacheGetTileIfDirty(m_tileCache, &m_tileStatus[16 * i], i, m_paletteId); + const color_t* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[8 * i], i, m_paletteId); if (data) { m_ui.tiles->setTile(i, data); } else if (force) { - m_ui.tiles->setTile(i, mTileCacheGetTile(m_tileCache, i, m_paletteId)); + m_ui.tiles->setTile(i, mTileCacheGetTile(cache, i, m_paletteId)); } } }