From beb76e4dd362374b8f42cd971d394bba1074cd8d Mon Sep 17 00:00:00 2001 From: Xavier Del Campo Romero Date: Sat, 5 Jul 2025 02:34:11 +0200 Subject: Replace .include with #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. --- indev/psn00bdbg-mk2/monitor/sdkinst.S | 65 ++++++ indev/psn00bdbg-mk2/monitor/sdkinst.s | 65 ------ indev/psn00bdbg-mk2/monitor/stubinst.S | 185 ++++++++++++++++ indev/psn00bdbg-mk2/monitor/stubinst.s | 185 ---------------- indev/psxpad/card.S | 377 +++++++++++++++++++++++++++++++++ indev/psxpad/card.s | 377 --------------------------------- indev/psxpad/pad.S | 264 +++++++++++++++++++++++ indev/psxpad/pad.s | 264 ----------------------- 8 files changed, 891 insertions(+), 891 deletions(-) create mode 100644 indev/psn00bdbg-mk2/monitor/sdkinst.S delete mode 100644 indev/psn00bdbg-mk2/monitor/sdkinst.s create mode 100644 indev/psn00bdbg-mk2/monitor/stubinst.S delete mode 100644 indev/psn00bdbg-mk2/monitor/stubinst.s create mode 100644 indev/psxpad/card.S delete mode 100644 indev/psxpad/card.s create mode 100644 indev/psxpad/pad.S delete mode 100644 indev/psxpad/pad.s (limited to 'indev') diff --git a/indev/psn00bdbg-mk2/monitor/sdkinst.S b/indev/psn00bdbg-mk2/monitor/sdkinst.S new file mode 100644 index 0000000..6d20624 --- /dev/null +++ b/indev/psn00bdbg-mk2/monitor/sdkinst.S @@ -0,0 +1,65 @@ +# +# To use this installer properly, the program text must be compiled to +# load at a higher address such as 0x80012000. +# +# Then call the function early in your program: +# +# void install_monitor(void); +# +# ... +# +# int main(int argc, const char *argv[]) +# { +# ResetGraph(0); +# +# EnterCriticalSection(); +# install_monitor(); +# ExitCriticalSection(); +# ... +# +.set noreorder + +.section .text + +.global _install_monitor +.type _install_monitor, @function +_install_monitor: # = Patch installer routine + + addiu $sp, -4 + sw $ra, 0($sp) + + la $a0, debug_payload + la $a1, debug_payload_end + la $a2, debug_payload + subu $a1, $a2 + jal .Lcopymem + lui $a2, 0xA001 + + lui $a0, 0x8001 + jalr $a0 + nop + + lw $ra, 0($sp) + addiu $sp, 4 + jr $ra + nop + + .Lcopymem: # installer's copy routine + + addiu $a1, -4 + lw $v0, 0($a0) + addiu $a0, 4 + sw $v0, 0($a2) + bgtz $a1, .Lcopymem + addiu $a2, 4 + jr $ra + nop + + +.section .data + +debug_payload: + + .incbin "patch.bin" + +debug_payload_end: diff --git a/indev/psn00bdbg-mk2/monitor/sdkinst.s b/indev/psn00bdbg-mk2/monitor/sdkinst.s deleted file mode 100644 index 6d20624..0000000 --- a/indev/psn00bdbg-mk2/monitor/sdkinst.s +++ /dev/null @@ -1,65 +0,0 @@ -# -# To use this installer properly, the program text must be compiled to -# load at a higher address such as 0x80012000. -# -# Then call the function early in your program: -# -# void install_monitor(void); -# -# ... -# -# int main(int argc, const char *argv[]) -# { -# ResetGraph(0); -# -# EnterCriticalSection(); -# install_monitor(); -# ExitCriticalSection(); -# ... -# -.set noreorder - -.section .text - -.global _install_monitor -.type _install_monitor, @function -_install_monitor: # = Patch installer routine - - addiu $sp, -4 - sw $ra, 0($sp) - - la $a0, debug_payload - la $a1, debug_payload_end - la $a2, debug_payload - subu $a1, $a2 - jal .Lcopymem - lui $a2, 0xA001 - - lui $a0, 0x8001 - jalr $a0 - nop - - lw $ra, 0($sp) - addiu $sp, 4 - jr $ra - nop - - .Lcopymem: # installer's copy routine - - addiu $a1, -4 - lw $v0, 0($a0) - addiu $a0, 4 - sw $v0, 0($a2) - bgtz $a1, .Lcopymem - addiu $a2, 4 - jr $ra - nop - - -.section .data - -debug_payload: - - .incbin "patch.bin" - -debug_payload_end: diff --git a/indev/psn00bdbg-mk2/monitor/stubinst.S b/indev/psn00bdbg-mk2/monitor/stubinst.S new file mode 100644 index 0000000..54bc8b9 --- /dev/null +++ b/indev/psn00bdbg-mk2/monitor/stubinst.S @@ -0,0 +1,185 @@ +# +# C-callable and linkable version of 'patchinst' portion of monitor.asm +# +# Assemble with: +# mipsel-none-elf-gcc -march=r3000 -c stubinst.s -o stubinst.o +# +# Then call the function early in your program: +# +# void mk2_InstallMonitor(void); +# +# ... +# +# int main(int argc, const char *argv[]) +# { +# ResetGraph(0); +# +# EnterCriticalSection(); +# mk2_InstallMonitor(); +# ExitCriticalSection(); +# ... +# +.set noreorder + +# +# These constants must reflect those in monitor.asm +# +.set MONADDR, 0xC000 +.set MAX_BREAK, 32 + +.set SAVE_mode, 0x30 +.set SAVE_tmode, 0x31 +.set SAVE_k0, 0x34 +.set SAVE_k1, 0x38 +.set SAVE_dcic, 0x3C + +.set DB_BRK_FLAG, 0 +.set DB_BRK_ADDR, 4 +.set DB_BRK_INST, 8 +.set DB_BRK_LCNT, 12 +.set DB_BRK_HCNT, 14 +.set DB_BRK_LEN, 16 + +.set DCIC, $7 + +.section .text + +.global _mk2_InstallMonitor +.type _mk2_InstallMonitor, @function +_mk2_InstallMonitor: + + addiu $sp, -4 + sw $ra, 0($sp) + li $a0, .Lbreakhook # Install breakpoint vector hook + li $a1, (.Lbreakhook_end-.Lbreakhook)+4 + li $a2, 0xA0000040 + jal .Lcopymem + nop + li $v0, 0x200 # Hook monitor entrypoint to + li $v1, 0x40 # SysErrUnresolvedException() slot + sll $v1, 2 + addu $v0, $v1 + la $v1, .Lpayload # Get entrypoint address + lw $v1, 0($v1) + nop + sw $v1, 0($v0) + addiu $t2, $0, 0xB0 # GetB0Table() + jalr $t2 + addiu $t1, $0, 0x57 + li $a0, 0x17 # Get pointer of ReturnFromException() + sll $a0, 2 + addu $a0, $v0 + lw $v0, 0($a0) # Save original address for later + la $v1, .Lpayload + lw $v1, 0($v1) + nop + beq $v0, $v1, .Lnoinstall # Don't install if hooked already + nop + addiu $sp, -4 + sw $a0, 0($sp) + li $a0, .Lpayload # Load monitor code into target + li $a1, (.Lpayload_end-.Lpayload)+4 # address + lui $a2, 0xA000 # write via uncached segment + jal .Lcopymem + ori $a2, MONADDR + lw $a0, 0($sp) + addiu $sp, 4 + lw $v0, 0($a0) + la $v1, .Lpayload + lw $v1, 4($v1) + nop + sw $v0, 0($v1) + la $v0, .Lpayload # Set new address to table + lw $v0, 0($v0) + nop + sw $v0, 0($a0) + li $a0, 0x80 # Move existing exception vector + li $a2, 0x90 # jump to prepend patch + jal .Lcopymem + li $a1, 16 + la $a0, .Lexceptpatch # Patch the exception vector for + li $a2, 0x80 # trace to work properly + jal .Lcopymem + li $a1, 16 + addiu $t2, $0, 0xA0 # FlushCache() just to make sure + jalr $t2 + addiu $t1, $0, 0x44 + jal .Linit_breakpoints + nop + .Lnoinstall: + lw $ra, 0($sp) # Return to caller, debugger + addiu $sp, 4 # already installed + jr $ra + nop + + # patchinst + +# +# = installer's copy routine +# +.Lcopymem: + addiu $a1, -4 + lw $v0, 0($a0) + addiu $a0, 4 + sw $v0, 0($a2) + bgtz $a1, .Lcopymem + addiu $a2, 4 + jr $ra + nop + + # copymem + +# +# = Initializes breakpoint list +# +.Linit_breakpoints: + la $a2, .Lpayload # Get address of breakpoint table + lw $a2, 8($a2) + li $a3, MAX_BREAK + addiu $v0, $0, -1 + .Lclear_loop: + sw $v0, DB_BRK_INST($a2) + sw $v0, DB_BRK_ADDR($a2) + sw $0 , DB_BRK_FLAG($a2) + addiu $a3, -1 + bnez $a3, .Lclear_loop + addiu $a2, DB_BRK_LEN + jr $ra + nop + # init_breakpoints + +# +# = Break vector hook code +# +# This is copied to the breakpoint exception vector at address 40h +# +.Lbreakhook: + sw $k0, SAVE_k0($0) # Save K0 and K1 registers + mfc0 $k0, DCIC # Save DCIC + sw $k1, SAVE_k1($0) + mtc0 $0, DCIC # Clear DCIC in case trace is still + sw $k0, SAVE_dcic($0) # effective + la $k0, breakhandler # Jump to break vector handler + jr $k0 + nop +.Lbreakhook_end: + +# +# = Exception vector patch +# +# This is prepended to the exception vector jump at address 80h +# +.Lexceptpatch: + mfc0 $k0, DCIC # backup DCIC value + nop + mtc0 $0 , DCIC # clear DCIC + sw $k0, SAVE_dcic($0) + +# +# = Payload data +# +.section .data + +.Lpayload: + .incbin "patchcode.bin" +.Lpayload_end: diff --git a/indev/psn00bdbg-mk2/monitor/stubinst.s b/indev/psn00bdbg-mk2/monitor/stubinst.s deleted file mode 100644 index 54bc8b9..0000000 --- a/indev/psn00bdbg-mk2/monitor/stubinst.s +++ /dev/null @@ -1,185 +0,0 @@ -# -# C-callable and linkable version of 'patchinst' portion of monitor.asm -# -# Assemble with: -# mipsel-none-elf-gcc -march=r3000 -c stubinst.s -o stubinst.o -# -# Then call the function early in your program: -# -# void mk2_InstallMonitor(void); -# -# ... -# -# int main(int argc, const char *argv[]) -# { -# ResetGraph(0); -# -# EnterCriticalSection(); -# mk2_InstallMonitor(); -# ExitCriticalSection(); -# ... -# -.set noreorder - -# -# These constants must reflect those in monitor.asm -# -.set MONADDR, 0xC000 -.set MAX_BREAK, 32 - -.set SAVE_mode, 0x30 -.set SAVE_tmode, 0x31 -.set SAVE_k0, 0x34 -.set SAVE_k1, 0x38 -.set SAVE_dcic, 0x3C - -.set DB_BRK_FLAG, 0 -.set DB_BRK_ADDR, 4 -.set DB_BRK_INST, 8 -.set DB_BRK_LCNT, 12 -.set DB_BRK_HCNT, 14 -.set DB_BRK_LEN, 16 - -.set DCIC, $7 - -.section .text - -.global _mk2_InstallMonitor -.type _mk2_InstallMonitor, @function -_mk2_InstallMonitor: - - addiu $sp, -4 - sw $ra, 0($sp) - li $a0, .Lbreakhook # Install breakpoint vector hook - li $a1, (.Lbreakhook_end-.Lbreakhook)+4 - li $a2, 0xA0000040 - jal .Lcopymem - nop - li $v0, 0x200 # Hook monitor entrypoint to - li $v1, 0x40 # SysErrUnresolvedException() slot - sll $v1, 2 - addu $v0, $v1 - la $v1, .Lpayload # Get entrypoint address - lw $v1, 0($v1) - nop - sw $v1, 0($v0) - addiu $t2, $0, 0xB0 # GetB0Table() - jalr $t2 - addiu $t1, $0, 0x57 - li $a0, 0x17 # Get pointer of ReturnFromException() - sll $a0, 2 - addu $a0, $v0 - lw $v0, 0($a0) # Save original address for later - la $v1, .Lpayload - lw $v1, 0($v1) - nop - beq $v0, $v1, .Lnoinstall # Don't install if hooked already - nop - addiu $sp, -4 - sw $a0, 0($sp) - li $a0, .Lpayload # Load monitor code into target - li $a1, (.Lpayload_end-.Lpayload)+4 # address - lui $a2, 0xA000 # write via uncached segment - jal .Lcopymem - ori $a2, MONADDR - lw $a0, 0($sp) - addiu $sp, 4 - lw $v0, 0($a0) - la $v1, .Lpayload - lw $v1, 4($v1) - nop - sw $v0, 0($v1) - la $v0, .Lpayload # Set new address to table - lw $v0, 0($v0) - nop - sw $v0, 0($a0) - li $a0, 0x80 # Move existing exception vector - li $a2, 0x90 # jump to prepend patch - jal .Lcopymem - li $a1, 16 - la $a0, .Lexceptpatch # Patch the exception vector for - li $a2, 0x80 # trace to work properly - jal .Lcopymem - li $a1, 16 - addiu $t2, $0, 0xA0 # FlushCache() just to make sure - jalr $t2 - addiu $t1, $0, 0x44 - jal .Linit_breakpoints - nop - .Lnoinstall: - lw $ra, 0($sp) # Return to caller, debugger - addiu $sp, 4 # already installed - jr $ra - nop - - # patchinst - -# -# = installer's copy routine -# -.Lcopymem: - addiu $a1, -4 - lw $v0, 0($a0) - addiu $a0, 4 - sw $v0, 0($a2) - bgtz $a1, .Lcopymem - addiu $a2, 4 - jr $ra - nop - - # copymem - -# -# = Initializes breakpoint list -# -.Linit_breakpoints: - la $a2, .Lpayload # Get address of breakpoint table - lw $a2, 8($a2) - li $a3, MAX_BREAK - addiu $v0, $0, -1 - .Lclear_loop: - sw $v0, DB_BRK_INST($a2) - sw $v0, DB_BRK_ADDR($a2) - sw $0 , DB_BRK_FLAG($a2) - addiu $a3, -1 - bnez $a3, .Lclear_loop - addiu $a2, DB_BRK_LEN - jr $ra - nop - # init_breakpoints - -# -# = Break vector hook code -# -# This is copied to the breakpoint exception vector at address 40h -# -.Lbreakhook: - sw $k0, SAVE_k0($0) # Save K0 and K1 registers - mfc0 $k0, DCIC # Save DCIC - sw $k1, SAVE_k1($0) - mtc0 $0, DCIC # Clear DCIC in case trace is still - sw $k0, SAVE_dcic($0) # effective - la $k0, breakhandler # Jump to break vector handler - jr $k0 - nop -.Lbreakhook_end: - -# -# = Exception vector patch -# -# This is prepended to the exception vector jump at address 80h -# -.Lexceptpatch: - mfc0 $k0, DCIC # backup DCIC value - nop - mtc0 $0 , DCIC # clear DCIC - sw $k0, SAVE_dcic($0) - -# -# = Payload data -# -.section .data - -.Lpayload: - .incbin "patchcode.bin" -.Lpayload_end: diff --git a/indev/psxpad/card.S b/indev/psxpad/card.S new file mode 100644 index 0000000..2732194 --- /dev/null +++ b/indev/psxpad/card.S @@ -0,0 +1,377 @@ +.set noreorder + +.include "hwregs_a.h" + +.section .text + +_CardCSum: + + # a0 - base csum + # a1 - data pointer + # a2 - length + + lbu $v0, 0($a1) + addi $a2, -1 + xor $a0, $v0 + bgtz $a2, _CardCSum + addiu $a1, 1 + + jr $ra + move $v0, $a0 + + +.global _CardWrite +.type _CardWrite, @function +_CardWrite: + + # a0 - port number + # a1 - pointer to 128 byte buffer + # a2 - sector number + + # return values: + # 0 - ok + # 1 - no device + # 2 - timeout + # 3 - bad checksum + # 4 - bad sector + + # note: you must wait at least two vsyncs between each sector write + + addiu $sp, -4 + sw $ra, 0($sp) + + lui $t0, IOBASE + + li $v0, 0x1003 # TX Enable, Joypad port select + andi $a0, 1 + sll $a0, 13 + or $v0, $a0 # Select port 2 if a0 is 1 + + sh $v0, JOY_CTRL($t0) # Set to Joypad control interface + + jal _wait # Delay for analog pads + li $v0, 310 # (needs optimization testing) + +# May cause issues with third party adapters such as Brook wireless +#.Lread_empty_fifo_write: # Flush the RX FIFO just in case +# lbu $v1, JOY_TXRX($t0) +# lhu $v0, JOY_STAT($t0) +# nop +# andi $v0, 0x2 +# bnez $v0, .Lread_empty_fifo_write +# nop + + lhu $v1, JOY_CTRL($t0) + nop + or $v1, 0x10 + sh $v1, JOY_CTRL($t0) + + jal _CardExchng # Send device check byte + li $a0, 0x81 + andi $v1, $v0, 0x100 # No card if exchange timed out + bnez $v1, .Lno_device_write + addiu $v0, $0 , 1 + + jal _wait # 1st exchange needs 27microsec after ACK + li $v0, 190 # (e.g. 7 as usual + an extra 20) + + jal _CardExchng # Send write command + li $a0, 0x57 + andi $v1, $v0, 0x100 # No card if exchange timed out + bnez $v1, .Lno_device_write + addiu $v0, $0 , 1 + + jal _CardExchng # Receive card ID bytes + move $a0, $0 + andi $v1, $v0, 0x100 + bnez $v1, .Lwrite_timeout + addiu $v0, $0 , 2 + jal _CardExchng + move $a0, $0 + andi $v1, $v0, 0x100 + bnez $v1, .Lwrite_timeout + addiu $v0, $0 , 2 + + jal _CardExchng # Send address bytes + srl $a0, $a2, 8 + andi $v1, $v0, 0x100 + bnez $v1, .Lwrite_timeout + addiu $v0, $0 , 2 + jal _CardExchng + andi $a0, $a2, 0xFF + andi $v1, $v0, 0x100 + bnez $v1, .Lwrite_timeout + addiu $v0, $0 , 2 + + srl $t1, $a2, 8 # Checksum address by MSB xor LSB + andi $v0, $a2, 0xFF + xor $t1, $v0 + + move $a2, $0 # Send data and compute checksum +.Lwrite_loop: + lbu $a0, 0($a1) + addiu $a1, 1 + jal _CardExchng + xor $t1, $a0 + addiu $a2, 1 + blt $a2, 128, .Lwrite_loop + nop + + jal _CardExchng # Send checksum byte + move $a0, $t1 + andi $v1, $v0, 0x100 + bnez $v1, .Lwrite_timeout + addiu $v0, $0 , 2 + + jal _CardExchng # Receive card acknowledge bytes + move $a0, $0 + andi $v1, $v0, 0x100 + bnez $v1, .Lwrite_timeout + addiu $v0, $0 , 2 + jal _CardExchng + move $a0, $0 + andi $v1, $v0, 0x100 + bnez $v1, .Lwrite_timeout + addiu $v0, $0 , 2 + + sb $0 , JOY_TXRX($t0) # Gets end byte + nop +.Lsend_wait_end_write: + lhu $v0, JOY_STAT($t0) + nop + andi $v0, 0x6 + bne $v0, 0x6, .Lsend_wait_end_write + nop + lbu $v0, JOY_TXRX($t0) + nop + + beq $v0, 0x4e, .Lwrite_timeout # Bad checksum + addiu $v0, $0 , 3 + beq $v0, 0xff, .Lwrite_timeout # Bad sector + addiu $v0, $0 , 4 + + move $v0, $0 + +.Lwrite_timeout: +.Lno_device_write: + + sh $0 , JOY_CTRL($t0) # Apparently required + + lw $ra, 0($sp) + addiu $sp, 4 + jr $ra + nop + + +.global _CardRead +.type _CardRead, @function +_CardRead: + + # a0 - port number + # a1 - pointer to 128 byte buffer + # a2 - sector number + + addiu $sp, -12 + sw $ra, 0($sp) + sw $a1, 4($sp) + sw $a2, 8($sp) + + lui $t0, IOBASE + + li $v0, 0x1003 # TX Enable, Joypad port select + andi $a0, 1 + sll $a0, 13 + or $v0, $a0 # Select port 2 if a0 is 1 + + sh $v0, JOY_CTRL($t0) # Set to Joypad control interface + + jal _wait # Delay for analog pads (needs testing) + li $v0, 310 + +# May cause issues with third party adapters such as Brook wireless +#.Lread_empty_fifo: # Flush the RX FIFO just in case +# lbu $v1, JOY_TXRX($t0) +# lhu $v0, JOY_STAT($t0) +# nop +# andi $v0, 0x2 +# bnez $v0, .Lread_empty_fifo +# nop + + lhu $v1, JOY_CTRL($t0) + nop + or $v1, 0x10 + sh $v1, JOY_CTRL($t0) + + jal _CardExchng # Send device check byte + li $a0, 0x81 + andi $v1, $v0, 0x100 # No card if exchange timed out + bnez $v1, .Lno_device + addiu $v0, $0 , 1 + + jal _wait # 1st exchange needs 27microsec after ACK + li $v0, 190 # (e.g. 7 as usual + an extra 20) + + jal _CardExchng # Send read command + li $a0, 0x52 + andi $v1, $v0, 0x100 # No card if exchange timed out + bnez $v1, .Lno_device + addiu $v0, $0 , 2 + + jal _CardExchng # Receive card ID bytes + move $a0, $0 + andi $v1, $v0, 0x100 + bnez $v1, .Lno_device + addiu $v0, $0 , 3 + jal _CardExchng + move $a0, $0 + andi $v1, $v0, 0x100 + bnez $v1, .Lno_device + addiu $v0, $0 , 4 + + jal _CardExchng # Send address + srl $a0, $a2, 8 + andi $v1, $v0, 0x100 + bnez $v1, .Lno_device + addiu $v0, $0 , 5 + jal _CardExchng + andi $a0, $a2, 0xFF + andi $v1, $v0, 0x100 + bnez $v1, .Lno_device + addiu $v0, $0 , 6 + + sb $0 , JOY_TXRX($t0) # Receive command acknowledge 1 + nop +.Lsend_wait: + lhu $v0, JOY_STAT($t0) + nop + andi $v0, 0x4 + beqz $v0, .Lsend_wait + nop + move $v1, $0 + lui $a0, 0xBFC0 +.Lwait_ack: + bgt $v1, 30000, .Lread_timeout + addiu $v0, $0, 10 + lhu $v0, JOY_STAT($t0) + lw $0 , 4($a0) + lw $0 , 0($a0) + andi $v0, 0x202 + bne $v0, 0x202, .Lwait_ack + addiu $v1, 1 + lhu $v1, JOY_CTRL($t0) + lbu $v0, JOY_TXRX($t0) + or $v1, 0x10 + sh $v1, JOY_CTRL($t0) + + jal _CardExchng # Receive command acknowledge 2 + move $a0, $0 + andi $v1, $v0, 0x100 + bnez $v1, .Lno_device + addiu $v0, $0 , 7 + + jal _CardExchng # Receive confirmed address MSB + move $a0, $0 + andi $v1, $v0, 0x100 + bnez $v1, .Lno_device + addiu $v0, $0 , 8 + + jal _CardExchng # Receive confirmed address LSB + move $a0, $0 + andi $v1, $v0, 0x100 + bnez $v1, .Lno_device + addiu $v0, $0 , 9 + + move $a2, $0 +.Ltransfer_loop: + jal _CardExchng + move $a0, $0 + sb $v0, 0($a1) + addiu $a2, 1 + blt $a2, 128, .Ltransfer_loop + addiu $a1, 1 + + jal _CardExchng # Gets checksum byte + move $a0, $0 + move $a3, $v0 + + sb $0 , JOY_TXRX($t0) # Gets end byte + nop +.Lsend_wait_end: + lhu $v1, JOY_STAT($t0) + nop + andi $v1, 0x6 + bne $v1, 0x6, .Lsend_wait_end + nop + lbu $v1, JOY_TXRX($t0) + nop + + lw $a2, 8($sp) + lw $a1, 4($sp) + andi $v1, $a2, 0xff + srl $a2, 8 + xor $a0, $a2, $v1 + jal _CardCSum + li $a2, 128 + + bne $v0, $a3, .Lno_device + addiu $v0, $0 , -1 + + move $v0, $0 +.Lread_timeout: +.Lno_device: + + sh $0 , JOY_CTRL($t0) # Apparently required + + lw $ra, 0($sp) + addiu $sp, 12 + jr $ra + nop + + +.global _CardExchng +.type _CardExchng, @function +_CardExchng: + + lui $t0, IOBASE + + sb $a0, JOY_TXRX($t0) + nop +.Lsend_wait_exchg: + lhu $v0, JOY_STAT($t0) + nop + andi $v0, 0x4 + beqz $v0, .Lsend_wait_exchg + nop + + lui $a0, 0xBFC0 + move $v1, $0 +.Lwait_ack_exchg: + bgt $v1, 500, .Ltimeout + lhu $v0, JOY_STAT($t0) + lw $0 , 4($a0) + lw $0 , 0($a0) + andi $v0, 0x202 + bne $v0, 0x202, .Lwait_ack_exchg + addiu $v1, 1 + + b .Ldone + nop + +.Ltimeout: + + lbu $v0, JOY_TXRX($t0) + nop + b .Lexit_exchg + ori $v0, 0x100 + +.Ldone: + + lhu $v1, JOY_CTRL($t0) + lbu $v0, JOY_TXRX($t0) + or $v1, 0x10 + sh $v1, JOY_CTRL($t0) + +.Lexit_exchg: + + jr $ra + nop diff --git a/indev/psxpad/card.s b/indev/psxpad/card.s deleted file mode 100644 index 2732194..0000000 --- a/indev/psxpad/card.s +++ /dev/null @@ -1,377 +0,0 @@ -.set noreorder - -.include "hwregs_a.h" - -.section .text - -_CardCSum: - - # a0 - base csum - # a1 - data pointer - # a2 - length - - lbu $v0, 0($a1) - addi $a2, -1 - xor $a0, $v0 - bgtz $a2, _CardCSum - addiu $a1, 1 - - jr $ra - move $v0, $a0 - - -.global _CardWrite -.type _CardWrite, @function -_CardWrite: - - # a0 - port number - # a1 - pointer to 128 byte buffer - # a2 - sector number - - # return values: - # 0 - ok - # 1 - no device - # 2 - timeout - # 3 - bad checksum - # 4 - bad sector - - # note: you must wait at least two vsyncs between each sector write - - addiu $sp, -4 - sw $ra, 0($sp) - - lui $t0, IOBASE - - li $v0, 0x1003 # TX Enable, Joypad port select - andi $a0, 1 - sll $a0, 13 - or $v0, $a0 # Select port 2 if a0 is 1 - - sh $v0, JOY_CTRL($t0) # Set to Joypad control interface - - jal _wait # Delay for analog pads - li $v0, 310 # (needs optimization testing) - -# May cause issues with third party adapters such as Brook wireless -#.Lread_empty_fifo_write: # Flush the RX FIFO just in case -# lbu $v1, JOY_TXRX($t0) -# lhu $v0, JOY_STAT($t0) -# nop -# andi $v0, 0x2 -# bnez $v0, .Lread_empty_fifo_write -# nop - - lhu $v1, JOY_CTRL($t0) - nop - or $v1, 0x10 - sh $v1, JOY_CTRL($t0) - - jal _CardExchng # Send device check byte - li $a0, 0x81 - andi $v1, $v0, 0x100 # No card if exchange timed out - bnez $v1, .Lno_device_write - addiu $v0, $0 , 1 - - jal _wait # 1st exchange needs 27microsec after ACK - li $v0, 190 # (e.g. 7 as usual + an extra 20) - - jal _CardExchng # Send write command - li $a0, 0x57 - andi $v1, $v0, 0x100 # No card if exchange timed out - bnez $v1, .Lno_device_write - addiu $v0, $0 , 1 - - jal _CardExchng # Receive card ID bytes - move $a0, $0 - andi $v1, $v0, 0x100 - bnez $v1, .Lwrite_timeout - addiu $v0, $0 , 2 - jal _CardExchng - move $a0, $0 - andi $v1, $v0, 0x100 - bnez $v1, .Lwrite_timeout - addiu $v0, $0 , 2 - - jal _CardExchng # Send address bytes - srl $a0, $a2, 8 - andi $v1, $v0, 0x100 - bnez $v1, .Lwrite_timeout - addiu $v0, $0 , 2 - jal _CardExchng - andi $a0, $a2, 0xFF - andi $v1, $v0, 0x100 - bnez $v1, .Lwrite_timeout - addiu $v0, $0 , 2 - - srl $t1, $a2, 8 # Checksum address by MSB xor LSB - andi $v0, $a2, 0xFF - xor $t1, $v0 - - move $a2, $0 # Send data and compute checksum -.Lwrite_loop: - lbu $a0, 0($a1) - addiu $a1, 1 - jal _CardExchng - xor $t1, $a0 - addiu $a2, 1 - blt $a2, 128, .Lwrite_loop - nop - - jal _CardExchng # Send checksum byte - move $a0, $t1 - andi $v1, $v0, 0x100 - bnez $v1, .Lwrite_timeout - addiu $v0, $0 , 2 - - jal _CardExchng # Receive card acknowledge bytes - move $a0, $0 - andi $v1, $v0, 0x100 - bnez $v1, .Lwrite_timeout - addiu $v0, $0 , 2 - jal _CardExchng - move $a0, $0 - andi $v1, $v0, 0x100 - bnez $v1, .Lwrite_timeout - addiu $v0, $0 , 2 - - sb $0 , JOY_TXRX($t0) # Gets end byte - nop -.Lsend_wait_end_write: - lhu $v0, JOY_STAT($t0) - nop - andi $v0, 0x6 - bne $v0, 0x6, .Lsend_wait_end_write - nop - lbu $v0, JOY_TXRX($t0) - nop - - beq $v0, 0x4e, .Lwrite_timeout # Bad checksum - addiu $v0, $0 , 3 - beq $v0, 0xff, .Lwrite_timeout # Bad sector - addiu $v0, $0 , 4 - - move $v0, $0 - -.Lwrite_timeout: -.Lno_device_write: - - sh $0 , JOY_CTRL($t0) # Apparently required - - lw $ra, 0($sp) - addiu $sp, 4 - jr $ra - nop - - -.global _CardRead -.type _CardRead, @function -_CardRead: - - # a0 - port number - # a1 - pointer to 128 byte buffer - # a2 - sector number - - addiu $sp, -12 - sw $ra, 0($sp) - sw $a1, 4($sp) - sw $a2, 8($sp) - - lui $t0, IOBASE - - li $v0, 0x1003 # TX Enable, Joypad port select - andi $a0, 1 - sll $a0, 13 - or $v0, $a0 # Select port 2 if a0 is 1 - - sh $v0, JOY_CTRL($t0) # Set to Joypad control interface - - jal _wait # Delay for analog pads (needs testing) - li $v0, 310 - -# May cause issues with third party adapters such as Brook wireless -#.Lread_empty_fifo: # Flush the RX FIFO just in case -# lbu $v1, JOY_TXRX($t0) -# lhu $v0, JOY_STAT($t0) -# nop -# andi $v0, 0x2 -# bnez $v0, .Lread_empty_fifo -# nop - - lhu $v1, JOY_CTRL($t0) - nop - or $v1, 0x10 - sh $v1, JOY_CTRL($t0) - - jal _CardExchng # Send device check byte - li $a0, 0x81 - andi $v1, $v0, 0x100 # No card if exchange timed out - bnez $v1, .Lno_device - addiu $v0, $0 , 1 - - jal _wait # 1st exchange needs 27microsec after ACK - li $v0, 190 # (e.g. 7 as usual + an extra 20) - - jal _CardExchng # Send read command - li $a0, 0x52 - andi $v1, $v0, 0x100 # No card if exchange timed out - bnez $v1, .Lno_device - addiu $v0, $0 , 2 - - jal _CardExchng # Receive card ID bytes - move $a0, $0 - andi $v1, $v0, 0x100 - bnez $v1, .Lno_device - addiu $v0, $0 , 3 - jal _CardExchng - move $a0, $0 - andi $v1, $v0, 0x100 - bnez $v1, .Lno_device - addiu $v0, $0 , 4 - - jal _CardExchng # Send address - srl $a0, $a2, 8 - andi $v1, $v0, 0x100 - bnez $v1, .Lno_device - addiu $v0, $0 , 5 - jal _CardExchng - andi $a0, $a2, 0xFF - andi $v1, $v0, 0x100 - bnez $v1, .Lno_device - addiu $v0, $0 , 6 - - sb $0 , JOY_TXRX($t0) # Receive command acknowledge 1 - nop -.Lsend_wait: - lhu $v0, JOY_STAT($t0) - nop - andi $v0, 0x4 - beqz $v0, .Lsend_wait - nop - move $v1, $0 - lui $a0, 0xBFC0 -.Lwait_ack: - bgt $v1, 30000, .Lread_timeout - addiu $v0, $0, 10 - lhu $v0, JOY_STAT($t0) - lw $0 , 4($a0) - lw $0 , 0($a0) - andi $v0, 0x202 - bne $v0, 0x202, .Lwait_ack - addiu $v1, 1 - lhu $v1, JOY_CTRL($t0) - lbu $v0, JOY_TXRX($t0) - or $v1, 0x10 - sh $v1, JOY_CTRL($t0) - - jal _CardExchng # Receive command acknowledge 2 - move $a0, $0 - andi $v1, $v0, 0x100 - bnez $v1, .Lno_device - addiu $v0, $0 , 7 - - jal _CardExchng # Receive confirmed address MSB - move $a0, $0 - andi $v1, $v0, 0x100 - bnez $v1, .Lno_device - addiu $v0, $0 , 8 - - jal _CardExchng # Receive confirmed address LSB - move $a0, $0 - andi $v1, $v0, 0x100 - bnez $v1, .Lno_device - addiu $v0, $0 , 9 - - move $a2, $0 -.Ltransfer_loop: - jal _CardExchng - move $a0, $0 - sb $v0, 0($a1) - addiu $a2, 1 - blt $a2, 128, .Ltransfer_loop - addiu $a1, 1 - - jal _CardExchng # Gets checksum byte - move $a0, $0 - move $a3, $v0 - - sb $0 , JOY_TXRX($t0) # Gets end byte - nop -.Lsend_wait_end: - lhu $v1, JOY_STAT($t0) - nop - andi $v1, 0x6 - bne $v1, 0x6, .Lsend_wait_end - nop - lbu $v1, JOY_TXRX($t0) - nop - - lw $a2, 8($sp) - lw $a1, 4($sp) - andi $v1, $a2, 0xff - srl $a2, 8 - xor $a0, $a2, $v1 - jal _CardCSum - li $a2, 128 - - bne $v0, $a3, .Lno_device - addiu $v0, $0 , -1 - - move $v0, $0 -.Lread_timeout: -.Lno_device: - - sh $0 , JOY_CTRL($t0) # Apparently required - - lw $ra, 0($sp) - addiu $sp, 12 - jr $ra - nop - - -.global _CardExchng -.type _CardExchng, @function -_CardExchng: - - lui $t0, IOBASE - - sb $a0, JOY_TXRX($t0) - nop -.Lsend_wait_exchg: - lhu $v0, JOY_STAT($t0) - nop - andi $v0, 0x4 - beqz $v0, .Lsend_wait_exchg - nop - - lui $a0, 0xBFC0 - move $v1, $0 -.Lwait_ack_exchg: - bgt $v1, 500, .Ltimeout - lhu $v0, JOY_STAT($t0) - lw $0 , 4($a0) - lw $0 , 0($a0) - andi $v0, 0x202 - bne $v0, 0x202, .Lwait_ack_exchg - addiu $v1, 1 - - b .Ldone - nop - -.Ltimeout: - - lbu $v0, JOY_TXRX($t0) - nop - b .Lexit_exchg - ori $v0, 0x100 - -.Ldone: - - lhu $v1, JOY_CTRL($t0) - lbu $v0, JOY_TXRX($t0) - or $v1, 0x10 - sh $v1, JOY_CTRL($t0) - -.Lexit_exchg: - - jr $ra - nop diff --git a/indev/psxpad/pad.S b/indev/psxpad/pad.S new file mode 100644 index 0000000..0fa66aa --- /dev/null +++ b/indev/psxpad/pad.S @@ -0,0 +1,264 @@ +.set noreorder + +.include "hwregs_a.h" + +.section .text + +.global _InitPadDirect +.type _InitPadDirect, @function +_InitPadDirect: + + addiu $sp, -4 + sw $ra, 0($sp) + + lui $t0, IOBASE + + # Interface setup + li $v0, 0x40 # Interface reset + sh $v0, JOY_CTRL($t0) + li $v0, 0x88 # 250kHz clock rate + sh $v0, JOY_BAUD($t0) + li $v0, 0x0d # 8-bit, no parity, x1 multiplier + sh $v0, JOY_MODE($t0) + li $v0, 0x1003 # JOY1, TX enabled + sh $v0, JOY_CTRL($t0) + + jal _wait + li $v0, 1000 + + # Empty RX fifo +.Lempty_fifo: + lbu $v1, JOY_TXRX($t0) + lhu $v0, JOY_STAT($t0) + nop + andi $v0, 0x2 + bnez $v0, .Lempty_fifo + nop + + lw $ra, 0($sp) + addiu $sp, 4 + jr $ra + nop + + +.global _PadSetPort +.type _PadSetPort, @function +_PadSetPort: + addiu $sp, -4 + sw $ra, 0($sp) + + lui $t0, IOBASE + + beq $a0, 2, .Lstop_comms + nop + + li $v0, 0x1003 # TX Enable, Joypad port select + andi $a0, 1 + sll $a0, 13 + or $v0, $a0 # Select port 2 if a0 is 1 + + sh $v0, JOY_CTRL($t0) # Set to Joypad control interface + + jal _wait # Delay for analog pads (needs testing) + li $v0, 500 + +.Lread_empty_fifo_set: # Flush the RX FIFO just in case + lbu $v1, JOY_TXRX($t0) + lhu $v0, JOY_STAT($t0) + nop + andi $v0, 0x2 + bnez $v0, .Lread_empty_fifo_set + nop + + lw $ra, 0($sp) + addiu $sp, 4 + jr $ra + nop + +.Lstop_comms: + + sh $0 , JOY_CTRL($t0) + + lw $ra, 0($sp) + addiu $sp, 4 + jr $ra + nop + + +.global _PadReadDirect +.type _PadReadDirect, @function +_PadReadDirect: + + # a0 - port number + # a1 - device data buffer + # a2 - data max length + + addiu $sp, -4 + sw $ra, 0($sp) + + lui $t0, IOBASE + + li $v0, 0x1003 # TX Enable, Joypad port select + andi $a0, 1 + sll $a0, 13 + or $v0, $a0 # Select port 2 if a0 is 1 + + sh $v0, JOY_CTRL($t0) # Set to Joypad control interface + + jal _wait # Delay for analog pads (needs testing) + li $v0, 310 + +# May cause issues with third party adapters such as Brook wireless +#.Lread_empty_fifo: # Flush the RX FIFO just in case +# lbu $v1, JOY_TXRX($t0) +# lhu $v0, JOY_STAT($t0) +# nop +# andi $v0, 0x2 +# bnez $v0, .Lread_empty_fifo +# nop + + jal _PadExchng # Send device check byte + li $a0, 0x01 + + andi $v1, $v0, 0x100 # No pad if exchange timed out + bnez $v1, .Lno_device + addiu $v0, $0 , 1 + + sb $v0, 0($a1) + addiu $a1, 1 + + jal _wait # 1st exchange needs 27microsec after ACK + li $v0, 190 # (e.g. 7 as usual + an extra 20) + + jal _PadExchng # Send command byte + li $a0, 0x42 + + sb $v0, 0($a1) + addiu $a1, 1 + addiu $a2, -2 + + jal _PadExchng # Send 0 for pads, 1 for multitap + move $a0, $0 # Read is usually 0x5A + + addi $a3, $0 , 1 + + la $t1, _pad_mot_values + +.Lread_loop: # Read until buffer full, or no more data + + lbu $a0, 0($t1) + nop + beqz $a0, .Lskip_mot + nop + + jal _PadExchng + nop + + b .Ldone_exchg + addiu $t1, 1 + +.Lskip_mot: + + jal _PadExchng # when ACK is no longer triggered + move $a0, $0 + +.Ldone_exchg: + + sb $v0, 0($a1) + + andi $v0, 0x100 + bnez $v0, .Lread_end + addi $a3, 1 + + addiu $a2, -1 + bgtz $a2, .Lread_loop + addiu $a1, 1 + +.Lread_end: + + b .Lexit + move $v0, $a3 + +.Lno_device: + + addiu $v0, $0 , -1 + sb $v0, 0($a1) + +.Lexit: + + sh $0 , JOY_CTRL($t0) + + lw $ra, 0($sp) + addiu $sp, 4 + jr $ra + nop + + +.global _PadExchng +.type _PadExchng, @function +_PadExchng: + + lui $t0, IOBASE + + sb $a0, JOY_TXRX($t0) + nop +.Lsend_wait: + lhu $v0, JOY_STAT($t0) + nop + andi $v0, 0x4 + beqz $v0, .Lsend_wait + nop + + move $v1, $0 +.Lwait_ack: + bgt $v1, 100, .Ltimeout + lhu $v0, JOY_STAT($t0) + nop + andi $v0, 0x202 + bne $v0, 0x202, .Lwait_ack + addiu $v1, 1 + + b .Ldone + nop + +.Ltimeout: + + lbu $v0, JOY_TXRX($t0) + nop + b .Lexit_exchg + ori $v0, 0x100 + +.Ldone: + + lhu $v1, JOY_CTRL($t0) + lbu $v0, JOY_TXRX($t0) + or $v1, 0x10 + sh $v1, JOY_CTRL($t0) + +.Lexit_exchg: + + jr $ra + nop + + +.global _wait +.type _wait, @function +_wait: + addiu $v0, -1 + bgtz $v0, _wait + nop + jr $ra + nop + + +.section .data + +.global _pad_mot_values +.type _pad_mot_values, @object +_pad_mot_values: + .byte 0 # Small motor + .byte 0 # Big motor + .byte 0 + .byte 0 + + diff --git a/indev/psxpad/pad.s b/indev/psxpad/pad.s deleted file mode 100644 index 0fa66aa..0000000 --- a/indev/psxpad/pad.s +++ /dev/null @@ -1,264 +0,0 @@ -.set noreorder - -.include "hwregs_a.h" - -.section .text - -.global _InitPadDirect -.type _InitPadDirect, @function -_InitPadDirect: - - addiu $sp, -4 - sw $ra, 0($sp) - - lui $t0, IOBASE - - # Interface setup - li $v0, 0x40 # Interface reset - sh $v0, JOY_CTRL($t0) - li $v0, 0x88 # 250kHz clock rate - sh $v0, JOY_BAUD($t0) - li $v0, 0x0d # 8-bit, no parity, x1 multiplier - sh $v0, JOY_MODE($t0) - li $v0, 0x1003 # JOY1, TX enabled - sh $v0, JOY_CTRL($t0) - - jal _wait - li $v0, 1000 - - # Empty RX fifo -.Lempty_fifo: - lbu $v1, JOY_TXRX($t0) - lhu $v0, JOY_STAT($t0) - nop - andi $v0, 0x2 - bnez $v0, .Lempty_fifo - nop - - lw $ra, 0($sp) - addiu $sp, 4 - jr $ra - nop - - -.global _PadSetPort -.type _PadSetPort, @function -_PadSetPort: - addiu $sp, -4 - sw $ra, 0($sp) - - lui $t0, IOBASE - - beq $a0, 2, .Lstop_comms - nop - - li $v0, 0x1003 # TX Enable, Joypad port select - andi $a0, 1 - sll $a0, 13 - or $v0, $a0 # Select port 2 if a0 is 1 - - sh $v0, JOY_CTRL($t0) # Set to Joypad control interface - - jal _wait # Delay for analog pads (needs testing) - li $v0, 500 - -.Lread_empty_fifo_set: # Flush the RX FIFO just in case - lbu $v1, JOY_TXRX($t0) - lhu $v0, JOY_STAT($t0) - nop - andi $v0, 0x2 - bnez $v0, .Lread_empty_fifo_set - nop - - lw $ra, 0($sp) - addiu $sp, 4 - jr $ra - nop - -.Lstop_comms: - - sh $0 , JOY_CTRL($t0) - - lw $ra, 0($sp) - addiu $sp, 4 - jr $ra - nop - - -.global _PadReadDirect -.type _PadReadDirect, @function -_PadReadDirect: - - # a0 - port number - # a1 - device data buffer - # a2 - data max length - - addiu $sp, -4 - sw $ra, 0($sp) - - lui $t0, IOBASE - - li $v0, 0x1003 # TX Enable, Joypad port select - andi $a0, 1 - sll $a0, 13 - or $v0, $a0 # Select port 2 if a0 is 1 - - sh $v0, JOY_CTRL($t0) # Set to Joypad control interface - - jal _wait # Delay for analog pads (needs testing) - li $v0, 310 - -# May cause issues with third party adapters such as Brook wireless -#.Lread_empty_fifo: # Flush the RX FIFO just in case -# lbu $v1, JOY_TXRX($t0) -# lhu $v0, JOY_STAT($t0) -# nop -# andi $v0, 0x2 -# bnez $v0, .Lread_empty_fifo -# nop - - jal _PadExchng # Send device check byte - li $a0, 0x01 - - andi $v1, $v0, 0x100 # No pad if exchange timed out - bnez $v1, .Lno_device - addiu $v0, $0 , 1 - - sb $v0, 0($a1) - addiu $a1, 1 - - jal _wait # 1st exchange needs 27microsec after ACK - li $v0, 190 # (e.g. 7 as usual + an extra 20) - - jal _PadExchng # Send command byte - li $a0, 0x42 - - sb $v0, 0($a1) - addiu $a1, 1 - addiu $a2, -2 - - jal _PadExchng # Send 0 for pads, 1 for multitap - move $a0, $0 # Read is usually 0x5A - - addi $a3, $0 , 1 - - la $t1, _pad_mot_values - -.Lread_loop: # Read until buffer full, or no more data - - lbu $a0, 0($t1) - nop - beqz $a0, .Lskip_mot - nop - - jal _PadExchng - nop - - b .Ldone_exchg - addiu $t1, 1 - -.Lskip_mot: - - jal _PadExchng # when ACK is no longer triggered - move $a0, $0 - -.Ldone_exchg: - - sb $v0, 0($a1) - - andi $v0, 0x100 - bnez $v0, .Lread_end - addi $a3, 1 - - addiu $a2, -1 - bgtz $a2, .Lread_loop - addiu $a1, 1 - -.Lread_end: - - b .Lexit - move $v0, $a3 - -.Lno_device: - - addiu $v0, $0 , -1 - sb $v0, 0($a1) - -.Lexit: - - sh $0 , JOY_CTRL($t0) - - lw $ra, 0($sp) - addiu $sp, 4 - jr $ra - nop - - -.global _PadExchng -.type _PadExchng, @function -_PadExchng: - - lui $t0, IOBASE - - sb $a0, JOY_TXRX($t0) - nop -.Lsend_wait: - lhu $v0, JOY_STAT($t0) - nop - andi $v0, 0x4 - beqz $v0, .Lsend_wait - nop - - move $v1, $0 -.Lwait_ack: - bgt $v1, 100, .Ltimeout - lhu $v0, JOY_STAT($t0) - nop - andi $v0, 0x202 - bne $v0, 0x202, .Lwait_ack - addiu $v1, 1 - - b .Ldone - nop - -.Ltimeout: - - lbu $v0, JOY_TXRX($t0) - nop - b .Lexit_exchg - ori $v0, 0x100 - -.Ldone: - - lhu $v1, JOY_CTRL($t0) - lbu $v0, JOY_TXRX($t0) - or $v1, 0x10 - sh $v1, JOY_CTRL($t0) - -.Lexit_exchg: - - jr $ra - nop - - -.global _wait -.type _wait, @function -_wait: - addiu $v0, -1 - bgtz $v0, _wait - nop - jr $ra - nop - - -.section .data - -.global _pad_mot_values -.type _pad_mot_values, @object -_pad_mot_values: - .byte 0 # Small motor - .byte 0 # Big motor - .byte 0 - .byte 0 - - -- cgit v1.2.3