all repos — mgba @ df9616c15c58454332c0dfb7f2b37e0098f518b9

mGBA Game Boy Advance Emulator

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}