diff options
| author | John Wilbert M. Villamor <lameguy64@gmail.com> | 2020-09-19 20:43:05 +0800 |
|---|---|---|
| committer | John Wilbert M. Villamor <lameguy64@gmail.com> | 2020-09-19 20:43:05 +0800 |
| commit | 9f4891f95070c66ea9f1aba99d72724d4ab24e5a (patch) | |
| tree | 723e3ef2118a3d1a9e6dafa811ed1b8b1bc9196e /libpsn00b/psxcd/isofs.c | |
| parent | 6762c39551ded059450d17d8bb0cb80642c8aaab (diff) | |
| download | psn00bsdk-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.c | 400 |
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; +} |
