aboutsummaryrefslogtreecommitdiff
path: root/libpsn00b/psxcd/isofs.c
diff options
context:
space:
mode:
authorJohn Wilbert M. Villamor <lameguy64@gmail.com>2020-09-19 20:43:05 +0800
committerJohn Wilbert M. Villamor <lameguy64@gmail.com>2020-09-19 20:43:05 +0800
commit9f4891f95070c66ea9f1aba99d72724d4ab24e5a (patch)
tree723e3ef2118a3d1a9e6dafa811ed1b8b1bc9196e /libpsn00b/psxcd/isofs.c
parent6762c39551ded059450d17d8bb0cb80642c8aaab (diff)
downloadpsn00bsdk-9f4891f95070c66ea9f1aba99d72724d4ab24e5a.tar.gz
Revised makefiles, added strtok(), command line arguments, SetHeapSize(), moved ISR and callback system to psxetc, moved debug font to psxgpu, fixed CD-ROM library crashing on PSIO, fixed interrupt callback setup to fix crashing on ResetGraph()
Diffstat (limited to 'libpsn00b/psxcd/isofs.c')
-rw-r--r--libpsn00b/psxcd/isofs.c400
1 files changed, 229 insertions, 171 deletions
diff --git a/libpsn00b/psxcd/isofs.c b/libpsn00b/psxcd/isofs.c
index 149f746..11dba6c 100644
--- a/libpsn00b/psxcd/isofs.c
+++ b/libpsn00b/psxcd/isofs.c
@@ -4,152 +4,11 @@
#include <psxgpu.h>
#include <psxsio.h>
#include "psxcd.h"
+#include "isofs.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;
@@ -157,10 +16,7 @@ typedef struct _CdlDIR_INT
u_char* _dir;
} CdlDIR_INT;
-// Leave non-aligned structure packing
-#pragma pack(pop)
-
-extern char _cd_media_changed;
+extern int _cd_media_changed;
static int _cd_iso_last_dir_lba;
@@ -176,7 +32,37 @@ static int _CdReadIsoDescriptor(int session_offs)
CdlLOC loc;
ISO_DESCRIPTOR *descriptor;
- // Seek to volume descriptor location
+ // Check if the lid had been opened
+ if( !_cd_media_changed )
+ {
+ CdControl(CdlNop, 0, 0);
+ if( (CdStatus()&0x10) )
+ {
+ // Check if lid is still open
+ CdControl(CdlNop, 0, 0);
+ if( (CdStatus()&0x10) )
+ {
+#ifdef DEBUG
+ printf("psxcd: Lid is still open.\n");
+#endif
+ _cd_iso_error = CdlIsoLidOpen;
+ return -1;
+ }
+ // Reparse the file system
+ _cd_media_changed = 1;
+ }
+ }
+
+ if( !_cd_media_changed )
+ {
+ return 0;
+ }
+
+#ifdef DEBUG
+ printf("psxcd: Parsing ISO file system.\n");
+#endif
+
+ // Seek to volume descriptor
CdIntToPos(16+session_offs, &loc);
if( !CdControl(CdlSetloc, (u_char*)&loc, 0) )
{
@@ -186,9 +72,17 @@ static int _CdReadIsoDescriptor(int session_offs)
_cd_iso_error = CdlIsoSeekError;
return -1;
}
+
+#ifdef DEBUG
+ printf("psxcd: Set seek target.\n");
+#endif
+#ifdef DEBUG
+ printf("psxcd: Read sectors.\n");
+#endif
// Read volume descriptor
CdRead(1, (u_int*)_cd_iso_descriptor_buff, CdlModeSpeed);
+
if( CdReadSync(0, 0) )
{
#ifdef DEBUG
@@ -198,13 +92,16 @@ static int _CdReadIsoDescriptor(int session_offs)
return -1;
}
+#ifdef DEBUG
+ printf("psxcd: Read complete.\n");
+#endif
// 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");
+ printf("psxcd: Disc does not contain a ISO9660 file system.\n");
#endif
_cd_iso_error = CdlIsoInvalidFs;
return -1;
@@ -240,8 +137,10 @@ static int _CdReadIsoDescriptor(int session_offs)
return -1;
}
- _cd_iso_last_dir_lba = 0;
- _cd_iso_error = CdlIsoOkay;
+ _cd_iso_last_dir_lba = 0;
+ _cd_iso_error = CdlIsoOkay;
+
+ _cd_media_changed = 0;
return 0;
}
@@ -572,21 +471,21 @@ CdlFILE *CdSearchFile(CdlFILE *fp, const char *filename)
ISO_DIR_ENTRY dir_entry;
// Read ISO descriptor if changed flag is set
- if( _cd_media_changed )
- {
+ //if( _cd_media_changed )
+ //{
// Read ISO descriptor and path table
- if( _CdReadIsoDescriptor(0) )
- {
+ if( _CdReadIsoDescriptor(0) )
+ {
#ifdef DEBUG
- printf("psxcd: Could not read ISO file system.\n");
+ printf("psxcd: Could not read ISO file system.\n");
#endif
- return NULL;
- }
+ return NULL;
+ }
#ifdef DEBUG
- printf("psxcd: ISO file system cache updated.\n");
+ // printf("psxcd: ISO file system cache updated.\n");
#endif
- _cd_media_changed = 0;
- }
+ // _cd_media_changed = 0;
+ //}
// Get number of directories in path table
num_dirs = get_pathtable_entry(0, NULL, NULL);
@@ -692,21 +591,21 @@ CdlDIR *CdOpenDir(const char* path)
ISO_PATHTABLE_ENTRY tbl_entry;
// Read ISO descriptor if changed flag is set
- if( _cd_media_changed )
+// if( _cd_media_changed )
+// {
+ // Read ISO descriptor and path table
+ if( _CdReadIsoDescriptor( 0 ) )
{
- // Read ISO descriptor and path table
- if( _CdReadIsoDescriptor( 0 ) )
- {
#ifdef DEBUG
- printf( "psxcd: Could not read ISO file system.\n" );
+ printf( "psxcd: Could not read ISO file system.\n" );
#endif
- return NULL;
- }
+ return NULL;
+ }
#ifdef DEBUG
- printf( "psxcd: ISO file system cache updated.\n" );
+// printf( "psxcd: ISO file system cache updated.\n" );
#endif
- _cd_media_changed = 0;
- }
+// _cd_media_changed = 0;
+// }
num_dirs = get_pathtable_entry( 0, NULL, NULL );
@@ -775,10 +674,17 @@ int CdReadDir(CdlDIR *dir, CdlFILE* file)
CdlDIR_INT* d_dir;
ISO_DIR_ENTRY* dir_entry;
+ // Locks up in an infinite loop if directory record size is 6144 bytes
+
d_dir = (CdlDIR_INT*)dir;
if( d_dir->_pos >= _cd_iso_directory_len )
return 0;
+
+ // Some generated file systems have a premature NULL entry, consider this
+ // the end of the directory record
+ if( d_dir->_dir[d_dir->_pos] == 0 )
+ return 0;
dir_entry = (ISO_DIR_ENTRY*)(d_dir->_dir+d_dir->_pos);
@@ -800,9 +706,17 @@ int CdReadDir(CdlDIR *dir, CdlFILE* file)
CdIntToPos( dir_entry->entryOffs.lsb, &file->pos );
file->size = dir_entry->entrySize.lsb;
+
+#ifdef DEBUG
+ printf("dir_entry->entryLength = %d, ", dir_entry->entryLength);
+#endif
d_dir->_pos += dir_entry->entryLength;
+#ifdef DEBUG
+ printf("d_dir->_pos = %d\n", d_dir->_pos);
+#endif
+
// Check if padding is reached (end of record sector)
if( d_dir->_dir[d_dir->_pos] == 0 )
{
@@ -849,4 +763,148 @@ int CdGetVolumeLabel(char* label)
label[i] = 0x00;
return 0;
-} \ No newline at end of file
+}
+
+
+// Session load routine
+
+void _cd_control(unsigned char com, unsigned char *param, int plen);
+
+static volatile unsigned int _ready_oldcb;
+
+static volatile int _ses_scanfound;
+static volatile int _ses_scancount;
+static volatile int _ses_scancomplete;
+//static volatile char _ses_scan_resultbuff[8];
+static volatile char *_ses_scanbuff;
+
+static void _scan_callback(int status, unsigned char *result)
+{
+ if( status == CdlDataReady )
+ {
+ CdGetSector((void*)_ses_scanbuff, 2048);
+
+ if( _ses_scanbuff[0] == 0x1 )
+ {
+ if( strncmp((const char*)_ses_scanbuff+1, "CD001", 5) == 0 )
+ {
+ _cd_control(CdlPause, 0, 0);
+ _ses_scancomplete = 1;
+ _ses_scanfound = 1;
+ return;
+ }
+ }
+ _ses_scancount++;
+ if( _ses_scancount >= 512 )
+ {
+ _cd_control(CdlPause, 0, 0);
+ _ses_scancomplete = 1;
+ return;
+ }
+ }
+
+ if( status == CdlDiskError )
+ {
+ _cd_control(CdlPause, 0, 0);
+ _ses_scancomplete = 1;
+ }
+}
+
+int CdLoadSession(int session)
+{
+ CdlLOC *loc;
+ unsigned int ready_oldcb;
+ char scanbuff[2048];
+ char resultbuff[16];
+ int i;
+
+ // Seek to specified session
+#ifdef DEBUG
+ printf("psxcd: CdLoadSession(): Seeking to session %d...\n", session);
+#endif
+ CdControl(CdlSetsession, (unsigned char*)&session,
+ (unsigned char*)&resultbuff);
+
+ if( CdSync(0, 0) == CdlDiskError )
+ {
+#ifdef DEBUG
+ printf("psxcd: CdLoadSession(): Session seek failed, "
+ "session does not exist.\n");
+ printf("psxcd: CdLoadSession(): Restarting CD-ROM...\n");
+#endif
+
+ // Restart CD-ROM on session seek failure
+ CdControl(CdlNop, 0, 0);
+ CdControl(CdlInit, 0, 0);
+ CdSync(0, 0);
+
+ return -1;
+ }
+
+ // Set search routine callback
+ ready_oldcb = CdReadyCallback(_scan_callback);
+
+ _ses_scanfound = 0;
+ _ses_scancount = 0;
+ _ses_scancomplete = 0;
+ _ses_scanbuff = scanbuff;
+
+ // Begin scan for an ISO volume descriptor
+#ifdef DEBUG
+ printf("psxcd: CdLoadSession(): Scanning for ISO9660 volume descriptor.\n");
+#endif
+ i = CdlModeSpeed;
+ CdControl(CdlSetmode, (unsigned char*)&i, 0);
+ CdControl(CdlReadN, 0, (unsigned char*)resultbuff);
+
+ // Wait until scan complete
+ while(!_ses_scancomplete);
+
+ CdReadyCallback((void*)_ready_oldcb);
+
+ if( !_ses_scanfound )
+ {
+#ifdef DEBUG
+ printf("psxcd: CdLoadSession(): Did not find volume descriptor.\n");
+#endif
+ _cd_iso_error = CdlIsoInvalidFs;
+ CdReadyCallback((CdlCB)ready_oldcb);
+ return -1;
+ }
+
+ // Restore old callback if any
+ CdReadyCallback((CdlCB)ready_oldcb);
+
+ // Wait until CD-ROM has completely stopped reading, to get a consistent
+ // fix of the CD-ROM pickup's current location
+ do
+ {
+ VSync(2);
+ CdControl(CdlNop, 0, 0);
+ } while(CdStatus()&0xE0);
+
+ // Get location of volume descriptor
+ CdControl(CdlGetlocL, 0, (unsigned char*)resultbuff);
+ CdSync(0, 0);
+
+ loc = (CdlLOC*)resultbuff;
+
+#ifdef DEBUG
+ printf("psxcd: CdLoadSession(): Session found in %02d:%02d:%02d (LBA=%d)\n",
+ btoi(loc->minute), btoi(loc->second), btoi(loc->sector), CdPosToInt(loc));
+#endif
+
+ i = CdPosToInt(loc)-17;
+#ifdef DEBUG
+ printf("psxcd: CdLoadSession(): Session starting at LBA=%d\n", i);
+#endif
+
+ _cd_media_changed = 1;
+
+ if( _CdReadIsoDescriptor(i) )
+ {
+ return -1;
+ }
+
+ return 0;
+}