all repos — mgba @ dd31a888620ad6e8481a4e688f38dc078e75fc37

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, 2, 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	mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 0), sysconfig, 0, 0);
 21	mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 0), config);
 22	sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 1024);
 23	mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 2), sysconfig, 0x10000, 0x100);
 24	mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 2), config);
 25
 26	sysconfig = mTileCacheSystemInfoSetPaletteBPP(sysconfig, 3); // 2^(2^3) = 256 entries
 27	sysconfig = mTileCacheSystemInfoSetPaletteCount(sysconfig, 0); // 1 palettes
 28	sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 2048);
 29	mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 1), sysconfig, 0, 0);
 30	mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 1), config);
 31	sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 1024);
 32	mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 3), sysconfig, 0x10000, 0x100);
 33	mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 3), config);
 34
 35	mBitmapCacheSystemInfo bitConfig;
 36	bitConfig = mBitmapCacheSystemInfoSetEntryBPP(0, 4);
 37	bitConfig = mBitmapCacheSystemInfoClearUsesPalette(bitConfig);
 38	bitConfig = mBitmapCacheSystemInfoSetHeight(bitConfig, 160);
 39	bitConfig = mBitmapCacheSystemInfoSetWidth(bitConfig, 240);
 40	bitConfig = mBitmapCacheSystemInfoSetBuffers(bitConfig, 1);
 41	mBitmapCacheConfigureSystem(mBitmapCacheSetGetPointer(&cache->bitmaps, 0), bitConfig);
 42	mBitmapCacheSetGetPointer(&cache->bitmaps, 0)->bitsStart[0] = 0;
 43	mBitmapCacheSetGetPointer(&cache->bitmaps, 0)->bitsStart[1] = 0xA000;
 44
 45	bitConfig = mBitmapCacheSystemInfoSetEntryBPP(0, 3);
 46	bitConfig = mBitmapCacheSystemInfoFillUsesPalette(bitConfig);
 47	bitConfig = mBitmapCacheSystemInfoSetHeight(bitConfig, 160);
 48	bitConfig = mBitmapCacheSystemInfoSetWidth(bitConfig, 240);
 49	bitConfig = mBitmapCacheSystemInfoSetBuffers(bitConfig, 2);
 50	mBitmapCacheConfigureSystem(mBitmapCacheSetGetPointer(&cache->bitmaps, 1), bitConfig);
 51	mBitmapCacheSetGetPointer(&cache->bitmaps, 1)->bitsStart[0] = 0;
 52	mBitmapCacheSetGetPointer(&cache->bitmaps, 1)->bitsStart[1] = 0xA000;
 53
 54	mMapCacheSetGetPointer(&cache->maps, 0)->context = NULL;
 55	mMapCacheSetGetPointer(&cache->maps, 1)->context = NULL;
 56	mMapCacheSetGetPointer(&cache->maps, 2)->context = NULL;
 57	mMapCacheSetGetPointer(&cache->maps, 3)->context = NULL;
 58}
 59
 60void GBAVideoCacheAssociate(struct mCacheSet* cache, struct GBAVideo* video) {
 61	mCacheSetAssignVRAM(cache, video->vram);
 62	video->renderer->cache = cache;
 63	size_t i;
 64	for (i = 0; i < SIZE_PALETTE_RAM / 2; ++i) {
 65		mCacheSetWritePalette(cache, i, mColorFrom555(video->palette[i]));
 66	}
 67	GBAVideoCacheWriteVideoRegister(cache, REG_DISPCNT, video->p->memory.io[REG_DISPCNT >> 1]);
 68	GBAVideoCacheWriteVideoRegister(cache, REG_BG0CNT, video->p->memory.io[REG_BG0CNT >> 1]);
 69	GBAVideoCacheWriteVideoRegister(cache, REG_BG1CNT, video->p->memory.io[REG_BG1CNT >> 1]);
 70	GBAVideoCacheWriteVideoRegister(cache, REG_BG2CNT, video->p->memory.io[REG_BG2CNT >> 1]);
 71	GBAVideoCacheWriteVideoRegister(cache, REG_BG3CNT, video->p->memory.io[REG_BG3CNT >> 1]);
 72}
 73
 74static void mapParser0(struct mMapCache* cache, struct mMapCacheEntry* entry, void* vram) {
 75	uint16_t map = *(uint16_t*) vram;
 76	entry->tileId = GBA_TEXT_MAP_TILE(map);
 77	entry->flags = mMapCacheEntryFlagsSetHMirror(entry->flags, !!GBA_TEXT_MAP_HFLIP(map));
 78	entry->flags = mMapCacheEntryFlagsSetVMirror(entry->flags, !!GBA_TEXT_MAP_VFLIP(map));
 79	if (mMapCacheSystemInfoGetPaletteBPP(cache->sysConfig) == 3) {
 80		entry->flags = mMapCacheEntryFlagsClearPaletteId(entry->flags);
 81	} else {
 82		entry->flags = mMapCacheEntryFlagsSetPaletteId(entry->flags, GBA_TEXT_MAP_PALETTE(map));
 83	}
 84}
 85
 86static void mapParser2(struct mMapCache* cache, struct mMapCacheEntry* entry, void* vram) {
 87	UNUSED(cache);
 88	entry->tileId = *(uint8_t*) vram;
 89	entry->flags = mMapCacheEntryFlagsClearHMirror(entry->flags);
 90	entry->flags = mMapCacheEntryFlagsClearVMirror(entry->flags);
 91	entry->flags = mMapCacheEntryFlagsClearPaletteId(entry->flags);
 92}
 93
 94static void GBAVideoCacheWriteDISPCNT(struct mCacheSet* cache, uint16_t value) {
 95	mBitmapCacheSetGetPointer(&cache->bitmaps, 1)->buffer = GBARegisterDISPCNTGetFrameSelect(value);
 96
 97	switch (GBARegisterDISPCNTGetMode(value)) {
 98	case 0:
 99	default:
100		mMapCacheSetGetPointer(&cache->maps, 0)->mapParser = mapParser0;
101		mMapCacheSetGetPointer(&cache->maps, 1)->mapParser = mapParser0;
102		mMapCacheSetGetPointer(&cache->maps, 2)->mapParser = mapParser0;
103		mMapCacheSetGetPointer(&cache->maps, 3)->mapParser = mapParser0;
104
105		mMapCacheSetGetPointer(&cache->maps, 0)->tileCache = mTileCacheSetGetPointer(&cache->tiles,
106			mMapCacheSystemInfoGetPaletteBPP(mMapCacheSetGetPointer(&cache->maps, 0)->sysConfig) == 3);
107		mMapCacheSetGetPointer(&cache->maps, 1)->tileCache = mTileCacheSetGetPointer(&cache->tiles,
108			mMapCacheSystemInfoGetPaletteBPP(mMapCacheSetGetPointer(&cache->maps, 1)->sysConfig) == 3);
109		mMapCacheSetGetPointer(&cache->maps, 2)->tileCache = mTileCacheSetGetPointer(&cache->tiles,
110			mMapCacheSystemInfoGetPaletteBPP(mMapCacheSetGetPointer(&cache->maps, 2)->sysConfig) == 3);
111		mMapCacheSetGetPointer(&cache->maps, 3)->tileCache = mTileCacheSetGetPointer(&cache->tiles,
112			mMapCacheSystemInfoGetPaletteBPP(mMapCacheSetGetPointer(&cache->maps, 3)->sysConfig) == 3);
113		break;
114	case 1:
115	case 2:
116		mMapCacheSetGetPointer(&cache->maps, 0)->mapParser = mapParser0;
117		mMapCacheSetGetPointer(&cache->maps, 1)->mapParser = mapParser0;
118		mMapCacheSetGetPointer(&cache->maps, 2)->mapParser = mapParser2;
119		mMapCacheSetGetPointer(&cache->maps, 3)->mapParser = mapParser2;
120
121		mMapCacheSetGetPointer(&cache->maps, 0)->tileCache = mTileCacheSetGetPointer(&cache->tiles,
122			mMapCacheSystemInfoGetPaletteBPP(mMapCacheSetGetPointer(&cache->maps, 0)->sysConfig) == 3);
123		mMapCacheSetGetPointer(&cache->maps, 1)->tileCache = mTileCacheSetGetPointer(&cache->tiles,
124			mMapCacheSystemInfoGetPaletteBPP(mMapCacheSetGetPointer(&cache->maps, 1)->sysConfig) == 3);
125
126		mMapCacheSetGetPointer(&cache->maps, 2)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 1);
127		mMapCacheSetGetPointer(&cache->maps, 3)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 1);
128		break;
129	}
130
131	mBitmapCacheSystemInfo bitConfig;
132	switch (GBARegisterDISPCNTGetMode(value)) {
133	case 3:
134		bitConfig = mBitmapCacheSystemInfoSetEntryBPP(0, 4);
135		bitConfig = mBitmapCacheSystemInfoClearUsesPalette(bitConfig);
136		bitConfig = mBitmapCacheSystemInfoSetHeight(bitConfig, 160);
137		bitConfig = mBitmapCacheSystemInfoSetWidth(bitConfig, 240);
138		bitConfig = mBitmapCacheSystemInfoSetBuffers(bitConfig, 1);
139		mBitmapCacheConfigureSystem(mBitmapCacheSetGetPointer(&cache->bitmaps, 0), bitConfig);
140		mBitmapCacheSetGetPointer(&cache->bitmaps, 0)->buffer = 0;
141		break;
142	case 5:
143		bitConfig = mBitmapCacheSystemInfoSetEntryBPP(0, 4);
144		bitConfig = mBitmapCacheSystemInfoClearUsesPalette(bitConfig);
145		bitConfig = mBitmapCacheSystemInfoSetHeight(bitConfig, 128);
146		bitConfig = mBitmapCacheSystemInfoSetWidth(bitConfig, 160);
147		bitConfig = mBitmapCacheSystemInfoSetBuffers(bitConfig, 2);
148		mBitmapCacheConfigureSystem(mBitmapCacheSetGetPointer(&cache->bitmaps, 0), bitConfig);
149		mBitmapCacheSetGetPointer(&cache->bitmaps, 0)->buffer = GBARegisterDISPCNTGetFrameSelect(value);
150		break;
151	}
152}
153
154static void GBAVideoCacheWriteBGCNT(struct mCacheSet* cache, size_t bg, uint16_t value) {
155	struct mMapCache* map = mMapCacheSetGetPointer(&cache->maps, bg);
156	map->context = (void*) (uintptr_t) value;
157
158	int tileStart = GBARegisterBGCNTGetCharBase(value) * 256;
159	bool p = GBARegisterBGCNTGet256Color(value);
160	int size = GBARegisterBGCNTGetSize(value);
161	int tilesWide = 0;
162	int tilesHigh = 0;
163	mMapCacheSystemInfo sysconfig = 0;
164	if (map->mapParser == mapParser0) {
165		map->tileCache = mTileCacheSetGetPointer(&cache->tiles, p);
166		sysconfig = mMapCacheSystemInfoSetPaletteBPP(sysconfig, 2 + p);
167		sysconfig = mMapCacheSystemInfoSetPaletteCount(sysconfig, 4 * !p);
168		sysconfig = mMapCacheSystemInfoSetMacroTileSize(sysconfig, 5);
169		sysconfig = mMapCacheSystemInfoSetMapAlign(sysconfig, 1);
170		tilesWide = 5;
171		tilesHigh = 5;
172		if (size & 1) {
173			++tilesWide;
174		}
175		if (size & 2) {
176			++tilesHigh;
177		}
178		map->tileStart = tileStart * (2 - p);
179	} else if (map->mapParser == mapParser2) {
180		map->tileCache = mTileCacheSetGetPointer(&cache->tiles, 1);
181		sysconfig = mMapCacheSystemInfoSetPaletteBPP(sysconfig, 3);
182		sysconfig = mMapCacheSystemInfoSetPaletteCount(sysconfig, 0);
183		sysconfig = mMapCacheSystemInfoSetMacroTileSize(sysconfig, 4 + size);
184		sysconfig = mMapCacheSystemInfoSetMapAlign(sysconfig, 0);
185
186		tilesHigh = 4 + size;
187		tilesWide = 4 + size;
188		map->tileStart = tileStart;
189	}
190	sysconfig = mMapCacheSystemInfoSetTilesHigh(sysconfig, tilesHigh);
191	sysconfig = mMapCacheSystemInfoSetTilesWide(sysconfig, tilesWide);
192	mMapCacheConfigureSystem(map, sysconfig);
193	mMapCacheConfigureMap(map, GBARegisterBGCNTGetScreenBase(value) << 11);
194}
195
196void GBAVideoCacheWriteVideoRegister(struct mCacheSet* cache, uint32_t address, uint16_t value) {
197	switch (address) {
198	case REG_DISPCNT:
199		GBAVideoCacheWriteDISPCNT(cache, value);
200		GBAVideoCacheWriteBGCNT(cache, 0, (uintptr_t) mMapCacheSetGetPointer(&cache->maps, 0)->context);
201		GBAVideoCacheWriteBGCNT(cache, 1, (uintptr_t) mMapCacheSetGetPointer(&cache->maps, 1)->context);
202		GBAVideoCacheWriteBGCNT(cache, 2, (uintptr_t) mMapCacheSetGetPointer(&cache->maps, 2)->context);
203		GBAVideoCacheWriteBGCNT(cache, 3, (uintptr_t) mMapCacheSetGetPointer(&cache->maps, 3)->context);
204		break;
205	case REG_BG0CNT:
206		GBAVideoCacheWriteBGCNT(cache, 0, value);
207		break;
208	case REG_BG1CNT:
209		GBAVideoCacheWriteBGCNT(cache, 1, value);
210		break;
211	case REG_BG2CNT:
212		GBAVideoCacheWriteBGCNT(cache, 2, value);
213		break;
214	case REG_BG3CNT:
215		GBAVideoCacheWriteBGCNT(cache, 3, value);
216		break;
217
218	}
219}