aboutsummaryrefslogtreecommitdiff
path: root/libpsn00b/psxgpu/resetgraph.s
diff options
context:
space:
mode:
authorJohn Wilbert M. Villamor <lameguy64@gmail.com>2019-06-23 07:42:16 +0800
committerJohn Wilbert M. Villamor <lameguy64@gmail.com>2019-06-23 07:42:16 +0800
commit7be9178c0f9b0e698a305ecc5c0c41fcc596a4fc (patch)
treee98c627e1da5c764563774b89b0c06d7ac5ad0a4 /libpsn00b/psxgpu/resetgraph.s
parentae9e545c3ed33d39ce21ae13ceb8337fa34901b8 (diff)
downloadpsn00bsdk-7be9178c0f9b0e698a305ecc5c0c41fcc596a4fc.tar.gz
LibPSn00b officially v0.10b, added psxsio library, better DrawSync() and VSync(), better reference manual.
Diffstat (limited to 'libpsn00b/psxgpu/resetgraph.s')
-rw-r--r--libpsn00b/psxgpu/resetgraph.s459
1 files changed, 305 insertions, 154 deletions
diff --git a/libpsn00b/psxgpu/resetgraph.s b/libpsn00b/psxgpu/resetgraph.s
index 189b1ad..ff0b353 100644
--- a/libpsn00b/psxgpu/resetgraph.s
+++ b/libpsn00b/psxgpu/resetgraph.s
@@ -1,5 +1,4 @@
.set noreorder
-.set noat
.include "hwregs_a.h"
@@ -16,21 +15,7 @@ ResetGraph:
la $v0, _hooks_installed # Skip installing hooks if this function
lbu $v0, 0($v0) # has already been called before once
nop
- bnez $v0, .skip_hook_init
- nop
-
- # Temporary, may help improve compatibility?
- #jal SetDefaultExitFromException
- #nop
-
- jal ChangeClearPAD # Remove pad handler left by the BIOS
- move $a0, $0
-
- li $a0, 1
- jal ChangeClearRCnt # Remove RCnt handler
- move $a1, $0
-
- jal _96_remove # Remove CD handling left by the BIOS
+ bnez $v0, .Lskip_hook_init
nop
lui $a3, 0x1f80 # Base address for I/O
@@ -40,48 +25,51 @@ ResetGraph:
sw $v0, DPCR($a3)
sw $0 , DICR($a3) # Clear DICR (not needed)
- li $v0, 0x9 # Enable IRQ0 (vblank)
- sw $v0, IMASK($a3)
-
- # Set an event handler
-
- li $a0, 0xf2000003 # RCntCNT3 (vsync class)
- li $a1, 0x2
- li $a2, 0x1000
- la $a3, _vsync_func # VSync event handler
-
- jal OpenEvent # Open a VSync event handler
- # (PSXSDK style vsync handler)
- addiu $sp, -16
- addiu $sp, 16
-
- la $v1, _vsync_event_desc # Save event descriptor
- sw $v0, 0($v1)
-
- move $a0, $v0
- jal EnableEvent # Enable the opened event
- addiu $sp, -4
- addiu $sp, 4
-
+ sw $0 , IMASK($a3) # Clear IRQ settings
+
la $v0, _hooks_installed # Set installed flag
li $v1, 0x1
sb $v1, 0($v0)
- la $v0, _vsync_counter # Clear VSync counter
+ la $v0, _vsync_cb_func # Clear VSync callback function
sw $0 , 0($v0)
- la $v0, _vsync_callback_func # Clear callback function
- sw $0 , 0($v0)
-
- la $a0, _custom_exit
+ la $a1, _vsync_irq_callback # Install VSync interrupt callback
+ jal InterruptCallback
+ li $a0, 0
+
+ la $a0, _custom_exit # Set custom exit handler
jal SetCustomExitFromException
addiu $sp, -4
addiu $sp, 4
+ move $a0, $0
+ jal ChangeClearPAD # Disable VSync IRQ auto ack
+ addiu $sp, -4
+ addiu $sp, 4
+
+ li $a0, 3
+ move $a1, $0
+ jal ChangeClearRCnt # Remove RCnt timer IRQ auto ack
+ addiu $sp, -8
+ addiu $sp, 8
+
+ jal _96_remove # Remove CD handling left by the BIOS
+ nop
+
+ la $a0, resetgraph_msg
+ move $a1, $0
+ move $a2, $0
+ la $a1, _irq_func_table
+ la $a2, _custom_exit
+ jal printf
+ addiu $sp, -16
+ addiu $sp, 16
+
jal ExitCriticalSection # Re-enable interrupts
nop
-
-.skip_hook_init:
+
+.Lskip_hook_init:
lui $a3, 0x1f80
@@ -89,42 +77,40 @@ ResetGraph:
lui $v1, 0x0010
and $v0, $v1
la $v1, _gpu_standard
- beqz $v0, .not_pal
+ beqz $v0, .Lnot_pal
sw $0 , 0($v1)
li $v0, 1
sw $v0, 0($v1)
-.not_pal:
+.Lnot_pal:
- lw $a0, 4($sp) # Get argument value
+ lw $a0, 4($sp) # Get argument value
lui $a3, 0x1f80 # Set base I/O again (likely destroyed
# by previous calls)
li $v0, 0x1d00 # Configure timer 1 as Hblank counter
sw $v0, T1_MODE($a3) # Set timer 1 value
-
- li $at, 1
- beq $a0, $at, .gpu_init_1
+
+ beq $a0, 1, .Lgpu_init_1
nop
- li $at, 3
- beq $a0, $at, .gpu_init_3
+ beq $a0, 3, .Lgpu_init_3
nop
sw $0 , GP1($a3) # Reset the GPU
- b .init_done
+ b .Linit_done
nop
-.gpu_init_1:
+.Lgpu_init_1:
sw $0 , D2_CHCR($a3) # Stop any DMA
-.gpu_init_3:
+.Lgpu_init_3:
li $v0, 0x1 # Reset the command buffer
sw $v0, GP1($a3)
-.init_done:
+.Linit_done:
lw $ra, 0($sp)
lw $a0, 4($sp) # Return
@@ -132,147 +118,312 @@ ResetGraph:
addiu $sp, 8
-.global _vsync_func # VSync event handler, executed on
-.type _vsync_func, @function # every VBlank
-_vsync_func:
-
- la $gp, _gp
-
- lui $at, 0x1f80 # Check if there's a VSync IRQ
- lw $v0, IMASK($at)
+.global VSync # VSync function
+.type VSync, @function
+VSync:
+
+ addiu $sp, -12
+ sw $ra, 0($sp)
+ sw $s0, 4($sp)
+
+ lui $a3, IOBASE # Get GPU status (for interlace sync)
+ lw $s0, GP1($a3)
+
+.Lhwait_loop: # Get Hblank time
+ lw $v0, T1_CNT($a3)
+ nop
+ lw $v1, T1_CNT($a3)
nop
- andi $v0, $v0, 0x1
- beqz $v0, .exit
+ bne $v0, $v1, .Lhwait_loop
nop
+
+ la $a3, _vsync_lasthblank # Calculate Hblank time since last
+ lw $v1, 0($a3)
+ nop
+ subu $v0, $v1
+ andi $v0, 0xffff
+
+ beq $a0, 1, .Lhblank_exit # Return Hblank time only, no VSync
+ sw $v0, 8($sp) # Stored as return value
+
+ bgez $a0, .Lvsync # Vsync if argument is 0 and up
+ nop
+
+ la $v0, _vsync_rcnt # Return VSync count only
+ lw $v0, 0($v0)
+ nop
+ b .Lvsync_exit
+ sw $v0, 8($sp)
+
+.Lvsync:
- lw $v1, ISTAT($at)
+ bnez $a0, .Lnot_zero
nop
- andi $v0, $v1, 0x1
- beqz $v0, .exit
+ li $a0, 1
+
+.Lnot_zero:
+
+ la $v0, _vsync_rcnt # Call vsync sub function (with timeout)
+ lw $v0, 0($v0)
+ addiu $a1, $a0, 1
+ jal _vsync_sub
+ addu $a0, $v0, $a0
+
+ lui $v0, 0x40
+ and $v0, $s0, $v0
+ beqz $v0, .Lhblank_exit
+ nop
+
+ lui $a3, IOBASE # Interlace wait logic
+
+ lw $v0, GP1($a3)
+ nop
+ xor $v0, $s0, $v0
+ bltz $v0, .Lhblank_exit
+ lui $a0, 0x8000
+
+.Linterlace_wait:
+ lw $v0, GP1($a3)
+ nop
+ xor $v0, $s0, $v0
+ and $v0, $a0
+ beqz $v0, .Linterlace_wait
nop
- #xori $v1, $v1, 0x1 # Acknowledge the IRQ
- #sw $v1, ISTAT($at) # Commented out as it breaks BIOS pads
+.Lhblank_exit: # Set current Hblank as last value
- la $v1, _vsync_counter # Increment VSync counter
- lw $v0, 0($v1)
+ la $a2, _vsync_lasthblank
+
+.Lhwait2_loop:
+ lw $v0, T1_CNT($a3)
+ nop
+ lw $v1, T1_CNT($a3)
+ sw $v0, 0($a2)
+ bne $v0, $v1, .Lhwait2_loop
nop
- addiu $v0, 1
- sw $v0, 0($v1)
- la $v0, _vsync_callback_func # Check if a callback function is set
+.Lvsync_exit:
+
+ lw $ra, 0($sp)
+ lw $s0, 4($sp)
+ lw $v0, 8($sp)
+ jr $ra
+ addiu $sp, 12
+
+
+.type _vsync_sub, @function
+_vsync_sub:
+
+ # a0 - VSync destination count
+ # a1 - Timeout ratio (number of vsyncs to wait relative to vsync count)
+
+ addiu $sp, -4
+ sw $ra, 0($sp)
+
+ sll $a1, 15 # Timeout counter
+
+ la $v0, _vsync_rcnt
lw $v0, 0($v0)
nop
- beqz $v0, .exit
+ bge $v0, $a0, .Lvsync_sub_exit
nop
+
+.Lvsync_wait:
- addiu $sp, -0x20 # Save return address
- sw $ra, 28($sp)
-
- jalr $v0 # Execute user function
+ addiu $a1, -1
+
+ la $v1, 0xffffffff
+ bne $a1, $v1, .Lnot_timeout
nop
- lw $ra, 28($sp) # Restore previous return address
- addiu $sp, 0x20
+ la $a0, vsynctimeout_msg
+ jal puts
+ addiu $sp, -8
+
+ jal ChangeClearPAD
+ move $a0, $0
+
+ li $a0, 3
+ jal ChangeClearRCnt
+ move $a1, $0
+
+ addiu $sp, 8
+ b .Lvsync_sub_exit
+ li $v0, -1
+
+.Lnot_timeout:
-.exit:
- jr $ra
+ la $v0, _vsync_rcnt
+ lw $v0, 0($v0)
+ nop
+ blt $v0, $a0, .Lvsync_wait
nop
+
+.Lvsync_sub_exit:
+
+ lw $ra, 0($sp)
+ addiu $sp, 4
+ jr $ra
+ move $v0, $0
-.global _vsync_func_2
-.type _vsync_func_2, @function
-_vsync_func_2:
- lui $at, 0x1f80 # Check if there's a VSync IRQ
- lw $v0, IMASK($at)
- nop
- andi $v0, $v0, 0x1
- beqz $v0, .exit_2
+.type _vsync_irq_callback, @function
+_vsync_irq_callback:
+
+ lui $a0, IOBASE
+
+ la $v1, _vsync_rcnt # Increment VSync root counter
+ lw $v0, 0($v1)
nop
+ addiu $v0, 1
+ sw $v0, 0($v1)
- lw $v1, ISTAT($at)
+ la $v0, _vsync_cb_func # Check if a callback function is set
+ lw $v0, 0($v0)
nop
- andi $v0, $v1, 0x1
- beqz $v0, .exit_2
+ beqz $v0, .Lno_callback
nop
- xori $v1, $v1, 0x1 # Acknowledge the IRQ
- sw $v1, ISTAT($at)
-
-.exit_2:
+ addiu $sp, -4 # Save return address
+ sw $ra, 0($sp)
+ jalr $v0 # Execute user callback function
+ nop
+ lw $ra, 0($sp) # Restore previous return address
+ addiu $sp, 4
- j ReturnFromException
+ lui $a0, IOBASE
+
+.Lno_callback:
+
+ jr $ra
nop
+
+# Global ISR handler of PSn00bSDK
-.global VSync # VSync function
-.type VSync, @function
-VSync:
- addiu $sp, -4
- sw $ra, 0($sp)
+.set at
+
+.type _global_isr, @function
+_global_isr:
+
+ lui $a0, IOBASE # Get IRQ status
+
+.Lisr_loop:
- la $a1, _vsync_counter
- lw $v0, 0($a1)
+ lui $a0, IOBASE # Get IRQ status
+ lw $v0, IMASK($a0)
nop
-.loop:
- lw $v1, 0($a1)
+
+ srl $v0, $s1 # Check IRQ mask bit if set
+ andi $v0, 0x1
+
+ beqz $v0, .Lno_irq # Don't execute callback if IRQ not enabled
nop
- beq $v0, $v1, .loop
+
+ lw $v0, ISTAT($a0)
nop
-
- la $v0, _gpu_current_field # Get last field value
- lbu $v1, 0($v0)
-.wait_field: # Wait for field bit to change
- jal ReadGPUstat
+ srl $v0, $s1 # Check IRQ status bit if set
+ andi $v0, 0x1
+ beqz $v0, .Lno_irq # Don't execute callback if no IRQ
nop
- srl $v0, 31
- beq $v0, $v1, .wait_field
+
+ lw $v1, 0($s0) # Load IRQ callback function
+ nop
+
+ lw $v0, ISTAT($a0) # Acknowledge the IRQ (by writing a 0 bit)
+ li $a1, 1
+ sll $a1, $s1
+ addiu $a2, $0 , -1
+ xor $a1, $a2
+ sw $a1, ISTAT($a0)
+
+ beqz $v1, .Lno_irq # Don't execute if callback is not set
nop
- la $v1, _gpu_current_field # Store new field value
- sb $v0, 0($v1)
-
- lw $ra, 0($sp)
- addiu $sp, 4
- jr $ra
+ jalr $v1 # Call interrupt handler
nop
+
+.Lno_irq:
+
+ addiu $s0, 4
+
+ blt $s1, 11, .Lisr_loop
+ addiu $s1, 1
+ j ReturnFromException
+ nop
+
.section .data
-.global library_credits
-.type library_credits, @object
-library_credits:
- .string "psxgpu programs by Lameguy64"
+# VSync root counter
+.type _vsync_rcnt, @object
+_vsync_rcnt:
+ .word 0
+
+.type _vsync_lasthblank, @object
+_vsync_lasthblank:
+ .word 0
+
+.comm _vsync_cb_func, 4, 4
+
+.comm _gpu_standard, 4, 4
+.comm _gpu_current_field, 4, 4
+.comm _hooks_installed, 4, 4
+# Global ISR callback table
+
+.global _irq_func_table
+.type _irq_func_table, @object
+_irq_func_table:
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+
+# Global ISR hook structure
.type _custom_exit, @object
_custom_exit:
- .word _vsync_func_2 # pc
- .word _vsync_stack # sp
- .word 0 # fp
- .word 0 # s0
- .word 0 # s1
- .word 0 # s2
- .word 0 # s3
- .word 0 # s4
- .word 0 # s5
- .word 0 # s6
- .word 0 # s7
- .word _gp # gp
-
- .fill 60
-_vsync_stack:
+ .word _global_isr # pc
+ .word _custom_exit_stack # sp
+ .word 0 # fp
+ .word _irq_func_table # s0
+ .word 0 # s1
+ .word 0 # s2
+ .word 0 # s3
+ .word 0 # s4
+ .word 0 # s5
+ .word 0 # s6
+ .word 0 # s7
+ .word _gp # gp
+
+# Global ISR stack
+ .fill 124
+_custom_exit_stack:
.fill 4
-.type _vsync_counter, @object
-_vsync_counter:
- .word 0
-
-.comm _vsync_callback_func, 4, 4
-.comm _vsync_event_desc, 4, 4
+
+.type vsynctimeout_msg, @object
+vsynctimeout_msg:
+ .asciiz "VSync: timeout\n"
-.comm _gpu_standard, 4, 4
-.comm _gpu_current_field, 4, 4
-.comm _hooks_installed, 4, 4
+.type resetgraph_msg, @object
+resetgraph_msg:
+ .asciiz "ResetGraph:itb=%08x,ehk=%08x\n"
+
+.global psxgpu_credits
+.type psxgpu_credits, @object
+psxgpu_credits:
+ .ascii "psxgpu programs by Lameguy64\n"
+ .asciiz "2019 PSn00bSDK Project / Meido-Tek Productions\n"
+ \ No newline at end of file