Major minor: at one point in the tutorial, the screen does get greyed out, even with Dolphin's broken rendering. That's a starting point to figure out why things broke.
EID 611 - the scissor region is over the screen in that case, but not in the others. Obj 232, which renders:
BP register BPMEM_SCISSOROFFSET
Scissor X offset: 171
Scissor Y offset: 171
Object 231, which doesn't render (actually in 218):
BP register BPMEM_SCISSOROFFSET
Scissor X offset: -341
Scissor Y offset: 171
From the original cutscene fifolog, object 1:
BP register BPMEM_SCISSOROFFSET
Scissor X offset: 171
Scissor Y offset: -341
void gx::GXSetScissorBoxOffset(int param_1,int param_2)
{
write_volatile_1(DAT_cc008000,0x61);
write_volatile_4(0xcc008000,
(param_2 + 0x156) * 0x200 & 0xffc00U | param_1 + 0x156U >> 1 & 0x3ff | 0x59000000
);
*(undefined2 *)(DAT_80361b50 + 2) = 0;
return;
}
0x156 is 342.
So calling with (0, 0) gives 342, 342. But they get divided by 2, so it actually gives (171, 171). OK.
The loading screen adjusts the scissor offset to scroll. OK.
80065ac0 GameLayout_setScissor Easy enough.
Dynamicly allocated: Gamelayout struct is at 806fd260. Relevant fields are at 806fd2a4, 806fd2a8. There are 4 sprite managers, at 805a7e00/805ada80/805b9300/805bef80. Relevant fields have offset 0x38/0x3c (giving 0xb8/0xbc for the ones ending in 0x80).
Messy memory breakpoint output, cleaned up later on
Init:
21:26:177 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065484 (GameLayout_init) Write32 0 at 806fd2a4 ( --- )
21:26:177 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065488 (GameLayout_init) Write32 0 at 806fd2a8 ( --- )
Press a on title:
21:40:810 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 3e0 at 806fd2a4 ( --- )
21:40:810 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:40:836 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 3c0 at 806fd2a4 ( --- )
21:40:836 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:40:870 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 3a0 at 806fd2a4 ( --- )
21:40:870 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:40:903 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 380 at 806fd2a4 ( --- )
21:40:903 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:40:936 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 360 at 806fd2a4 ( --- )
21:40:936 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:40:967 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 340 at 806fd2a4 ( --- )
21:40:967 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:41:003 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 320 at 806fd2a4 ( --- )
21:41:003 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:41:034 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 300 at 806fd2a4 ( --- )
21:41:034 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:41:069 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 2e0 at 806fd2a4 ( --- )
21:41:069 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:41:105 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 2c0 at 806fd2a4 ( --- )
21:41:105 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:41:134 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 2a0 at 806fd2a4 ( --- )
21:41:135 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:41:171 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 280 at 806fd2a4 ( --- )
21:41:171 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:41:202 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 260 at 806fd2a4 ( --- )
21:41:202 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:41:237 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 240 at 806fd2a4 ( --- )
21:41:237 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:41:268 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 220 at 806fd2a4 ( --- )
21:41:268 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:41:303 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 200 at 806fd2a4 ( --- )
21:41:303 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:41:335 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 1e0 at 806fd2a4 ( --- )
21:41:335 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:41:371 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 1c0 at 806fd2a4 ( --- )
21:41:371 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:41:400 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 1a0 at 806fd2a4 ( --- )
21:41:400 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:41:438 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 180 at 806fd2a4 ( --- )
21:41:438 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
Finishes loading main menu:
21:43:639 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 660 at 806fd2a4 ( --- )
21:43:639 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:43:673 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 640 at 806fd2a4 ( --- )
21:43:673 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:43:704 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 620 at 806fd2a4 ( --- )
21:43:704 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:43:736 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 600 at 806fd2a4 ( --- )
21:43:736 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:43:771 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 5e0 at 806fd2a4 ( --- )
21:43:771 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:43:803 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 5c0 at 806fd2a4 ( --- )
21:43:804 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:43:840 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 5a0 at 806fd2a4 ( --- )
21:43:840 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:43:874 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 580 at 806fd2a4 ( --- )
21:43:874 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:43:906 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 560 at 806fd2a4 ( --- )
21:43:906 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:43:940 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 540 at 806fd2a4 ( --- )
21:43:941 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:43:971 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 520 at 806fd2a4 ( --- )
21:43:971 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:44:004 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 500 at 806fd2a4 ( --- )
21:44:004 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:44:036 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 4e0 at 806fd2a4 ( --- )
21:44:036 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:44:071 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 4c0 at 806fd2a4 ( --- )
21:44:071 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:44:112 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 4a0 at 806fd2a4 ( --- )
21:44:112 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:44:140 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 480 at 806fd2a4 ( --- )
21:44:140 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:44:173 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 460 at 806fd2a4 ( --- )
21:44:173 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:44:205 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 440 at 806fd2a4 ( --- )
21:44:205 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:44:239 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 420 at 806fd2a4 ( --- )
21:44:239 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
21:44:271 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 400 at 806fd2a4 ( --- )
21:44:271 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 0 at 806fd2a8 ( --- )
Click return to title: starts scrolling up
21:49:412 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:49:412 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 3ee at 806fd2a8 ( --- )
21:49:443 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:49:443 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 3dc at 806fd2a8 ( --- )
21:49:478 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:49:478 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 3ca at 806fd2a8 ( --- )
21:49:510 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:49:510 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 3b8 at 806fd2a8 ( --- )
21:49:545 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:49:545 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 3a6 at 806fd2a8 ( --- )
21:49:578 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:49:578 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 394 at 806fd2a8 ( --- )
21:49:610 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:49:610 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 382 at 806fd2a8 ( --- )
21:49:645 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:49:645 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 370 at 806fd2a8 ( --- )
21:49:676 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:49:676 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 35e at 806fd2a8 ( --- )
21:49:710 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:49:710 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 34c at 806fd2a8 ( --- )
21:49:747 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:49:747 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 33a at 806fd2a8 ( --- )
21:49:776 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:49:776 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 328 at 806fd2a8 ( --- )
21:49:812 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:49:812 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 316 at 806fd2a8 ( --- )
21:49:845 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:49:845 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 304 at 806fd2a8 ( --- )
21:49:877 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:49:877 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 2f2 at 806fd2a8 ( --- )
21:49:910 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:49:911 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 2e0 at 806fd2a8 ( --- )
21:49:943 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:49:943 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 2ce at 806fd2a8 ( --- )
21:49:980 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:49:980 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 2bc at 806fd2a8 ( --- )
21:50:012 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:50:012 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 2aa at 806fd2a8 ( --- )
21:50:045 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:50:045 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 298 at 806fd2a8 ( --- )
21:50:079 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:50:079 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 286 at 806fd2a8 ( --- )
21:50:110 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:50:110 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 274 at 806fd2a8 ( --- )
21:50:144 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:50:144 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 262 at 806fd2a8 ( --- )
21:50:177 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:50:177 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 250 at 806fd2a8 ( --- )
21:50:210 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:50:210 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 23e at 806fd2a8 ( --- )
21:50:247 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:50:247 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 22c at 806fd2a8 ( --- )
21:50:279 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:50:279 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 220 at 806fd2a8 ( --- )
Finishes loading, more scrolling:
21:51:029 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:029 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 5ce at 806fd2a8 ( --- )
21:51:064 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:064 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 5bc at 806fd2a8 ( --- )
21:51:095 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:095 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 5aa at 806fd2a8 ( --- )
21:51:131 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:131 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 598 at 806fd2a8 ( --- )
21:51:160 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:160 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 586 at 806fd2a8 ( --- )
21:51:197 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:197 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 574 at 806fd2a8 ( --- )
21:51:228 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:228 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 562 at 806fd2a8 ( --- )
21:51:262 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:262 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 550 at 806fd2a8 ( --- )
21:51:295 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:295 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 53e at 806fd2a8 ( --- )
21:51:329 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:329 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 52c at 806fd2a8 ( --- )
21:51:360 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:360 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 51a at 806fd2a8 ( --- )
21:51:395 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:395 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 508 at 806fd2a8 ( --- )
21:51:431 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:431 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 4f6 at 806fd2a8 ( --- )
21:51:461 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:461 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 4e4 at 806fd2a8 ( --- )
21:51:498 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:498 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 4d2 at 806fd2a8 ( --- )
21:51:528 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:528 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 4c0 at 806fd2a8 ( --- )
21:51:564 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:564 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 4ae at 806fd2a8 ( --- )
21:51:595 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:595 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 49c at 806fd2a8 ( --- )
21:51:629 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:629 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 48a at 806fd2a8 ( --- )
21:51:661 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:661 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 478 at 806fd2a8 ( --- )
21:51:698 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:698 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 466 at 806fd2a8 ( --- )
21:51:729 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:729 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 454 at 806fd2a8 ( --- )
21:51:764 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:764 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 442 at 806fd2a8 ( --- )
21:51:795 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:795 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 430 at 806fd2a8 ( --- )
21:51:831 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:831 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 41e at 806fd2a8 ( --- )
21:51:861 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:861 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 40c at 806fd2a8 ( --- )
21:51:898 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac0 (GameLayout_setScissor) Write32 0 at 806fd2a4 ( --- )
21:51:898 Core\PowerPC\BreakPoints.cpp:308 N[MI]: MBP 80065ac4 (GameLayout_setScissor) Write32 400 at 806fd2a8 ( --- )
After doing this, the title screen is white.
In fact, when pressing A on the title screen, it IMMEDIATELY goes blank, instead of scrolling. Huh.
Hardware: https://youtu.be/9apb8K5tWLc?t=40
Dolphin: https://youtu.be/nrl0NFycXOw?t=20
A very simple patch is this:
diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp
index 593417d485..c1f5347b59 100644
--- a/Source/Core/VideoCommon/BPStructs.cpp
+++ b/Source/Core/VideoCommon/BPStructs.cpp
@@ -131,6 +131,8 @@ static void BPWritten(const BPCmd& bp)
case BPMEM_SCISSORTL: // Scissor Rectable Top, Left
case BPMEM_SCISSORBR: // Scissor Rectable Bottom, Right
case BPMEM_SCISSOROFFSET: // Scissor Offset
+ bpmem.scissorOffset.x = 171;
+ bpmem.scissorOffset.y = 171;
SetScissor();
SetViewport();
VertexShaderManager::SetViewportChanged();
While this gets things to render, the scrolling breaks. It also breaks the boss roars in Super Mario Galaxy... which might be a good thing to analyze too:
Super Mario Galaxy, frame 2: objects 604 and 605. But object 603 is what actually adjusts the scissor rectangle.
BP register BPMEM_SCISSOROFFSET (603)
Scissor X offset: 171
Scissor Y offset: -61
BP register BPMEM_SCISSOROFFSET (604)
Scissor X offset: 171
Scissor Y offset: 171
OK, these numbers are hard to visualize. I've converted them back to the ranges that would be passed as inputs to GXSetScissorBoxOffset:
BP register BPMEM_SCISSOROFFSET (603)
Scissor X offset: 0 (171)
Scissor Y offset: -464 (-61)
BP register BPMEM_SCISSOROFFSET (604)
Scissor X offset: 0 (171)
Scissor Y offset: 0 (171)
This still violates the warning that the x value should be between -342 - 382 inclusive and the y value should be between -342 - 494 inclusive. But that's fine.
And also the values for major minor:
BP register BPMEM_SCISSOROFFSET (232)
Scissor X offset: 0 (171)
Scissor Y offset: 0 (171)
BP register BPMEM_SCISSOROFFSET (231 / 218)
Scissor X offset: -1024 (-341)
Scissor Y offset: 0 (171)
BP register BPMEM_SCISSOROFFSET (orig 1)
Scissor X offset: 0 (171)
Scissor Y offset: -1024 (-341)
Next idea for a fix:
diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp
index 593417d485..c1f5347b59 100644
--- a/Source/Core/VideoCommon/BPStructs.cpp
+++ b/Source/Core/VideoCommon/BPStructs.cpp
@@ -131,6 +131,8 @@ static void BPWritten(const BPCmd& bp)
case BPMEM_SCISSORTL: // Scissor Rectable Top, Left
case BPMEM_SCISSORBR: // Scissor Rectable Bottom, Right
case BPMEM_SCISSOROFFSET: // Scissor Offset
+ bpmem.scissorOffset.x = ((((bpmem.scissorOffset.x << 1) - 342) & (1024 - 1)) + 342) >> 1;
+ bpmem.scissorOffset.y = ((((bpmem.scissorOffset.y << 1) - 342) & (1024 - 1)) + 342) >> 1;
SetScissor();
SetViewport();
VertexShaderManager::SetViewportChanged();
And yes, this gets things to render, but the title screen is still broken (it immediately disappears instead of scrolling), and this still breaks the boss roar. Probably because it's handling negative values wrong still.
SceneLoading_tick
(8005f920) does deliberately add 1024 in some cases (see FLOAT_80361108 = 1024.0
)
Note that for SceneLoading_tick to decompile right, 8000fb78
must have a signature of int zz_8000fb78_(void)
and 8000fb90
must have a signature of bool get_8023e869(void)
(the automatic name for that function is very misleading).
It's still hard to understand what it's doing, because ghidra and floats don't go well together, and because of C++ vtables. But it's clear that the 1024 is deliberate. (For reference, 8005fde4 is a call to SceneLoading_preparescissor
at 80060294).
Because the above pile of output is a bit confusing, let's focus on one value at a time.
Memory breakpoint at 806fd2a4 (gameManager->gameLayout->scissorXOff
, dynamically allocated but seems to be consistent).
First, we get these (decimal followed by hex) as the title screen goes away:
992, 960, 928, 896, 864, 832, 800, 768, 736, 704, 672, 640, 608, 576, 544, 512, 480, 448, 416, 384
3e0, 3c0, 3a0, 380, 360, 340, 320, 300, 2e0, 2c0, 2a0, 280, 260, 240, 220, 200, 1e0, 1c0, 1a0, 180
Then we get these as the menu screen loads in, with the 3rd value being sign extension (computed by subtracting 2048 / 0x800):
1632, 1600, 1568, 1536, 1504, 1472, 1440, 1408, 1376, 1344, 1312, 1280, 1248, 1216, 1184, 1152, 1120, 1088, 1056, 1024
660, 640, 620, 600, 5e0, 5c0, 5a0, 580, 560, 540, 520, 500, 4e0, 4c0, 4a0, 480, 460, 440, 420, 400
-416, -448, -480, -512, -544, -576, -608, -640, -672, -704, -736, -768, -800, -832, -864, -896, -928, -960, -992, -1024
And when going back to the title screen from the menu, with a breakpoint at 806fd2a8 (gameManager->gameLayout->scissorYOff
):
First, we get these (decimal followed by hex) as the menu screen goes away:
1006, 988, 970, 952, 934, 916, 898, 880, 862, 844, 826, 808, 790, 772, 754, 736, 718, 700, 682, 664, 646, 628, 610, 592, 574, 556, 544
3ee, 3dc, 3ca, 3b8, 3a6, 394, 382, 370, 35e, 34c, 33a, 328, 316, 304, 2f2, 2e0, 2ce, 2bc, 2aa, 298, 286, 274, 262, 250, 23e, 22c, 220
Then we get these as the title screen loads in:
1486, 1468, 1450, 1432, 1414, 1396, 1378, 1360, 1342, 1324, 1306, 1288, 1270, 1252, 1234, 1216, 1198, 1180, 1162, 1144, 1126, 1108, 1090, 1072, 1054, 1036, 1024
5ce, 5bc, 5aa, 598, 586, 574, 562, 550, 53e, 52c, 51a, 508, 4f6, 4e4, 4d2, 4c0, 4ae, 49c, 48a, 478, 466, 454, 442, 430, 41e, 40c, 400
-562, -580, -598, -616, -634, -652, -670, -688, -706, -724, -742, -760, -778, -796, -814, -832, -850, -868, -886, -904, -922, -940, -958, -976, -994, -1012, -1024
The negative values are an issue, but the title screen immediately disappearing indicates that they aren't the only problem.
I notice that the difference between values for x is 32 / 0x20, and for y it is 18 / 0x12 apart from the last one where it is 12/0xc. Note also that 384 = 1024 - 640
, 1632 = 1024 + 640 - 20
, 544 = 1024 - 480
, and 1486 = 1024 + 480 - 18
.
How about remapping it like this:
-1024 -513 -512 -1 0 511 512 1023
0 511 -512 -1 0 511 -512 -1
First, to make things easier, let's rework the way we're editing the value:
diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp
index 593417d485..598174eb2d 100644
--- a/Source/Core/VideoCommon/BPStructs.cpp
+++ b/Source/Core/VideoCommon/BPStructs.cpp
@@ -131,11 +131,21 @@ static void BPWritten(const BPCmd& bp)
case BPMEM_SCISSORTL: // Scissor Rectable Top, Left
case BPMEM_SCISSORBR: // Scissor Rectable Bottom, Right
case BPMEM_SCISSOROFFSET: // Scissor Offset
+ {
+ auto converttoinput = [](int val) { return (val << 1) - 342; };
+ auto remap = [](int val) {
+ // This is still the old incorrect conversion
+ return val & (1024 - 1);
+ };
+ auto converttoreg = [](int val) { return (val + 342) >> 1; };
+ bpmem.scissorOffset.x = converttoreg(remap(converttoinput(bpmem.scissorOffset.x)));
+ bpmem.scissorOffset.y = converttoreg(remap(converttoinput(bpmem.scissorOffset.y)));
SetScissor();
SetViewport();
VertexShaderManager::SetViewportChanged();
GeometryShaderManager::SetViewportChanged();
return;
+ }
case BPMEM_LINEPTWIDTH: // Line Width
GeometryShaderManager::SetLinePtWidthChanged();
return;
And now adjust it to implement that logic in a very simple way:
diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp
index 593417d485..9153884657 100644
--- a/Source/Core/VideoCommon/BPStructs.cpp
+++ b/Source/Core/VideoCommon/BPStructs.cpp
@@ -131,11 +131,24 @@ static void BPWritten(const BPCmd& bp)
case BPMEM_SCISSORTL: // Scissor Rectable Top, Left
case BPMEM_SCISSORBR: // Scissor Rectable Bottom, Right
case BPMEM_SCISSOROFFSET: // Scissor Offset
+ {
+ auto converttoinput = [](int val) { return (val << 1) - 342; };
+ auto remap = [](int val) {
+ if (val < -512)
+ val += 1024;
+ else if (val > 511)
+ val -= 1024;
+ return val;
+ };
+ auto converttoreg = [](int val) { return (val + 342) >> 1; };
+ bpmem.scissorOffset.x = converttoreg(remap(converttoinput(bpmem.scissorOffset.x)));
+ bpmem.scissorOffset.y = converttoreg(remap(converttoinput(bpmem.scissorOffset.y)));
SetScissor();
SetViewport();
VertexShaderManager::SetViewportChanged();
GeometryShaderManager::SetViewportChanged();
return;
+ }
case BPMEM_LINEPTWIDTH: // Line Width
GeometryShaderManager::SetLinePtWidthChanged();
return;
This actually fixes it! Or at least the title screen is fixed. I still see a flash of white after loading screens though.
In major_minor_loading_long.dff (120 frames), frame 46 is the last loading frame, 47 is when the scroll starts, frame 50 is the last all-white frame, and frame 51 is WEIRD (even if it's the only enabled frame, you get multiple outputs?) - though it works fine with immediately present XFB enabled. Frames 51+ have the world visible.
On frame 49:
BP register BPMEM_SCISSOROFFSET
Scissor X offset: -480 (-69)
Scissor Y offset: 0 (171)
which stays at -480...
On frame 50:
BP register BPMEM_SCISSOROFFSET
Scissor X offset: -512 (-85)
Scissor Y offset: 0 (171)
which stays as -512...
And on frame 51:
BP register BPMEM_SCISSOROFFSET
Scissor X offset: -544 (-101)
Scissor Y offset: 0 (171)
which becomes +480. This is definitely wrong, looking at renderdoc.
I think I need a better way to visualize this - renderdoc helps, but it doesn't show ones that end up completely off-screen. Interestingly, there's existing imgui functionality that helps - OverlayProjStats under [Settings] in GFX.ini (not exposed in the UI). This doesn't really work that well, since it assumes the projection is the same for the whole frame, but it's a start...
I've done some experimentation with additional rendering with imgui, but haven't figured out a proper fix yet. It does help visualize what's going on, though. One thing I have found is that getting rid of the game's 1024 offset does fix everything (write 00000000 to 80361108), but it should be possible to emulate correctly without a patch.