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 UNUSED(cache);
61 uint16_t map = *(uint16_t*) vram;
62 entry->tileId = GBA_TEXT_MAP_TILE(map);
63 entry->flags = mMapCacheEntryFlagsSetHMirror(entry->flags, !!GBA_TEXT_MAP_HFLIP(map));
64 entry->flags = mMapCacheEntryFlagsSetVMirror(entry->flags, !!GBA_TEXT_MAP_VFLIP(map));
65 entry->flags = mMapCacheEntryFlagsSetPaletteId(entry->flags, GBA_TEXT_MAP_PALETTE(map));
66}
67
68static void mapParser2(struct mMapCache* cache, struct mMapCacheEntry* entry, void* vram) {
69 UNUSED(cache);
70 entry->tileId = *(uint8_t*) vram;
71 entry->flags = mMapCacheEntryFlagsClearHMirror(entry->flags);
72 entry->flags = mMapCacheEntryFlagsClearVMirror(entry->flags);
73 entry->flags = mMapCacheEntryFlagsClearPaletteId(entry->flags);
74}
75
76static void GBAVideoCacheWriteDISPCNT(struct mCacheSet* cache, uint16_t value) {
77 switch (GBARegisterDISPCNTGetMode(value)) {
78 case 0:
79 default:
80 mMapCacheSetGetPointer(&cache->maps, 0)->mapParser = mapParser0;
81 mMapCacheSetGetPointer(&cache->maps, 1)->mapParser = mapParser0;
82 mMapCacheSetGetPointer(&cache->maps, 2)->mapParser = mapParser0;
83 mMapCacheSetGetPointer(&cache->maps, 3)->mapParser = mapParser0;
84
85 mMapCacheSetGetPointer(&cache->maps, 0)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0);
86 mMapCacheSetGetPointer(&cache->maps, 1)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0);
87 mMapCacheSetGetPointer(&cache->maps, 2)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0);
88 mMapCacheSetGetPointer(&cache->maps, 3)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0);
89 break;
90 case 1:
91 case 2:
92 mMapCacheSetGetPointer(&cache->maps, 0)->mapParser = mapParser0;
93 mMapCacheSetGetPointer(&cache->maps, 1)->mapParser = mapParser0;
94 mMapCacheSetGetPointer(&cache->maps, 2)->mapParser = mapParser2;
95 mMapCacheSetGetPointer(&cache->maps, 3)->mapParser = mapParser2;
96
97 mMapCacheSetGetPointer(&cache->maps, 0)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0);
98 mMapCacheSetGetPointer(&cache->maps, 1)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0);
99 mMapCacheSetGetPointer(&cache->maps, 2)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 1);
100 mMapCacheSetGetPointer(&cache->maps, 3)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 1);
101 break;
102 }
103}
104
105static void GBAVideoCacheWriteBGCNT(struct mCacheSet* cache, size_t bg, uint16_t value) {
106 struct mMapCache* map = mMapCacheSetGetPointer(&cache->maps, bg);
107
108 int tileStart = GBARegisterBGCNTGetCharBase(value) * 256;
109 bool p = GBARegisterBGCNTGet256Color(value);
110 int size = GBARegisterBGCNTGetSize(value);
111 int tilesWide = 0;
112 int tilesHigh = 0;
113 mMapCacheSystemInfo sysconfig = 0;
114 if (map->mapParser == mapParser0) {
115 sysconfig = mMapCacheSystemInfoSetPaletteBPP(sysconfig, 2 + p);
116 sysconfig = mMapCacheSystemInfoSetPaletteCount(sysconfig, 4 * !p);
117 sysconfig = mMapCacheSystemInfoSetMaxTiles(sysconfig, 512);
118 sysconfig = mMapCacheSystemInfoSetMapAlign(sysconfig, 1);
119 tilesWide = 5;
120 tilesHigh = 5;
121 if (size & 1) {
122 ++tilesWide;
123 }
124 if (size & 2) {
125 ++tilesHigh;
126 }
127 map->tileStart = tileStart * 2;
128 } else if (map->mapParser == mapParser2) {
129 sysconfig = mMapCacheSystemInfoSetPaletteBPP(sysconfig, 3);
130 sysconfig = mMapCacheSystemInfoSetPaletteCount(sysconfig, 0);
131 sysconfig = mMapCacheSystemInfoSetMaxTiles(sysconfig, 256);
132 sysconfig = mMapCacheSystemInfoSetMapAlign(sysconfig, 0);
133
134 tilesHigh = 4 + size;
135 tilesWide = 4 + size;
136 map->tileStart = tileStart;
137 }
138 sysconfig = mMapCacheSystemInfoSetTilesHigh(sysconfig, tilesHigh);
139 sysconfig = mMapCacheSystemInfoSetTilesWide(sysconfig, tilesWide);
140 mMapCacheConfigureSystem(map, sysconfig);
141 mMapCacheConfigureMap(map, GBARegisterBGCNTGetScreenBase(value) << 11);
142}
143
144void GBAVideoCacheWriteVideoRegister(struct mCacheSet* cache, uint32_t address, uint16_t value) {
145 switch (address) {
146 case REG_DISPCNT:
147 GBAVideoCacheWriteDISPCNT(cache, value);
148 break;
149 case REG_BG0CNT:
150 GBAVideoCacheWriteBGCNT(cache, 0, value);
151 break;
152 case REG_BG1CNT:
153 GBAVideoCacheWriteBGCNT(cache, 1, value);
154 break;
155 case REG_BG2CNT:
156 GBAVideoCacheWriteBGCNT(cache, 2, value);
157 break;
158 case REG_BG3CNT:
159 GBAVideoCacheWriteBGCNT(cache, 3, value);
160 break;
161
162 }
163}