#include #include #include #include #include #include #include #include #include "CDVDiso.h" #include "Config.h" #ifndef MAX_PATH #define MAX_PATH 255 #endif char IsoFile[256]; char IsoCWD[256]; char CdDev[256]; _cdIso cdIso[8]; u8 *pbuffer; int cdblocksize; int cdblockofs; int cdoffset; int cdtype; int cdblocks; int Zmode; // 1 Z - 2 bz2 int fmode; // 0 - file / 1 - Zfile char *Ztable; int BlockDump; isoFile *fdump; isoFile *iso; FILE *cdvdLog = NULL; // This var is used to detect resume-style behavior of the Pcsx2 emulator, // and skip prompting the user for a new CD when it's likely they want to run the existing one. static char cdvdCurrentIso[MAX_PATH]; char *methods[] = { ".Z - compress faster", ".BZ - compress better", NULL }; #ifdef PCSX2_DEBUG char *LibName = "Linuz Iso CDVD (Debug) "; #else char *LibName = "Linuz Iso CDVD "; #endif const u8 version = PS2E_CDVD_VERSION; const u8 revision = 0; const u8 build = 9; u8 cdbuffer[CD_FRAMESIZE_RAW * 10] = {0}; s32 msf_to_lba(u8 m, u8 s, u8 f) { u32 lsn; lsn = f; lsn += (s - 2) * 75; lsn += m * 75 * 60; return lsn; } void lba_to_msf(s32 lba, u8* m, u8* s, u8* f) { lba += 150; *m = lba / (60 * 75); *s = (lba / 75) % 60; *f = lba % 75; } #define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */ #define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */ EXPORT_C_(char*) PS2EgetLibName() { return LibName; } EXPORT_C_(u32) PS2EgetLibType() { return PS2E_LT_CDVD; } EXPORT_C_(u32) PS2EgetLibVersion2(u32 type) { return (version << 16) | (revision << 8) | build; } #ifdef PCSX2_DEBUG void __Log(char *fmt, ...) { va_list list; if (cdvdLog == NULL) return; va_start(list, fmt); vfprintf(cdvdLog, fmt, list); va_end(list); } #else #define __Log 0&& #endif EXPORT_C_(s32) CDVDinit() { #ifdef PCSX2_DEBUG cdvdLog = fopen("logs/cdvdLog.txt", "w"); if (cdvdLog == NULL) { cdvdLog = fopen("cdvdLog.txt", "w"); if (cdvdLog == NULL) { SysMessage("Can't create cdvdLog.txt"); return -1; } } setvbuf(cdvdLog, NULL, _IONBF, 0); CDVD_LOG("CDVDinit\n"); #endif cdvdCurrentIso[0] = 0; memset(cdIso, 0, sizeof(cdIso)); return 0; } EXPORT_C_(void) CDVDshutdown() { cdvdCurrentIso[0] = 0; #ifdef CDVD_LOG if (cdvdLog != NULL) fclose(cdvdLog); #endif } EXPORT_C_(s32) CDVDopen(const char* pTitle) { LoadConf(); if (pTitle != NULL) strcpy(IsoFile, pTitle); if (*IsoFile == 0) strcpy(IsoFile, cdvdCurrentIso); if (*IsoFile == 0) { char temp[256]; CfgOpenFile(); if (IsoFile[0] == 0) { // user pressed CANCEL return 1; } strcpy(temp, IsoFile); *IsoFile = 0; SaveConf(); strcpy(IsoFile, temp); } iso = isoOpen(IsoFile); if (iso == NULL) { SysMessage("Error loading %s\nMake sure the iso file is not mounted in any disk emulation software!", IsoFile); return -1; } if (iso->type == ISOTYPE_DVD) cdtype = CDVD_TYPE_PS2DVD; else if (iso->type == ISOTYPE_AUDIO) cdtype = CDVD_TYPE_CDDA; else cdtype = CDVD_TYPE_PS2CD; if (BlockDump) { char fname_only[MAX_PATH]; #ifdef _WIN32 char fname[MAX_PATH], ext[MAX_PATH]; _splitpath(IsoFile, NULL, NULL, fname, ext); _makepath(fname_only, NULL, NULL, fname, NULL); #else char* p, *plast; plast = p = strchr(IsoFile, '/'); while (p != NULL) { plast = p; p = strchr(p + 1, '/'); } // Lets not create dumps in the plugin directory. strcpy(fname_only, "../"); if (plast != NULL) strcat(fname_only, plast + 1); else strcat(fname_only, IsoFile); plast = p = strchr(fname_only, '.'); while (p != NULL) { plast = p; p = strchr(p + 1, '.'); } if (plast != NULL) *plast = 0; #endif strcat(fname_only, ".dump"); fdump = isoCreate(fname_only, ISOFLAGS_BLOCKDUMP); if (fdump) isoSetFormat(fdump, iso->blockofs, iso->blocksize, iso->blocks); } else { fdump = NULL; } return 0; } EXPORT_C_(void) CDVDclose() { if (!iso) return; strcpy(cdvdCurrentIso, IsoFile); isoClose(iso); if (fdump != NULL) isoClose(fdump); } EXPORT_C_(s32) CDVDreadSubQ(u32 lsn, cdvdSubQ* subq) { if (!iso) return -1; // fake it u8 min, sec, frm; subq->ctrl = 4; subq->mode = 1; subq->trackNum = itob(1); subq->trackIndex = itob(1); lba_to_msf(lsn, &min, &sec, &frm); subq->trackM = itob(min); subq->trackS = itob(sec); subq->trackF = itob(frm); subq->pad = 0; lba_to_msf(lsn + (2*75), &min, &sec, &frm); subq->discM = itob(min); subq->discS = itob(sec); subq->discF = itob(frm); return 0; } EXPORT_C_(s32) CDVDgetTN(cdvdTN *Buffer) { Buffer->strack = 1; Buffer->etrack = 1; return 0; } EXPORT_C_(s32) CDVDgetTD(u8 Track, cdvdTD *Buffer) { if (!iso) return -1; if (Track == 0) { Buffer->lsn = iso->blocks; } else { Buffer->type = CDVD_MODE1_TRACK; Buffer->lsn = 0; } return 0; } static s32 layer1start = -1; static bool testForPartitionInfo( const u8 (&tempbuffer)[CD_FRAMESIZE_RAW] ) { const int off = iso->blockofs; // test for: CD001 return ( (tempbuffer[off+1] == 0x43) && (tempbuffer[off+2] == 0x44) && (tempbuffer[off+3] == 0x30) && (tempbuffer[off+4] == 0x30) && (tempbuffer[off+5] == 0x31) ); } EXPORT_C_(s32) CDVDgetTOC(void* toc) { if (!iso) return -1; u8 type = CDVDgetDiskType(); u8* tocBuff = (u8*)toc; //__Log("CDVDgetTOC\n"); if (type == CDVD_TYPE_DVDV || type == CDVD_TYPE_PS2DVD) { // get dvd structure format // scsi command 0x43 memset(tocBuff, 0, 2048); if (layer1start != -2 && iso->blocks >= 0x300000) { int off = iso->blockofs; // dual sided tocBuff[ 0] = 0x24; tocBuff[ 1] = 0x02; tocBuff[ 2] = 0xF2; tocBuff[ 3] = 0x00; tocBuff[ 4] = 0x41; tocBuff[ 5] = 0x95; tocBuff[14] = 0x60; // dual sided, ptp tocBuff[16] = 0x00; tocBuff[17] = 0x03; tocBuff[18] = 0x00; tocBuff[19] = 0x00; // search for it if (layer1start == -1) { printf("CDVD: searching for layer1..."); /*tempbuffer = (u8*)malloc(CD_FRAMESIZE_RAW * 10); for (layer1start = (iso->blocks / 2 - 0x10) & ~0xf; layer1start < 0x200010; layer1start += 16) { isoReadBlock(iso, tempbuffer, layer1start); // CD001 if (tempbuffer[off+1] == 0x43 && tempbuffer[off+2] == 0x44 && tempbuffer[off+3] == 0x30 && tempbuffer[off+4] == 0x30 && tempbuffer[off+5] == 0x31) break; } free(tempbuffer);*/ uint midsector = (iso->blocks / 2) & ~0xf; uint deviation = 0; while( (layer1start == -1) && (deviation < midsector-16) ) { u8 tempbuffer[CD_FRAMESIZE_RAW]; isoReadBlock(iso, tempbuffer, midsector-deviation); if(testForPartitionInfo( tempbuffer )) layer1start = midsector-deviation; else { isoReadBlock(iso, tempbuffer, midsector+deviation); if( testForPartitionInfo( tempbuffer ) ) layer1start = midsector+deviation; } if( layer1start != -1 ) { if( tempbuffer[iso->blockofs] != 0x01 ) { fprintf( stderr, "(LinuzCDVDiso): Invalid partition type on layer 1!? (type=0x%x)", tempbuffer[iso->blockofs] ); } } deviation += 16; } if (layer1start == -1) { printf("(LinuzCDVDiso): Couldn't find second layer on dual layer... ignoring\n"); // fake it tocBuff[ 0] = 0x04; tocBuff[ 1] = 0x02; tocBuff[ 2] = 0xF2; tocBuff[ 3] = 0x00; tocBuff[ 4] = 0x86; tocBuff[ 5] = 0x72; tocBuff[16] = 0x00; tocBuff[17] = 0x03; tocBuff[18] = 0x00; tocBuff[19] = 0x00; layer1start = -2; return 0; } printf("(LinuzCDVDiso): found at 0x%8.8x\n", layer1start); layer1start = layer1start + 0x30000 - 1; } tocBuff[20] = layer1start >> 24; tocBuff[21] = (layer1start >> 16) & 0xff; tocBuff[22] = (layer1start >> 8) & 0xff; tocBuff[23] = (layer1start >> 0) & 0xff; } else { // fake it tocBuff[ 0] = 0x04; tocBuff[ 1] = 0x02; tocBuff[ 2] = 0xF2; tocBuff[ 3] = 0x00; tocBuff[ 4] = 0x86; tocBuff[ 5] = 0x72; tocBuff[16] = 0x00; tocBuff[17] = 0x03; tocBuff[18] = 0x00; tocBuff[19] = 0x00; } } else if ((type == CDVD_TYPE_CDDA) || (type == CDVD_TYPE_PS2CDDA) || (type == CDVD_TYPE_PS2CD) || (type == CDVD_TYPE_PSCDDA) || (type == CDVD_TYPE_PSCD)) { // cd toc // (could be replaced by 1 command that reads the full toc) u8 min, sec, frm; s32 i, err; cdvdTN diskInfo; cdvdTD trackInfo; memset(tocBuff, 0, 1024); if (CDVDgetTN(&diskInfo) == -1) { diskInfo.etrack = 0; diskInfo.strack = 1; } if (CDVDgetTD(0, &trackInfo) == -1) trackInfo.lsn = 0; tocBuff[0] = 0x41; tocBuff[1] = 0x00; //Number of FirstTrack tocBuff[2] = 0xA0; tocBuff[7] = itob(diskInfo.strack); //Number of LastTrack tocBuff[12] = 0xA1; tocBuff[17] = itob(diskInfo.etrack); //DiskLength lba_to_msf(trackInfo.lsn, &min, &sec, &frm); tocBuff[22] = 0xA2; tocBuff[27] = itob(min); tocBuff[28] = itob(sec); for (i = diskInfo.strack; i <= diskInfo.etrack; i++) { err = CDVDgetTD(i, &trackInfo); lba_to_msf(trackInfo.lsn, &min, &sec, &frm); tocBuff[i*10+30] = trackInfo.type; tocBuff[i*10+32] = err == -1 ? 0 : itob(i); //number tocBuff[i*10+37] = itob(min); tocBuff[i*10+38] = itob(sec); tocBuff[i*10+39] = itob(frm); } } else return -1; return 0; } EXPORT_C_(s32) CDVDreadTrack(u32 lsn, int mode) { if (!iso) return -1; int _lsn = lsn; //__Log("CDVDreadTrack: %x %x\n", lsn, mode); if (_lsn < 0) { // lsn = 2097152 + (-_lsn); lsn = iso->blocks - (-_lsn); } // printf ("CDRreadTrack %d\n", lsn); isoReadBlock(iso, cdbuffer, lsn); if (fdump != NULL) { isoWriteBlock(fdump, cdbuffer, lsn); } pbuffer = cdbuffer; switch (mode) { case CDVD_MODE_2352: break; case CDVD_MODE_2340: pbuffer += 12; break; case CDVD_MODE_2328: pbuffer += 24; break; case CDVD_MODE_2048: pbuffer += 24; break; } return 0; } EXPORT_C_(u8*) CDVDgetBuffer() { return pbuffer; } EXPORT_C_(s32) CDVDgetDiskType() { return cdtype; } EXPORT_C_(s32) CDVDgetTrayStatus() { return CDVD_TRAY_CLOSE; } EXPORT_C_(s32) CDVDctrlTrayOpen() { return 0; } EXPORT_C_(s32) CDVDctrlTrayClose() { return 0; } EXPORT_C_(s32) CDVDtest() { if (*IsoFile == 0) return 0; iso = isoOpen(IsoFile); if (iso == NULL) return -1; isoClose(iso); return 0; }