aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-05-20 22:55:24 +0200
committerBad Diode <bd@badd10de.dev>2021-05-20 22:55:24 +0200
commit5219f9952d471dce549798b4d0064b727a4b78b0 (patch)
treeaf220ad05a21dfaefbb047d92f54826543013c4a /src
parentd81fe3c22410be6beba3577c6985a07483da4694 (diff)
downloaduxngba-5219f9952d471dce549798b4d0064b727a4b78b0.tar.gz
uxngba-5219f9952d471dce549798b4d0064b727a4b78b0.zip
Apply asie's patch 3 with a PPU fix
Diffstat (limited to 'src')
-rw-r--r--src/uxn/devices/ppu.c163
1 files changed, 90 insertions, 73 deletions
diff --git a/src/uxn/devices/ppu.c b/src/uxn/devices/ppu.c
index 60ede0a..97b5e4f 100644
--- a/src/uxn/devices/ppu.c
+++ b/src/uxn/devices/ppu.c
@@ -143,9 +143,9 @@ static Uint32 unpack_icon_lut_flipx[256] = {
143}; 143};
144 144
145EWRAM_BSS 145EWRAM_BSS
146static u32 *backbuffer_bg0[30 * 20 * sizeof(Tile) / 4]; 146static u32 *backbuffer_bg0[32 * 20 * sizeof(Tile) / 4];
147EWRAM_BSS 147EWRAM_BSS
148static u32 *backbuffer_bg1[30 * 20 * sizeof(Tile) / 4]; 148static u32 *backbuffer_bg1[32 * 20 * sizeof(Tile) / 4];
149static u32 dirty_tiles[20] = {0}; 149static u32 dirty_tiles[20] = {0};
150 150
151void 151void
@@ -173,7 +173,7 @@ putpixel(Ppu *p, Uint32 *layer, Uint16 x, Uint16 y, Uint8 color) {
173 size_t tile_y = y / 8; 173 size_t tile_y = y / 8;
174 size_t start_col = x % 8; 174 size_t start_col = x % 8;
175 size_t start_row = y % 8; 175 size_t start_row = y % 8;
176 size_t pos = (start_row + ((tile_x + tile_y * 30) * 8)); 176 size_t pos = (start_row + ((tile_x + tile_y * 32) * 8));
177 size_t shift = start_col * 4; 177 size_t shift = start_col * 4;
178 layer[pos] = (layer[pos] & (~(0xF << shift))) | (color << shift); 178 layer[pos] = (layer[pos] & (~(0xF << shift))) | (color << shift);
179 dirty_tiles[tile_y] |= 1 << tile_x; 179 dirty_tiles[tile_y] |= 1 << tile_x;
@@ -181,77 +181,96 @@ putpixel(Ppu *p, Uint32 *layer, Uint16 x, Uint16 y, Uint8 color) {
181 181
182IWRAM_CODE 182IWRAM_CODE
183void 183void
184puticn(Ppu *p, Uint32 *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, 184puticn(Ppu *p, Uint32 *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy) {
185 Uint8 flipx, Uint8 flipy) { 185 Uint8 sprline;
186 if(x >= 30 * 8 || y >= 20 * 8) { 186 Uint8 xrightedge = x < ((32 - 1) * 8);
187 return; 187 Uint16 v;
188 } 188 Uint32 dirtyflag = (1 << (x >> 3)) | (1 << ((x + 7) >> 3));
189 size_t tile_x = x / 8;
190 size_t tile_y = y / 8;
191 size_t start_col = x % 8;
192 size_t start_row = y % 8;
193 size_t shift_left = start_col * 4;
194 size_t shift_right = (8 - start_col) * 4;
195 189
196 if (flipy) { 190 Uint32 layerpos = ((y & 7) + (((x >> 3) + (y >> 3) * 32) * 8));
197 flipy = 7; 191 Uint32 *layerptr = &layer[layerpos];
198 } 192 Uint32 shift = (x & 7) << 2;
193 Uint32 *lut_expand = flipx ? unpack_icon_lut : unpack_icon_lut_flipx;
199 194
200 size_t pos = (start_row + ((tile_x + tile_y * 30) * 8)); 195 if (flipy) flipy = 7;
201 size_t *layer_ptr = &layer[pos]; 196
202 size_t *lut = flipx ? unpack_icon_lut : unpack_icon_lut_flipx; 197 if (x >= 240 || y >= 160) return;
203 198
204 // There are 4 possible cases: 199 if (color != 0x05 && color != 0x0a && color != 0x0f) {
205 // 1. The sprite is exactly at the tile boundary. We can just copy the 200 u64 mask = ~((u64)0xFFFFFFFF << shift);
206 // tile directly to memory. 201
207 // 2. The sprite covers 2 tiles horizontally. 202 for (v = 0; v < 8; v++, layerptr++) {
208 // 3. The sprite covers 2 tiles vertically. 203 if ((y + v) >= 160) break;
209 // 4. The sprite covers 4 tiles. 204
210 if (start_row == 0 && start_col == 0) { 205 sprline = sprite[v ^ flipy];
211 for (size_t i = 0; i < 8; ++i) { 206 u64 data = (u64)(lut_expand[sprline] * (color & 3)) << shift;
212 layer_ptr[i] = lut[sprite[i ^ flipy]] * color; 207 data |= (u64)(lut_expand[sprline ^ 0xFF] * (color >> 2)) << shift;
213 } 208
214 dirty_tiles[tile_y] |= 1 << tile_x; 209 layerptr[0] = (layerptr[0] & mask) | data;
215 } else { 210 if (xrightedge) layerptr[8] = (layerptr[8] & (mask >> 32)) | (data >> 32);
216 u32 row_mask = 0xFFFFFFFF << shift_left; 211
217 for (size_t i = 0; i < (8 - start_row); ++i) { 212 if (((y + v) & 7) == 7) layerptr += (32 - 1) * 8;
218 u32 sprite_row = lut[sprite[i ^ flipy]] * color; 213 }
219 layer_ptr[0] = (layer_ptr[0] & ~row_mask) | (sprite_row << shift_left); 214 } else {
220 layer_ptr[8] = (layer_ptr[8] & row_mask) | (sprite_row >> shift_right); 215 for (v = 0; v < 8; v++, layerptr++) {
221 layer_ptr++; 216 if ((y + v) >= 160) break;
222 } 217
223 layer_ptr += 8 * 29; 218 sprline = sprite[v ^ flipy];
224 for (size_t i = (8 - start_row); i < 8; ++i) { 219 u64 mask = ~((u64)(lut_expand[sprline] * 0xF) << shift);
225 u32 sprite_row = lut[sprite[i ^ flipy]] * color; 220 u64 data = (u64)(lut_expand[sprline] * (color & 3)) << shift;
226 layer_ptr[0] = (layer_ptr[0] & ~row_mask) | (sprite_row << shift_left); 221
227 layer_ptr[8] = (layer_ptr[8] & row_mask) | (sprite_row >> shift_right); 222 layerptr[0] = (layerptr[0] & mask) | data;
228 layer_ptr++; 223 if (xrightedge) layerptr[8] = (layerptr[8] & (mask >> 32)) | (data >> 32);
229 } 224
230 dirty_tiles[tile_y] |= 1 << tile_x; 225 if (((y + v) & 7) == 7) layerptr += (32 - 1) * 8;
231 dirty_tiles[tile_y] |= 1 << (tile_x + 1); 226 }
232 dirty_tiles[tile_y + 1] |= 1 << tile_x; 227 }
233 dirty_tiles[tile_y + 1] |= 1 << (tile_x + 1); 228
234 } 229 dirty_tiles[y >> 3] |= dirtyflag;
230 dirty_tiles[(y + 7) >> 3] |= dirtyflag;
235} 231}
236 232
237IWRAM_CODE 233IWRAM_CODE
238void 234void
239putchr(Ppu *p, Uint32 *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, 235putchr(Ppu *p, Uint32 *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color,
240 Uint8 flipx, Uint8 flipy) { 236 Uint8 flipx, Uint8 flipy) {
241 if(x >= 30 * 8 || y >= 20 * 8) { 237 Uint8 sprline1, sprline2;
242 return; 238 Uint8 xrightedge = x < ((32 - 1) * 8);
243 } 239 Uint16 v;
244 Uint16 v, h; 240 Uint32 dirtyflag = (1 << (x >> 3)) | (1 << ((x + 7) >> 3));
245 for(v = 0; v < 8; v++) 241
246 for(h = 0; h < 8; h++) { 242 Uint32 layerpos = ((y & 7) + (((x >> 3) + (y >> 3) * 32) * 8));
247 Uint8 ch1 = ((sprite[v] >> (7 - h)) & 0x1) * color; 243 Uint32 *layerptr = &layer[layerpos];
248 Uint8 ch2 = ((sprite[v + 8] >> (7 - h)) & 0x1) * color; 244 Uint32 shift = (x & 7) << 2;
249 putpixel(p, 245 Uint32 *lut_expand = flipx ? unpack_icon_lut : unpack_icon_lut_flipx;
250 layer, 246
251 x + (flipx ? 7 - h : h), 247 if (flipy) flipy = 7;
252 y + (flipy ? 7 - v : v), 248
253 (((ch1 + ch2 * 2) + color / 4) & 0x3)); 249 if (x >= 240 || y >= 160) return;
254 } 250
251 u64 mask = ~((u64)0xFFFFFFFF << shift);
252 u32 colconst = (color >> 2) * 0x11111111;
253
254 for (v = 0; v < 8; v++, layerptr++) {
255 if ((y + v) >= 160) break;
256
257 sprline1 = sprite[v ^ flipy];
258 sprline2 = sprite[(v ^ flipy) | 8];
259
260 u32 data32 =
261 (lut_expand[sprline1] * (color & 3))
262 + (lut_expand[sprline2] * ((color & 1) << 1))
263 + colconst;
264 u64 data = ((u64) (data32 & 0x33333333)) << shift;
265
266 layerptr[0] = (layerptr[0] & mask) | data;
267 if (xrightedge) layerptr[8] = (layerptr[8] & (mask >> 32)) | (data >> 32);
268
269 if (((y + v) & 7) == 7) layerptr += (32 - 1) * 8;
270 }
271
272 dirty_tiles[y >> 3] |= dirtyflag;
273 dirty_tiles[(y + 7) >> 3] |= dirtyflag;
255} 274}
256 275
257IWRAM_CODE 276IWRAM_CODE
@@ -269,8 +288,8 @@ flipbuf(Ppu *p) {
269 if (dirty_tiles[j] & k) { 288 if (dirty_tiles[j] & k) {
270 Tile *tile_fg = p->fg; 289 Tile *tile_fg = p->fg;
271 Tile *tile_bg = p->bg; 290 Tile *tile_bg = p->bg;
272 mem_fg[i + j * 30] = tile_fg[i + j * 30]; 291 mem_fg[i + j * 32] = tile_fg[i + j * 32];
273 mem_bg[i + j * 30] = tile_bg[i + j * 30]; 292 mem_bg[i + j * 32] = tile_bg[i + j * 32];
274 } 293 }
275 } 294 }
276 dirty_tiles[j] = 0; 295 dirty_tiles[j] = 0;
@@ -298,7 +317,7 @@ initppu(Ppu *p, Uint8 hor, Uint8 ver, Uint8 pad) {
298 // Clear tile memory. 317 // Clear tile memory.
299 p->fg = backbuffer_bg0; 318 p->fg = backbuffer_bg0;
300 p->bg = backbuffer_bg1; 319 p->bg = backbuffer_bg1;
301 for (size_t i = 0; i < 30 * 20 * 8; ++i) { 320 for (size_t i = 0; i < 32 * 20 * 8; ++i) {
302 p->fg[i] = 0; 321 p->fg[i] = 0;
303 p->bg[i] = 0; 322 p->bg[i] = 0;
304 } 323 }
@@ -312,10 +331,8 @@ initppu(Ppu *p, Uint8 hor, Uint8 ver, Uint8 pad) {
312 // Initialize memory map. 331 // Initialize memory map.
313 u16 *mem_map = SCREENBLOCK_MEM[sb_idx]; 332 u16 *mem_map = SCREENBLOCK_MEM[sb_idx];
314 size_t k = 0; 333 size_t k = 0;
315 for (size_t j = 0; j < 20; ++j) { 334 for (size_t i = 0; i < 32 * 20; ++i, ++k) {
316 for (size_t i = 0; i < 30; ++i, ++k) { 335 mem_map[i] = k;
317 mem_map[i + j * 32] = k;
318 }
319 } 336 }
320 337
321 return 1; 338 return 1;