aboutsummaryrefslogtreecommitdiff
path: root/libpsn00b/psxgpu/resetgraph.s
diff options
context:
space:
mode:
authorJohn Wilbert M. Villamor <lameguy64@gmail.com>2019-04-06 10:11:07 +0800
committerJohn Wilbert M. Villamor <lameguy64@gmail.com>2019-04-06 10:11:07 +0800
commitf3e040230772f978540a71aea43dfde200992922 (patch)
treebd8ca31b72dd01e24980b073854e263589530f56 /libpsn00b/psxgpu/resetgraph.s
downloadpsn00bsdk-f3e040230772f978540a71aea43dfde200992922.tar.gz
First commit
Diffstat (limited to 'libpsn00b/psxgpu/resetgraph.s')
-rw-r--r--libpsn00b/psxgpu/resetgraph.s223
1 files changed, 223 insertions, 0 deletions
diff --git a/libpsn00b/psxgpu/resetgraph.s b/libpsn00b/psxgpu/resetgraph.s
new file mode 100644
index 0000000..bc30d3b
--- /dev/null
+++ b/libpsn00b/psxgpu/resetgraph.s
@@ -0,0 +1,223 @@
+.set noreorder
+.set noat
+
+.include "hwregs_a.h"
+
+.section .text
+
+
+.global ResetGraph # Resets the GPU and installs a
+.type ResetGraph, @function # VSync event handler
+ResetGraph:
+ addiu $sp, -0x20 # C style stack allocation (required if
+ sw $ra, 28($sp) # you call BIOS functions from asm)
+ sw $a0, 24($sp)
+
+ 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
+ nop
+
+ lui $a3, 0x1f80 # Base address for I/O
+
+ lui $v0, 0x3b33 # Enables DMA channel 6 (for ClearOTag)
+ ori $v0, 0x3b33 # Enables DMA channel 2
+ 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)
+ nop
+
+ la $v1, _vsync_event_desc # Save event descriptor
+ sw $v0, 0($v1)
+
+ jal EnableEvent # Enable the opened event
+ move $a0, $v0
+
+ la $v0, _hooks_installed # Set installed flag
+ li $v1, 0x1
+ sb $v1, 0($v0)
+
+ la $v0, _vsync_counter # Clear VSync counter
+ sw $0 , 0($v0)
+
+ la $v0, _vsync_callback_func # Clear callback function
+ sw $0 , 0($v0)
+
+ jal ExitCriticalSection # Re-enable interrupts
+ nop
+
+.skip_hook_init:
+
+ lui $a3, 0x1f80
+
+ lw $v0, GP1($a3) # Get video standard
+ lui $v1, 0x0010
+ and $v0, $v1
+ la $v1, _gpu_standard
+ beqz $v0, .not_pal
+ sw $0 , 0($v1)
+ li $v0, 1
+ sw $v0, 0($v1)
+.not_pal:
+
+ lw $a0, 24($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
+ nop
+ li $at, 3
+ beq $a0, $at, .gpu_init_3
+ nop
+
+ sw $0 , GP1($a3) # Reset the GPU
+
+ b .init_done
+ nop
+
+.gpu_init_1:
+
+ sw $0 , D2_CHCR($a3) # Stop any DMA
+
+.gpu_init_3:
+
+ li $v0, 0x1 # Reset the command buffer
+ sw $v0, GP1($a3)
+
+.init_done:
+
+ lw $ra, 28($sp)
+ lw $a0, 24($sp) # Return
+ jr $ra
+ addiu $sp, 0x20
+
+
+.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)
+ nop
+ andi $v0, $v0, 0x1
+ beqz $v0, .exit
+ nop
+
+ lw $v1, ISTAT($at)
+ nop
+ andi $v0, $v1, 0x1
+ beqz $v0, .exit
+ nop
+ xori $v1, $v1, 0x1 # Acknowledge the IRQ
+ sw $v1, ISTAT($at)
+
+ la $v1, _vsync_counter # Increment VSync counter
+ lw $v0, 0($v1)
+ nop
+ addiu $v0, 1
+ sw $v0, 0($v1)
+
+ la $v0, _vsync_callback_func # Check if a callback function is set
+ lw $v0, 0($v0)
+ nop
+ beqz $v0, .exit
+ nop
+
+ addiu $sp, -0x20 # Save return address
+ sw $ra, 28($sp)
+
+ jalr $v0 # Execute user function
+ nop
+
+ lw $ra, 28($sp) # Restore previous return address
+ addiu $sp, 0x20
+
+.exit:
+ jr $ra
+ nop
+
+
+.global VSync # VSync function
+.type VSync, @function
+VSync:
+ addiu $sp, -4
+ sw $ra, 0($sp)
+
+ la $a1, _vsync_counter
+ lw $v0, 0($a1)
+ nop
+.loop:
+ lw $v1, 0($a1)
+ nop
+ beq $v0, $v1, .loop
+ nop
+
+ la $v0, _gpu_current_field # Get last field value
+ lbu $v1, 0($v0)
+.wait_field: # Wait for field bit to change
+ jal ReadGPUstat
+ nop
+ srl $v0, 31
+ beq $v0, $v1, .wait_field
+ nop
+
+ la $v1, _gpu_current_field # Store new field value
+ sb $v0, 0($v1)
+
+ lw $ra, 0($sp)
+ addiu $sp, 4
+ jr $ra
+ nop
+
+
+.section .data
+
+.global library_credits
+.type library_credits, @object
+library_credits:
+ .string "psxgpu programs by Lameguy64"
+
+.type _vsync_counter, @object
+_vsync_counter:
+ .word 0
+
+.comm _vsync_callback_func, 4, 4
+.comm _vsync_event_desc, 4, 4
+
+.comm _gpu_standard, 4, 4
+.comm _gpu_current_field, 4, 4
+.comm _hooks_installed, 4, 4