From 6ee55c23b042a1559e8cabfccf3b9d3320c4c5cc Mon Sep 17 00:00:00 2001 From: spicyjpeg Date: Thu, 6 Oct 2022 12:15:24 +0200 Subject: Replace psxgpu debug font, add CdGetSector2() --- libpsn00b/psxcd/cdgetsector.s | 56 ------------------------------------------- libpsn00b/psxcd/getsector.c | 35 +++++++++++++++++++++++++++ libpsn00b/psxcd/isofs.c | 8 +++---- libpsn00b/psxcd/psxcd_asm.s | 8 +------ 4 files changed, 40 insertions(+), 67 deletions(-) delete mode 100644 libpsn00b/psxcd/cdgetsector.s create mode 100644 libpsn00b/psxcd/getsector.c (limited to 'libpsn00b/psxcd') diff --git a/libpsn00b/psxcd/cdgetsector.s b/libpsn00b/psxcd/cdgetsector.s deleted file mode 100644 index 6a29069..0000000 --- a/libpsn00b/psxcd/cdgetsector.s +++ /dev/null @@ -1,56 +0,0 @@ -.set noreorder - -.include "hwregs_a.inc" - -.section .text - -.global CdGetSector -.type CdGetSector, @function -CdGetSector: - - lui $a2, IOBASE - -#.Lwait_fifo: # Probably redundant as the BIOS CD-ROM -# lbu $v0, CD_REG0($a2) # routines do not not wait for this -# nop -# andi $v0, 0x40 -# beqz $v0, .Lwait_fifo -# nop - - lui $v0, 0x1 -# srl $a1, 2 # (the official implementation expects $a1/size - # to be in 32-bit words rather than bytes) - or $v0, $a1 - sw $a0, DMA3_MADR($a2) # Set DMA base address and transfer length - sw $v0, DMA3_BCR($a2) - - lui $v0, 0x1100 # Start DMA transfer - sw $v0, DMA3_CHCR($a2) - nop - nop - -.Ldma_wait: # Ensure DMA transfer has completed - lw $v0, DMA3_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/psxcd/getsector.c b/libpsn00b/psxcd/getsector.c new file mode 100644 index 0000000..bc1c8ae --- /dev/null +++ b/libpsn00b/psxcd/getsector.c @@ -0,0 +1,35 @@ +/* + * PSn00bSDK CD drive library (sector DMA API) + * (C) 2022 spicyjpeg - MPL licensed + */ + +#include +#include +#include + +/* DMA transfer functions */ + +int CdGetSector(void *madr, int size) { + //while (!(CD_STAT & (1 << 6))) + //__asm__ volatile(""); + + DMA_MADR(3) = (uint32_t) madr; + DMA_BCR(3) = size | (1 << 16); + DMA_CHCR(3) = 0x11000000; + + while (DMA_CHCR(3) & (1 << 24)) + __asm__ volatile(""); + + return 1; +} + +int CdGetSector2(void *madr, int size) { + //while (!(CD_STAT & (1 << 6))) + //__asm__ volatile(""); + + DMA_MADR(3) = (uint32_t) madr; + DMA_BCR(3) = size | (1 << 16); + DMA_CHCR(3) = 0x11400100; // Transfer 1 word every 16 CPU cycles + + return 1; +} diff --git a/libpsn00b/psxcd/isofs.c b/libpsn00b/psxcd/isofs.c index 582b8d9..d620377 100644 --- a/libpsn00b/psxcd/isofs.c +++ b/libpsn00b/psxcd/isofs.c @@ -434,8 +434,8 @@ static int find_dir_entry(const char *name, ISO_DIR_ENTRY *dirent) static char* get_pathname(char *path, const char *filename) { - char *c = 0; - for (char *i = filename; *i; i++) { + const char *c = 0; + for (const char *i = filename; *i; i++) { if (IS_PATH_SEP(*i)) c = i; } @@ -453,8 +453,8 @@ static char* get_pathname(char *path, const char *filename) static char* get_filename(char *name, const char *filename) { - char *c = 0; - for (char *i = filename; *i; i++) { + const char *c = 0; + for (const char *i = filename; *i; i++) { if (IS_PATH_SEP(*i)) c = i; } diff --git a/libpsn00b/psxcd/psxcd_asm.s b/libpsn00b/psxcd/psxcd_asm.s index 906ab32..16e17d8 100644 --- a/libpsn00b/psxcd/psxcd_asm.s +++ b/libpsn00b/psxcd/psxcd_asm.s @@ -490,13 +490,7 @@ CdSyncCallback: .section .data - -.global psxcd_credits -.type psxcd_credits, @object -psxgpu_credits: - .ascii "psxcd library programs by Lameguy64\n" - .asciiz "2020 PSn00bSDK Project / Meido-Tek Productions\n" - + .comm _cd_last_cmd, 1, 1 .comm _cd_last_mode, 1, 1 .comm _cd_ack_wait, 1, 1 -- cgit v1.2.3 From 3acc4f93f3b6a96da484aab1f08d61f900085e43 Mon Sep 17 00:00:00 2001 From: spicyjpeg Date: Sat, 8 Oct 2022 10:12:31 +0200 Subject: Fix DMACallback bug, disable logging in release builds --- libpsn00b/libc/abort.c | 12 +- libpsn00b/psxapi/drivers.s | 24 ++-- libpsn00b/psxapi/stubs.json | 6 +- libpsn00b/psxcd/isofs.c | 251 ++++++++++++++++-------------------------- libpsn00b/psxcd/psxcd.c | 22 ++-- libpsn00b/psxetc/interrupts.c | 12 +- libpsn00b/psxgpu/common.c | 14 ++- libpsn00b/psxgpu/image.c | 14 ++- libpsn00b/psxpress/mdec.c | 16 ++- libpsn00b/psxspu/common.c | 22 ++-- 10 files changed, 181 insertions(+), 212 deletions(-) (limited to 'libpsn00b/psxcd') diff --git a/libpsn00b/libc/abort.c b/libpsn00b/libc/abort.c index de4323d..562b619 100644 --- a/libpsn00b/libc/abort.c +++ b/libpsn00b/libc/abort.c @@ -1,10 +1,16 @@ #include +#ifdef DEBUG +#define _LOG(...) printf(__VA_ARGS__) +#else +#define _LOG(...) +#endif + /* Standard abort */ void abort() { - printf("abort()\n"); + _LOG("abort()\n"); for (;;) __asm__ volatile(""); @@ -13,7 +19,7 @@ void abort() { /* Internal function used by assert() macro */ void _assert_abort(const char *file, int line, const char *expr) { - printf("%s:%d: assert(%s)\n", file, line, expr); + _LOG("%s:%d: assert(%s)\n", file, line, expr); for (;;) __asm__ volatile(""); @@ -22,7 +28,7 @@ void _assert_abort(const char *file, int line, const char *expr) { /* Pure virtual function call (C++) */ void __cxa_pure_virtual(void) { - printf("__cxa_pure_virtual()\n"); + _LOG("__cxa_pure_virtual()\n"); for (;;) __asm__ volatile(""); diff --git a/libpsn00b/psxapi/drivers.s b/libpsn00b/psxapi/drivers.s index 1cf5050..d991f90 100644 --- a/libpsn00b/psxapi/drivers.s +++ b/libpsn00b/psxapi/drivers.s @@ -90,26 +90,26 @@ ListDev: jr $t2 li $t1, 0x49 -.section .text.InitCard -.global InitCard -.type InitCard, @function -InitCard: +.section .text.InitCARD +.global InitCARD +.type InitCARD, @function +InitCARD: li $t2, 0xb0 jr $t2 li $t1, 0x4a -.section .text.StartCard -.global StartCard -.type StartCard, @function -StartCard: +.section .text.StartCARD +.global StartCARD +.type StartCARD, @function +StartCARD: li $t2, 0xb0 jr $t2 li $t1, 0x4b -.section .text.StopCard -.global StopCard -.type StopCard, @function -StopCard: +.section .text.StopCARD +.global StopCARD +.type StopCARD, @function +StopCARD: li $t2, 0xb0 jr $t2 li $t1, 0x4c diff --git a/libpsn00b/psxapi/stubs.json b/libpsn00b/psxapi/stubs.json index 200cbc7..50ffb55 100644 --- a/libpsn00b/psxapi/stubs.json +++ b/libpsn00b/psxapi/stubs.json @@ -362,19 +362,19 @@ { "type": "b", "id": 74, - "name": "InitCard", + "name": "InitCARD", "file": "drivers.s" }, { "type": "b", "id": 75, - "name": "StartCard", + "name": "StartCARD", "file": "drivers.s" }, { "type": "b", "id": 76, - "name": "StopCard", + "name": "StopCARD", "file": "drivers.s" }, { diff --git a/libpsn00b/psxcd/isofs.c b/libpsn00b/psxcd/isofs.c index d620377..6755d3f 100644 --- a/libpsn00b/psxcd/isofs.c +++ b/libpsn00b/psxcd/isofs.c @@ -10,6 +10,12 @@ // Uncommend to enable debug output //#define DEBUG +#ifdef DEBUG +#define _LOG(...) printf(__VA_ARGS__) +#else +#define _LOG(...) +#endif + #define DEFAULT_PATH_SEP '\\' #define IS_PATH_SEP(ch) (((ch) == '/') || ((ch) == '\\')) @@ -46,9 +52,8 @@ static int _CdReadIsoDescriptor(int session_offs) CdControl(CdlNop, 0, 0); if( (CdStatus()&0x10) ) { -#ifdef DEBUG - printf("psxcd: Lid is still open.\n"); -#endif + _LOG("psxcd: Lid is still open.\n"); + _cd_iso_error = CdlIsoLidOpen; return -1; } @@ -61,61 +66,47 @@ static int _CdReadIsoDescriptor(int session_offs) { return 0; } - -#ifdef DEBUG - printf("psxcd: Parsing ISO file system.\n"); -#endif + + _LOG("psxcd: Parsing ISO file system.\n"); // Seek to volume descriptor CdIntToPos(16+session_offs, &loc); if( !CdControl(CdlSetloc, (uint8_t*)&loc, 0) ) { -#ifdef DEBUG - printf("psxcd: Could not set seek destination.\n"); -#endif + _LOG("psxcd: Could not set seek destination.\n"); + _cd_iso_error = CdlIsoSeekError; return -1; } -#ifdef DEBUG - printf("psxcd: Set seek target.\n"); -#endif - -#ifdef DEBUG - printf("psxcd: Read sectors.\n"); -#endif + _LOG("psxcd: Read sectors.\n"); + // Read volume descriptor CdRead(1, (uint32_t*)_cd_iso_descriptor_buff, CdlModeSpeed); if( CdReadSync(0, 0) ) { -#ifdef DEBUG - printf("psxcd: Error reading ISO volume descriptor.\n"); -#endif + _LOG("psxcd: Error reading ISO volume descriptor.\n"); + _cd_iso_error = CdlIsoReadError; return -1; } - -#ifdef DEBUG - printf("psxcd: Read complete.\n"); -#endif - + + _LOG("psxcd: Read complete.\n"); + // 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 contain a ISO9660 file system.\n"); -#endif + _LOG("psxcd: Disc does not contain a ISO9660 file system.\n"); + _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 - + + _LOG("psxcd: Path table LBA = %d\n", descriptor->pathTable1Offs); + _LOG("psxcd: Path table len = %d\n", descriptor->pathTableSize.lsb); + // Allocate path table buffer i = ((2047+descriptor->pathTableSize.lsb)>>11)<<11; if( _cd_iso_pathtable_buff ) @@ -123,20 +114,17 @@ static int _CdReadIsoDescriptor(int session_offs) free(_cd_iso_pathtable_buff); } _cd_iso_pathtable_buff = (uint8_t*)malloc(i); - -#ifdef DEBUG - printf("psxcd_dbg: Allocated %d bytes for path table.\n", i); -#endif - + + _LOG("psxcd: Allocated %d bytes for path table.\n", i); + // Read path table CdIntToPos(descriptor->pathTable1Offs, &loc); CdControl(CdlSetloc, (uint8_t*)&loc, 0); CdRead(i>>11, (uint32_t*)_cd_iso_pathtable_buff, CdlModeSpeed); if( CdReadSync(0, 0) ) { -#ifdef DEBUG - printf("psxcd: Error reading ISO path table.\n"); -#endif + _LOG("psxcd: Error reading ISO path table.\n"); + _cd_iso_error = CdlIsoReadError; return -1; } @@ -162,14 +150,13 @@ static int _CdReadIsoDirectory(int lba) CdIntToPos(lba, &loc); i = CdPosToInt(&loc); -#ifdef DEBUG - printf("psxcd_dbg: Seek to sector %d\n", i); -#endif + + _LOG("psxcd_dbg: Seek to sector %d\n", i); + if( !CdControl(CdlSetloc, (uint8_t*)&loc, 0) ) { -#ifdef DEBUG - printf("psxcd: Could not set seek destination.\n"); -#endif + _LOG("psxcd: Could not set seek destination.\n"); + _cd_iso_error = CdlIsoSeekError; return -1; } @@ -184,28 +171,24 @@ static int _CdReadIsoDirectory(int lba) CdRead(1, (uint32_t*)_cd_iso_directory_buff, CdlModeSpeed); if( CdReadSync(0, 0) ) { -#ifdef DEBUG - printf("psxcd: Error reading initial directory record.\n"); -#endif + _LOG("psxcd: Error reading initial directory record.\n"); + _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 + + _LOG("psxcd: Location of directory record = %d\n", direntry->entryOffs.lsb); + _LOG("psxcd: Size of directory record = %d\n", _cd_iso_directory_len); if( _cd_iso_directory_len > 2048 ) { if( !CdControl(CdlSetloc, (uint8_t*)&loc, 0) ) { -#ifdef DEBUG - printf("psxcd: Could not set seek destination.\n"); -#endif + _LOG("psxcd: Could not set seek destination.\n"); + _cd_iso_error = CdlIsoSeekError; return -1; } @@ -213,16 +196,14 @@ static int _CdReadIsoDirectory(int lba) free(_cd_iso_directory_buff); i = ((2047+_cd_iso_directory_len)>>11)<<11; _cd_iso_directory_buff = (uint8_t*)malloc(i); -#ifdef DEBUG - printf("psxcd_dbg: Allocated %d bytes for directory record.\n", i); -#endif + + _LOG("psxcd: Allocated %d bytes for directory record.\n", i); CdRead(i>>11, (uint32_t*)_cd_iso_directory_buff, CdlModeSpeed); if( CdReadSync(0, 0) ) { -#ifdef DEBUG - printf("psxcd: Error reading remaining directory record.\n"); -#endif + _LOG("psxcd: Error reading remaining directory record.\n"); + _cd_iso_error = CdlIsoReadError; return -1; } @@ -243,7 +224,7 @@ static void dump_directory(void) ISO_DIR_ENTRY *dir_entry; char namebuff[16]; - printf("psxcd_dbg: Cached directory record contents:\n"); + _LOG("psxcd: Cached directory record contents:\n"); i = 0; dir_pos = 0; @@ -254,7 +235,7 @@ static void dump_directory(void) 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); + _LOG("P:%d L:%d %s\n", dir_pos, dir_entry->identifierLen, namebuff); dir_pos += dir_entry->entryLength; i++; @@ -273,7 +254,7 @@ static void dump_directory(void) } } - printf("--\n"); + _LOG("--\n"); } @@ -284,7 +265,7 @@ static void dump_pathtable(void) ISO_DESCRIPTOR *descriptor; char namebuff[16]; - printf("psxcd_dbg: Path table entries:\n"); + _LOG("psxcd: Path table entries:\n"); descriptor = (ISO_DESCRIPTOR*)_cd_iso_descriptor_buff; @@ -298,7 +279,7 @@ static void dump_pathtable(void) tbl_pos+sizeof(ISO_PATHTABLE_ENTRY), tbl_entry->nameLength); - printf("psxcd_dbg: %s\n", namebuff); + _LOG("psxcd: %s\n", namebuff); // Advance to next entry tbl_pos += sizeof(ISO_PATHTABLE_ENTRY) @@ -393,10 +374,8 @@ static int find_dir_entry(const char *name, ISO_DIR_ENTRY *dirent) int dir_pos; ISO_DIR_ENTRY *dir_entry; char namebuff[16]; - -#ifdef DEBUG - printf( "psxcd_dbg: Locating file %s.\n", name ); -#endif + + _LOG("psxcd: Locating file %s.\n", name); i = 0; dir_pos = 0; @@ -489,14 +468,11 @@ CdlFILE *CdSearchFile(CdlFILE *fp, const char *filename) // Read ISO descriptor and path table if( _CdReadIsoDescriptor(0) ) { -#ifdef DEBUG - printf("psxcd: Could not read ISO file system.\n"); -#endif + _LOG("psxcd: Could not read ISO file system.\n"); return NULL; } -#ifdef DEBUG - // printf("psxcd: ISO file system cache updated.\n"); -#endif + + // _LOG("psxcd: ISO file system cache updated.\n"); // _cd_media_changed = 0; //} @@ -504,25 +480,23 @@ CdlFILE *CdSearchFile(CdlFILE *fp, const char *filename) num_dirs = get_pathtable_entry(0, NULL, NULL); #ifdef DEBUG - printf("psxcd_dbg: Directories in path table: %d\n", num_dirs); + _LOG("psxcd: 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"); + _LOG("psxcd: Could not resolve path.\n"); } else { - printf("psxcd_dbg: Longest path: %s|\n", rbuff); + _LOG("psxcd: Longest path: %s|\n", rbuff); } #endif if( get_pathname(search_path, filename) ) { -#ifdef DEBUG - printf("psxcd_dbg: Search path = %s|\n", search_path); -#endif + _LOG("psxcd: Search path = %s|\n", search_path); } // Search the pathtable for a matching path @@ -530,9 +504,8 @@ CdlFILE *CdSearchFile(CdlFILE *fp, const char *filename) for(i=1; iname, filename); // Add version number if not specified @@ -577,15 +542,12 @@ CdlFILE *CdSearchFile(CdlFILE *fp, const char *filename) if( find_dir_entry(fp->name, &dir_entry) ) { -#ifdef DEBUG - printf("psxcd: Could not find file.\n"); -#endif + _LOG("psxcd: Could not find file.\n"); + return NULL; } - -#ifdef DEBUG - printf("psxcd_dbg: Located file at LBA %d.\n", dir_entry.entryOffs.lsb); -#endif + + _LOG("psxcd: Located file at LBA %d.\n", dir_entry.entryOffs.lsb); CdIntToPos(dir_entry.entryOffs.lsb, &fp->pos); fp->size = dir_entry.entrySize.lsb; @@ -609,14 +571,11 @@ CdlDIR *CdOpenDir(const char* path) // Read ISO descriptor and path table if( _CdReadIsoDescriptor( 0 ) ) { -#ifdef DEBUG - printf( "psxcd: Could not read ISO file system.\n" ); -#endif + _LOG( "psxcd: Could not read ISO file system.\n" ); return NULL; } -#ifdef DEBUG -// printf( "psxcd: ISO file system cache updated.\n" ); -#endif + +// _LOG( "psxcd: ISO file system cache updated.\n" ); // _cd_media_changed = 0; // } @@ -626,9 +585,8 @@ CdlDIR *CdOpenDir(const char* path) for( i=1; isize = dir_entry->entrySize.lsb; -#ifdef DEBUG - printf("dir_entry->entryLength = %d, ", dir_entry->entryLength); -#endif - + _LOG("dir_entry->entryLength = %d, ", dir_entry->entryLength); + d_dir->_pos += dir_entry->entryLength; - -#ifdef DEBUG - printf("d_dir->_pos = %d\n", d_dir->_pos); -#endif + + _LOG("d_dir->_pos = %d\n", d_dir->_pos); // Check if padding is reached (end of record sector) if( d_dir->_dir[d_dir->_pos] == 0 ) @@ -832,19 +779,15 @@ int CdLoadSession(int session) int i; // Seek to specified session -#ifdef DEBUG - printf("psxcd: CdLoadSession(): Seeking to session %d...\n", session); -#endif + _LOG("psxcd: CdLoadSession(): Seeking to session %d...\n", session); CdControl(CdlSetsession, (unsigned char*)&session, (unsigned char*)&resultbuff); if( CdSync(0, 0) == CdlDiskError ) { -#ifdef DEBUG - printf("psxcd: CdLoadSession(): Session seek failed, " + _LOG("psxcd: CdLoadSession(): Session seek failed, " "session does not exist.\n"); - printf("psxcd: CdLoadSession(): Restarting CD-ROM...\n"); -#endif + _LOG("psxcd: CdLoadSession(): Restarting CD-ROM...\n"); // Restart CD-ROM on session seek failure CdControl(CdlNop, 0, 0); @@ -863,9 +806,8 @@ int CdLoadSession(int session) _ses_scanbuff = scanbuff; // Begin scan for an ISO volume descriptor -#ifdef DEBUG - printf("psxcd: CdLoadSession(): Scanning for ISO9660 volume descriptor.\n"); -#endif + _LOG("psxcd: CdLoadSession(): Scanning for ISO9660 volume descriptor.\n"); + i = CdlModeSpeed; CdControl(CdlSetmode, (unsigned char*)&i, 0); CdControl(CdlReadN, 0, (unsigned char*)resultbuff); @@ -877,9 +819,8 @@ int CdLoadSession(int session) if( !_ses_scanfound ) { -#ifdef DEBUG - printf("psxcd: CdLoadSession(): Did not find volume descriptor.\n"); -#endif + _LOG("psxcd: CdLoadSession(): Did not find volume descriptor.\n"); + _cd_iso_error = CdlIsoInvalidFs; CdReadyCallback((CdlCB)ready_oldcb); return -1; @@ -901,16 +842,12 @@ int CdLoadSession(int session) CdSync(0, 0); loc = (CdlLOC*)resultbuff; - -#ifdef DEBUG - printf("psxcd: CdLoadSession(): Session found in %02d:%02d:%02d (LBA=%d)\n", + + _LOG("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 + _LOG("psxcd: CdLoadSession(): Session starting at LBA=%d\n", i); _cd_media_changed = 1; diff --git a/libpsn00b/psxcd/psxcd.c b/libpsn00b/psxcd/psxcd.c index 6340638..ac93376 100644 --- a/libpsn00b/psxcd/psxcd.c +++ b/libpsn00b/psxcd/psxcd.c @@ -20,13 +20,18 @@ volatile int _cd_last_sector_count; int _cd_media_changed; +#ifdef DEBUG +#define _LOG(...) printf(__VA_ARGS__) +#else +#define _LOG(...) +#endif + void _cd_init(void); void _cd_control(unsigned char com, const void *param, int plen); void _cd_wait_ack(void); void _cd_wait(void); -int CdInit(void) -{ +int CdInit(void) { // Sets up CD-ROM hardware and low-level subsystem _cd_init(); @@ -37,14 +42,11 @@ int CdInit(void) CdControl(CdlNop, 0, 0); CdControl(CdlInit, 0, 0); - if( CdSync(0, 0) != CdlDiskError ) - { + 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"); + _LOG("psxcd: setup done\n"); + } else { + _LOG("psxcd: initialization error, bad disc/drive or no disc inserted\n"); } return 1; @@ -319,7 +321,7 @@ static void CdDoRetry() { int cb; - printf( "CdRead: Retrying...\n" ); + _LOG("psxcd: retrying read...\n"); // Stop reading CdControl(CdlPause, 0, 0); diff --git a/libpsn00b/psxetc/interrupts.c b/libpsn00b/psxetc/interrupts.c index 859209a..1b5ac32 100644 --- a/libpsn00b/psxetc/interrupts.c +++ b/libpsn00b/psxetc/interrupts.c @@ -90,7 +90,7 @@ static void _global_dma_handler(void) { } } -/* Callback registration API */ +/* IRQ and DMA handler API */ void *InterruptCallback(int irq, void (*func)(void)) { if ((irq < 0) || (irq >= NUM_IRQ_CHANNELS)) @@ -127,12 +127,12 @@ void *DMACallback(int dma, void (*func)(void)) { // the callback is being registered or removed. The main DMA IRQ dispatcher // is also registered if this is the first DMA callback being configured, // or disabled if it's the last one being removed. - if (func) { + if (!old_callback && func) { DMA_DICR |= (0x10000 << dma) | (1 << 23); if (!(_num_dma_handlers++)) InterruptCallback(3, &_global_dma_handler); - } else { + } else if (old_callback && !func) { if (--_num_dma_handlers) { DMA_DICR &= ~(0x10000 << dma); } else { @@ -158,7 +158,7 @@ int ResetCallback(void) { return -1; EnterCriticalSection(); - _saved_irq_mask = 1 << 3; // Enable DMA IRQ by default + _saved_irq_mask = 0; _saved_dma_dpcr = 0x03333333; _saved_dma_dicr = 0; @@ -167,10 +167,6 @@ int ResetCallback(void) { for (int i = 0; i < NUM_DMA_CHANNELS; i++) _dma_handlers[i] = (void *) 0; - // Set up the DMA IRQ handler. This handler shall *not* be overridden using - // InterruptCallback(). - _irq_handlers[3] = &_global_dma_handler; - _96_remove(); RestartCallback(); return 0; diff --git a/libpsn00b/psxgpu/common.c b/libpsn00b/psxgpu/common.c index cef1508..e06c63a 100644 --- a/libpsn00b/psxgpu/common.c +++ b/libpsn00b/psxgpu/common.c @@ -29,7 +29,13 @@ static volatile uint8_t _queue_head, _queue_tail, _queue_length; static volatile uint32_t _vblank_counter; static volatile uint16_t _last_hblank; -/* Interrupt handlers */ +/* Private utilities and interrupt handlers */ + +#ifdef DEBUG +#define _LOG(...) printf(__VA_ARGS__) +#else +#define _LOG(...) +#endif static void _vblank_handler(void) { _vblank_counter++; @@ -69,7 +75,7 @@ void ResetGraph(int mode) { _gpu_video_mode = (GPU_GP1 >> 20) & 1; ExitCriticalSection(); - printf("psxgpu: setup done, default mode is %s\n", _gpu_video_mode ? "PAL" : "NTSC"); + _LOG("psxgpu: setup done, default mode is %s\n", _gpu_video_mode ? "PAL" : "NTSC"); } if (mode == 3) { @@ -108,7 +114,7 @@ static void _default_vsync_halt(void) { return; } - printf("psxgpu: VSync() timeout\n"); + _LOG("psxgpu: VSync() timeout\n"); ChangeClearPAD(0); ChangeClearRCnt(3, 0); } @@ -230,7 +236,7 @@ void DrawOTag(const uint32_t *ot) { } IRQ_MASK = mask; - printf("psxgpu: DrawOTag() failed, draw queue full\n"); + _LOG("psxgpu: DrawOTag() failed, draw queue full\n"); return; } diff --git a/libpsn00b/psxgpu/image.c b/libpsn00b/psxgpu/image.c index da51e7d..6190c7a 100644 --- a/libpsn00b/psxgpu/image.c +++ b/libpsn00b/psxgpu/image.c @@ -10,7 +10,13 @@ #define DMA_CHUNK_LENGTH 8 -/* VRAM transfer API */ +/* Private utilities */ + +#ifdef DEBUG +#define _LOG(...) printf(__VA_ARGS__) +#else +#define _LOG(...) +#endif static void _load_store_image( uint32_t command, @@ -20,11 +26,11 @@ static void _load_store_image( ) { size_t length = rect->w * rect->h; if (length % 2) - printf("psxgpu: can't transfer an odd number of pixels\n"); + _LOG("psxgpu: can't transfer an odd number of pixels\n"); length /= 2; if ((length >= DMA_CHUNK_LENGTH) && (length % DMA_CHUNK_LENGTH)) { - printf("psxgpu: transfer data length (%d) is not a multiple of %d, rounding\n", length, DMA_CHUNK_LENGTH); + _LOG("psxgpu: transfer data length (%d) is not a multiple of %d, rounding\n", length, DMA_CHUNK_LENGTH); length += DMA_CHUNK_LENGTH - 1; } @@ -50,6 +56,8 @@ static void _load_store_image( DMA_CHCR(2) = 0x01000200 | ((mode & 1) ^ 1); } +/* VRAM transfer API */ + void LoadImage(const RECT *rect, const uint32_t *data) { _load_store_image(0xa0000000, 2, rect, (uint32_t *) data); } diff --git a/libpsn00b/psxpress/mdec.c b/libpsn00b/psxpress/mdec.c index 9c82d6b..53c596e 100644 --- a/libpsn00b/psxpress/mdec.c +++ b/libpsn00b/psxpress/mdec.c @@ -10,7 +10,7 @@ #include #define DMA_CHUNK_LENGTH 32 -#define MDEC_SYNC_TIMEOUT 0x1000000 +#define MDEC_SYNC_TIMEOUT 0x100000 /* Default IDCT matrix and quantization tables */ @@ -81,6 +81,14 @@ static const DECDCTENV _default_mdec_env = { } }; +/* Private utilities */ + +#ifdef DEBUG +#define _LOG(...) printf(__VA_ARGS__) +#else +#define _LOG(...) +#endif + /* Public API */ void DecDCTReset(int mode) { @@ -127,7 +135,7 @@ void DecDCTin(const uint32_t *data, int mode) { // the stream. void DecDCTinRaw(const uint32_t *data, size_t length) { if ((length >= DMA_CHUNK_LENGTH) && (length % DMA_CHUNK_LENGTH)) { - printf("psxmdec: transfer data length (%d) is not a multiple of %d, rounding\n", length, DMA_CHUNK_LENGTH); + _LOG("psxpress: transfer data length (%d) is not a multiple of %d, rounding\n", length, DMA_CHUNK_LENGTH); length += DMA_CHUNK_LENGTH - 1; } @@ -149,7 +157,7 @@ int DecDCTinSync(int mode) { return 0; } - printf("psxpress: DecDCTinSync() timeout\n"); + _LOG("psxpress: DecDCTinSync() timeout\n"); return -1; } @@ -174,6 +182,6 @@ int DecDCToutSync(int mode) { return 0; } - printf("psxpress: DecDCToutSync() timeout\n"); + _LOG("psxpress: DecDCToutSync() timeout\n"); return -1; } diff --git a/libpsn00b/psxspu/common.c b/libpsn00b/psxspu/common.c index 55a3dba..4809684 100644 --- a/libpsn00b/psxspu/common.c +++ b/libpsn00b/psxspu/common.c @@ -17,7 +17,13 @@ static SPU_TransferMode _transfer_mode = SPU_TRANSFER_BY_DMA; static uint16_t _transfer_addr = WRITABLE_AREA_ADDR; -/* SPU initialization */ +/* Private utilities */ + +#ifdef DEBUG +#define _LOG(...) printf(__VA_ARGS__) +#else +#define _LOG(...) +#endif static void _wait_status(uint16_t mask, uint16_t value) { for (int i = STATUS_TIMEOUT; i; i--) { @@ -25,9 +31,11 @@ static void _wait_status(uint16_t mask, uint16_t value) { return; } - printf("psxspu: status register timeout (0x%04x)\n", SPU_STAT); + _LOG("psxspu: status register timeout (0x%04x)\n", SPU_STAT); } +/* Public API */ + void SpuInit(void) { SPU_CTRL = 0x0000; // SPU disabled _wait_status(0x001f, 0x0000); @@ -75,19 +83,17 @@ void SpuInit(void) { SPU_KEY_ON = 0x00ffffff; SPU_MASTER_VOL_L = 0x3fff; SPU_MASTER_VOL_R = 0x3fff; - SPU_CD_VOL_L = 0x3fff; - SPU_CD_VOL_R = 0x3fff; + SPU_CD_VOL_L = 0x7fff; + SPU_CD_VOL_R = 0x7fff; } -/* SPU RAM transfer API */ - static void _load_store_data(uint32_t *data, size_t length, int mode) { if (length % 4) - printf("psxspu: can't transfer a number of bytes that isn't multiple of 4\n"); + _LOG("psxspu: can't transfer a number of bytes that isn't multiple of 4\n"); length /= 4; if ((length >= DMA_CHUNK_LENGTH) && (length % DMA_CHUNK_LENGTH)) { - printf("psxspu: transfer data length (%d) is not a multiple of %d, rounding\n", length, DMA_CHUNK_LENGTH); + _LOG("psxspu: transfer data length (%d) is not a multiple of %d, rounding\n", length, DMA_CHUNK_LENGTH); length += DMA_CHUNK_LENGTH - 1; } -- cgit v1.2.3 From e0e608855b9b2e83a92047294e1f5a242ff51e88 Mon Sep 17 00:00:00 2001 From: spicyjpeg Date: Tue, 11 Oct 2022 11:46:24 +0200 Subject: Replace DEBUG macro with standard NDEBUG macro --- libpsn00b/cmake/flags.cmake | 2 +- libpsn00b/include/assert.h | 6 +++--- libpsn00b/libc/abort.c | 6 +++--- libpsn00b/psxcd/isofs.c | 15 ++++++--------- libpsn00b/psxcd/psxcd.c | 32 ++++++++++++++++---------------- libpsn00b/psxetc/dl.c | 6 +++--- libpsn00b/psxgpu/common.c | 6 +++--- libpsn00b/psxgpu/image.c | 6 +++--- libpsn00b/psxpress/mdec.c | 6 +++--- libpsn00b/psxspu/common.c | 6 +++--- 10 files changed, 44 insertions(+), 47 deletions(-) (limited to 'libpsn00b/psxcd') diff --git a/libpsn00b/cmake/flags.cmake b/libpsn00b/cmake/flags.cmake index e56d3fc..1ca25c2 100644 --- a/libpsn00b/cmake/flags.cmake +++ b/libpsn00b/cmake/flags.cmake @@ -86,5 +86,5 @@ target_link_options( target_compile_definitions( psn00bsdk INTERFACE PSN00BSDK=1 - $<$:DEBUG=1> + $<$:NDEBUG=1> ) diff --git a/libpsn00b/include/assert.h b/libpsn00b/include/assert.h index e27f2ed..32301e2 100644 --- a/libpsn00b/include/assert.h +++ b/libpsn00b/include/assert.h @@ -8,13 +8,13 @@ void _assert_abort(const char *file, int line, const char *expr); -#ifdef DEBUG +#ifdef NDEBUG +#define assert(x) +#else #define assert(expr) { \ if (!(expr)) \ _assert_abort(__FILE__, __LINE__, #expr); \ } -#else -#define assert(x) #endif #endif diff --git a/libpsn00b/libc/abort.c b/libpsn00b/libc/abort.c index 562b619..1108160 100644 --- a/libpsn00b/libc/abort.c +++ b/libpsn00b/libc/abort.c @@ -1,10 +1,10 @@ #include -#ifdef DEBUG -#define _LOG(...) printf(__VA_ARGS__) -#else +#ifdef NDEBUG #define _LOG(...) +#else +#define _LOG(...) printf(__VA_ARGS__) #endif /* Standard abort */ diff --git a/libpsn00b/psxcd/isofs.c b/libpsn00b/psxcd/isofs.c index 6755d3f..fb1f6c9 100644 --- a/libpsn00b/psxcd/isofs.c +++ b/libpsn00b/psxcd/isofs.c @@ -7,13 +7,10 @@ #include "psxcd.h" #include "isofs.h" -// Uncommend to enable debug output -//#define DEBUG - -#ifdef DEBUG -#define _LOG(...) printf(__VA_ARGS__) -#else +#ifdef NDEBUG #define _LOG(...) +#else +#define _LOG(...) printf(__VA_ARGS__) #endif #define DEFAULT_PATH_SEP '\\' @@ -215,7 +212,7 @@ static int _CdReadIsoDirectory(int lba) return 0; } -#ifdef DEBUG +#ifndef NDEBUG static void dump_directory(void) { @@ -479,7 +476,7 @@ CdlFILE *CdSearchFile(CdlFILE *fp, const char *filename) // Get number of directories in path table num_dirs = get_pathtable_entry(0, NULL, NULL); -#ifdef DEBUG +#ifndef NDEBUG _LOG("psxcd: Directories in path table: %d\n", num_dirs); rbuff = resolve_pathtable_path(num_dirs-1, tpath_rbuff+127); @@ -536,7 +533,7 @@ CdlFILE *CdSearchFile(CdlFILE *fp, const char *filename) strcat(fp->name, ";1"); } -#ifdef DEBUG +#ifndef NDEBUG dump_directory(); #endif diff --git a/libpsn00b/psxcd/psxcd.c b/libpsn00b/psxcd/psxcd.c index ac93376..65dea48 100644 --- a/libpsn00b/psxcd/psxcd.c +++ b/libpsn00b/psxcd/psxcd.c @@ -20,10 +20,10 @@ volatile int _cd_last_sector_count; int _cd_media_changed; -#ifdef DEBUG -#define _LOG(...) printf(__VA_ARGS__) -#else +#ifdef NDEBUG #define _LOG(...) +#else +#define _LOG(...) printf(__VA_ARGS__) #endif void _cd_init(void); @@ -88,7 +88,7 @@ int CdControlB(unsigned char com, const void *param, unsigned char *result) int CdControlF(unsigned char com, const void *param) { int param_len=0; - + // Command specific parameters switch(com) { @@ -116,21 +116,21 @@ int CdControlF(unsigned char com, const void *param) break; case CdlGetTD: param_len = 1; + break; + case CdlReadN: + case CdlReadS: + case CdlSeekL: + case CdlSeekP: + if( param ) + { + _cd_control(CdlSetloc, param, 3); + _cd_last_setloc = *((CdlLOC*)param); + } } - - // Issue Setloc if parameters are specified on CdlReadN and CdlReadS - if( ( com == CdlReadN ) || ( com == CdlReadS ) ) - { - if( param ) - { - _cd_control(CdlSetloc, param, 3); - _cd_last_setloc = *((CdlLOC*)param); - } - } - + // Issue CD command _cd_control(com, param, param_len); - + return 1; } diff --git a/libpsn00b/psxetc/dl.c b/libpsn00b/psxetc/dl.c index 6d37605..3d8f3ab 100644 --- a/libpsn00b/psxetc/dl.c +++ b/libpsn00b/psxetc/dl.c @@ -69,10 +69,10 @@ void *(*_dl_resolve_callback)(DLL *, const char *) = 0; /* Private utilities */ -#ifdef DEBUG -#define _LOG(...) printf(__VA_ARGS__) -#else +#ifdef NDEBUG #define _LOG(...) +#else +#define _LOG(...) printf(__VA_ARGS__) #endif #define _ERROR(code, ret) { \ diff --git a/libpsn00b/psxgpu/common.c b/libpsn00b/psxgpu/common.c index e06c63a..1e3d9e5 100644 --- a/libpsn00b/psxgpu/common.c +++ b/libpsn00b/psxgpu/common.c @@ -31,10 +31,10 @@ static volatile uint16_t _last_hblank; /* Private utilities and interrupt handlers */ -#ifdef DEBUG -#define _LOG(...) printf(__VA_ARGS__) -#else +#ifdef NDEBUG #define _LOG(...) +#else +#define _LOG(...) printf(__VA_ARGS__) #endif static void _vblank_handler(void) { diff --git a/libpsn00b/psxgpu/image.c b/libpsn00b/psxgpu/image.c index 6190c7a..a0d7065 100644 --- a/libpsn00b/psxgpu/image.c +++ b/libpsn00b/psxgpu/image.c @@ -12,10 +12,10 @@ /* Private utilities */ -#ifdef DEBUG -#define _LOG(...) printf(__VA_ARGS__) -#else +#ifdef NDEBUG #define _LOG(...) +#else +#define _LOG(...) printf(__VA_ARGS__) #endif static void _load_store_image( diff --git a/libpsn00b/psxpress/mdec.c b/libpsn00b/psxpress/mdec.c index 53c596e..d308994 100644 --- a/libpsn00b/psxpress/mdec.c +++ b/libpsn00b/psxpress/mdec.c @@ -83,10 +83,10 @@ static const DECDCTENV _default_mdec_env = { /* Private utilities */ -#ifdef DEBUG -#define _LOG(...) printf(__VA_ARGS__) -#else +#ifdef NDEBUG #define _LOG(...) +#else +#define _LOG(...) printf(__VA_ARGS__) #endif /* Public API */ diff --git a/libpsn00b/psxspu/common.c b/libpsn00b/psxspu/common.c index 4809684..d6508c7 100644 --- a/libpsn00b/psxspu/common.c +++ b/libpsn00b/psxspu/common.c @@ -19,10 +19,10 @@ static uint16_t _transfer_addr = WRITABLE_AREA_ADDR; /* Private utilities */ -#ifdef DEBUG -#define _LOG(...) printf(__VA_ARGS__) -#else +#ifdef NDEBUG #define _LOG(...) +#else +#define _LOG(...) printf(__VA_ARGS__) #endif static void _wait_status(uint16_t mask, uint16_t value) { -- cgit v1.2.3 From b458ea70700739bf8a64217af369c7ace08fc954 Mon Sep 17 00:00:00 2001 From: spicyjpeg Date: Thu, 13 Oct 2022 23:21:32 +0200 Subject: Fix dropped IRQs, clean up psxcd and psxetc logging --- doc/known_bugs.md | 7 +-- examples/system/childexec/CMakeLists.txt | 18 +++--- examples/system/childexec/child/child.c | 8 +-- examples/system/childexec/parent.c | 27 +++------ libpsn00b/psxcd/isofs.c | 20 +++---- libpsn00b/psxcd/psxcd.c | 9 +-- libpsn00b/psxetc/dl.c | 98 ++++++++++++++------------------ libpsn00b/psxetc/interrupts.c | 50 +++++++++------- 8 files changed, 107 insertions(+), 130 deletions(-) (limited to 'libpsn00b/psxcd') diff --git a/doc/known_bugs.md b/doc/known_bugs.md index 9e4785c..620a805 100644 --- a/doc/known_bugs.md +++ b/doc/known_bugs.md @@ -37,11 +37,6 @@ fixed. due to the SPU status register being emulated incorrectly. They work as expected on other emulators as well as on real hardware. -`psxcd`: - -- Custom callbacks registered using `CdReadyCallback()` seem to be unstable on - DuckStation (and possibly on real hardware), occasionally dropping sectors. - `psxetc`: - `DL_LoadSymbolMapFromFile()`, `DL_LoadDLLFromFile()` and `dlopen()` have been @@ -54,4 +49,4 @@ fixed. See [README.md in the examples directory](../examples/README.md#examples-summary). ----------------------------------------- -_Last updated on 2022-10-11 by spicyjpeg_ +_Last updated on 2022-10-13 by spicyjpeg_ diff --git a/examples/system/childexec/CMakeLists.txt b/examples/system/childexec/CMakeLists.txt index 0c25ca4..e542d2a 100644 --- a/examples/system/childexec/CMakeLists.txt +++ b/examples/system/childexec/CMakeLists.txt @@ -13,14 +13,14 @@ project( file(GLOB _sources *.c) file(GLOB _child_sources child/*.c) -psn00bsdk_add_executable(parent GPREL ${_sources}) -psn00bsdk_add_executable(child GPREL ${_child_sources}) -#psn00bsdk_add_cd_image(childexec_iso childexec iso.xml DEPENDS parent) +psn00bsdk_add_executable(childexec GPREL ${_sources}) +psn00bsdk_add_executable(childexec_child GPREL ${_child_sources}) +#psn00bsdk_add_cd_image(childexec_iso childexec iso.xml DEPENDS childexec) -psn00bsdk_target_incbin(parent PRIVATE ball16c ball16c.tim) +psn00bsdk_target_incbin(childexec PRIVATE ball16c ball16c.tim) psn00bsdk_target_incbin( - parent PRIVATE child_exe - ${PROJECT_BINARY_DIR}/child.exe + childexec PRIVATE child_exe + ${PROJECT_BINARY_DIR}/childexec_child.exe ) # Relocate the child executable to a non-default address to prevent it from @@ -28,9 +28,9 @@ psn00bsdk_target_incbin( # NOTE: child executables are not position-independent and can't be relocated # at runtime. If you need your code to be relocatable (e.g. to load it into a # dynamically-allocated buffer), consider using a DLL instead. -target_link_options(child PRIVATE -Ttext=0x80030000) +target_link_options(childexec_child PRIVATE -Ttext=0x80030000) # Make sure the child executable is built before the parent. -add_dependencies(parent child) +add_dependencies(childexec childexec_child) -install(FILES ${PROJECT_BINARY_DIR}/parent.exe TYPE BIN) +install(FILES ${PROJECT_BINARY_DIR}/childexec.exe TYPE BIN) diff --git a/examples/system/childexec/child/child.c b/examples/system/childexec/child/child.c index bd17440..dcfbfaf 100644 --- a/examples/system/childexec/child/child.c +++ b/examples/system/childexec/child/child.c @@ -98,8 +98,8 @@ MATRIX light_mtx = { char pad_buff[2][34]; /* Function declarations */ -void init(); -void display(); +void init(void); +void display(void); /* Main function */ @@ -245,7 +245,7 @@ int main(int argc, const char *argv[]) { } -void init() { +void init(void) { /* Reset the GPU, also installs a VSync event handler */ ResetGraph( 0 ); @@ -300,7 +300,7 @@ void init() { } -void display() { +void display(void) { /* Wait for GPU to finish drawing and vertical retrace */ DrawSync( 0 ); diff --git a/examples/system/childexec/parent.c b/examples/system/childexec/parent.c index 3e7d218..83d964c 100644 --- a/examples/system/childexec/parent.c +++ b/examples/system/childexec/parent.c @@ -67,12 +67,12 @@ extern const uint32_t ball16c[]; TIM_IMAGE tim; -void run_child(); +void run_child(void); char pad_buff[2][34]; -void init() { +void init(void) { int i; @@ -270,10 +270,7 @@ typedef struct { // Child program address extern char child_exe[]; -// Manually defined as its not defined in psxapi by default -void SetDefaultExitFromException(); - -void run_child() { +void run_child(void) { // Arguments for the child program char *args[] = @@ -289,29 +286,23 @@ void run_child() { // Copy child executable to its intended adddress memcpy((void*)exe->param.t_addr, child_exe+2048, exe->param.t_size); - // Enter critical section to prepare for program execution - EnterCriticalSection(); + // Prepare for program execution and disable interrupts + //EnterCriticalSection(); + StopCallback(); // Stop pads, enable auto acknowledge StopPAD(); ChangeClearPAD(1); ChangeClearRCnt(3, 1); - - // Set default exception handler just in case - //SetDefaultExitFromException(); - - // Last three function calls could be relegated to - // a StopCallback() function in the future. - + // Execute child printf("Child exec!\n"); Exec(&exe->param, 3, args); // Restore interrupts for this PS-EXE - EnterCriticalSection(); RestartCallback(); - ExitCriticalSection(); - + //ExitCriticalSection(); + // Re-init and re-enable pads InitPAD(pad_buff[0], 34, pad_buff[1], 34); StartPAD(); diff --git a/libpsn00b/psxcd/isofs.c b/libpsn00b/psxcd/isofs.c index fb1f6c9..16e64ef 100644 --- a/libpsn00b/psxcd/isofs.c +++ b/libpsn00b/psxcd/isofs.c @@ -148,7 +148,7 @@ static int _CdReadIsoDirectory(int lba) CdIntToPos(lba, &loc); i = CdPosToInt(&loc); - _LOG("psxcd_dbg: Seek to sector %d\n", i); + _LOG("psxcd: Seek to sector %d\n", i); if( !CdControl(CdlSetloc, (uint8_t*)&loc, 0) ) { @@ -232,7 +232,7 @@ static void dump_directory(void) strncpy(namebuff, _cd_iso_directory_buff+dir_pos+sizeof(ISO_DIR_ENTRY), dir_entry->identifierLen); - _LOG("P:%d L:%d %s\n", dir_pos, dir_entry->identifierLen, namebuff); + _LOG("psxcd: P:%d L:%d %s\n", dir_pos, dir_entry->identifierLen, namebuff); dir_pos += dir_entry->entryLength; i++; @@ -251,7 +251,7 @@ static void dump_directory(void) } } - _LOG("--\n"); + _LOG("psxcd: --\n"); } @@ -534,7 +534,7 @@ CdlFILE *CdSearchFile(CdlFILE *fp, const char *filename) } #ifndef NDEBUG - dump_directory(); + //dump_directory(); #endif if( find_dir_entry(fp->name, &dir_entry) ) @@ -582,7 +582,7 @@ CdlDIR *CdOpenDir(const char* path) for( i=1; isize = dir_entry->entrySize.lsb; - _LOG("dir_entry->entryLength = %d, ", dir_entry->entryLength); + _LOG("psxcd: dir_entry->entryLength = %d, ", dir_entry->entryLength); d_dir->_pos += dir_entry->entryLength; - _LOG("d_dir->_pos = %d\n", d_dir->_pos); + _LOG("psxcd: d_dir->_pos = %d\n", d_dir->_pos); // Check if padding is reached (end of record sector) if( d_dir->_dir[d_dir->_pos] == 0 ) diff --git a/libpsn00b/psxcd/psxcd.c b/libpsn00b/psxcd/psxcd.c index 65dea48..160a1ed 100644 --- a/libpsn00b/psxcd/psxcd.c +++ b/libpsn00b/psxcd/psxcd.c @@ -46,7 +46,7 @@ int CdInit(void) { CdControl(CdlDemute, 0, 0); _LOG("psxcd: setup done\n"); } else { - _LOG("psxcd: initialization error, bad disc/drive or no disc inserted\n"); + _LOG("psxcd: setup error, bad disc/drive or no disc inserted\n"); } return 1; @@ -106,14 +106,8 @@ int CdControlF(unsigned char com, const void *param) 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; break; @@ -126,6 +120,7 @@ int CdControlF(unsigned char com, const void *param) _cd_control(CdlSetloc, param, 3); _cd_last_setloc = *((CdlLOC*)param); } + break; } // Issue CD command diff --git a/libpsn00b/psxetc/dl.c b/libpsn00b/psxetc/dl.c index 3d8f3ab..cf4e466 100644 --- a/libpsn00b/psxetc/dl.c +++ b/libpsn00b/psxetc/dl.c @@ -34,9 +34,6 @@ /* Compile options */ -// Uncomment before building to enable debug logging (via printf()). -//#define DEBUG - // Comment before building to disable functions that rely on BIOS file APIs, // i.e. DL_LoadSymbolMapFromFile() and DL_LoadDLLFromFile(). // FIXME: those seem to be broken currently, and shouldn't be used anyway @@ -95,7 +92,7 @@ void *_dl_resolve_helper(DLL *dll, uint32_t index) { address = DL_GetSymbolByName(_name); if (!address) { - _LOG("psxetc: FATAL! Can't resolve %s, locking up\n", _name); + _LOG("psxetc: FATAL! can't resolve %s, locking up\n", _name); while (1) __asm__ volatile("nop"); } @@ -136,7 +133,7 @@ static uint32_t _elf_hash(const char *str) { static uint8_t *_dl_load_file(const char *filename, size_t *size_output) { int32_t fd = open(filename, 1); if (fd < 0) { - _LOG("psxetc: Can't open %s, error = %d\n", filename, fd); + _LOG("psxetc: can't open %s, error = %d\n", filename, fd); _ERROR(RTLD_E_FILE_OPEN, 0); } @@ -147,11 +144,11 @@ static uint8_t *_dl_load_file(const char *filename, size_t *size_output) { uint8_t *buffer = malloc(size); if (!buffer) { - _LOG("psxetc: Unable to allocate %d bytes for %s\n", size, filename); + _LOG("psxetc: unable to allocate %d bytes for %s\n", size, filename); _ERROR(RTLD_E_FILE_ALLOC, 0); } - _LOG("psxetc: Loading %s (%d bytes)..", filename, size); + //_LOG("psxetc: loading %s (%d bytes)..", filename, size); for (uint32_t offset = 0; offset < size; ) { int32_t length = read(fd, &(buffer[offset]), 0x800); @@ -164,7 +161,7 @@ static uint8_t *_dl_load_file(const char *filename, size_t *size_output) { _ERROR(RTLD_E_FILE_READ, 0); } - _LOG("."); + //_LOG("."); offset += length; } @@ -196,7 +193,7 @@ int32_t DL_ParseSymbolMap(const char *ptr, size_t size) { _symbol_map.nbucket = entries; _symbol_map.nchain = entries; _LOG( - "psxetc: Allocating nbucket = %d, nchain = %d\n", + "psxetc: allocating nbucket = %d, nchain = %d\n", _symbol_map.nbucket, entries ); @@ -208,7 +205,7 @@ int32_t DL_ParseSymbolMap(const char *ptr, size_t size) { _symbol_map.chain = malloc(sizeof(uint32_t) * entries); if (!_symbol_map.entries || !_symbol_map.bucket || !_symbol_map.chain) { - _LOG("psxetc: Unable to allocate symbol map table\n"); + _LOG("psxetc: unable to allocate symbol map table\n"); _ERROR(RTLD_E_MAP_ALLOC, -1); } @@ -251,13 +248,10 @@ int32_t DL_ParseSymbolMap(const char *ptr, size_t size) { (_type == 'D') || // .data (_type == 'B') // .bss )) { - _LOG( - "psxetc: Map sym: %08x,%08x [%c %s]\n", - address, - _size, - _type, - name - ); + //_LOG( + //"psxetc: map sym: %08x,%08x [%c %s]\n", + //address, _size, _type, name + //); MapEntry *entry = &(_symbol_map.entries[index]); entry->hash = hash; @@ -280,7 +274,7 @@ int32_t DL_ParseSymbolMap(const char *ptr, size_t size) { pos++; } - _LOG("psxetc: Parsed %d symbols\n", entries); + _LOG("psxetc: parsed %d symbols\n", entries); if (!entries) _ERROR(RTLD_E_NO_SYMBOLS, -1); @@ -313,7 +307,7 @@ void DL_UnloadSymbolMap(void) { void *DL_GetSymbolByName(const char *name) { if (!_symbol_map.entries) { - _LOG("psxetc: Attempted lookup with no map loaded\n"); + _LOG("psxetc: attempted lookup with no map loaded\n"); _ERROR(RTLD_E_NO_MAP, 0); } @@ -326,9 +320,8 @@ void *DL_GetSymbolByName(const char *name) { for (uint32_t i = _symbol_map.bucket[hash_mod]; i != 0xffffffff;) { if (i >= _symbol_map.nchain) { _LOG( - "psxetc: GetSymbolByName() index out of bounds (i = %d, n = %d)\n", - i, - _symbol_map.nchain + "psxetc: GetSymbolByName() index out of bounds (%d >= %d)\n", + i, _symbol_map.nchain ); _ERROR(RTLD_E_HASH_LOOKUP, 0); } @@ -336,14 +329,14 @@ void *DL_GetSymbolByName(const char *name) { MapEntry *entry = &(_symbol_map.entries[i]); if (hash == entry->hash) { - _LOG("psxetc: Map lookup [%s = %08x]\n", name, entry->ptr); + //_LOG("psxetc: map lookup [%s = %08x]\n", name, entry->ptr); return entry->ptr; } i = _symbol_map.chain[i]; } - _LOG("psxetc: Map lookup [%s not found]\n", name); + _LOG("psxetc: map lookup [%s not found]\n", name); _ERROR(RTLD_E_MAP_SYMBOL, 0); } @@ -359,14 +352,14 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) { DLL *dll = malloc(sizeof(DLL)); if (!dll) { - _LOG("psxetc: Unable to allocate DLL struct\n"); + _LOG("psxetc: unable to allocate DLL struct\n"); _ERROR(RTLD_E_DLL_ALLOC, 0); } dll->ptr = ptr; dll->malloc_ptr = (mode & RTLD_FREE_ON_DESTROY) ? ptr : 0; dll->size = size; - _LOG("psxetc: Initializing DLL at %08x\n", ptr); + _LOG("psxetc: initializing DLL at %08x\n", ptr); // Interpret the key-value pairs in the .dynamic section to obtain info // about all the other sections. The pairs are null-terminated, which makes @@ -375,33 +368,33 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) { uint32_t first_got_sym = 0; for (Elf32_Dyn *dyn = (Elf32_Dyn *) ptr; dyn->d_tag; dyn++) { - _LOG("psxetc: .dynamic %08x=%08x ", dyn->d_tag, dyn->d_un.d_val); + //_LOG("psxetc: .dynamic %08x=%08x ", dyn->d_tag, dyn->d_un.d_val); switch (dyn->d_tag) { // Offset of .got section case DT_PLTGOT: - _LOG("[PLTGOT]\n"); + //_LOG("[PLTGOT]\n"); dll->got = (void *) (ptr + dyn->d_un.d_val); break; // Offset of .hash section case DT_HASH: - _LOG("[HASH]\n"); + //_LOG("[HASH]\n"); dll->hash = (void *) (ptr + dyn->d_un.d_val); break; // Offset of .dynstr (NOT .strtab) section case DT_STRTAB: - _LOG("[STRTAB]\n"); + //_LOG("[STRTAB]\n"); dll->strtab = (void *) (ptr + dyn->d_un.d_val); break; // Offset of .dynsym (NOT .symtab) section case DT_SYMTAB: - _LOG("[SYMTAB]\n"); + //_LOG("[SYMTAB]\n"); dll->symtab = (void *) (ptr + dyn->d_un.d_val); break; @@ -413,67 +406,67 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) { // Length of each .dynsym entry case DT_SYMENT: - _LOG("[SYMENT]\n"); + //_LOG("[SYMENT]\n"); // Only 16-byte symbol table entries are supported. if (dyn->d_un.d_val != sizeof(Elf32_Sym)) { free(dll); - _LOG("psxetc: Invalid symtab entry size %d\n", dyn->d_un.d_val); + _LOG("psxetc: invalid DLL symtab entry size %d\n", dyn->d_un.d_val); _ERROR(RTLD_E_DLL_FORMAT, 0); } break; // MIPS ABI (?) version case DT_MIPS_RLD_VERSION: - _LOG("[MIPS_RLD_VERSION]\n"); + //_LOG("[MIPS_RLD_VERSION]\n"); // Versions other than 1 are unsupported (do they even exist?). if (dyn->d_un.d_val != 1) { free(dll); - _LOG("psxetc: Invalid DLL version %d\n", dyn->d_un.d_val); + _LOG("psxetc: invalid DLL version %d\n", dyn->d_un.d_val); _ERROR(RTLD_E_DLL_FORMAT, 0); } break; // DLL/ABI flags case DT_MIPS_FLAGS: - _LOG("[MIPS_FLAGS]\n"); + //_LOG("[MIPS_FLAGS]\n"); // Shortcut pointers (whatever they are) are not supported. if (dyn->d_un.d_val & RHF_QUICKSTART) { free(dll); - _LOG("psxetc: Invalid flags\n"); + _LOG("psxetc: invalid DLL flags\n"); _ERROR(RTLD_E_DLL_FORMAT, 0); } break; // Number of local (not to resolve) GOT entries case DT_MIPS_LOCAL_GOTNO: - _LOG("[MIPS_LOCAL_GOTNO]\n"); + //_LOG("[MIPS_LOCAL_GOTNO]\n"); local_got_len = dyn->d_un.d_val; break; // Base address DLL was compiled for case DT_MIPS_BASE_ADDRESS: - _LOG("[MIPS_BASE_ADDRESS]\n"); + //_LOG("[MIPS_BASE_ADDRESS]\n"); // Base addresses other than zero are not supported. It would // be easy enough to support them, but why? if (dyn->d_un.d_val) { free(dll); - _LOG("psxetc: Invalid base address %08x\n", dyn->d_un.d_val); + _LOG("psxetc: invalid DLL base address %08x\n", dyn->d_un.d_val); _ERROR(RTLD_E_DLL_FORMAT, 0); } break; // Number of symbol table entries case DT_MIPS_SYMTABNO: - _LOG("[MIPS_SYMTABNO]\n"); + //_LOG("[MIPS_SYMTABNO]\n"); dll->symbol_count = dyn->d_un.d_val; break; @@ -485,7 +478,7 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) { // Index of first symbol table entry which has a matching GOT entry case DT_MIPS_GOTSYM: - _LOG("[MIPS_GOTSYM]\n"); + //_LOG("[MIPS_GOTSYM]\n"); first_got_sym = dyn->d_un.d_val; break; @@ -495,8 +488,8 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) { //_LOG("[MIPS_HIPAGENO]\n"); //break; - default: - _LOG("[ignored]\n"); + //default: + //_LOG("[ignored]\n"); } } @@ -510,8 +503,7 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) { dll->got_length = local_got_len + (dll->symbol_count - first_got_sym) - 2; _LOG( "psxetc: %d symbols, %d GOT entries\n", - dll->symbol_count, - dll->got_length + dll->symbol_count, dll->got_length ); // Relocate the DLL by adding its base address to all pointers in the GOT @@ -538,12 +530,10 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) { continue; sym->st_value += (uint32_t) ptr; - _LOG( - "psxetc: DLL sym: %08x,%08x [%s]\n", - sym->st_value, - sym->st_size, - _name - ); + //_LOG( + //"psxetc: DLL sym: %08x,%08x [%s]\n", + //sym->st_value, sym->st_size, _name + //); // If RTLD_NOW was passed, resolve GOT entries ahead of time by // cross-referencing them with the symbol table. @@ -651,7 +641,7 @@ void *DL_GetDLLSymbol(const DLL *dll, const char *name) { // provided. for (uint32_t i = bucket[hash_mod]; i != 0xffffffff;) { if (i >= nchain) { - _LOG("psxetc: DL_GetDLLSymbol() index out of bounds (i = %d, n = %d)\n", i, nchain); + _LOG("psxetc: DL_GetDLLSymbol() index out of bounds (%d >= %d)\n", i, nchain); _ERROR(RTLD_E_HASH_LOOKUP, 0); } @@ -659,7 +649,7 @@ void *DL_GetDLLSymbol(const DLL *dll, const char *name) { const char *_name = &(dll->strtab[sym->st_name]); if (!strcmp(name, _name)) { - _LOG("psxetc: DLL lookup [%s = %08x]\n", name, sym->st_value); + //_LOG("psxetc: DLL lookup [%s = %08x]\n", name, sym->st_value); return sym->st_value; } diff --git a/libpsn00b/psxetc/interrupts.c b/libpsn00b/psxetc/interrupts.c index 1b5ac32..cc9d12c 100644 --- a/libpsn00b/psxetc/interrupts.c +++ b/libpsn00b/psxetc/interrupts.c @@ -53,40 +53,46 @@ static const struct JMP_BUF _isr_jmp_buf = { /* Internal IRQ and DMA handlers */ static void _global_isr(void) { - uint16_t stat = IRQ_STAT, mask = IRQ_MASK; + uint16_t stat = IRQ_STAT & IRQ_MASK; - // Clear all IRQ flags in one shot. This is not the "proper" way to do it - // but it's much faster than clearing one flag at a time. - IRQ_STAT = ~mask; + for (; stat; stat = IRQ_STAT & IRQ_MASK) { + //for (int i = 0; i < NUM_IRQ_CHANNELS; i++) { + for (int i = 0, mask = 1; stat; i++, stat >>= 1, mask <<= 1) { + if (!(stat & 1)) + continue; - //for (int i = 0; i < NUM_IRQ_CHANNELS; i++) { - for (int i = 0; stat; i++, stat >>= 1) { - if (!(stat & 1)) - continue; + // Acknowledge the current IRQ. Note that clearing all IRQ flags in one + // shot would result in hard-to-debug race conditions (been there, done + // that). + IRQ_STAT = (uint16_t) (mask ^ 0xffff); - if (_irq_handlers[i]) - _irq_handlers[i](); + if (_irq_handlers[i]) + _irq_handlers[i](); + } } ReturnFromException(); } static void _global_dma_handler(void) { - uint32_t stat = DMA_DICR; + uint32_t dicr = DMA_DICR; + uint32_t stat = (dicr >> 24) & 0x7f; + + for (; stat; dicr = DMA_DICR, stat = (dicr >> 24) & 0x7f) { + uint32_t base = dicr & 0x00ffffff; - // Clear all DMA IRQ flags in one shot (note that flags are cleared by - // writing 1 to them rather than 0). - stat &= 0x7fff0000; - DMA_DICR = stat; - stat >>= 24; + //for (int i = 0; i < NUM_DMA_CHANNELS; i++) { + for (int i = 0, mask = (1 << 24); stat; i++, stat >>= 1, mask <<= 1) { + if (!(stat & 1)) + continue; - //for (int i = 0; i < NUM_DMA_CHANNELS; i++) { - for (int i = 0; stat; i++, stat >>= 1) { - if (!(stat & 1)) - continue; + // Acknowledge the current DMA channel's IRQ. For whatever reason + // DMA IRQ flags are cleared by writing 1 to them rather than 0. + DMA_DICR = base | mask; - if (_dma_handlers[i]) - _dma_handlers[i](); + if (_dma_handlers[i]) + _dma_handlers[i](); + } } } -- cgit v1.2.3 From 03434a230d8c3ed2e32a3885128e05e42ee11769 Mon Sep 17 00:00:00 2001 From: spicyjpeg Date: Sun, 16 Oct 2022 23:52:19 +0200 Subject: Add mdec/strvideo example, fix psxpress bug --- examples/mdec/strvideo/CMakeLists.txt | 24 ++ examples/mdec/strvideo/iso.xml | 28 +++ examples/mdec/strvideo/main.c | 439 ++++++++++++++++++++++++++++++++++ examples/mdec/strvideo/system.cnf | 4 + libpsn00b/include/psxcd.h | 7 +- libpsn00b/psxcd/getsector.c | 23 ++ libpsn00b/psxcd/psxcd.c | 10 +- libpsn00b/psxpress/mdec.c | 5 + libpsn00b/psxpress/vlc.s | 10 +- libpsn00b/psxpress/vlc2.c | 5 +- 10 files changed, 539 insertions(+), 16 deletions(-) create mode 100644 examples/mdec/strvideo/CMakeLists.txt create mode 100644 examples/mdec/strvideo/iso.xml create mode 100644 examples/mdec/strvideo/main.c create mode 100644 examples/mdec/strvideo/system.cnf (limited to 'libpsn00b/psxcd') diff --git a/examples/mdec/strvideo/CMakeLists.txt b/examples/mdec/strvideo/CMakeLists.txt new file mode 100644 index 0000000..d41556b --- /dev/null +++ b/examples/mdec/strvideo/CMakeLists.txt @@ -0,0 +1,24 @@ +# PSn00bSDK example CMake script +# (C) 2021 spicyjpeg - MPL licensed + +cmake_minimum_required(VERSION 3.21) + +project( + strvideo + LANGUAGES C + VERSION 1.0.0 + DESCRIPTION "PSn00bSDK .STR video playback example" + HOMEPAGE_URL "http://lameguy64.net/?page=psn00bsdk" +) + +file(GLOB _sources *.c) +psn00bsdk_add_executable(strvideo GPREL ${_sources}) +#psn00bsdk_add_cd_image(strvideo_iso strvideo iso.xml DEPENDS strvideo) + +install( + FILES + #${PROJECT_BINARY_DIR}/strvideo.bin + #${PROJECT_BINARY_DIR}/strvideo.cue + ${PROJECT_BINARY_DIR}/strvideo.exe + TYPE BIN +) diff --git a/examples/mdec/strvideo/iso.xml b/examples/mdec/strvideo/iso.xml new file mode 100644 index 0000000..65e0ff5 --- /dev/null +++ b/examples/mdec/strvideo/iso.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + diff --git a/examples/mdec/strvideo/main.c b/examples/mdec/strvideo/main.c new file mode 100644 index 0000000..842bbb8 --- /dev/null +++ b/examples/mdec/strvideo/main.c @@ -0,0 +1,439 @@ +/* + * PSn00bSDK .STR FMV playback example + * (C) 2022 spicyjpeg - MPL licensed + * + * This example demonstrates playback of full-motion video in the standard .STR + * format, using the MDEC for frame decoding and XA for audio. Decoded frames + * are transferred directly to the main framebuffer in this example, but could + * also be output to another VRAM location and used as a background or texture + * for a 2D or 3D scene. + * + * Playing video files requires setting up a fairly complex pipeline, involving + * several buffers and components working in parallel: + * + * - .STR sectors are read continuously from the CD and each frame, usually + * spanning multiple sectors, is reassembled (demuxed) into a buffer in + * memory. In this example the task is performed by cd_sector_handler(). The + * CD drive handles XA-ADPCM sectors automatically, so no CPU intervention is + * necessary to play the audio track interleaved with the video. + * - Once a full frame has been demuxed, the bitstream data is parsed and + * decompressed by the CPU (using DecDCTvlc()) to an array of run-length + * codes to be fed to the MDEC. This is done in the main loop. + * - At the same time the last frame decompressed is read from RAM by the MDEC, + * which decodes it and outputs one 16-pixel-wide vertical slice at a time. + * - When a slice is ready, it is uploaded by mdec_dma_handler() to the current + * framebuffer in VRAM while the MDEC is decoding the next slice. + * A text overlay is drawn on top of the framebuffer using the GPU after the + * entire frame has been decoded. + * + * Since pretty much all buffers used are going to be read and written at the + * same time, double buffering is required for all of them. Every part of the + * pipeline must also run in lockstep with each other to prevent frame + * corruption, hence several functions and flag variables are used to stall the + * main loop until a frame is available for decoding and the MDEC is ready. + * Playback is stopped when a sector with the end-of-file flag set in the XA + * subheader (added at the end of the file by most .STR encoders) is + * encountered; in order to access the subheader, this example requests 2340 + * bytes of data for each sector (rather than the usual 2048) from the drive. + * + * Note that PSn00bSDK's bitstream decoding API only supports version 1 and 2 + * bitstreams currently, so make sure your .STR files are encoded as v2 and not + * v3. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Uncomment to display the video in 24bpp mode. Note that the GPU does not +// support 24bpp rendering, so the text overlay is only enabled in 16bpp mode. +//#define DISP_24BPP + +/* Display/GPU context utilities */ + +#define SCREEN_XRES 320 +#define SCREEN_YRES 240 + +#define BGCOLOR_R 0 +#define BGCOLOR_G 0 +#define BGCOLOR_B 0 + +typedef struct { + DISPENV disp; + DRAWENV draw; +} Framebuffer; + +typedef struct { + Framebuffer db[2]; + int db_active; +} RenderContext; + +void init_context(RenderContext *ctx) { + Framebuffer *db; + + ResetGraph(0); + ctx->db_active = 0; + + db = &(ctx->db[0]); + SetDefDispEnv(&(db->disp), 0, 0, SCREEN_XRES, SCREEN_YRES); + SetDefDrawEnv(&(db->draw), 0, SCREEN_YRES, SCREEN_XRES, SCREEN_YRES); + setRGB0(&(db->draw), BGCOLOR_R, BGCOLOR_G, BGCOLOR_B); + db->draw.isbg = 1; + db->draw.dtd = 1; + + db = &(ctx->db[1]); + SetDefDispEnv(&(db->disp), 0, SCREEN_YRES, SCREEN_XRES, SCREEN_YRES); + SetDefDrawEnv(&(db->draw), 0, 0, SCREEN_XRES, SCREEN_YRES); + setRGB0(&(db->draw), BGCOLOR_R, BGCOLOR_G, BGCOLOR_B); + db->draw.isbg = 1; + db->draw.dtd = 1; + + PutDrawEnv(&(db->draw)); + //PutDispEnv(&(db->disp)); + + // Create a text stream at the top of the screen. + FntLoad(960, 0); + FntOpen(4, 12, 312, 16, 2, 256); +} + +void display(RenderContext *ctx, int sync) { + Framebuffer *db; + ctx->db_active ^= 1; + + DrawSync(0); + if (sync) + VSync(0); + + db = &(ctx->db[ctx->db_active]); + PutDrawEnv(&(db->draw)); + PutDispEnv(&(db->disp)); + SetDispMask(1); +} + +/* CD and MDEC interrupt handlers */ + +#ifdef DISP_24BPP +#define BLOCK_SIZE 24 +#else +#define BLOCK_SIZE 16 +#define DRAW_OVERLAY +#endif + +#define VRAM_X_COORD(x) ((x) * BLOCK_SIZE / 16) + +// All non-audio sectors in .STR files begin with this 32-byte header, which +// contains metadata about the sector and is followed by a chunk of frame +// bitstream data. +// https://problemkaputt.de/psx-spx.htm#cdromfilevideostrstreamingandbspicturecompressionsony +typedef struct { + uint16_t magic; // Always 0x0160 + uint16_t type; // 0x8001 for MDEC + uint16_t sector_id; // Chunk number (0 = first chunk of this frame) + uint16_t sector_count; // Total number of chunks for this frame + uint32_t frame_id; // Frame number + uint32_t bs_length; // Total length of this frame in bytes + + uint16_t width, height; + uint8_t bs_header[8]; + uint32_t _reserved; +} STR_Header; + +// https://problemkaputt.de/psx-spx.htm#cdromxasubheaderfilechannelinterleave +typedef struct { + uint8_t file, channel; + uint8_t submode, coding_info; +} XA_Header; + +// https://problemkaputt.de/psx-spx.htm#cdromsectorencoding +typedef struct { + CdlLOC pos; + XA_Header xa_header[2]; + STR_Header str_header; + uint8_t data[2016]; + uint32_t edc; + uint8_t ecc[276]; +} STR_Sector; + +typedef struct { + uint16_t width, height; + uint32_t bs_data[0x2000]; // Bitstream data read from the disc + uint32_t mdec_data[0x8000]; // Decompressed data to be fed to the MDEC +} StreamBuffer; + +typedef struct { + StreamBuffer frames[2]; + uint32_t slices[2][BLOCK_SIZE * SCREEN_YRES / 2]; + + int frame_id, sector_count; + int dropped_frames; + RECT slice_pos; + int frame_width; + + volatile int8_t sector_pending, frame_ready; + volatile int8_t cur_frame, cur_slice; +} StreamContext; + +StreamContext str_ctx; + +// This buffer is used by cd_sector_handler() as a temporary area for sectors +// read from the CD. Due to DMA limitations it can't be allocated on the stack +// (especially not in the interrupt callbacks' stack, whose size is very +// limited). +STR_Sector sector_buffer; + +void cd_sector_handler(void) { + // Fetch the .STR header of the sector that has been read and check if the + // end-of-file bit is set in the XA header. + CdGetSector(§or_buffer, sizeof(STR_Sector) / 4); + + if ( + (sector_buffer.xa_header[0].submode & (1 << 7)) || + (sector_buffer.xa_header[1].submode & (1 << 7)) + ) { + CdControlF(CdlPause, 0); + str_ctx.frame_ready = -1; + return; + } + + STR_Header *header = §or_buffer.str_header; + StreamBuffer *frame = &str_ctx.frames[str_ctx.cur_frame]; + + // Ignore any non-MDEC sectors that might be present in the stream. + if (header->type != 0x8001) + return; + + // If this sector is actually part of a new frame, validate the sectors + // that have been read so far and flip the bitstream data buffers. + if (header->frame_id != str_ctx.frame_id) { + // Do not set the ready flag if any sector has been missed. + if (str_ctx.sector_count) + str_ctx.dropped_frames++; + else + str_ctx.frame_ready = 1; + + str_ctx.frame_id = header->frame_id; + str_ctx.sector_count = header->sector_count; + str_ctx.cur_frame ^= 1; + + frame = &str_ctx.frames[str_ctx.cur_frame]; + + // Initialize the next frame. Dimensions must be rounded up to the + // nearest multiple of 16 as the MDEC operates on 16x16 pixel blocks. + frame->width = (header->width + 15) & 0xfff0; + frame->height = (header->height + 15) & 0xfff0; + } + + // Append the payload contained in this sector to the current buffer. + memcpy( + &(frame->bs_data[2016 / 4 * header->sector_id]), + sector_buffer.data, + 2016 + ); + str_ctx.sector_count--; +} + +void mdec_dma_handler(void) { + // Handle any sectors that were not processed by cd_event_handler() (see + // below) while a DMA transfer from the MDEC was in progress. As the MDEC + // has just finished decoding a slice, they can be safely handled now. + if (str_ctx.sector_pending) { + cd_sector_handler(); + str_ctx.sector_pending = 0; + } + + // Upload the decoded slice to VRAM and start decoding the next slice (into + // another buffer) if any. + LoadImage(&str_ctx.slice_pos, str_ctx.slices[str_ctx.cur_slice]); + + str_ctx.cur_slice ^= 1; + str_ctx.slice_pos.x += BLOCK_SIZE; + + if (str_ctx.slice_pos.x < str_ctx.frame_width) + DecDCTout( + str_ctx.slices[str_ctx.cur_slice], + BLOCK_SIZE * str_ctx.slice_pos.h / 2 + ); +} + +void cd_event_handler(int event, uint8_t *payload) { + // Ignore all events other than a sector being ready. + if (event != CdlDataReady) + return; + + // Only handle sectors immediately if the MDEC is not decoding a frame, + // otherwise defer handling to mdec_dma_handler(). This is a workaround for + // a hardware conflict between the DMA channels used for the CD drive and + // MDEC output, which shall not run simultaneously. + if (DecDCTinSync(1)) + str_ctx.sector_pending = 1; + else + cd_sector_handler(); +} + +/* Stream helpers */ + +void init_stream(void) { + EnterCriticalSection(); + DMACallback(1, &mdec_dma_handler); + CdReadyCallback(&cd_event_handler); + ExitCriticalSection(); + + // Set the maximum amount of data DecDCTvlc() can output and copy the + // lookup table used for decompression to the scratchpad area. This is + // optional but makes the decompressor slightly faster. See the libpsxpress + // documentation for more details. + DecDCTvlcSize(0x8000); + DecDCTvlcCopyTable((DECDCTTAB *) 0x1f800000); + + str_ctx.dropped_frames = 0; + str_ctx.cur_frame = 0; + str_ctx.cur_slice = 0; +} + +StreamBuffer *get_next_frame(void) { + while (!str_ctx.frame_ready) + __asm__ volatile(""); + + if (str_ctx.frame_ready < 0) + return 0; + + str_ctx.frame_ready = 0; + return &str_ctx.frames[str_ctx.cur_frame ^ 1]; +} + +void start_stream(CdlFILE *file) { + str_ctx.frame_id = -1; + str_ctx.sector_pending = 0; + str_ctx.frame_ready = 0; + + CdSync(0, 0); + + // Configure the CD drive to read 2340-byte sectors at 2x speed and to + // play any XA-ADPCM sectors that might be interleaved with the video data. + uint8_t mode = CdlModeSize | CdlModeRT | CdlModeSpeed; + CdControl(CdlSetmode, (const uint8_t *) &mode, 0); + + // Start reading in real-time mode (i.e. without retrying in case of read + // errors) and wait for the first frame to be buffered. + CdControl(CdlReadS, &(file->pos), 0); + + get_next_frame(); +} + +/* Main */ + +static RenderContext ctx; + +#define SHOW_STATUS(...) { FntPrint(-1, __VA_ARGS__); FntFlush(-1); display(&ctx, 1); } +#define SHOW_ERROR(...) { SHOW_STATUS(__VA_ARGS__); while (1) __asm__("nop"); } + +int main(int argc, const char* argv[]) { + init_context(&ctx); + + SHOW_STATUS("INITIALIZING\n"); + SpuInit(); + CdInit(); + InitGeom(); // Required for PSn00bSDK's DecDCTvlc() + DecDCTReset(0); + + SHOW_STATUS("OPENING VIDEO FILE\n"); + + CdlFILE file; + if (!CdSearchFile(&file, "\\VIDEO.STR")) + SHOW_ERROR("FAILED TO FIND VIDEO.STR\n"); + + init_stream(); + start_stream(&file); + + // Disable framebuffer clearing to get rid of flickering during playback. + display(&ctx, 1); + ctx.db[0].draw.isbg = 0; + ctx.db[1].draw.isbg = 0; +#ifdef DISP_24BPP + ctx.db[0].disp.isrgb24 = 1; + ctx.db[1].disp.isrgb24 = 1; +#endif + + int decode_errors = 0; + + while (1) { + // Wait for a full frame to be read from the disc and decompress the + // bitstream into the format expected by the MDEC. If the video has + // ended, restart playback from the beginning. + StreamBuffer *frame = get_next_frame(); + if (!frame) { + start_stream(&file); + continue; + } + +#ifdef DRAW_OVERLAY + // Measure CPU usage of the decompressor using the hblank counter. + int total_time = TIMER_VALUE(1) + 1; + TIMER_VALUE(1) = 0; +#endif + + if (DecDCTvlc(frame->bs_data, frame->mdec_data)) { + decode_errors++; + continue; + } + +#ifdef DRAW_OVERLAY + int cpu_usage = TIMER_VALUE(1) * 100 / total_time; +#endif + + // Wait for the MDEC to finish decoding the previous frame, then flip + // the framebuffers to display it and prepare the buffer for the next + // frame. + // NOTE: you should *not* call VSync(0) during playback, as the refresh + // rate of the GPU is not synced to the video's frame rate. If you want + // to minimize screen tearing, consider triple buffering instead (i.e. + // always keep 2 fully decoded frames in VRAM and use VSyncCallback() + // to register a function that displays the next decoded frame whenever + // vblank occurs). + DecDCTinSync(0); + DecDCToutSync(0); + +#ifdef DRAW_OVERLAY + FntPrint(-1, "FRAME:%5d READ ERRORS: %5d\n", str_ctx.frame_id, str_ctx.dropped_frames); + FntPrint(-1, "CPU: %5d%% DECODE ERRORS:%5d\n", cpu_usage, decode_errors); + FntFlush(-1); +#endif + display(&ctx, 0); + + // Feed the newly decompressed frame to the MDEC. The MDEC will not + // actually start decoding it until an output buffer is also configured + // by calling DecDCTout() (see below). +#ifdef DISP_24BPP + DecDCTin(frame->mdec_data, DECDCT_MODE_24BPP); +#else + DecDCTin(frame->mdec_data, DECDCT_MODE_16BPP); +#endif + + // Place the frame at the center of the currently active framebuffer + // and start decoding the first slice. Decoded slices will be uploaded + // to VRAM in the background by mdec_dma_handler(). + RECT *fb_clip = &(ctx.db[ctx.db_active].draw.clip); + int x_offset = (fb_clip->w - frame->width) / 2; + int y_offset = (fb_clip->h - frame->height) / 2; + + str_ctx.slice_pos.x = VRAM_X_COORD(fb_clip->x + x_offset); + str_ctx.slice_pos.y = fb_clip->y + y_offset; + str_ctx.slice_pos.w = BLOCK_SIZE; + str_ctx.slice_pos.h = frame->height; + str_ctx.frame_width = VRAM_X_COORD(frame->width); + + DecDCTout( + str_ctx.slices[str_ctx.cur_slice], + BLOCK_SIZE * str_ctx.slice_pos.h / 2 + ); + } + + return 0; +} diff --git a/examples/mdec/strvideo/system.cnf b/examples/mdec/strvideo/system.cnf new file mode 100644 index 0000000..d199117 --- /dev/null +++ b/examples/mdec/strvideo/system.cnf @@ -0,0 +1,4 @@ +BOOT=cdrom:\strvideo.exe;1 +TCB=4 +EVENT=10 +STACK=801FFFF0 diff --git a/libpsn00b/include/psxcd.h b/libpsn00b/include/psxcd.h index cf9ecad..429a439 100644 --- a/libpsn00b/include/psxcd.h +++ b/libpsn00b/include/psxcd.h @@ -55,8 +55,10 @@ #define CdlModeAP 0x02 #define CdlModeRept 0x04 #define CdlModeSF 0x08 -#define CdlModeSize0 0x10 -#define CdlModeSize1 0x20 +//#define CdlModeSize0 0x10 +//#define CdlModeSize1 0x20 +#define CdlModeIgnore 0x10 +#define CdlModeSize 0x20 #define CdlModeRT 0x40 #define CdlModeSpeed 0x80 @@ -146,6 +148,7 @@ uint32_t CdSyncCallback(CdlCB func); long CdReadyCallback(CdlCB func); int CdGetSector(void *madr, int size); int CdGetSector2(void *madr, int size); +int CdDataSync(int mode); CdlFILE* CdSearchFile(CdlFILE *loc, const char *filename); diff --git a/libpsn00b/psxcd/getsector.c b/libpsn00b/psxcd/getsector.c index bc1c8ae..ee5315a 100644 --- a/libpsn00b/psxcd/getsector.c +++ b/libpsn00b/psxcd/getsector.c @@ -7,6 +7,16 @@ #include #include +#define DATA_SYNC_TIMEOUT 0x100000 + +/* Private utilities */ + +#ifdef NDEBUG +#define _LOG(...) +#else +#define _LOG(...) printf(__VA_ARGS__) +#endif + /* DMA transfer functions */ int CdGetSector(void *madr, int size) { @@ -33,3 +43,16 @@ int CdGetSector2(void *madr, int size) { return 1; } + +int CdDataSync(int mode) { + if (mode) + return (DMA_CHCR(3) >> 24) & 1; + + for (int i = DATA_SYNC_TIMEOUT; i; i--) { + if (!(DMA_CHCR(3) & (1 << 24))) + return 0; + } + + _LOG("psxcd: CdDataSync() timeout\n"); + return -1; +} diff --git a/libpsn00b/psxcd/psxcd.c b/libpsn00b/psxcd/psxcd.c index 160a1ed..f48542d 100644 --- a/libpsn00b/psxcd/psxcd.c +++ b/libpsn00b/psxcd/psxcd.c @@ -285,18 +285,10 @@ int CdRead(int sectors, uint32_t *buf, int mode) _cd_read_addr = buf; // Determine sector based on mode flags - if( mode & CdlModeSize0 ) - { - _cd_read_sector_sz = 2328 / 4; - } - else if( mode & CdlModeSize1 ) - { + if( mode & CdlModeSize ) _cd_read_sector_sz = 2340 / 4; - } else - { _cd_read_sector_sz = 2048 / 4; - } _cd_read_counter = VSync(-1); diff --git a/libpsn00b/psxpress/mdec.c b/libpsn00b/psxpress/mdec.c index d308994..06510cb 100644 --- a/libpsn00b/psxpress/mdec.c +++ b/libpsn00b/psxpress/mdec.c @@ -164,6 +164,11 @@ int DecDCTinSync(int mode) { void DecDCTout(uint32_t *data, size_t length) { DecDCToutSync(0); + if ((length >= DMA_CHUNK_LENGTH) && (length % DMA_CHUNK_LENGTH)) { + _LOG("psxpress: transfer data length (%d) is not a multiple of %d, rounding\n", length, DMA_CHUNK_LENGTH); + length += DMA_CHUNK_LENGTH - 1; + } + DMA_MADR(1) = (uint32_t) data; if (length < DMA_CHUNK_LENGTH) DMA_BCR(1) = 0x00010000 | length; diff --git a/libpsn00b/psxpress/vlc.s b/libpsn00b/psxpress/vlc.s index fe51642..885a3f7 100644 --- a/libpsn00b/psxpress/vlc.s +++ b/libpsn00b/psxpress/vlc.s @@ -131,10 +131,12 @@ _vlc_skip_context_load: #nop .Lprocess_dc_v2_coefficient: # if (!coeff_index && !is_v3) - # The DC coefficient in version 2 frames is not compressed. - srl $v0, $t0, 22 # *output = (window >> (32 - 10)) | quant_scale - or $v0, $t3 - addiu $t7, 1 # coeff_index++ + # The DC coefficient in version 2 frames is not compressed. Value 0x1ff is + # used to signal the end of the bitstream. + srl $v0, $t0, 22 # prefix = (window >> (32 - 10)) + li $v1, 0x01ff + beq $v0, $v1, .Lstop_processing # if (prefix == 0x1ff) break + or $v0, $t3 # *output = prefix | quant_scale sll $t0, 10 # window <<= 10 addiu $t5, -10 # bit_offset -= 10 b .Lwrite_value diff --git a/libpsn00b/psxpress/vlc2.c b/libpsn00b/psxpress/vlc2.c index 73b54b2..9eb99bf 100644 --- a/libpsn00b/psxpress/vlc2.c +++ b/libpsn00b/psxpress/vlc2.c @@ -141,7 +141,10 @@ int __attribute__((optimize(3))) DecDCTvlcContinue2( // TODO: version 3 is currently not supported. return -1; } else { - value = _get_bits_unsigned(10); + value = _get_bits_unsigned(10); + if (value == 0x1ff) + break; + *output = value | quant_scale; _advance_window(10); } -- cgit v1.2.3 From 2f100c78c0f12b56bcd73c203e6216d415d9f772 Mon Sep 17 00:00:00 2001 From: spicyjpeg Date: Mon, 17 Oct 2022 22:42:00 +0200 Subject: Remove interrupt disabling calls in psxcd callback APIs --- examples/cdrom/cdxa/main.c | 2 ++ libpsn00b/include/psxcd.h | 4 ++-- libpsn00b/psxcd/isofs.c | 19 ++++++++++++++----- libpsn00b/psxcd/psxcd.c | 11 ++++++++--- libpsn00b/psxcd/psxcd_asm.s | 30 ++++++------------------------ 5 files changed, 32 insertions(+), 34 deletions(-) (limited to 'libpsn00b/psxcd') diff --git a/examples/cdrom/cdxa/main.c b/examples/cdrom/cdxa/main.c index 4921658..93cf01a 100644 --- a/examples/cdrom/cdxa/main.c +++ b/examples/cdrom/cdxa/main.c @@ -349,7 +349,9 @@ int main(int argc, const char* argv[]) xa_loc = file.pos; /* Hook XA callback function to CdReadyCallback (for auto stop/loop */ + EnterCriticalSection(); CdReadyCallback(xa_callback); + ExitCriticalSection(); /* Set CD mode for XA streaming (2x speed, send XA to SPU, enable filter */ i = CdlModeSpeed|CdlModeRT|CdlModeSF; diff --git a/libpsn00b/include/psxcd.h b/libpsn00b/include/psxcd.h index 429a439..0460f20 100644 --- a/libpsn00b/include/psxcd.h +++ b/libpsn00b/include/psxcd.h @@ -145,7 +145,7 @@ int CdControlF(uint8_t com, const void *param); int CdSync(int mode, uint8_t *result); uint32_t CdSyncCallback(CdlCB func); -long CdReadyCallback(CdlCB func); +int CdReadyCallback(CdlCB func); int CdGetSector(void *madr, int size); int CdGetSector2(void *madr, int size); int CdDataSync(int mode); @@ -168,7 +168,7 @@ void CdCloseDir(CdlDIR* dir); int CdGetVolumeLabel(char* label); -long* CdAutoPauseCallback(void(*func)()); +int* CdAutoPauseCallback(void(*func)()); int CdIsoError(); int CdLoadSession(int session); diff --git a/libpsn00b/psxcd/isofs.c b/libpsn00b/psxcd/isofs.c index 16e64ef..4ec701c 100644 --- a/libpsn00b/psxcd/isofs.c +++ b/libpsn00b/psxcd/isofs.c @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include "psxcd.h" #include "isofs.h" @@ -795,8 +795,10 @@ int CdLoadSession(int session) } // Set search routine callback + EnterCriticalSection(); ready_oldcb = CdReadyCallback(_scan_callback); - + ExitCriticalSection(); + _ses_scanfound = 0; _ses_scancount = 0; _ses_scancomplete = 0; @@ -811,21 +813,28 @@ int CdLoadSession(int session) // Wait until scan complete while(!_ses_scancomplete); - + + EnterCriticalSection(); CdReadyCallback((void*)_ready_oldcb); - + ExitCriticalSection(); + if( !_ses_scanfound ) { _LOG("psxcd: CdLoadSession(): Did not find volume descriptor.\n"); _cd_iso_error = CdlIsoInvalidFs; + EnterCriticalSection(); CdReadyCallback((CdlCB)ready_oldcb); + ExitCriticalSection(); + return -1; } // Restore old callback if any + EnterCriticalSection(); CdReadyCallback((CdlCB)ready_oldcb); - + ExitCriticalSection(); + // Wait until CD-ROM has completely stopped reading, to get a consistent // fix of the CD-ROM pickup's current location do diff --git a/libpsn00b/psxcd/psxcd.c b/libpsn00b/psxcd/psxcd.c index f48542d..6730531 100644 --- a/libpsn00b/psxcd/psxcd.c +++ b/libpsn00b/psxcd/psxcd.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "psxcd.h" #define READ_TIMEOUT 600 // 10 seconds for NTSC @@ -293,8 +294,10 @@ int CdRead(int sectors, uint32_t *buf, int mode) _cd_read_counter = VSync(-1); // Set read callback + EnterCriticalSection(); _cd_read_oldcb = CdReadyCallback(_CdReadReadyCallback); - + ExitCriticalSection(); + // Set specified mode CdControl(CdlSetmode, (uint8_t*)&mode, 0); @@ -320,9 +323,11 @@ static void CdDoRetry() // Reset timeout _cd_read_counter = VSync(-1); - + + EnterCriticalSection(); CdReadyCallback(_CdReadReadyCallback); - + ExitCriticalSection(); + // Retry read CdControl(CdlSetloc, (void*)&_cd_last_setloc, 0); CdControl(CdlReadN, 0, (uint8_t*)_cd_read_result); diff --git a/libpsn00b/psxcd/psxcd_asm.s b/libpsn00b/psxcd/psxcd_asm.s index 16e17d8..c0a5312 100644 --- a/libpsn00b/psxcd/psxcd_asm.s +++ b/libpsn00b/psxcd/psxcd_asm.s @@ -413,17 +413,11 @@ CdAutoPauseCallback: 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 @@ -443,17 +437,11 @@ CdReadyCallback: 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 @@ -472,17 +460,11 @@ CdSyncCallback: 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 -- cgit v1.2.3 From 9b2ffc6078a850b7d354855cca7622090b41f30c Mon Sep 17 00:00:00 2001 From: spicyjpeg Date: Tue, 18 Oct 2022 17:29:42 +0200 Subject: Add debug log buffering, fix GetHeapUsage() --- libpsn00b/include/psxetc.h | 15 ++++++ libpsn00b/libc/abort.c | 16 ++----- libpsn00b/libc/malloc.c | 22 ++++----- libpsn00b/psxcd/getsector.c | 11 +---- libpsn00b/psxcd/isofs.c | 112 ++++++++++++++++++++------------------------ libpsn00b/psxcd/psxcd.c | 14 ++---- libpsn00b/psxetc/dl.c | 91 +++++++++++++++++------------------ libpsn00b/psxetc/logging.c | 50 ++++++++++++++++++++ libpsn00b/psxgpu/common.c | 31 +++++------- libpsn00b/psxgpu/env.c | 2 +- libpsn00b/psxgpu/image.c | 22 ++++----- libpsn00b/psxpress/mdec.c | 20 +++----- libpsn00b/psxspu/common.c | 14 ++---- 13 files changed, 216 insertions(+), 204 deletions(-) create mode 100644 libpsn00b/psxetc/logging.c (limited to 'libpsn00b/psxcd') diff --git a/libpsn00b/include/psxetc.h b/libpsn00b/include/psxetc.h index 24485d9..fcfec06 100644 --- a/libpsn00b/include/psxetc.h +++ b/libpsn00b/include/psxetc.h @@ -6,12 +6,27 @@ #ifndef __PSXETC_H #define __PSXETC_H +/* Macros */ + +// This macro is used internally by PSn00bSDK to log debug messages to a buffer +// which is then printed to stdout when calling VSync(). +#ifdef NDEBUG +#define _sdk_log(...) +#define _sdk_dump_log() +#else +#define _sdk_log(...) _sdk_log_inner(__VA_ARGS__) +#define _sdk_dump_log() _sdk_dump_log_inner() +#endif + /* Public API */ #ifdef __cplusplus extern "C" { #endif +void _sdk_log_inner(const char *fmt, ...); +void _sdk_dump_log_inner(void); + void *InterruptCallback(int irq, void (*func)(void)); void *GetInterruptCallback(int irq); void *DMACallback(int dma, void (*func)(void)); diff --git a/libpsn00b/libc/abort.c b/libpsn00b/libc/abort.c index 1108160..2db5016 100644 --- a/libpsn00b/libc/abort.c +++ b/libpsn00b/libc/abort.c @@ -1,16 +1,10 @@ -#include - -#ifdef NDEBUG -#define _LOG(...) -#else -#define _LOG(...) printf(__VA_ARGS__) -#endif +#include /* Standard abort */ -void abort() { - _LOG("abort()\n"); +void abort(void) { + _sdk_log("abort()\n"); for (;;) __asm__ volatile(""); @@ -19,7 +13,7 @@ void abort() { /* Internal function used by assert() macro */ void _assert_abort(const char *file, int line, const char *expr) { - _LOG("%s:%d: assert(%s)\n", file, line, expr); + _sdk_log("%s:%d: assert(%s)\n", file, line, expr); for (;;) __asm__ volatile(""); @@ -28,7 +22,7 @@ void _assert_abort(const char *file, int line, const char *expr) { /* Pure virtual function call (C++) */ void __cxa_pure_virtual(void) { - _LOG("__cxa_pure_virtual()\n"); + _sdk_log("__cxa_pure_virtual()\n"); for (;;) __asm__ volatile(""); diff --git a/libpsn00b/libc/malloc.c b/libpsn00b/libc/malloc.c index acac753..e9fd6f4 100644 --- a/libpsn00b/libc/malloc.c +++ b/libpsn00b/libc/malloc.c @@ -120,7 +120,7 @@ __attribute__((weak)) void *malloc(size_t size) { _alloc_head = new; _alloc_tail = new; - TrackHeapUsage(_size); + TrackHeapUsage(size); return ptr; } @@ -139,7 +139,7 @@ __attribute__((weak)) void *malloc(size_t size) { _alloc_head->prev = new; _alloc_head = new; - TrackHeapUsage(_size); + TrackHeapUsage(size); return ptr; } @@ -157,7 +157,7 @@ __attribute__((weak)) void *malloc(size_t size) { (new->next)->prev = new; prev->next = new; - TrackHeapUsage(_size); + TrackHeapUsage(size); return ptr; } @@ -175,7 +175,7 @@ __attribute__((weak)) void *malloc(size_t size) { _alloc_tail->next = new; _alloc_tail = new; - TrackHeapUsage(_size); + TrackHeapUsage(size); return ptr; } @@ -196,7 +196,7 @@ __attribute__((weak)) void *realloc(void *ptr, size_t size) { // New memory block shorter? if (prev->size >= _size) { - TrackHeapUsage(_size - prev->size); + TrackHeapUsage(size - prev->size); prev->size = _size; if (!prev->next) @@ -211,14 +211,14 @@ __attribute__((weak)) void *realloc(void *ptr, size_t size) { if (!new) return 0; - TrackHeapUsage(_size - prev->size); + TrackHeapUsage(size - prev->size); prev->size = _size; return ptr; } // Do we have free memory after it? if (((prev->next)->ptr - ptr) > _size) { - TrackHeapUsage(_size - prev->size); + TrackHeapUsage(size - prev->size); prev->size = _size; return ptr; } @@ -250,7 +250,7 @@ __attribute__((weak)) void free(void *ptr) { sbrk(-size); } - TrackHeapUsage(-size); + TrackHeapUsage(-(_alloc_head->size)); return; } @@ -265,17 +265,15 @@ __attribute__((weak)) void free(void *ptr) { if (cur->next) { // In the middle, just unlink it (cur->next)->prev = cur->prev; - TrackHeapUsage(-(cur->size + sizeof(BlockHeader))); } else { // At the end, shrink heap - _alloc_tail = cur->prev; - void *top = sbrk(0); size_t size = (top - (cur->prev)->ptr) - (cur->prev)->size; + _alloc_tail = cur->prev; sbrk(-size); - TrackHeapUsage(-size); } + TrackHeapUsage(-(cur->size)); (cur->prev)->next = cur->next; } diff --git a/libpsn00b/psxcd/getsector.c b/libpsn00b/psxcd/getsector.c index ee5315a..31d0ac7 100644 --- a/libpsn00b/psxcd/getsector.c +++ b/libpsn00b/psxcd/getsector.c @@ -4,19 +4,12 @@ */ #include +#include #include #include #define DATA_SYNC_TIMEOUT 0x100000 -/* Private utilities */ - -#ifdef NDEBUG -#define _LOG(...) -#else -#define _LOG(...) printf(__VA_ARGS__) -#endif - /* DMA transfer functions */ int CdGetSector(void *madr, int size) { @@ -53,6 +46,6 @@ int CdDataSync(int mode) { return 0; } - _LOG("psxcd: CdDataSync() timeout\n"); + _sdk_log("psxcd: CdDataSync() timeout\n"); return -1; } diff --git a/libpsn00b/psxcd/isofs.c b/libpsn00b/psxcd/isofs.c index 4ec701c..0425c0d 100644 --- a/libpsn00b/psxcd/isofs.c +++ b/libpsn00b/psxcd/isofs.c @@ -1,18 +1,12 @@ #include -#include #include #include #include #include +#include #include "psxcd.h" #include "isofs.h" -#ifdef NDEBUG -#define _LOG(...) -#else -#define _LOG(...) printf(__VA_ARGS__) -#endif - #define DEFAULT_PATH_SEP '\\' #define IS_PATH_SEP(ch) (((ch) == '/') || ((ch) == '\\')) @@ -49,7 +43,7 @@ static int _CdReadIsoDescriptor(int session_offs) CdControl(CdlNop, 0, 0); if( (CdStatus()&0x10) ) { - _LOG("psxcd: Lid is still open.\n"); + _sdk_log("psxcd: Lid is still open.\n"); _cd_iso_error = CdlIsoLidOpen; return -1; @@ -64,45 +58,45 @@ static int _CdReadIsoDescriptor(int session_offs) return 0; } - _LOG("psxcd: Parsing ISO file system.\n"); + _sdk_log("psxcd: Parsing ISO file system.\n"); // Seek to volume descriptor CdIntToPos(16+session_offs, &loc); if( !CdControl(CdlSetloc, (uint8_t*)&loc, 0) ) { - _LOG("psxcd: Could not set seek destination.\n"); + _sdk_log("psxcd: Could not set seek destination.\n"); _cd_iso_error = CdlIsoSeekError; return -1; } - _LOG("psxcd: Read sectors.\n"); + _sdk_log("psxcd: Read sectors.\n"); // Read volume descriptor CdRead(1, (uint32_t*)_cd_iso_descriptor_buff, CdlModeSpeed); if( CdReadSync(0, 0) ) { - _LOG("psxcd: Error reading ISO volume descriptor.\n"); + _sdk_log("psxcd: Error reading ISO volume descriptor.\n"); _cd_iso_error = CdlIsoReadError; return -1; } - _LOG("psxcd: Read complete.\n"); + _sdk_log("psxcd: Read complete.\n"); // Verify if volume descriptor is present descriptor = (ISO_DESCRIPTOR*)_cd_iso_descriptor_buff; if( strncmp("CD001", descriptor->header.id, 5) ) { - _LOG("psxcd: Disc does not contain a ISO9660 file system.\n"); + _sdk_log("psxcd: Disc does not contain a ISO9660 file system.\n"); _cd_iso_error = CdlIsoInvalidFs; return -1; } - _LOG("psxcd: Path table LBA = %d\n", descriptor->pathTable1Offs); - _LOG("psxcd: Path table len = %d\n", descriptor->pathTableSize.lsb); + _sdk_log("psxcd: Path table LBA = %d\n", descriptor->pathTable1Offs); + _sdk_log("psxcd: Path table len = %d\n", descriptor->pathTableSize.lsb); // Allocate path table buffer i = ((2047+descriptor->pathTableSize.lsb)>>11)<<11; @@ -112,7 +106,7 @@ static int _CdReadIsoDescriptor(int session_offs) } _cd_iso_pathtable_buff = (uint8_t*)malloc(i); - _LOG("psxcd: Allocated %d bytes for path table.\n", i); + _sdk_log("psxcd: Allocated %d bytes for path table.\n", i); // Read path table CdIntToPos(descriptor->pathTable1Offs, &loc); @@ -120,7 +114,7 @@ static int _CdReadIsoDescriptor(int session_offs) CdRead(i>>11, (uint32_t*)_cd_iso_pathtable_buff, CdlModeSpeed); if( CdReadSync(0, 0) ) { - _LOG("psxcd: Error reading ISO path table.\n"); + _sdk_log("psxcd: Error reading ISO path table.\n"); _cd_iso_error = CdlIsoReadError; return -1; @@ -148,11 +142,11 @@ static int _CdReadIsoDirectory(int lba) CdIntToPos(lba, &loc); i = CdPosToInt(&loc); - _LOG("psxcd: Seek to sector %d\n", i); + _sdk_log("psxcd: Seek to sector %d\n", i); if( !CdControl(CdlSetloc, (uint8_t*)&loc, 0) ) { - _LOG("psxcd: Could not set seek destination.\n"); + _sdk_log("psxcd: Could not set seek destination.\n"); _cd_iso_error = CdlIsoSeekError; return -1; @@ -168,7 +162,7 @@ static int _CdReadIsoDirectory(int lba) CdRead(1, (uint32_t*)_cd_iso_directory_buff, CdlModeSpeed); if( CdReadSync(0, 0) ) { - _LOG("psxcd: Error reading initial directory record.\n"); + _sdk_log("psxcd: Error reading initial directory record.\n"); _cd_iso_error = CdlIsoReadError; return -1; @@ -177,14 +171,14 @@ static int _CdReadIsoDirectory(int lba) direntry = (ISO_DIR_ENTRY*)_cd_iso_directory_buff; _cd_iso_directory_len = direntry->entrySize.lsb; - _LOG("psxcd: Location of directory record = %d\n", direntry->entryOffs.lsb); - _LOG("psxcd: Size of directory record = %d\n", _cd_iso_directory_len); + _sdk_log("psxcd: Location of directory record = %d\n", direntry->entryOffs.lsb); + _sdk_log("psxcd: Size of directory record = %d\n", _cd_iso_directory_len); if( _cd_iso_directory_len > 2048 ) { if( !CdControl(CdlSetloc, (uint8_t*)&loc, 0) ) { - _LOG("psxcd: Could not set seek destination.\n"); + _sdk_log("psxcd: Could not set seek destination.\n"); _cd_iso_error = CdlIsoSeekError; return -1; @@ -194,12 +188,12 @@ static int _CdReadIsoDirectory(int lba) i = ((2047+_cd_iso_directory_len)>>11)<<11; _cd_iso_directory_buff = (uint8_t*)malloc(i); - _LOG("psxcd: Allocated %d bytes for directory record.\n", i); + _sdk_log("psxcd: Allocated %d bytes for directory record.\n", i); CdRead(i>>11, (uint32_t*)_cd_iso_directory_buff, CdlModeSpeed); if( CdReadSync(0, 0) ) { - _LOG("psxcd: Error reading remaining directory record.\n"); + _sdk_log("psxcd: Error reading remaining directory record.\n"); _cd_iso_error = CdlIsoReadError; return -1; @@ -221,7 +215,7 @@ static void dump_directory(void) ISO_DIR_ENTRY *dir_entry; char namebuff[16]; - _LOG("psxcd: Cached directory record contents:\n"); + _sdk_log("psxcd: Cached directory record contents:\n"); i = 0; dir_pos = 0; @@ -232,7 +226,7 @@ static void dump_directory(void) strncpy(namebuff, _cd_iso_directory_buff+dir_pos+sizeof(ISO_DIR_ENTRY), dir_entry->identifierLen); - _LOG("psxcd: P:%d L:%d %s\n", dir_pos, dir_entry->identifierLen, namebuff); + _sdk_log("psxcd: P:%d L:%d %s\n", dir_pos, dir_entry->identifierLen, namebuff); dir_pos += dir_entry->entryLength; i++; @@ -251,7 +245,7 @@ static void dump_directory(void) } } - _LOG("psxcd: --\n"); + _sdk_log("psxcd: --\n"); } @@ -262,7 +256,7 @@ static void dump_pathtable(void) ISO_DESCRIPTOR *descriptor; char namebuff[16]; - _LOG("psxcd: Path table entries:\n"); + _sdk_log("psxcd: Path table entries:\n"); descriptor = (ISO_DESCRIPTOR*)_cd_iso_descriptor_buff; @@ -276,7 +270,7 @@ static void dump_pathtable(void) tbl_pos+sizeof(ISO_PATHTABLE_ENTRY), tbl_entry->nameLength); - _LOG("psxcd: %s\n", namebuff); + _sdk_log("psxcd: %s\n", namebuff); // Advance to next entry tbl_pos += sizeof(ISO_PATHTABLE_ENTRY) @@ -372,7 +366,7 @@ static int find_dir_entry(const char *name, ISO_DIR_ENTRY *dirent) ISO_DIR_ENTRY *dir_entry; char namebuff[16]; - _LOG("psxcd: Locating file %s.\n", name); + _sdk_log("psxcd: Locating file %s.\n", name); i = 0; dir_pos = 0; @@ -465,11 +459,11 @@ CdlFILE *CdSearchFile(CdlFILE *fp, const char *filename) // Read ISO descriptor and path table if( _CdReadIsoDescriptor(0) ) { - _LOG("psxcd: Could not read ISO file system.\n"); + _sdk_log("psxcd: Could not read ISO file system.\n"); return NULL; } - // _LOG("psxcd: ISO file system cache updated.\n"); + // _sdk_log("psxcd: ISO file system cache updated.\n"); // _cd_media_changed = 0; //} @@ -477,23 +471,23 @@ CdlFILE *CdSearchFile(CdlFILE *fp, const char *filename) num_dirs = get_pathtable_entry(0, NULL, NULL); #ifndef NDEBUG - _LOG("psxcd: Directories in path table: %d\n", num_dirs); + _sdk_log("psxcd: Directories in path table: %d\n", num_dirs); rbuff = resolve_pathtable_path(num_dirs-1, tpath_rbuff+127); if( !rbuff ) { - _LOG("psxcd: Could not resolve path.\n"); + _sdk_log("psxcd: Could not resolve path.\n"); } else { - _LOG("psxcd: Longest path: %s|\n", rbuff); + _sdk_log("psxcd: Longest path: %s|\n", rbuff); } #endif if( get_pathname(search_path, filename) ) { - _LOG("psxcd: Search path = %s|\n", search_path); + _sdk_log("psxcd: Search path = %s|\n", search_path); } // Search the pathtable for a matching path @@ -501,7 +495,7 @@ CdlFILE *CdSearchFile(CdlFILE *fp, const char *filename) for(i=1; iname, filename); @@ -539,12 +533,12 @@ CdlFILE *CdSearchFile(CdlFILE *fp, const char *filename) if( find_dir_entry(fp->name, &dir_entry) ) { - _LOG("psxcd: Could not find file.\n"); + _sdk_log("psxcd: Could not find file.\n"); return NULL; } - _LOG("psxcd: Located file at LBA %d.\n", dir_entry.entryOffs.lsb); + _sdk_log("psxcd: Located file at LBA %d.\n", dir_entry.entryOffs.lsb); CdIntToPos(dir_entry.entryOffs.lsb, &fp->pos); fp->size = dir_entry.entrySize.lsb; @@ -568,11 +562,11 @@ CdlDIR *CdOpenDir(const char* path) // Read ISO descriptor and path table if( _CdReadIsoDescriptor( 0 ) ) { - _LOG( "psxcd: Could not read ISO file system.\n" ); + _sdk_log( "psxcd: Could not read ISO file system.\n" ); return NULL; } -// _LOG( "psxcd: ISO file system cache updated.\n" ); +// _sdk_log( "psxcd: ISO file system cache updated.\n" ); // _cd_media_changed = 0; // } @@ -582,7 +576,7 @@ CdlDIR *CdOpenDir(const char* path) for( i=1; isize = dir_entry->entrySize.lsb; - _LOG("psxcd: dir_entry->entryLength = %d, ", dir_entry->entryLength); + _sdk_log("psxcd: dir_entry->entryLength = %d, ", dir_entry->entryLength); d_dir->_pos += dir_entry->entryLength; - _LOG("psxcd: d_dir->_pos = %d\n", d_dir->_pos); + _sdk_log("psxcd: d_dir->_pos = %d\n", d_dir->_pos); // Check if padding is reached (end of record sector) if( d_dir->_dir[d_dir->_pos] == 0 ) @@ -776,15 +770,13 @@ int CdLoadSession(int session) int i; // Seek to specified session - _LOG("psxcd: CdLoadSession(): Seeking to session %d...\n", session); + _sdk_log("psxcd: CdLoadSession(): Seeking to session %d...\n", session); CdControl(CdlSetsession, (unsigned char*)&session, (unsigned char*)&resultbuff); if( CdSync(0, 0) == CdlDiskError ) { - _LOG("psxcd: CdLoadSession(): Session seek failed, " - "session does not exist.\n"); - _LOG("psxcd: CdLoadSession(): Restarting CD-ROM...\n"); + _sdk_log("psxcd: CdLoadSession(): Session seek failed, session does not exist. Restarting CD-ROM...\n"); // Restart CD-ROM on session seek failure CdControl(CdlNop, 0, 0); @@ -805,7 +797,7 @@ int CdLoadSession(int session) _ses_scanbuff = scanbuff; // Begin scan for an ISO volume descriptor - _LOG("psxcd: CdLoadSession(): Scanning for ISO9660 volume descriptor.\n"); + _sdk_log("psxcd: CdLoadSession(): Scanning for ISO9660 volume descriptor.\n"); i = CdlModeSpeed; CdControl(CdlSetmode, (unsigned char*)&i, 0); @@ -820,7 +812,7 @@ int CdLoadSession(int session) if( !_ses_scanfound ) { - _LOG("psxcd: CdLoadSession(): Did not find volume descriptor.\n"); + _sdk_log("psxcd: CdLoadSession(): Did not find volume descriptor.\n"); _cd_iso_error = CdlIsoInvalidFs; EnterCriticalSection(); @@ -849,11 +841,11 @@ int CdLoadSession(int session) loc = (CdlLOC*)resultbuff; - _LOG("psxcd: CdLoadSession(): Session found in %02d:%02d:%02d (LBA=%d)\n", + _sdk_log("psxcd: CdLoadSession(): Session found in %02d:%02d:%02d (LBA=%d)\n", btoi(loc->minute), btoi(loc->second), btoi(loc->sector), CdPosToInt(loc)); i = CdPosToInt(loc)-17; - _LOG("psxcd: CdLoadSession(): Session starting at LBA=%d\n", i); + _sdk_log("psxcd: CdLoadSession(): Session starting at LBA=%d\n", i); _cd_media_changed = 1; diff --git a/libpsn00b/psxcd/psxcd.c b/libpsn00b/psxcd/psxcd.c index 6730531..b914b5e 100644 --- a/libpsn00b/psxcd/psxcd.c +++ b/libpsn00b/psxcd/psxcd.c @@ -1,6 +1,6 @@ #include -#include #include +#include #include #include "psxcd.h" @@ -21,12 +21,6 @@ volatile int _cd_last_sector_count; int _cd_media_changed; -#ifdef NDEBUG -#define _LOG(...) -#else -#define _LOG(...) printf(__VA_ARGS__) -#endif - void _cd_init(void); void _cd_control(unsigned char com, const void *param, int plen); void _cd_wait_ack(void); @@ -45,9 +39,9 @@ int CdInit(void) { if(CdSync(0, 0) != CdlDiskError) { CdControl(CdlDemute, 0, 0); - _LOG("psxcd: setup done\n"); + _sdk_log("psxcd: setup done\n"); } else { - _LOG("psxcd: setup error, bad disc/drive or no disc inserted\n"); + _sdk_log("psxcd: setup error, bad disc/drive or no disc inserted\n"); } return 1; @@ -311,7 +305,7 @@ static void CdDoRetry() { int cb; - _LOG("psxcd: retrying read...\n"); + _sdk_log("psxcd: retrying read...\n"); // Stop reading CdControl(CdlPause, 0, 0); diff --git a/libpsn00b/psxetc/dl.c b/libpsn00b/psxetc/dl.c index cf4e466..b85a7df 100644 --- a/libpsn00b/psxetc/dl.c +++ b/libpsn00b/psxetc/dl.c @@ -30,6 +30,7 @@ #include #include #include +#include #include /* Compile options */ @@ -66,12 +67,6 @@ void *(*_dl_resolve_callback)(DLL *, const char *) = 0; /* Private utilities */ -#ifdef NDEBUG -#define _LOG(...) -#else -#define _LOG(...) printf(__VA_ARGS__) -#endif - #define _ERROR(code, ret) { \ _error_code = code; \ return ret; \ @@ -92,7 +87,7 @@ void *_dl_resolve_helper(DLL *dll, uint32_t index) { address = DL_GetSymbolByName(_name); if (!address) { - _LOG("psxetc: FATAL! can't resolve %s, locking up\n", _name); + _sdk_log("psxetc: FATAL! can't resolve %s, locking up\n", _name); while (1) __asm__ volatile("nop"); } @@ -133,7 +128,7 @@ static uint32_t _elf_hash(const char *str) { static uint8_t *_dl_load_file(const char *filename, size_t *size_output) { int32_t fd = open(filename, 1); if (fd < 0) { - _LOG("psxetc: can't open %s, error = %d\n", filename, fd); + _sdk_log("psxetc: can't open %s, error = %d\n", filename, fd); _ERROR(RTLD_E_FILE_OPEN, 0); } @@ -144,11 +139,11 @@ static uint8_t *_dl_load_file(const char *filename, size_t *size_output) { uint8_t *buffer = malloc(size); if (!buffer) { - _LOG("psxetc: unable to allocate %d bytes for %s\n", size, filename); + _sdk_log("psxetc: unable to allocate %d bytes for %s\n", size, filename); _ERROR(RTLD_E_FILE_ALLOC, 0); } - //_LOG("psxetc: loading %s (%d bytes)..", filename, size); + //_sdk_log("psxetc: loading %s (%d bytes)..", filename, size); for (uint32_t offset = 0; offset < size; ) { int32_t length = read(fd, &(buffer[offset]), 0x800); @@ -157,16 +152,16 @@ static uint8_t *_dl_load_file(const char *filename, size_t *size_output) { close(fd); free(buffer); - _LOG("failed, error = %d\n", length); + _sdk_log("failed, error = %d\n", length); _ERROR(RTLD_E_FILE_READ, 0); } - //_LOG("."); + //_sdk_log("."); offset += length; } close(fd); - _LOG(" done\n"); + _sdk_log(" done\n"); if (size_output) *size_output = size; @@ -192,7 +187,7 @@ int32_t DL_ParseSymbolMap(const char *ptr, size_t size) { // in order to minimize hash table size _symbol_map.nbucket = entries; _symbol_map.nchain = entries; - _LOG( + _sdk_log( "psxetc: allocating nbucket = %d, nchain = %d\n", _symbol_map.nbucket, entries @@ -205,7 +200,7 @@ int32_t DL_ParseSymbolMap(const char *ptr, size_t size) { _symbol_map.chain = malloc(sizeof(uint32_t) * entries); if (!_symbol_map.entries || !_symbol_map.bucket || !_symbol_map.chain) { - _LOG("psxetc: unable to allocate symbol map table\n"); + _sdk_log("psxetc: unable to allocate symbol map table\n"); _ERROR(RTLD_E_MAP_ALLOC, -1); } @@ -248,7 +243,7 @@ int32_t DL_ParseSymbolMap(const char *ptr, size_t size) { (_type == 'D') || // .data (_type == 'B') // .bss )) { - //_LOG( + //_sdk_log( //"psxetc: map sym: %08x,%08x [%c %s]\n", //address, _size, _type, name //); @@ -274,7 +269,7 @@ int32_t DL_ParseSymbolMap(const char *ptr, size_t size) { pos++; } - _LOG("psxetc: parsed %d symbols\n", entries); + _sdk_log("psxetc: parsed %d symbols\n", entries); if (!entries) _ERROR(RTLD_E_NO_SYMBOLS, -1); @@ -307,7 +302,7 @@ void DL_UnloadSymbolMap(void) { void *DL_GetSymbolByName(const char *name) { if (!_symbol_map.entries) { - _LOG("psxetc: attempted lookup with no map loaded\n"); + _sdk_log("psxetc: attempted lookup with no map loaded\n"); _ERROR(RTLD_E_NO_MAP, 0); } @@ -319,7 +314,7 @@ void *DL_GetSymbolByName(const char *name) { // calculated. for (uint32_t i = _symbol_map.bucket[hash_mod]; i != 0xffffffff;) { if (i >= _symbol_map.nchain) { - _LOG( + _sdk_log( "psxetc: GetSymbolByName() index out of bounds (%d >= %d)\n", i, _symbol_map.nchain ); @@ -329,14 +324,14 @@ void *DL_GetSymbolByName(const char *name) { MapEntry *entry = &(_symbol_map.entries[i]); if (hash == entry->hash) { - //_LOG("psxetc: map lookup [%s = %08x]\n", name, entry->ptr); + //_sdk_log("psxetc: map lookup [%s = %08x]\n", name, entry->ptr); return entry->ptr; } i = _symbol_map.chain[i]; } - _LOG("psxetc: map lookup [%s not found]\n", name); + _sdk_log("psxetc: map lookup [%s not found]\n", name); _ERROR(RTLD_E_MAP_SYMBOL, 0); } @@ -352,14 +347,14 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) { DLL *dll = malloc(sizeof(DLL)); if (!dll) { - _LOG("psxetc: unable to allocate DLL struct\n"); + _sdk_log("psxetc: unable to allocate DLL struct\n"); _ERROR(RTLD_E_DLL_ALLOC, 0); } dll->ptr = ptr; dll->malloc_ptr = (mode & RTLD_FREE_ON_DESTROY) ? ptr : 0; dll->size = size; - _LOG("psxetc: initializing DLL at %08x\n", ptr); + _sdk_log("psxetc: initializing DLL at %08x\n", ptr); // Interpret the key-value pairs in the .dynamic section to obtain info // about all the other sections. The pairs are null-terminated, which makes @@ -368,128 +363,128 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) { uint32_t first_got_sym = 0; for (Elf32_Dyn *dyn = (Elf32_Dyn *) ptr; dyn->d_tag; dyn++) { - //_LOG("psxetc: .dynamic %08x=%08x ", dyn->d_tag, dyn->d_un.d_val); + //_sdk_log("psxetc: .dynamic %08x=%08x ", dyn->d_tag, dyn->d_un.d_val); switch (dyn->d_tag) { // Offset of .got section case DT_PLTGOT: - //_LOG("[PLTGOT]\n"); + //_sdk_log("[PLTGOT]\n"); dll->got = (void *) (ptr + dyn->d_un.d_val); break; // Offset of .hash section case DT_HASH: - //_LOG("[HASH]\n"); + //_sdk_log("[HASH]\n"); dll->hash = (void *) (ptr + dyn->d_un.d_val); break; // Offset of .dynstr (NOT .strtab) section case DT_STRTAB: - //_LOG("[STRTAB]\n"); + //_sdk_log("[STRTAB]\n"); dll->strtab = (void *) (ptr + dyn->d_un.d_val); break; // Offset of .dynsym (NOT .symtab) section case DT_SYMTAB: - //_LOG("[SYMTAB]\n"); + //_sdk_log("[SYMTAB]\n"); dll->symtab = (void *) (ptr + dyn->d_un.d_val); break; // Length of .dynstr section //case DT_STRSZ: - //_LOG("[STRSZ]\n"); + //_sdk_log("[STRSZ]\n"); //break; // Length of each .dynsym entry case DT_SYMENT: - //_LOG("[SYMENT]\n"); + //_sdk_log("[SYMENT]\n"); // Only 16-byte symbol table entries are supported. if (dyn->d_un.d_val != sizeof(Elf32_Sym)) { free(dll); - _LOG("psxetc: invalid DLL symtab entry size %d\n", dyn->d_un.d_val); + _sdk_log("psxetc: invalid DLL symtab entry size %d\n", dyn->d_un.d_val); _ERROR(RTLD_E_DLL_FORMAT, 0); } break; // MIPS ABI (?) version case DT_MIPS_RLD_VERSION: - //_LOG("[MIPS_RLD_VERSION]\n"); + //_sdk_log("[MIPS_RLD_VERSION]\n"); // Versions other than 1 are unsupported (do they even exist?). if (dyn->d_un.d_val != 1) { free(dll); - _LOG("psxetc: invalid DLL version %d\n", dyn->d_un.d_val); + _sdk_log("psxetc: invalid DLL version %d\n", dyn->d_un.d_val); _ERROR(RTLD_E_DLL_FORMAT, 0); } break; // DLL/ABI flags case DT_MIPS_FLAGS: - //_LOG("[MIPS_FLAGS]\n"); + //_sdk_log("[MIPS_FLAGS]\n"); // Shortcut pointers (whatever they are) are not supported. if (dyn->d_un.d_val & RHF_QUICKSTART) { free(dll); - _LOG("psxetc: invalid DLL flags\n"); + _sdk_log("psxetc: invalid DLL flags\n"); _ERROR(RTLD_E_DLL_FORMAT, 0); } break; // Number of local (not to resolve) GOT entries case DT_MIPS_LOCAL_GOTNO: - //_LOG("[MIPS_LOCAL_GOTNO]\n"); + //_sdk_log("[MIPS_LOCAL_GOTNO]\n"); local_got_len = dyn->d_un.d_val; break; // Base address DLL was compiled for case DT_MIPS_BASE_ADDRESS: - //_LOG("[MIPS_BASE_ADDRESS]\n"); + //_sdk_log("[MIPS_BASE_ADDRESS]\n"); // Base addresses other than zero are not supported. It would // be easy enough to support them, but why? if (dyn->d_un.d_val) { free(dll); - _LOG("psxetc: invalid DLL base address %08x\n", dyn->d_un.d_val); + _sdk_log("psxetc: invalid DLL base address %08x\n", dyn->d_un.d_val); _ERROR(RTLD_E_DLL_FORMAT, 0); } break; // Number of symbol table entries case DT_MIPS_SYMTABNO: - //_LOG("[MIPS_SYMTABNO]\n"); + //_sdk_log("[MIPS_SYMTABNO]\n"); dll->symbol_count = dyn->d_un.d_val; break; // Index of first unresolved symbol table entry //case DT_MIPS_UNREFEXTNO: - //_LOG("[MIPS_UNREFEXTNO]\n"); + //_sdk_log("[MIPS_UNREFEXTNO]\n"); //break; // Index of first symbol table entry which has a matching GOT entry case DT_MIPS_GOTSYM: - //_LOG("[MIPS_GOTSYM]\n"); + //_sdk_log("[MIPS_GOTSYM]\n"); first_got_sym = dyn->d_un.d_val; break; // Number of pages the GOT is split into (does not apply to PS1) //case DT_MIPS_HIPAGENO: - //_LOG("[MIPS_HIPAGENO]\n"); + //_sdk_log("[MIPS_HIPAGENO]\n"); //break; //default: - //_LOG("[ignored]\n"); + //_sdk_log("[ignored]\n"); } } @@ -501,7 +496,7 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) { ((uint32_t) ptr + size - (uint32_t) dll->got) / sizeof(uint32_t) - 2; dll->got_length = local_got_len + (dll->symbol_count - first_got_sym) - 2; - _LOG( + _sdk_log( "psxetc: %d symbols, %d GOT entries\n", dll->symbol_count, dll->got_length ); @@ -530,7 +525,7 @@ DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) { continue; sym->st_value += (uint32_t) ptr; - //_LOG( + //_sdk_log( //"psxetc: DLL sym: %08x,%08x [%s]\n", //sym->st_value, sym->st_size, _name //); @@ -641,7 +636,7 @@ void *DL_GetDLLSymbol(const DLL *dll, const char *name) { // provided. for (uint32_t i = bucket[hash_mod]; i != 0xffffffff;) { if (i >= nchain) { - _LOG("psxetc: DL_GetDLLSymbol() index out of bounds (%d >= %d)\n", i, nchain); + _sdk_log("psxetc: DL_GetDLLSymbol() index out of bounds (%d >= %d)\n", i, nchain); _ERROR(RTLD_E_HASH_LOOKUP, 0); } @@ -649,14 +644,14 @@ void *DL_GetDLLSymbol(const DLL *dll, const char *name) { const char *_name = &(dll->strtab[sym->st_name]); if (!strcmp(name, _name)) { - //_LOG("psxetc: DLL lookup [%s = %08x]\n", name, sym->st_value); + //_sdk_log("psxetc: DLL lookup [%s = %08x]\n", name, sym->st_value); return sym->st_value; } i = chain[i]; } - _LOG("psxetc: DLL lookup [%s not found]\n", name); + _sdk_log("psxetc: DLL lookup [%s not found]\n", name); _ERROR(RTLD_E_DLL_SYMBOL, 0); } diff --git a/libpsn00b/psxetc/logging.c b/libpsn00b/psxetc/logging.c new file mode 100644 index 0000000..5199190 --- /dev/null +++ b/libpsn00b/psxetc/logging.c @@ -0,0 +1,50 @@ +/* + * PSn00bSDK internal debug logger + * (C) 2022 spicyjpeg - MPL licensed + * + * This file provides the (admittedly minimal) logging system used by all + * PSn00bSDK libraries. Log messages and warnings are issued using the + * _sdk_log() macro and collected into a buffer, whose contents can be flushed + * by calling _sdk_dump_log() (by default this is done by VSync()). Logging is + * only enabled in debug builds of libpsn00b. + */ + +#include +#include +#include +#include +#include + +#define LOG_BUFFER_SIZE 256 + +#ifndef NDEBUG + +/* Internal globals */ + +static char _log_buffer[LOG_BUFFER_SIZE]; +static size_t _log_buffer_length = 0; + +/* Internal logging API */ + +void _sdk_log_inner(const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + _log_buffer_length += vsnprintf( + &_log_buffer[_log_buffer_length], + LOG_BUFFER_SIZE - _log_buffer_length, + fmt, + ap + ); + va_end(ap); +} + +void _sdk_dump_log_inner(void) { + if (!_log_buffer_length) + return; + + write(1, _log_buffer, _log_buffer_length); + _log_buffer_length = 0; +} + +#endif diff --git a/libpsn00b/psxgpu/common.c b/libpsn00b/psxgpu/common.c index bf70b72..a262472 100644 --- a/libpsn00b/psxgpu/common.c +++ b/libpsn00b/psxgpu/common.c @@ -4,7 +4,6 @@ */ #include -#include #include #include #include @@ -36,13 +35,7 @@ static volatile uint8_t _queue_head, _queue_tail, _queue_length; static volatile uint32_t _vblank_counter; static volatile uint16_t _last_hblank; -/* Private utilities and interrupt handlers */ - -#ifdef NDEBUG -#define _LOG(...) -#else -#define _LOG(...) printf(__VA_ARGS__) -#endif +/* Private interrupt handlers */ static void _vblank_handler(void) { _vblank_counter++; @@ -57,8 +50,8 @@ static void _gpu_dma_handler(void) { __asm__ volatile(""); if (--_queue_length) { - QueueEntry *entry = &_draw_queue[_queue_head++]; - _queue_head %= QUEUE_LENGTH; + volatile QueueEntry *entry = &_draw_queue[_queue_head++]; + _queue_head %= QUEUE_LENGTH; entry->func(entry->arg1, entry->arg2, entry->arg3); } else { @@ -82,7 +75,7 @@ void ResetGraph(int mode) { _gpu_video_mode = (GPU_GP1 >> 20) & 1; ExitCriticalSection(); - _LOG("psxgpu: setup done, default mode is %s\n", _gpu_video_mode ? "PAL" : "NTSC"); + _sdk_log("psxgpu: setup done, default mode is %s\n", _gpu_video_mode ? "PAL" : "NTSC"); } if (mode == 3) { @@ -115,13 +108,13 @@ void ResetGraph(int mode) { // TODO: add support for no$psx's "halt" register static void _default_vsync_halt(void) { int counter = _vblank_counter; - for (int i = VSYNC_TIMEOUT; i; i--) { if (counter != _vblank_counter) return; } - _LOG("psxgpu: VSync() timeout\n"); + _sdk_log("psxgpu: VSync() timeout\n"); + _sdk_dump_log(); ChangeClearPAD(0); ChangeClearRCnt(3, 0); } @@ -137,6 +130,7 @@ int VSync(int mode) { // Wait for at least one vertical blank event to occur. do { + _sdk_dump_log(); _vsync_halt_func(); // If interlaced mode is enabled, wait until the GPU starts displaying @@ -190,15 +184,15 @@ int EnqueueDrawOp( if (_queue_length) { if (_queue_length >= QUEUE_LENGTH) { IRQ_MASK = mask; - _LOG("psxgpu: draw queue overflow, dropping commands\n"); + _sdk_log("psxgpu: draw queue overflow, dropping commands\n"); return -1; } int length = _queue_length; _queue_length = length + 1; - QueueEntry *entry = &_draw_queue[_queue_tail++]; - _queue_tail %= QUEUE_LENGTH; + volatile QueueEntry *entry = &_draw_queue[_queue_tail++]; + _queue_tail %= QUEUE_LENGTH; entry->func = func; entry->arg1 = arg1; @@ -236,7 +230,8 @@ int DrawSync(int mode) { while (!(GPU_GP1 & (1 << 26))) __asm__ volatile(""); } else { - printf("psxgpu: DrawSync() timeout\n"); + _sdk_log("psxgpu: DrawSync() timeout\n"); + _sdk_dump_log(); } return _queue_length; @@ -297,7 +292,7 @@ void DrawPrim(const uint32_t *pri) { } int DrawOTag(const uint32_t *ot) { - return EnqueueDrawOp(&DrawOTag2, (uint32_t) ot, 0, 0); + return EnqueueDrawOp((void *) &DrawOTag2, (uint32_t) ot, 0, 0); } void DrawOTag2(const uint32_t *ot) { diff --git a/libpsn00b/psxgpu/env.c b/libpsn00b/psxgpu/env.c index 1b97026..f513727 100644 --- a/libpsn00b/psxgpu/env.c +++ b/libpsn00b/psxgpu/env.c @@ -85,7 +85,7 @@ int DrawOTagEnv(const uint32_t *ot, DRAWENV *env) { //while (!(GPU_GP1 & (1 << 26))) //__asm__ volatile(""); - return EnqueueDrawOp(&DrawOTag2, (uint32_t) prim, 0, 0); + return EnqueueDrawOp((void *) &DrawOTag2, (uint32_t) prim, 0, 0); } void PutDrawEnv(DRAWENV *env) { diff --git a/libpsn00b/psxgpu/image.c b/libpsn00b/psxgpu/image.c index c09a59d..968dde5 100644 --- a/libpsn00b/psxgpu/image.c +++ b/libpsn00b/psxgpu/image.c @@ -4,7 +4,7 @@ */ #include -#include +#include #include #include @@ -12,20 +12,14 @@ /* Private utilities */ -#ifdef NDEBUG -#define _LOG(...) -#else -#define _LOG(...) printf(__VA_ARGS__) -#endif - static void _dma_transfer(const RECT *rect, uint32_t *data, int write) { size_t length = rect->w * rect->h; if (length % 2) - _LOG("psxgpu: can't transfer an odd number of pixels\n"); + _sdk_log("psxgpu: can't transfer an odd number of pixels\n"); length /= 2; if ((length >= DMA_CHUNK_LENGTH) && (length % DMA_CHUNK_LENGTH)) { - _LOG("psxgpu: transfer data length (%d) is not a multiple of %d, rounding\n", length, DMA_CHUNK_LENGTH); + _sdk_log("psxgpu: transfer data length (%d) is not a multiple of %d, rounding\n", length, DMA_CHUNK_LENGTH); length += DMA_CHUNK_LENGTH - 1; } @@ -53,15 +47,19 @@ static void _dma_transfer(const RECT *rect, uint32_t *data, int write) { /* VRAM transfer API */ int LoadImage(const RECT *rect, const uint32_t *data) { - return EnqueueDrawOp(&_dma_transfer, (uint32_t) rect, (uint32_t) data, 1); + return EnqueueDrawOp( + (void *) &_dma_transfer, (uint32_t) rect, (uint32_t) data, 1 + ); } int StoreImage(const RECT *rect, uint32_t *data) { - return EnqueueDrawOp(&_dma_transfer, (uint32_t) rect, (uint32_t) data, 0); + return EnqueueDrawOp( + (void *) &_dma_transfer, (uint32_t) rect, (uint32_t) data, 0 + ); } int MoveImage(const RECT *rect, int x, int y) { - return EnqueueDrawOp(&MoveImage2, (uint32_t) rect, x, y); + return EnqueueDrawOp((void *) &MoveImage2, (uint32_t) rect, x, y); } void LoadImage2(const RECT *rect, const uint32_t *data) { diff --git a/libpsn00b/psxpress/mdec.c b/libpsn00b/psxpress/mdec.c index 06510cb..d43436f 100644 --- a/libpsn00b/psxpress/mdec.c +++ b/libpsn00b/psxpress/mdec.c @@ -4,7 +4,7 @@ */ #include -#include +#include #include #include #include @@ -81,14 +81,6 @@ static const DECDCTENV _default_mdec_env = { } }; -/* Private utilities */ - -#ifdef NDEBUG -#define _LOG(...) -#else -#define _LOG(...) printf(__VA_ARGS__) -#endif - /* Public API */ void DecDCTReset(int mode) { @@ -135,7 +127,7 @@ void DecDCTin(const uint32_t *data, int mode) { // the stream. void DecDCTinRaw(const uint32_t *data, size_t length) { if ((length >= DMA_CHUNK_LENGTH) && (length % DMA_CHUNK_LENGTH)) { - _LOG("psxpress: transfer data length (%d) is not a multiple of %d, rounding\n", length, DMA_CHUNK_LENGTH); + _sdk_log("psxpress: transfer data length (%d) is not a multiple of %d, rounding\n", length, DMA_CHUNK_LENGTH); length += DMA_CHUNK_LENGTH - 1; } @@ -157,7 +149,8 @@ int DecDCTinSync(int mode) { return 0; } - _LOG("psxpress: DecDCTinSync() timeout\n"); + _sdk_log("psxpress: DecDCTinSync() timeout\n"); + _sdk_dump_log(); return -1; } @@ -165,7 +158,7 @@ void DecDCTout(uint32_t *data, size_t length) { DecDCToutSync(0); if ((length >= DMA_CHUNK_LENGTH) && (length % DMA_CHUNK_LENGTH)) { - _LOG("psxpress: transfer data length (%d) is not a multiple of %d, rounding\n", length, DMA_CHUNK_LENGTH); + _sdk_log("psxpress: transfer data length (%d) is not a multiple of %d, rounding\n", length, DMA_CHUNK_LENGTH); length += DMA_CHUNK_LENGTH - 1; } @@ -187,6 +180,7 @@ int DecDCToutSync(int mode) { return 0; } - _LOG("psxpress: DecDCToutSync() timeout\n"); + _sdk_log("psxpress: DecDCToutSync() timeout\n"); + _sdk_dump_log(); return -1; } diff --git a/libpsn00b/psxspu/common.c b/libpsn00b/psxspu/common.c index 380bd3d..7d90858 100644 --- a/libpsn00b/psxspu/common.c +++ b/libpsn00b/psxspu/common.c @@ -4,7 +4,7 @@ */ #include -#include +#include #include #include @@ -19,28 +19,22 @@ static uint16_t _transfer_addr = WRITABLE_AREA_ADDR; /* Private utilities */ -#ifdef NDEBUG -#define _LOG(...) -#else -#define _LOG(...) printf(__VA_ARGS__) -#endif - static void _wait_status(uint16_t mask, uint16_t value) { for (int i = STATUS_TIMEOUT; i; i--) { if ((SPU_STAT & mask) == value) return; } - _LOG("psxspu: status register timeout (0x%04x)\n", SPU_STAT); + _sdk_log("psxspu: status register timeout (0x%04x)\n", SPU_STAT); } static void _dma_transfer(uint32_t *data, size_t length, int write) { if (length % 4) - _LOG("psxspu: can't transfer a number of bytes that isn't multiple of 4\n"); + _sdk_log("psxspu: can't transfer a number of bytes that isn't multiple of 4\n"); length /= 4; if ((length >= DMA_CHUNK_LENGTH) && (length % DMA_CHUNK_LENGTH)) { - _LOG("psxspu: transfer data length (%d) is not a multiple of %d, rounding\n", length, DMA_CHUNK_LENGTH); + _sdk_log("psxspu: transfer data length (%d) is not a multiple of %d, rounding\n", length, DMA_CHUNK_LENGTH); length += DMA_CHUNK_LENGTH - 1; } -- cgit v1.2.3