aboutsummaryrefslogtreecommitdiff
path: root/libpsn00b/libpsxcd/psxcd.c
diff options
context:
space:
mode:
authorJohn Wilbert M. Villamor <lameguy64@gmail.com>2019-11-22 09:11:12 +0800
committerJohn Wilbert M. Villamor <lameguy64@gmail.com>2019-11-22 09:11:12 +0800
commitea46d05aed0343c20d8fdfaa0e67d54d51e8e2a0 (patch)
tree43e2a53f4e5f7f55b075cfc9d6dc7a652a7b0837 /libpsn00b/libpsxcd/psxcd.c
parentd80d92e13330d527ddb94420b19f9e21bf0e74eb (diff)
downloadpsn00bsdk-ea46d05aed0343c20d8fdfaa0e67d54d51e8e2a0.tar.gz
Added long awaited CD-ROM library and loads of fixes, see changelog for details
Diffstat (limited to 'libpsn00b/libpsxcd/psxcd.c')
-rw-r--r--libpsn00b/libpsxcd/psxcd.c319
1 files changed, 319 insertions, 0 deletions
diff --git a/libpsn00b/libpsxcd/psxcd.c b/libpsn00b/libpsxcd/psxcd.c
new file mode 100644
index 0000000..5be9eec
--- /dev/null
+++ b/libpsn00b/libpsxcd/psxcd.c
@@ -0,0 +1,319 @@
+#include <stdio.h>
+#include "psxcd.h"
+
+extern volatile char _cd_ack_wait;
+extern volatile unsigned char _cd_last_int;
+extern volatile unsigned char _cd_last_mode;
+extern volatile unsigned char _cd_status;
+extern volatile CdlCB _cd_callback_int1_data;
+volatile unsigned char *_cd_result_ptr;
+
+extern volatile char _cd_media_changed;
+
+void _cd_init(void);
+void _cd_control(unsigned char com, unsigned char *param, int plen);
+void _cd_wait_ack(void);
+void _cd_wait(void);
+
+int CdInit(int mode)
+{
+ // Sets up CD-ROM hardware and low-level subsystem
+ _cd_init();
+
+ // So CD ISO file system component will update the ISO descriptor
+ _cd_media_changed = 1;
+
+ // Issue commands to initialize the CD-ROM hardware
+ CdControl(CdlNop, 0, 0);
+ CdControl(CdlInit, 0, 0);
+
+ if( CdSync(0, 0) != CdlDiskError )
+ {
+ CdControl(CdlDemute, 0, 0);
+ printf("psxcd: Init Ok!\n");
+ }
+ else
+ {
+ printf("psxcd: Error initializing. Bad disc/drive or no disc inserted.\n");
+ }
+
+ return 1;
+}
+
+int CdControl(unsigned char com, unsigned char *param, unsigned char *result)
+{
+ // Don't issue command if ack is not received yet
+ if( _cd_ack_wait )
+ {
+ return 0;
+ }
+
+ _cd_result_ptr = result;
+
+ CdControlF(com, param);
+ _cd_wait_ack();
+
+ return 1;
+}
+
+int CdControlB(unsigned char com, unsigned char *param, unsigned char *result)
+{
+ if( !CdControl(com, param, result) )
+ {
+ return 0;
+ }
+
+ CdSync(0, 0);
+ return 1;
+}
+
+int CdControlF(unsigned char com, unsigned char *param)
+{
+ int param_len=0;
+
+ // Command specific parameters
+ switch(com)
+ {
+ case CdlSetloc:
+ param_len = 3;
+ break;
+ case CdlPlay:
+ if( param )
+ {
+ param_len = 1;
+ }
+ break;
+ case CdlSetfilter:
+ param_len = 2;
+ break;
+ case CdlSetmode:
+ param_len = 1;
+ break;
+ case CdlSetsession:
+ param_len = 1;
+ break;
+ case CdlTest:
+ param_len = 1;
+ break;
+ case CdlGetTD:
+ param_len = 1;
+ }
+
+ // Issue Setloc if parameters are specified on CdlReadN and CdlReadS
+ if( ( com == CdlReadN ) || ( com == CdlReadS ) )
+ {
+ if( param )
+ {
+ _cd_control(CdlSetloc, param, 3);
+ }
+ }
+
+ // Issue CD command
+ _cd_control(com, param, param_len);
+
+ return 1;
+}
+
+int CdSync(int mode, unsigned char *result)
+{
+ int cdirq;
+
+ if( mode )
+ {
+ if( result )
+ {
+ *result = _cd_status;
+ }
+
+ cdirq = _cd_last_int;
+ if( cdirq == CdlAcknowledge )
+ {
+ cdirq = CdlComplete;
+ }
+ return cdirq;
+ }
+
+ _cd_wait();
+
+ if( result )
+ {
+ *result = _cd_status;
+ }
+
+ cdirq = _cd_last_int;
+ if( cdirq == CdlAcknowledge )
+ {
+ cdirq = CdlComplete;
+ }
+
+ return cdirq;
+}
+
+int CdGetToc(CdlLOC *toc)
+{
+ u_char track_info[8];
+ int i,tracks;
+
+ // Get number of tracks
+ if( !CdControl(CdlGetTN, 0, track_info) )
+ {
+ return 0;
+ }
+
+ if( CdSync(1, 0) != CdlComplete )
+ {
+ return 0;
+ }
+
+ tracks = 1+(btoi(track_info[2])-btoi(track_info[1]));
+
+ // Get track positions
+ for(i=0; i<tracks; i++)
+ {
+ int t = itob(1+i);
+ if( !CdControl(CdlGetTD, (u_char*)&t, (u_char*)&toc[i]) )
+ {
+ return 0;
+ }
+ if( CdSync(1, 0) != CdlComplete )
+ {
+ return 0;
+ }
+ toc[i].sector = 0;
+ toc[i].track = 1+i;
+ }
+
+ return tracks;
+}
+
+CdlLOC *CdIntToPos(int i, CdlLOC *p) {
+
+ i += 150;
+
+ p->minute = itob((i/75)/60);
+ p->second = itob((i/75)%60);
+ p->sector = itob(i%75);
+
+ return p;
+
+}
+
+int CdPosToInt(CdlLOC *p)
+{
+ return ((75*(btoi(p->minute)*60))+(75*btoi(p->second))+btoi(p->sector))-150;
+}
+
+int CdStatus(void)
+{
+ return _cd_status;
+}
+
+int CdMode(void)
+{
+ return _cd_last_mode;
+}
+
+
+// CD data read routines
+volatile int _cd_sector_count = 0;
+volatile unsigned int *_cd_read_addr;
+volatile unsigned char _cd_read_result[8];
+volatile unsigned int _cd_read_oldcb;
+volatile unsigned int _cd_read_sector_sz;
+volatile CdlCB _cd_read_cb;
+
+// Sector callback
+static void _CdReadReadyCallback(int status, unsigned char *result)
+{
+ if( status == CdlDataReady )
+ {
+ // Fetch sector from CD controller
+ CdGetSector((void*)_cd_read_addr, _cd_read_sector_sz);
+
+ // Increment destination address
+ _cd_read_addr += _cd_read_sector_sz>>2;
+
+ // Subtract sector count
+ _cd_sector_count--;
+ }
+
+ // End reading with pause command when sector count reaches zero
+ // or when an error occurs
+ if( ( _cd_sector_count <= 0 ) || ( status == CdlDiskError ) )
+ {
+ // Stop reading
+ _cd_control(CdlPause, 0, 0);
+
+ // Revert previous ready callback
+ _cd_callback_int1_data = (CdlCB)_cd_read_oldcb;
+
+ // Execute read completion callback
+ if( _cd_read_cb )
+ {
+ _cd_read_cb(status, result);
+ }
+ }
+}
+
+int CdRead(int sectors, unsigned int *buf, int mode)
+{
+ // Set sectors to read count
+ _cd_sector_count = sectors;
+ _cd_read_addr = buf;
+
+ // Determine sector based on mode flags
+ if( mode & CdlModeSize0 )
+ {
+ _cd_read_sector_sz = 2328;
+ }
+ else if( mode & CdlModeSize1 )
+ {
+ _cd_read_sector_sz = 2340;
+ }
+ else
+ {
+ _cd_read_sector_sz = 2048;
+ }
+
+ // Set readt callback
+ _cd_read_oldcb = CdReadyCallback(_CdReadReadyCallback);
+
+ // Set specified mode
+ CdControl(CdlSetmode, (unsigned char*)&mode, 0);
+
+ // Begin reading sectors
+ CdControl(CdlReadN, 0, (unsigned char*)_cd_read_result);
+
+ return 0;
+}
+
+int CdReadSync(int mode, unsigned char *result)
+{
+ if( mode )
+ {
+ if( CdSync(1, 0) == CdlDiskError )
+ {
+ return -1;
+ }
+ return _cd_sector_count;
+ }
+
+ while(_cd_sector_count > 0);
+ if( CdSync(0, result) != CdlComplete )
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+unsigned int CdReadCallback(CdlCB func)
+{
+ unsigned int old_func;
+
+ old_func = (unsigned int)_cd_read_cb;
+
+ _cd_read_cb = func;
+
+ return old_func;
+}