diff options
| author | John Wilbert M. Villamor <lameguy64@gmail.com> | 2019-06-23 07:42:16 +0800 |
|---|---|---|
| committer | John Wilbert M. Villamor <lameguy64@gmail.com> | 2019-06-23 07:42:16 +0800 |
| commit | 7be9178c0f9b0e698a305ecc5c0c41fcc596a4fc (patch) | |
| tree | e98c627e1da5c764563774b89b0c06d7ac5ad0a4 /libpsn00b/psxgpu/resetgraph.s | |
| parent | ae9e545c3ed33d39ce21ae13ceb8337fa34901b8 (diff) | |
| download | psn00bsdk-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.s | 459 |
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 |
