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/gb/renderers/cache-set.h>
7 
8 #include <mgba/core/cache-set.h>
9 #include <mgba/internal/gb/gb.h>
10 #include <mgba/internal/gb/io.h>
11 #include <mgba/internal/gb/video.h>
12 
GBVideoCacheInit(struct mCacheSet * cache)13 void GBVideoCacheInit(struct mCacheSet* cache) {
14 	mCacheSetInit(cache, 2, 0, 1);
15 	mTileCacheSystemInfo sysconfig = 0;
16 	mTileCacheConfiguration config = mTileCacheConfigurationFillShouldStore(0);
17 	sysconfig = mTileCacheSystemInfoSetPaletteBPP(sysconfig, 1); // 2^(2^1) = 4 entries
18 	sysconfig = mTileCacheSystemInfoSetPaletteCount(sysconfig, 4); // 16 palettes
19 	sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 1024);
20 	mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 0), sysconfig, 0, 0);
21 	mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 0), config);
22 
23 	mMapCacheSetGetPointer(&cache->maps, 0)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0);
24 	mMapCacheSetGetPointer(&cache->maps, 1)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0);
25 }
26 
GBVideoCacheAssociate(struct mCacheSet * cache,struct GBVideo * video)27 void GBVideoCacheAssociate(struct mCacheSet* cache, struct GBVideo* video) {
28 	mCacheSetAssignVRAM(cache, video->vram);
29 	video->renderer->cache = cache;
30 	size_t i;
31 	for (i = 0; i < 64; ++i) {
32 		mCacheSetWritePalette(cache, i, mColorFrom555(video->palette[i]));
33 	}
34 	mMapCacheSystemInfo sysconfig = mMapCacheSystemInfoSetPaletteCount(0, 0);
35 	if (video->p->model >= GB_MODEL_CGB) {
36 		sysconfig = mMapCacheSystemInfoSetPaletteCount(0, 2);
37 	}
38 	mMapCacheConfigureSystem(mMapCacheSetGetPointer(&cache->maps, 0), sysconfig);
39 	mMapCacheConfigureSystem(mMapCacheSetGetPointer(&cache->maps, 1), sysconfig);
40 
41 	GBVideoCacheWriteVideoRegister(cache, GB_REG_LCDC, video->p->memory.io[GB_REG_LCDC]);
42 }
43 
mapParserDMG0(struct mMapCache * cache,struct mMapCacheEntry * entry,void * vram)44 static void mapParserDMG0(struct mMapCache* cache, struct mMapCacheEntry* entry, void* vram) {
45 	UNUSED(cache);
46 	int map = *(uint8_t*) vram;
47 	entry->tileId = map;
48 	entry->flags = mMapCacheEntryFlagsClearHMirror(entry->flags);
49 	entry->flags = mMapCacheEntryFlagsClearVMirror(entry->flags);
50 	entry->flags = mMapCacheEntryFlagsSetPaletteId(entry->flags, 0);
51 }
52 
mapParserDMG1(struct mMapCache * cache,struct mMapCacheEntry * entry,void * vram)53 static void mapParserDMG1(struct mMapCache* cache, struct mMapCacheEntry* entry, void* vram) {
54 	UNUSED(cache);
55 	int map = *(int8_t*) vram;
56 	entry->tileId = map + 128;
57 	entry->flags = mMapCacheEntryFlagsClearHMirror(entry->flags);
58 	entry->flags = mMapCacheEntryFlagsClearVMirror(entry->flags);
59 	entry->flags = mMapCacheEntryFlagsSetPaletteId(entry->flags, 0);
60 }
61 
mapParserCGB0(struct mMapCache * cache,struct mMapCacheEntry * entry,void * vram)62 static void mapParserCGB0(struct mMapCache* cache, struct mMapCacheEntry* entry, void* vram) {
63 	UNUSED(cache);
64 	int map = *(uint8_t*) vram;
65 	uint8_t attr = ((uint8_t*) vram)[0x2000];
66 	entry->tileId = map + GBObjAttributesGetBank(attr) * 512;
67 	entry->flags = mMapCacheEntryFlagsSetHMirror(entry->flags, GBObjAttributesGetXFlip(attr));
68 	entry->flags = mMapCacheEntryFlagsSetVMirror(entry->flags, GBObjAttributesGetYFlip(attr));
69 	entry->flags = mMapCacheEntryFlagsSetPaletteId(entry->flags, GBObjAttributesGetCGBPalette(attr));
70 }
71 
mapParserCGB1(struct mMapCache * cache,struct mMapCacheEntry * entry,void * vram)72 static void mapParserCGB1(struct mMapCache* cache, struct mMapCacheEntry* entry, void* vram) {
73 	UNUSED(cache);
74 	int map = *(int8_t*) vram;
75 	uint8_t attr = ((uint8_t*) vram)[0x2000];
76 	entry->tileId = map + 128 + GBObjAttributesGetBank(attr) * 512;
77 	entry->flags = mMapCacheEntryFlagsSetHMirror(entry->flags, GBObjAttributesGetXFlip(attr));
78 	entry->flags = mMapCacheEntryFlagsSetVMirror(entry->flags, GBObjAttributesGetYFlip(attr));
79 	entry->flags = mMapCacheEntryFlagsSetPaletteId(entry->flags, GBObjAttributesGetCGBPalette(attr));
80 }
81 
GBVideoCacheWriteVideoRegister(struct mCacheSet * cache,uint16_t address,uint8_t value)82 void GBVideoCacheWriteVideoRegister(struct mCacheSet* cache, uint16_t address, uint8_t value) {
83 	if (address != GB_REG_LCDC) {
84 		return;
85 	}
86 	struct mMapCache* map = mMapCacheSetGetPointer(&cache->maps, 0);
87 	struct mMapCache* window = mMapCacheSetGetPointer(&cache->maps, 1);
88 
89 	mMapCacheSystemInfo sysconfig = mMapCacheSystemInfoIsPaletteCount(map->sysConfig);
90 	int tileStart = 0;
91 	int mapStart = GB_BASE_MAP;
92 	int windowStart = GB_BASE_MAP;
93 	if (GBRegisterLCDCIsTileMap(value)) {
94 		mapStart += GB_SIZE_MAP;
95 	}
96 	if (GBRegisterLCDCIsWindowTileMap(value)) {
97 		windowStart += GB_SIZE_MAP;
98 	}
99 	if (GBRegisterLCDCIsTileData(value)) {
100 		if (!sysconfig) {
101 			map->mapParser = mapParserDMG0;
102 			window->mapParser = mapParserDMG0;
103 		} else {
104 			map->mapParser = mapParserCGB0;
105 			window->mapParser = mapParserCGB0;
106 		}
107 	} else {
108 		if (!sysconfig) {
109 			map->mapParser = mapParserDMG1;
110 			window->mapParser = mapParserDMG1;
111 		} else {
112 			map->mapParser = mapParserCGB1;
113 			window->mapParser = mapParserCGB1;
114 		}
115 		tileStart = 0x80;
116 	}
117 	map->tileStart = tileStart;
118 	window->tileStart = tileStart;
119 	sysconfig = mMapCacheSystemInfoSetMacroTileSize(sysconfig, 5);
120 	sysconfig = mMapCacheSystemInfoSetPaletteBPP(sysconfig, 1);
121 	sysconfig = mMapCacheSystemInfoSetMapAlign(sysconfig, 0);
122 	sysconfig = mMapCacheSystemInfoSetTilesHigh(sysconfig, 5);
123 	sysconfig = mMapCacheSystemInfoSetTilesWide(sysconfig, 5);
124 	mMapCacheConfigureSystem(map, sysconfig);
125 	mMapCacheConfigureSystem(window, sysconfig);
126 	mMapCacheConfigureMap(map, mapStart);
127 	mMapCacheConfigureMap(window, windowStart);
128 }
129