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, (uint16_t) mMapCacheSetGetPointer(&cache->maps, 0)->context);
162 GBAVideoCacheWriteBGCNT(cache, 1, (uint16_t) mMapCacheSetGetPointer(&cache->maps, 1)->context);
163 GBAVideoCacheWriteBGCNT(cache, 2, (uint16_t) mMapCacheSetGetPointer(&cache->maps, 2)->context);
164 GBAVideoCacheWriteBGCNT(cache, 3, (uint16_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}