src/core/map-cache.c (view raw)
1/* Copyright (c) 2013-2017 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include <mgba/core/map-cache.h>
7
8#include <mgba/core/tile-cache.h>
9#include <mgba-util/memory.h>
10
11void mMapCacheInit(struct mMapCache* cache) {
12 // TODO: Reconfigurable cache for space savings
13 cache->cache = NULL;
14 cache->config = mMapCacheConfigurationFillShouldStore(0);
15 cache->status = NULL;
16}
17
18static void _freeCache(struct mMapCache* cache) {
19 size_t tiles = (1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig)) * (1 << mMapCacheSystemInfoGetTilesHigh(cache->sysConfig));
20 mappedMemoryFree(cache->cache, 8 * 8 * sizeof(color_t) * tiles);
21 mappedMemoryFree(cache->status, tiles * sizeof(*cache->status));
22 cache->cache = NULL;
23 cache->status = NULL;
24}
25
26static void _redoCacheSize(struct mMapCache* cache) {
27 if (!mMapCacheConfigurationIsShouldStore(cache->config)) {
28 return;
29 }
30
31 size_t tiles = (1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig)) * (1 << mMapCacheSystemInfoGetTilesHigh(cache->sysConfig));
32 cache->cache = anonymousMemoryMap(8 * 8 * sizeof(color_t) * tiles);
33 cache->status = anonymousMemoryMap(tiles * sizeof(*cache->status));
34}
35
36void mMapCacheConfigure(struct mMapCache* cache, mMapCacheConfiguration config) {
37 _freeCache(cache);
38 cache->config = config;
39 _redoCacheSize(cache);
40}
41
42void mMapCacheConfigureSystem(struct mMapCache* cache, mMapCacheSystemInfo config) {
43 _freeCache(cache);
44 cache->sysConfig = config;
45 _redoCacheSize(cache);
46
47 size_t mapSize = (1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig)) * (1 << mMapCacheSystemInfoGetTilesHigh(cache->sysConfig));
48 cache->mapSize = mapSize << mMapCacheSystemInfoGetMapAlign(cache->sysConfig);
49}
50
51void mMapCacheConfigureMap(struct mMapCache* cache, uint32_t mapStart) {
52 size_t tiles = (1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig)) * (1 << mMapCacheSystemInfoGetTilesHigh(cache->sysConfig));
53 memset(cache->status, 0, tiles * sizeof(*cache->status));
54 cache->mapStart = mapStart;
55}
56
57void mMapCacheDeinit(struct mMapCache* cache) {
58 _freeCache(cache);
59}
60
61void mMapCacheWriteVRAM(struct mMapCache* cache, uint32_t address) {
62 if (address >= cache->mapStart && address < cache->mapStart + cache->mapSize) {
63 address >>= mMapCacheSystemInfoGetMapAlign(cache->sysConfig);
64 ++cache->status[address].vramVersion;
65 cache->status[address].flags = mMapCacheEntryFlagsClearVramClean(cache->status[address].flags);
66 }
67}
68
69bool mMapCacheCheckTile(struct mMapCache* cache, const struct mMapCacheEntry* entry, unsigned x, unsigned y) {
70 size_t location = (1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig)) * y + x;
71 const struct mMapCacheEntry* status = &cache->status[location];
72 return memcmp(status, &entry[location], sizeof(*entry)) == 0;
73}
74
75void mMapCacheCleanTile(struct mMapCache* cache, struct mMapCacheEntry* entry, unsigned x, unsigned y) {
76 size_t location = (1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig)) * y + x;
77 struct mMapCacheEntry* status = &cache->status[location];
78 status->flags = mMapCacheEntryFlagsFillVramClean(status->flags);
79 int align = mMapCacheSystemInfoGetMapAlign(cache->sysConfig);
80 cache->mapParser(cache, status, &cache->vram[(location << align) + cache->mapStart]);
81
82 int bytesPerPixel = 1 << mMapCacheSystemInfoGetPaletteBPP(cache->sysConfig);
83 size_t stride = bytesPerPixel * (1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig));
84 color_t* mapOut = &cache->cache[(y * stride + x) * 8];
85 const color_t* tile = mTileCacheGetTileIfDirty(cache->tileCache, cache->tileEntries, status->tileId + cache->tileStart, mMapCacheEntryFlagsGetPaletteId(status->flags));
86 memcpy(mapOut, tile, sizeof(color_t) * 8);
87 memcpy(&mapOut[stride], &tile[0x08], sizeof(color_t) * 8);
88 memcpy(&mapOut[stride * 2], &tile[0x10], sizeof(color_t) * 8);
89 memcpy(&mapOut[stride * 3], &tile[0x18], sizeof(color_t) * 8);
90 memcpy(&mapOut[stride * 4], &tile[0x20], sizeof(color_t) * 8);
91 memcpy(&mapOut[stride * 5], &tile[0x28], sizeof(color_t) * 8);
92 memcpy(&mapOut[stride * 6], &tile[0x30], sizeof(color_t) * 8);
93 memcpy(&mapOut[stride * 7], &tile[0x38], sizeof(color_t) * 8);
94
95 entry[location] = *status;
96}