Closed G4Vi closed 3 years ago
Alright, that's odd.
I'd start by checking that:
li a0, 1
syscall
Then remove the EnterCriticalSection from the secondary.c reinit_kernel function. I didn't see any ill effects from issuing a EnterCriticalSection with the interrupts disabled, but maybe it matters for this game.
I think the stack pointer is okay, if I single step through the syscall / set a breakpoint on 0x1010
(exit of syscall I think), it returns to the correct location (ExitCriticalSection stub
then reinit_kernel
, back into main
. If I continue single stepping the screen goes black.
It appears after it returns from the syscall into ExitCriticalSection
stub breakpoints do not work at all! Not sure if that's just a no$psx bug or sign of another issue.
Replacing the mfc/mtc block with the syscall and removing the call to EnterCriticalSection
appeared to have no effect. Having the mfc/mtc block AND the syscall in the first stage also did not appear make a difference.
Could you please check on the GPU view what the VRAM contents are? For example, is the font loaded?
With the VRAM viewer, if I run after the ExitCriticalSection
in reinit_kernel
and then click into the debugger window to stop it, both 3D/RE and Screen are green. I'm not sure how to check if the font is loaded. X-range is 590..3150. Y-range is 16..256.
If you just let it run, where does it get stuck? If it gets stuck in one of the busy loops, you should be able to do a mips-linux-gnu-objdump -D secondary.elf
on the tonyhax folder to figure out to which function it corresponds.
Also, I'd recommend going to Options -> Emulation Setup -> Xcept, enabling Custom settings and enabling all exceptions except for "Bad I/O" (many games do it and it's inocuous) and "HC05 Sub-CPU errors" (as the debugging changes to debugging the slave CPU and there's apparently no way to go back to the main CPU). This should make easier to tell if the code is jumping somewhere it shouldn't.
I deleted some posts to remove some incorrect/confusing/irrelevant information.
After ExitCriticalSection
in reinit_kernel
an IRQ runs with
I_MASK (1F801074) has CDROM, DMA, and SPU set (0x20C)
I_STAT (1F801070) has CDROM and DMA set (0x0C).
It proceed to get stuck in an infinite loop inside this IRQ from 0xDF8 to 0xE30, dereferencing s6 waiting for s6 == 0, but s6 == 0x6DA8 which points to 0x6DA8.
If I_MASK is set to 0 at the end of stage one.
li a0, 0
li t1, 0x1F801074
sw a0, 0(t1)
Instead it will proceed all the way until it gets stuck in cd_wait_int
(while (CD_REGS[0] & 0x80);
) part of unlock_drive
, with the screen stuck at "Unlocking CD drive".
I'm not sure what is the easiest way to make unlocking the CD drive work.
I've found the posible culprit, which might also be the same reason XS Moto et al aren't working. Could you please try with latest master?
I've found the posible culprit, which might also be the same reason XS Moto et al aren't working. Could you please try with latest master?
mips-linux-gnu-ld -EL --gc-sections -T secondary.ld patcher.o secondary.o crc.o str.o cfgparse.o gpu.o cdrom.o debugscreen.o bios.o -o secondary.elf
mips-linux-gnu-ld: secondary.elf section `.rodata' will not fit in region `ram'
mips-linux-gnu-ld: region `ram' overflowed by 161 bytes
Makefile:95: recipe for target 'secondary.elf' failed
make: *** [secondary.elf] Error 1
Commenting out the orca image, I was able to build. It gets stuck in the first loop of cd_wait_int
inside of cd_drive_init
.
Hmmm that is odd. I was getting the same issue with XS Moto, but the CD init fixed it for me.
Could you please try now? Commit db0dbdfbdd80a938d73e22fc162f7aec879cc168: https://github.com/socram8888/tonyhax/files/6267227/tonyhax-v1.2.3b.zip
I am now resetting the I_MASK and I_STAT registers, just like official kernel does before exiting the critical section, which before I didn't. The original assembly used two zero writes outside any function, just there in the WarmBoot, and I assummed they weren't critical or anything.
Unfortunately, it still gets stuck in the first loop ofcd_wait_int
inside of cd_drive_init
.
Edit:
It appears the CDROM flag in I_STAT gets set in InstallDevices
in reset_kernel
(after I_STAT and I_MASK) are reset, does this need to be handled somehow?
Edit 2: It doesn't always get set there.
Getting set in InstallDevices is totally normal, it's how the official kernel does it.
The exploit works when background music BGM
from OPTION
in game is set to off (included in the save in the PR). That fixes this game.
The issue may present itself again in other games. The CDROM ISR likely causes the problem, as with BGM set to off it appears the SPU and CDROM no longer set their flags in I_STAT (0x1F801070) .
I really gotta attempt to tweak the I_STAT register on the first stage to disable any interrupt that's not related to controller and memory card, much like FreePSXBoot does.
Since this seems to work well in hardware I'm closing this issue. FTR latest master does disable all interrupts except the VBlank one, required for memory card file reading.
I found one of the player name stack buffer overflows in Castlevania Chronicles https://playstationdev.wiki/ps1devwiki/index.php?title=Vulnerabilities and successfully used it to boot tonyhax on no$psx. However, it gets stuck on the green screen in the secondary loader, the ExitCriticalSection in reinit_kernel does not return properly.
Video, memory card, and memory dump made in video:
https://drive.google.com/drive/u/0/folders/125LJk4hROzLFuWxQGrVfzYVFRx8fLHfv
Console: no$psx 2.0 BIOS: ps30a.bin SHA256: 11052B6499E466BBF0A709B1F9CB6834A9418E66680387912451E971CF8A1FEF Tonyhax version: built from https://github.com/socram8888/tonyhax/commit/1c94f46ee4b3c21927df91452e875784e2d1834b tonyhax-v1.2.3 (with Castlevania Chronicles (CC) stuff added) using mips-mti-linux-gnu toolchain. The CC mcs is built with
entry-full
.