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}