aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlameguy64 <lameguy64@gmail.com>2019-05-23 22:24:56 +0800
committerlameguy64 <lameguy64@gmail.com>2019-05-23 22:24:56 +0800
commit3ffebff2aad2ca438cf76db51fb3459c5639cd67 (patch)
treea234fc6158d3c09904c4c1fb2feee09afb479a4c
parente70cd149f41ea71f9ca9ee86c03d1e59005dad2a (diff)
downloadpsn00bsdk-3ffebff2aad2ca438cf76db51fb3459c5639cd67.tar.gz
Added BIOS Controller, BIOS CD, 2 new examples and custom exit handler in the works
-rw-r--r--README.md78
-rw-r--r--changelog.txt28
-rw-r--r--doc/dev notes.txt44
-rw-r--r--doc/libn00bref.odtbin33008 -> 36114 bytes
-rw-r--r--examples/cartrom/bios.inc67
-rw-r--r--examples/cartrom/cop0.inc11
-rw-r--r--examples/cartrom/makefile14
-rw-r--r--examples/cartrom/parse.inc113
-rw-r--r--examples/cartrom/readme.txt74
-rw-r--r--examples/cartrom/rom.ld11
-rw-r--r--examples/cartrom/rom.s399
-rw-r--r--examples/rgb24/bunpattern.timbin0 -> 921620 bytes
-rw-r--r--examples/rgb24/main.c52
-rw-r--r--examples/rgb24/makefile41
-rw-r--r--examples/rgb24/tim.s7
-rw-r--r--libpsn00b/include/psxapi.h16
-rw-r--r--libpsn00b/include/psxpad.h1
-rw-r--r--libpsn00b/libc/readme.txt4
-rw-r--r--libpsn00b/libc/start.s16
-rw-r--r--libpsn00b/psxapi/fs/_InitCd.s37
-rw-r--r--libpsn00b/psxapi/makefile2
-rw-r--r--libpsn00b/psxapi/pad/initpad.s10
-rw-r--r--libpsn00b/psxapi/pad/startpad.s10
-rw-r--r--libpsn00b/psxapi/pad/stoppad.s10
-rw-r--r--libpsn00b/psxapi/sys/initcard.s10
-rw-r--r--libpsn00b/psxapi/sys/initpad.s11
-rw-r--r--libpsn00b/psxapi/sys/returnfromexception.s10
-rw-r--r--libpsn00b/psxgpu/readme.txt15
-rw-r--r--libpsn00b/psxgpu/resetgraph.s81
29 files changed, 1102 insertions, 70 deletions
diff --git a/README.md b/README.md
index e059473..e7b2247 100644
--- a/README.md
+++ b/README.md
@@ -1,46 +1,88 @@
# PSn00bSDK
-PSn00bSDK is a 100% free and open source SDK for developing homebrew games and applications for the original Sony PlayStation. The SDK consists mainly of libraries and some tools for converting and building resources to be used on the console.
-
-While PSn00bSDK is currently a work in progress the project aims to develop an SDK that is as close to the official Sony SDK as possiblein in terms of supported hardware features which include GPU, GTE, SPU, CD, MDEC and controller/memory card peripherals and a library API written to follow the official SDK's API syntax. With extensive low-level technical documentation of the PSX readily available (such as nocash's PSX specs) there should be no excuse to not have full support of the aforementioned hardware features.
-
-The PSn00bSDK libraries are written mostly in MIPS assembly language with compiler generated code limited to small and moderately sized support functions for best possible performance and to keep the runtime library footprint as small as possible. Many of the library functions avoid using BIOS calls such as C string and memory manipulation functions and use pure assembly equivalents for improved performance for memory and string manipulation operations.
+PSn00bSDK is a 100% free and open source SDK for developing homebrew games
+and applications for the original Sony PlayStation. The SDK consists mainly
+of libraries and some tools for converting and building resources to be
+used on the console.
+
+While PSn00bSDK is currently a work in progress the project aims to develop
+an SDK that is as close to the official Sony SDK as possiblein in terms of
+supported hardware features which include GPU, GTE, SPU, CD, MDEC and
+controller/memory card peripherals and a library API written to follow the
+official SDK's API syntax. With extensive low-level technical documentation
+of the PSX readily available (such as nocash's PSX specs) there should be no
+excuse to not have full support of the aforementioned hardware features.
+
+The PSn00bSDK libraries are written mostly in MIPS assembly language with
+compiler generated code limited to small and moderately sized support
+functions for best possible performance and to keep the runtime library
+footprint as small as possible. Many of the library functions avoid using
+BIOS calls such as C string and memory manipulation functions and use pure
+assembly equivalents for improved performance for memory and string
+manipulation operations.
## Building the SDK
-For most users (particularly those who run Windows) it is recommended to just download a release package containing the GCC toolchain and libraries in binary form ready to be used.
+For most users (particularly those who run Windows) it is recommended to
+just download a release package containing the GCC toolchain and libraries
+in binary form ready to be used.
-If you wish to build the SDK yourself building PSn00bSDK requires a GNU GCC toolchain targeting mipsel-unknown-elf. For instructions on how to build the GCC toolchain please read toolchain.txt.
+If you wish to build the SDK yourself building PSn00bSDK requires a GNU
+GCC toolchain targeting mipsel-unknown-elf. For instructions on how to
+build the GCC toolchain please read toolchain.txt.
-To build the PSn00bSDK libraries simply enter the libpsn00b directory and run make. Make sure you have the path of the toolchain binaries in your PATH environment variable. If things go accordingly it should run through all library directories and produce library files.
+To build the PSn00bSDK libraries simply enter the libpsn00b directory and
+run make. Make sure you have the path of the toolchain binaries in your PATH
+environment variable. If things go accordingly it should run through all
+library directories and produce library files.
-To build the PSn00bSDK tools simply enter the tools directory and run make. You'll need tinyxml2 to satisfy the lzpack and smxlink tools.
+To build the PSn00bSDK tools simply enter the tools directory and run make.
+You'll need tinyxml2 to satisfy the lzpack and smxlink tools.
-To build the PSn00bSDK examples which also tests if your SDK setup works correctly simply enter the examples directory and run make. You may want to modify the sdk-common.mk file first and make sure the library paths are correct and that your PATH environment variable has the tools/bin directory in it as elf2x and lzpack are required for the examples to build correctly.
+To build the PSn00bSDK examples which also tests if your SDK setup works
+correctly simply enter the examples directory and run make. You may want
+to modify the sdk-common.mk file first and make sure the library paths are
+correct and that your PATH environment variable has the tools/bin directory
+in it as elf2x and lzpack are required for the examples to build correctly.
## Examples
-There are a few graphics examples and complete source code of n00bdemo included in the examples directory. More example programs may be added in future updates and contributions are welcome.
+There are a few graphics examples and complete source code of n00bdemo
+included in the examples directory. More example programs may be added in
+future updates and contributions are welcome.
## To-do
-* Support functions to get C++ classes working are yet to be implemented. glibc won't compile and likely depends on a Linux kernel that does not exist on the PS1. Newlib might be undesirable as it appears to be too bloated for PS1.
+* Support functions to get C++ classes working are yet to be implemented.
+ glibc won't compile (or its not included with GCC sources) and likely
+ depends on a Linux kernel that does not exist on the PS1. Newlib might
+ be undesirable as it appears to be too bloated for PS1. Just getting
+ classes to work would be enough.
-* psxspu needs to be expanded upon. Currently lacks support for reverb and many voice controls.
+* psxspu needs to be expanded upon. Currently lacks support for reverb
+ and many voice controls.
-* Controller library that polls the pads on every vblank and support for multitaps are yet to be made.
-
-* An 'IRQ handler for all' implementation through BIOS function SetCustomExitFromException() is yet to be implemented for better/more reliable interrupt handling. Details can be found in the readme of psxgpu.
+* An 'IRQ handler for all' implementation through BIOS function
+ SetCustomExitFromException() is yet to be implemented for better/more
+ reliable interrupt handling. UPDATE: SetCustomExitFromException() hook
+ is now working! See readme of psxgpu for details.
* CD-ROM library is yet to be made.
+* Better (and faster) sprintf() function.
+
## Usage terms
-PSn00bSDK falls under the terms and conditions of the Mozilla Public License. A quick summary of this license is that PSn00bSDK can be used freely in both free and open source projects and commercial closed source projects. But if modifications to the SDK were made as part of the development of such projects such changes must be contributed back in return.
+PSn00bSDK falls under the terms and conditions of the Mozilla Public
+License. A quick summary of this license is that PSn00bSDK can be used
+freely in both free and open source projects and commercial closed source
+projects. But if modifications to the SDK were made as part of the
+development of such projects such changes must be contributed back in
+return.
## Credits
@@ -50,4 +92,4 @@ Main developer:
Important references used:
* nocash's PlayStation specs document (http://problemkaputt.de/psx-spx.htm)
-* Tails92's PSXSDK project (bits and pieces used as reference).
+* Tails92's PSXSDK project (bits and pieces of it).
diff --git a/changelog.txt b/changelog.txt
new file mode 100644
index 0000000..1c27eaf
--- /dev/null
+++ b/changelog.txt
@@ -0,0 +1,28 @@
+PSn00bSDK changelog
+
+05-23-2019 by Lameguy64:
+
+* Added dev notes.txt file in docs that includes notes about the many
+ quirks discovered about the system throughout the development of this SDK.
+
+* Updated libn00bref.odf a little.
+
+* Added rgb24 example.
+
+* Made stack usage in ResetGraph() less wasteful.
+
+* VSync IRQ handling now done using a custom exit handler. Actual VSync
+ handling is yet to be moved to the custom exit handler though.
+
+* Made stack usage in start.s of libc a lot less wasteful.
+
+* Implemented controller support via BIOS functions (use _InitPad(),
+ _StartPad() and _StopPad()). BIOS memory card functions may also
+ work as well but its not tested yet.
+
+* Removed duplicate initpad.s and initcard.s functions in psxapi.
+
+* Added _InitCd() function to psxapi which is a safer version of _96_init()
+ as it preserves other DMA channel settings. Use BIOS file functions such
+ as open(), read() and close() with path names starting with cdrom:/ to
+ access files from CD after calling _InitCd().
diff --git a/doc/dev notes.txt b/doc/dev notes.txt
new file mode 100644
index 0000000..336e6d3
--- /dev/null
+++ b/doc/dev notes.txt
@@ -0,0 +1,44 @@
+These are some development notes I've put together that would be of great
+aid to those willing to contribute to the PSn00bSDK project. Many of these
+came from my own experience dealing with the PS1 at low-level when I ran
+into some unexplained quirks while some are from disassembly observations
+and clarification of existing documents. More entries will be added when
+I run into more previously undocumented quirks in the future.
+ - Lameguy64
+
+* When calling C functions (ie. BIOS functions) from assembly code you'll
+need to allocate N words on the stack first when calling a function that has
+N arguments (addiu $sp, -(4*N) where N = number of arguments of the function
+being called) even if the arguments are on registers a0 to a3 and the C
+functions don't always use the space allotted in stack.
+
+* A custom handler hooked using BIOS function B(19h)
+(SetCustomExitFromException) is only triggered when there's an interrupt
+that hasn't been acknowledged by previous IRQ handlers that have been
+executed prior. This is also the best point to acknowledge any interrupts
+without breaking compatibility with built-in BIOS features and is what the
+official SDK uses to handle interrupts.
+
+* It is not advisable to acknowledge interrupts in event handlers like in
+PSXSDK as it would break BIOS features that depend on interrupts. Clearing
+the VBlank IRQ in a event handler for example prevents the BIOS controller
+functions from working as it depends on the VBlank IRQ to determine when to
+query controllers. Acknowledge interrupts using a custom handler set by BIOS
+function B(19h) (SetCustomExitFromException).
+
+* When running in high resolution mode you must additionally wait for bit 31
+in GPUSTAT (1F801814h) to alternate on every frame (frame 0: wait until 0,
+frame 1: wait until 1, frame 2: wait until 0) before waiting for VSync
+otherwise the GPU will only draw the first field if you don't have drawing
+to displayed area enabled. Performing this check in a low resolution/non
+interlaced mode is harmless.
+
+* There's a hardware bug in the GPU FillVRAM command GP0(02h) where if you
+set the height to 512 pixels the primitive is executed with a height of 0 as
+the hardware does not appear to interpret the last bit of the height value.
+This is most apparent when putting a DRAWENV with the height of 512 pixels
+(for PAL for example) and background clearing is enabled.
+
+* In the official SDK, DMA IRQs appear to be enabled only when a callback
+function is set (ie. DrawSyncCallback() enables IRQ for DMA channel 2). DMA
+IRQs are only triggered on transfer completion. \ No newline at end of file
diff --git a/doc/libn00bref.odt b/doc/libn00bref.odt
index 6ed8285..99de092 100644
--- a/doc/libn00bref.odt
+++ b/doc/libn00bref.odt
Binary files differ
diff --git a/examples/cartrom/bios.inc b/examples/cartrom/bios.inc
new file mode 100644
index 0000000..1c0201d
--- /dev/null
+++ b/examples/cartrom/bios.inc
@@ -0,0 +1,67 @@
+printf:
+ addiu $t2, $0, 0xA0
+ jr $t2
+ addiu $t1, $0, 0x3F
+
+atoi:
+ addiu $t2, $0, 0xA0
+ jr $t2
+ addiu $t1, $0, 0x10
+
+toupper:
+ addiu $t2, $0, 0xA0
+ jr $t2
+ addiu $t1, $0, 0x25
+
+open:
+ addiu $t2, $0, 0xB0
+ jr $t2
+ addiu $t1, $0, 0x32
+
+read:
+ addiu $t2, $0, 0xB0
+ jr $t2
+ addiu $t1, $0, 0x34
+
+close:
+ addiu $t2, $0, 0xB0
+ jr $t2
+ addiu $t1, $0, 0x36
+
+_96_init:
+ addiu $t2, $0, 0xA0
+ jr $t2
+ addiu $t1, $0, 0x71
+
+LoadExe:
+ addiu $t2, $0, 0xA0
+ jr $t2
+ addiu $t1, $0, 0x42
+
+DoExec:
+ addiu $t2, $0, 0xA0
+ jr $t2
+ addiu $t1, $0, 0x43
+
+SetConf:
+ addiu $t2, $0, 0xA0
+ jr $t2
+ addiu $t1, $0, 0x9C
+
+SetDefaultExitFromException:
+ addiu $t2, $0, 0xB0
+ jr $t2
+ addiu $t1, $0, 0x18
+
+EnterCriticalSection:
+ addiu $a0, $0, 1
+ syscall 0
+ jr $ra
+ nop
+
+ExitCriticalSection:
+ addiu $a0, $0, 2
+ syscall 0
+ jr $ra
+ nop
+ \ No newline at end of file
diff --git a/examples/cartrom/cop0.inc b/examples/cartrom/cop0.inc
new file mode 100644
index 0000000..620fa44
--- /dev/null
+++ b/examples/cartrom/cop0.inc
@@ -0,0 +1,11 @@
+.set BPC, $3
+.set BDA, $5
+.set JUMPDEST, $6
+.set DCIC, $7
+.set BADVADDR, $8
+.set BDAM, $9
+.set BPCM, $11
+.set SR, $12
+.set CAUSE, $13
+.set EPC, $14
+.set PRID, $15
diff --git a/examples/cartrom/makefile b/examples/cartrom/makefile
new file mode 100644
index 0000000..2434685
--- /dev/null
+++ b/examples/cartrom/makefile
@@ -0,0 +1,14 @@
+PREFIX = mipsel-unknown-elf-
+
+CC = $(PREFIX)gcc
+AS = $(PREFIX)as
+LD = $(PREFIX)ld
+
+all: rom.o
+ $(LD) --oformat binary -T rom.ld -o cartrom.rom rom.o
+
+%.o: %.s
+ $(AS) -msoft-float --warn $< -o $@
+
+clean:
+ rm -f rom.o cartrom.rom \ No newline at end of file
diff --git a/examples/cartrom/parse.inc b/examples/cartrom/parse.inc
new file mode 100644
index 0000000..b1190f7
--- /dev/null
+++ b/examples/cartrom/parse.inc
@@ -0,0 +1,113 @@
+# Skips spaces and equal signs (used by CNF parser)
+skipspace:
+ # a0 - Input string
+ # Return: v0 - Address to first non-space character.
+ lbu $v1, 0($a0)
+ nop
+ beq $v1, ' ', .skip
+ nop
+ beq $v1, '=', .skip
+ nop
+ jr $ra
+ move $v0, $a0
+.skip:
+ b skipspace
+ addiu $a0, 1
+
+
+# Copies a string until a CR/LF or space is encountered
+getline:
+ # a0 - Output address
+ # a1 - String to copy from
+ lbu $v0, 0($a1)
+ addiu $a1, 1
+ beqz $v0, .end
+ nop
+ beq $v0, 0x0D, .end
+ nop
+ beq $v0, 0x0A, .end
+ nop
+ beq $v0, ' ', .end
+ nop
+ sb $v0, 0($a0)
+ b getline
+ addiu $a0, 1
+.end:
+ jr $ra
+ sb $0, 0($a0)
+
+
+# strcasestr implementation
+strcasestr:
+ # a0 - String to search
+ # a1 - String to find
+ addiu $sp, -24
+ sw $ra, 0($sp)
+ sw $s0, 4($sp)
+ sw $s1, 8($sp)
+ sw $a1, 16($sp)
+
+.scan_start:
+
+ sw $a0, 12($sp)
+
+.comp_loop:
+
+ lbu $s0, 0($a0) # Load character from A and B
+ lbu $s1, 0($a1)
+
+ beqz $s0, .end_strcasestr
+ nop
+ beqz $s1, .found
+ nop
+
+ sw $a0, 20($sp) # Save a0 parameter
+
+ jal toupper # tolower character A
+ move $a0, $s0
+ move $s0, $v0
+
+ jal toupper # tolower character B
+ move $a0, $s1
+ move $s1, $v0
+
+ lw $a0, 20($sp) # Restore a0 parameter
+
+ addiu $a1, 1
+ addiu $a0, 1
+
+ beq $s0, $s1, .comp_loop # If value matches continue compare
+ nop
+
+.end_strcasestr:
+
+ lw $a0, 12($sp) # Rescan from next character of string A
+ lw $a1, 16($sp)
+ addiu $a0, 1
+
+ lbu $v0, 0($a0)
+ nop
+ beqz $v0, .not_found # If terminator is reached, string is not found
+ nop
+
+ b .scan_start
+ nop
+
+.not_found:
+
+ b .quit
+ move $v0, $0
+
+.found:
+
+ lw $v0, 12($sp) # Return address of string match
+
+.quit:
+
+ lw $ra, 0($sp)
+ lw $s0, 4($sp)
+ lw $s1, 8($sp)
+ jr $ra
+ addiu $sp, 24
+
+
diff --git a/examples/cartrom/readme.txt b/examples/cartrom/readme.txt
new file mode 100644
index 0000000..8d11a7f
--- /dev/null
+++ b/examples/cartrom/readme.txt
@@ -0,0 +1,74 @@
+LibPSn00b Example Programs
+Part of the PSn00bSDK Poject
+
+TurboBoot Example by Lameguy64
+
+
+Explanation:
+
+This example demonstrates how to create a ROM program to be used on a cheat
+cartridge such as an Action Replay or Xplorer using GNU assembler. The program
+stored in ROM is executed pretty much instantly on power-on.
+
+The PS1 BIOS can execute code from a ROM chip connected to the expansion port
+(or Parallel I/O port) such as a cheat cartridge provided the valid headers
+are present. However, the boot vectors are somewhat limited as it only
+provides a preboot vector and a postboot vector.
+
+The preboot vector is executed at the earliest point of the BIOS start-up
+sequence which means the RAM is almost completely blank and you can't execute
+PS-EXEs from this point whearas the postboot vector is only executed between
+the PS logo and game execution. To get around this limitation, the preboot
+vector is used to execute code that places a breakpoint to a desired point
+in memory and returns execution to the BIOS. This will effectively intercept
+execution once it reaches the breakpoint allowing to run code from ROM with
+an initialized kernel allowing for bootstrapping PS-EXEs from ROM, CD or
+from a comms interface such as serial.
+
+The Xplorer and later Pro Action Replay cheat devices use this so called
+'midboot' trick in their firmwares.
+
+In this TurboBoot example, the ROM program attempts to boot a PS-EXE from
+CD using BIOS CD-ROM and file functions. It will also parse through the
+SYSTEM.CNF to retrieve the file name of executable as well as some boot
+parameters such as stack addres and number of TCBs and EvCBs. The ROM
+program can fallback to attempting to load a PS-EXE named PSX.EXE if the
+SYSTEM.CNF file does not exist like in the official BIOS.
+
+This example can also be used as a turbo boot utility as it boots straight
+to the game, skipping the start-up animation altogether. It cannot be used
+as a way to bypass the authentication check of an unmodified console however
+(though it would help with bypassing the license data check on older Japanese
+consoles) as the CD-ROM would only read data discs correctly IF the elusive
+wobble groove containing the SCE string of the disc is present or when a
+modchip is installed. It is possible to circumvent this by issuing special
+'CD Unlock' commands (see nocash's psx-spx document) to the CD-ROM controller
+which would effectively turn this into a chipless modchip solution that plugs
+to the expansion port. However, the unlock commands only works on US and EU
+consoles.
+
+It is possible and pretty trivial to boot a PS-EXE straight from ROM by
+simply copying the program text from ROM to its desired location in RAM and
+transferring execution to it. Such an example may be created in the future.
+
+This ROM program example had to be written entirely in assembly as C cannot
+be used to write a ROM program even though it should be possible with some
+assembly code to take care of the bootstrapping. GNU ld would complain about
+'relocation truncation of R_MIPS_GPREL16' when you map program text to ROM
+starting at 0x1f000000 (EXP ROM segment) and program data and bss sections
+to RAM. Unknown how to get around this as all methods I've tried so far
+either don't work or it just produces a massive binary file.
+
+
+Building:
+
+To build this example, simply run make and a file named cartrom.rom should
+be created. Run the ROM in no$psx (make sure a ISO image has been opened
+first) or burn it to an Xplorer/PAR EEPROM (I recommend modding a PAR with
+a DIP32 socket if you wish to program the chip externally which in many
+cases would be easier).
+
+
+Changelog:
+
+May 23, 2019 - Initial version.
diff --git a/examples/cartrom/rom.ld b/examples/cartrom/rom.ld
new file mode 100644
index 0000000..f3f9cd3
--- /dev/null
+++ b/examples/cartrom/rom.ld
@@ -0,0 +1,11 @@
+MEMORY {
+ ROM : ORIGIN = 0x1f000000, LENGTH = 256K
+}
+
+ENTRY (entry)
+
+SECTIONS {
+ .text :{
+ *(.text)
+ } >ROM
+}
diff --git a/examples/cartrom/rom.s b/examples/cartrom/rom.s
new file mode 100644
index 0000000..14c1167
--- /dev/null
+++ b/examples/cartrom/rom.s
@@ -0,0 +1,399 @@
+# LibPSn00b Example Programs
+# Part of the PSn00bSDk project
+#
+# TurboBoot Example by Lameguy64
+#
+
+
+# Uncomment either PAR or XPLORER depending on the cartridge
+# you're going to use (makes disabling turbo boot via switch to work)
+
+#.set PAR, 0
+#.set XPLORER, 1
+
+
+.set noreorder
+
+.include "cop0.inc" # Contains definitions for cop0 registers
+
+.set SP_base, 0x801ffff0
+.set BREAK_ADDR, 0xa0000040 # cop0 breakpoint vector address
+
+
+.set RAM_buff, 2048
+.set RAM_handle, 2052
+.set RAM_tcb, 2056
+.set RAM_evcb, 2060
+.set RAM_stack, 2064
+.set RAM_psexe, 2068
+
+
+.set EXE_pc0, 0 # PS-EXE header offsets
+.set EXE_gp0, 4
+.set EXE_taddr, 8
+.set EXE_tsize, 12
+.set EXE_daddr, 16
+.set EXE_dsize, 20
+.set EXE_baddr, 24
+.set EXE_bsize, 28
+.set EXE_spaddr, 32
+.set EXE_sp_size, 36
+.set EXE_sp, 40
+.set EXE_fp, 44
+.set EXE_gp, 48
+.set EXE_ret, 52
+.set EXE_base, 56
+.set EXE_datapos, 60
+
+
+.section .text
+
+
+# ROM header
+#
+# The Licensed by... strings are essential otherwise the BIOS will not
+# execute the boot vectors. Always make sure the tty message fields (string
+# after Licensed by) must be no more than 80 bytes long and must have a null
+# terminating byte.
+#
+# Postboot vector isn't particularly practical as its only executed in between
+# the PS boot logo and the point where game execution occurs.
+#
+header:
+ # Postboot vector
+ .word 0
+ .ascii "Licensed by Sony Computer Entertainment Inc."
+ .ascii "Not officially licensed or endorsed by Sony Computer Entertainment Inc."
+
+ .balign 0x80 # This keeps things in the header aligned
+
+ # Preboot vector
+ .word preboot
+ .ascii "Licensed by Sony Computer Entertainment Inc."
+ .ascii "Cart ROM example for PSn00bSDK https://github.com/lameguy64/psn00bsdk"
+
+ .balign 0x80 # This keeps things in the header aligned
+
+
+# Preboot vector
+#
+# All it does is it initializes a breakpoint vector at 0x40
+# and sets a cop0 breakpoint at 0x80030000 to perform a midboot
+# exploit as preboot doesn't have the kernel area initialized.
+#
+preboot:
+
+ li $v0, 1
+
+.ifdef XPLORER
+ lui $a0, 0x1f06 # Read switch status for Xplorer
+ lbu $v0, 0($a0)
+.endif
+
+.ifdef PAR
+ lui $a0, 0x1f02 # Read switch status for PAR/GS devices
+ lbu $v0, 0x18($a0)
+.endif
+
+ nop
+ andi $v0, 0x1
+ beqz $v0, .no_rom # If switch is off don't install hook
+ nop # and effectively disables the cartridge
+
+ li $v0, BREAK_ADDR # Patch a jump at cop0 breakpoint vector
+
+ li $a0, 0x3c1a1f00 # lui $k0, $1f00
+ sw $a0, 0($v0)
+ la $a1, entry # ori $k0, < address to code entrypoint >
+ andi $a1, 0xffff
+ lui $a0, 0x375a
+ or $a0, $a1
+ sw $a0, 4($v0)
+ li $a0, 0x03400008 # jr $k0
+ sw $a0, 8($v0)
+ sw $0 , 12($v0) # nop
+
+ lui $v0, 0xffff # Set BPCM and BDAM masks
+ ori $v0, 0xffff
+ mtc0 $v0, BDAM
+ mtc0 $v0, BPCM
+
+
+ li $v0, 0x80030000 # Set break on PC and data-write address
+
+ mtc0 $v0, BDA # BPC break is for compatibility with no$psx
+ mtc0 $v0, BPC # as it does not emulate break on BDA
+
+ lui $v0, 0xeb80 # Enable break on data-write and and break
+ mtc0 $v0, DCIC # on PC to DCIC control register
+
+.no_rom:
+
+ jr $ra # Return to BIOS
+ nop
+
+
+# Actual ROM entrypoint
+.global entry
+entry:
+
+ mtc0 $0 , DCIC # Clear DCIC register
+
+ la $sp, SP_base # Set stack base
+ la $gp, 0x8000c000 # Set GP address as RAM base addr in this case
+
+ jal SetDefaultExitFromException # Set default exit handler just in case
+ nop
+ jal ExitCriticalSection # Exit out of critical section (brings back interrupts)
+ nop
+
+ # Beyond this point, the PS1 is in full control to the ROM
+
+ la $a0, m_banner # Print out program banner
+ jal printf
+ addiu $sp, -4
+ addiu $sp, 4
+
+ la $a0, m_cdinit
+ jal printf
+ addiu $sp, -4
+ addiu $sp, 4
+
+ jal _96_init # Initialize the CD
+ nop
+
+ la $a0, m_ok # Print OK message if init didn't crash
+ jal printf
+ addiu $sp, -4
+ addiu $sp, 4
+
+ la $a0, m_readfile
+ la $a1, s_systemcnf
+ jal printf
+ addiu $sp, -8
+ addiu $sp, 8
+
+ la $a0, s_systemcnf # Attempt to open the SYSTEM.CNF file on CD
+ li $a1, 1
+ jal open
+ addiu $sp, -8
+ addiu $sp, 8
+
+ bltz $v0, .no_systemcnf # Fallback to loading PSX.EXE if not found
+ nop
+
+ sw $v0, RAM_handle($gp) # Save file handle
+
+ move $a0, $v0 # Read file contents of SYSTEM.CNF
+ move $a1, $gp
+ li $a2, 0x0800
+ jal read
+ addiu $sp, -12
+ addiu $sp, 12
+
+ lw $a0, RAM_handle($gp) # Close file
+ jal close
+ addiu $sp, -4
+ addiu $sp, 4
+
+ la $a0, m_ok # Output ok message
+ jal printf
+ addiu $sp, -4
+ addiu $sp, 4
+
+ # Parse CNF file
+
+ la $a0, m_parsecnf
+ jal printf
+ nop
+
+ la $a1, s_tcb # Get TCB number
+ jal strcasestr
+ move $a0, $gp
+ jal skipspace # Skip spaces
+ addiu $a0, $v0, 3
+ addiu $a0, $v0, -2 # Step two charactters back and inject '0x'
+ li $v0, '0'
+ sb $v0, 0($a0)
+ li $v0, 'x'
+ sb $v0, 1($a0)
+ jal atoi
+ addiu $sp, -4
+ addiu $sp, 4
+ move $s1, $v0
+
+ la $a1, s_evcb # Get EVCB number
+ jal strcasestr
+ move $a0, $gp
+ jal skipspace
+ addiu $a0, $v0, 5
+ addiu $a0, $v0, -2
+ li $v0, '0'
+ sb $v0, 0($a0)
+ li $v0, 'x'
+ sb $v0, 1($a0)
+ jal atoi
+ addiu $sp, -4
+ addiu $sp, 4
+ move $s0, $v0
+
+ la $a1, s_stack # Get STACK address
+ jal strcasestr
+ move $a0, $gp
+ jal skipspace
+ addiu $a0, $v0, 5
+ addiu $a0, $v0, -2
+ li $v0, '0'
+ sb $v0, 0($a0)
+ li $v0, 'x'
+ sb $v0, 1($a0)
+ jal atoi
+ addiu $sp, -4
+ addiu $sp, 4
+ move $s2, $v0
+
+ la $a1, s_boot # Get the PS-EXE file name
+ jal strcasestr
+ move $a0, $gp
+
+ jal skipspace # Skip spaces
+ addiu $a0, $v0, 4
+
+ addiu $a0, $gp, RAM_psexe # Extract the line
+ jal getline
+ move $a1, $v0
+
+ la $a0, m_ok # Print successful parsing
+ jal printf
+ addiu $sp, -4
+ addiu $sp, 4
+
+ la $a0, m_readfile
+ addiu $a1, $gp, RAM_psexe
+ jal printf
+ addiu $sp, -8
+ addiu $sp, 8
+
+ b .do_load # Proceed loading PS-EXE
+ addiu $a0, $gp, RAM_psexe
+
+.no_systemcnf: # Load fallback
+
+ la $a0, m_notfound
+ jal printf
+ addiu $sp, -4
+ addiu $sp, 4
+
+ la $a0, m_fallback
+ jal printf
+ addiu $sp, -4
+ addiu $sp, 4
+
+ li $s0, 0x10 # Default EvCBs and TCBs
+ li $s1, 0x04
+ li $s2, SP_base # Default stack
+ la $a0, s_psxexe # Attempt loading PSX.EXE
+
+.do_load:
+
+ jal LoadExe # Load PS-EXE
+ move $a1, $gp
+
+ beqz $v0, load_fail
+ nop
+
+ la $a0, m_ok
+ jal printf
+ addiu $sp, -4
+ addiu $sp, 4
+
+ sw $s2, EXE_sp($gp) # Patch the header
+ sw $s2, EXE_spaddr($gp)
+
+ la $a0, m_boot
+ jal printf
+ addiu $sp, -4
+ addiu $sp, 4
+
+ jal EnterCriticalSection # Disable interrupt handling
+ nop
+
+ move $a0, $s0 # Set configuration (EvCBs and TCBs)
+ move $a1, $s1
+ move $a2, $s2
+ jal SetConf
+ addiu $sp, -12
+ addiu $sp, 12
+
+ move $a0, $gp # Transfer execution
+ move $a1, $0
+ move $a2, $0
+ jal DoExec
+ addiu $sp, -12
+ addiu $sp, 12
+
+
+load_fail: # Fail state
+ la $a0, m_loadfail
+ jal printf
+ nop
+.fail_loop:
+ b .fail_loop
+ nop
+
+
+.include "parse.inc"
+.include "bios.inc"
+
+
+# Strings
+
+s_boot:
+ .asciz "BOOT"
+ .balign 4
+s_tcb:
+ .asciz "TCB"
+ .balign 4
+s_evcb:
+ .asciz "EVENT"
+ .balign 4
+s_stack:
+ .asciz "STACK"
+ .balign 4
+s_systemcnf:
+ .asciz "cdrom:SYSTEM.CNF;1"
+ .balign 4
+s_psxexe:
+ .asciz "cdrom:PSX.EXE;1"
+ .balign 4
+
+
+# Message strings
+
+m_banner:
+ .asciz "\nCARTROM Bootstrap Example by Lameguy64\nPart of the PSn00bSDK Project\n\n"
+ .balign 4
+m_cdinit:
+ .asciz "Initializing CD-ROM (BIOS)... "
+ .balign 4
+m_readfile:
+ .asciz "Attempting to read %s... "
+ .balign 4
+m_parsecnf:
+ .asciz "Parsing CNF file... "
+ .balign 4
+m_fallback:
+ .asciz "Falling back to loading PSX.EXE... "
+ .balign 4
+m_notfound:
+ .asciiz "Not found.\n"
+ .balign 4
+m_ok:
+ .asciz "Ok.\n"
+ .balign 4
+m_boot:
+ .asciz "Boot!\n"
+ .balign 4
+m_loadfail:
+ .asciz "Failed to load PS-EXE file.\n"
+ .balign 4
diff --git a/examples/rgb24/bunpattern.tim b/examples/rgb24/bunpattern.tim
new file mode 100644
index 0000000..f233453
--- /dev/null
+++ b/examples/rgb24/bunpattern.tim
Binary files differ
diff --git a/examples/rgb24/main.c b/examples/rgb24/main.c
new file mode 100644
index 0000000..178ece2
--- /dev/null
+++ b/examples/rgb24/main.c
@@ -0,0 +1,52 @@
+/* LibPSn00b Example Programs
+ * Part of the PSn00bSDK Project
+ *
+ * RGB24 Example by Lameguy64
+ *
+ *
+ * This example demonstrates the 24-bit color mode of the PS1. This mode is
+ * not practical for gameplay as the GPU can only draw graphics primitives
+ * in 16-bit color depth so this feature would normally be used only for
+ * fullscreen graphic illustrations or FMV sequences.
+ *
+ *
+ * Changelog:
+ *
+ * 05-03-2019 - Initial version.
+ *
+ */
+
+#include <stdio.h>
+#include <psxgte.h>
+#include <psxgpu.h>
+
+// So data from tim.s can be accessed
+extern unsigned int tim_image[];
+
+int main() {
+
+ DISPENV disp;
+ TIM_IMAGE tim;
+
+ // Reset GPU
+ ResetGraph(0);
+
+ // Setup 640x480 24-bit video mode
+ SetDefDispEnv(&disp, 0, 0, 640, 480);
+ disp.isrgb24 = 1;
+ disp.isinter = 1;
+
+ // Apply and enable display
+ PutDispEnv(&disp);
+ SetDispMask(1);
+
+ // Upload image to VRAM
+ GetTimInfo(tim_image, &tim);
+ LoadImage(tim.prect, tim.paddr);
+ DrawSync();
+
+ while(1) {
+ }
+
+ return 0;
+} \ No newline at end of file
diff --git a/examples/rgb24/makefile b/examples/rgb24/makefile
new file mode 100644
index 0000000..ada9fbb
--- /dev/null
+++ b/examples/rgb24/makefile
@@ -0,0 +1,41 @@
+include ../sdk-common.mk
+
+TARGET = rgb24.elf
+
+CFILES = $(notdir $(wildcard *.c))
+CPPFILES = $(notdir $(wildcard *.cpp))
+AFILES = $(notdir $(wildcard *.s))
+
+OFILES = $(addprefix build/,$(CFILES:.c=.o) $(CPPFILES:.cpp=.o) $(AFILES:.s=.o))
+
+INCLUDE +=
+LIBDIRS +=
+
+LIBS = -lc -lpsxgpu -lpsxapi -lgcc
+
+CFLAGS = -g -O2 -fno-builtin -fdata-sections -ffunction-sections
+CPPFLAGS = $(CFLAGS) -fno-exceptions
+AFLAGS = -g -msoft-float
+LDFLAGS = -g -Ttext=0x80010000 -gc-sections
+
+CC = $(PREFIX)gcc
+CXX = $(PREFIX)g++
+AS = $(PREFIX)as
+LD = $(PREFIX)ld
+
+all: $(OFILES)
+ $(LD) $(LDFLAGS) $(LIBDIRS) $(OFILES) $(LIBS) -o $(TARGET)
+ elf2x -q $(TARGET)
+
+build/%.o: %.c
+ @mkdir -p $(dir $@)
+ $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
+
+build/%.o: %.s
+ @mkdir -p $(dir $@)
+ $(CC) $(AFLAGS) $(INCLUDE) -c $< -o $@
+
+build/%.o: %.tim
+
+clean:
+ rm -rf build $(TARGET) $(TARGET:.elf=.exe)
diff --git a/examples/rgb24/tim.s b/examples/rgb24/tim.s
new file mode 100644
index 0000000..a4432d9
--- /dev/null
+++ b/examples/rgb24/tim.s
@@ -0,0 +1,7 @@
+.section .data
+
+.global tim_image
+.type tim_image, @object
+tim_image:
+ .incbin "bunpattern.tim"
+ \ No newline at end of file
diff --git a/libpsn00b/include/psxapi.h b/libpsn00b/include/psxapi.h
index 54b87ee..9cfb6cb 100644
--- a/libpsn00b/include/psxapi.h
+++ b/libpsn00b/include/psxapi.h
@@ -84,14 +84,20 @@ extern int chdir(const char *path);
int AddDev(DCB *dcb);
int DelDev(const char *name);
-extern void ListDev();
+extern void ListDev(void);
-extern void EnterCriticalSection();
-extern void ExitCriticalSection();
+extern void EnterCriticalSection(void);
+extern void ExitCriticalSection(void);
-extern void _96_init();
-extern void _96_remove();
+extern void _InitCd(void);
+extern void _96_init(void);
+extern void _96_remove(void);
extern void ChangeClearPAD(int mode);
+// BIOS pad functions
+void _InitPad(char *buff1, int len1, char *buff2, int len2);
+void _StartPad(void);
+void _StopPad(void);
+
#endif
diff --git a/libpsn00b/include/psxpad.h b/libpsn00b/include/psxpad.h
index 09d17b1..5478596 100644
--- a/libpsn00b/include/psxpad.h
+++ b/libpsn00b/include/psxpad.h
@@ -104,5 +104,4 @@ typedef struct {
unsigned short gun_y; // Gun Y position in scanlines
} GCONTYPE;
-
#endif \ No newline at end of file
diff --git a/libpsn00b/libc/readme.txt b/libpsn00b/libc/readme.txt
index d7abf0a..064a353 100644
--- a/libpsn00b/libc/readme.txt
+++ b/libpsn00b/libc/readme.txt
@@ -45,4 +45,6 @@ Todo list:
Changelog:
- None thus far...
+ 05-23-2019 by Lameguy64:
+
+ * Made stack usage a lot less wastefull in _start entrypoint.
diff --git a/libpsn00b/libc/start.s b/libpsn00b/libc/start.s
index c9b529b..d08a2c7 100644
--- a/libpsn00b/libc/start.s
+++ b/libpsn00b/libc/start.s
@@ -1,5 +1,5 @@
# Start function!
-# This is essentially the entrypoint of the PS-EXE
+# This is essentially the entry point of the PS-EXE
.set noreorder
@@ -8,11 +8,10 @@
.global _start
.type _start, @function
_start:
-
- addiu $sp, -32
- sw $ra, 28($sp)
+ addiu $sp, -4
+ sw $ra, 0($sp)
- la $gp, _gp # Very important to set!
+ la $gp, _gp # Very important!
la $a0, .bss # What are the CORRECT symbols for BSS start and end?
la $a1, _end
@@ -30,10 +29,11 @@ _start:
move $a1, $0
jal main
- nop
+ addiu $sp, -8
+ addiu $sp, 8
- lw $ra, 28($sp)
- addiu $sp, 32
+ lw $ra, 0($sp) # Return
+ addiu $sp, 4
jr $ra
nop
\ No newline at end of file
diff --git a/libpsn00b/psxapi/fs/_InitCd.s b/libpsn00b/psxapi/fs/_InitCd.s
new file mode 100644
index 0000000..decf2bd
--- /dev/null
+++ b/libpsn00b/psxapi/fs/_InitCd.s
@@ -0,0 +1,37 @@
+.section .text
+.set noreorder
+
+.include "hwregs_a.h"
+
+.global _InitCd
+.type _InitCd, @function
+_InitCd:
+ addiu $sp, -8
+ sw $ra, 0($sp)
+
+ lui $a0, IOBASE # Load IOBASE value
+
+ lw $v0, DPCR($a0) # Get current DMA settings
+ nop
+ sw $v0, 4($sp) # Save to stack
+
+ jal _96_init # Init CD subsystem
+ nop
+
+ lui $a0, IOBASE # Load IOBASE again
+
+ lw $v0, 4($sp) # Get old DMA control settings
+ lw $v1, DPCR($a0) # Get DMA settings by _96_init()
+
+ lui $a1, 0xffff # Mask out settings for CD DMA
+ ori $a1, 0x0f00
+ and $v0, $a1
+
+ or $v0, $v1 # Merge and set new DMA settings
+ sw $v0, DPCR($a0)
+
+ lw $ra, 0($sp)
+ addiu $sp, 8
+ jr $ra
+ nop
+ \ No newline at end of file
diff --git a/libpsn00b/psxapi/makefile b/libpsn00b/psxapi/makefile
index 30c1522..e97451c 100644
--- a/libpsn00b/psxapi/makefile
+++ b/libpsn00b/psxapi/makefile
@@ -6,7 +6,7 @@ PREFIX = mipsel-unknown-elf-
TARGET = ../libpsxapi.a
-SOURCES = stdio fs sys
+SOURCES = stdio fs sys pad
AFILES = $(foreach dir,$(SOURCES),$(wildcard $(dir)/*.s))
OFILES = $(addprefix build/,$(AFILES:.s=.o))
diff --git a/libpsn00b/psxapi/pad/initpad.s b/libpsn00b/psxapi/pad/initpad.s
new file mode 100644
index 0000000..d983d75
--- /dev/null
+++ b/libpsn00b/psxapi/pad/initpad.s
@@ -0,0 +1,10 @@
+.set noreorder
+.section .text
+
+.global _InitPad
+.type _InitPad, @function
+_InitPad:
+ addiu $t2, $0 , 0xb0
+ jr $t2
+ addiu $t1, $0 , 0x12
+ \ No newline at end of file
diff --git a/libpsn00b/psxapi/pad/startpad.s b/libpsn00b/psxapi/pad/startpad.s
new file mode 100644
index 0000000..c8e7da8
--- /dev/null
+++ b/libpsn00b/psxapi/pad/startpad.s
@@ -0,0 +1,10 @@
+.set noreorder
+.section .text
+
+.global _StartPad
+.type _StartPad, @function
+_StartPad:
+ addiu $t2, $0 , 0xb0
+ jr $t2
+ addiu $t1, $0 , 0x13
+ \ No newline at end of file
diff --git a/libpsn00b/psxapi/pad/stoppad.s b/libpsn00b/psxapi/pad/stoppad.s
new file mode 100644
index 0000000..4465e5a
--- /dev/null
+++ b/libpsn00b/psxapi/pad/stoppad.s
@@ -0,0 +1,10 @@
+.set noreorder
+.section .text
+
+.global _StopPad
+.type _StopPad, @function
+_StopPad:
+ addiu $t2, $0 , 0xb0
+ jr $t2
+ addiu $t1, $0 , 0x14
+ \ No newline at end of file
diff --git a/libpsn00b/psxapi/sys/initcard.s b/libpsn00b/psxapi/sys/initcard.s
deleted file mode 100644
index e589592..0000000
--- a/libpsn00b/psxapi/sys/initcard.s
+++ /dev/null
@@ -1,10 +0,0 @@
-.set noreorder
-.section .text
-
-.global InitCard
-.type InitCard, @function
-InitCard:
- addiu $t2, $0, 0xb0
- jr $t2
- addiu $t1, $0, 0x4a
- \ No newline at end of file
diff --git a/libpsn00b/psxapi/sys/initpad.s b/libpsn00b/psxapi/sys/initpad.s
deleted file mode 100644
index b0f1b6f..0000000
--- a/libpsn00b/psxapi/sys/initpad.s
+++ /dev/null
@@ -1,11 +0,0 @@
-.set noreorder
-.section .text
-
-.include "hwregs_a.h"
-
-.global InitPad
-.type InitPad, @function
-InitPad:
- addiu $t2, $0, 0xb0
- jr $t2
- addiu $t1, $0, 0x12
diff --git a/libpsn00b/psxapi/sys/returnfromexception.s b/libpsn00b/psxapi/sys/returnfromexception.s
new file mode 100644
index 0000000..ec67b64
--- /dev/null
+++ b/libpsn00b/psxapi/sys/returnfromexception.s
@@ -0,0 +1,10 @@
+.set noreorder
+.section .text
+
+.global ReturnFromException
+.type ReturnFromException, @function
+ReturnFromException:
+ addiu $t2, $0, 0xb0
+ jr $t2
+ addiu $t1, $0, 0x17
+ \ No newline at end of file
diff --git a/libpsn00b/psxgpu/readme.txt b/libpsn00b/psxgpu/readme.txt
index 55fcb68..0d44e72 100644
--- a/libpsn00b/psxgpu/readme.txt
+++ b/libpsn00b/psxgpu/readme.txt
@@ -27,7 +27,7 @@ Todo list:
getting number of vsyncs elapsed and waiting until a specified number of
vsyncs have passed.
- * VSync interrupt handler should be hooked using BIOS function
+ * (old) 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
@@ -47,4 +47,15 @@ Todo list:
Changelog:
- None thus far...
+ 05-23-2019 by Lameguy64:
+
+ * Got custom exit handler set using SetCustomExitFromException() (BIOS
+ function B(19h)) working. Currently used to acknowledge VSync IRQ but
+ actual VSync handling is still done with events and needs to be
+ transferred to the custom exit handler. At least it lets BIOS
+ controller functions to work now. See doc/dev notes.txt for details
+ on how this handler behaves.
+
+ * Made stack usage a lot less wasteful in ResetGraph() (you only need
+ to allocate N words on stack based on N arguments of the function
+ being called.
diff --git a/libpsn00b/psxgpu/resetgraph.s b/libpsn00b/psxgpu/resetgraph.s
index bc30d3b..189b1ad 100644
--- a/libpsn00b/psxgpu/resetgraph.s
+++ b/libpsn00b/psxgpu/resetgraph.s
@@ -9,9 +9,9 @@
.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)
+ addiu $sp, -8 # C style stack allocation (required if
+ sw $ra, 0($sp) # you call BIOS functions from asm)
+ sw $a0, 4($sp)
la $v0, _hooks_installed # Skip installing hooks if this function
lbu $v0, 0($v0) # has already been called before once
@@ -20,8 +20,8 @@ ResetGraph:
nop
# Temporary, may help improve compatibility?
- jal SetDefaultExitFromException
- nop
+ #jal SetDefaultExitFromException
+ #nop
jal ChangeClearPAD # Remove pad handler left by the BIOS
move $a0, $0
@@ -52,13 +52,16 @@ ResetGraph:
jal OpenEvent # Open a VSync event handler
# (PSXSDK style vsync handler)
- nop
+ addiu $sp, -16
+ addiu $sp, 16
la $v1, _vsync_event_desc # Save event descriptor
sw $v0, 0($v1)
- jal EnableEvent # Enable the opened event
move $a0, $v0
+ jal EnableEvent # Enable the opened event
+ addiu $sp, -4
+ addiu $sp, 4
la $v0, _hooks_installed # Set installed flag
li $v1, 0x1
@@ -70,6 +73,11 @@ ResetGraph:
la $v0, _vsync_callback_func # Clear callback function
sw $0 , 0($v0)
+ la $a0, _custom_exit
+ jal SetCustomExitFromException
+ addiu $sp, -4
+ addiu $sp, 4
+
jal ExitCriticalSection # Re-enable interrupts
nop
@@ -87,7 +95,7 @@ ResetGraph:
sw $v0, 0($v1)
.not_pal:
- lw $a0, 24($sp) # Get argument value
+ lw $a0, 4($sp) # Get argument value
lui $a3, 0x1f80 # Set base I/O again (likely destroyed
# by previous calls)
@@ -118,10 +126,10 @@ ResetGraph:
.init_done:
- lw $ra, 28($sp)
- lw $a0, 24($sp) # Return
+ lw $ra, 0($sp)
+ lw $a0, 4($sp) # Return
jr $ra
- addiu $sp, 0x20
+ addiu $sp, 8
.global _vsync_func # VSync event handler, executed on
@@ -142,8 +150,9 @@ _vsync_func:
andi $v0, $v1, 0x1
beqz $v0, .exit
nop
- xori $v1, $v1, 0x1 # Acknowledge the IRQ
- sw $v1, ISTAT($at)
+
+ #xori $v1, $v1, 0x1 # Acknowledge the IRQ
+ #sw $v1, ISTAT($at) # Commented out as it breaks BIOS pads
la $v1, _vsync_counter # Increment VSync counter
lw $v0, 0($v1)
@@ -171,6 +180,32 @@ _vsync_func:
nop
+.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
+ nop
+
+ lw $v1, ISTAT($at)
+ nop
+ andi $v0, $v1, 0x1
+ beqz $v0, .exit_2
+ nop
+
+ xori $v1, $v1, 0x1 # Acknowledge the IRQ
+ sw $v1, ISTAT($at)
+
+.exit_2:
+
+ j ReturnFromException
+ nop
+
+
.global VSync # VSync function
.type VSync, @function
VSync:
@@ -211,6 +246,26 @@ VSync:
library_credits:
.string "psxgpu programs by Lameguy64"
+
+.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:
+ .fill 4
+
.type _vsync_counter, @object
_vsync_counter:
.word 0