aboutsummaryrefslogtreecommitdiff
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
parentae9e545c3ed33d39ce21ae13ceb8337fa34901b8 (diff)
downloadpsn00bsdk-7be9178c0f9b0e698a305ecc5c0c41fcc596a4fc.tar.gz
LibPSn00b officially v0.10b, added psxsio library, better DrawSync() and VSync(), better reference manual.
-rw-r--r--README.md194
-rw-r--r--changelog.txt93
-rw-r--r--doc/LibPSn00b Reference.odtbin0 -> 95022 bytes
-rw-r--r--doc/dev notes.txt38
-rw-r--r--examples/balls/main.c4
-rw-r--r--examples/gte/main.c4
-rw-r--r--examples/n00bdemo/disp.c4
-rw-r--r--examples/n00bdemo/main.c2
-rw-r--r--examples/rgb24/main.c2
-rw-r--r--libpsn00b/include/hwregs_a.h7
-rw-r--r--libpsn00b/include/psxapi.h76
-rw-r--r--libpsn00b/include/psxgpu.h104
-rw-r--r--libpsn00b/include/psxpad.h2
-rw-r--r--libpsn00b/include/psxsio.h66
-rw-r--r--libpsn00b/include/stdio.h10
-rw-r--r--libpsn00b/include/stdlib.h8
-rw-r--r--libpsn00b/include/string.h7
-rw-r--r--libpsn00b/libc/malloc.s46
-rw-r--r--libpsn00b/libc/memcmp.s8
-rw-r--r--libpsn00b/libc/memcpy.s6
-rw-r--r--libpsn00b/libc/memmove.s8
-rw-r--r--libpsn00b/libc/memset.s4
-rw-r--r--libpsn00b/libc/start.s4
-rw-r--r--libpsn00b/lzp/compress.c1
-rw-r--r--libpsn00b/lzp/makefile2
-rw-r--r--libpsn00b/makefile2
-rw-r--r--libpsn00b/psxapi/stdio/getchar.s10
-rw-r--r--libpsn00b/psxapi/stdio/gets.s10
-rw-r--r--libpsn00b/psxapi/stdio/putc.s4
-rw-r--r--libpsn00b/psxapi/stdio/putchar.s10
-rw-r--r--libpsn00b/psxapi/stdio/puts.s10
-rw-r--r--libpsn00b/psxapi/sys/exec.s10
-rw-r--r--libpsn00b/psxetc/fntsort.c2
-rw-r--r--libpsn00b/psxetc/font.c4
-rw-r--r--libpsn00b/psxetc/makefile4
-rw-r--r--libpsn00b/psxgpu/dmacallback.s191
-rw-r--r--libpsn00b/psxgpu/drawotag.s14
-rw-r--r--libpsn00b/psxgpu/drawprim.s40
-rw-r--r--libpsn00b/psxgpu/drawsync.s49
-rw-r--r--libpsn00b/psxgpu/drawsynccallback.s103
-rw-r--r--libpsn00b/psxgpu/getinterruptcallback.s17
-rw-r--r--libpsn00b/psxgpu/interruptcallback.s48
-rw-r--r--libpsn00b/psxgpu/loadimage.s4
-rw-r--r--libpsn00b/psxgpu/putdispenv.s60
-rw-r--r--libpsn00b/psxgpu/putdrawenv.s12
-rw-r--r--libpsn00b/psxgpu/readme.txt34
-rw-r--r--libpsn00b/psxgpu/resetgraph.s459
-rw-r--r--libpsn00b/psxgpu/setvideomode.s6
-rw-r--r--libpsn00b/psxgpu/vsynccallback.s2
-rw-r--r--libpsn00b/psxgte/readme.txt4
-rw-r--r--libpsn00b/psxgte/squareroot.s30
-rw-r--r--libpsn00b/psxgte/vectornormals.s11
-rw-r--r--libpsn00b/psxsio/_sio_control.s182
-rw-r--r--libpsn00b/psxsio/makefile38
-rw-r--r--libpsn00b/psxsio/siocons.c137
-rw-r--r--libpsn00b/psxspu/readme.txt5
-rw-r--r--libpsn00b/psxspu/spuinit.s8
-rw-r--r--libpsn00b/psxspu/spusetkey.s4
-rw-r--r--libpsn00b/psxspu/transfer.s10
59 files changed, 1747 insertions, 487 deletions
diff --git a/README.md b/README.md
index e7b2247..8d8c1ae 100644
--- a/README.md
+++ b/README.md
@@ -1,78 +1,149 @@
# 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 project for the original Sony
+PlayStation for developing homebrew applications and games for the console
+whether it be an open source, freeware, or commercial project.
+The SDK is composed mainly of libraries (libpsn00b) and some utilities that
+provide a basic framework for developing software for the PlayStation
+hardware, the compiler is separate (GCC) and should be acquired from GNU.
+The library API is intentionally written to resemble the library API of the
+official libraries as closely as possible. This design decision is not only
+for familiarity reasons and so that existing sample code and tutorials would
+still apply, but to also make porting existing homebrew originally made with
+official SDKs to PSn00bSDK easier with few modifications.
-## Building the SDK
+PSn00bSDK is currently a work in progress and cannot really be considered
+production ready, but what is currently implemented should be enough to
+produce some interesting homebrew with the SDK, especially with extensive
+support for the GPU and GTE hardware. There's no reason not to fully support
+the hardware features of the target platform when they have been fully
+documented for years (nocash's PSX specs document in this case).
+
+Most of libpsn00b is written mostly in MIPS assembly, more so functions that
+interface with hardware. Many of the standard C functions are implemented in
+custom MIPS assembly instead of equivalents found in the BIOS ROM for
+performance reasons.
+
+
+## Notable features
+
+* Extensive GPU support with polygon primitives, high-speed DMA VRAM
+ transfers and DMA ordering table processing. All video modes for both NTSC
+ and PAL standards also supported with fully adjustable display area and
+ automatic video standard detection based on last GPU mode, no BIOS ROM
+ string checks used.
+
+* Extensive GTE support with rotate, translate, perspective correction and
+ lighting through assembly macros (for both C and ASM) and high performance
+ matrix and vector functions, all calculations performed in fixed point
+ integer math.
+
+* Stable and easy to use interrupt service routine with callback system for
+ simplified handling of hardware and DMA interrupts, no crude event handlers
+ or kernel hacks used and should be compatible with HLE BIOS implementations
+ and homebrew loaders and menus.
+
+* Complete Serial I/O support with SIOCONS driver for tty console access
+ through serial interface.
+
+* BIOS controller functions for polling controller input function as
+ intended, no crude manual polling in main loop.
-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.
+* BIOS CD-ROM support with custom initialization function that does not
+ break other DMA channels (such as GPU and SPU DMA) for easier CD-ROM
+ initialization.
-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.
+* Uses Sony SDK library syntax for familiarity to experienced programmers
+ and to make porting existing homebrew to PSn00bSDK easier.
-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.
+* Works on real hardware and most popular emulators.
-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.
+## Obtaining PSn00bSDK
+
+Because PSn00bSDK is updated semi-regularly as this project is mostly a
+work-in-progress, it is better to obtain this SDK from source by building
+it yourself in the long run. Prepared packages containing precompiled
+libpsn00b libraries, the toolchain and additional utilities not included
+in this repository for Windows users are planned, but some arrangements
+need to be made. Perhaps when PSn00bSDK is halfway production ready.
+
+A precompiled copy of the GCC 7.2.0 toolchain for Windows is available
+in lameguy64's website in the PSn00bSDK page. This should make building
+PSn00bSDK under Windows a bit easier as building the toolchain is the
+hardest part of building PSn00bSDK and its more difficult to get it to
+compile correctly under Windows.
+
+
+## Building the SDK
+
+### Windows (needs work/testing):
+1. Download the following:
+ * MinGW GCC
+ * MSys2
+ * tinyxml2 (for lzpack and smxlink)
+ * GCC 7.2.0 for mipsel-unknown-elf (download from Lameguy64's website)
+2. Install MSys2 and MinGW GCC.
+3. Extract GCC 7.2.0 for mipsel-unknown-elf to the root of your C drive.
+4. Update your PATH environment variable to point to the bin directories of
+ GCC 7.2.0 for mipsel-unknown-elf, MSys2 and MinGW GCC. Make sure you can
+ access gcc, mipsel-unknown-elf-gcc and make from any directory in the
+ command prompt.
+5. Build tinyxml2 with MinGW GCC through MSys2's shell.
+6. Clone/download PSn00bSDK source files.
+7. Enter libpsn00b directory and run make (with optional -j parameter for
+ building across multiple cores/threads).
+8. Enter tools directory and run make, then make install to consolidate the
+ executables to a bin directory. Add this directory to your PATH
+ environment variable.
+9. Compile the example programs to test if the SDK is set up correctly.
+ Set correct paths in sdk-common.mk when necessary.
+
+### Linux and Unix-likes:
+1. Build and install the GNU GCC toolchain configured for mipsel-unknown-elf
+ (see toolchain.txt for details).
+2. Install the following (development) package:
+ * tinyxml2
+3. Clone/download PSn00bSDK source files.
+4. Enter the libpsn00b directory and run make. Make sure
+ mipsel-unknown-elf-gcc is accessible in the terminal from within any
+ directory beforehand.
+5. Enter the tools directory and run make, then make install to consolidate
+ the binaries to a bin directory. Add this directory to your PATH variable.
+6. Compile the example programs to test if the SDK is set up correctly.
+ Set correct paths in sdk-common.mk when necessary.
## 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 examples and complete source code of n00bdemo included in
+the examples directory. More example programs may be added in the future
+and contributed example programs are welcome.
-## To-do
+## To-do List
-* 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.
+* libc: C++ support (getting classes, new and delete working is enough)
+ and better sprintf() (one from PSXSDK is slow due to unnecessary usage
+ of int64 and somewhat a bit buggy) yet to be implemented. More standard
+ C library stuff also yet to be implemented.
-* psxspu needs to be expanded upon. Currently lacks support for reverb
- and many voice controls.
+* psxgpu: VRAM download and VRAM move functions, some more primitives
+ and macros yet to be implemented.
-* 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.
+* psxgte: Higher level GTE rotate translate and perspective functions
+ yet to be implemented.
-* CD-ROM library is yet to be made.
+* psxspu: Lots of work to do.
-* Better (and faster) sprintf() function.
+* psxapi: Plenty of BIOS function calls yet to be added.
+
+* psxetc: Text stream stuff (FntOpen(), FntPrint(), FndFlush()) for
+ debug purposes yet to be implemented.
+
+* Libraries yet to be made: psxcd (for better CD-ROM support) and
+ psxmdec (MDEC support).
## Usage terms
@@ -80,9 +151,12 @@ future updates and contributions are welcome.
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.
+projects as projects using PSn00bSDK does not necessarily have to follow
+the MPL as well.
+
+If modifications to the SDK were made as part of the development of such
+projects that enhance its functionality, such changes must be contributed
+back in return.
## Credits
@@ -90,6 +164,6 @@ return.
Main developer:
* Lameguy64
-Important references used:
+References used:
* nocash's PlayStation specs document (http://problemkaputt.de/psx-spx.htm)
-* Tails92's PSXSDK project (bits and pieces of it).
+* Tails92's PSXSDK project.
diff --git a/changelog.txt b/changelog.txt
index 1c27eaf..65717bd 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,18 +1,103 @@
PSn00bSDK changelog
+
+06-23-2019 by Lameguy64:
+
+* LibPSn00b Run-time Library is officially version 0.10b.
+
+* Reworked readme file with improved build instructions.
+
+* libpsn00b: Added missing C extern groups for C++ compatibility in
+ psxapi.h, stdlib.h and string.h.
+
+* libpsn00b: Removed changelogs in the readmes of each libpsn00b library
+ as its much easier to keep track of changes in a single changelog than
+ scattering them across multiple changelogs.
+
+* psxapi: Added Exec() function and EXEC struct.
+
+* psxgpu: Added DrawPrim() function (uses direct I/O).
+
+* psxgpu: VSync() function completely overhauled. Logic is now based on
+ Sony's code but more efficient and can return total number of vblanks
+ elapsed, number of hblanks since last call and wait up to n vblanks
+ specified by an appropriate argument value. It will also generate a
+ timeout when vblank interrupt stops working and would attempt to
+ restart it.
+
+* psxapi: Added gets() and getc() BIOS functions.
+
+* psxapi: Corrected a putc()/putchar() discrepancy. putc() puts a character
+ to a file stream, putchar() puts a character to stdout.
+
+* Completely revised library reference manual with better formatting and
+ more functions documented.
+
+* psxgpu: Added DrawSyncCallback().
+
+* psxgpu: Implemented DMA interrupt callback system with DMACallback()
+ allowing to handle DMA interrupts very easily.
+
+* libpsn00b: Implemented Serial I/O library (psxsio) with serial tty device
+ (installed using AddSIO) and serial callback support. Serial library
+ is also fully documented.
+
+* psxgpu: Implemented IRQ callback system with InterruptCallback() allowing
+ to set interrupt callbacks very easily.
+
+* psxgpu: Implemented proper IRQ handler installed using HookEntryInt or
+ SetCustomExitFromException() for handling VSync and other interrupts.
+ ChangeClearPAD(0) must now be called after _InitPad() or vsync timeout
+ will occur.
+
+* libpsn00b: Started making local labels prefixed with .L instead of . making
+ them not appear in symbol lists resulting in a cleaner symbol dump. Still
+ not possible to do function-scope local labels like in ASMPSX because GAS
+ syntax is ASS (or ASS GAS which is farts, GAS is farts).
+
+* psxgpu: DrawSync() function now waits for DMA completion and GPU transfer
+ ready instead of simply waiting for GPU transfer ready which is the likely
+ cause of subtle GPU related timing issues, it also sets GPU DMA transfer
+ mode to off afterwards. It can also read number of words remaining in DMA
+ transfer if a0 is non-zero but it likely only returns the correct value on
+ VRAM transfers. Exact way how DrawSync() returns the count in the official
+ SDK is currently unknown.
+
+
+
+06-07-2019 by qbradq:
+
+* lzpack: Swapped a buffer length litteral with sizeof operator, fixing a
+ stack overflow bug in some instances.
+
+
+
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.
+ quirks about the console discovered during the development of this
+ SDK project.
* Updated libn00bref.odf a little.
+* Added turboboot example.
+
* Added rgb24 example.
-* Made stack usage in ResetGraph() less wasteful.
+* 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 in ResetGraph() less wasteful. You only need to
+ allocate N words on stack based on N arguments of the function
+ being called.
-* VSync IRQ handling now done using a custom exit handler. Actual VSync
- handling is yet to be moved to the custom exit handler though.
+* VSync IRQ handling now done using a custom exit from exception 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.
diff --git a/doc/LibPSn00b Reference.odt b/doc/LibPSn00b Reference.odt
new file mode 100644
index 0000000..ca5346d
--- /dev/null
+++ b/doc/LibPSn00b Reference.odt
Binary files differ
diff --git a/doc/dev notes.txt b/doc/dev notes.txt
index 336e6d3..2b280c7 100644
--- a/doc/dev notes.txt
+++ b/doc/dev notes.txt
@@ -10,21 +10,28 @@ I run into more previously undocumented quirks in the future.
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.
+functions don't always use the space allotted in stack. When calling a
+function with a variable number of arguments (printf) always allocate
+16 bytes of 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.
+* Hooking a custom handler using BIOS function HookEntryInt (B(19h), known
+as SetCustomExitFromException in nocash docs) is only triggered when there's
+an IRQ that is not yet acknowledged by previous IRQ handlers built into the
+kernel. This is also the best point to acknowledge any IRQs without breaking
+compatibility with built-in BIOS IRQ handlers and is what the official SDK
+uses to handle IRQs. To make sure this handler is triggered on every interrupt
+you must call ChangeClearPad(0) and ChangeClearRCnt(3, 0) (which are functions
+(B(5Bh)) and C(0Ah) respectively) otherwise the pad and root counter handlers
+in the kernel will acknowledge the interrupt before your handler, preventing
+you from handling them yourself.
-* 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
+* It is not advisable to handle interrupts using event handlers like in
+PSXSDK as it breaks 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).
+function HookEntryInt (B(19h), known as SetCustomExitFromException in nocash
+docs).
* 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,
@@ -34,10 +41,11 @@ 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.
+set the height to 512 pixels the primitive is processed 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, hence why
+DRAWENV.isbg is not effective in the official SDK.
* 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
diff --git a/examples/balls/main.c b/examples/balls/main.c
index 3e23fb5..ba6a391 100644
--- a/examples/balls/main.c
+++ b/examples/balls/main.c
@@ -203,8 +203,8 @@ int main(int argc, const char* argv[]) {
nextpri += sizeof(DR_TPAGE);
/* Wait for GPU and VSync */
- DrawSync();
- VSync();
+ DrawSync( 0 );
+ VSync( 0 );
/* Since draw.isbg is non-zero this clears the screen */
PutDrawEnv( &draw );
diff --git a/examples/gte/main.c b/examples/gte/main.c
index aa7042d..3fec9d7 100644
--- a/examples/gte/main.c
+++ b/examples/gte/main.c
@@ -288,8 +288,8 @@ void init() {
void display() {
/* Wait for GPU to finish drawing and vertical retrace */
- DrawSync();
- VSync();
+ DrawSync( 0 );
+ VSync( 0 );
/* Swap buffers */
db_active ^= 1;
diff --git a/examples/n00bdemo/disp.c b/examples/n00bdemo/disp.c
index 5a9bb22..d798ee9 100644
--- a/examples/n00bdemo/disp.c
+++ b/examples/n00bdemo/disp.c
@@ -57,8 +57,8 @@ void initDisplay() {
void display() {
- VSync();
- DrawSync();
+ DrawSync(0);
+ VSync(0);
PutDrawEnv( &draw );
DrawOTag( ot[db]+OT_LEN-1 );
diff --git a/examples/n00bdemo/main.c b/examples/n00bdemo/main.c
index 2a5874f..a6eb57e 100644
--- a/examples/n00bdemo/main.c
+++ b/examples/n00bdemo/main.c
@@ -615,7 +615,7 @@ void transition() {
}
- DrawSync();
+ DrawSync(0);
draw.isbg = 1;
diff --git a/examples/rgb24/main.c b/examples/rgb24/main.c
index 178ece2..9f1a647 100644
--- a/examples/rgb24/main.c
+++ b/examples/rgb24/main.c
@@ -43,7 +43,7 @@ int main() {
// Upload image to VRAM
GetTimInfo(tim_image, &tim);
LoadImage(tim.prect, tim.paddr);
- DrawSync();
+ DrawSync(0);
while(1) {
}
diff --git a/libpsn00b/include/hwregs_a.h b/libpsn00b/include/hwregs_a.h
index a71a657..27cfc88 100644
--- a/libpsn00b/include/hwregs_a.h
+++ b/libpsn00b/include/hwregs_a.h
@@ -63,6 +63,13 @@
.set JOY_CTRL, 0x104A
.set JOY_BAUD, 0x104E
+# Serial
+.set SIO_TXRX, 0x1050
+.set SIO_STAT, 0x1054
+.set SIO_MODE, 0x1058
+.set SIO_CTRL, 0x105a
+.set SIO_BAUD, 0x105e
+
# IRQ
.set ISTAT, 0x1070
.set IMASK, 0x1074
diff --git a/libpsn00b/include/psxapi.h b/libpsn00b/include/psxapi.h
index 9cfb6cb..68dac67 100644
--- a/libpsn00b/include/psxapi.h
+++ b/libpsn00b/include/psxapi.h
@@ -47,6 +47,20 @@ struct DIRENTRY { // Directory entry
char system[4];
};
+struct EXEC {
+ unsigned int pc0;
+ unsigned int gp0;
+ unsigned int t_addr;
+ unsigned int t_size;
+ unsigned int d_addr;
+ unsigned int d_size;
+ unsigned int b_addr;
+ unsigned int b_size;
+ unsigned int s_addr;
+ unsigned int s_size;
+ unsigned int sp,fp,rp,ret,base;
+};
+
// Not recommended to use these functions to install IRQ handlers
typedef struct {
@@ -56,48 +70,60 @@ typedef struct {
unsigned int pad;
} INT_RP;
-extern void SysEnqIntRP(int pri, INT_RP *rp);
-extern void SysDeqIntRP(int pri, INT_RP *rp);
+#ifdef __cplusplus
+extern "C" {
+#endif
-// Use event handlers instead
+void SysEnqIntRP(int pri, INT_RP *rp);
+void SysDeqIntRP(int pri, INT_RP *rp);
-extern int OpenEvent(unsigned int class, int spec, int mode, void (*func)());
-extern int CloseEvent(int ev_desc);
-extern int EnableEvent(int ev_desc);
-extern int DisableEvent(int ev_desc);
+// Event handler stuff
+
+int OpenEvent(unsigned int class, int spec, int mode, void (*func)());
+int CloseEvent(int ev_desc);
+int EnableEvent(int ev_desc);
+int DisableEvent(int ev_desc);
// BIOS file functions
-extern int open(const char *name, int mode);
-extern int close(int fd);
-extern int seek(int fd, unsigned int offset, int mode);
-extern int read(int fd, char *buff, unsigned int len);
-extern int write(int fd, const char *buff, unsigned int len);
-extern int ioctl(int fd, int cmd, int arg);
-extern struct DIRENTRY *firstfile(const char *wildcard, struct DIRENTRY *entry);
-extern struct DIRENTRY *nextfile(struct DIRENTRY *entry);
-extern int erase(const char *name);
-extern int chdir(const char *path);
+int open(const char *name, int mode);
+int close(int fd);
+int seek(int fd, unsigned int offset, int mode);
+int read(int fd, char *buff, unsigned int len);
+int write(int fd, const char *buff, unsigned int len);
+int ioctl(int fd, int cmd, int arg);
+struct DIRENTRY *firstfile(const char *wildcard, struct DIRENTRY *entry);
+struct DIRENTRY *nextfile(struct DIRENTRY *entry);
+int erase(const char *name);
+int chdir(const char *path);
#define delete( p ) erase( p )
#define cd( p ) chdir( p ) // For compatibility
int AddDev(DCB *dcb);
int DelDev(const char *name);
-extern void ListDev(void);
-
-extern void EnterCriticalSection(void);
-extern void ExitCriticalSection(void);
+void ListDev(void);
-extern void _InitCd(void);
-extern void _96_init(void);
-extern void _96_remove(void);
+void EnterCriticalSection(void);
+void ExitCriticalSection(void);
-extern void ChangeClearPAD(int mode);
+void _InitCd(void);
+void _96_init(void);
+void _96_remove(void);
// BIOS pad functions
void _InitPad(char *buff1, int len1, char *buff2, int len2);
void _StartPad(void);
void _StopPad(void);
+void ChangeClearPAD(int mode);
+void ChangeClearRCnt(int t, int m);
+
+// Executable functions
+int Exec(struct EXEC *exec, int argc, char *argv);
+
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/libpsn00b/include/psxgpu.h b/libpsn00b/include/psxgpu.h
index 24d023a..40b9159 100644
--- a/libpsn00b/include/psxgpu.h
+++ b/libpsn00b/include/psxgpu.h
@@ -38,8 +38,8 @@
#define setDrawTPage( p, tp, abr, x, y ) \
( (p)->code[0] = getTPage( tp, abr, x, y ), \
setlen( p, 1 ), setcode( p, 0xe1 ) )
-
-/** ORIGINAL FUNCTION **/
+
+/* ORIGINAL */
#define setDrawTPageVal( p, tp ) \
( (p)->code[0] = tp, \
setlen( p, 1 ), setcode( p, 0xe1 ) )
@@ -217,25 +217,24 @@ typedef struct {
unsigned int tag;
unsigned char r0,g0,b0,code;
short x0,y0;
- unsigned char u0,v0;
- unsigned short clut;
short x1,y1;
- unsigned char u1,v1;
- unsigned short tpage;
short x2,y2;
- unsigned char u2,v2;
- unsigned short pad;
-} POLY_FT3;
+ short x3,y3;
+} POLY_F4;
typedef struct {
unsigned int tag;
unsigned char r0,g0,b0,code;
short x0,y0;
- unsigned char r1,g1,b1,pad0;
+ unsigned char u0,v0;
+ unsigned short clut;
short x1,y1;
- unsigned char r2,g2,b2,pad1;
+ unsigned char u1,v1;
+ unsigned short tpage;
short x2,y2;
-} POLY_G3;
+ unsigned char u2,v2;
+ unsigned short pad;
+} POLY_FT3;
typedef struct {
unsigned int tag;
@@ -243,53 +242,54 @@ typedef struct {
short x0,y0;
unsigned char u0,v0;
unsigned short clut;
- unsigned char r1,g1,b1,pad0;
short x1,y1;
unsigned char u1,v1;
unsigned short tpage;
- unsigned char r2,g2,b2,pad1;
short x2,y2;
unsigned char u2,v2;
- unsigned short pad2;
-} POLY_GT3;
+ unsigned short pad0;
+ short x3,y3;
+ unsigned char u3,v3;
+ unsigned short pad1;
+} POLY_FT4;
typedef struct {
unsigned int tag;
unsigned char r0,g0,b0,code;
short x0,y0;
+ unsigned char r1,g1,b1,pad0;
short x1,y1;
+ unsigned char r2,g2,b2,pad1;
short x2,y2;
- short x3,y3;
-} POLY_F4;
+} POLY_G3;
typedef struct {
unsigned int tag;
unsigned char r0,g0,b0,code;
short x0,y0;
- unsigned char u0,v0;
- unsigned short clut;
+ unsigned char r1,g1,b1,pad0;
short x1,y1;
- unsigned char u1,v1;
- unsigned short tpage;
+ unsigned char r2,g2,b2,pad1;
short x2,y2;
- unsigned char u2,v2;
- unsigned short pad0;
+ unsigned char r3,g3,b3,pad2;
short x3,y3;
- unsigned char u3,v3;
- unsigned short pad1;
-} POLY_FT4;
+} POLY_G4;
typedef struct {
unsigned int tag;
unsigned char r0,g0,b0,code;
short x0,y0;
+ unsigned char u0,v0;
+ unsigned short clut;
unsigned char r1,g1,b1,pad0;
short x1,y1;
+ unsigned char u1,v1;
+ unsigned short tpage;
unsigned char r2,g2,b2,pad1;
short x2,y2;
- unsigned char r3,g3,b3,pad2;
- short x3,y3;
-} POLY_G4;
+ unsigned char u2,v2;
+ unsigned short pad2;
+} POLY_GT3;
typedef struct {
unsigned int tag;
@@ -431,21 +431,6 @@ typedef struct {
/*
* VRAM fill and transfer primitive definitions
*/
-typedef struct {
- unsigned int tag;
- unsigned char r0,g0,b0,code;
- unsigned short x0,y0; // Note: coordinates must be in 16 pixel steps
- unsigned short w,h;
-} FILL;
-
-typedef struct {
- unsigned int tag;
- unsigned char p0,p1,p2,code;
- unsigned short x0,y0;
- unsigned short x1,y1;
- unsigned short w,h;
- unsigned int nop[4];
-} VRAM2VRAM;
typedef struct {
unsigned int tag;
@@ -462,11 +447,26 @@ typedef struct {
unsigned int code[1];
} DR_TPAGE;
-typedef struct { /* ORIGINAL CODE */
+typedef struct { /* ORIGINAL */
unsigned int tag;
unsigned int code[1];
} DR_MASK;
+typedef struct { /* ORIGINAL */
+ unsigned int tag;
+ unsigned char r0,g0,b0,code;
+ unsigned short x0,y0; // Note: coordinates must be in 16 pixel steps
+ unsigned short w,h;
+} FILL;
+
+typedef struct { /* ORIGINAL */
+ unsigned int tag;
+ unsigned char p0,p1,p2,code;
+ unsigned short x0,y0;
+ unsigned short x1,y1;
+ unsigned short w,h;
+ unsigned int nop[4];
+} VRAM2VRAM;
// General structs
@@ -528,17 +528,23 @@ void PutDrawEnv(DRAWENV *draw);
void SetDispMask(int mask);
-void VSync();
-void DrawSync();
+int VSync(int m);
+int DrawSync(int m);
void WaitGPUcmd();
void WaitGPUdma();
-void VSyncCallback(void (*func)());
+void *VSyncCallback(void (*func)());
+void *DrawSyncCallback(void (*func)());
+
+void *DMACallback(int dma, void (*func)());
+void *InterruptCallback(int irq, void (*func)());
+void *GetInterruptCallback(int irq); // Original
void LoadImage(RECT *rect, unsigned int *data);
void ClearOTagR(unsigned int* ot, int n);
void DrawOTag(unsigned int* ot);
+void DrawPrim(void *pri);
void AddPrim(unsigned int* ot, void* pri);
diff --git a/libpsn00b/include/psxpad.h b/libpsn00b/include/psxpad.h
index 5478596..01aff06 100644
--- a/libpsn00b/include/psxpad.h
+++ b/libpsn00b/include/psxpad.h
@@ -68,7 +68,7 @@ typedef struct {
unsigned char stat;
unsigned char len:4;
unsigned char type:4; // Device type (0x1)
- unsigned char btn;
+ unsigned short btn;
char x_mov; // X movement of mouse
char y_mov; // Y movement of mouse
} MOUSETYPE;
diff --git a/libpsn00b/include/psxsio.h b/libpsn00b/include/psxsio.h
new file mode 100644
index 0000000..df218ac
--- /dev/null
+++ b/libpsn00b/include/psxsio.h
@@ -0,0 +1,66 @@
+#ifndef __PSXSIO_H
+#define __PSXSIO_H
+
+#define SR_TXRDY 0x1
+#define SR_RXRDY 0x2
+#define SR_TXU 0x4
+#define SR_PERROR 0x8
+#define SR_OE 0x10
+#define SR_FE 0x20
+#define SR_DSR 0x80
+#define SR_CTS 0x100
+#define SR_IRQ 0x200
+
+#define SIO_TXRDY 0x1
+#define SIO_RXRDY 0x2
+#define SIO_TXU 0x4
+#define SIO_PERROR 0x8
+#define SIO_OE 0x10
+#define SIO_FE 0x20
+#define SIO_DSR 0x80
+#define SIO_CTS 0x100
+#define SIO_IRQ 0x200
+
+#define MR_CHLEN_5 0x00
+#define MR_CHLEN_6 0x04
+#define MR_CHLEN_7 0x08
+#define MR_CHLEN_8 0x0C
+#define MR_PEN 0x10
+#define MR_P_EVEN 0x30
+#define MR_SB_01 0x40
+#define MR_SB_10 0x80
+#define MR_SB_11 0xc0
+
+#define CR_TXEN 0x1
+#define CR_DTR 0x2
+#define CR_RXEN 0x4
+#define CR_BRK 0x8
+#define CR_INTRST 0x10
+#define CR_RTS 0x20
+#define CR_ERRRST 0x40
+#define CR_BUFSZ_1 0x00
+#define CR_BUFSZ_2 0x100
+#define CR_BUFSZ_4 0x200
+#define CR_BUFSZ_8 0x300
+#define CR_TXIEN 0x400
+#define CR_RXIEN 0x800
+#define CR_DSRIEN 0x1000
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int _sio_control(int cmd, int arg, int param);
+void AddSIO(int baud);
+void DelSIO(void);
+
+void *Sio1Callback(void (*func)(void));
+
+// ORIGINAL
+void WaitSIO(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif \ No newline at end of file
diff --git a/libpsn00b/include/stdio.h b/libpsn00b/include/stdio.h
index 5ee9e9b..98c69d0 100644
--- a/libpsn00b/include/stdio.h
+++ b/libpsn00b/include/stdio.h
@@ -4,7 +4,7 @@
#include <stdarg.h>
#ifndef NULL
-#define NULL (void*)0
+#define NULL 0
#endif
// BIOS seek modes
@@ -32,6 +32,14 @@ extern void printf (const char *__format, ...);
extern int getc(int __fd);
extern int putc(int __char, int __fd);
+
+#define fputc(__char, __fd) putc(__char, __fd)
+#define fgetc(__char, __fd) getc(__char, __fd)
+
+// Console TTY
+extern void gets(char *__s);
+extern void puts(const char *__s);
+extern int getchar(void);
extern void putchar(int __c);
// The following functions do not use the BIOS
diff --git a/libpsn00b/include/stdlib.h b/libpsn00b/include/stdlib.h
index 3909796..f9f41db 100644
--- a/libpsn00b/include/stdlib.h
+++ b/libpsn00b/include/stdlib.h
@@ -41,6 +41,10 @@ void *calloc(int number, int size);
void *realloc(void *buf , int n);
*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
int rand();
void srand(unsigned long seed);
@@ -53,5 +57,9 @@ long double strtold(const char *nptr, char **endptr);
double strtod(const char *nptr, char **endptr);
float strtof(const char *nptr, char **endptr);
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/libpsn00b/include/string.h b/libpsn00b/include/string.h
index 95796d5..9cd1d64 100644
--- a/libpsn00b/include/string.h
+++ b/libpsn00b/include/string.h
@@ -9,6 +9,10 @@
#ifndef _STRING_H
#define _STRING_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
int strcmp(const char *dst , const char *src);
int strncmp(const char *dst , const char *src , int len);
char *strpbrk(const char *dst , const char *src);
@@ -37,6 +41,9 @@ void *memcpy(void *dst , const void *src , int n);
void *memset(void *dst , char c , int n);
int memcmp(const void *b1 , const void *b2 , int n);
+#ifdef __cplusplus
+}
+#endif
#endif
diff --git a/libpsn00b/libc/malloc.s b/libpsn00b/libc/malloc.s
index 20e5371..fdb196d 100644
--- a/libpsn00b/libc/malloc.s
+++ b/libpsn00b/libc/malloc.s
@@ -52,7 +52,7 @@ malloc:
lw $a2, 0($a2)
sll $a0, 2
-.find_next:
+.Lfind_next:
move $a1, $a2
@@ -61,16 +61,16 @@ malloc:
subu $v0, $a2, $a1 # Compute space between current and next
- beqz $v1, .empty_block # Occupy empty block (if size = 0)
+ beqz $v1, .Lempty_block # Occupy empty block (if size = 0)
nop
- beqz $a2, .new_block # Allocate a new block (if no next)
+ beqz $a2, .Lnew_block # Allocate a new block (if no next)
nop
addiu $v0, -(ND_HSIZ*2) # Compute remaining space of block
subu $v0, $v1
- blt $v0, $a0, .find_next # Search for the next block if space is not big enough
+ blt $v0, $a0, .Lfind_next # Search for the next block if space is not big enough
nop
# Perform a block split using remaining space of current block
@@ -88,19 +88,19 @@ malloc:
jr $ra
addiu $v0, ND_HSIZ
-.empty_block: # Occupy an empty block
+.Lempty_block: # Occupy an empty block
- beqz $a2, .no_next # Skip size calculation if there's no next
+ beqz $a2, .Lno_next # Skip size calculation if there's no next
nop
addiu $v0, -ND_HSIZ
- blt $v0, $a0, .find_next
+ blt $v0, $a0, .Lfind_next
nop
- b .skip_space_check
+ b .Lskip_space_check
nop
-.no_next:
+.Lno_next:
la $v1, _malloc_addr # Check if there's enough space for a block
lw $v1, 0($v1)
@@ -111,16 +111,16 @@ malloc:
addu $v1, $a0
addiu $v1, ND_HSIZ
- bgt $v1, $v0, .no_space
+ bgt $v1, $v0, .Lno_space
nop
-.skip_space_check:
+.Lskip_space_check:
sw $a0, ND_SIZE($a1)
jr $ra # Return address
addiu $v0, $a1, ND_HSIZ
-.new_block: # Create a new block
+.Lnew_block: # Create a new block
addu $a2, $a1, $v1 # Compute address for new block
addiu $a2, ND_HSIZ
@@ -134,7 +134,7 @@ malloc:
addu $v1, $a0
addiu $v1, ND_HSIZ
- bgt $v1, $v0, .no_space # Reject if it exceeds specified size
+ bgt $v1, $v0, .Lno_space # Reject if it exceeds specified size
nop
sw $a1, ND_PREV($a2)
@@ -146,7 +146,8 @@ malloc:
jr $ra # Return address
addiu $v0, $a2, ND_HSIZ
-.no_space: # Return a null if no space can be found
+.Lno_space: # Return a null if no space can be found
+
jr $ra
move $v0, $0
@@ -168,10 +169,12 @@ calloc:
move $a0, $v0
mflo $a1
-.clear_loop:
+
+.Lclear_loop:
+
sw $0 , 0($a0)
addi $a1, 4
- bgtz $a1, .clear_loop
+ bgtz $a1, .Lclear_loop
addiu $a0, 4
lw $ra, 0($sp)
@@ -191,10 +194,10 @@ free:
lw $a1, ND_PREV($a0)
lw $a2, ND_NEXT($a0)
- beqz $a1, .is_start # Check if block is a starting block
+ beqz $a1, .Lis_start # Check if block is a starting block
nop
- beqz $a2, .is_end
+ beqz $a2, .Lis_end
nop
# Unlink
@@ -203,10 +206,13 @@ free:
jr $ra
sw $a1, ND_PREV($a2)
-.is_end: # Unlinks the ending block
+.Lis_end: # Unlinks the ending block
+
jr $ra
sw $0 , ND_NEXT($a1)
-.is_start: # Simply set size to 0 if starting block
+
+.Lis_start: # Simply set size to 0 if starting block
+
jr $ra
sw $0 , ND_SIZE($a0)
diff --git a/libpsn00b/libc/memcmp.s b/libpsn00b/libc/memcmp.s
index b8b495d..ec1e729 100644
--- a/libpsn00b/libc/memcmp.s
+++ b/libpsn00b/libc/memcmp.s
@@ -13,19 +13,19 @@
.global memcmp
.type memcmp, @function
memcmp:
- blez $a2, .exit
+ blez $a2, .Lexit
addi $a2, -1
lbu $v0, 0($a0)
lbu $v1, 0($a1)
addiu $a0, 1
- bne $v0, $v1, .mismatch
+ bne $v0, $v1, .Lmismatch
addiu $a1, 1
b memcmp
nop
-.mismatch:
+.Lmismatch:
jr $ra
sub $v0, $v1
-.exit:
+.Lexit:
jr $ra
move $v0, $0
\ No newline at end of file
diff --git a/libpsn00b/libc/memcpy.s b/libpsn00b/libc/memcpy.s
index e1a4e30..e3d1dd5 100644
--- a/libpsn00b/libc/memcpy.s
+++ b/libpsn00b/libc/memcpy.s
@@ -14,15 +14,15 @@
.type memcpy, @function
memcpy:
move $v0, $a0
-.loop:
+.Lloop:
blez $a2, .exit
addi $a2, -1
lbu $a3, 0($a1)
addiu $a1, 1
sb $a3, 0($a0)
- b .loop
+ b .Lloop
addiu $a0, 1
-.exit:
+.Lexit:
jr $ra
nop
\ No newline at end of file
diff --git a/libpsn00b/libc/memmove.s b/libpsn00b/libc/memmove.s
index 961e71f..d32e2ca 100644
--- a/libpsn00b/libc/memmove.s
+++ b/libpsn00b/libc/memmove.s
@@ -14,16 +14,16 @@ memmove:
addu $a1, $a2
addiu $a0, -1
addiu $a1, -1
-.loop:
- blez $a2, .exit
+.Lloop:
+ blez $a2, .Lexit
addi $a2, -1
lbu $v1, 0($a1)
addiu $a1, -1
sb $v1, 0($a0)
addiu $a0, -1
- b .loop
+ b .Lloop
nop
-.exit:
+.Lexit:
jr $ra
nop
\ No newline at end of file
diff --git a/libpsn00b/libc/memset.s b/libpsn00b/libc/memset.s
index f7d86b1..b3a3af3 100644
--- a/libpsn00b/libc/memset.s
+++ b/libpsn00b/libc/memset.s
@@ -14,12 +14,12 @@
.type memset,@function
memset:
move $v0, $a0
- blez $a2, .exit
+ blez $a2, .Lexit
addi $a2, -1
sb $a1, 0($a0)
b memset
addiu $a0, 1
-.exit:
+.Lexit:
jr $ra
nop
\ No newline at end of file
diff --git a/libpsn00b/libc/start.s b/libpsn00b/libc/start.s
index d08a2c7..2cf6ed0 100644
--- a/libpsn00b/libc/start.s
+++ b/libpsn00b/libc/start.s
@@ -15,9 +15,9 @@ _start:
la $a0, .bss # What are the CORRECT symbols for BSS start and end?
la $a1, _end
-.clear_bss:
+.Lclear_bss:
sb $0 , 0($a0)
- blt $a0, $a1, .clear_bss
+ blt $a0, $a1, .Lclear_bss
addiu $a0, 1
la $a0, _end+4 # Initialize heap for malloc (does not use BIOS maalloc)
diff --git a/libpsn00b/lzp/compress.c b/libpsn00b/lzp/compress.c
index 33af08d..5f2b78c 100644
--- a/libpsn00b/lzp/compress.c
+++ b/libpsn00b/lzp/compress.c
@@ -3,6 +3,7 @@
#include <string.h>
#if LZP_USE_MALLOC == TRUE
#include <stdlib.h>
+#include <malloc.h>
#endif
#include "lzconfig.h"
diff --git a/libpsn00b/lzp/makefile b/libpsn00b/lzp/makefile
index befdc34..4f9974f 100644
--- a/libpsn00b/lzp/makefile
+++ b/libpsn00b/lzp/makefile
@@ -1,6 +1,6 @@
PREFIX = mipsel-unknown-elf-
-TARGET = liblzp.a
+TARGET = ../liblzp.a
CFILES = $(notdir $(wildcard ./*.c))
OFILES = $(addprefix build/,$(CFILES:.c=.o))
diff --git a/libpsn00b/makefile b/libpsn00b/makefile
index bcfc9a5..d4bba32 100644
--- a/libpsn00b/makefile
+++ b/libpsn00b/makefile
@@ -4,7 +4,7 @@
TOPTARGETS = all clean
-LIBDIRS = libc lzp psxgpu psxgte psxapi psxetc psxspu
+LIBDIRS = libc lzp psxgpu psxgte psxapi psxetc psxspu psxsio
$(TOPTARGETS): $(LIBDIRS)
diff --git a/libpsn00b/psxapi/stdio/getchar.s b/libpsn00b/psxapi/stdio/getchar.s
new file mode 100644
index 0000000..ad645c0
--- /dev/null
+++ b/libpsn00b/psxapi/stdio/getchar.s
@@ -0,0 +1,10 @@
+.set noreorder
+.section .text
+
+.global getchar
+.type getchar, @function
+getchar:
+ addiu $t2, $0, 0xa0
+ jr $t2
+ addiu $t1, $0, 0x3b
+ \ No newline at end of file
diff --git a/libpsn00b/psxapi/stdio/gets.s b/libpsn00b/psxapi/stdio/gets.s
new file mode 100644
index 0000000..ba423ef
--- /dev/null
+++ b/libpsn00b/psxapi/stdio/gets.s
@@ -0,0 +1,10 @@
+.set noreorder
+.section .text
+
+.global gets
+.type gets, @function
+gets:
+ addiu $t2, $0, 0xa0
+ jr $t2
+ addiu $t1, $0, 0x3d
+ \ No newline at end of file
diff --git a/libpsn00b/psxapi/stdio/putc.s b/libpsn00b/psxapi/stdio/putc.s
index 7c73241..1c6d916 100644
--- a/libpsn00b/psxapi/stdio/putc.s
+++ b/libpsn00b/psxapi/stdio/putc.s
@@ -1,9 +1,9 @@
.set noreorder
.section .text
-.global putchar
+.global putc
.type putc, @function
-putchar:
+putc:
addiu $t2, $0, 0xa0
jr $t2
addiu $t1, $0, 0x09
diff --git a/libpsn00b/psxapi/stdio/putchar.s b/libpsn00b/psxapi/stdio/putchar.s
new file mode 100644
index 0000000..a3f6c57
--- /dev/null
+++ b/libpsn00b/psxapi/stdio/putchar.s
@@ -0,0 +1,10 @@
+.set noreorder
+.section .text
+
+.global putchar
+.type putchar, @function
+putchar:
+ addiu $t2, $0, 0xa0
+ jr $t2
+ addiu $t1, $0, 0x3c
+ \ No newline at end of file
diff --git a/libpsn00b/psxapi/stdio/puts.s b/libpsn00b/psxapi/stdio/puts.s
new file mode 100644
index 0000000..96815eb
--- /dev/null
+++ b/libpsn00b/psxapi/stdio/puts.s
@@ -0,0 +1,10 @@
+.set noreorder
+.section .text
+
+.global puts
+.type puts, @function
+puts:
+ addiu $t2, $0, 0xa0
+ jr $t2
+ addiu $t1, $0, 0x3e
+ \ No newline at end of file
diff --git a/libpsn00b/psxapi/sys/exec.s b/libpsn00b/psxapi/sys/exec.s
new file mode 100644
index 0000000..dacce7e
--- /dev/null
+++ b/libpsn00b/psxapi/sys/exec.s
@@ -0,0 +1,10 @@
+.set noreorder
+
+.section .text
+
+.global Exec
+.type Exec, @function
+Exec:
+ addiu $t2, $0, 0xa0
+ jr $t2
+ addiu $t1, $0, 0x43 \ No newline at end of file
diff --git a/libpsn00b/psxetc/fntsort.c b/libpsn00b/psxetc/fntsort.c
index 29e7de5..3890ebb 100644
--- a/libpsn00b/psxetc/fntsort.c
+++ b/libpsn00b/psxetc/fntsort.c
@@ -36,8 +36,8 @@ char *FntSort(unsigned int *ot, char *pri, int x, int y, const char *text) {
pri = (char*)sprt;
tpage = (DR_TPAGE*)pri;
- setlen( tpage, 1 );
tpage->code[0] = _font_tpage;
+ setlen( tpage, 1 );
setcode( tpage, 0xe1 );
addPrim( ot, pri );
pri += sizeof(DR_TPAGE);
diff --git a/libpsn00b/psxetc/font.c b/libpsn00b/psxetc/font.c
index 3b0370b..2f062b7 100644
--- a/libpsn00b/psxetc/font.c
+++ b/libpsn00b/psxetc/font.c
@@ -22,7 +22,7 @@ void FntLoad(int x, int y) {
_font_tpage = getTPage( 0, 0, pos.x, 0 ) | 0x200;
LoadImage( &pos, tim.paddr );
- DrawSync();
+ DrawSync(0);
// Load font clut
pos = *tim.crect;
@@ -32,6 +32,6 @@ void FntLoad(int x, int y) {
_font_clut = getClut( pos.x, pos.y );
LoadImage( &pos, tim.caddr );
- DrawSync();
+ DrawSync(0);
} \ No newline at end of file
diff --git a/libpsn00b/psxetc/makefile b/libpsn00b/psxetc/makefile
index 676fc6e..fe29212 100644
--- a/libpsn00b/psxetc/makefile
+++ b/libpsn00b/psxetc/makefile
@@ -12,8 +12,8 @@ OFILES = $(addprefix build/,$(CFILES:.c=.o) $(AFILES:.s=.o))
INCLUDE = -I../include
-CFLAGS = -O2 -msoft-float -fno-builtin -nostdlib -Wa,--strip-local-absolute
-AFLAGS = -msoft-float --strip-local-absolute
+CFLAGS = -g -O2 -msoft-float -fno-builtin -nostdlib -Wa,--strip-local-absolute
+AFLAGS = -g -msoft-float --strip-local-absolute
CC = $(PREFIX)gcc
AS = $(PREFIX)as
diff --git a/libpsn00b/psxgpu/dmacallback.s b/libpsn00b/psxgpu/dmacallback.s
new file mode 100644
index 0000000..b2f86cf
--- /dev/null
+++ b/libpsn00b/psxgpu/dmacallback.s
@@ -0,0 +1,191 @@
+.set noreorder
+
+.include "hwregs_a.h"
+
+.section .text
+
+.global DMACallback
+.type DMACallback, @function
+DMACallback:
+
+ # a0 - DMA channel
+ # a1 - Callback function
+
+ addiu $sp, -8
+ sw $ra, 0($sp)
+
+ beqz $a1, .Lremove_cb # Remove callback if function is NULL
+ nop
+
+ addiu $sp, -8 # Install IRQ handler for DMA handler
+ sw $a0, 0($sp) # if not set installed yet
+ sw $a1, 4($sp)
+
+ jal GetInterruptCallback
+ li $a0, 3
+
+ bnez $v0, .Lskip_install
+ nop
+
+ la $a1, _dma_handler
+ jal InterruptCallback
+ li $a0, 3
+
+.Lskip_install:
+
+ lw $a0, 0($sp)
+ lw $a1, 4($sp)
+ addiu $sp, 8
+
+ la $v0, _dma_func_table
+ sll $v1, $a0, 2
+ addu $v0, $v1
+ lw $v1, 0($v0)
+ sw $a1, 0($v0)
+ sw $v1, 4($sp)
+
+ lui $a2, IOBASE
+
+ lw $v0, DICR($a2) # Enable DMA interrupt
+ lui $v1, 0x1
+ sll $v1, $a0
+ or $v0, $v1
+ lui $v1, 0x80
+ or $v0, $v1
+ sw $v0, DICR($a2)
+
+ b .Lskip_remove
+ nop
+
+.Lremove_cb:
+
+ la $v0, _dma_func_table # Set callback address
+ sll $v1, $a0, 2
+ addu $v0, $v1
+ lw $v1, 0($v0)
+ sw $a1, 0($v0)
+ sw $v1, 4($sp)
+
+ lui $a2, IOBASE # Disable DMA interrupt
+ lw $v0, DICR($a2)
+ lui $v1, 0x1
+ sll $v1, $a0
+ .set noat
+ addiu $at, $0, -1
+ xor $v1, $at
+ and $v0, $v1
+ lui $v1, 0x7f00
+ xor $v1, $at
+ and $v0, $v1
+ .set at
+ sw $v0, DICR($a2)
+
+ jal _dma_has_cb # Check if callbacks are present
+ nop
+ bnez $v0, .Lskip_remove
+ nop
+ sw $0 , DICR($a2)
+
+ jal GetInterruptCallback # Check if callback is the DMA handler
+ li $a0, 3
+ la $v1, _dma_handler
+ bne $v0, $v1, .Lskip_remove
+ nop
+
+ li $a0, 3
+ jal InterruptCallback
+ move $a1, $0
+
+.Lskip_remove:
+
+ lw $ra, 0($sp)
+ lw $v0, 4($sp)
+ jr $ra
+ addiu $sp, 8
+
+
+.type _dma_has_cb, @function
+_dma_has_cb:
+
+ la $v1, _dma_func_table
+ li $t0, 6
+
+.Lscan_loop:
+
+ lw $v0, 0($v1)
+ addiu $v1, 4
+ bnez $v0, .Lhas_cb
+ nop
+
+ bgtz $t0, .Lscan_loop
+ addiu $t0, -1
+
+ jr $ra
+ move $v0, $0
+
+.Lhas_cb:
+
+ jr $ra
+ li $v0, 1
+
+
+.type _dma_handler, @function
+_dma_handler:
+
+ addiu $sp, -12
+ sw $ra, 0($sp)
+ sw $s0, 4($sp)
+ sw $s1, 8($sp)
+
+ move $s0, $0
+ la $s1, _dma_func_table
+
+.Lhandler_loop:
+
+ lui $a0, IOBASE
+ lw $v0, DICR($a0)
+ li $v1, 24
+ addu $v1, $s0
+ srl $v0, $v1
+ andi $v0, 0x1
+
+ lw $v1, 0($s1)
+
+ beqz $v0, .Lno_irq
+ addiu $s1, 4
+
+ beqz $v1, .Lno_irq
+ nop
+
+ jalr $v1
+ nop
+
+.Lno_irq:
+
+ blt $s0, 6, .Lhandler_loop
+ addi $s0, 1
+
+ lui $a0, IOBASE
+ lw $v0, DICR($a0)
+ nop
+ sw $v0, DICR($a0)
+
+ lw $ra, 0($sp)
+ lw $s0, 4($sp)
+ lw $s1, 8($sp)
+
+ jr $ra
+ addiu $sp, -12
+
+
+.section .data
+
+_dma_func_table:
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ \ No newline at end of file
diff --git a/libpsn00b/psxgpu/drawotag.s b/libpsn00b/psxgpu/drawotag.s
index 8a5ff0c..ba771fc 100644
--- a/libpsn00b/psxgpu/drawotag.s
+++ b/libpsn00b/psxgpu/drawotag.s
@@ -13,20 +13,20 @@ DrawOTag:
lui $a3, 0x1f80 # I/O segment base
-.gpu_wait: # Wait for GPU to be ready for commands & DMA
+ lui $v0, 0x0400 # Set DMA direction to CPUtoGPU
+ ori $v0, 0x2
+ sw $v0, GP1($a3)
+
+.Lgpu_wait: # Wait for GPU to be ready for commands & DMA
jal ReadGPUstat
nop
srl $v0, 26
andi $v0, 1
- beqz $v0, .gpu_wait
+ beqz $v0, .Lgpu_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)
+ sw $0 , D2_BCR($a3)
lui $v0, 0x0100 # Begin OT transfer!
ori $v0, 0x0401
diff --git a/libpsn00b/psxgpu/drawprim.s b/libpsn00b/psxgpu/drawprim.s
new file mode 100644
index 0000000..a216720
--- /dev/null
+++ b/libpsn00b/psxgpu/drawprim.s
@@ -0,0 +1,40 @@
+.set noreorder
+
+.include "hwregs_a.h"
+
+.text
+
+.global DrawPrim
+.type DrawPrim, @function
+DrawPrim:
+
+ addiu $sp, -8
+ sw $ra, 0($sp)
+ sw $s0, 4($sp)
+
+ move $s0, $a0 # Wait for GPU to complete
+ jal DrawSync
+ move $a0, $0
+
+ lui $a3, IOBASE
+ lui $v0, 0x0400 # Set transfer direction to off
+ sw $v0, GP1($a3)
+
+ move $a0, $s0
+ lbu $a1, 3($a0) # Get length of primitive packet
+ addiu $a0, 4
+
+.Ltransfer_loop:
+ lw $v0, 0($a0)
+ addiu $a0, 4
+ sw $v0, GP0($a3)
+ bgtz $a1, .Ltransfer_loop
+ addiu $a1, -1
+
+ jal DrawSync
+ move $a0, $0
+
+ lw $ra, 0($sp)
+ lw $s0, 4($sp)
+ jr $ra
+ addiu $sp, 8 \ No newline at end of file
diff --git a/libpsn00b/psxgpu/drawsync.s b/libpsn00b/psxgpu/drawsync.s
index 149519d..66d37e2 100644
--- a/libpsn00b/psxgpu/drawsync.s
+++ b/libpsn00b/psxgpu/drawsync.s
@@ -8,19 +8,60 @@
.global DrawSync
.type DrawSync, @function
DrawSync:
+
+ bnez $a0, .Lgetwords
+ lui $a0, IOBASE
+
addiu $sp, -4
sw $ra, 0($sp)
-.gpu_wait: # Wait for GPU to be ready for commands and DMA
+ jal ReadGPUstat # Check if DMA enabled
+ nop
+ srl $v0, 29
+ andi $v0, 0x3
+
+ beqz $v0, .Lsimple_wait
+ nop
+
+.Ldma_wait:
+ lw $v0, D2_CHCR
+ nop
+ srl $v0, 24
+ andi $v0, 0x1
+ bnez $v0, .Ldma_wait
+ nop
+
+.Lgpu_wait:
jal ReadGPUstat
nop
- srl $v0, 0x1a
+ srl $v0, 26
andi $v0, 0x5
- li $v1, 5
- bne $v0, $v1, .gpu_wait
+ bne $v0, 5, .Lgpu_wait
+ nop
+
+ b .Lexit
nop
+
+.Lsimple_wait: # Wait for GPU to be ready for next DMA
+ jal ReadGPUstat
+ nop
+ srl $v0, 28
+ andi $v0, 0x1
+ beqz $v0, .Lsimple_wait
+ nop
+
+.Lexit:
lw $ra, 0($sp)
addiu $sp, 4
jr $ra
nop
+
+.Lgetwords:
+
+ lw $v0, D2_BCR($a0)
+ nop
+
+ jr $ra
+ srl $v0, 16
+ \ No newline at end of file
diff --git a/libpsn00b/psxgpu/drawsynccallback.s b/libpsn00b/psxgpu/drawsynccallback.s
new file mode 100644
index 0000000..c1e28fe
--- /dev/null
+++ b/libpsn00b/psxgpu/drawsynccallback.s
@@ -0,0 +1,103 @@
+.set noreorder
+
+.include "hwregs_a.h"
+
+.text
+
+.global DrawSyncCallback
+.type DrawSyncCallback, @function
+DrawSyncCallback:
+
+ addiu $sp, -8
+ sw $ra, 0($sp)
+ sw $a0, 4($sp)
+
+ jal EnterCriticalSection
+ nop
+
+ beqz $a0, .Luninstall
+ nop
+ la $a1, _drawsync_handler
+ jal DMACallback
+ li $a0, 2
+ b .Lcontinue
+ nop
+
+.Luninstall:
+
+ move $a1, $0
+ jal DMACallback
+ li $a0, 2
+
+.Lcontinue:
+
+ lw $a0, 4($sp)
+ la $v1, _drawsync_func
+ lw $v0, 0($v1)
+ sw $a0, 0($v1)
+ sw $v0, 4($sp)
+
+.Lexit:
+
+ jal ExitCriticalSection
+ nop
+
+ lw $ra, 0($sp)
+ lw $v0, 4($sp)
+ jr $ra
+ addiu $sp, 8
+
+
+.type _drawsync_handler, @function
+_drawsync_handler:
+
+.Ldma_wait:
+
+ la $v0, _drawsync_func
+ lw $v0, 0($v0)
+ nop
+ beqz $v0, .Lskip
+ nop
+
+ addiu $sp, -4
+ sw $ra, 0($sp)
+
+ lw $v0, D2_CHCR($a0)
+ nop
+ srl $v0, 24
+ andi $v0, 0x1
+
+ bnez $v0, .Ldma_wait
+ nop
+
+.Lgpu_wait:
+ jal ReadGPUstat
+ nop
+ srl $v0, 28
+ andi $v0, 0x1
+ beqz $v0, .Lgpu_wait
+ nop
+
+ la $v1, _drawsync_func
+ lw $v1, 0($v1)
+
+ lui $v0, 0x0400 # Set DMA direction to off
+ sw $v0, GP1($a0)
+
+ jalr $v1
+ nop
+
+ lw $ra, 0($sp)
+ addiu $sp, 4
+
+.Lskip:
+
+ jr $ra
+ nop
+
+
+.data
+
+_drawsync_func:
+ .word 0
+ \ No newline at end of file
diff --git a/libpsn00b/psxgpu/getinterruptcallback.s b/libpsn00b/psxgpu/getinterruptcallback.s
new file mode 100644
index 0000000..b465567
--- /dev/null
+++ b/libpsn00b/psxgpu/getinterruptcallback.s
@@ -0,0 +1,17 @@
+.set noreorder
+
+.section .text
+
+.global GetInterruptCallback
+.type GetInterruptCallback, @function
+GetInterruptCallback:
+
+ # a0 - Interrupt number
+
+ la $a1, _irq_func_table
+ sll $a0, 2
+ addu $a1, $a0
+
+ jr $ra
+ lw $v0, 0($a1)
+ \ No newline at end of file
diff --git a/libpsn00b/psxgpu/interruptcallback.s b/libpsn00b/psxgpu/interruptcallback.s
new file mode 100644
index 0000000..8e912d8
--- /dev/null
+++ b/libpsn00b/psxgpu/interruptcallback.s
@@ -0,0 +1,48 @@
+.set noreorder
+
+.include "hwregs_a.h"
+
+.section .text
+
+.global InterruptCallback
+.type InterruptCallback, @function
+InterruptCallback:
+
+ # a0 - Interrupt number
+ # a1 - Callback function
+
+ lui $a2, IOBASE
+
+ beqz $a1, .Ldisable_irq
+ nop
+
+ lw $v0, IMASK($a2) # Enable interrupt mask
+ li $v1, 1
+ sll $v1, $a0
+ or $v0, $v1
+
+ b .Lcont
+ sw $v0, IMASK($a2)
+
+.Ldisable_irq:
+
+.set noat
+ lw $v0, IMASK($a2) # Disable interrupt mask
+ li $v1, 1
+ sll $v1, $a0
+ addiu $at, $0 , -1
+ xor $v1, $at
+.set at
+ and $v0, $v1
+ sw $v0, IMASK($a2)
+
+.Lcont:
+
+ la $a2, _irq_func_table # Get address to IRQ function table
+
+ sll $v1, $a0, 2 # Compute the slot
+ addu $v1, $a2, $v1
+ lw $v0, 0($v1) # Get old handler address
+
+ jr $ra # Return and set new IRQ handler
+ sw $a1, 0($v1)
diff --git a/libpsn00b/psxgpu/loadimage.s b/libpsn00b/psxgpu/loadimage.s
index 2376b31..4a3b4e0 100644
--- a/libpsn00b/psxgpu/loadimage.s
+++ b/libpsn00b/psxgpu/loadimage.s
@@ -19,7 +19,7 @@ LoadImage:
lui $s0, 0x1f80 # Set I/O segment base address
-.gpu_wait: # Wait for GPU to be ready for commands and DMA
+.Lgpu_wait: # Wait for GPU to be ready for commands and DMA
jal ReadGPUstat
nop
srl $v0, 0x1a
@@ -27,7 +27,7 @@ LoadImage:
li $v1, 5
#srl $v0, 28
#andi $v0, 1
- bne $v0, $v1, .gpu_wait
+ bne $v0, $v1, .Lgpu_wait
nop
lui $v0, 0x400 # Set DMA direction to off
diff --git a/libpsn00b/psxgpu/putdispenv.s b/libpsn00b/psxgpu/putdispenv.s
index 0993e5c..4baa20e 100644
--- a/libpsn00b/psxgpu/putdispenv.s
+++ b/libpsn00b/psxgpu/putdispenv.s
@@ -32,53 +32,53 @@ PutDispEnv:
move $a1, $0 # To use as mode value
- bgt $a2, 560, .mode_640
+ bgt $a2, 560, .Lmode_640
nop
- bgt $a2, 400, .mode_512
+ bgt $a2, 400, .Lmode_512
nop
- bgt $a2, 352, .mode_384
+ bgt $a2, 352, .Lmode_384
nop
- bgt $a2, 280, .mode_320
+ bgt $a2, 280, .Lmode_320
nop
.set noat
-.mode_256:
+.Lmode_256:
li $at, 10
mult $at, $v1
li $a2, 0x24e
sll $v0, 2
add $a2, $v0
- b .mode_end
+ b .Lmode_end
li $v1, 0xa00
-.mode_320:
+.Lmode_320:
li $at, 8
mult $at, $v1
li $a2, 0x258
ori $a1, 0x01
sll $v0, 2
add $a2, $v0
- b .mode_end
+ b .Lmode_end
li $v1, 0xa00
-.mode_384:
+.Lmode_384:
li $at, 7
mult $at, $v1
li $a2, 0x21b
ori $a1, 0x64
sll $v0, 2
add $a2, $v0
- b .mode_end
+ b .Lmode_end
li $v1, 0xa80
-.mode_512:
+.Lmode_512:
li $at, 5
mult $at, $v1
li $a2, 0x267
ori $a1, 0x02
sll $v0, 2
add $a2, $v0
- b .mode_end
+ b .Lmode_end
li $v1, 0xa00
-.mode_640:
+.Lmode_640:
li $at, 4
mult $at, $v1
li $a2, 0x26c
@@ -86,15 +86,15 @@ PutDispEnv:
sll $v0, 2
add $a2, $v0
li $v1, 0xa00
-.mode_end:
+.Lmode_end:
.set at
mflo $v0
- bnez $v0, .no_default # Check if screen with is non zero
+ bnez $v0, .Lno_default # Check if screen with is non zero
nop
move $v0, $v1 # Use default if screen width is 0
-.no_default:
+.Lno_default:
addu $v0, $a2 # Apply horizontal display coordinates
sll $v0, 12
@@ -108,19 +108,19 @@ PutDispEnv:
lh $v0, DISP_dh($a0)
li $a2, 0x10
- ble $v0, 256, .mode_low
+ ble $v0, 256, .Lmode_low
nop
-.mode_high:
+.Lmode_high:
ori $a1, 0x04
-.mode_low:
+.Lmode_low:
lh $v0, DISP_sy($a0)
lh $v1, DISP_sh($a0)
add $a2, $v0
- bnez $v1, .no_default_vert
+ bnez $v1, .Lno_default_vert
nop
li $v1, 0xf0
-.no_default_vert:
+.Lno_default_vert:
add $v1, $a2
and $a2, 0x3ff
sll $v1, 10
@@ -134,28 +134,28 @@ PutDispEnv:
la $v0, _gpu_standard
lbu $v0, 0($v0)
nop
- beqz $v0, .config_ntsc
+ beqz $v0, .Lconfig_ntsc
nop
-.config_pal:
+.Lconfig_pal:
ori $a1, 0x08
-.config_ntsc:
+.Lconfig_ntsc:
lbu $v0, DISP_inter($a0)
lbu $v1, DISP_isrgb24($a0)
- beqz $v0, .no_inter
+ beqz $v0, .Lno_inter
nop
or $a1, 0x20
-.no_inter:
- beqz $v1, .no_rgb24
+.Lno_inter:
+ beqz $v1, .Lno_rgb24
nop
or $a1, 0x10
-.no_rgb24:
+.Lno_rgb24:
lbu $v0, DISP_inter($a0)
nop
- beqz $v0, .no_reverse
+ beqz $v0, .Lno_reverse
nop
or $a1, 0x80
-.no_reverse:
+.Lno_reverse:
lui $v0, 0x800 # Apply mode
or $a1, $v0
diff --git a/libpsn00b/psxgpu/putdrawenv.s b/libpsn00b/psxgpu/putdrawenv.s
index 69af437..c0d5676 100644
--- a/libpsn00b/psxgpu/putdrawenv.s
+++ b/libpsn00b/psxgpu/putdrawenv.s
@@ -97,7 +97,7 @@ PutDrawEnv:
lbu $v0, DRAW_isbg($a0)
nop
- beqz $v0, .no_fillVRAM
+ beqz $v0, .Lno_fillVRAM
nop
lw $v0, DRAW_isbg($a0) # FillVRAM
@@ -110,7 +110,7 @@ PutDrawEnv:
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
+ blt $v0, 511, .Lno_overflow # don't accept a height of 512
nop
li $v0, 511
@@ -118,19 +118,19 @@ PutDrawEnv:
andi $v1, 0xffff
or $v1, $v0
-.no_overflow:
+.Lno_overflow:
sw $v1, 28($a1) # 7
li $v0, 0x07ffffff # Packet header (length+terminator)
sw $v0, 0($a1)
-.no_fillVRAM:
+.Lno_fillVRAM:
-.gpu_wait: # Wait for GPU to become ready for commands and DMA
+.Lgpu_wait: # Wait for GPU to become ready for commands and DMA
jal ReadGPUstat
nop
srl $v0, 26
andi $v0, 1
- beqz $v0, .gpu_wait
+ beqz $v0, .Lgpu_wait
nop
jal DrawOTag
diff --git a/libpsn00b/psxgpu/readme.txt b/libpsn00b/psxgpu/readme.txt
index 0d44e72..8fe439b 100644
--- a/libpsn00b/psxgpu/readme.txt
+++ b/libpsn00b/psxgpu/readme.txt
@@ -23,39 +23,7 @@ Library header(s):
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.
-
- * (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
- 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.
+ implemented (but should be trivial).
* StoreImage() equivalent yet to be implemented.
-
-
-Changelog:
-
- 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 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
diff --git a/libpsn00b/psxgpu/setvideomode.s b/libpsn00b/psxgpu/setvideomode.s
index 718a4dd..4395f0a 100644
--- a/libpsn00b/psxgpu/setvideomode.s
+++ b/libpsn00b/psxgpu/setvideomode.s
@@ -30,13 +30,13 @@ SetVideoMode:
andi $a1, 0xf7 # Mask off PAL bit
la $v0, _gpu_standard
- beqz $a0, .set_done
+ beqz $a0, .Lset_done
sw $0 , 0($v0)
li $v1, 1
sw $v1, 0($v0)
- b .set_done
+ b .Lset_done
or $a1, 0x8
-.set_done:
+.Lset_done:
lui $v0, 0x800 # Apply new mode
or $a1, $v0
diff --git a/libpsn00b/psxgpu/vsynccallback.s b/libpsn00b/psxgpu/vsynccallback.s
index 1f96bbc..4be29c8 100644
--- a/libpsn00b/psxgpu/vsynccallback.s
+++ b/libpsn00b/psxgpu/vsynccallback.s
@@ -12,7 +12,7 @@ VSyncCallback:
sw $a0, 4($sp)
lw $a0, 4($sp)
- la $v0, _vsync_callback_func
+ la $v0, _vsync_cb_func
sw $a0, 0($v0)
jal ExitCriticalSection
diff --git a/libpsn00b/psxgte/readme.txt b/libpsn00b/psxgte/readme.txt
index 13b92b6..74951c5 100644
--- a/libpsn00b/psxgte/readme.txt
+++ b/libpsn00b/psxgte/readme.txt
@@ -33,7 +33,3 @@ Todo list:
be implemented.
* Various high level RotTransPersp style functions not yet implemented.
-
-Changelog:
-
- None thus far...
diff --git a/libpsn00b/psxgte/squareroot.s b/libpsn00b/psxgte/squareroot.s
index 71f40a9..a262d94 100644
--- a/libpsn00b/psxgte/squareroot.s
+++ b/libpsn00b/psxgte/squareroot.s
@@ -5,6 +5,8 @@
.section .text
+# Implementation based from Sony libs
+
.global SquareRoot12
.type SquareRoot12, @function
SquareRoot12:
@@ -12,7 +14,7 @@ SquareRoot12:
nop
nop
mfc2 $v0, C2_LZCR
- beq $v0, 32, $bad_sqr12
+ beq $v0, 32, .Lbad_sqr12
nop
andi $t0, $v0, 0x1
addiu $v1, $0 , -2
@@ -21,15 +23,15 @@ SquareRoot12:
sub $t1, $t2
sra $t1, 1
addi $t3, $t2, -24
- bltz $t3, $value_less12
+ bltz $t3, .Lvalue_less12
nop
sllv $t4, $a0, $t3
- b $value_greater12
-$value_less12:
+ b .Lvalue_greater12
+.Lvalue_less12:
addiu $t3, $0 , 24
sub $t3, $t2
srav $t4, $a0, $t3
-$value_greater12:
+.Lvalue_greater12:
addi $t4, -64
sll $t4, 1
la $t5, sqrt_table
@@ -37,18 +39,18 @@ $value_greater12:
lh $t5, 0($t5)
nop
- bltz $t1, $1594c
+ bltz $t1, .L1594c
nop
jr $ra
sllv $v0, $t5, $t1
-$1594c:
+.L1594c:
sub $t1, $0 , $t1
jr $ra
srl $v0, $t5, $t1
-$bad_sqr12:
+.Lbad_sqr12:
jr $ra
move $v0, $0
@@ -60,7 +62,7 @@ SquareRoot0:
nop
nop
mfc2 $v0, C2_LZCR
- beq $v0, 32, $bad_sqr
+ beq $v0, 32, .Lbad_sqr
nop
andi $t0, $v0, 0x1
addiu $v1, $0 , -2
@@ -69,15 +71,15 @@ SquareRoot0:
sub $t1, $t2
sra $t1, 1
addi $t3, $t2, -24
- bltz $t3, $value_less
+ bltz $t3, .Lvalue_less
nop
sllv $t4, $a0, $t3
- b $value_greater
-$value_less:
+ b .Lvalue_greater
+.Lvalue_less:
addiu $t3, $0 , 24
sub $t3, $t2
srav $t4, $a0, $t3
-$value_greater:
+.Lvalue_greater:
addi $t4, -64
sll $t4, 1
la $t5, sqrt_table
@@ -87,7 +89,7 @@ $value_greater:
sllv $t5, $t5, $t1
jr $ra
srl $v0, $t5, 12
-$bad_sqr:
+.Lbad_sqr:
jr $ra
move $v0, $0
diff --git a/libpsn00b/psxgte/vectornormals.s b/libpsn00b/psxgte/vectornormals.s
index 8907d43..49d949d 100644
--- a/libpsn00b/psxgte/vectornormals.s
+++ b/libpsn00b/psxgte/vectornormals.s
@@ -6,13 +6,12 @@
.section .text
+# Implementation based from Sony libs
.global VectorNormalS
.type VectorNormalS, @function
VectorNormalS:
- # Implementation ripped from Sony libs
-
lw $t0, 0($a0)
lw $t1, 4($a0)
lw $t2, 8($a0)
@@ -42,15 +41,15 @@ VectorNormalS:
sra $t6, 1
addiu $t3, $v1, -24
- bltz $t3, $value_neg
+ bltz $t3, .Lvalue_neg
nop
- b $value_pos
+ b .Lvalue_pos
sllv $t4, $v0, $t3
-$value_neg:
+.Lvalue_neg:
addiu $t3, $0 , 24
sub $t3, $v1
srav $t4, $v0, $t3
-$value_pos:
+.Lvalue_pos:
addi $t4, -64
sll $t4, 1
diff --git a/libpsn00b/psxsio/_sio_control.s b/libpsn00b/psxsio/_sio_control.s
new file mode 100644
index 0000000..bae7822
--- /dev/null
+++ b/libpsn00b/psxsio/_sio_control.s
@@ -0,0 +1,182 @@
+.set noreorder
+
+.include "hwregs_a.h"
+
+.section .text
+
+# Currently implemented serial control functions:
+#
+# cmd(a0) sub(a1)
+# 0 0 Get serial status
+# 0 1 Get control line status
+# 0 2 Get serial mode
+# 0 3 Get baud rate
+# 0 4 Read 1 byte
+# 1 1 Set serial control
+# 1 2 Set serial mode
+# 1 3 Set baud rate
+# 1 4 Write 1 byte
+# 2 0 Reset serial
+# 2 1 Acknowledge serial
+
+.global _sio_control
+.type _sio_control, @function
+_sio_control:
+
+ # a0 - command
+ # a1 - subcommand
+ # a2 - argument
+
+ lui $a3, IOBASE
+
+ beq $a0, $0, .Lcmd0
+ nop
+ beq $a0, 1, .Lcmd1
+ nop
+ beq $a0, 2, .Lcmd2
+ nop
+ jr $ra
+ nop
+
+
+.Lcmd0:
+
+ beq $a1, $0, .Lcmd0arg0
+ nop
+ beq $a1, 1, .Lcmd0arg1
+ nop
+ beq $a1, 2, .Lcmd0arg2
+ nop
+ beq $a1, 3, .Lcmd0arg3
+ nop
+ beq $a1, 4, .Lcmd0arg4
+ nop
+ jr $ra
+ nop
+
+.Lcmd0arg0: # Get SIO status
+
+ lhu $v0, SIO_STAT($a3)
+ nop
+
+ jr $ra
+ andi $v0, 0x3FF
+
+.Lcmd0arg1: # Get control line status
+
+ lhu $v1, SIO_CTRL($a3)
+ nop
+ srl $v0, $v1, 1
+ andi $v0, 0x1
+ srl $v1, 4
+ andi $v1, 0x2
+
+ jr $ra
+ or $v0, $v1
+
+
+.Lcmd0arg2: # Get serial mode
+
+ lhu $v0, SIO_MODE($a3)
+ nop
+ jr $ra
+ andi $v0, 0xFF
+
+.Lcmd0arg3:
+
+ lui $v1, 0x1f
+ lhu $v0, SIO_BAUD($a3)
+ ori $v1, 0xa400
+ div $v1, $v0
+ nop
+ nop
+ jr $ra
+ mflo $v0
+
+.Lcmd0arg4: # Serial RX read
+
+ lbu $v0, SIO_TXRX($a3)
+ nop
+ jr $ra
+ nop
+
+
+.Lcmd1:
+
+ beq $a1, 1, .Lcmd1arg1
+ nop
+ beq $a1, 2, .Lcmd1arg2
+ nop
+ beq $a1, 3, .Lcmd1arg3
+ nop
+ beq $a1, 4, .Lcmd1arg4
+ nop
+ jr $ra
+ nop
+
+.Lcmd1arg1:
+
+ andi $v0, $a2, 0x1CFF
+
+ jr $ra
+ sh $a2, SIO_CTRL($a3)
+
+.Lcmd1arg2:
+
+ jr $ra
+ sh $a2, SIO_MODE($a3)
+
+.Lcmd1arg3:
+
+ lui $v0, 0x1f
+ ori $v0, 0xa400
+ divu $v0, $a2
+ bnez $a2, .Lgood_baud
+ nop
+ jr $ra
+ nop
+
+.Lgood_baud:
+
+ mflo $v0
+ sh $v0, SIO_BAUD($a3)
+ nop
+ jr $ra
+ nop
+
+.Lcmd1arg4:
+
+ sb $a2, SIO_TXRX($a3)
+ nop
+ jr $ra
+ nop
+
+.Lcmd2:
+
+ beq $a1, $0 , .Lcmd2arg0
+ li $v0, 1
+ beq $a1, $v0, .Lcmd2arg1
+ nop
+ jr $ra
+ nop
+
+.Lcmd2arg0:
+
+ li $v0, 0x40
+ sh $v0, SIO_CTRL($a3)
+ sh $0 , SIO_MODE($a3)
+ sh $0 , SIO_BAUD($a3)
+ nop
+ jr $ra
+ nop
+
+.Lcmd2arg1:
+
+ lhu $v0, SIO_CTRL($a3)
+ nop
+ ori $v0, 0x10
+ sh $v0, SIO_CTRL($a3)
+ jr $ra
+ nop
+
+ \ No newline at end of file
diff --git a/libpsn00b/psxsio/makefile b/libpsn00b/psxsio/makefile
new file mode 100644
index 0000000..ecd6c65
--- /dev/null
+++ b/libpsn00b/psxsio/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 = ../libpsxsio.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/psxsio/siocons.c b/libpsn00b/psxsio/siocons.c
new file mode 100644
index 0000000..cd99d68
--- /dev/null
+++ b/libpsn00b/psxsio/siocons.c
@@ -0,0 +1,137 @@
+#include <stdio.h>
+#include <psxapi.h>
+#include <psxgpu.h>
+#include <psxsio.h>
+
+static void _sio_init() {
+}
+
+static int _sio_open(FCB *fcb, const char* file, int mode) {
+
+ fcb->diskid = 1;
+
+ return 0;
+
+}
+
+static int _sio_inout(FCB *fcb, int cmd) {
+
+ int i;
+
+ if(cmd == 2) { // Write
+
+ for(i=0; i<fcb->trns_len; i++) {
+ while(!(_sio_control(0, 0, 0) & SR_TXU));
+ _sio_control(1, 4, ((char*)fcb->trns_addr)[i]);
+ }
+
+ return fcb->trns_len;
+
+ } else if (cmd == 1) { // Read
+
+ for(i=0; i<fcb->trns_len; i++) {
+ while(!(_sio_control(0, 0, 0) & SR_RXRDY));
+ ((char*)fcb->trns_addr)[i] = _sio_control(0, 4, 0);
+ }
+
+ return fcb->trns_len;
+
+ }
+
+ return 0;
+
+}
+
+static int _sio_close(int h) {
+
+ return h;
+
+}
+
+static DCB _sio_dcb = {
+ "tty",
+ 0x3,
+ 0x1,
+ 0x0,
+ (void*)_sio_init, // init
+ (void*)_sio_open, // open
+ (void*)_sio_inout, // inout
+ _sio_close, // close
+ NULL, // ioctl
+ NULL, // read
+ NULL, // write
+ NULL, // erase
+ NULL, // undelete
+ NULL, // firstfile
+ NULL, // nextfile
+ NULL, // format
+ NULL, // chdir
+ NULL, // rename
+ NULL, // remove
+ NULL // testdevice
+};
+
+
+volatile void (*_sio_callback)(void) = NULL;
+
+extern void _sio_irq_handler(void);
+
+
+void AddSIO(int baud) {
+
+ _sio_control(2, 0, 0);
+ _sio_control(1, 2, MR_SB_01|MR_CHLEN_8|0x02);
+ _sio_control(1, 3, baud);
+ _sio_control(1, 1, CR_RXEN|CR_TXEN);
+
+ close(0);
+ close(1);
+
+ DelDev(_sio_dcb.name);
+ AddDev(&_sio_dcb);
+
+ open(_sio_dcb.name, 2);
+ open(_sio_dcb.name, 1);
+
+}
+
+void DelSIO(void) {
+
+ // Reset serial interface
+ _sio_control(2, 0, 0);
+
+ // Remove TTY device
+ DelDev(_sio_dcb.name);
+
+}
+
+void WaitSIO(void) {
+
+ while((_sio_control(0, 0, 0)&(SR_RXRDY)) != (SR_RXRDY));
+ _sio_control(0, 4, NULL);
+
+}
+
+void *Sio1Callback(void (*func)()) {
+
+ void *old_isr; //= *((int*)&_sio_callback);
+
+ EnterCriticalSection();
+
+ if( func ) {
+
+ old_isr = InterruptCallback(8, func);
+ //_sio_callback = func;
+
+ } else {
+
+ old_isr = InterruptCallback(8, NULL);
+ //_sio_callback = NULL;
+
+ }
+
+ ExitCriticalSection();
+
+ return old_isr;
+
+} \ No newline at end of file
diff --git a/libpsn00b/psxspu/readme.txt b/libpsn00b/psxspu/readme.txt
index 4cac976..3ed90d0 100644
--- a/libpsn00b/psxspu/readme.txt
+++ b/libpsn00b/psxspu/readme.txt
@@ -29,8 +29,3 @@ Todo list:
* SpuKeyOn() is actually not part of the official library.
* SPU reverb configuration functions yet to be implemented.
-
-
-Changelog:
-
- None so far...
diff --git a/libpsn00b/psxspu/spuinit.s b/libpsn00b/psxspu/spuinit.s
index fa5ec32..51a54ea 100644
--- a/libpsn00b/psxspu/spuinit.s
+++ b/libpsn00b/psxspu/spuinit.s
@@ -58,11 +58,11 @@ SpuInit:
li $a2, 23
-.clear_voices:
+.Lclear_voices:
jal SpuSetVoiceRaw
move $a0, $a2
addiu $a2, -1
- bgez $a2, .clear_voices
+ bgez $a2, .Lclear_voices
nop
li $v0, 0xffff # Set all keys to off
@@ -104,11 +104,11 @@ SpuInit:
SpuCtrlSync:
lui $v1, IOBASE
andi $a0, 0x3f
-.ctrl_wait:
+.Lctrl_wait:
lhu $v0, SPUSTAT($v1) # Get SPUSTAT value
nop
andi $v0, 0x3f
- bne $v0, $a0, .ctrl_wait # Wait until SPUCNT and SPUSTAT are equal
+ bne $v0, $a0, .Lctrl_wait # Wait until SPUCNT and SPUSTAT are equal
nop
jr $ra
nop
diff --git a/libpsn00b/psxspu/spusetkey.s b/libpsn00b/psxspu/spusetkey.s
index 1270b2a..25a6107 100644
--- a/libpsn00b/psxspu/spusetkey.s
+++ b/libpsn00b/psxspu/spusetkey.s
@@ -13,13 +13,13 @@ SpuSetKey:
lui $a2, IOBASE
- beqz $a0, .key_off
+ beqz $a0, .Lkey_off
nop
jr $ra
sh $a1, SPU_KEY_ON($v1)
-.key_off:
+.Lkey_off:
jr $ra
sh $a1, SPU_KEY_OFF($v1)
diff --git a/libpsn00b/psxspu/transfer.s b/libpsn00b/psxspu/transfer.s
index aed69dc..086bb3b 100644
--- a/libpsn00b/psxspu/transfer.s
+++ b/libpsn00b/psxspu/transfer.s
@@ -18,10 +18,10 @@ SpuSetTransferMode:
.type SpuSetTransferStartAddr, @function
SpuSetTransferStartAddr:
li $v0, 0x1000 # Check if value is valid
- blt $a0, $v0, .bad_value
+ blt $a0, $v0, .Lbad_value
nop
li $v0, 0xffff
- bgt $a0, $v0, .bad_value
+ bgt $a0, $v0, .Lbad_value
nop
la $v1, _spu_transfer_addr
@@ -31,7 +31,7 @@ SpuSetTransferStartAddr:
jr $ra
move $v0, $a0
-.bad_value:
+.Lbad_value:
jr $ra
move $v0, $0
@@ -67,11 +67,11 @@ SpuWrite:
lw $a0, 4($sp)
-.dma_wait: # Wait for SPU to be ready for DMA
+.Ldma_wait: # Wait for SPU to be ready for DMA
lhu $v0, SPUSTAT($a3)
nop
andi $v0, 0x400 # Bit 8 in SPUSTAT never changes to 1 on
- bnez $v0, .dma_wait # emulators so use bit 10 instead
+ bnez $v0, .Ldma_wait # emulators so use bit 10 instead
nop
sw $a0, D4_MADR($a3) # Set DMA source address