From 84422eceb3ecaa325f814b306665e58b0c3be647 Mon Sep 17 00:00:00 2001 From: "John Wilbert M. Villamor" Date: Fri, 28 Feb 2020 11:41:30 +0800 Subject: Added CdOpenDir(), CdReadDir() and CdCloseDir(). Fixed SpuKeyOn() bug and added cdbrowse example. --- changelog.txt | 23 ++ doc/LibPSn00b Reference.odt | Bin 125874 -> 128542 bytes examples/cdbrowse/ball16c.h | 16 + examples/cdbrowse/iso.xml | 33 ++ examples/cdbrowse/main.c | 517 +++++++++++++++++++++++++ examples/cdbrowse/makefile | 59 +++ examples/cdbrowse/system.cnf | 4 + examples/cdxa/makefile | 1 - libpsn00b/include/psxcd.h | 61 ++- libpsn00b/include/psxgpu.h | 16 +- libpsn00b/psxcd/cdsearchfile.c | 663 -------------------------------- libpsn00b/psxcd/isofs.c | 852 +++++++++++++++++++++++++++++++++++++++++ libpsn00b/psxcd/psxcd_asm.s | 11 + libpsn00b/psxgpu/getode.s | 20 + libpsn00b/psxspu/spukeyon.s | 3 +- 15 files changed, 1586 insertions(+), 693 deletions(-) create mode 100644 examples/cdbrowse/ball16c.h create mode 100644 examples/cdbrowse/iso.xml create mode 100644 examples/cdbrowse/main.c create mode 100644 examples/cdbrowse/makefile create mode 100644 examples/cdbrowse/system.cnf delete mode 100644 libpsn00b/psxcd/cdsearchfile.c create mode 100644 libpsn00b/psxcd/isofs.c create mode 100644 libpsn00b/psxgpu/getode.s diff --git a/changelog.txt b/changelog.txt index 5c0f824..9754e27 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,29 @@ PSn00bSDK changelog Items that are lower in the log are more recently implemented. +02-28-2020 by Lameguy64: + +* documentation: Added docs for CdOpenDir(), CdReadDir() and CdCloseDir(). + +* psxgpu: Added GetODE(). + +* psxspu: Fixed SpuKeyOn() bug where only 16 of the 24 channels can be + activated, due to channel bits being written as a 16-bit word. + +* psxcd: Added CdOpenDir(), CdReadDir() and CdCloseDir() for parsing directories. + +* psxcd: Issuing CdlNop (GetStat) commands now triggers the media change flag + internal to the libraries when CD lid is opened, so file system functions can + update the cached ISO descriptor when the disc has been changed. + +* psxcd: Made internal variables and functions for iso9660 parsing static. + + +02-25-2020 by thp: + +* libc: Added abs and labs() functions. + + 01-06-2020 by Lameguy64: * libpsn00b: Renamed libpsxcd directory to psxcd to match with other libraries. diff --git a/doc/LibPSn00b Reference.odt b/doc/LibPSn00b Reference.odt index 1b4afef..5586ff5 100644 Binary files a/doc/LibPSn00b Reference.odt and b/doc/LibPSn00b Reference.odt differ diff --git a/examples/cdbrowse/ball16c.h b/examples/cdbrowse/ball16c.h new file mode 100644 index 0000000..c79f273 --- /dev/null +++ b/examples/cdbrowse/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/cdbrowse/iso.xml b/examples/cdbrowse/iso.xml new file mode 100644 index 0000000..a828df1 --- /dev/null +++ b/examples/cdbrowse/iso.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/cdbrowse/main.c b/examples/cdbrowse/main.c new file mode 100644 index 0000000..7f91b44 --- /dev/null +++ b/examples/cdbrowse/main.c @@ -0,0 +1,517 @@ +/* + * LibPSn00b Example Programs + * + * CD File Browser Example + * 2020 Meido-Tek Productions / PSn00bSDK Project + * + * Demonstrates listing and browsing directory contents of a CD-ROM containing + * an ISO9660 file system, using the directory query functions of the libpsxcd + * library. + * + * The ISO9660 support in libpsxcd only supports the original ISO9660 + * version 1 file system specification, meaning it cannot query Rock Ridge + * or Joliet extensions that allow for long file names and unicode, despite + * the ISO9660 version 1 specification supporting names longer than 8.3 to + * begin with. However, discs written with such extensions should still be + * readable as the ISO9660 version should still be present for compatibility, + * with file names truncated to 8.3. + * + * + * Directory querying with libpsxcd is accomplished by using functions + * CdOpenDir(), CdReadDir() and CdCloseDir(). These functions work more or + * less the same as opendir(), readdir() and closedir() in *nix-like + * environments. While the library can support directories containing + * any number of files, the file browser in this example is limited to 40 + * entries, but this can be easily extended if need be. + * + * Differentiating file and directory entries is easily determined by whether + * or not the file has a version number suffix (ie. MYFILE.DAT;1). Directory + * records do not have a version number suffix. + * + * Currently, the only way to signal the isofs routines of libpsxcd that a + * disc change has occured is by simply issuing a CdlNop command. In a file + * browser that is aware of a disc change occuring at any moment a CdlNop + * command shall be issued at regular intervals of at least once a second. + * This also keeps CdStatus() up to date with disc presence. + * + * + * Controls: + * + * Up/Down - Move selection cursor. + * Cross - Enter directory. + * Circle - Go back to root directory. + * + * + * Example by Lameguy64 + * + * + * Changelog: + * + * February 25, 2020: Initial version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#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; + +/* Pad input buffer*/ +char padbuff[2][34]; + + +int query_dir(const char* path, CdlFILE* files, int max) +{ + CdlDIR* dir; + int files_found; + + printf( "Querying directory %s... ", path ); + files_found = 0; + + /* Open the directory */ + dir = CdOpenDir( path ); + if( dir ) + { + /* Read entries */ + while( CdReadDir( dir, &files[files_found] ) ) + { + files_found++; + if( files_found >= max ) + break; + } + + /* Close directory after query */ + CdCloseDir( dir ); + } + else + { + /* If directory path does not exist */ + printf( "Directory not found.\n" ); + return 0; + } + + printf( "Done.\n" ); + return files_found; +} + + +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, 400); + + + /* 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; istat == 0 ) + { + if(( pad->type == 0x4 )||( pad->type == 0x5 )||( pad->type == 0x7 )) + { + /* Menu controls */ + if( disc_present ) + { + if( !(pad->btn&PAD_UP) ) + { + if( !p_up ) + { + if( sel_channel > 0 ) + { + sel_channel--; + + if( (sel_channel-list_scroll) < 0 ) + { + list_scroll = sel_channel; + } + } + p_up = 1; + } + } + else + { + p_up = 0; + } + + if( !(pad->btn&PAD_DOWN) ) + { + if( !p_down ) + { + if( sel_channel < files_found-1 ) + { + sel_channel++; + + if( (sel_channel-list_scroll) > 15 ) + { + list_scroll = sel_channel-15; + } + } + p_down = 1; + } + } + else + { + p_down = 0; + } + } + + /* Enter a selected directory */ + if( !(pad->btn&PAD_CROSS) ) + { + if( !p_cross ) + { + if( disc_present ) + { + if( strchr( files[sel_channel].name, ';' ) == 0 ) + { + if( strcmp( files[sel_channel].name, ".." ) + == 0 ) + { + *(strrchr( path, '\\' )+1) = 0x0; + if( strlen( path ) > 1 ) + { + path[strlen( path )-1] = 0x0; + } + } + else if( strcmp( files[sel_channel].name, "." ) ) + { + if( strlen( path ) > 1 ) + { + strcat( path, "\\" ); + } + strcat( path, files[sel_channel].name ); + } + update_listing = true; + } + } + else + { + strcpy( path, "\\" ); + update_listing = true; + } + p_cross = 1; + } + } + else + { + p_cross = 0; + } + + /* Return to root directory */ + if( !(pad->btn&PAD_CIRCLE) ) + { + if( !p_circle ) + { + strcpy( path, "\\ ); + update_listing = true; + p_circle = 1; + } + } + else + { + p_circle = 0; + } + } + } + + + /* Updates directory listing */ + if( update_listing ) + { + if ( (CdStatus()&0x12) == 0x2 ) + { + + /* Reset path and update label if new disc inserted */ + if( !disc_present ) + { + strcpy( path, "\\" ); + CdGetVolumeLabel(disc_label); + disc_present = true; + } + + /* Query directory */ + files_found = query_dir( path, files, 40 ); + sel_channel = 0; + list_scroll = 0; + + } + update_listing = false; + } + + + /* Display information */ + FntPrint( -1, "\n PSN00BSDK CD BROWSER EXAMPLE\n\n" ); + + if( disc_present ) + { + FntPrint( -1, " FILES:%d LABEL:%s\n", files_found, disc_label ); + FntPrint( -1, " %s\n", path ); + + for(i=0; i<16; i++) + { + if( (i+list_scroll) > (files_found-1) ) + break; + + if( (i+list_scroll) == sel_channel ) + { + FntPrint( -1, " ->%s\n", files[i+list_scroll].name ); + } + else + { + FntPrint( -1, " %s\n", files[i+list_scroll].name ); + } + + } + } + else + { + if( (CdStatus()&0x12) == 0x2 ) + { + FntPrint( -1, "\n PRESS TO LIST CONTENTS %x\n", + CdStatus() ); + } + else + { + FntPrint( -1, "\n NO DISC INSERTED %x\n", + CdStatus() ); + } + } + + /* 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; ix, 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 a CdlNop to keep CdStatus() updated */ + counter++; + if( (counter%60) == 59 ) + { + CdControl(CdlNop, 0, 0); + } + } + + return 0; + +} diff --git a/examples/cdbrowse/makefile b/examples/cdbrowse/makefile new file mode 100644 index 0000000..7e90b3c --- /dev/null +++ b/examples/cdbrowse/makefile @@ -0,0 +1,59 @@ +include ../sdk-common.mk + +TARGET = cdbrowse.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: + rm -rf build $(TARGET) $(TARGET:.elf=.exe) diff --git a/examples/cdbrowse/system.cnf b/examples/cdbrowse/system.cnf new file mode 100644 index 0000000..9cf5593 --- /dev/null +++ b/examples/cdbrowse/system.cnf @@ -0,0 +1,4 @@ +BOOT=cdrom:\cdbrowse.exe;1 +TCB=4 +EVENT=10 +STACK=801FFFF0 diff --git a/examples/cdxa/makefile b/examples/cdxa/makefile index c94f48c..57f1959 100644 --- a/examples/cdxa/makefile +++ b/examples/cdxa/makefile @@ -56,5 +56,4 @@ build/%.o: %.s $(CC) $(AFLAGS) $(INCLUDE) -c $< -o $@ clean: - make -C libpsxcd clean rm -rf build $(TARGET) $(TARGET:.elf=.exe) diff --git a/libpsn00b/include/psxcd.h b/libpsn00b/include/psxcd.h index 5bb1b5f..1d045d9 100644 --- a/libpsn00b/include/psxcd.h +++ b/libpsn00b/include/psxcd.h @@ -65,13 +65,21 @@ #define CdlDataEnd 0x04 #define CdlDiskError 0x05 +/* + * CD-ROM file system error codes (original) + */ +#define CdlIsoOkay 0x00 +#define CdlIsoSeekError 0x01 +#define CdlIsoReadError 0x02 +#define CdlIsoInvalidFs 0x03 + #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 +typedef struct _CdlLOC { u_char minute; u_char second; @@ -82,7 +90,7 @@ typedef struct CdlLOC /* * CD-ROM audio attenuation struct (volume) */ -typedef struct CdlATV +typedef struct _CdlATV { u_char val0; /* L -> SPU L */ u_char val1; /* L -> SPU R */ @@ -93,20 +101,23 @@ typedef struct CdlATV /* * CD-ROM file information struct */ -typedef struct CdlFILE +typedef struct _CdlFILE { CdlLOC loc; u_int size; char name[16]; } CdlFILE; -typedef struct CdlFILTER +typedef struct _CdlFILTER { u_char file; u_char chan; u_short pad; } CdlFILTER; +/* Directory query context */ +typedef void* CdlDIR; + /* Data callback */ typedef void (*CdlCB)(int, unsigned char *); @@ -114,33 +125,41 @@ typedef void (*CdlCB)(int, unsigned char *); extern "C" { #endif -int CdInit(int mode); +int CdInit(int mode); -CdlLOC *CdIntToPos(int i, CdlLOC *p); -int CdPosToInt(CdlLOC *p); -int CdGetToc(CdlLOC *toc); +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); +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); +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); +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 CdStatus(void); +int CdMode(void); -int CdMix(CdlATV *vol); +int CdMix(CdlATV *vol); /* ORIGINAL CODE */ -long *CdAutoPauseCallback(void(*func)()); +CdlDIR* CdOpenDir(const char* path); +int CdReadDir(CdlDIR* dir, CdlFILE* file); +void CdCloseDir(CdlDIR* dir); + +int CdGetVolumeLabel(char* label); + +long* CdAutoPauseCallback(void(*func)()); +int CdIsoError(); #ifdef __cplusplus } diff --git a/libpsn00b/include/psxgpu.h b/libpsn00b/include/psxgpu.h index 65d3f66..01b3280 100644 --- a/libpsn00b/include/psxgpu.h +++ b/libpsn00b/include/psxgpu.h @@ -540,9 +540,11 @@ extern "C" { void ResetGraph(int mode); -int GetVideoMode(); +int GetVideoMode(void); void SetVideoMode(int mode); +int GetODE(void); + void PutDispEnvRaw(DISPENV_RAW *disp); void PutDispEnv(DISPENV *disp); void PutDrawEnv(DRAWENV *draw); @@ -551,16 +553,16 @@ void SetDispMask(int mask); int VSync(int m); int DrawSync(int m); -void WaitGPUcmd(); -void WaitGPUdma(); +void WaitGPUcmd(void); +void WaitGPUdma(void); // Callback hook functions -void *VSyncCallback(void (*func)()); -void *DrawSyncCallback(void (*func)()); +void *VSyncCallback(void (*func)(void)); +void *DrawSyncCallback(void (*func)(void)); // Interrupt callback functions -void *DMACallback(int dma, void (*func)()); -void *InterruptCallback(int irq, void (*func)()); +void *DMACallback(int dma, void (*func)(void)); +void *InterruptCallback(int irq, void (*func)(void)); void *GetInterruptCallback(int irq); // Original void RestartCallback(); diff --git a/libpsn00b/psxcd/cdsearchfile.c b/libpsn00b/psxcd/cdsearchfile.c deleted file mode 100644 index 60e4377..0000000 --- a/libpsn00b/psxcd/cdsearchfile.c +++ /dev/null @@ -1,663 +0,0 @@ -#include -#include -#include -#include -#include -#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; iname, 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/psxcd/isofs.c b/libpsn00b/psxcd/isofs.c new file mode 100644 index 0000000..7d48eea --- /dev/null +++ b/libpsn00b/psxcd/isofs.c @@ -0,0 +1,852 @@ +#include +#include +#include +#include +#include +#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; + +typedef struct _CdlDIR_INT +{ + u_int _pos; + u_int _len; + u_char* _dir; +} CdlDIR_INT; + +// Leave non-aligned structure packing +#pragma pack(pop) + +extern char _cd_media_changed; + + +static int _cd_iso_last_dir_lba; +static u_char _cd_iso_descriptor_buff[2048]; +static u_char* _cd_iso_pathtable_buff=NULL; +static u_char* _cd_iso_directory_buff=NULL; +static int _cd_iso_directory_len; +static int _cd_iso_error=0; + +static 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 + _cd_iso_error = CdlIsoSeekError; + 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 + _cd_iso_error = CdlIsoReadError; + 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 + _cd_iso_error = CdlIsoInvalidFs; + 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 + _cd_iso_error = CdlIsoReadError; + return -1; + } + + _cd_iso_last_dir_lba = 0; + _cd_iso_error = CdlIsoOkay; + + return 0; +} + +static 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 + _cd_iso_error = CdlIsoSeekError; + 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 + _cd_iso_error = CdlIsoReadError; + 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 + _cd_iso_error = CdlIsoSeekError; + 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 remaining directory record.\n"); +#endif + _cd_iso_error = CdlIsoReadError; + return -1; + } + } + + _cd_iso_last_dir_lba = lba; + _cd_iso_error = CdlIsoOkay; + + return 0; +} + +#ifdef DEBUG + +static 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"); + +} + +static 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 + +static 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; +} + +static 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; +} + +static 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; +} + +static 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; +} + +static 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; iname, 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; +} + +CdlDIR *CdOpenDir(const char* path) +{ + CdlDIR_INT* dir; + int num_dirs; + int i,found_dir; + char tpath_rbuff[128]; + char* rbuff; + + ISO_PATHTABLE_ENTRY tbl_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; + } + + num_dirs = get_pathtable_entry( 0, NULL, NULL ); + + found_dir = 0; + for( i=1; i_len = _cd_iso_directory_len; + dir->_dir = malloc( _cd_iso_directory_len ); + + memcpy( dir->_dir, _cd_iso_directory_buff, _cd_iso_directory_len ); + + dir->_pos = 0; + + if( found_dir == 1 ) + { + ISO_DIR_ENTRY *dir_entry; + + for( i=0; i<2; i++ ) + { + dir_entry = (ISO_DIR_ENTRY*)(dir->_dir+dir->_pos); + dir->_pos += dir_entry->entryLength; + } + } + + return (CdlDIR)dir; +} + +int CdReadDir(CdlDIR *dir, CdlFILE* file) +{ + CdlDIR_INT* d_dir; + ISO_DIR_ENTRY* dir_entry; + + d_dir = (CdlDIR_INT*)dir; + + if( d_dir->_pos >= _cd_iso_directory_len ) + return 0; + + dir_entry = (ISO_DIR_ENTRY*)(d_dir->_dir+d_dir->_pos); + + if( d_dir->_dir[d_dir->_pos+sizeof(ISO_DIR_ENTRY)] == 0 ) + { + strcpy( file->name, "." ); + } + else if( d_dir->_dir[d_dir->_pos+sizeof(ISO_DIR_ENTRY)] == 1 ) + { + strcpy( file->name, ".." ); + } + else + { + strncpy( file->name, + d_dir->_dir+d_dir->_pos+sizeof(ISO_DIR_ENTRY), + dir_entry->identifierLen ); + } + + CdIntToPos( dir_entry->entryOffs.lsb, &file->loc ); + + file->size = dir_entry->entrySize.lsb; + + d_dir->_pos += dir_entry->entryLength; + + // Check if padding is reached (end of record sector) + if( d_dir->_dir[d_dir->_pos] == 0 ) + { + // Snap it to next sector + d_dir->_pos = ((d_dir->_pos+2047)>>11)<<11; + } + + return 1; +} + +void CdCloseDir(CdlDIR *dir) +{ + CdlDIR_INT* d_dir; + + d_dir = (CdlDIR_INT*)dir; + + free( d_dir->_dir ); + free( d_dir ); +} + +int CdIsoError() +{ + return _cd_iso_error; +} + +int CdGetVolumeLabel(char* label) +{ + int i; + ISO_DESCRIPTOR* descriptor; + + if( _CdReadIsoDescriptor(0) ) + { + return -1; + } + + descriptor = (ISO_DESCRIPTOR*)_cd_iso_descriptor_buff; + + i = 0; + for( i=0; (descriptor->volumeID[i]!=0x20)&&(i<32); i++ ) + { + label[i] = descriptor->volumeID[i]; + } + + label[i] = 0x00; + + return 0; +} \ No newline at end of file diff --git a/libpsn00b/psxcd/psxcd_asm.s b/libpsn00b/psxcd/psxcd_asm.s index 7fe1c1d..0bfe5ca 100644 --- a/libpsn00b/psxcd/psxcd_asm.s +++ b/libpsn00b/psxcd/psxcd_asm.s @@ -371,6 +371,17 @@ _cd_fetch_result: .Lwrite_status: + andi $v1, $v0, 0x10 + + beqz $v1, .Lno_disc_change + nop + + la $v1, _cd_media_changed + addiu $a1, $0 , 1 + sw $a1, 0($v1) + +.Lno_disc_change: + sb $v0, 0($a0) .Lskip_status: diff --git a/libpsn00b/psxgpu/getode.s b/libpsn00b/psxgpu/getode.s new file mode 100644 index 0000000..5dc1e70 --- /dev/null +++ b/libpsn00b/psxgpu/getode.s @@ -0,0 +1,20 @@ +.set noreorder + +.include "hwregs_a.h" + +.section .text + + +.global GetODE +.type GetODE, @function +GetODE: + addiu $sp, -4 + sw $ra, 0($sp) + jal ReadGPUstat + nop + srl $v0, 31 + andi $v0, 1 + lw $ra, 0($sp) + addiu $sp, 4 + jr $ra + nop diff --git a/libpsn00b/psxspu/spukeyon.s b/libpsn00b/psxspu/spukeyon.s index 556f976..33592c2 100644 --- a/libpsn00b/psxspu/spukeyon.s +++ b/libpsn00b/psxspu/spukeyon.s @@ -11,6 +11,7 @@ SpuKeyOn: lui $v1, IOBASE li $v0, 1 sll $v0, $a0 - sh $v0, SPU_KEY_ON($v1) + sw $v0, SPU_KEY_ON($v1) + sw $v0, SPU_KEY_ON($v1) jr $ra nop \ No newline at end of file -- cgit v1.2.3