all repos — mgba @ a748e0c795a4ab7117eaac78349cecb303873ddf

mGBA Game Boy Advance Emulator

src/gba/renderers/cache-set.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/internal/gba/renderers/cache-set.h>
  7
  8#include <mgba/core/cache-set.h>
  9#include <mgba/internal/gba/gba.h>
 10#include <mgba/internal/gba/io.h>
 11#include <mgba/internal/gba/video.h>
 12
 13void GBAVideoCacheInit(struct mCacheSet* cache) {
 14	mCacheSetInit(cache, 4, 4);
 15	mTileCacheSystemInfo sysconfig = 0;
 16	mTileCacheConfiguration config = mTileCacheConfigurationFillShouldStore(0);
 17	sysconfig = mTileCacheSystemInfoSetPaletteBPP(sysconfig, 2); // 2^(2^2) = 16 entries
 18	sysconfig = mTileCacheSystemInfoSetPaletteCount(sysconfig, 4); // 16 palettes
 19	sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 2048);
 20	mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, 0));
 21	mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 0), config);
 22	mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 0), sysconfig, 0, 0);
 23	sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 1024);
 24	mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, 2));
 25	mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 2), config);
 26	mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 2), sysconfig, 0x10000, 0x100);
 27
 28	sysconfig = mTileCacheSystemInfoSetPaletteBPP(sysconfig, 3); // 2^(2^3) = 256 entries
 29	sysconfig = mTileCacheSystemInfoSetPaletteCount(sysconfig, 0); // 1 palettes
 30	sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 2048);
 31	mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, 1));
 32	mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 1), config);
 33	mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 1), sysconfig, 0, 0);
 34	sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 1024);
 35	mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, 3));
 36	mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 3), config);
 37	mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 3), sysconfig, 0x10000, 0x100);
 38
 39	mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 0));
 40	mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 1));
 41	mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 2));
 42	mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 3));
 43}
 44
 45void GBAVideoCacheAssociate(struct mCacheSet* cache, struct GBAVideo* video) {
 46	mCacheSetAssignVRAM(cache, video->vram);
 47	video->renderer->cache = cache;
 48	size_t i;
 49	for (i = 0; i < SIZE_PALETTE_RAM / 2; ++i) {
 50		mCacheSetWritePalette(cache, i, mColorFrom555(video->palette[i]));
 51	}
 52	GBAVideoCacheWriteVideoRegister(cache, REG_DISPCNT, video->p->memory.io[REG_DISPCNT >> 1]);
 53	GBAVideoCacheWriteVideoRegister(cache, REG_BG0CNT, video->p->memory.io[REG_BG0CNT >> 1]);
 54	GBAVideoCacheWriteVideoRegister(cache, REG_BG1CNT, video->p->memory.io[REG_BG1CNT >> 1]);
 55	GBAVideoCacheWriteVideoRegister(cache, REG_BG2CNT, video->p->memory.io[REG_BG2CNT >> 1]);
 56	GBAVideoCacheWriteVideoRegister(cache, REG_BG3CNT, video->p->memory.io[REG_BG3CNT >> 1]);
 57}
 58
 59static void mapParser0(struct mMapCache* cache, struct mMapCacheEntry* entry, void* vram) {
 60	uint16_t map = *(uint16_t*) vram;
 61	entry->tileId = GBA_TEXT_MAP_TILE(map);
 62	entry->flags = mMapCacheEntryFlagsSetHMirror(entry->flags, !!GBA_TEXT_MAP_HFLIP(map));
 63	entry->flags = mMapCacheEntryFlagsSetVMirror(entry->flags, !!GBA_TEXT_MAP_VFLIP(map));
 64	if (mMapCacheSystemInfoGetPaletteBPP(cache->sysConfig) == 3) {
 65		entry->flags = mMapCacheEntryFlagsClearPaletteId(entry->flags);
 66	} else {
 67		entry->flags = mMapCacheEntryFlagsSetPaletteId(entry->flags, GBA_TEXT_MAP_PALETTE(map));
 68	}
 69}
 70
 71static void mapParser2(struct mMapCache* cache, struct mMapCacheEntry* entry, void* vram) {
 72	UNUSED(cache);
 73	entry->tileId = *(uint8_t*) vram;
 74	entry->flags = mMapCacheEntryFlagsClearHMirror(entry->flags);
 75	entry->flags = mMapCacheEntryFlagsClearVMirror(entry->flags);
 76	entry->flags = mMapCacheEntryFlagsClearPaletteId(entry->flags);
 77}
 78
 79static void GBAVideoCacheWriteDISPCNT(struct mCacheSet* cache, uint16_t value) {
 80	switch (GBARegisterDISPCNTGetMode(value)) {
 81	case 0:
 82	default:
 83		mMapCacheSetGetPointer(&cache->maps, 0)->mapParser = mapParser0;
 84		mMapCacheSetGetPointer(&cache->maps, 1)->mapParser = mapParser0;
 85		mMapCacheSetGetPointer(&cache->maps, 2)->mapParser = mapParser0;
 86		mMapCacheSetGetPointer(&cache->maps, 3)->mapParser = mapParser0;
 87
 88		mMapCacheSetGetPointer(&cache->maps, 0)->tileCache = mTileCacheSetGetPointer(&cache->tiles,
 89			mMapCacheSystemInfoGetPaletteBPP(mMapCacheSetGetPointer(&cache->maps, 0)->sysConfig) == 3);
 90		mMapCacheSetGetPointer(&cache->maps, 1)->tileCache = mTileCacheSetGetPointer(&cache->tiles,
 91			mMapCacheSystemInfoGetPaletteBPP(mMapCacheSetGetPointer(&cache->maps, 1)->sysConfig) == 3);
 92		mMapCacheSetGetPointer(&cache->maps, 2)->tileCache = mTileCacheSetGetPointer(&cache->tiles,
 93			mMapCacheSystemInfoGetPaletteBPP(mMapCacheSetGetPointer(&cache->maps, 2)->sysConfig) == 3);
 94		mMapCacheSetGetPointer(&cache->maps, 3)->tileCache = mTileCacheSetGetPointer(&cache->tiles,
 95			mMapCacheSystemInfoGetPaletteBPP(mMapCacheSetGetPointer(&cache->maps, 3)->sysConfig) == 3);
 96		break;
 97	case 1:
 98	case 2:
 99		mMapCacheSetGetPointer(&cache->maps, 0)->mapParser = mapParser0;
100		mMapCacheSetGetPointer(&cache->maps, 1)->mapParser = mapParser0;
101		mMapCacheSetGetPointer(&cache->maps, 2)->mapParser = mapParser2;
102		mMapCacheSetGetPointer(&cache->maps, 3)->mapParser = mapParser2;
103
104		mMapCacheSetGetPointer(&cache->maps, 0)->tileCache = mTileCacheSetGetPointer(&cache->tiles,
105			mMapCacheSystemInfoGetPaletteBPP(mMapCacheSetGetPointer(&cache->maps, 0)->sysConfig) == 3);
106		mMapCacheSetGetPointer(&cache->maps, 1)->tileCache = mTileCacheSetGetPointer(&cache->tiles,
107			mMapCacheSystemInfoGetPaletteBPP(mMapCacheSetGetPointer(&cache->maps, 1)->sysConfig) == 3);
108
109		mMapCacheSetGetPointer(&cache->maps, 2)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 1);
110		mMapCacheSetGetPointer(&cache->maps, 3)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 1);
111		break;
112	}
113}
114
115static void GBAVideoCacheWriteBGCNT(struct mCacheSet* cache, size_t bg, uint16_t value) {
116	struct mMapCache* map = mMapCacheSetGetPointer(&cache->maps, bg);
117	map->context = (void*) (uintptr_t) value;
118
119	int tileStart = GBARegisterBGCNTGetCharBase(value) * 256;
120	bool p = GBARegisterBGCNTGet256Color(value);
121	int size = GBARegisterBGCNTGetSize(value);
122	int tilesWide = 0;
123	int tilesHigh = 0;
124	mMapCacheSystemInfo sysconfig = 0;
125	if (map->mapParser == mapParser0) {
126		map->tileCache = mTileCacheSetGetPointer(&cache->tiles, p);
127		sysconfig = mMapCacheSystemInfoSetPaletteBPP(sysconfig, 2 + p);
128		sysconfig = mMapCacheSystemInfoSetPaletteCount(sysconfig, 4 * !p);
129		sysconfig = mMapCacheSystemInfoSetMacroTileSize(sysconfig, 5);
130		sysconfig = mMapCacheSystemInfoSetMapAlign(sysconfig, 1);
131		tilesWide = 5;
132		tilesHigh = 5;
133		if (size & 1) {
134			++tilesWide;
135		}
136		if (size & 2) {
137			++tilesHigh;
138		}
139		map->tileStart = tileStart * (2 - p);
140	} else if (map->mapParser == mapParser2) {
141		map->tileCache = mTileCacheSetGetPointer(&cache->tiles, 1);
142		sysconfig = mMapCacheSystemInfoSetPaletteBPP(sysconfig, 3);
143		sysconfig = mMapCacheSystemInfoSetPaletteCount(sysconfig, 0);
144		sysconfig = mMapCacheSystemInfoSetMacroTileSize(sysconfig, 4 + size);
145		sysconfig = mMapCacheSystemInfoSetMapAlign(sysconfig, 0);
146
147		tilesHigh = 4 + size;
148		tilesWide = 4 + size;
149		map->tileStart = tileStart;
150	}
151	sysconfig = mMapCacheSystemInfoSetTilesHigh(sysconfig, tilesHigh);
152	sysconfig = mMapCacheSystemInfoSetTilesWide(sysconfig, tilesWide);
153	mMapCacheConfigureSystem(map, sysconfig);
154	mMapCacheConfigureMap(map, GBARegisterBGCNTGetScreenBase(value) << 11);
155}
156
157void GBAVideoCacheWriteVideoRegister(struct mCacheSet* cache, uint32_t address, uint16_t value) {
158	switch (address) {
159	case REG_DISPCNT:
160		GBAVideoCacheWriteDISPCNT(cache, value);
161		GBAVideoCacheWriteBGCNT(cache, 0, (uintptr_t) mMapCacheSetGetPointer(&cache->maps, 0)->context);
162		GBAVideoCacheWriteBGCNT(cache, 1, (uintptr_t) mMapCacheSetGetPointer(&cache->maps, 1)->context);
163		GBAVideoCacheWriteBGCNT(cache, 2, (uintptr_t) mMapCacheSetGetPointer(&cache->maps, 2)->context);
164		GBAVideoCacheWriteBGCNT(cache, 3, (uintptr_t) mMapCacheSetGetPointer(&cache->maps, 3)->context);
165		break;
166	case REG_BG0CNT:
167		GBAVideoCacheWriteBGCNT(cache, 0, value);
168		break;
169	case REG_BG1CNT:
170		GBAVideoCacheWriteBGCNT(cache, 1, value);
171		break;
172	case REG_BG2CNT:
173		GBAVideoCacheWriteBGCNT(cache, 2, value);
174		break;
175	case REG_BG3CNT:
176		GBAVideoCacheWriteBGCNT(cache, 3, value);
177		break;
178
179	}
180}