Closed DaveTCode closed 2 years ago
This is "in game" and is running mode 0 with all 4 backgrounds enabled as well as objects but no windows.
BG0 has priority 0 with tile map base 31 BG1 has priority 1 with tile map base 30 BG2 has priority 2 with tile map base 29 BG3 has priority 3 with tile map base 28
BG0 should be just tile 512 which is all palette 0 so shouldn't be appearing. BG1 contains the sprite looking things that appear in the above screenshot and the rest is black tiles BG2 should be the background
mgba looks like this
Best guess is that one of BG0/1 is being placed above BG3 despite it containing tiles which are supposed to be Backdrop
It seems like the scanline combine routine is finding no backgrounds which are both enabled and have non-zero value for the palette.
Ah interesting, this is actually because the backgrounds (and presumably objects) are being disabled for some weird reason.
Printing out the values of dispcnt after dispcnt + 1 is written to gives me the following values cycling whilst that screen is supposed to be up.
0x00005340=0b0101_0011_0100_0000
0x00001F40=0b0001_1111_0100_0000
0x00004240=0b0100_0010_0100_0000
0x00004F40=0b0100_1111_0100_0000
First 8 bits mean mode 0, GBA mode, Frame 0, HBlank OAM accessible, 1D OAM mapping, forced blank off. They're consistent.
The next 5 are for enabling bg and obj and they cycle through various options. Looking at what line these writes happen shows:
So if the write to 4240 didn't happen then this would work I think. 1F40 is the write which doesn't enable window which I think makes more sense for this game.
The real question then is whether a write is happening at the wrong time, the wrong value is being written or no write should be happening at all.
Started looking into where each of the DISPCNT set register calls come from: 0x1f40 - 0x080114B8 (instruction 7050) whilst in Thumb/IRQ 0x4240 - 0x08012826 (instruction 7050) whilst in Thumb/System 0x4F40 - 0x08006864 (instruction 7050) whilst in Thumb/IRQ 0x5340 - 0x080056B8 (instruction 7050) whilst in Thumb/IRQ
7050 is STRB r0, [r1,#1]
and r1 in all cases is DISPCNT with r0 correctly being the high byte of DISPCNT. So no instruction issues (as expected, this has all been well tested already)
A disassembly of spyro shows the following at the suspect call:
08012818 0000E006 b 0x8012828
0801281A 00002280 mov r2,0x80
0801281C 000004D2 lsl r2,r2,0x13
0801281E 00007851 ldrb r1,[r2,0x1]
08012820 00002021 mov r0,0x21
08012822 00004240 neg r0,r0
08012824 00004008 and r0,r1
08012826 00007050 strb r0,[r2,0x1]
Clearly the most sequential instructions that could be used here are from 0801281A as the previous is an unconditional branch. These instructions seem fairly straightforward. Load R2 with 0x80, left shift that value by 0x13 to get 0x0400_0000 (DISPCNT), load DISPCNT + 1 into r1, Fill r0 with 0-0x21 which is 0xFFFFFFDF then AND with the high byte of DISPCNT to put the result in r0 and write it back to DISPCNT + 1.
A worked example of that with DISPCNT containing 0x1f40 has r1 containing 0x1F, r0 containing 0xFFFF_FFDF and then r0 getting masked to stay as 0x1F.
r0:00000000 r1:00000000 r2:FFFFFFFF r3:03006D04
r4:030010BC r5:00000000 r6:030010BC r7:030010BC
r8:00000000 r9:00000000 r10:00000000 r11:00000000
r12:00000273 r13:03007ED0 r14:08011E13 r15:0801281E
cpsr: 6000003F -ZC---- Thm System
spsr: 6000003F -ZC---- Thm System
Cycle: 735866353
0801281A: 2280 Move/compare/add/sub #imm
r0:00000000 r1:00000000 r2:00000080 r3:03006D04
r4:030010BC r5:00000000 r6:030010BC r7:030010BC
r8:00000000 r9:00000000 r10:00000000 r11:00000000
r12:00000273 r13:03007ED0 r14:08011E13 r15:08012820
cpsr: 2000003F --C---- Thm System
spsr: 2000003F --C---- Thm System
Cycle: 735866354
0801281C: 04D2 MOV Shifted reg
r0:00000000 r1:00000000 r2:04000000 r3:03006D04
r4:030010BC r5:00000000 r6:030010BC r7:030010BC
r8:00000000 r9:00000000 r10:00000000 r11:00000000
r12:00000273 r13:03007ED0 r14:08011E13 r15:08012822
cpsr: 0000003F ------- Thm System
spsr: 0000003F ------- Thm System
Cycle: 735866355
0801281E: 7851 LDR #imm/STR #imm
r0:00000000 r1:00000042 r2:04000000 r3:03006D04
r4:030010BC r5:00000000 r6:030010BC r7:030010BC
r8:00000000 r9:00000000 r10:00000000 r11:00000000
r12:00000273 r13:03007ED0 r14:08011E13 r15:08012824
cpsr: 0000003F ------- Thm System
spsr: 0000003F ------- Thm System
Cycle: 735866358
08012820: 2021 Move/compare/add/sub #imm
r0:00000021 r1:00000042 r2:04000000 r3:03006D04
r4:030010BC r5:00000000 r6:030010BC r7:030010BC
r8:00000000 r9:00000000 r10:00000000 r11:00000000
r12:00000273 r13:03007ED0 r14:08011E13 r15:08012826
cpsr: 0000003F ------- Thm System
spsr: 0000003F ------- Thm System
Cycle: 735866359
08012822: 4240 NEG R0, R0
r0:FFFFFFDF r1:00000042 r2:04000000 r3:03006D04
r4:030010BC r5:00000000 r6:030010BC r7:030010BC
r8:00000000 r9:00000000 r10:00000000 r11:00000000
r12:00000273 r13:03007ED0 r14:08011E13 r15:08012828
cpsr: 8000003F N------ Thm System
spsr: 8000003F N------ Thm System
Cycle: 735866360
08012824: 4008 AND R0, R1
r0:00000042 r1:00000042 r2:04000000 r3:03006D04
r4:030010BC r5:00000000 r6:030010BC r7:030010BC
r8:00000000 r9:00000000 r10:00000000 r11:00000000
r12:00000273 r13:03007ED0 r14:08011E13 r15:0801282A
cpsr: 0000003F ------- Thm System
spsr: 0000003F ------- Thm System
Cycle: 735866361
08012826: 7050 LDR #imm/STR #imm
Contains a dump of those lines being executed in my emulator with my half arsed disassembly.
Spoiler. 42 is not the answer. The LDRB is returning the wrong value from DISPCNT. What could that possibly be???
Turns out that my ReadRegisterByte function for the PPU forgot to align the address for the half word read so reads of DISPCNT+1 ended up getting the byte in DISPCNT+2.
3 hours debugging for a 14 character fix. Emulation development in a nutshell.
Looks like a priority issue to me but could also be tile rendering issues