diff options
| author | John Wilbert M. Villamor <lameguy64@gmail.com> | 2019-04-06 10:11:07 +0800 |
|---|---|---|
| committer | John Wilbert M. Villamor <lameguy64@gmail.com> | 2019-04-06 10:11:07 +0800 |
| commit | f3e040230772f978540a71aea43dfde200992922 (patch) | |
| tree | bd8ca31b72dd01e24980b073854e263589530f56 /libpsn00b/psxgpu | |
| download | psn00bsdk-f3e040230772f978540a71aea43dfde200992922.tar.gz | |
First commit
Diffstat (limited to 'libpsn00b/psxgpu')
| -rw-r--r-- | libpsn00b/psxgpu/addprim.s | 26 | ||||
| -rw-r--r-- | libpsn00b/psxgpu/clearotagr.s | 21 | ||||
| -rw-r--r-- | libpsn00b/psxgpu/drawotag.s | 38 | ||||
| -rw-r--r-- | libpsn00b/psxgpu/drawsync.s | 26 | ||||
| -rw-r--r-- | libpsn00b/psxgpu/gettimimage.c | 39 | ||||
| -rw-r--r-- | libpsn00b/psxgpu/getvideomode.s | 14 | ||||
| -rw-r--r-- | libpsn00b/psxgpu/loadimage.s | 70 | ||||
| -rw-r--r-- | libpsn00b/psxgpu/makefile | 38 | ||||
| -rw-r--r-- | libpsn00b/psxgpu/putdispenv.s | 174 | ||||
| -rw-r--r-- | libpsn00b/psxgpu/putdispenvraw.s | 71 | ||||
| -rw-r--r-- | libpsn00b/psxgpu/putdrawenv.s | 142 | ||||
| -rw-r--r-- | libpsn00b/psxgpu/readgpustat.s | 14 | ||||
| -rw-r--r-- | libpsn00b/psxgpu/readme.txt | 50 | ||||
| -rw-r--r-- | libpsn00b/psxgpu/resetgraph.s | 223 | ||||
| -rw-r--r-- | libpsn00b/psxgpu/setdefdispenv.c | 21 | ||||
| -rw-r--r-- | libpsn00b/psxgpu/setdefdrawenv.c | 26 | ||||
| -rw-r--r-- | libpsn00b/psxgpu/setdispmask.s | 19 | ||||
| -rw-r--r-- | libpsn00b/psxgpu/setvideomode.s | 50 | ||||
| -rw-r--r-- | libpsn00b/psxgpu/vsynccallback.s | 25 |
19 files changed, 1087 insertions, 0 deletions
diff --git a/libpsn00b/psxgpu/addprim.s b/libpsn00b/psxgpu/addprim.s new file mode 100644 index 0000000..1b66274 --- /dev/null +++ b/libpsn00b/psxgpu/addprim.s @@ -0,0 +1,26 @@ +.set noreorder +.set noat + +.section .text + + +.global AddPrim +.type AddPrim, @function +AddPrim: + + lw $v0, 0($a0) # Load OT entry + lw $v1, 0($a1) # Set packet length value (in words) + lui $at, 0x00ff + or $at, 0xffff + and $v0, $at # Mask off the upper 8 bits of OT entry + or $v1, $v0 # OR values together + sw $v1, 0($a1) # Store new address to primitive tag + lw $v0, 0($a0) # Load OT entry + and $a1, $at # Mask off the upper 8 bits of primitive tag + lui $at, 0xff00 + and $v0, $at # Mask off the first 24 bits of OT entry + or $v0, $a1 # OR values together + + jr $ra + sw $v0, 0($a0) # Store result to OT + diff --git a/libpsn00b/psxgpu/clearotagr.s b/libpsn00b/psxgpu/clearotagr.s new file mode 100644 index 0000000..3e888f1 --- /dev/null +++ b/libpsn00b/psxgpu/clearotagr.s @@ -0,0 +1,21 @@ +.set noreorder + +.include "hwregs_a.h" + +.section .text + + +.global ClearOTagR +.type ClearOTagR, @function +ClearOTagR: + lui $a2, 0x1f80 + addi $v0, $a1, -1 + sll $v0, 2 + addu $a0, $v0 + sw $a0, D6_MADR($a2) + andi $a1, 0xffff + sw $a1, D6_BCR($a2) + lui $v0, 0x1100 + addiu $v0, 2 + jr $ra + sw $v0, D6_CHCR($a2) diff --git a/libpsn00b/psxgpu/drawotag.s b/libpsn00b/psxgpu/drawotag.s new file mode 100644 index 0000000..8a5ff0c --- /dev/null +++ b/libpsn00b/psxgpu/drawotag.s @@ -0,0 +1,38 @@ +.set noreorder + +.include "hwregs_a.h" + +.section .text + + +.global DrawOTag +.type DrawOTag, @function +DrawOTag: + addiu $sp, -4 + sw $ra, 0($sp) + + lui $a3, 0x1f80 # I/O segment base + +.gpu_wait: # Wait for GPU to be ready for commands & DMA + jal ReadGPUstat + nop + srl $v0, 26 + andi $v0, 1 + beqz $v0, .gpu_wait + nop + + lui $v0, 0x0400 # Set DMA direction to CPUtoGPU + ori $v0, 0x2 + sw $v0, GP1($a3) + + sw $a0, D2_MADR($a3) # Set DMA base address to specified OT + sw $0, D2_BCR($a3) + + lui $v0, 0x0100 # Begin OT transfer! + ori $v0, 0x0401 + sw $v0, D2_CHCR($a3) + + lw $ra, 0($sp) + addiu $sp, 4 + jr $ra + nop diff --git a/libpsn00b/psxgpu/drawsync.s b/libpsn00b/psxgpu/drawsync.s new file mode 100644 index 0000000..149519d --- /dev/null +++ b/libpsn00b/psxgpu/drawsync.s @@ -0,0 +1,26 @@ +.set noreorder + +.include "hwregs_a.h" + +.section .text + + +.global DrawSync +.type DrawSync, @function +DrawSync: + addiu $sp, -4 + sw $ra, 0($sp) + +.gpu_wait: # Wait for GPU to be ready for commands and DMA + jal ReadGPUstat + nop + srl $v0, 0x1a + andi $v0, 0x5 + li $v1, 5 + bne $v0, $v1, .gpu_wait + nop + + lw $ra, 0($sp) + addiu $sp, 4 + jr $ra + nop diff --git a/libpsn00b/psxgpu/gettimimage.c b/libpsn00b/psxgpu/gettimimage.c new file mode 100644 index 0000000..49ce8e9 --- /dev/null +++ b/libpsn00b/psxgpu/gettimimage.c @@ -0,0 +1,39 @@ +#include <psxgpu.h> + +int GetTimInfo(unsigned int *tim, TIM_IMAGE *timimg) { + + unsigned int *rtim; + + // Check ID + if( ( tim[0]&0xff ) != 0x10 ) { + return 1; + } + + // Check version + if( ( (tim[0]>>8)&0xff ) != 0x0 ) { + return 2; + } + + timimg->mode = tim[1]; + rtim = tim+2; + + // Clut present? + if( timimg->mode & 0x8 ) { + + timimg->crect = (RECT*)(rtim+1); + timimg->caddr = (unsigned int*)(rtim+3); + + rtim += rtim[0]>>2; + + } else { + + timimg->caddr = 0; + + } + + timimg->prect = (RECT*)(rtim+1); + timimg->paddr = (unsigned int*)(rtim+3); + + return 0; + +} diff --git a/libpsn00b/psxgpu/getvideomode.s b/libpsn00b/psxgpu/getvideomode.s new file mode 100644 index 0000000..6f1613c --- /dev/null +++ b/libpsn00b/psxgpu/getvideomode.s @@ -0,0 +1,14 @@ +.set noreorder + + +.section .text + +.global GetVideoMode +.type GetVideoMode, @function +GetVideoMode: + + la $v0, _gpu_standard + lw $v0, 0($v0) + + jr $ra + nop diff --git a/libpsn00b/psxgpu/loadimage.s b/libpsn00b/psxgpu/loadimage.s new file mode 100644 index 0000000..2376b31 --- /dev/null +++ b/libpsn00b/psxgpu/loadimage.s @@ -0,0 +1,70 @@ +.set noreorder + +.include "hwregs_a.h" + +.set RECT_x, 0 +.set RECT_y, 2 +.set RECT_w, 4 +.set RECT_h, 6 + +.section .text + + +.global LoadImage +.type LoadImage, @function +LoadImage: + addiu $sp, -8 + sw $ra, 0($sp) + sw $s0, 4($sp) + + lui $s0, 0x1f80 # Set I/O segment base address + +.gpu_wait: # Wait for GPU to be ready for commands and DMA + jal ReadGPUstat + nop + srl $v0, 0x1a + andi $v0, 0x5 + li $v1, 5 + #srl $v0, 28 + #andi $v0, 1 + bne $v0, $v1, .gpu_wait + nop + + lui $v0, 0x400 # Set DMA direction to off + sw $v0, GP1($s0) + + lui $v0, 0x0100 # Clear GPU cache + sw $v0, GP0($s0) + + lui $v1, 0xa000 # Load image to VRAM + sw $v1, GP0($s0) + lw $v0, RECT_x($a0) # Set XY and dimensions of image + lw $v1, RECT_w($a0) + sw $v0, GP0($s0) + sw $v1, GP0($s0) + + lui $v0, 0x400 # Set DMA direction to CPUtoVRAM + ori $v0, 0x2 + sw $v0, GP1($s0) + + lhu $v0, RECT_w($a0) # Get rectangle size + lhu $v1, RECT_h($a0) + nop + mult $v0, $v1 # Calculate BCR value + mflo $v1 + srl $v1, 0x4 + sll $v1, 0x10 + ori $v1, 0x8 + + sw $a1, D2_MADR($s0) # Set DMA base address and transfer length + sw $v1, D2_BCR($s0) + + lui $v0, 0x100 # Start DMA transfer + ori $v0, 0x201 + sw $v0, D2_CHCR($s0) + + lw $ra, 0($sp) + lw $s0, 4($sp) + jr $ra + addiu $sp, 8 + diff --git a/libpsn00b/psxgpu/makefile b/libpsn00b/psxgpu/makefile new file mode 100644 index 0000000..5eb6265 --- /dev/null +++ b/libpsn00b/psxgpu/makefile @@ -0,0 +1,38 @@ +# Run using make (Linux) or gmake (BSD) +# Part of the PSn00bSDK Project +# 2019 Lameguy64 / Meido-Tek Productions + +PREFIX = mipsel-unknown-elf- + +TARGET = ../libpsxgpu.a + +CFILES = $(notdir $(wildcard ./*.c)) +AFILES = $(notdir $(wildcard ./*.s)) +OFILES = $(addprefix build/,$(CFILES:.c=.o) $(AFILES:.s=.o)) + +INCLUDE = -I../include + +CFLAGS = -O2 -msoft-float -fno-builtin -Wa,--strip-local-absolute +AFLAGS = -msoft-float -Wa,--strip-local-absolute + +CC = $(PREFIX)gcc +AS = $(PREFIX)as +AR = $(PREFIX)ar +RANLIB = $(PREFIX)ranlib + +all: $(TARGET) + +$(TARGET): $(OFILES) + $(AR) cr $(TARGET) $(OFILES) + $(RANLIB) $(TARGET) + +build/%.o: %.c + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ + +build/%.o: %.s + @mkdir -p $(dir $@) + $(CC) $(AFLAGS) $(INCLUDE) -c $< -o $@ + +clean: + rm -Rf build $(TARGET) diff --git a/libpsn00b/psxgpu/putdispenv.s b/libpsn00b/psxgpu/putdispenv.s new file mode 100644 index 0000000..0993e5c --- /dev/null +++ b/libpsn00b/psxgpu/putdispenv.s @@ -0,0 +1,174 @@ +.set noreorder + +.include "hwregs_a.h" + +.set DISP_dx, 0 +.set DISP_dy, 2 +.set DISP_dw, 4 +.set DISP_dh, 6 +.set DISP_sx, 8 +.set DISP_sy, 10 +.set DISP_sw, 12 +.set DISP_sh, 14 +.set DISP_inter, 16 +.set DISP_isrgb24, 17 +.set DISP_reverse, 18 + +.section .text + + +.global PutDispEnv +.type PutDispEnv, @function +PutDispEnv: + + lui $a3, IOBASE + + # Horizontal resolution stuff + + lh $a2, DISP_dw($a0) # Get X resolution + + lh $v0, DISP_sx($a0) + lh $v1, DISP_sw($a0) # Get X screen width + + move $a1, $0 # To use as mode value + + bgt $a2, 560, .mode_640 + nop + bgt $a2, 400, .mode_512 + nop + bgt $a2, 352, .mode_384 + nop + bgt $a2, 280, .mode_320 + nop + + .set noat + +.mode_256: + li $at, 10 + mult $at, $v1 + li $a2, 0x24e + sll $v0, 2 + add $a2, $v0 + b .mode_end + li $v1, 0xa00 +.mode_320: + li $at, 8 + mult $at, $v1 + li $a2, 0x258 + ori $a1, 0x01 + sll $v0, 2 + add $a2, $v0 + b .mode_end + li $v1, 0xa00 +.mode_384: + li $at, 7 + mult $at, $v1 + li $a2, 0x21b + ori $a1, 0x64 + sll $v0, 2 + add $a2, $v0 + b .mode_end + li $v1, 0xa80 +.mode_512: + li $at, 5 + mult $at, $v1 + li $a2, 0x267 + ori $a1, 0x02 + sll $v0, 2 + add $a2, $v0 + b .mode_end + li $v1, 0xa00 +.mode_640: + li $at, 4 + mult $at, $v1 + li $a2, 0x26c + ori $a1, 0x03 + sll $v0, 2 + add $a2, $v0 + li $v1, 0xa00 +.mode_end: + + .set at + + mflo $v0 + bnez $v0, .no_default # Check if screen with is non zero + nop + move $v0, $v1 # Use default if screen width is 0 +.no_default: + + addu $v0, $a2 # Apply horizontal display coordinates + sll $v0, 12 + andi $a2, 0xfff + or $a2, $v0 + lui $v0, 0x0600 + or $v0, $a2 + sw $v0, GP1($a3) + + # Vertical resolution + + lh $v0, DISP_dh($a0) + li $a2, 0x10 + ble $v0, 256, .mode_low + nop + +.mode_high: + ori $a1, 0x04 +.mode_low: + lh $v0, DISP_sy($a0) + lh $v1, DISP_sh($a0) + add $a2, $v0 + bnez $v1, .no_default_vert + nop + li $v1, 0xf0 +.no_default_vert: + add $v1, $a2 + and $a2, 0x3ff + sll $v1, 10 + or $v1, $a2 + lui $v0, 0x0700 + or $v1, $v0 + sw $v1, GP1($a3) + + # Video mode + + la $v0, _gpu_standard + lbu $v0, 0($v0) + nop + beqz $v0, .config_ntsc + nop +.config_pal: + ori $a1, 0x08 +.config_ntsc: + + lbu $v0, DISP_inter($a0) + lbu $v1, DISP_isrgb24($a0) + beqz $v0, .no_inter + nop + or $a1, 0x20 +.no_inter: + beqz $v1, .no_rgb24 + nop + or $a1, 0x10 +.no_rgb24: + lbu $v0, DISP_inter($a0) + nop + beqz $v0, .no_reverse + nop + or $a1, 0x80 +.no_reverse: + + lui $v0, 0x800 # Apply mode + or $a1, $v0 + sw $a1, GP1($a3) + + lhu $v0, DISP_dx($a0) # Set VRAM XY offset + lhu $v1, DISP_dy($a0) + andi $v0, 0x3ff + andi $v1, 0x1ff + sll $v1, 10 + or $v0, $v1 + lui $v1, 0x500 + or $v0, $v1 + + jr $ra + sw $v0, GP1($a3) diff --git a/libpsn00b/psxgpu/putdispenvraw.s b/libpsn00b/psxgpu/putdispenvraw.s new file mode 100644 index 0000000..157150d --- /dev/null +++ b/libpsn00b/psxgpu/putdispenvraw.s @@ -0,0 +1,71 @@ +.set noreorder +.set noat + +.include "hwregs_a.h" + +.set DISP_mode, 0 +.set DISP_vxpos, 4 +.set DISP_vypos, 6 +.set DISP_fbx, 8 +.set DISP_fby, 10 + +.section .text + + +.global PutDispEnvRaw +.type PutDispEnvRaw, @function +PutDispEnvRaw: + addiu $sp, -8 + sw $ra, 0($sp) + sw $s0, 4($sp) + + lui $s0, 0x1f80 + + lh $at, DISP_vxpos($a0) # Set horizontal display range + li $v0, 608 + add $v0, $at + li $v1, 3168 + add $v1, $at + sll $v1, 12 + or $v0, $v1 + lui $v1, 0x600 + or $v1, $v0 + sw $v1, GP1($s0) + + lh $at, DISP_vypos($a0) # Set vertical display range (for NTSC) + li $v1, 120 # (values differet for PAL modes) + sub $v1, $at + li $v0, 136 + sub $v0, $v1 + andi $v0, 0x1ff + li $v1, 120 + add $v1, $at + li $at, 136 + add $at, $v1 + andi $at, 0x1ff + sll $at, 10 + or $v0, $at + lui $at, 0x700 + or $v0, $at + sw $v0, GP1($s0) + + lw $v0, DISP_mode($a0) # Set video mode + lui $at, 0x800 + or $v0, $at + sw $v0, GP1($s0) + + lhu $v0, DISP_fbx($a0) # Set VRAM XY offset + lhu $v1, DISP_fby($a0) + andi $v0, 0x3ff + andi $v1, 0x1ff + sll $v1, 10 + or $v0, $v1 + lui $v1, 0x500 + or $v0, $v1 + sw $v0, GP1($s0) + + lw $ra, 0($sp) + lw $s0, 4($sp) + jr $ra + addiu $sp, 8 + diff --git a/libpsn00b/psxgpu/putdrawenv.s b/libpsn00b/psxgpu/putdrawenv.s new file mode 100644 index 0000000..69af437 --- /dev/null +++ b/libpsn00b/psxgpu/putdrawenv.s @@ -0,0 +1,142 @@ +.set noreorder +.set noat + +.include "hwregs_a.h" + +.set DRAW_x, 0 # Drawing area +.set DRAW_y, 2 +.set DRAW_w, 4 +.set DRAW_h, 6 +.set DRAW_ofx, 8 # Draw offset +.set DRAW_ofy, 10 +.set DRAW_tx, 12 # Texture window +.set DRAW_ty, 14 +.set DRAW_tw, 16 +.set DRAW_th, 18 +.set DRAW_tpage, 20 # TPage values +.set DRAW_dtd, 22 +.set DRAW_dfe, 23 +.set DRAW_isbg, 24 # Clear draw area +.set DRAW_r0, 25 +.set DRAW_g0, 26 +.set DRAW_b0, 27 +.set DRAW_env, 28 + + +.section .text + +.global PutDrawEnv +.type PutDrawEnv, @function +PutDrawEnv: + addiu $sp, -4 + sw $ra, 0($sp) + + addiu $a1, $a0, DRAW_env + + li $v0, 0x04ffffff # Packet header (length+terminator) + sw $v0, 0($a1) + + lhu $v0, DRAW_x($a0) # Set draw area top-left + lhu $v1, DRAW_y($a0) + andi $v0, 0x3ff + andi $v1, 0x1ff + sll $v1, 10 + or $v0, $v1 + lui $v1, 0xe300 + or $v0, $v1 + sw $v0, 4($a1) # 1 + + .set noat + + lhu $v0, DRAW_w($a0) # Set draw area bottom-right + lhu $at, DRAW_x($a0) + addiu $v0, -1 + addu $at, $v0 + andi $at, 0x3ff + lhu $v1, DRAW_h($a0) + lhu $v0, DRAW_y($a0) + addiu $v1, -1 + addu $v0, $v1 + andi $v0, 0x1ff + sll $v0, 10 + or $at, $v0 + lui $v0, 0xe400 + or $at, $v0 + sw $at, 8($a1) # 2 + + lhu $v0, DRAW_x($a0) # Set drawing offset + lhu $v1, DRAW_ofx($a0) + nop + add $v0, $v1 + andi $at, $v0, 0x7ff + lhu $v0, DRAW_y($a0) + lhu $v1, DRAW_ofy($a0) + nop + add $v0, $v1 + andi $v0, 0x7ff + sll $v0, 11 + or $at, $v0 + lui $v0, 0xe500 + or $at, $v0 + sw $at, 12($a1) # 3 + + lhu $at, DRAW_tpage($a0) # Set tpage + lbu $v0, DRAW_dtd($a0) + lbu $v1, DRAW_dfe($a0) + andi $v0, 1 + and $v1, 1 + sll $v0, 9 + sll $v1, 10 + or $at, $v0 + or $at, $v1 + lui $v0, 0xe100 + or $at, $v0 + sw $at, 16($a1) # 4 + + .set at + + lbu $v0, DRAW_isbg($a0) + nop + beqz $v0, .no_fillVRAM + nop + + lw $v0, DRAW_isbg($a0) # FillVRAM + lui $v1, 0x0200 + srl $v0, 8 + or $v0, $v1 + sw $v0, 20($a1) # 5 + lw $v0, DRAW_x($a0) + lw $v1, DRAW_w($a0) + sw $v0, 24($a1) # 6 + + srl $v0, $v1, 16 # Workaround as rectangle primitives + blt $v0, 511, .no_overflow # don't accept a height of 512 + nop + + li $v0, 511 + sll $v0, 16 + andi $v1, 0xffff + or $v1, $v0 + +.no_overflow: + sw $v1, 28($a1) # 7 + li $v0, 0x07ffffff # Packet header (length+terminator) + sw $v0, 0($a1) + +.no_fillVRAM: + +.gpu_wait: # Wait for GPU to become ready for commands and DMA + jal ReadGPUstat + nop + srl $v0, 26 + andi $v0, 1 + beqz $v0, .gpu_wait + nop + + jal DrawOTag + move $a0, $a1 + + lw $ra, 0($sp) + addiu $sp, 4 + jr $ra + nop diff --git a/libpsn00b/psxgpu/readgpustat.s b/libpsn00b/psxgpu/readgpustat.s new file mode 100644 index 0000000..c587cfb --- /dev/null +++ b/libpsn00b/psxgpu/readgpustat.s @@ -0,0 +1,14 @@ +.set noreorder + +.include "hwregs_a.h" + +.section .text + + +.global ReadGPUstat +.type ReadGPUstat, @function +ReadGPUstat: + lui $v0, 0x1f80 + lw $v0, GP1($v0) + jr $ra + nop diff --git a/libpsn00b/psxgpu/readme.txt b/libpsn00b/psxgpu/readme.txt new file mode 100644 index 0000000..55fcb68 --- /dev/null +++ b/libpsn00b/psxgpu/readme.txt @@ -0,0 +1,50 @@ +PSX GPU library, part of PSn00bSDK +2019 Lameguy64 / Meido-Tek Productions + +Licensed under Mozilla Public License + + Open source implementation of the GPU library written mostly in MIPS +assembly. Supports DMA transfers for ordering table draw and transferring +image data to VRAM. The syntax is intentionally made to closely resemble +Sony's syntax for familiarity and to make porting homebrew made using the +official SDK to PSn00bSDK a little easier. + + +Library developer(s): + + Lameguy64 + + +Library header(s): + + hwregs_a.h (GNU assembler port defs) + psxgpu.h + + +Todo list: + + * VSync() and DrawSync() functions lack alternate operating modes such as + getting number of vsyncs elapsed and waiting until a specified number of + vsyncs have passed. + + * VSync interrupt handler should be hooked using BIOS function + SetCustomExitFromException() like the official GPU library instead of + hooking an event handler, but said hook never seems to work. Perhaps + something in the kernel area needs to be patched/set or some event/IRQ + handler needs to be removed as such handlers can skip the custom + exception exit entirely. + + It also appears that all interrupt handling in the official libraries + are done through the GPU library. This would also explain why the + official documentation tells you to always call ResetGraph() at the + very beginning of your programs. + + * ClearOTag() function (non reverse version of ClearOTagR()) yet to be + implemented. + + * StoreImage() equivalent yet to be implemented. + + +Changelog: + + None thus far... 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 diff --git a/libpsn00b/psxgpu/setdefdispenv.c b/libpsn00b/psxgpu/setdefdispenv.c new file mode 100644 index 0000000..6dec49c --- /dev/null +++ b/libpsn00b/psxgpu/setdefdispenv.c @@ -0,0 +1,21 @@ +#include <psxgpu.h> + +DISPENV *SetDefDispEnv(DISPENV *disp, int x, int y, int w, int h) { + + disp->disp.x = x; + disp->disp.y = y; + disp->disp.w = w; + disp->disp.h = h; + + disp->screen.x = 0; + disp->screen.y = 0; + disp->screen.w = 0; + disp->screen.h = 0; + + disp->isinter = 0; + disp->isrgb24 = 0; + disp->reverse = 0; + + return disp; + +} diff --git a/libpsn00b/psxgpu/setdefdrawenv.c b/libpsn00b/psxgpu/setdefdrawenv.c new file mode 100644 index 0000000..bcd93ca --- /dev/null +++ b/libpsn00b/psxgpu/setdefdrawenv.c @@ -0,0 +1,26 @@ +#include <psxgpu.h> + +DRAWENV *SetDefDrawEnv(DRAWENV *draw, int x, int y, int w, int h) { + + draw->clip.x = x; + draw->clip.y = y; + draw->clip.w = w; + draw->clip.h = h; + + draw->ofs[0] = 0; + draw->ofs[1] = 0; + + draw->tw.x = 0; + draw->tw.y = 0; + draw->tw.w = 0; + draw->tw.h = 0; + + draw->tpage = 0x0a; + draw->dtd = 1; + draw->dfe = 0; + draw->isbg = 0; + setRGB0( draw, 0, 0, 0 ); + + return draw; + +} diff --git a/libpsn00b/psxgpu/setdispmask.s b/libpsn00b/psxgpu/setdispmask.s new file mode 100644 index 0000000..77ceb04 --- /dev/null +++ b/libpsn00b/psxgpu/setdispmask.s @@ -0,0 +1,19 @@ +.set noreorder + +.include "hwregs_a.h" + +.section .text + + +.global SetDispMask +.type SetDispMask, @function +SetDispMask: + lui $v1, 0x1f80 + andi $a0, 0x1 + lui $v0, 0x300 + ori $v0, 0x1 + sub $v0, $a0 + sw $v0, GP1($v1) + jr $ra + nop + diff --git a/libpsn00b/psxgpu/setvideomode.s b/libpsn00b/psxgpu/setvideomode.s new file mode 100644 index 0000000..718a4dd --- /dev/null +++ b/libpsn00b/psxgpu/setvideomode.s @@ -0,0 +1,50 @@ +.set noreorder + +.include "hwregs_a.h" + + +.section .text + +.global SetVideoMode +.type SetVideoMode, @function +SetVideoMode: + addiu $sp, -4 + sw $ra, 0($sp) + + jal ReadGPUstat + nop + + srl $a1, $v0, 17 + andi $a1, 0x1f + + srl $v1, $v0, 14 # Reverse flag + andi $v1, 1 + sll $v1, 6 + or $a1, $v1 + + srl $v1, $v0, 16 # Horizontal resolution 2 + andi $v1, 1 + sll $v1, 6 + or $a1, $v1 + + andi $a1, 0xf7 # Mask off PAL bit + + la $v0, _gpu_standard + beqz $a0, .set_done + sw $0 , 0($v0) + li $v1, 1 + sw $v1, 0($v0) + b .set_done + or $a1, 0x8 +.set_done: + + lui $v0, 0x800 # Apply new mode + or $a1, $v0 + lui $v0, IOBASE + sw $a1, GP1($v0) + + lw $ra, 0($sp) + addiu $sp, 4 + jr $ra + nop + diff --git a/libpsn00b/psxgpu/vsynccallback.s b/libpsn00b/psxgpu/vsynccallback.s new file mode 100644 index 0000000..1f96bbc --- /dev/null +++ b/libpsn00b/psxgpu/vsynccallback.s @@ -0,0 +1,25 @@ +.set noreorder + +.section .text + +.global VSyncCallback +.type VSyncCallback, @function +VSyncCallback: + addiu $sp, -8 + sw $ra, 0($sp) + + jal EnterCriticalSection + sw $a0, 4($sp) + + lw $a0, 4($sp) + la $v0, _vsync_callback_func + sw $a0, 0($v0) + + jal ExitCriticalSection + nop + + lw $ra, 0($sp) + addiu $sp, 8 + jr $ra + nop + |
