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