From 7a07b148cbd4add45afff1908dd364360f0fb084 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 8 Jun 2022 00:15:49 -0700 Subject: [PATCH] GBA Video: Fix OBJ tile wrapping with 2D char mapping (fixes #2443) --- CHANGES | 1 + cinema/gba/obj/2d-wrap/baseline_0000.png | Bin 0 -> 253 bytes cinema/gba/obj/2d-wrap/config.ini | 3 +++ cinema/gba/obj/2d-wrap/test.gba | Bin 0 -> 4096 bytes src/gba/renderers/software-obj.c | 18 ++++++++++-------- 5 files changed, 14 insertions(+), 8 deletions(-) create mode 100644 cinema/gba/obj/2d-wrap/baseline_0000.png create mode 100644 cinema/gba/obj/2d-wrap/config.ini create mode 100644 cinema/gba/obj/2d-wrap/test.gba diff --git a/CHANGES b/CHANGES index 17b2df376..10831f0c2 100644 --- a/CHANGES +++ b/CHANGES @@ -43,6 +43,7 @@ Emulation fixes: - GBA Video: Fix Hblank timing (fixes mgba.io/i/2131, mgba.io/i/2310) - GBA Video: Fix rare crash in modes 3-5 - GBA Video: Fix sprites with mid-frame palette changes in GL (fixes mgba.io/i/2476) + - GBA Video: Fix OBJ tile wrapping with 2D char mapping (fixes mgba.io/i/2443) Other fixes: - ARM: Disassemble Thumb mov pseudo-instruction properly - Core: Don't attempt to restore rewind diffs past start of rewind diff --git a/cinema/gba/obj/2d-wrap/baseline_0000.png b/cinema/gba/obj/2d-wrap/baseline_0000.png new file mode 100644 index 0000000000000000000000000000000000000000..c0866f0a8ba8a68c0a7fd9f60dfc3a9e92936e40 GIT binary patch literal 253 zcmeAS@N?(olHy`uVBq!ia0vp^AAooP2NRIoyR*y)NFDKXaSW-L^Y+e0-U9|4u8!8f z-}{IaSgA~Tzx$Htq4jCHKsCgH2mar_Fl4TJ^<&@uu(#|{wwIY5)E$LgFSrPr1hV*w zfS8yD865iiBTete`J&r>8ck|l3p$lD7IDl1GZ`^eV-;!O-t%M*n|$?#vui-|p00i_ I>zopr05;S*xBvhE literal 0 HcmV?d00001 diff --git a/cinema/gba/obj/2d-wrap/config.ini b/cinema/gba/obj/2d-wrap/config.ini new file mode 100644 index 000000000..108616db9 --- /dev/null +++ b/cinema/gba/obj/2d-wrap/config.ini @@ -0,0 +1,3 @@ +[testinfo] +skip=1 +frames=1 diff --git a/cinema/gba/obj/2d-wrap/test.gba b/cinema/gba/obj/2d-wrap/test.gba new file mode 100644 index 0000000000000000000000000000000000000000..3b5998ff375aa2467f0f905a2f312fc5bc3d2b2f GIT binary patch literal 4096 zcmdO6V0fkSe_deatVN2pElpf4PdL{Ks&vmd&{(gyIB1{bWX^L60&ZSjKhzE1L>zx% z-1PX|{?;$|r=0WVJUAt+>ws|4@;~!ie2W*Knw1zaeX;r<<{4$mvd0sdS=NQ^w`gH- zSkCwNf6zbX{HX>Xr~f|CnsBW_b!GBCW=21YM?V*t{NHWI>{7un;dFebQ~gwWdh%$`5vbC$A9K;1C87a1QlzH8-CIW`l{j3=E9S3m!8{EqJ^^z~P|? zUK$-z4#|V`BqcH#J1_g(QObiW=7zF|!{r>-7 z>J0-#?gbXP8&J6`SmcfX<(PnG9>5~E0V=l!i`*Qj+zc#o>?{i&w+H~;2=os-)Gr`E zfc#Pb)K`Ee7YCJ#0m{_@*<5-+wF(CwGVxD<`|scX|F0OB7+C+;gF=mwO;C`5;Q=!v zo01Zc%fiTJYz(A17}*#Z85j<5GqN!;0r@> 1) & 2); -#define SPRITE_YBASE_16(localY) unsigned yBase = (localY & ~0x7) * stride + (localY & 0x7) * 4; +#define SPRITE_YBASE_16(localY) unsigned yBase = (localY & ~0x7) * stride + (localY & 0x7) * 4 + maskHi; #define SPRITE_DRAW_PIXEL_16_NORMAL(localX) \ - LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFE), vramBase); \ + LOAD_16(tileData, (yBase + ((xBase + charBase) & maskLo)) & 0x7FFE, vramBase); \ tileData = (tileData >> ((localX & 3) << 2)) & 0xF; \ current = renderer->spriteLayer[outX]; \ if ((current & FLAG_ORDER_MASK) > flags) { \ @@ -86,7 +86,7 @@ } #define SPRITE_DRAW_PIXEL_16_NORMAL_OBJWIN(localX) \ - LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFE), vramBase); \ + LOAD_16(tileData, (yBase + ((xBase + charBase) & maskLo)) & 0x7FFE, vramBase); \ tileData = (tileData >> ((localX & 3) << 2)) & 0xF; \ current = renderer->spriteLayer[outX]; \ if ((current & FLAG_ORDER_MASK) > flags) { \ @@ -99,17 +99,17 @@ } #define SPRITE_DRAW_PIXEL_16_OBJWIN(localX) \ - LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFE), vramBase); \ + LOAD_16(tileData, (yBase + ((xBase + charBase) & maskLo)) & 0x7FFE, vramBase); \ tileData = (tileData >> ((localX & 3) << 2)) & 0xF; \ if (tileData) { \ renderer->row[outX] |= FLAG_OBJWIN; \ } #define SPRITE_XBASE_256(localX) unsigned xBase = (localX & ~0x7) * 8 + (localX & 6); -#define SPRITE_YBASE_256(localY) unsigned yBase = (localY & ~0x7) * stride + (localY & 0x7) * 8; +#define SPRITE_YBASE_256(localY) unsigned yBase = (localY & ~0x7) * stride + (localY & 0x7) * 8 + maskHi; #define SPRITE_DRAW_PIXEL_256_NORMAL(localX) \ - LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFE), vramBase); \ + LOAD_16(tileData, (yBase + ((xBase + charBase) & maskLo)) & 0x7FFE, vramBase); \ tileData = (tileData >> ((localX & 1) << 3)) & 0xFF; \ current = renderer->spriteLayer[outX]; \ if ((current & FLAG_ORDER_MASK) > flags) { \ @@ -121,7 +121,7 @@ } #define SPRITE_DRAW_PIXEL_256_NORMAL_OBJWIN(localX) \ - LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFE), vramBase); \ + LOAD_16(tileData, (yBase + ((xBase + charBase) & maskLo)) & 0x7FFE, vramBase); \ tileData = (tileData >> ((localX & 1) << 3)) & 0xFF; \ current = renderer->spriteLayer[outX]; \ if ((current & FLAG_ORDER_MASK) > flags) { \ @@ -134,7 +134,7 @@ } #define SPRITE_DRAW_PIXEL_256_OBJWIN(localX) \ - LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFE), vramBase); \ + LOAD_16(tileData, (yBase + ((xBase + charBase) & maskLo)) & 0x7FFE, vramBase); \ tileData = (tileData >> ((localX & 1) << 3)) & 0xFF; \ if (tileData) { \ renderer->row[outX] |= FLAG_OBJWIN; \ @@ -157,6 +157,8 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re uint16_t* vramBase = &renderer->d.vram[BASE_TILE >> 1]; unsigned align = GBAObjAttributesAIs256Color(sprite->a) && !GBARegisterDISPCNTIsObjCharacterMapping(renderer->dispcnt); unsigned charBase = (GBAObjAttributesCGetTile(sprite->c) & ~align) * 0x20; + unsigned maskLo = GBARegisterDISPCNTIsObjCharacterMapping(renderer->dispcnt) ? 0x7FFE : 0x3FE; + unsigned maskHi = GBARegisterDISPCNTIsObjCharacterMapping(renderer->dispcnt) ? 0 : charBase & 0x7C00; if (GBARegisterDISPCNTGetMode(renderer->dispcnt) >= 3 && GBAObjAttributesCGetTile(sprite->c) < 512) { return 0; }