diff options
| author | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-07-05 02:34:11 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-07-05 02:34:11 +0200 |
| commit | beb76e4dd362374b8f42cd971d394bba1074cd8d (patch) | |
| tree | 3ea4cc342737afb9225c01160c92647ba66c78bd /examples/lowlevel/cartrom/rom.S | |
| parent | 5d9aa2d3dfc7d6e51c2eb942ab4cdbae5571a40a (diff) | |
| download | psn00bsdk-fix-include.tar.gz | |
Replace .include with #includefix-include
For some reason, both mipsel-unknown-elf-gcc 8.2.0 and mipsel-non-elf
15.1.0 were unable to resolve .include assembler directives.
As a workaround, it is still possible to use the preprocessor, and
therefore the usual #include preprocessor directive. However, this
requires the assembly files to use the uppercase .S file extension.
Diffstat (limited to 'examples/lowlevel/cartrom/rom.S')
| -rw-r--r-- | examples/lowlevel/cartrom/rom.S | 402 |
1 files changed, 402 insertions, 0 deletions
diff --git a/examples/lowlevel/cartrom/rom.S b/examples/lowlevel/cartrom/rom.S new file mode 100644 index 0000000..587ba6f --- /dev/null +++ b/examples/lowlevel/cartrom/rom.S @@ -0,0 +1,402 @@ +# LibPSn00b Example Programs +# Part of the PSn00bSDk project +# +# TurboBoot Example by Lameguy64 +# +# Note: This example is being obsoleted as GAS is not ideal for making +# ROM firmwares. Use ARMIPS instead, but it cannot build this example +# as it is not GAS syntax compatible. + + +# Uncomment either PAR or XPLORER depending on the cartridge +# you're going to use (makes disabling turbo boot via switch to work) + +#.set PAR, 0 +#.set XPLORER, 1 + + +.set noreorder + +.include "cop0.inc" # Contains definitions for cop0 registers + +.set SP_base, 0x801ffff0 +.set BREAK_ADDR, 0xa0000040 # cop0 breakpoint vector address + + +.set RAM_buff, 2048 +.set RAM_handle, 2052 +.set RAM_tcb, 2056 +.set RAM_evcb, 2060 +.set RAM_stack, 2064 +.set RAM_psexe, 2068 + + +.set EXE_pc0, 0 # PS-EXE header offsets +.set EXE_gp0, 4 +.set EXE_taddr, 8 +.set EXE_tsize, 12 +.set EXE_daddr, 16 +.set EXE_dsize, 20 +.set EXE_baddr, 24 +.set EXE_bsize, 28 +.set EXE_spaddr, 32 +.set EXE_sp_size, 36 +.set EXE_sp, 40 +.set EXE_fp, 44 +.set EXE_gp, 48 +.set EXE_ret, 52 +.set EXE_base, 56 +.set EXE_datapos, 60 + + +.section .text + + +# ROM header +# +# The Licensed by... strings are essential otherwise the BIOS will not +# execute the boot vectors. Always make sure the tty message fields (string +# after Licensed by) must be no more than 80 bytes long and must have a null +# terminating byte. +# +# Postboot vector isn't particularly practical as its only executed in between +# the PS boot logo and the point where game execution occurs. +# +header: + # Postboot vector + .word 0 + .ascii "Licensed by Sony Computer Entertainment Inc." + .ascii "Not officially licensed or endorsed by Sony Computer Entertainment Inc." + + .balign 0x80 # This keeps things in the header aligned + + # Preboot vector + .word preboot + .ascii "Licensed by Sony Computer Entertainment Inc." + .ascii "Cart ROM example for PSn00bSDK https://github.com/lameguy64/psn00bsdk" + + .balign 0x80 # This keeps things in the header aligned + + +# Preboot vector +# +# All it does is it initializes a breakpoint vector at 0x40 +# and sets a cop0 breakpoint at 0x80030000 to perform a midboot +# exploit as preboot doesn't have the kernel area initialized. +# +preboot: + + li $v0, 1 + +.ifdef XPLORER + lui $a0, 0x1f06 # Read switch status for Xplorer + lbu $v0, 0($a0) +.endif + +.ifdef PAR + lui $a0, 0x1f02 # Read switch status for PAR/GS devices + lbu $v0, 0x18($a0) +.endif + + nop + andi $v0, 0x1 + beqz $v0, .no_rom # If switch is off don't install hook + nop # and effectively disables the cartridge + + li $v0, BREAK_ADDR # Patch a jump at cop0 breakpoint vector + + li $a0, 0x3c1a1f00 # lui $k0, $1f00 + sw $a0, 0($v0) + la $a1, entry # ori $k0, < address to code entrypoint > + andi $a1, 0xffff + lui $a0, 0x375a + or $a0, $a1 + sw $a0, 4($v0) + li $a0, 0x03400008 # jr $k0 + sw $a0, 8($v0) + sw $0 , 12($v0) # nop + + lui $v0, 0xffff # Set BPCM and BDAM masks + ori $v0, 0xffff + mtc0 $v0, BDAM + mtc0 $v0, BPCM + + + li $v0, 0x80030000 # Set break on PC and data-write address + + mtc0 $v0, BDA # BPC break is for compatibility with no$psx + mtc0 $v0, BPC # as it does not emulate break on BDA + + lui $v0, 0xeb80 # Enable break on data-write and and break + mtc0 $v0, DCIC # on PC to DCIC control register + +.no_rom: + + jr $ra # Return to BIOS + nop + + +# Actual ROM entrypoint +.global entry +entry: + + mtc0 $0 , DCIC # Clear DCIC register + + la $sp, SP_base # Set stack base + la $gp, 0x8000c000 # Set GP address as RAM base addr in this case + + jal SetDefaultExitFromException # Set default exit handler just in case + nop + jal ExitCriticalSection # Exit out of critical section (brings back interrupts) + nop + + # Beyond this point, the PS1 is in full control to the ROM + + la $a0, m_banner # Print out program banner + jal printf + addiu $sp, -4 + addiu $sp, 4 + + la $a0, m_cdinit + jal printf + addiu $sp, -4 + addiu $sp, 4 + + jal _96_init # Initialize the CD + nop + + la $a0, m_ok # Print OK message if init didn't crash + jal printf + addiu $sp, -4 + addiu $sp, 4 + + la $a0, m_readfile + la $a1, s_systemcnf + jal printf + addiu $sp, -8 + addiu $sp, 8 + + la $a0, s_systemcnf # Attempt to open the SYSTEM.CNF file on CD + li $a1, 1 + jal open + addiu $sp, -8 + addiu $sp, 8 + + bltz $v0, .no_systemcnf # Fallback to loading PSX.EXE if not found + nop + + sw $v0, RAM_handle($gp) # Save file handle + + move $a0, $v0 # Read file contents of SYSTEM.CNF + move $a1, $gp + li $a2, 0x0800 + jal read + addiu $sp, -12 + addiu $sp, 12 + + lw $a0, RAM_handle($gp) # Close file + jal close + addiu $sp, -4 + addiu $sp, 4 + + la $a0, m_ok # Output ok message + jal printf + addiu $sp, -4 + addiu $sp, 4 + + # Parse CNF file + + la $a0, m_parsecnf + jal printf + nop + + la $a1, s_tcb # Get TCB number + jal strcasestr + move $a0, $gp + jal skipspace # Skip spaces + addiu $a0, $v0, 3 + addiu $a0, $v0, -2 # Step two charactters back and inject '0x' + li $v0, '0' + sb $v0, 0($a0) + li $v0, 'x' + sb $v0, 1($a0) + jal atoi + addiu $sp, -4 + addiu $sp, 4 + move $s1, $v0 + + la $a1, s_evcb # Get EVCB number + jal strcasestr + move $a0, $gp + jal skipspace + addiu $a0, $v0, 5 + addiu $a0, $v0, -2 + li $v0, '0' + sb $v0, 0($a0) + li $v0, 'x' + sb $v0, 1($a0) + jal atoi + addiu $sp, -4 + addiu $sp, 4 + move $s0, $v0 + + la $a1, s_stack # Get STACK address + jal strcasestr + move $a0, $gp + jal skipspace + addiu $a0, $v0, 5 + addiu $a0, $v0, -2 + li $v0, '0' + sb $v0, 0($a0) + li $v0, 'x' + sb $v0, 1($a0) + jal atoi + addiu $sp, -4 + addiu $sp, 4 + move $s2, $v0 + + la $a1, s_boot # Get the PS-EXE file name + jal strcasestr + move $a0, $gp + + jal skipspace # Skip spaces + addiu $a0, $v0, 4 + + addiu $a0, $gp, RAM_psexe # Extract the line + jal getline + move $a1, $v0 + + la $a0, m_ok # Print successful parsing + jal printf + addiu $sp, -4 + addiu $sp, 4 + + la $a0, m_readfile + addiu $a1, $gp, RAM_psexe + jal printf + addiu $sp, -8 + addiu $sp, 8 + + b .do_load # Proceed loading PS-EXE + addiu $a0, $gp, RAM_psexe + +.no_systemcnf: # Load fallback + + la $a0, m_notfound + jal printf + addiu $sp, -4 + addiu $sp, 4 + + la $a0, m_fallback + jal printf + addiu $sp, -4 + addiu $sp, 4 + + li $s0, 0x10 # Default EvCBs and TCBs + li $s1, 0x04 + li $s2, SP_base # Default stack + la $a0, s_psxexe # Attempt loading PSX.EXE + +.do_load: + + jal LoadExe # Load PS-EXE + move $a1, $gp + + beqz $v0, load_fail + nop + + la $a0, m_ok + jal printf + addiu $sp, -4 + addiu $sp, 4 + + sw $s2, EXE_sp($gp) # Patch the header + sw $s2, EXE_spaddr($gp) + + la $a0, m_boot + jal printf + addiu $sp, -4 + addiu $sp, 4 + + jal EnterCriticalSection # Disable interrupt handling + nop + + move $a0, $s0 # Set configuration (EvCBs and TCBs) + move $a1, $s1 + move $a2, $s2 + jal SetConf + addiu $sp, -12 + addiu $sp, 12 + + move $a0, $gp # Transfer execution + move $a1, $0 + move $a2, $0 + jal DoExec + addiu $sp, -12 + addiu $sp, 12 + + +load_fail: # Fail state + la $a0, m_loadfail + jal printf + nop +.fail_loop: + b .fail_loop + nop + + +.include "parse.inc" +.include "bios.inc" + + +# Strings + +s_boot: + .asciz "BOOT" + .balign 4 +s_tcb: + .asciz "TCB" + .balign 4 +s_evcb: + .asciz "EVENT" + .balign 4 +s_stack: + .asciz "STACK" + .balign 4 +s_systemcnf: + .asciz "cdrom:SYSTEM.CNF;1" + .balign 4 +s_psxexe: + .asciz "cdrom:PSX.EXE;1" + .balign 4 + + +# Message strings + +m_banner: + .asciz "\nCARTROM Bootstrap Example by Lameguy64\nPart of the PSn00bSDK Project\n\n" + .balign 4 +m_cdinit: + .asciz "Initializing CD-ROM (BIOS)... " + .balign 4 +m_readfile: + .asciz "Attempting to read %s... " + .balign 4 +m_parsecnf: + .asciz "Parsing CNF file... " + .balign 4 +m_fallback: + .asciz "Falling back to loading PSX.EXE... " + .balign 4 +m_notfound: + .asciiz "Not found.\n" + .balign 4 +m_ok: + .asciz "Ok.\n" + .balign 4 +m_boot: + .asciz "Boot!\n" + .balign 4 +m_loadfail: + .asciz "Failed to load PS-EXE file.\n" + .balign 4 |
