aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wilbert M. Villamor <lameguy64@gmail.com>2019-11-22 09:11:12 +0800
committerJohn Wilbert M. Villamor <lameguy64@gmail.com>2019-11-22 09:11:12 +0800
commitea46d05aed0343c20d8fdfaa0e67d54d51e8e2a0 (patch)
tree43e2a53f4e5f7f55b075cfc9d6dc7a652a7b0837
parentd80d92e13330d527ddb94420b19f9e21bf0e74eb (diff)
downloadpsn00bsdk-ea46d05aed0343c20d8fdfaa0e67d54d51e8e2a0.tar.gz
Added long awaited CD-ROM library and loads of fixes, see changelog for details
-rw-r--r--README.md15
-rw-r--r--changelog.txt41
-rw-r--r--doc/LibPSn00b Reference.odtbin113754 -> 114279 bytes
-rw-r--r--examples/cdxa/ball16c.h16
-rw-r--r--examples/cdxa/iso.xml29
-rw-r--r--examples/cdxa/main.c551
-rw-r--r--examples/cdxa/makefile60
-rw-r--r--examples/cdxa/system.cnf4
-rw-r--r--examples/childexec/parent.c5
-rw-r--r--examples/fpscam/makefile6
-rw-r--r--examples/gte/makefile2
-rw-r--r--examples/makefile2
-rw-r--r--examples/n00bdemo/makefile2
-rw-r--r--examples/rgb24/makefile4
-rw-r--r--examples/timer/main.c154
-rw-r--r--examples/timer/makefile39
-rw-r--r--libpsn00b/include/hwregs_a.h4
-rw-r--r--libpsn00b/include/psxapi.h58
-rw-r--r--libpsn00b/include/psxcd.h149
-rw-r--r--libpsn00b/include/psxgpu.h56
-rw-r--r--libpsn00b/include/psxsio.h3
-rw-r--r--libpsn00b/include/string.h4
-rw-r--r--libpsn00b/libc/readme.txt6
-rw-r--r--libpsn00b/libc/string.c6
-rw-r--r--libpsn00b/libpsxcd/_cd_control.s109
-rw-r--r--libpsn00b/libpsxcd/cdgetsector.s53
-rw-r--r--libpsn00b/libpsxcd/cdmix.s34
-rw-r--r--libpsn00b/libpsxcd/cdsearchfile.c663
-rw-r--r--libpsn00b/libpsxcd/makefile38
-rw-r--r--libpsn00b/libpsxcd/psxcd.c319
-rw-r--r--libpsn00b/libpsxcd/psxcd_asm.s520
-rw-r--r--libpsn00b/libpsxcd/readme.txt48
-rw-r--r--libpsn00b/makefile2
-rw-r--r--libpsn00b/psxapi/sys/adddummytty.s10
-rw-r--r--libpsn00b/psxapi/sys/getrcnt.s10
-rw-r--r--libpsn00b/psxapi/sys/resetrcnt.s10
-rw-r--r--libpsn00b/psxapi/sys/setrcnt.s10
-rw-r--r--libpsn00b/psxapi/sys/startrcnt.s10
-rw-r--r--libpsn00b/psxapi/sys/stoprcnt.s10
-rw-r--r--libpsn00b/psxgpu/drawsync.s4
-rw-r--r--libpsn00b/psxgpu/readme.txt8
-rw-r--r--libpsn00b/psxgpu/resetgraph.s2
-rw-r--r--libpsn00b/psxgte/readme.txt2
-rw-r--r--libpsn00b/psxsio/siocons.c76
-rw-r--r--libpsn00b/psxspu/spuinit.s2
-rw-r--r--libpsn00b/readme.txt136
-rw-r--r--tools/smxlink/main.cpp2
47 files changed, 3147 insertions, 147 deletions
diff --git a/README.md b/README.md
index 94f5e16..675c63e 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ performance reasons.
## Notable features
-As of libpsn00b run-time library v0.12b
+As of LibPSn00b run-time library v0.15b
* Extensive GPU support with polygon primitives, high-speed DMA VRAM
transfers and DMA ordering table processing. All video modes for both NTSC
@@ -43,8 +43,8 @@ As of libpsn00b run-time library v0.12b
* Stable interrupt service routine with easy to use 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 should play well with writing loader programs.
+ or kernel hacks used and should be compatible with HLE BIOS implementations.
+ Should also play well with writing loader programs.
* Complete Serial I/O support with SIOCONS driver for tty console access
through serial interface.
@@ -53,10 +53,11 @@ As of libpsn00b run-time library v0.12b
thanks to proper interrupt handling, no crude manual polling of controllers
in your main loop.
-* BIOS CD-ROM support with a custom initialization function that doesn't
- clear other DMA channel settings (such as GPU and SPU DMA) for easier
- initialization.
-
+* Full CD-ROM support with data reading, CD audio and XA audio playback.
+ Features built-in ISO9660 file system parser for locating files and
+ supports directories containing more than 30 files. Data streaming
+ should also be possible.
+
* Uses Sony SDK library syntax for familiarity to experienced programmers
and to make porting existing homebrew projects to PSn00bSDK easier.
diff --git a/changelog.txt b/changelog.txt
index 806e4b3..66b847b 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -2,6 +2,47 @@ PSn00bSDK changelog
Items that are lower in the log are more recently implemented.
+11-22-2019 by Lameguy64:
+
+* psxapi: Added root counter or timer functions and related definitions.
+
+* examples: Added timer example.
+
+* psxgpu: Added DR_AREA, DR_OFFSET and DR_TWIN primitives and accompanying
+ setDrawArea(), setDrawOffset() and setTexWindow() macros.
+
+* psxgpu: Added parenthesis to argument value in setlen(), setaddr() and
+ setcode() macros, preventing addPrims() from being used in a more
+ sensible manner (ie. addPrims(ot, sub_ot+3, sub_ot)).
+
+* examples: Added render2tex render to texture example.
+
+* psxspu: Fixed typo in spuinit.s on section specifier specifying a data
+ section instead of text section, resulting to jump to
+ non-instruction-aligned linker errors.
+
+* psxgpu: Increased ISR stack size to 2048 bytes.
+
+* psxsio: Added kbhit() to poll keyboard input asynchronously and stdin
+ is now buffered with an IRQ handler.
+
+* psxapi: Added AddDummyTty() (for psxsio DelSIO() fix).
+
+* psxsio: DelSIO() now calls AddDummyTty().
+
+* libc: Fixed bug in strncpy() not placing a NULL byte at end of string.
+
+* libc: Fixed strchr() and strrchr() declarations commented out in string.h.
+
+* libpsn00b: Added the long awaited libpsxcd library with cdxa example.
+ Documentation will come soon but existing libcd docs should be good
+ enough for awhile.
+
+* psxgpu: Fixed non functioning GPU DMA wait in DrawSync().
+
+* LibPSn00b run-time library is now officially 0.15b.
+
+
10-11-2019 by Lameguy64:
* psxetc: Added FntOpen(), FntPrint() and FntFlush() functions.
diff --git a/doc/LibPSn00b Reference.odt b/doc/LibPSn00b Reference.odt
index ab305d3..d12510c 100644
--- a/doc/LibPSn00b Reference.odt
+++ b/doc/LibPSn00b Reference.odt
Binary files differ
diff --git a/examples/cdxa/ball16c.h b/examples/cdxa/ball16c.h
new file mode 100644
index 0000000..c79f273
--- /dev/null
+++ b/examples/cdxa/ball16c.h
@@ -0,0 +1,16 @@
+unsigned int ball16c_size=192;
+unsigned char ball16c[] = {
+0x10,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0xc0,0x03,0x10,
+0x01,0x10,0x00,0x01,0x00,0x00,0x00,0x31,0xc6,0x73,0xce,0x94,0xd2,0x07,0x9d,
+0xd6,0xda,0x38,0xe3,0xef,0xbd,0x9b,0xef,0x8c,0xb1,0xc6,0x98,0xde,0xfb,0x4a,
+0xa9,0xa4,0x90,0xad,0xb5,0x00,0x00,0x8c,0x00,0x00,0x00,0xc0,0x03,0x00,0x01,
+0x04,0x00,0x10,0x00,0x00,0x00,0x10,0x22,0x12,0x02,0x00,0x00,0x00,0x10,0x32,
+0x33,0x23,0x11,0x04,0x00,0x00,0x23,0x55,0x66,0x35,0x72,0x47,0x00,0x20,0x52,
+0x86,0x68,0x36,0x12,0x97,0x0a,0x20,0x65,0xbb,0x8b,0x36,0x12,0x91,0x04,0x31,
+0x85,0xbb,0x68,0x35,0x12,0x97,0xdc,0x32,0x86,0x8b,0x56,0x35,0x73,0x97,0xa4,
+0x32,0x66,0x68,0x55,0x23,0x71,0x9e,0xac,0x32,0x65,0x56,0x33,0x13,0x71,0xce,
+0xa4,0x21,0x33,0x33,0x23,0x11,0xe7,0xc9,0xd4,0x12,0x22,0x22,0x13,0x71,0xe7,
+0xc9,0xda,0x10,0x17,0x11,0x77,0x77,0x9e,0x4c,0x0d,0x40,0x77,0x71,0xe7,0x9e,
+0xc9,0xd4,0x0d,0x00,0x94,0x99,0x99,0xcc,0x4c,0xda,0x00,0x00,0xa0,0xc4,0xc4,
+0x44,0xda,0x0d,0x00,0x00,0x00,0xd0,0xaa,0xda,0x0d,0x00,0x00
+};
diff --git a/examples/cdxa/iso.xml b/examples/cdxa/iso.xml
new file mode 100644
index 0000000..840b414
--- /dev/null
+++ b/examples/cdxa/iso.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<iso_project image_name="cdxa.iso">
+
+ <track type="data">
+
+ <identifiers
+ system ="PLAYSTATION"
+ application ="PLAYSTATION"
+ volume ="PSN00BSDK"
+ volume_set ="PSN00BSDK"
+ publisher ="MEIDOTEK"
+ />
+
+ <directory_tree>
+
+ <file name="system.cnf" type="data" source="system.cnf"/>
+ <file name="cdxa.exe" type="data" source="cdxa.exe"/>
+
+ <!-- CD-XA file, you'll have to provide your own to make this example work -->
+ <file name="xasample.xa" type="xa" source="D:\str-temp\subcon.xa"/>
+
+ <dummy sectors="1024"/>
+
+ </directory_tree>
+
+ </track>
+
+</iso_project>
diff --git a/examples/cdxa/main.c b/examples/cdxa/main.c
new file mode 100644
index 0000000..5d043eb
--- /dev/null
+++ b/examples/cdxa/main.c
@@ -0,0 +1,551 @@
+/*
+ * LibPSn00b Example Programs
+ *
+ * CD-XA Audio Example
+ * 2019 Meido-Tek Productions / PSn00bSDK Project
+ *
+ * Demonstrates playback and looping of CD-XA audio using the
+ * new libpsxcd library.
+ *
+ *
+ * Since there is not yet an open source XA audio encoder yet, the
+ * only way to create XA audio data is by using the official tools.
+ * You will have to provide your own XA file to get this example
+ * to work.
+ *
+ * You will also need MKPSXISO (https://github.com/lameguy64/mkpsxiso)
+ * to build an ISO image with your XA audio data.
+ *
+ *
+ * Theory of operation:
+ *
+ * CD-XA playback is accomplished by first locating the XA file in
+ * the ISO9660 file system using CdSearchFile(). CD mode is then set
+ * using the CdlSetmode command with CdlModeSpeed, CdlModeRT and
+ * CdlModeSF flags to configure the CD controller for XA audio
+ * streaming. Trying to play XA audio without CdlModeSF, which
+ * enables filtering, will feed all XA channels to the SPU resulting
+ * in a stuttery cacophony of sounds.
+ *
+ * The XA channel for playback is selected using the CdlSetfilter
+ * command and CdlFILTER struct. XA audio is usually comprised of
+ * multiple audio streams interleaved together and this command
+ * sets which channel to filter in from all the other channels.
+ * CdlModeSF enables the filtering feature and is required when
+ * playing back XA audio streams with multiple interleaved sound
+ * channels.
+ *
+ * Playback is initiated by issuing CdlReadS with the XA file's
+ * location specified as a parameter, which is internally issued
+ * to the CD controller as the seek target before CdlReadS is
+ * actually issued.
+ *
+ * Playback can be stopped by simply issuing CdlPause during playback.
+ * It is not recommended to use CdlStop as it will stop the disc spinning
+ * and result to much slower response once the disc has stopped.
+ *
+ * The most effective method of determining the end of an XA stream is
+ * by hooking a callback routine with CdReadyCallback(), which is
+ * triggered whenever a data sector has been read and checking the
+ * header of the received sector if it belongs to the channel currently
+ * being played.
+ *
+ * Additionally, XA audio data must be encoded with video sectors at
+ * the end of each XA stream to serve as a terminator marker which
+ * triggers CdReadyCallback() during playback. From within the callback
+ * a CdlReadS command with the location of the XA data can be issued again
+ * to repeat the track or CdlPause to stop playback.
+ *
+ *
+ * Tips:
+ *
+ * - For best efficiency, it is recommended to have all XA tracks in
+ * a single XA file have roughly the same length to one another,
+ * otherwise tracks that end short will be padded with empty sectors
+ * which wastes potentially usable disc space.
+ *
+ * - The CD filter can be changed during playback and the switchover is
+ * completely seamless. Use this trick to accomplish dynamic music
+ * effects that change seamlessly based on events during gameplay.
+ *
+ * - With custom tools, it is possible to interleave data sectors with
+ * a single XA audio stream which would permit music playback during
+ * loading sessions (aside from using sequenced music). Alternatively,
+ * CdlReadN can be used to begin playback but with more reliable data
+ * reading. This is also how streaming FMV sequences are accomplished.
+ *
+ *
+ * Pros over CD audio:
+ *
+ * - Does not require changing disc speed when switching between data
+ * access and audio playback.
+ *
+ * - Permits switching between streams during playback without restart.
+ *
+ * - Near 1:4 audio compression ratio.
+ *
+ * - Data sectors can be interleaved alongside XA audio.
+ *
+ *
+ * Cons compared to CD audio:
+ *
+ * - Skips more often on a poor condition disc or optical pick-up.
+ *
+ * - Cannot be played with any CD player.
+ *
+ * - Lower audio sample rate (37.8KHz whereas CD audio is 44.1KHz, not
+ * good for audiophools).
+ *
+ *
+ * Controls:
+ *
+ * Up/Down - Select channel.
+ * Cross - Play selected channel.
+ * Circle - Stop selected channel.
+ * Right - Switch channel (without restarting playback).
+ *
+ *
+ * Example by Lameguy64
+ *
+ *
+ * Changelog:
+ *
+ * November 22, 2019 - Initial version
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <psxetc.h>
+#include <psxgte.h>
+#include <psxgpu.h>
+#include <psxapi.h>
+#include <psxpad.h>
+#include <psxsio.h>
+#include <psxspu.h>
+#include <psxcd.h>
+
+#include <malloc.h>
+#include "ball16c.h"
+
+
+#define MAX_BALLS 1536 /* Number of balls to display */
+
+#define OT_LEN 8 /* Ordering table length */
+
+
+/* Screen coordinates */
+#define SCREEN_XRES 320
+#define SCREEN_YRES 240
+
+#define CENTER_X SCREEN_XRES/2
+#define CENTER_Y SCREEN_YRES/2
+
+
+/* Display and drawing environments */
+DISPENV disp[2];
+DRAWENV draw[2];
+
+char pribuff[2][65536]; /* Primitive packet buffers */
+unsigned int ot[2][OT_LEN]; /* Ordering tables */
+char *nextpri; /* Pointer to next packet buffer offset */
+int db = 0; /* Double buffer index */
+
+
+/* Ball struct and array */
+typedef struct BALL_TYPE
+{
+ short x,y;
+ short xdir,ydir;
+ unsigned char r,g,b,p;
+} BALL_TYPE;
+
+BALL_TYPE balls[MAX_BALLS];
+
+
+/* TIM image parameters for loading the ball texture and drawing sprites */
+TIM_IMAGE tim;
+
+
+/* XA audio handling stuff */
+volatile int num_loops=0; /* Loop counter */
+volatile int xa_play_channel; /* Currently playing channel number */
+CdlLOC xa_loc; /* XA data start location
+
+
+/* Sector header structure for video sector terminator */
+typedef struct SECTOR_HEAD
+{
+ u_short id;
+ u_short chan;
+ u_char pad[28];
+} SECTOR_HEAD;
+
+
+/* Pad input buffer*/
+char padbuff[2][34];
+
+char xa_sector_buff[2048];
+
+/* Callback for detecting end of channel (hooked by CdReadyCallback) */
+void xa_callback(int intr, unsigned char *result)
+{
+ SECTOR_HEAD *sec;
+
+ /* Only respond to data ready callbacks */
+ if (intr == CdlDataReady)
+ {
+ /* Fetch data sector */
+ CdGetSector((u_long*)&xa_sector_buff, 2048);
+
+ /* Quirk: This CdGetSector() implementation must fetch 2048 bytes */
+ /* or more otherwise the following sectors will be read in an */
+ /* incorrect byte order, probably due to stray data in the data */
+ /* FIFO. Trying to flush remaining bytes in the FIFO through */
+ /* memory reads after DMA transfer yields random deadlocking on */
+ /* real hardware for some reason. CdGetSector() probably reads */
+ /* the data FIFO in software rather than DMA transfer whereas */
+ /* CdGetSector2() uses DMA transfer in the official SDK. */
+
+ /* Check if sector belongs to the currently playing channel */
+ sec = (SECTOR_HEAD*)xa_sector_buff;
+
+ if( sec->id == 352 )
+ {
+ // Debug
+ //printf("ID=%d CHAN=%d PL=%d\n", sec->id, (sec->chan>>10)&0xF, xa_play_channel);
+
+ /* Check if sector is of the currently playing channel */
+ if( ((sec->chan>>10)&0xF) == xa_play_channel )
+ {
+ num_loops++;
+
+ /* Retry playback by seeking to start of XA data and stream */
+ CdControlF(CdlReadS, (u_char*)&xa_loc);
+
+ /* Stop playback */
+ //CdControlF(CdlPause, 0);
+ }
+ }
+ }
+}
+
+void init()
+{
+ int i;
+
+ /* Reset GPU (also installs event handler for VSync) */
+ printf("Init GPU... ");
+ ResetGraph( 0 );
+ printf("Done.\n");
+
+
+ /* Uncomment to direct tty messages to serial */
+ AddSIO(115200);
+
+
+ /* Initialize SPU and CD-ROM */
+ printf("Initializing CD-ROM... ");
+ SpuInit();
+ CdInit(0);
+ printf("Done.\n");
+
+
+ /* Set display and draw environment parameters */
+ SetDefDispEnv(&disp[0], 0, 0, SCREEN_XRES, SCREEN_YRES);
+ SetDefDispEnv(&disp[1], 0, SCREEN_YRES, SCREEN_XRES, SCREEN_YRES);
+
+ SetDefDrawEnv(&draw[0], 0, SCREEN_YRES, SCREEN_XRES, SCREEN_YRES);
+ SetDefDrawEnv(&draw[1], 0, 0, SCREEN_XRES, SCREEN_YRES);
+
+
+ /* Set clear color, area clear and dither processing */
+ setRGB0(&draw[0], 63, 0, 127);
+ draw[0].isbg = 1;
+ draw[0].dtd = 1;
+ setRGB0(&draw[1], 63, 0, 127);
+ draw[1].isbg = 1;
+ draw[1].dtd = 1;
+
+
+ /* Load and open font stream */
+ FntLoad(960, 0);
+ FntOpen(32, 32, 256, 176, 2, 200);
+
+
+ /* Upload the ball texture */
+ GetTimInfo((unsigned int*)ball16c, &tim); /* Get TIM parameters */
+ LoadImage(tim.prect, tim.paddr); /* Upload texture to VRAM */
+ if( tim.mode & 0x8 )
+ {
+ LoadImage(tim.crect, tim.caddr); /* Upload CLUT if present */
+ }
+
+
+ /* Calculate ball positions */
+ printf("Calculating balls... ");
+
+ for(i=0; i<MAX_BALLS; i++)
+ {
+ balls[i].x = (rand()%304);
+ balls[i].y = (rand()%224);
+ balls[i].xdir = 1-(rand()%3);
+ balls[i].ydir = 1-(rand()%3);
+ if( !balls[i].xdir )
+ balls[i].xdir = 1;
+ if( !balls[i].ydir )
+ balls[i].ydir = 1;
+ balls[i].xdir *= 2;
+ balls[i].ydir *= 2;
+ balls[i].r = (rand()%256);
+ balls[i].g = (rand()%256);
+ balls[i].b = (rand()%256);
+ }
+
+ printf("Done.\n");
+
+
+ /* Initialize pad */
+ InitPAD(padbuff[0], 34, padbuff[1], 34);
+ StartPAD();
+ ChangeClearPAD(0);
+
+}
+
+
+int main(int argc, const char* argv[])
+{
+
+ SPRT *spr;
+ SPRT_16 *sprt;
+ DR_TPAGE *tpri;
+ PADTYPE *pad;
+
+ CdlFILE file;
+ CdlFILTER filter;
+
+ int i,counter=0;
+ int sel_channel=0;
+ int p_up=0,p_down=0,p_right=0,p_cross=0,p_circle=0;
+
+
+ /* Init graphics and stuff before doing anything else */
+ init();
+
+ /* Locate the XA file */
+ if( !CdSearchFile(&file, "\\XASAMPLE.XA") )
+ {
+ printf("Unable to find file.\n");
+ return 0;
+ }
+ else
+ {
+ int sec;
+ sec = CdPosToInt(&file.loc);
+ printf("XA located at sector %d size %d.\n", sec, file.size);
+ }
+
+ /* Save file location as XA location */
+ xa_loc = file.loc;
+
+ /* Hook XA callback function to CdReadyCallback (for auto stop/loop */
+ CdReadyCallback(xa_callback);
+
+ /* Set CD mode for XA streaming (2x speed, send XA to SPU, enable filter */
+ i = CdlModeSpeed|CdlModeRT|CdlModeSF;
+ CdControl(CdlSetmode, (u_char*)&i, 0);
+
+ /* Set file 1 on filter for channels 0-7 */
+ filter.file = 1;
+
+ /* Main loop */
+ printf("Entering loop...\n");
+
+ while(1) {
+
+ pad = ((PADTYPE*)padbuff[0]);
+
+ if( pad->stat == 0 )
+ {
+ if(( pad->type == 0x4 )||( pad->type == 0x5 )||( pad->type == 0x7 ))
+ {
+ /* Menu selection controls */
+ if( !(pad->btn&PAD_UP) )
+ {
+ if( !p_up )
+ {
+ if( sel_channel > 0 )
+ {
+ sel_channel--;
+ }
+ p_up = 1;
+ }
+ }
+ else
+ {
+ p_up = 0;
+ }
+
+ if( !(pad->btn&PAD_DOWN) )
+ {
+ if( !p_down )
+ {
+ if( sel_channel < 7 )
+ {
+ sel_channel++;
+ }
+ p_down = 1;
+ }
+ }
+ else
+ {
+ p_down = 0;
+ }
+
+ /* Play selected XA channel from start */
+ if( !(pad->btn&PAD_CROSS) )
+ {
+ if( !p_cross )
+ {
+ filter.chan = sel_channel;
+ CdControl(CdlSetfilter, (u_char*)&filter, 0);
+ CdControl(CdlReadS, (u_char*)&xa_loc, 0);
+ xa_play_channel = sel_channel;
+ p_cross = 1;
+ }
+ }
+ else
+ {
+ p_cross = 0;
+ }
+
+ /* Stop playback */
+ if( !(pad->btn&PAD_CIRCLE) )
+ {
+ if( !p_circle )
+ {
+ CdControl(CdlPause, 0, 0);
+ p_circle = 1;
+ }
+ }
+ else
+ {
+ p_circle = 0;
+ }
+
+ /* Change XA channel */
+ if( !(pad->btn&PAD_RIGHT) )
+ {
+ if( !p_right )
+ {
+ filter.chan = sel_channel;
+ CdControl(CdlSetfilter, (u_char*)&filter, 0);
+ xa_play_channel = sel_channel;
+ p_right = 1;
+ }
+ }
+ else
+ {
+ p_right = 0;
+ }
+
+ }
+ }
+
+
+ /* Display information */
+ FntPrint(-1, "\n PSN00BSDK XA AUDIO EXAMPLE\n\n");
+ FntPrint(-1, " CHANNEL:\n");
+
+ for(i=0; i<8; i++)
+ {
+ if( i == sel_channel )
+ {
+ FntPrint(-1, " -->%d\n", i);
+ }
+ else
+ {
+ FntPrint(-1, " %d\n", i);
+ }
+ }
+
+ FntPrint(-1, "\n CURRENT=%d STATUS=%x LOOPS=%d\n",
+ xa_play_channel, CdStatus(), num_loops);
+ FntPrint(-1, "\n <X>-PLAY (START) <O>-STOP\n <R>-SET CHANNEL\n");
+
+
+ /* Clear ordering table and set start address of primitive buffer */
+ ClearOTagR(ot[db], OT_LEN);
+ nextpri = pribuff[db];
+
+
+ /* Sort the balls */
+ sprt = (SPRT_16*)nextpri;
+ for( i=0; i<MAX_BALLS; i++ ) {
+
+ setSprt16(sprt);
+ setXY0(sprt, balls[i].x, balls[i].y);
+ setRGB0(sprt, balls[i].r, balls[i].g, balls[i].b);
+ setUV0(sprt, 0, 0);
+ setClut(sprt, tim.crect->x, tim.crect->y);
+
+ addPrim(ot[db]+(OT_LEN-1), sprt);
+ sprt++;
+
+ balls[i].x += balls[i].xdir;
+ balls[i].y += balls[i].ydir;
+
+ if( ( balls[i].x+16 ) > SCREEN_XRES ) {
+ balls[i].xdir = -2;
+ } else if( balls[i].x < 0 ) {
+ balls[i].xdir = 2;
+ }
+
+ if( ( balls[i].y+16 ) > SCREEN_YRES ) {
+ balls[i].ydir = -2;
+ } else if( balls[i].y < 0 ) {
+ balls[i].ydir = 2;
+ }
+
+ }
+ nextpri = (char*)sprt;
+
+
+ /* Sort a TPage primitive so the sprites will draw pixels from */
+ /* the correct texture page in VRAM */
+ tpri = (DR_TPAGE*)nextpri;
+ setDrawTPage(tpri, 0, 0, getTPage(0, 0, tim.prect->x, tim.prect->y));
+ addPrim(ot[db]+(OT_LEN-1), tpri);
+ nextpri += sizeof(DR_TPAGE);
+
+ /* Draw font */
+ FntFlush(-1);
+
+ /* Wait for GPU and VSync */
+ DrawSync(0);
+ VSync(0);
+
+ /* Since draw.isbg is non-zero this clears the screen */
+ PutDispEnv(&disp[db]);
+ PutDrawEnv(&draw[db]);
+ SetDispMask(1);
+
+ /* Begin drawing the new frame */
+ DrawOTag( ot[db]+(OT_LEN-1) );
+
+ /* Alternate to the next buffer */
+ db = !db;
+
+ /* Periodically issue CdlNop every second to update CdStatus() */
+ counter++;
+ if( (counter%60) == 59 )
+ {
+ CdControl(CdlNop, 0, 0);
+ }
+
+ }
+
+ return 0;
+
+}
diff --git a/examples/cdxa/makefile b/examples/cdxa/makefile
new file mode 100644
index 0000000..c94f48c
--- /dev/null
+++ b/examples/cdxa/makefile
@@ -0,0 +1,60 @@
+include ../sdk-common.mk
+
+TARGET = cdxa.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))
+
+PREFIX = mipsel-unknown-elf-
+
+# Include directories
+INCLUDE = -I../../libpsn00b/include
+
+# Library directories, last entry must point toolchain libraries
+LIBDIRS = -L../../libpsn00b
+
+LIBDIRS += -L$(GCC_BASE)/lib/gcc/mipsel-unknown-elf/$(GCC_VERSION)
+INCLUDE += -I$(GCC_BASE)/lib/gcc/mipsel-unknown-elf/$(GCC_VERSION)/include
+
+LIBS = -lpsxcd -lpsxetc -lpsxgpu -lpsxgte -lpsxspu -lpsxsio -lpsxapi -lc
+
+CFLAGS = -g -O2 -fno-builtin -fdata-sections -ffunction-sections
+CPPFLAGS = $(CFLAGS) \
+ -fno-exceptions \
+ -fno-rtti \
+ -fno-unwind-tables \
+ -fno-threadsafe-statics \
+ -fno-use-cxa-atexit
+
+AFLAGS = -g -msoft-float
+LDFLAGS = -g -Ttext=0x80010000 -gc-sections \
+ -T $(GCC_BASE)/mipsel-unknown-elf/lib/ldscripts/elf32elmip.x
+
+CC = $(PREFIX)gcc
+CXX = $(PREFIX)g++
+AS = $(PREFIX)as
+LD = $(PREFIX)ld
+
+all: $(OFILES)
+ $(LD) $(LDFLAGS) $(LIBDIRS) $(OFILES) $(LIBS) -o $(TARGET)
+ elf2x -q $(TARGET)
+ mkpsxiso -y -q iso.xml
+
+build/%.o: %.c
+ @mkdir -p $(dir $@)
+ $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
+
+build/%.o: %.cpp
+ @mkdir -p $(dir $@)
+ $(CXX) $(CPPFLAGS) $(INCLUDE) -c $< -o $@
+
+build/%.o: %.s
+ @mkdir -p $(dir $@)
+ $(CC) $(AFLAGS) $(INCLUDE) -c $< -o $@
+
+clean:
+ make -C libpsxcd clean
+ rm -rf build $(TARGET) $(TARGET:.elf=.exe)
diff --git a/examples/cdxa/system.cnf b/examples/cdxa/system.cnf
new file mode 100644
index 0000000..e61e50e
--- /dev/null
+++ b/examples/cdxa/system.cnf
@@ -0,0 +1,4 @@
+BOOT=cdrom:\cdxa.exe;1
+TCB=4
+EVENT=10
+STACK=801FFFF0
diff --git a/examples/childexec/parent.c b/examples/childexec/parent.c
index dbaf696..7f577e4 100644
--- a/examples/childexec/parent.c
+++ b/examples/childexec/parent.c
@@ -223,7 +223,8 @@ int main(int argc, const char* argv[]) {
/* Sort a TPage primitive so the sprites will draw pixels from */
/* the correct texture page in VRAM */
tpri = (DR_TPAGE*)nextpri;
- setDrawTPage( tpri, 0, 0, tim.prect->x, tim.prect->y );
+ setDrawTPage( tpri, 0, 0,
+ getTPage( 0, 0, tim.prect->x, tim.prect->y ) );
addPrim( ot[db]+(OT_LEN-1), tpri );
nextpri += sizeof(DR_TPAGE);
@@ -301,4 +302,4 @@ void run_child() {
// Set this program's display mode
PutDispEnv(&disp);
-} \ No newline at end of file
+}
diff --git a/examples/fpscam/makefile b/examples/fpscam/makefile
index 67fe7c2..4f344eb 100644
--- a/examples/fpscam/makefile
+++ b/examples/fpscam/makefile
@@ -11,13 +11,7 @@ OFILES = $(addprefix build/,$(CFILES:.c=.o) $(CPPFILES:.cpp=.o) $(AFILES:.s=.o)
INCLUDE +=
LIBDIRS +=
-<<<<<<< .mine
LIBS = -lpsxetc -lpsxgpu -lpsxgte -lpsxspu -lpsxapi -lc
-||||||| .r23
-LIBS = -lc -lpsxetc -lpsxgpu -lpsxgte -lpsxspu -lpsxapi -lgcc
-=======
-LIBS = -lc -lpsxetc -lpsxgpu -lpsxgte -lpsxspu -lpsxapi -lc
->>>>>>> .r27
CFLAGS = -g -O2 -fno-builtin -fdata-sections -ffunction-sections
CPPFLAGS = $(CFLAGS) -fno-exceptions
diff --git a/examples/gte/makefile b/examples/gte/makefile
index 89b27d3..2be2374 100644
--- a/examples/gte/makefile
+++ b/examples/gte/makefile
@@ -11,7 +11,7 @@ OFILES = $(addprefix build/,$(CFILES:.c=.o) $(CPPFILES:.cpp=.o) $(AFILES:.s=.o)
INCLUDE +=
LIBDIRS +=
-LIBS = -lc -lpsxetc -lpsxgpu -lpsxgte -lpsxspu -lpsxapi -lgcc
+LIBS = -lc -lpsxetc -lpsxgpu -lpsxgte -lpsxspu -lpsxapi -lc
CFLAGS = -g -O2 -fno-builtin -fdata-sections -ffunction-sections
CPPFLAGS = $(CFLAGS) -fno-exceptions
diff --git a/examples/makefile b/examples/makefile
index dda76ce..4c4aadf 100644
--- a/examples/makefile
+++ b/examples/makefile
@@ -4,7 +4,7 @@
TOPTARGETS = all clean
-DIRS = balls gte n00bdemo
+DIRS = balls gte n00bdemo fpscam childexec render2tex rgb24 timer billboard
$(TOPTARGETS): $(DIRS)
diff --git a/examples/n00bdemo/makefile b/examples/n00bdemo/makefile
index 8159a22..96275fb 100644
--- a/examples/n00bdemo/makefile
+++ b/examples/n00bdemo/makefile
@@ -10,7 +10,7 @@ OFILES = $(addprefix build/,$(CFILES:.c=.o) $(AFILES:.s=.o))
INCLUDE += -I../../libpsn00b/lzp
LIBDIRS += -L../../libpsn00b/lzp
-LIBS = -llzp -lc -lpsxetc -lpsxgpu -lpsxgte -lpsxspu -lpsxapi -lgcc
+LIBS = -llzp -lc -lpsxetc -lpsxgpu -lpsxgte -lpsxspu -lpsxapi -lc
CFLAGS = -g -O2 -fno-builtin -fdata-sections -ffunction-sections
CPPFLAGS = $(CFLAGS) -fno-exceptions
diff --git a/examples/rgb24/makefile b/examples/rgb24/makefile
index ada9fbb..eea866d 100644
--- a/examples/rgb24/makefile
+++ b/examples/rgb24/makefile
@@ -11,12 +11,12 @@ OFILES = $(addprefix build/,$(CFILES:.c=.o) $(CPPFILES:.cpp=.o) $(AFILES:.s=.o)
INCLUDE +=
LIBDIRS +=
-LIBS = -lc -lpsxgpu -lpsxapi -lgcc
+LIBS = -lpsxgpu -lpsxapi -lc
CFLAGS = -g -O2 -fno-builtin -fdata-sections -ffunction-sections
CPPFLAGS = $(CFLAGS) -fno-exceptions
AFLAGS = -g -msoft-float
-LDFLAGS = -g -Ttext=0x80010000 -gc-sections
+LDFLAGS = -g -Ttext=0x80010000 -gc-sections -T $(GCC_BASE)/mipsel-unknown-elf/lib/ldscripts/elf32elmip.x
CC = $(PREFIX)gcc
CXX = $(PREFIX)g++
diff --git a/examples/timer/main.c b/examples/timer/main.c
new file mode 100644
index 0000000..7d9f7b3
--- /dev/null
+++ b/examples/timer/main.c
@@ -0,0 +1,154 @@
+#include <stdio.h>
+#include <psxgpu.h>
+#include <psxapi.h>
+#include <psxetc.h>
+
+/* OT and Packet Buffer sizes */
+#define OT_LEN 256
+#define PACKET_LEN 1024
+
+/* Screen resolution */
+#define SCREEN_XRES 320
+#define SCREEN_YRES 240
+
+/* Screen center position */
+#define CENTERX SCREEN_XRES>>1
+#define CENTERY SCREEN_YRES>>1
+
+
+/* Double buffer structure */
+typedef struct {
+ DISPENV disp; /* Display environment */
+ DRAWENV draw; /* Drawing environment */
+} DB;
+
+/* Double buffer variables */
+DB db[2];
+int db_active = 0;
+
+
+/* Function declarations */
+void init();
+void display();
+
+
+volatile int timer_calls = 0;
+volatile short *timer2_ctrl = (short*)0x1F801124;
+void timer_func()
+{
+ timer_calls++;
+}
+
+volatile int vsync_count = 0;
+volatile int tick_count = 0;
+volatile int tick_value = 0;
+
+void vsync_func()
+{
+ vsync_count++;
+ if( vsync_count > 60 )
+ {
+ tick_value = timer_calls-tick_count;
+ tick_count = timer_calls;
+ vsync_count = 0;
+ }
+}
+
+/* Main function */
+int main() {
+
+ int counter;
+
+ /* Init graphics and GTE */
+ init();
+
+
+ EnterCriticalSection();
+ //SetRCnt(RCntCNT2, 0xF040, RCntMdINTR);
+
+ // NTSC clock base
+ counter = 4304000/560;
+
+ // PAL clock base
+ //counter = 5163000/560;
+
+ SetRCnt(RCntCNT2, counter, RCntMdINTR);
+ *timer2_ctrl = 0x1E58;
+ InterruptCallback(6, timer_func);
+ StartRCnt(RCntCNT2);
+ ChangeClearRCnt(2, 0);
+ ExitCriticalSection();
+
+ VSyncCallback(vsync_func);
+
+ /* Main loop */
+ while( 1 ) {
+
+ FntPrint(-1, "TIMER COUNT=%d\n", timer_calls);
+ FntPrint(-1, "TICKS/SEC=%d\n", tick_value);
+
+ /* Swap buffers and draw text */
+ display();
+
+ }
+
+ return 0;
+
+}
+
+void init() {
+
+ /* Reset the GPU, also installs a VSync event handler */
+ ResetGraph( 0 );
+ //SetVideoMode(MODE_PAL);
+
+ /* Set display and draw environment areas */
+ /* (display and draw areas must be separate, otherwise hello flicker) */
+ SetDefDispEnv( &db[0].disp, 0, 0, SCREEN_XRES, SCREEN_YRES );
+ SetDefDrawEnv( &db[0].draw, SCREEN_XRES, 0, SCREEN_XRES, SCREEN_YRES );
+
+ /* Enable draw area clear and dither processing */
+ setRGB0( &db[0].draw, 63, 0, 127 );
+ db[0].draw.isbg = 1;
+ db[0].draw.dtd = 1;
+
+
+ /* Define the second set of display/draw environments */
+ SetDefDispEnv( &db[1].disp, SCREEN_XRES, 0, SCREEN_XRES, SCREEN_YRES );
+ SetDefDrawEnv( &db[1].draw, 0, 0, SCREEN_XRES, SCREEN_YRES );
+
+ //db[0].disp.screen.y = 24;
+ //db[1].disp.screen.y = 24;
+
+ setRGB0( &db[1].draw, 63, 0, 127 );
+ db[1].draw.isbg = 1;
+ db[1].draw.dtd = 1;
+
+
+ /* Apply the drawing environment of the first double buffer */
+ PutDrawEnv( &db[0].draw );
+
+ FntLoad(960, 0);
+ FntOpen(0, 8, 320, 216, 0, 100);
+
+}
+
+void display() {
+
+ FntFlush(-1);
+
+ /* Wait for GPU to finish drawing and vertical retrace */
+ DrawSync( 0 );
+ VSync( 0 );
+
+ /* Swap buffers */
+ db_active ^= 1;
+
+ /* Apply display/drawing environments */
+ PutDrawEnv( &db[db_active].draw );
+ PutDispEnv( &db[db_active].disp );
+
+ /* Enable display */
+ SetDispMask( 1 );
+
+} \ No newline at end of file
diff --git a/examples/timer/makefile b/examples/timer/makefile
new file mode 100644
index 0000000..0c1340d
--- /dev/null
+++ b/examples/timer/makefile
@@ -0,0 +1,39 @@
+include ../sdk-common.mk
+
+TARGET = timer.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 = -lpsxetc -lpsxgpu -lpsxgte -lpsxspu -lpsxapi -lc
+
+CFLAGS = -g -O2 -fno-builtin -fdata-sections -ffunction-sections
+CPPFLAGS = $(CFLAGS) -fno-exceptions
+AFLAGS = -g -msoft-float
+LDFLAGS = -g -Ttext=0x80010000 -gc-sections -T $(GCC_BASE)/mipsel-unknown-elf/lib/ldscripts/elf32elmip.x
+
+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 $@
+
+clean:
+ rm -rf build $(TARGET) $(TARGET:.elf=.exe)
diff --git a/libpsn00b/include/hwregs_a.h b/libpsn00b/include/hwregs_a.h
index 27cfc88..9d4313b 100644
--- a/libpsn00b/include/hwregs_a.h
+++ b/libpsn00b/include/hwregs_a.h
@@ -82,6 +82,10 @@
.set D2_BCR, 0x10a4
.set D2_CHCR, 0x10a8
+.set D3_MADR, 0x10b0
+.set D3_BCR, 0x10b4
+.set D3_CHCR, 0x10b8
+
.set D4_MADR, 0x10c0
.set D4_BCR, 0x10c4
.set D4_CHCR, 0x10c8
diff --git a/libpsn00b/include/psxapi.h b/libpsn00b/include/psxapi.h
index 9abcd0c..0953dc3 100644
--- a/libpsn00b/include/psxapi.h
+++ b/libpsn00b/include/psxapi.h
@@ -1,23 +1,38 @@
#ifndef __PSXAPI__
#define __PSXAPI__
-#define DescHW 0xf0000000
-#define DescSW 0xf4000000
-
-#define HwCARD (DescHW|0x11)
-#define HwCARD_1 (DescHW|0x12)
-#define HwCARD_0 (DescHW|0x13)
-#define SwCARD (DescHW|0x02)
-
-#define EvSpIOE 0x0004
-#define EvSpERROR 0x8000
-#define EvSpTIMOUT 0x0100
-#define EvSpNEW 0x0200
-
-#define EvMdINTR 0x1000
-#define EvMdNOINTR 0x2000
-
-typedef struct { // Device control block
+#define DescHW 0xf0000000
+#define DescSW 0xf4000000
+
+#define HwCARD (DescHW|0x11)
+#define HwCARD_1 (DescHW|0x12)
+#define HwCARD_0 (DescHW|0x13)
+#define SwCARD (DescHW|0x02)
+
+#define EvSpIOE 0x0004
+#define EvSpERROR 0x8000
+#define EvSpTIMOUT 0x0100
+#define EvSpNEW 0x0200
+
+#define EvMdINTR 0x1000
+#define EvMdNOINTR 0x2000
+
+// Root counter (timer) definitions
+#define DescRC 0xf2000000
+
+#define RCntCNT0 (DescRC|0x00)
+#define RCntCNT1 (DescRC|0x01)
+#define RCntCNT2 (DescRC|0x02)
+#define RCntCNT3 (DescRC|0x03)
+
+#define RCntMdINTR 0x1000 // Turns on IRQ
+#define RCntMdNOINTR 0x2000 // Polling mode
+#define RCntMdSC 0x0001 // IRQ when counter target
+#define RCntMdSP 0x0000
+#define RCntMdFR 0x0000
+#define RCntMdGATE 0x0010
+
+typedef struct { // Device control block
char *name;
int flags;
int ssize;
@@ -121,6 +136,7 @@ int chdir(const char *path);
int AddDev(DCB *dcb);
int DelDev(const char *name);
void ListDev(void);
+void AddDummyTty(void);
void EnterCriticalSection(void);
void ExitCriticalSection(void);
@@ -151,8 +167,14 @@ int _card_read(int chan, int sector, unsigned char *buf);
int _card_write(int chan, int sector, unsigned char *buf);
void _new_card(void);
+// Timers
+int SetRCnt(int spec, unsigned short target, int mode);
+int GetRCnt(int spec);
+int StartRCnt(int spec);
+int StopRCnt(int spec);
+int ResetRCnt(int spec);
-// Interrupt acknowledge control
+// BIOS IRQ acknowledge control
void ChangeClearPAD(int mode);
void ChangeClearRCnt(int t, int m);
diff --git a/libpsn00b/include/psxcd.h b/libpsn00b/include/psxcd.h
new file mode 100644
index 0000000..5bb1b5f
--- /dev/null
+++ b/libpsn00b/include/psxcd.h
@@ -0,0 +1,149 @@
+#ifndef _LIBPSXCD_H
+#define _LIBPSXCD_H
+
+#include <sys/types.h>
+
+/*
+ * CD-ROM control commands
+ */
+#define CdlNop 0x01 /* a.k.a. Getstat */
+#define CdlSetloc 0x02
+#define CdlPlay 0x03
+#define CdlForward 0x04
+#define CdlBackward 0x05
+#define CdlReadN 0x06
+#define CdlStandby 0x07 /* a.k.a. MotorOn */
+#define CdlStop 0x08
+#define CdlPause 0x09
+#define CdlInit 0x0A
+#define CdlMute 0x0B
+#define CdlDemute 0x0C
+#define CdlSetfilter 0x0D
+#define CdlSetmode 0x0E
+#define CdlGetparam 0x0F
+#define CdlGetlocL 0x10
+#define CdlGetlocP 0x11
+#define CdlSetsession 0x12 /* ORIGINAL CODE */
+#define CdlGetTN 0x13
+#define CdlGetTD 0x14
+#define CdlSeekL 0x15
+#define CdlSeekP 0x16
+#define CdlTest 0x19 /* ORIGINAL CODE */
+#define CdlReadS 0x1B
+
+/*
+ * CD-ROM status bits
+ */
+#define CdlStatError 0x01
+#define CdlStatStandby 0x02
+#define CdlStatSeekError 0x04
+#define CdlStatIdError 0x08 /* ORIGINAL CODE */
+#define CdlStatShellOpen 0x10
+#define CdlStatRead 0x20
+#define CdlStatSeek 0x40
+#define CdlStatPlay 0x80
+
+/*
+ * CD-ROM mode bits
+ */
+#define CdlModeDA 0x01
+#define CdlModeAP 0x02
+#define CdlModeRept 0x04
+#define CdlModeSF 0x08
+#define CdlModeSize0 0x10
+#define CdlModeSize1 0x20
+#define CdlModeRT 0x40
+#define CdlModeSpeed 0x80
+
+/*
+ * CD-ROM interrupt result values
+ */
+#define CdlNoIntr 0x00
+#define CdlDataReady 0x01
+#define CdlComplete 0x02
+#define CdlAcknowledge 0x03
+#define CdlDataEnd 0x04
+#define CdlDiskError 0x05
+
+#define btoi(b) ((b)/16*10+(b)%16) /* Convert BCD value to integer */
+#define itob(i) ((i)/10*16+(i)%10) /* Convert integer to BCD value */
+
+/*
+ * CD-ROM disc location struct
+ */
+typedef struct CdlLOC
+{
+ u_char minute;
+ u_char second;
+ u_char sector;
+ u_char track;
+} CdlLOC;
+
+/*
+ * CD-ROM audio attenuation struct (volume)
+ */
+typedef struct CdlATV
+{
+ u_char val0; /* L -> SPU L */
+ u_char val1; /* L -> SPU R */
+ u_char val2; /* R -> SPU R */
+ u_char val3; /* R -> SPU L */
+} CdlATV;
+
+/*
+ * CD-ROM file information struct
+ */
+typedef struct CdlFILE
+{
+ CdlLOC loc;
+ u_int size;
+ char name[16];
+} CdlFILE;
+
+typedef struct CdlFILTER
+{
+ u_char file;
+ u_char chan;
+ u_short pad;
+} CdlFILTER;
+
+/* Data callback */
+typedef void (*CdlCB)(int, unsigned char *);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int CdInit(int mode);
+
+CdlLOC *CdIntToPos(int i, CdlLOC *p);
+int CdPosToInt(CdlLOC *p);
+int CdGetToc(CdlLOC *toc);
+
+int CdControl(unsigned char com, unsigned char *param, unsigned char *result);
+int CdControlB(unsigned char com, unsigned char *param, unsigned char *result);
+int CdControlF(unsigned char com, unsigned char *param);
+int CdSync(int mode, unsigned char *result);
+unsigned int CdSyncCallback(CdlCB func);
+
+long CdReadyCallback(CdlCB func);
+int CdGetSector(void *madr, int size);
+
+CdlFILE *CdSearchFile(CdlFILE *loc, const char *filename);
+int CdRead(int sectors, unsigned int *buf, int mode);
+int CdReadSync(int mode, unsigned char *result);
+unsigned int CdReadCallback(CdlCB func);
+
+int CdStatus(void);
+int CdMode(void);
+
+int CdMix(CdlATV *vol);
+
+/* ORIGINAL CODE */
+long *CdAutoPauseCallback(void(*func)());
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBPSXCD_H */
diff --git a/libpsn00b/include/psxgpu.h b/libpsn00b/include/psxgpu.h
index 230775f..5f0798a 100644
--- a/libpsn00b/include/psxgpu.h
+++ b/libpsn00b/include/psxgpu.h
@@ -114,9 +114,9 @@
/*
* Primitive handling macros
*/
-#define setlen( p, _len ) ( ((P_TAG*)(p))->len = (unsigned char)_len )
-#define setaddr( p, _addr ) ( ((P_TAG*)(p))->addr = (unsigned int)_addr )
-#define setcode( p, _code ) ( ((P_TAG*)(p))->code = (unsigned char)_code )
+#define setlen( p, _len ) ( ((P_TAG*)(p))->len = (unsigned char)(_len) )
+#define setaddr( p, _addr ) ( ((P_TAG*)(p))->addr = (unsigned int)(_addr) )
+#define setcode( p, _code ) ( ((P_TAG*)(p))->code = (unsigned char)(_code) )
#define getlen( p ) ( ((P_TAG*)(p))->len )
#define getaddr( p ) ( ((P_TAG*)(p))->addr )
@@ -126,7 +126,7 @@
#define isendprim( p ) ((((P_TAG*)(p))->addr)==0xffffff)
#define addPrim( ot, p ) setaddr( p, getaddr( ot ) ), setaddr( ot, p )
-#define addPrims(ot, p0, p1) setaddr( p1, getaddr( ot ) ), setaddr( ot, p0 )
+#define addPrims( ot, p0, p1 ) setaddr( p1, getaddr( ot ) ), setaddr( ot, p0 )
#define catPrim( p0, p1 ) setaddr( p0, p1 )
#define termPrim( p ) setaddr( p, 0xffffff )
@@ -186,6 +186,22 @@
#define setFill( p ) setlen( p, 3 ), setcode( p, 0x02 )
+#define setDrawOffset( p, _x, _y ) \
+ setlen( p, 1 ), \
+ (p)->code[0] = (_x&0x3FF)|((_y&0x3FF)<<11), \
+ ((char*)(p)->code)[3] = 0xE5
+
+#define setDrawArea( p, r ) \
+ setlen( p, 2 ), \
+ (p)->code[0] = ((r)->x&0x3FF)|(((r)->y&0x1FF)<<10), \
+ (p)->code[1] = (((r)->x+(r)->w-1)&0x3FF)|((((r)->y+(r)->h-1)&0x1FF)<<10), \
+ ((char*)&(p)->code[0])[3] = 0xE3, \
+ ((char*)&(p)->code[1])[3] = 0xE4
+
+#define setTexWindow( p, r ) \
+ setlen( p, 1 ), \
+ (p)->code[0] = ((r)->w&0x1F)|(((r)->h&0x1F)<<5)|(((r)->x&0x1F)<<10)|(((r)->y&0x1F)<<15), \
+ ((char*)&(p)->code[0])[3] = 0xE2
/*
* Primitive definitions
@@ -427,34 +443,44 @@ typedef struct {
* VRAM fill and transfer primitive definitions
*/
-typedef struct {
+typedef struct DR_ENV {
unsigned int tag;
unsigned int code[15];
} DR_ENV;
-typedef struct {
+typedef struct DR_AREA {
+ unsigned int tag;
+ unsigned int code[2];
+} DR_AREA;
+
+typedef struct DR_OFFSET {
+ unsigned int tag;
+ unsigned int code[1];
+} DR_OFFSET;
+
+typedef struct DR_TWIN {
unsigned int tag;
unsigned int code[2];
} DR_TWIN;
-typedef struct {
+typedef struct DR_TPAGE {
unsigned int tag;
unsigned int code[1];
} DR_TPAGE;
-typedef struct { /* ORIGINAL */
+typedef struct DR_MASK { /* ORIGINAL */
unsigned int tag;
unsigned int code[1];
} DR_MASK;
-typedef struct { /* ORIGINAL */
+typedef struct FILL { /* 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 */
+typedef struct VRAM2VRAM { /* ORIGINAL */
unsigned int tag;
unsigned char p0,p1,p2,code;
unsigned short x0,y0;
@@ -465,18 +491,18 @@ typedef struct { /* ORIGINAL */
// General structs
-typedef struct {
+typedef struct RECT {
short x,y;
short w,h;
} RECT;
-typedef struct {
+typedef struct DISPENV_RAW {
unsigned int vid_mode; // Video mode
short vid_xpos,vid_ypos; // Video position (not framebuffer)
short fb_x,fb_y; // Framebuffer display position
} DISPENV_RAW;
-typedef struct {
+typedef struct DISPENV {
RECT disp;
RECT screen;
char isinter;
@@ -485,7 +511,7 @@ typedef struct {
char pad;
} DISPENV;
-typedef struct {
+typedef struct DRAWENV {
RECT clip; // Drawing area
short ofs[2]; // GPU draw offset (relative to draw area)
RECT tw; // Texture window (doesn't do anything atm)
@@ -497,7 +523,7 @@ typedef struct {
DR_ENV dr_env; // Draw mode packet area (used by PutDrawEnv)
} DRAWENV;
-typedef struct {
+typedef struct TIM_IMAGE {
unsigned int mode;
RECT *crect;
unsigned int *caddr;
diff --git a/libpsn00b/include/psxsio.h b/libpsn00b/include/psxsio.h
index df218ac..3f571d7 100644
--- a/libpsn00b/include/psxsio.h
+++ b/libpsn00b/include/psxsio.h
@@ -58,9 +58,10 @@ void *Sio1Callback(void (*func)(void));
// ORIGINAL
void WaitSIO(void);
+int kbhit();
#ifdef __cplusplus
}
#endif
-#endif \ No newline at end of file
+#endif
diff --git a/libpsn00b/include/string.h b/libpsn00b/include/string.h
index 9cd1d64..365d238 100644
--- a/libpsn00b/include/string.h
+++ b/libpsn00b/include/string.h
@@ -29,8 +29,8 @@ char *strncat(char *s , const char *append, int n);
char *strcpy(char *dst , const char *src);
char *strncpy(char *dst , const char *src , int n);
int strlen(const char *s);
-//char *strchr(const char *s , int c);
-//char *strrchr(const char *s , int c);
+char *strchr(const char *s , int c);
+char *strrchr(const char *s , int c);
void *memmove(void *dst , const void *src , int n);
void *memchr(void *s , int c , int n);
diff --git a/libpsn00b/libc/readme.txt b/libpsn00b/libc/readme.txt
index 064a353..5bef0fd 100644
--- a/libpsn00b/libc/readme.txt
+++ b/libpsn00b/libc/readme.txt
@@ -32,12 +32,6 @@ Library header(s):
Todo list:
-
- * Current vsprintf/sprintf implementation from PSXSDK needs to be replaced
- as it performs quite slow likely due to the unnecessary int64 arithmetic
- performed on any integer value which the compiler has to emulate on the
- R3000. A more efficient implementation that only uses int32 is much
- preferred.
* Many of the string manipulation and memory fill functions in string.c
are yet to be replaced with more efficient assembly implementations.
diff --git a/libpsn00b/libc/string.c b/libpsn00b/libc/string.c
index a14d950..0b7307d 100644
--- a/libpsn00b/libc/string.c
+++ b/libpsn00b/libc/string.c
@@ -43,7 +43,7 @@ char *strncpy(char *dst, const char *src, int len)
len--;
}
- if(len)*dst = 0;
+ *dst = 0;
return odst;
}
@@ -139,13 +139,13 @@ char *strstr(const char *big, const char *little)
int strcmp(const char *s1, const char *s2)
{
- while(*s1 && *s2 && (*s1 == *s2))
+ while((*s1) && (*s2) && (*s1 == *s2))
{
s1++;
s2++;
}
- return *s1-*s2;
+ return(*s1-*s2);
}
int strncmp(const char *s1, const char *s2, int len)
diff --git a/libpsn00b/libpsxcd/_cd_control.s b/libpsn00b/libpsxcd/_cd_control.s
new file mode 100644
index 0000000..7f69266
--- /dev/null
+++ b/libpsn00b/libpsxcd/_cd_control.s
@@ -0,0 +1,109 @@
+.set noreorder
+
+.include "hwregs_a.h"
+
+.section .text
+
+#
+# Issues command and parameter bytes to CD controller directly
+#
+.global _cd_control
+.type _cd_control, @function
+_cd_control:
+
+ # a0 - command value
+ # a1 - pointer to parameters
+ # a2 - length of parameters
+
+ li $v0, 1 # Set acknowledge wait flag
+ la $v1, _cd_ack_wait
+ sb $v0, 0($v1)
+
+ # Commands that have a 'completion' interrupt (CDIRQ2)
+
+ beq $a0, 0x07, .Lset_complete # CdlStandby
+ nop
+ beq $a0, 0x08, .Lset_complete # CdlStop
+ nop
+ beq $a0, 0x09, .Lset_complete # CdlPause
+ nop
+ beq $a0, 0x0A, .Lset_complete # CdlInit
+ nop
+ beq $a0, 0x12, .Lset_complete # CdlSetsession
+ nop
+ beq $a0, 0x15, .Lset_complete # CdlSeekL
+ nop
+ beq $a0, 0x16, .Lset_complete # CdlSeekP
+ nop
+ beq $a0, 0x1A, .Lset_complete # GetID
+ nop
+ beq $a0, 0x1D, .Lset_complete # GetQ
+ nop
+
+ la $v1, _cd_complt_wait # Set wait complete flag
+ sb $0 , 0($v1)
+
+ b .Lno_complete
+ nop
+
+.Lset_complete:
+
+ la $v1, _cd_complt_wait # Set wait complete flag
+ sb $v0, 0($v1)
+
+.Lno_complete:
+
+ bne $a0, 0x0E, .Lnot_mode
+ lbu $v0, 0($a1)
+ la $v1, _cd_last_mode
+ sb $v0, 0($v1)
+
+.Lnot_mode:
+
+ la $v1, _cd_last_int # Clear last IRQ value
+ sb $0 , 0($v1)
+
+ la $v1, _cd_last_cmd # Save command as last command
+ sb $a0, 0($v1)
+
+ lui $v1, IOBASE
+
+.Lbusy_wait:
+ lbu $v0, CD_REG0($v1)
+ nop
+ andi $v0, 0x80
+ bnez $v0, .Lbusy_wait
+ nop
+
+ li $v0, 1 # Clear parameter FIFO (in case it wasn't cleared)
+ sb $v0, CD_REG0($v1)
+ li $v0, 0x40
+ sb $v0, CD_REG3($v1)
+
+.Lcmd_wait: # Wait for CD to become ready for commands
+ lbu $v0, CD_REG0($v1)
+ nop
+ andi $v0, 0x80
+ bnez $v0, .Lcmd_wait
+ nop
+
+ sb $0 , CD_REG0($v1)
+
+ beqz $a2, .Lno_params
+ nop
+
+.Lfeed_params: # Feed parameters to parameter FIFO
+ lbu $v0, 0($a1)
+ addi $a2, -1
+ sb $v0, CD_REG2($v1)
+ bgtz $a2, .Lfeed_params
+ addiu $a1, 1
+
+.Lno_params:
+
+ sb $0 , CD_REG0($v1) # Feed command value
+ sb $a0, CD_REG1($v1)
+
+ jr $ra
+ nop
+ \ No newline at end of file
diff --git a/libpsn00b/libpsxcd/cdgetsector.s b/libpsn00b/libpsxcd/cdgetsector.s
new file mode 100644
index 0000000..70039bf
--- /dev/null
+++ b/libpsn00b/libpsxcd/cdgetsector.s
@@ -0,0 +1,53 @@
+.set noreorder
+
+.include "hwregs_a.h"
+
+.section .text
+
+.global CdGetSector
+.type CdGetSector, @function
+CdGetSector:
+
+ lui $a2, IOBASE
+
+.Lwait_fifo:
+ lbu $v0, CD_REG0($a2)
+ nop
+ andi $v0, 0x40
+ beqz $v0, .Lwait_fifo
+ nop
+
+ lui $v0, 0x1
+ srl $a1, 2
+ or $v0, $a1
+ sw $a0, D3_MADR($a2) # Set DMA base address and transfer length
+ sw $v0, D3_BCR($a2)
+
+ lui $v0, 0x1100 # Start DMA transfer
+ sw $v0, D3_CHCR($a2)
+ nop
+ nop
+.Ldma_wait:
+ lw $v0, D3_CHCR($a2)
+ nop
+ srl $v0, 24
+ andi $v0, 0x1
+ bnez $v0, .Ldma_wait
+ nop
+
+# Not stable
+# sb $0 , CD_REG0($a2)
+#.Lflush_fifo: # Read out any remaining bytes in the buffer
+# lbu $v1, CD_REG0($a2)
+# li $v0, 0x40
+# and $v1, $v0
+# beqz $v1, .Lend_flush
+# nop
+# lbu $v0, CD_REG2($a2)
+# b .Lflush_fifo
+# nop
+#.Lend_flush:
+
+ jr $ra
+ li $v0, 1
+
diff --git a/libpsn00b/libpsxcd/cdmix.s b/libpsn00b/libpsxcd/cdmix.s
new file mode 100644
index 0000000..745fb65
--- /dev/null
+++ b/libpsn00b/libpsxcd/cdmix.s
@@ -0,0 +1,34 @@
+.set noreorder
+
+.include "hwregs_a.h"
+
+.section .text
+
+
+.global CdMix
+.type CdMix, @function
+CdMix:
+
+ lui $a3, IOBASE
+
+ lbu $t0, 0($a0)
+ lbu $t1, 1($a0)
+ lbu $t2, 2($a0)
+ lbu $t3, 3($a0)
+
+ li $v0, 2
+ sb $v0, CD_REG0($a3)
+ sb $t0, CD_REG2($a3)
+ sb $t1, CD_REG3($a3)
+
+ li $v0, 3
+ sb $v0, CD_REG0($a3)
+ sb $t2, CD_REG1($a3)
+ sb $t3, CD_REG2($a3)
+
+ li $v0, 0x20
+ sb $v0, CD_REG3($a3)
+
+ jr $ra
+ li $v0, 1
+ \ No newline at end of file
diff --git a/libpsn00b/libpsxcd/cdsearchfile.c b/libpsn00b/libpsxcd/cdsearchfile.c
new file mode 100644
index 0000000..60e4377
--- /dev/null
+++ b/libpsn00b/libpsxcd/cdsearchfile.c
@@ -0,0 +1,663 @@
+#include <stdio.h>
+#include <malloc.h>
+#include <string.h>
+#include <psxgpu.h>
+#include <psxsio.h>
+#include "psxcd.h"
+
+// Uncommend to enable debug output
+//#define DEBUG
+
+#pragma pack(push, 1)
+
+/// Structure of a double-endian unsigned short word
+typedef struct ISO_USHORT_PAIR
+{
+ unsigned short lsb; /// LSB format 16-bit word
+ unsigned short msb; /// MSB format 16-bit word
+} ISO_USHORT_PAIR;
+
+/// Structure of a double-endian unsigned int word
+typedef struct ISO_UINT_PAIR
+{
+ unsigned int lsb; /// LSB format 32-bit word
+ unsigned int msb; /// MSB format 32-bit word
+} ISO_UINT_PAIR;
+
+/// ISO descriptor header structure
+typedef struct ISO_DESCRIPTOR_HEADER
+{
+ unsigned char type; /// Volume descriptor type (1 is descriptor, 255 is descriptor terminator)
+ char id[5]; /// Volume descriptor ID (always CD001)
+ unsigned short version; /// Volume descriptor version (always 0x01)
+} ISO_DESCRIPTOR_HEADER;
+
+/// Structure of a date stamp for ISO_DIR_ENTRY structure
+typedef struct ISO_DATESTAMP
+{
+ unsigned char year; /// number of years since 1900
+ unsigned char month; /// month, where 1=January, 2=February, etc.
+ unsigned char day; /// day of month, in the range from 1 to 31
+ unsigned char hour; /// hour, in the range from 0 to 23
+ unsigned char minute; /// minute, in the range from 0 to 59
+ unsigned char second; /// Second, in the range from 0 to 59
+ unsigned char GMToffs; /// Greenwich Mean Time offset
+} ISO_DATESTAMP;
+
+/// Structure of an ISO path table entry (specifically for the cd::IsoReader class)
+typedef struct ISO_PATHTABLE_ENTRY
+{
+ unsigned char nameLength; /// Name length (or 1 for the root directory)
+ unsigned char extLength; /// Number of sectors in extended attribute record
+ unsigned int dirOffs; /// Number of the first sector in the directory, as a double word
+ unsigned short dirLevel; /// Index of the directory record's parent directory
+ /// If nameLength is odd numbered, a padding byte will be present after the identifier text.
+} ISO_PATHTABLE_ENTRY;
+
+typedef struct ISO_DIR_ENTRY
+{
+ unsigned char entryLength; // Directory entry length (variable, use for parsing through entries)
+ unsigned char extLength; // Extended entry data length (always 0)
+ ISO_UINT_PAIR entryOffs; // Points to the LBA of the file/directory entry
+ ISO_UINT_PAIR entrySize; // Size of the file/directory entry
+ ISO_DATESTAMP entryDate; // Date & time stamp of entry
+ unsigned char flags; // File flags (0x02 for directories, 0x00 for files)
+ unsigned char fileUnitSize; // Unit size (usually 0 even with Form 2 files such as STR/XA)
+ unsigned char interleaveGapSize; // Interleave gap size (usually 0 even with Form 2 files such as STR/XA)
+ ISO_USHORT_PAIR volSeqNum; // Volume sequence number (always 1)
+ unsigned char identifierLen; // Identifier (file/directory name) length in bytes
+} ISO_DIR_ENTRY;
+
+typedef struct ISO_ROOTDIR_HEADER
+{
+ unsigned char entryLength; // Always 34 bytes
+ unsigned char extLength; // Always 0
+ ISO_UINT_PAIR entryOffs; // Should point to LBA 22
+ ISO_UINT_PAIR entrySize; // Size of entry extent
+ ISO_DATESTAMP entryDate; // Record date and time
+ unsigned char flags; // File flags
+ unsigned char fileUnitSize;
+ unsigned char interleaveGapSize;
+ ISO_USHORT_PAIR volSeqNum;
+ unsigned char identifierLen; // 0x01
+ unsigned char identifier; // 0x00
+} ISO_ROOTDIR_HEADER;
+
+// ISO descriptor structure
+typedef struct ISO_DESCRIPTOR
+{
+
+ // ISO descriptor header
+ ISO_DESCRIPTOR_HEADER header;
+ // System ID (always PLAYSTATION)
+ char systemID[32];
+ // Volume ID (or label, can be blank or anything)
+ char volumeID[32];
+ // Unused null bytes
+ unsigned char pad2[8];
+ // Size of volume in sector units
+ ISO_UINT_PAIR volumeSize;
+ // Unused null bytes
+ unsigned char pad3[32];
+ // Number of discs in this volume set (always 1 for single volume)
+ ISO_USHORT_PAIR volumeSetSize;
+ // Number of this disc in volume set (always 1 for single volume)
+ ISO_USHORT_PAIR volumeSeqNumber;
+ // Size of sector in bytes (always 2048 bytes)
+ ISO_USHORT_PAIR sectorSize;
+ // Path table size in bytes (applies to all the path tables)
+ ISO_UINT_PAIR pathTableSize;
+ // LBA to Type-L path table
+ unsigned int pathTable1Offs;
+ // LBA to optional Type-L path table (usually a copy of the primary path table)
+ unsigned int pathTable2Offs;
+ // LBA to Type-L path table but with MSB format values
+ unsigned int pathTable1MSBoffs;
+ // LBA to optional Type-L path table but with MSB format values (usually a copy of the main path table)
+ unsigned int pathTable2MSBoffs;
+ // Directory entry for the root directory (similar to a directory entry)
+ ISO_ROOTDIR_HEADER rootDirRecord;
+ // Volume set identifier (can be blank or anything)
+ char volumeSetIdentifier[128];
+ // Publisher identifier (can be blank or anything)
+ char publisherIdentifier[128];
+ // Data preparer identifier (can be blank or anything)
+ char dataPreparerIdentifier[128];
+ // Application identifier (always PLAYSTATION)
+ char applicationIdentifier[128];
+ // Copyright file in the file system identifier (can be blank or anything)
+ char copyrightFileIdentifier[37];
+ // Abstract file in the file system identifier (can be blank or anything)
+ char abstractFileIdentifier[37];
+ // Bibliographical file identifier in the file system (can be blank or anything)
+ char bibliographicFilelIdentifier[37];
+ // Volume create date (in text format YYYYMMDDHHMMSSMMGG)
+ char volumeCreateDate[17];
+ // Volume modify date (in text format YYYYMMDDHHMMSSMMGG)
+ char volumeModifyDate[17];
+ // Volume expiry date (in text format YYYYMMDDHHMMSSMMGG)
+ char volumeExpiryDate[17];
+ // Volume effective date (in text format YYYYMMDDHHMMSSMMGG)
+ char volumeEffeciveDate[17];
+ // File structure version (always 1)
+ unsigned char fileStructVersion;
+ // Padding
+ unsigned char dummy0;
+ // Application specific data (says CD-XA001 at [141], the rest are null bytes)
+ unsigned char appData[512];
+ // Padding
+ unsigned char pad4[653];
+
+} ISO_DESCRIPTOR;
+
+// Leave non-aligned structure packing
+#pragma pack(pop)
+
+extern char _cd_media_changed;
+int _cd_iso_last_dir_lba;
+
+u_char _cd_iso_descriptor_buff[2048];
+u_char *_cd_iso_pathtable_buff=NULL;
+u_char *_cd_iso_directory_buff=NULL;
+int _cd_iso_directory_len;
+
+int _CdReadIsoDescriptor(int session_offs)
+{
+ int i;
+ CdlLOC loc;
+ ISO_DESCRIPTOR *descriptor;
+
+ // Seek to volume descriptor location
+ CdIntToPos(16+session_offs, &loc);
+ if( !CdControl(CdlSetloc, (u_char*)&loc, 0) )
+ {
+#ifdef DEBUG
+ printf("psxcd: Could not set seek destination.\n");
+#endif
+ return -1;
+ }
+
+ // Read volume descriptor
+ CdRead(1, (u_int*)_cd_iso_descriptor_buff, CdlModeSpeed);
+ if( CdReadSync(0, 0) )
+ {
+#ifdef DEBUG
+ printf("psxcd: Error reading ISO volume descriptor.\n");
+#endif
+ return -1;
+ }
+
+
+ // Verify if volume descriptor is present
+ descriptor = (ISO_DESCRIPTOR*)_cd_iso_descriptor_buff;
+ if( strncmp("CD001", descriptor->header.id, 5) )
+ {
+#ifdef DEBUG
+ printf("psxcd: Disc does not have a ISO9660 file system.\n");
+#endif
+ return -1;
+ }
+
+#ifdef DEBUG
+ printf("psxcd_dbg: Path table LBA = %d\n", descriptor->pathTable1Offs);
+ printf("psxcd_dbg: Path table len = %d\n", descriptor->pathTableSize.lsb);
+#endif
+
+ // Allocate path table buffer
+ i = ((2047+descriptor->pathTableSize.lsb)>>11)<<11;
+ if( _cd_iso_pathtable_buff )
+ {
+ free(_cd_iso_pathtable_buff);
+ }
+ _cd_iso_pathtable_buff = (u_char*)malloc(i);
+
+#ifdef DEBUG
+ printf("psxcd_dbg: Allocated %d bytes for path table.\n", i);
+#endif
+
+ // Read path table
+ CdIntToPos(descriptor->pathTable1Offs, &loc);
+ CdControl(CdlSetloc, (u_char*)&loc, 0);
+ CdRead(i>>11, (u_int*)_cd_iso_pathtable_buff, CdlModeSpeed);
+ if( CdReadSync(0, 0) )
+ {
+#ifdef DEBUG
+ printf("psxcd: Error reading ISO path table.\n");
+#endif
+ return -1;
+ }
+
+ _cd_iso_last_dir_lba = 0;
+
+ return 0;
+}
+
+int _CdReadIsoDirectory(int lba)
+{
+ int i;
+ CdlLOC loc;
+ ISO_DIR_ENTRY *direntry;
+
+ if( lba == _cd_iso_last_dir_lba )
+ {
+ return 0;
+ }
+
+ CdIntToPos(lba, &loc);
+ i = CdPosToInt(&loc);
+#ifdef DEBUG
+ printf("psxcd_dbg: Seek to sector %d\n", i);
+#endif
+ if( !CdControl(CdlSetloc, (u_char*)&loc, 0) )
+ {
+#ifdef DEBUG
+ printf("psxcd: Could not set seek destination.\n");
+#endif
+ return -1;
+ }
+
+ if( _cd_iso_directory_buff )
+ {
+ free(_cd_iso_directory_buff);
+ }
+
+ // Read first sector of directory record
+ _cd_iso_directory_buff = (u_char*)malloc(2048);
+ CdRead(1, (u_int*)_cd_iso_directory_buff, CdlModeSpeed);
+ if( CdReadSync(0, 0) )
+ {
+#ifdef DEBUG
+ printf("psxcd: Error reading initial directory record.\n");
+#endif
+ return -1;
+ }
+
+ direntry = (ISO_DIR_ENTRY*)_cd_iso_directory_buff;
+ _cd_iso_directory_len = direntry->entrySize.lsb;
+
+#ifdef DEBUG
+ printf("psxcd_dbg: Location of directory record = %d\n", direntry->entryOffs.lsb);
+ printf("psxcd_dbg: Size of directory record = %d\n", _cd_iso_directory_len);
+#endif
+
+ if( _cd_iso_directory_len > 2048 )
+ {
+ if( !CdControl(CdlSetloc, (u_char*)&loc, 0) )
+ {
+#ifdef DEBUG
+ printf("psxcd: Could not set seek destination.\n");
+#endif
+ return -1;
+ }
+
+ free(_cd_iso_directory_buff);
+ i = ((2047+_cd_iso_directory_len)>>11)<<11;
+ _cd_iso_directory_buff = (u_char*)malloc(i);
+#ifdef DEBUG
+ printf("psxcd_dbg: Allocated %d bytes for directory record.\n", i);
+#endif
+
+ CdRead(i>>11, (u_int*)_cd_iso_directory_buff, CdlModeSpeed);
+ if( CdReadSync(0, 0) )
+ {
+#ifdef DEBUG
+ printf("psxcd: Error reading initial directory record.\n");
+#endif
+ return -1;
+ }
+ }
+
+ _cd_iso_last_dir_lba = lba;
+
+ return 0;
+}
+
+#ifdef DEBUG
+
+void dump_directory(void)
+{
+ int i;
+ int dir_pos;
+ ISO_DIR_ENTRY *dir_entry;
+ char namebuff[16];
+
+ printf("psxcd_dbg: Cached directory record contents:\n");
+
+ i = 0;
+ dir_pos = 0;
+ while(1)
+ {
+ dir_entry = (ISO_DIR_ENTRY*)(_cd_iso_directory_buff+dir_pos);
+
+ strncpy(namebuff,
+ _cd_iso_directory_buff+dir_pos+sizeof(ISO_DIR_ENTRY), dir_entry->identifierLen);
+
+ printf("P:%d L:%d %s\n", dir_pos, dir_entry->identifierLen, namebuff);
+
+ dir_pos += dir_entry->entryLength;
+ i++;
+
+ // Check if padding is reached (end of record sector)
+ if( _cd_iso_directory_buff[dir_pos] == 0 )
+ {
+ // Snap it to next sector
+ dir_pos = ((dir_pos+2047)>>11)<<11;
+
+ // Break if exceeds length of directory buffer (end)
+ if( dir_pos >= _cd_iso_directory_len )
+ {
+ break;
+ }
+ }
+ }
+
+ printf("--\n");
+
+}
+
+void dump_pathtable(void)
+{
+ u_char *tbl_pos;
+ ISO_PATHTABLE_ENTRY *tbl_entry;
+ ISO_DESCRIPTOR *descriptor;
+ char namebuff[16];
+
+ printf("psxcd_dbg: Path table entries:\n");
+
+ descriptor = (ISO_DESCRIPTOR*)_cd_iso_descriptor_buff;
+
+ tbl_pos = _cd_iso_pathtable_buff;
+ tbl_entry = (ISO_PATHTABLE_ENTRY*)tbl_pos;
+
+ while( (int)(tbl_pos-_cd_iso_pathtable_buff) <
+ descriptor->pathTableSize.lsb )
+ {
+ strncpy(namebuff,
+ tbl_pos+sizeof(ISO_PATHTABLE_ENTRY),
+ tbl_entry->nameLength);
+
+ printf("psxcd_dbg: %s\n", namebuff);
+
+ // Advance to next entry
+ tbl_pos += sizeof(ISO_PATHTABLE_ENTRY)
+ +(2*((tbl_entry->nameLength+1)/2));
+
+ tbl_entry = (ISO_PATHTABLE_ENTRY*)tbl_pos;
+ }
+
+}
+
+#endif
+
+int get_pathtable_entry(int entry, ISO_PATHTABLE_ENTRY *tbl, char *namebuff)
+{
+ int i;
+ u_char *tbl_pos;
+ ISO_PATHTABLE_ENTRY *tbl_entry;
+ ISO_DESCRIPTOR *descriptor;
+
+ descriptor = (ISO_DESCRIPTOR*)_cd_iso_descriptor_buff;
+
+ tbl_pos = _cd_iso_pathtable_buff;
+ tbl_entry = (ISO_PATHTABLE_ENTRY*)tbl_pos;
+
+ i = 0;
+ while( (int)(tbl_pos-_cd_iso_pathtable_buff) <
+ descriptor->pathTableSize.lsb )
+ {
+ if( i == (entry-1) )
+ {
+ if( namebuff )
+ {
+ strncpy(namebuff,
+ tbl_pos+sizeof(ISO_PATHTABLE_ENTRY),
+ tbl_entry->nameLength);
+ }
+
+ if( tbl )
+ {
+ *tbl = *tbl_entry;
+ }
+
+ return 0;
+ }
+
+ // Advance to next entry
+ tbl_pos += sizeof(ISO_PATHTABLE_ENTRY)
+ +(2*((tbl_entry->nameLength+1)/2));
+
+ tbl_entry = (ISO_PATHTABLE_ENTRY*)tbl_pos;
+ i++;
+ }
+
+ if( entry <= 0 )
+ {
+ return i+1;
+ }
+
+ return -1;
+}
+
+char *resolve_pathtable_path(int entry, char *rbuff)
+{
+ char namebuff[16];
+ ISO_PATHTABLE_ENTRY tbl_entry;
+
+ *rbuff = 0;
+
+ do
+ {
+ if( get_pathtable_entry(entry, &tbl_entry, namebuff) )
+ {
+ return NULL;
+ }
+
+ rbuff -= tbl_entry.nameLength;
+ memcpy(rbuff, namebuff, tbl_entry.nameLength);
+ rbuff--;
+ *rbuff = '\\';
+
+ // Parse to the parent
+ entry = tbl_entry.dirLevel;
+
+ } while( entry > 1 );
+
+ return rbuff;
+}
+
+int find_dir_entry(const char *name, ISO_DIR_ENTRY *dirent)
+{
+ int i;
+ int dir_pos;
+ ISO_DIR_ENTRY *dir_entry;
+ char namebuff[16];
+
+#ifdef DEBUG
+ printf("psxcd_dbg: Locating file %s.\n", name);
+#endif
+
+ i = 0;
+ dir_pos = 0;
+ while(dir_pos < _cd_iso_directory_len)
+ {
+ dir_entry = (ISO_DIR_ENTRY*)(_cd_iso_directory_buff+dir_pos);
+
+ if( !(dir_entry->flags & 0x2) )
+ {
+ strncpy(namebuff,
+ _cd_iso_directory_buff+dir_pos+sizeof(ISO_DIR_ENTRY),
+ dir_entry->identifierLen);
+
+ if( strcmp(namebuff, name) == 0 )
+ {
+ *dirent = *dir_entry;
+ return 0;
+ }
+ }
+
+ dir_pos += dir_entry->entryLength;
+ i++;
+
+ // Check if padding is reached (end of record sector)
+ if( _cd_iso_directory_buff[dir_pos] == 0 )
+ {
+ // Snap it to next sector
+ dir_pos = ((dir_pos+2047)>>11)<<11;
+
+ }
+ }
+
+ return -1;
+}
+
+char *get_pathname(char *path, const char *filename)
+{
+ char *c;
+ c = strrchr(filename, '\\');
+
+ if(( c == filename ) || ( !c ))
+ {
+ path[0] = '\\';
+ path[1] = 0;
+ return NULL;
+ }
+
+ strncpy(path, filename, (int)(c-filename));
+ return path;
+}
+
+char *get_filename(char *name, const char *filename)
+{
+ char *c;
+ c = strrchr(filename, '\\');
+
+ if(( c == filename ) || ( !c ))
+ {
+ strcpy(name, filename+1);
+ return name;
+ }
+
+ c++;
+ strcpy(name, c);
+ return name;
+}
+
+CdlFILE *CdSearchFile(CdlFILE *fp, const char *filename)
+{
+ int i,j,found_dir,num_dirs;
+ int dir_len;
+ char tpath_rbuff[128];
+ char search_path[128];
+ char *rbuff;
+ ISO_PATHTABLE_ENTRY tbl_entry;
+ ISO_DIR_ENTRY dir_entry;
+
+ // Read ISO descriptor if changed flag is set
+ if( _cd_media_changed )
+ {
+ // Read ISO descriptor and path table
+ if( _CdReadIsoDescriptor(0) )
+ {
+#ifdef DEBUG
+ printf("psxcd: Could not read ISO file system.\n");
+#endif
+ return NULL;
+ }
+#ifdef DEBUG
+ printf("psxcd: ISO file system cache updated.\n");
+#endif
+ _cd_media_changed = 0;
+ }
+
+ // Get number of directories in path table
+ num_dirs = get_pathtable_entry(0, NULL, NULL);
+
+#ifdef DEBUG
+ printf("psxcd_dbg: Directories in path table: %d\n", num_dirs);
+
+ rbuff = resolve_pathtable_path(num_dirs-1, tpath_rbuff+127);
+
+ if( !rbuff )
+ {
+ printf("psxcd_dbg: Could not resolve path.\n");
+ }
+ else
+ {
+ printf("psxcd_dbg: Longest path: %s|\n", rbuff);
+ }
+#endif
+
+ if( get_pathname(search_path, filename) )
+ {
+#ifdef DEBUG
+ printf("psxcd_dbg: Search path = %s|\n", search_path);
+#endif
+ }
+
+ // Search the pathtable for a matching path
+ found_dir = 0;
+ for(i=1; i<num_dirs; i++)
+ {
+ rbuff = resolve_pathtable_path(i, tpath_rbuff+127);
+#ifdef DEBUG
+ printf("psxcd_dbg: Found = %s|\n", rbuff);
+#endif
+ if( rbuff )
+ {
+ if( strcmp(search_path, rbuff) == 0 )
+ {
+ found_dir = i;
+ break;
+ }
+ }
+ }
+
+ if( !found_dir )
+ {
+#ifdef DEBUG
+ printf("psxcd_dbg: Directory path not found.\n");
+#endif
+ return NULL;
+ }
+
+#ifdef DEBUG
+ printf("psxcd_dbg: Found directory at record %d!\n", found_dir);
+#endif
+
+ get_pathtable_entry(found_dir, &tbl_entry, NULL);
+
+#ifdef DEBUG
+ printf("psxcd_dbg: Directory LBA = %d\n", tbl_entry.dirOffs);
+#endif
+
+ _CdReadIsoDirectory(tbl_entry.dirOffs);
+
+ get_filename(fp->name, filename);
+
+ // Add version number if not specified
+ if( !strchr(fp->name, ';') )
+ {
+ strcat(fp->name, ";1");
+ }
+
+#ifdef DEBUG
+ dump_directory();
+#endif
+
+ if( find_dir_entry(fp->name, &dir_entry) )
+ {
+#ifdef DEBUG
+ printf("psxcd: Could not find file.\n");
+#endif
+ return NULL;
+ }
+
+#ifdef DEBUG
+ printf("psxcd_dbg: Located file at LBA %d.\n", dir_entry.entryOffs.lsb);
+#endif
+
+ CdIntToPos(dir_entry.entryOffs.lsb, &fp->loc);
+ fp->size = dir_entry.entrySize.lsb;
+
+ return fp;
+}
diff --git a/libpsn00b/libpsxcd/makefile b/libpsn00b/libpsxcd/makefile
new file mode 100644
index 0000000..87466b3
--- /dev/null
+++ b/libpsn00b/libpsxcd/makefile
@@ -0,0 +1,38 @@
+# Run using make (Linux) or gmake (BSD)
+# Part of the PSn00bSDK Project
+# 2019 Lameguy64 / Meido-Tek Productions
+
+include ../common.mk
+
+TARGET = ../libpsxcd.a
+
+CFILES = $(notdir $(wildcard ./*.c))
+AFILES = $(notdir $(wildcard ./*.s))
+OFILES = $(addprefix build/,$(CFILES:.c=.o) $(AFILES:.s=.o))
+
+INCLUDE = -I../include
+
+CFLAGS = -g -msoft-float -fno-builtin -fdata-sections -ffunction-sections -Wa,--strip-local-absolute
+AFLAGS = -g -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) -O2 $(CFLAGS) $(INCLUDE) -c $< -o $@
+
+build/%.o: %.s
+ @mkdir -p $(dir $@)
+ $(CC) $(AFLAGS) $(INCLUDE) -c $< -o $@
+
+clean:
+ rm -Rf build $(TARGET)
diff --git a/libpsn00b/libpsxcd/psxcd.c b/libpsn00b/libpsxcd/psxcd.c
new file mode 100644
index 0000000..5be9eec
--- /dev/null
+++ b/libpsn00b/libpsxcd/psxcd.c
@@ -0,0 +1,319 @@
+#include <stdio.h>
+#include "psxcd.h"
+
+extern volatile char _cd_ack_wait;
+extern volatile unsigned char _cd_last_int;
+extern volatile unsigned char _cd_last_mode;
+extern volatile unsigned char _cd_status;
+extern volatile CdlCB _cd_callback_int1_data;
+volatile unsigned char *_cd_result_ptr;
+
+extern volatile char _cd_media_changed;
+
+void _cd_init(void);
+void _cd_control(unsigned char com, unsigned char *param, int plen);
+void _cd_wait_ack(void);
+void _cd_wait(void);
+
+int CdInit(int mode)
+{
+ // Sets up CD-ROM hardware and low-level subsystem
+ _cd_init();
+
+ // So CD ISO file system component will update the ISO descriptor
+ _cd_media_changed = 1;
+
+ // Issue commands to initialize the CD-ROM hardware
+ CdControl(CdlNop, 0, 0);
+ CdControl(CdlInit, 0, 0);
+
+ if( CdSync(0, 0) != CdlDiskError )
+ {
+ CdControl(CdlDemute, 0, 0);
+ printf("psxcd: Init Ok!\n");
+ }
+ else
+ {
+ printf("psxcd: Error initializing. Bad disc/drive or no disc inserted.\n");
+ }
+
+ return 1;
+}
+
+int CdControl(unsigned char com, unsigned char *param, unsigned char *result)
+{
+ // Don't issue command if ack is not received yet
+ if( _cd_ack_wait )
+ {
+ return 0;
+ }
+
+ _cd_result_ptr = result;
+
+ CdControlF(com, param);
+ _cd_wait_ack();
+
+ return 1;
+}
+
+int CdControlB(unsigned char com, unsigned char *param, unsigned char *result)
+{
+ if( !CdControl(com, param, result) )
+ {
+ return 0;
+ }
+
+ CdSync(0, 0);
+ return 1;
+}
+
+int CdControlF(unsigned char com, unsigned char *param)
+{
+ int param_len=0;
+
+ // Command specific parameters
+ switch(com)
+ {
+ case CdlSetloc:
+ param_len = 3;
+ break;
+ case CdlPlay:
+ if( param )
+ {
+ param_len = 1;
+ }
+ break;
+ case CdlSetfilter:
+ param_len = 2;
+ break;
+ case CdlSetmode:
+ param_len = 1;
+ break;
+ case CdlSetsession:
+ param_len = 1;
+ break;
+ case CdlTest:
+ param_len = 1;
+ break;
+ case CdlGetTD:
+ param_len = 1;
+ }
+
+ // Issue Setloc if parameters are specified on CdlReadN and CdlReadS
+ if( ( com == CdlReadN ) || ( com == CdlReadS ) )
+ {
+ if( param )
+ {
+ _cd_control(CdlSetloc, param, 3);
+ }
+ }
+
+ // Issue CD command
+ _cd_control(com, param, param_len);
+
+ return 1;
+}
+
+int CdSync(int mode, unsigned char *result)
+{
+ int cdirq;
+
+ if( mode )
+ {
+ if( result )
+ {
+ *result = _cd_status;
+ }
+
+ cdirq = _cd_last_int;
+ if( cdirq == CdlAcknowledge )
+ {
+ cdirq = CdlComplete;
+ }
+ return cdirq;
+ }
+
+ _cd_wait();
+
+ if( result )
+ {
+ *result = _cd_status;
+ }
+
+ cdirq = _cd_last_int;
+ if( cdirq == CdlAcknowledge )
+ {
+ cdirq = CdlComplete;
+ }
+
+ return cdirq;
+}
+
+int CdGetToc(CdlLOC *toc)
+{
+ u_char track_info[8];
+ int i,tracks;
+
+ // Get number of tracks
+ if( !CdControl(CdlGetTN, 0, track_info) )
+ {
+ return 0;
+ }
+
+ if( CdSync(1, 0) != CdlComplete )
+ {
+ return 0;
+ }
+
+ tracks = 1+(btoi(track_info[2])-btoi(track_info[1]));
+
+ // Get track positions
+ for(i=0; i<tracks; i++)
+ {
+ int t = itob(1+i);
+ if( !CdControl(CdlGetTD, (u_char*)&t, (u_char*)&toc[i]) )
+ {
+ return 0;
+ }
+ if( CdSync(1, 0) != CdlComplete )
+ {
+ return 0;
+ }
+ toc[i].sector = 0;
+ toc[i].track = 1+i;
+ }
+
+ return tracks;
+}
+
+CdlLOC *CdIntToPos(int i, CdlLOC *p) {
+
+ i += 150;
+
+ p->minute = itob((i/75)/60);
+ p->second = itob((i/75)%60);
+ p->sector = itob(i%75);
+
+ return p;
+
+}
+
+int CdPosToInt(CdlLOC *p)
+{
+ return ((75*(btoi(p->minute)*60))+(75*btoi(p->second))+btoi(p->sector))-150;
+}
+
+int CdStatus(void)
+{
+ return _cd_status;
+}
+
+int CdMode(void)
+{
+ return _cd_last_mode;
+}
+
+
+// CD data read routines
+volatile int _cd_sector_count = 0;
+volatile unsigned int *_cd_read_addr;
+volatile unsigned char _cd_read_result[8];
+volatile unsigned int _cd_read_oldcb;
+volatile unsigned int _cd_read_sector_sz;
+volatile CdlCB _cd_read_cb;
+
+// Sector callback
+static void _CdReadReadyCallback(int status, unsigned char *result)
+{
+ if( status == CdlDataReady )
+ {
+ // Fetch sector from CD controller
+ CdGetSector((void*)_cd_read_addr, _cd_read_sector_sz);
+
+ // Increment destination address
+ _cd_read_addr += _cd_read_sector_sz>>2;
+
+ // Subtract sector count
+ _cd_sector_count--;
+ }
+
+ // End reading with pause command when sector count reaches zero
+ // or when an error occurs
+ if( ( _cd_sector_count <= 0 ) || ( status == CdlDiskError ) )
+ {
+ // Stop reading
+ _cd_control(CdlPause, 0, 0);
+
+ // Revert previous ready callback
+ _cd_callback_int1_data = (CdlCB)_cd_read_oldcb;
+
+ // Execute read completion callback
+ if( _cd_read_cb )
+ {
+ _cd_read_cb(status, result);
+ }
+ }
+}
+
+int CdRead(int sectors, unsigned int *buf, int mode)
+{
+ // Set sectors to read count
+ _cd_sector_count = sectors;
+ _cd_read_addr = buf;
+
+ // Determine sector based on mode flags
+ if( mode & CdlModeSize0 )
+ {
+ _cd_read_sector_sz = 2328;
+ }
+ else if( mode & CdlModeSize1 )
+ {
+ _cd_read_sector_sz = 2340;
+ }
+ else
+ {
+ _cd_read_sector_sz = 2048;
+ }
+
+ // Set readt callback
+ _cd_read_oldcb = CdReadyCallback(_CdReadReadyCallback);
+
+ // Set specified mode
+ CdControl(CdlSetmode, (unsigned char*)&mode, 0);
+
+ // Begin reading sectors
+ CdControl(CdlReadN, 0, (unsigned char*)_cd_read_result);
+
+ return 0;
+}
+
+int CdReadSync(int mode, unsigned char *result)
+{
+ if( mode )
+ {
+ if( CdSync(1, 0) == CdlDiskError )
+ {
+ return -1;
+ }
+ return _cd_sector_count;
+ }
+
+ while(_cd_sector_count > 0);
+ if( CdSync(0, result) != CdlComplete )
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+unsigned int CdReadCallback(CdlCB func)
+{
+ unsigned int old_func;
+
+ old_func = (unsigned int)_cd_read_cb;
+
+ _cd_read_cb = func;
+
+ return old_func;
+}
diff --git a/libpsn00b/libpsxcd/psxcd_asm.s b/libpsn00b/libpsxcd/psxcd_asm.s
new file mode 100644
index 0000000..7fe1c1d
--- /dev/null
+++ b/libpsn00b/libpsxcd/psxcd_asm.s
@@ -0,0 +1,520 @@
+.set noreorder
+
+.include "hwregs_a.h"
+
+.section .text
+
+.global _cd_init
+.type _cd_init, @function
+_cd_init:
+
+ addiu $sp, -4
+ sw $ra, 0($sp)
+
+ jal EnterCriticalSection
+ nop
+
+ lui $a3, IOBASE # Acknowledge all CD IRQs
+ li $v0, 1
+ sb $v0, CD_REG0($a3)
+ li $v0, 0x1f
+ sb $v0, CD_REG3($a3)
+ sb $v0, CD_REG2($a3) # Enable all IRQs
+
+ sb $0 , CD_REG0($a3)
+ sb $0 , CD_REG3($a3)
+
+ li $v0, 0x1325
+ sw $v0, COM_DELAY($a3)
+
+ la $a1, _cd_handler
+ jal InterruptCallback
+ li $a0, 2
+
+ li $v0, 2 # Set CD left volume
+ sb $v0, CD_REG0($a3)
+ li $v0, 0x80
+ sb $v0, CD_REG2($a3)
+
+ li $v0, 3 # Set CD right volume
+ sb $v0, CD_REG0($a3)
+ li $v0, 0x80
+ sb $v0, CD_REG1($a3)
+
+ li $v0, 0x20 # Apply volume
+ sb $v0, CD_REG3($a3)
+
+ # Clear a bunch of stats
+ la $v0, _cd_ack_wait
+ sb $0 , 0($v0)
+ la $v0, _cd_complt_wait
+ sb $0 , 0($v0)
+ la $v0, _cd_last_cmd
+ sb $0 , 0($v0)
+ la $v0, _cd_last_mode
+ sb $0 , 0($v0)
+ la $v0, _cd_last_int
+ sb $0 , 0($v0)
+
+ la $v0, _cd_result_ptr
+ sw $0 , 0($v0)
+
+ # Clear callback hooks
+ la $v0, _cd_callback_int1_data
+ sw $0 , 0($v0)
+ la $v0, _cd_callback_int4
+ sw $0 , 0($v0)
+
+ la $v0, _cd_read_cb
+ sw $0 , 0($v0)
+
+ lw $v0, DPCR($a3)
+ li $v1, 0xB000
+ or $v0, $v1
+ sw $v0, DPCR($a3)
+
+ jal ExitCriticalSection
+ nop
+
+ #li $a0, 0x01 # GetStat
+ #jal _cd_control
+ #move $a2, $0
+ #jal _cd_wait
+ #nop
+
+ #li $a0, 0x0a # Init
+ #jal _cd_control
+ #move $a2, $0
+ #jal _cd_wait
+ #nop
+
+ #li $a0, 0x0c # Demute
+ #jal _cd_control
+ #move $a2, $0
+ #jal _cd_wait
+ #nop
+
+ #la $a0, _cd_init_msg
+ #jal printf
+ #addiu $sp, -16
+ #addiu $sp, 16
+
+ lw $ra, 0($sp)
+ addiu $sp, 4
+ jr $ra
+ nop
+
+
+.global _cd_wait
+.type _cd_wait, @function
+_cd_wait:
+ la $v0, _cd_ack_wait
+ lbu $v0, 0($v0)
+ nop
+ bnez $v0, _cd_wait
+ nop
+.Lcomplete:
+ la $v0, _cd_complt_wait
+ lbu $v0, 0($v0)
+ nop
+ bnez $v0, .Lcomplete
+ nop
+ jr $ra
+ nop
+
+
+.global _cd_wait_ack
+.type _cd_wait_ack, @function
+_cd_wait_ack:
+ la $v0, _cd_ack_wait
+ lbu $v0, 0($v0)
+ nop
+ bnez $v0, _cd_wait_ack
+ nop
+ jr $ra
+ nop
+
+
+.global _cd_wait_complt
+.type _cd_wait_complt, @function
+_cd_wait_complt:
+ la $v0, _cd_complt_wait
+ lbu $v0, 0($v0)
+ nop
+ bnez $v0, _cd_wait_complt
+ nop
+ jr $ra
+ nop
+
+
+.type _cd_handler, @function
+_cd_handler:
+
+ addiu $sp, -4
+ sw $ra, 0($sp)
+
+ lui $a3, IOBASE # Print out IRQ number
+ li $v0, 1
+ sb $v0, CD_REG0($a3)
+
+ lbu $v0, CD_REG3($a3)
+ nop
+ andi $v0, 0x7
+
+ la $v1, _cd_last_int # Save last IRQ value
+ sb $v0, 0($v1)
+
+ bne $v0, 0x1, .Lno_data
+ nop
+
+ sb $0 , CD_REG0($a3) # Load data FIFO on INT1
+ li $v1, 0x80
+ sb $v1, CD_REG3($a3)
+
+.Lno_data:
+
+ li $v1, 1
+ sb $v1, CD_REG0($a3) # Clear CD interrupt and parameter FIFO
+ li $v1, 0x5f
+ sb $v1, CD_REG3($a3)
+ li $v1, 0x40
+ sb $v1, CD_REG3($a3)
+
+ li $v1, 0 # Delay when clearing parameter FIFO
+ sw $v1, 0($0)
+ li $v1, 1
+ sw $v1, 0($0)
+ li $v1, 2
+ sw $v1, 0($0)
+ li $v1, 3
+ sw $v1, 0($0)
+
+ beq $v0, 0x1, .Lirq_1 # Data ready
+ nop
+ beq $v0, 0x2, .Lirq_2 # Command finish
+ nop
+ beq $v0, 0x3, .Lirq_3 # Acknowledge
+ nop
+ beq $v0, 0x4, .Lirq_4 # Data/track end
+ nop
+ beq $v0, 0x5, .Lirq_5 # Error
+ nop
+
+ b .Lirq_misc
+ nop
+
+.Lirq_1: # Data ready
+
+ jal _cd_fetch_result
+ nop
+
+ la $v0, _cd_callback_int1_data
+ lw $v0, 0($v0)
+ nop
+ beqz $v0, .Lirq_misc
+ nop
+
+ la $a0, _cd_last_int
+ lbu $a0, 0($a0)
+ la $a1, _cd_result_ptr
+ lw $a1, 0($a1)
+
+ jalr $v0
+ addiu $sp, -16
+ addiu $sp, 16
+
+ b .Lirq_misc
+ nop
+
+.Lirq_2: # Command complete
+
+ jal _cd_fetch_result
+ nop
+
+ la $v0, _cd_complt_wait
+ sb $0 , 0($v0)
+
+ la $v0, _cd_sync_cb
+ lw $v0, 0($v0)
+ nop
+ beqz $v0, .Lirq_misc
+ nop
+
+ la $a0, _cd_last_int
+ lbu $a0, 0($a0)
+ la $a1, _cd_result_ptr
+ lw $a1, 0($a1)
+ jalr $v0
+ addiu $sp, -16
+ addiu $sp, 16
+
+ b .Lirq_misc
+ nop
+
+.Lirq_3: # Command acknowledge
+
+ jal _cd_fetch_result
+ nop
+
+ la $v0, _cd_ack_wait
+ sb $0 , 0($v0)
+
+ b .Lirq_misc
+ nop
+
+.Lirq_4:
+
+ jal _cd_fetch_result
+ nop
+
+ la $v0, _cd_callback_int4
+ lw $v0, 0($v0)
+ nop
+ beqz $v0, .Lirq_misc
+ nop
+
+ jalr $v0
+ addiu $sp, -16
+ addiu $sp, 16
+
+ b .Lirq_misc
+ nop
+
+.Lirq_5: # Error
+
+ jal _cd_fetch_result
+ nop
+
+ la $v0, _cd_complt_wait
+ lbu $v0, 0($v0)
+ nop
+ beqz $v0, .Lno_complete
+ nop
+
+ la $v0, _cd_sync_cb
+ lw $v0, 0($v0)
+ nop
+ beqz $v0, .Lno_complete
+ nop
+
+ li $a0, 0x05 # CdlDiskError
+ la $a1, _cd_result_ptr
+ lw $a1, 0($a1)
+ jalr $v0
+ addiu $sp, -16
+ addiu $sp, 16
+
+.Lno_complete:
+
+ la $v0, _cd_complt_wait
+ sb $0 , 0($v0)
+ la $v0, _cd_ack_wait
+ sb $0 , 0($v0)
+
+ la $v0, _cd_callback_int1_data
+ lw $v0, 0($v0)
+ nop
+ beqz $v0, .Lirq_misc
+ nop
+
+ li $a0, 0x05 # CdlDiskError
+ la $a1, _cd_result_ptr
+ lw $a1, 0($a1)
+
+ jalr $v0
+ addiu $sp, -16
+ addiu $sp, 16
+
+.Lirq_misc:
+
+ lw $ra, 0($sp)
+ addiu $sp, 4
+ jr $ra
+ nop
+
+
+_cd_fetch_result:
+
+ lui $a3, IOBASE
+
+ la $a0, _cd_status
+ lbu $v0, CD_REG1($a3)
+
+ la $v1, _cd_last_int
+ lbu $v1, 0($v1)
+ nop
+ beq $v1, 0x2, .Lirq2_checks
+ nop
+
+ # IRQ3 checks
+
+ la $v1, _cd_last_cmd
+ lbu $v1, 0($v1)
+ nop
+ beq $v1, 0x10, .Lskip_status
+ nop
+ beq $v1, 0x11, .Lskip_status
+ nop
+
+ b .Lwrite_status
+ nop
+
+ # IRQ2 checks
+
+.Lirq2_checks:
+
+ la $v1, _cd_last_cmd
+ lbu $v1, 0($v1)
+ nop
+ beq $v1, 0x1D, .Lskip_status
+ nop
+
+.Lwrite_status:
+
+ sb $v0, 0($a0)
+
+.Lskip_status:
+
+ la $a0, _cd_result_ptr
+ lw $a0, 0($a0)
+ nop
+ beqz $a0, .Lno_result
+ nop
+ sb $v0, 0($a0)
+ addiu $a0, 1
+
+.Lread_futher_result:
+
+ lbu $v0, CD_REG0($a3)
+ nop
+ andi $v0, 0x20
+ beqz $v0, .Lno_result
+ nop
+
+ lbu $v0, CD_REG1($a3)
+ lbu $v1, CD_REG0($a3)
+ sb $v0, 0($a0)
+ andi $v1, 0x20
+ bnez $v1, .Lread_futher_result
+ addiu $a0, 1
+
+.Lno_result:
+
+ jr $ra
+ nop
+
+
+.global CdAutoPauseCallback
+.type CdAutoPauseCallback, @function
+CdAutoPauseCallback:
+
+ addiu $sp, -8
+ sw $ra, 0($sp)
+ sw $a0, 4($sp)
+
+ la $v1, _cd_callback_int4
+ lw $v0, 0($v1)
+
+ la $v1, _cd_callback_int4
+
+ jal EnterCriticalSection
+ nop
+
+ lw $a0, 4($sp)
+ nop
+ sw $a0, 0($v1)
+
+ jal ExitCriticalSection
+ nop
+
+ lw $ra, 0($sp)
+ addiu $sp, 8
+ jr $ra
+ nop
+
+
+.global CdReadyCallback
+.type CdReadyCallback, @function
+CdReadyCallback:
+
+ addiu $sp, -12
+ sw $ra, 0($sp)
+ sw $a0, 4($sp)
+
+ la $v1, _cd_callback_int1_data
+ lw $v0, 0($v1)
+
+ la $v1, _cd_callback_int1_data
+ sw $v0, 8($sp)
+
+ jal EnterCriticalSection
+ nop
+
+ lw $a0, 4($sp)
+ nop
+ sw $a0, 0($v1)
+
+ jal ExitCriticalSection
+ nop
+
+ lw $ra, 0($sp)
+ lw $v0, 8($sp)
+ jr $ra
+ addiu $sp, 12
+
+
+.global CdSyncCallback
+.type CdSyncCallback, @function
+CdSyncCallback:
+ addiu $sp, -12
+ sw $ra, 0($sp)
+ sw $a0, 4($sp)
+
+ la $v1, _cd_sync_cb
+ lw $v0, 0($v1)
+
+ la $v1, _cd_sync_cb
+ sw $v0, 8($sp)
+
+ jal EnterCriticalSection
+ nop
+
+ lw $a0, 4($sp)
+ nop
+ sw $a0, 0($v1)
+
+ jal ExitCriticalSection
+ nop
+
+ lw $ra, 0($sp)
+ lw $v0, 8($sp)
+ jr $ra
+ addiu $sp, 12
+
+
+.section .data
+
+.global psxcd_credits
+.type psxcd_credits, @object
+psxgpu_credits:
+ .ascii "psxcd library programs by Lameguy64\n"
+ .asciiz "2019 PSn00bSDK Project / Meido-Tek Productions\n"
+
+_cd_init_msg:
+.asciiz "psxcd: Init OK\n"
+.align 4
+
+.comm _cd_last_cmd, 1, 1
+.comm _cd_last_mode, 1, 1
+.comm _cd_ack_wait, 1, 1
+.comm _cd_complt_wait, 1, 1
+
+.comm _cd_status, 1, 1
+.comm _cd_last_int, 1, 1
+
+.comm _cd_media_changed, 1, 1
+
+# Callback hooks
+.comm _cd_callback_int1_data, 4, 4 # Data IRQ callback
+.comm _cd_callback_int4, 4, 4 # Autopause callback
+.comm _cd_sync_cb, 4, 4
diff --git a/libpsn00b/libpsxcd/readme.txt b/libpsn00b/libpsxcd/readme.txt
new file mode 100644
index 0000000..a85fab5
--- /dev/null
+++ b/libpsn00b/libpsxcd/readme.txt
@@ -0,0 +1,48 @@
+PSX CD-ROM library, part of PSn00bSDK
+2019 Lameguy64 / Meido-Tek Productions
+
+Licensed under Mozilla Public License
+
+ Open source implementation of the long awaited CD-ROM library that
+provides greater functionality than the BIOS CD-ROM subsystem. Supports
+pretty much all features of the CD-ROM hardware such as CD data read,
+CD Audio and XA audio playback. Data streaming should also be possible
+with the use of CdlReadN/CdlReadS commands and CdReadyCallback().
+
+ Library also includes an ISO9660 file system parser for locating
+files within the CD-ROM file system. Unlike the file system parser in
+the official libraries libpsxcd can parse directories containing any
+number of files. Rock-ridge and Joliet extensions are not supported
+however.
+
+ Be aware that the CD-ROM library might have some loose ends as it
+is still a work in progress, but should work flawlessly in most use
+cases.
+
+
+Library developer(s):
+
+ Lameguy64
+
+
+Library header(s):
+
+ psxcd.h
+
+
+Todo list:
+
+ * Command query mechanism so that more than 2 CD-ROM commands can
+ easily be issued in callbacks. Official library probably does this.
+
+ * Helper functions for handling disc changes (CdDiskReady and
+ CdGetDiskType) are not yet implemented.
+
+ * CdReadBreak() not yet implemented.
+
+ * Data streaming functions (prefixed with St*) not yet implemented.
+ Would require devising a PSn00bSDK equivalent of the STR file
+ format.
+
+ * Original functions for querying directory contents in the file
+ system not yet implemented. \ No newline at end of file
diff --git a/libpsn00b/makefile b/libpsn00b/makefile
index d4bba32..f095f17 100644
--- a/libpsn00b/makefile
+++ b/libpsn00b/makefile
@@ -4,7 +4,7 @@
TOPTARGETS = all clean
-LIBDIRS = libc lzp psxgpu psxgte psxapi psxetc psxspu psxsio
+LIBDIRS = libc lzp psxgpu psxgte psxapi psxetc psxspu psxsio libpsxcd
$(TOPTARGETS): $(LIBDIRS)
diff --git a/libpsn00b/psxapi/sys/adddummytty.s b/libpsn00b/psxapi/sys/adddummytty.s
new file mode 100644
index 0000000..a569d38
--- /dev/null
+++ b/libpsn00b/psxapi/sys/adddummytty.s
@@ -0,0 +1,10 @@
+.set noreorder
+
+.section .text
+
+.global AddDummyTty
+.type AddDummyTty, @function
+AddDummyTty:
+ addiu $t2, $0, 0xa0
+ jr $t2
+ addiu $t1, $0, 0x99
diff --git a/libpsn00b/psxapi/sys/getrcnt.s b/libpsn00b/psxapi/sys/getrcnt.s
new file mode 100644
index 0000000..0b035ed
--- /dev/null
+++ b/libpsn00b/psxapi/sys/getrcnt.s
@@ -0,0 +1,10 @@
+.set noreorder
+
+.section .text
+
+.global GetRCnt
+.type GetRCnt, @function
+GetRCnt:
+ addiu $t2, $0, 0xb0
+ jr $t2
+ addiu $t1, $0, 0x03 \ No newline at end of file
diff --git a/libpsn00b/psxapi/sys/resetrcnt.s b/libpsn00b/psxapi/sys/resetrcnt.s
new file mode 100644
index 0000000..5811625
--- /dev/null
+++ b/libpsn00b/psxapi/sys/resetrcnt.s
@@ -0,0 +1,10 @@
+.set noreorder
+
+.section .text
+
+.global ResetRCnt
+.type ResetRCnt, @function
+ResetRCnt:
+ addiu $t2, $0, 0xb0
+ jr $t2
+ addiu $t1, $0, 0x06 \ No newline at end of file
diff --git a/libpsn00b/psxapi/sys/setrcnt.s b/libpsn00b/psxapi/sys/setrcnt.s
new file mode 100644
index 0000000..ec6180a
--- /dev/null
+++ b/libpsn00b/psxapi/sys/setrcnt.s
@@ -0,0 +1,10 @@
+.set noreorder
+
+.section .text
+
+.global SetRCnt
+.type SetRCnt, @function
+SetRCnt:
+ addiu $t2, $0, 0xb0
+ jr $t2
+ addiu $t1, $0, 0x02 \ No newline at end of file
diff --git a/libpsn00b/psxapi/sys/startrcnt.s b/libpsn00b/psxapi/sys/startrcnt.s
new file mode 100644
index 0000000..0fd5c33
--- /dev/null
+++ b/libpsn00b/psxapi/sys/startrcnt.s
@@ -0,0 +1,10 @@
+.set noreorder
+
+.section .text
+
+.global StartRCnt
+.type StartRCnt, @function
+StartRCnt:
+ addiu $t2, $0, 0xb0
+ jr $t2
+ addiu $t1, $0, 0x04 \ No newline at end of file
diff --git a/libpsn00b/psxapi/sys/stoprcnt.s b/libpsn00b/psxapi/sys/stoprcnt.s
new file mode 100644
index 0000000..4af94da
--- /dev/null
+++ b/libpsn00b/psxapi/sys/stoprcnt.s
@@ -0,0 +1,10 @@
+.set noreorder
+
+.section .text
+
+.global StopRCnt
+.type StopRCnt, @function
+StopRCnt:
+ addiu $t2, $0, 0xb0
+ jr $t2
+ addiu $t1, $0, 0x05 \ No newline at end of file
diff --git a/libpsn00b/psxgpu/drawsync.s b/libpsn00b/psxgpu/drawsync.s
index 66d37e2..2e29381 100644
--- a/libpsn00b/psxgpu/drawsync.s
+++ b/libpsn00b/psxgpu/drawsync.s
@@ -24,7 +24,7 @@ DrawSync:
nop
.Ldma_wait:
- lw $v0, D2_CHCR
+ lw $v0, D2_CHCR($a0)
nop
srl $v0, 24
andi $v0, 0x1
@@ -64,4 +64,4 @@ DrawSync:
jr $ra
srl $v0, 16
- \ No newline at end of file
+
diff --git a/libpsn00b/psxgpu/readme.txt b/libpsn00b/psxgpu/readme.txt
index 8fe439b..b626e1d 100644
--- a/libpsn00b/psxgpu/readme.txt
+++ b/libpsn00b/psxgpu/readme.txt
@@ -5,9 +5,9 @@ Licensed under Mozilla Public License
Open source implementation of the GPU library written mostly in MIPS
assembly. Supports DMA transfers for ordering table draw and transferring
-image data to VRAM. The syntax is intentionally made to closely resemble
-Sony's syntax for familiarity and to make porting homebrew made using the
-official SDK to PSn00bSDK a little easier.
+image data to and from VRAM. The syntax is intentionally made to closely
+resemble Sony's syntax for familiarity and to make porting homebrew made
+using the official SDK to PSn00bSDK a little easier.
Library developer(s):
@@ -25,5 +25,3 @@ Todo list:
* ClearOTag() function (non reverse version of ClearOTagR()) yet to be
implemented (but should be trivial).
-
- * StoreImage() equivalent yet to be implemented.
diff --git a/libpsn00b/psxgpu/resetgraph.s b/libpsn00b/psxgpu/resetgraph.s
index 93ce185..b956873 100644
--- a/libpsn00b/psxgpu/resetgraph.s
+++ b/libpsn00b/psxgpu/resetgraph.s
@@ -4,7 +4,7 @@
.section .text
-.set ISR_STACK_SIZE, 1024
+.set ISR_STACK_SIZE, 2048
.global ResetGraph # Resets the GPU and installs a
.type ResetGraph, @function # VSync event handler
diff --git a/libpsn00b/psxgte/readme.txt b/libpsn00b/psxgte/readme.txt
index 74951c5..13067ee 100644
--- a/libpsn00b/psxgte/readme.txt
+++ b/libpsn00b/psxgte/readme.txt
@@ -29,7 +29,7 @@ Library header(s):
Todo list:
- * Alternate RotMatrix() functions with different rotation order are yet to
+ * Alternate RotMatrix() functions with different rotation orders are yet to
be implemented.
* Various high level RotTransPersp style functions not yet implemented.
diff --git a/libpsn00b/psxsio/siocons.c b/libpsn00b/psxsio/siocons.c
index cd99d68..76bf8be 100644
--- a/libpsn00b/psxsio/siocons.c
+++ b/libpsn00b/psxsio/siocons.c
@@ -1,9 +1,25 @@
#include <stdio.h>
+#include <string.h>
#include <psxapi.h>
#include <psxgpu.h>
#include <psxsio.h>
+#define SIO_BUFF_LEN 32
+
+static volatile int _sio_key_pending;
+
+static volatile int _sio_buff_rpos;
+static volatile int _sio_buff_wpos;
+static volatile char _sio_buff[SIO_BUFF_LEN];
+
static void _sio_init() {
+
+ _sio_key_pending = 0;
+
+ memset((void*)_sio_buff, 0, SIO_BUFF_LEN);
+ _sio_buff_rpos = 0;
+ _sio_buff_wpos = 0;
+
}
static int _sio_open(FCB *fcb, const char* file, int mode) {
@@ -29,9 +45,25 @@ static int _sio_inout(FCB *fcb, int cmd) {
} else if (cmd == 1) { // Read
- for(i=0; i<fcb->trns_len; i++) {
+ /*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);
+ }*/
+
+
+
+ for(i=0; i<fcb->trns_len; i++) {
+
+ while( _sio_key_pending == 0 );
+
+ ((char*)fcb->trns_addr)[i] = _sio_buff[_sio_buff_rpos];
+ _sio_key_pending--;
+ _sio_buff_rpos++;
+ if( _sio_buff_rpos >= SIO_BUFF_LEN )
+ {
+ _sio_buff_rpos = 0;
+ }
+
}
return fcb->trns_len;
@@ -48,6 +80,29 @@ static int _sio_close(int h) {
}
+static void _sio_tty_cb(void)
+{
+ _sio_key_pending++;
+
+ // Get received byte
+ if( _sio_key_pending < SIO_BUFF_LEN )
+ {
+ _sio_buff[_sio_buff_wpos] = _sio_control(0, 4, 0);
+ _sio_buff_wpos++;
+ if( _sio_buff_wpos >= SIO_BUFF_LEN )
+ {
+ _sio_buff_wpos = 0;
+ }
+ }
+ else
+ {
+ _sio_control(0, 4, 0);
+ }
+
+ // Acknowledge SIO IRQ
+ _sio_control(2, 1, 0);
+}
+
static DCB _sio_dcb = {
"tty",
0x3,
@@ -74,15 +129,12 @@ static DCB _sio_dcb = {
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);
+ _sio_control(1, 1, CR_RXEN|CR_TXEN|CR_RXIEN);
close(0);
close(1);
@@ -90,6 +142,8 @@ void AddSIO(int baud) {
DelDev(_sio_dcb.name);
AddDev(&_sio_dcb);
+ Sio1Callback(_sio_tty_cb);
+
open(_sio_dcb.name, 2);
open(_sio_dcb.name, 1);
@@ -97,12 +151,17 @@ void AddSIO(int baud) {
void DelSIO(void) {
+ Sio1Callback(NULL);
+
// Reset serial interface
_sio_control(2, 0, 0);
// Remove TTY device
DelDev(_sio_dcb.name);
+ // Add dummy TTY device
+ AddDummyTty();
+
}
void WaitSIO(void) {
@@ -134,4 +193,9 @@ void *Sio1Callback(void (*func)()) {
return old_isr;
-} \ No newline at end of file
+}
+
+int kbhit()
+{
+ return(_sio_key_pending>0);
+}
diff --git a/libpsn00b/psxspu/spuinit.s b/libpsn00b/psxspu/spuinit.s
index d3a8e8d..42f302a 100644
--- a/libpsn00b/psxspu/spuinit.s
+++ b/libpsn00b/psxspu/spuinit.s
@@ -3,7 +3,7 @@
.include "hwregs_a.h"
-.section .data
+.section .text
.global SpuInit
diff --git a/libpsn00b/readme.txt b/libpsn00b/readme.txt
index 43b120a..1e2e6d7 100644
--- a/libpsn00b/readme.txt
+++ b/libpsn00b/readme.txt
@@ -3,100 +3,108 @@ LibPSn00b, PSn00bSDK software libraries
Licensed under Mozilla Public License
-LibPSn00b make up the majority of PSn00bSDK as it provides the functions
-necessary for developing software for the PSX. Most libraries, mainly the
-GPU and GTE libraries are written mostly in assembly language.
+LibPSn00b is a collection of libraries which make up the core backbone of
+PSn00bSDK as it provides an essential software framework for developing
+homebrew software for the PSX platform. Great majority of the libraries
+are been written from scratch written in a mix of C and hand optimized
+assembly language for best performance.
-Brief library overview:
+These libraries can only be compiled with a build of GCC that supports mipsel
+as one of the supported targets, naturally as these libraries are intended
+for the PSX hardware which uses a MIPS R3000 CPU supported by mipsel.
+Compiler version shouldn't matter much and should build fine in 9.1.0,
+though 7.4.0 is the most recommended version to use as it is the version
+currently used for the majority of the development and testing of LibPSn00b.
+
+
+Brief summary of libraries:
libc - Standard C library. Contains only a small subset of the full
- standard C library, mostly string and memory manipulation
- functions.
+ standard C library such as string and memory manipulation
+ functions. Should include libgcc for special compiler specific
+ dependencies and prevents libc related linker hell.
- psxgpu - GPU library for video and graphics control. Most of the
- important functions are implemented.
+ psxgpu - GPU library for video and graphics control. Also includes
+ interrupt handling for various library subsystems.
- psxgte - GTE library for GTE accelerated vector transformations. Most
- important functions are implemented.
+ psxgte - GTE library for GTE accelerated vector transformations necessary
+ for high performance 3D graphics.
- psxapi - Provides access to most of the BIOS functions calls of the
- PSX BIOS.
+ psxapi - Provides access to various BIOS functions in the PSX BIOS.
- psxetc - Provides some misc functions such as debug font.
+ psxetc - Provides some miscellaneous features such as debug font.
- psxspu - SPU library. Basic functions such as hardware init, uploading
- data to SPU RAM via DMA transfer and playing sound playback
- are fully working but is currently lacking a number of
- important functions, especially reverb.
+ psxspu - SPU library. Basic capabilities such as hardware init,
+ sample upload using DMA and playing samples are supported.
+ Lacks support for reverb and various sequenced music related
+ features.
- Each library has its own readme file that contains its changelog, todo
- list, credits and some additional details of the library.
+ Each library has its own readme file that contains a todo list, credits
+ and some additional details of the library. Changelog of all libraries are
+ compiled in the changelog.txt file.
Compiling:
- Compiling the LibPSn00b libraries requires GCC and binutils targetting
+ Compiling the LibPSn00b libraries requires GCC and binutils targeting
mipsel-unknown-elf built with libgcc. The path to those binaries must be
specified in your PATH environment variable and the binaries must be
prefixed by the target architecture (ie. mipsel-unknown-elf-gcc).
- Simply run the Makefile in this directory using make (or gmake if you're
- in a BSD environment). The Makefile should parse though each library
- directory and run the makefile in it.
+ Simply run the Makefile in this directory with make (or gmake if you're
+ working in a BSD environment). The Makefile should parse though each
+ library directory and run the makefile in it.
Documentation:
- Documentation of all the libraries are found in libn00bref.odf and it features
- the same formatting as the official library documents. The document can be
- exported in PDF format for easier viewing with a web browser or PDF viewer.
+ Documentation of all the libraries are found in libn00bref.odf and it
+ features the same formatting as the official library documents. It is
+ recommended to export it as a PDF document for easier viewing.
Contributing:
- Contributions are open for this project. Just obey the following rules
- when making a contribution:
+ Contributions are open for this project. But it is recommended to at
+ least follow the following rules when contributing to prevent headaches.
* If you add new functions to libpsn00b make sure you document them in
- libn00bref.odf. Documentation using Doxygen is discouraged.
- * This project desires functions that interact with hardware registers to
- be written in assembly language. If you decide to write your functions
- that interact with hardware registers in C make sure you define your
- register pointers as volatile and they must work properly when compiled
- with -O2 optimization.
- * Functions must work flawlessly on both emulators and real hardware.
- * Don't forget to put your user name in the readme file of the library
- you've made a contribution on, and details of what you've changed in the
- changelog.
+ libn00bref.odf. Documentation using Doxygen is not recommended.
+
+ * Library functions can either be written in C or assembly language
+ whichever you prefer. Though it is not entirely mandatory but
+ recommended to write functions that directly interact with hardware
+ registers in assembly.
+
+ * Functions must work on both emulators and real hardware.
+
+ * Don't forget to put your name in the readme file of the library you've
+ made a contribution on and details of what you've changed in the
+ changelog.txt file. Annoyingmous is not tolerated in this project.
+
* New functions that are not originally in the official SDK must be marked
- as original code in both the library headers and the libn00bref document.
+ as original code in both the library headers and the libn00bref document
+ to help differentiate from original functions and new additions.
-Library to-do list:
-
- Since the PSn00bSDK project still a work in progress, essential libraries
- for CD and controllers support are not yet created but are high priority.
+LibPSn00b to-do list:
- libc - Yet to include a complete C standard function
+ Because the PSn00bSDK project still a work in progress, a number of
+ essential libraries are considered but not yet developed. The following
+ lists a number of essential libraries not yet developed.
- psxcd - CD library. Not much progress as getting the CD controller to
- cooperate has been one heck of a force to be reckoned with.
- Gave up with my repeated attempts with no success. Absolutely
- huge props to anyone who can figure out how to use the CD
- controller properly! -Lameguy64
-
- psxpad - Pad/tap/gun library. No work has been done on it currently.
- Supporting the Konami Justifier can be ignored as the way how
- that lightgun works is pretty crude and likely going to be
- awful to implement. Namco's Guncon is a lot simpler to
- implement.
-
- psxpress - MDEC library. No work has been done on it currently. libpress
- from the official libraries also contains functions for
- encoding SPU compatible ADPCM data from raw PCM samples.
-
- Before implementing CD and controller support a better interrupt handling
- scheme must be implemented as it would save a lot of trouble. Details
- regarding this interrupt handler implementation can be found in psxgpu's
- readme document. \ No newline at end of file
+ psxcd - Full CD-ROM support library.
+
+ psxpad - Pad/tap/gun library for better controller support. May support
+ PS2 controllers natively. Should provide functions for directly
+ controlling the controller/memory card interfaces to cater to
+ development of custom peripherals.
+
+ psxmcrd - Better and faster memory card library that works alongside the
+ psxpad library.
+
+ psxpress - MDEC and data decompression library. May use DEFLATE for
+ compressing MDEC data instead of Huffman as used in the
+ official libraries, which may yield better compression and
+ higher quality FMVs. \ No newline at end of file
diff --git a/tools/smxlink/main.cpp b/tools/smxlink/main.cpp
index ec6f707..8072274 100644
--- a/tools/smxlink/main.cpp
+++ b/tools/smxlink/main.cpp
@@ -314,7 +314,7 @@ int main(int argc, const char* argv[]) {
prim = (PRIM_ID*)priptr;
- if( smxPrimitive->IntAttribute( "double", 0 ) )
+ if( smxPrimitive->IntAttribute( "double" ) )
prim->nocull = true;
if( ( strcasecmp( "F3", primType ) == 0 ) ||