mirror of https://github.com/PCSX2/pcsx2.git
CDVD: clang-format
This commit is contained in:
parent
c4fa3e3304
commit
f9be4286bd
|
@ -39,18 +39,18 @@ bool BlockdumpFileReader::DetectBlockdump(AsyncFileReader* reader)
|
|||
|
||||
bool isbd = (strncmp(buf, "BDV2", 4) == 0);
|
||||
|
||||
if(!isbd)
|
||||
if (!isbd)
|
||||
reader->SetBlockSize(oldbs);
|
||||
|
||||
return isbd;
|
||||
}
|
||||
|
||||
BlockdumpFileReader::BlockdumpFileReader(void) :
|
||||
m_file(NULL),
|
||||
m_blocks(0),
|
||||
m_blockofs(0),
|
||||
m_dtablesize(0),
|
||||
m_lresult(0)
|
||||
BlockdumpFileReader::BlockdumpFileReader(void)
|
||||
: m_file(NULL)
|
||||
, m_blocks(0)
|
||||
, m_blockofs(0)
|
||||
, m_dtablesize(0)
|
||||
, m_lresult(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ bool BlockdumpFileReader::Open(const wxString& fileName)
|
|||
|
||||
m_filename = fileName;
|
||||
|
||||
m_file = new wxFileInputStream( m_filename );
|
||||
m_file = new wxFileInputStream(m_filename);
|
||||
|
||||
m_file->SeekI(0);
|
||||
m_file->Read(buf, 4);
|
||||
|
@ -83,20 +83,21 @@ bool BlockdumpFileReader::Open(const wxString& fileName)
|
|||
wxFileOffset flen = m_file->GetLength();
|
||||
static const wxFileOffset datalen = flen - BlockDumpHeaderSize;
|
||||
|
||||
pxAssert( (datalen % (m_blocksize + 4)) == 0);
|
||||
pxAssert((datalen % (m_blocksize + 4)) == 0);
|
||||
|
||||
m_dtablesize = datalen / (m_blocksize + 4);
|
||||
m_dtable = std::unique_ptr<u32[]>(new u32[m_dtablesize]);
|
||||
|
||||
m_file->SeekI(BlockDumpHeaderSize);
|
||||
|
||||
u32 bs = 1024*1024;
|
||||
u32 bs = 1024 * 1024;
|
||||
u32 off = 0;
|
||||
u32 has = 0;
|
||||
int i = 0;
|
||||
|
||||
std::unique_ptr<u8[]> buffer(new u8[bs]);
|
||||
do {
|
||||
do
|
||||
{
|
||||
m_file->Read(buffer.get(), bs);
|
||||
has = m_file->LastRead();
|
||||
|
||||
|
@ -109,7 +110,7 @@ bool BlockdumpFileReader::Open(const wxString& fileName)
|
|||
|
||||
off -= has;
|
||||
|
||||
} while(has == bs);
|
||||
} while (has == bs);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -119,7 +120,7 @@ int BlockdumpFileReader::ReadSync(void* pBuffer, uint lsn, uint count)
|
|||
u8* dst = (u8*)pBuffer;
|
||||
// Console.WriteLn("_isoReadBlockD %u, blocksize=%u, blockofs=%u\n", lsn, iso->blocksize, iso->blockofs);
|
||||
|
||||
while(count > 0)
|
||||
while (count > 0)
|
||||
{
|
||||
bool ok = false;
|
||||
for (int i = 0; i < m_dtablesize; ++i)
|
||||
|
@ -132,20 +133,20 @@ int BlockdumpFileReader::ReadSync(void* pBuffer, uint lsn, uint count)
|
|||
|
||||
#ifdef PCSX2_DEBUG
|
||||
u32 check_lsn;
|
||||
m_file->SeekI( BlockDumpHeaderSize + (i * (m_blocksize + 4)) );
|
||||
m_file->Read( &check_lsn, sizeof(check_lsn) );
|
||||
pxAssert( check_lsn == lsn );
|
||||
m_file->SeekI(BlockDumpHeaderSize + (i * (m_blocksize + 4)));
|
||||
m_file->Read(&check_lsn, sizeof(check_lsn));
|
||||
pxAssert(check_lsn == lsn);
|
||||
#else
|
||||
m_file->SeekI( BlockDumpHeaderSize + (i * (m_blocksize + 4)) + 4 );
|
||||
m_file->SeekI(BlockDumpHeaderSize + (i * (m_blocksize + 4)) + 4);
|
||||
#endif
|
||||
|
||||
m_file->Read( dst, m_blocksize );
|
||||
m_file->Read(dst, m_blocksize);
|
||||
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!ok)
|
||||
if (!ok)
|
||||
{
|
||||
Console.WriteLn("Block %u not found in dump", lsn);
|
||||
return -1;
|
||||
|
@ -175,7 +176,7 @@ void BlockdumpFileReader::CancelRead(void)
|
|||
|
||||
void BlockdumpFileReader::Close(void)
|
||||
{
|
||||
if(m_file)
|
||||
if (m_file)
|
||||
{
|
||||
delete m_file;
|
||||
m_file = NULL;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -20,15 +20,15 @@
|
|||
#include "IopCommon.h"
|
||||
#include "CDVDaccess.h"
|
||||
|
||||
#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */
|
||||
#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */
|
||||
#define btoi(b) ((b) / 16 * 10 + (b) % 16) /* BCD to u_char */
|
||||
#define itob(i) ((i) / 10 * 16 + (i) % 10) /* u_char to BCD */
|
||||
|
||||
static __fi s32 msf_to_lsn(u8 *Time)
|
||||
static __fi s32 msf_to_lsn(u8* Time)
|
||||
{
|
||||
u32 lsn;
|
||||
|
||||
lsn = Time[2];
|
||||
lsn +=(Time[1] - 2) * 75;
|
||||
lsn += (Time[1] - 2) * 75;
|
||||
lsn += Time[0] * 75 * 60;
|
||||
return lsn;
|
||||
}
|
||||
|
@ -64,7 +64,8 @@ static __fi void lba_to_msf(s32 lba, u8* m, u8* s, u8* f)
|
|||
*f = lba % 75;
|
||||
}
|
||||
|
||||
struct cdvdRTC {
|
||||
struct cdvdRTC
|
||||
{
|
||||
u8 status;
|
||||
u8 second;
|
||||
u8 minute;
|
||||
|
@ -75,7 +76,8 @@ struct cdvdRTC {
|
|||
u8 year;
|
||||
};
|
||||
|
||||
struct cdvdStruct {
|
||||
struct cdvdStruct
|
||||
{
|
||||
u8 nCommand;
|
||||
u8 Ready;
|
||||
u8 Error;
|
||||
|
@ -124,9 +126,9 @@ struct cdvdStruct {
|
|||
u8 mg_buffer[65536];
|
||||
int mg_size;
|
||||
int mg_maxsize;
|
||||
int mg_datatype;//0-data(encrypted); 1-header
|
||||
u8 mg_kbit[16];//last BIT key 'seen'
|
||||
u8 mg_kcon[16];//last content key 'seen'
|
||||
int mg_datatype; //0-data(encrypted); 1-header
|
||||
u8 mg_kbit[16]; //last BIT key 'seen'
|
||||
u8 mg_kcon[16]; //last content key 'seen'
|
||||
|
||||
u8 TrayTimeout;
|
||||
u8 Action; // the currently scheduled emulated action
|
||||
|
|
|
@ -40,13 +40,13 @@ without proper emulation of the cdvd status flag it also tends to break things.
|
|||
|
||||
enum CdvdIrqId
|
||||
{
|
||||
Irq_None = 0
|
||||
, Irq_DataReady = 0
|
||||
, Irq_CommandComplete
|
||||
, Irq_Acknowledge
|
||||
, Irq_EndOfData
|
||||
, Irq_Error
|
||||
, Irq_NotReady
|
||||
Irq_None = 0,
|
||||
Irq_DataReady = 0,
|
||||
Irq_CommandComplete,
|
||||
Irq_Acknowledge,
|
||||
Irq_EndOfData,
|
||||
Irq_Error,
|
||||
Irq_NotReady
|
||||
|
||||
};
|
||||
|
||||
|
@ -77,12 +77,12 @@ enum cdvdready
|
|||
// Actions are handled by the cdvdInterrupt()
|
||||
enum cdvdActions
|
||||
{
|
||||
cdvdAction_None = 0
|
||||
, cdvdAction_Seek
|
||||
, cdvdAction_Standby
|
||||
, cdvdAction_Stop
|
||||
, cdvdAction_Break
|
||||
, cdvdAction_Read // note: not used yet.
|
||||
cdvdAction_None = 0,
|
||||
cdvdAction_Seek,
|
||||
cdvdAction_Standby,
|
||||
cdvdAction_Stop,
|
||||
cdvdAction_Break,
|
||||
cdvdAction_Read // note: not used yet.
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -104,7 +104,7 @@ enum CDVD_MODE_TYPE
|
|||
};
|
||||
|
||||
static const uint tbl_FastSeekDelta[3] =
|
||||
{
|
||||
{
|
||||
4371, // CD-ROM
|
||||
14764, // Single-layer DVD-ROM
|
||||
13360 // dual-layer DVD-ROM [currently unused]
|
||||
|
@ -113,7 +113,7 @@ static const uint tbl_FastSeekDelta[3] =
|
|||
// if a seek is within this many blocks, read instead of seek.
|
||||
// These values are arbitrary assumptions. Not sure what the real PS2 uses.
|
||||
static const uint tbl_ContigiousSeekDelta[3] =
|
||||
{
|
||||
{
|
||||
8, // CD-ROM
|
||||
16, // single-layer DVD-ROM
|
||||
16, // dual-layer DVD-ROM [currently unused]
|
||||
|
@ -134,14 +134,14 @@ static const uint PSX_DVD_READSPEED = 1382400 + 256000; // normal is 1 Byte Time
|
|||
// Legacy Note: FullSeek timing causes many games to load very slow, but it likely not the real problem.
|
||||
// Games breaking with it set to PSXCLK*40 : "wrath unleashed" and "Shijou Saikyou no Deshi Kenichi".
|
||||
|
||||
static const uint Cdvd_FullSeek_Cycles = (PSXCLK*100) / 1000; // average number of cycles per fullseek (100ms)
|
||||
static const uint Cdvd_FastSeek_Cycles = (PSXCLK*30) / 1000; // average number of cycles per fastseek (37ms)
|
||||
static const uint Cdvd_FullSeek_Cycles = (PSXCLK * 100) / 1000; // average number of cycles per fullseek (100ms)
|
||||
static const uint Cdvd_FastSeek_Cycles = (PSXCLK * 30) / 1000; // average number of cycles per fastseek (37ms)
|
||||
short DiscSwapTimerSeconds = 0;
|
||||
bool trayState = 0; // Used to check if the CD tray status has changed since the last time
|
||||
|
||||
static const char *mg_zones[8] = {"Japan", "USA", "Europe", "Oceania", "Asia", "Russia", "China", "Mexico"};
|
||||
static const char* mg_zones[8] = {"Japan", "USA", "Europe", "Oceania", "Asia", "Russia", "China", "Mexico"};
|
||||
|
||||
static const char *nCmdName[0x100]= {
|
||||
static const char* nCmdName[0x100] = {
|
||||
"CdSync",
|
||||
"CdNop",
|
||||
"CdStandby",
|
||||
|
@ -178,15 +178,15 @@ enum nCmds
|
|||
N_CD_CHG_SPDL_CTRL = 0x0F, // CdChgSpdlCtrl
|
||||
};
|
||||
|
||||
static const char *sCmdName[0x100]= {
|
||||
"", "sceCdGetDiscType", "sceCdReadSubQ", "subcommands",//sceCdGetMecaconVersion, read/write console id, read renewal date
|
||||
static const char* sCmdName[0x100] = {
|
||||
"", "sceCdGetDiscType", "sceCdReadSubQ", "subcommands", //sceCdGetMecaconVersion, read/write console id, read renewal date
|
||||
"", "sceCdTrayState", "sceCdTrayCtrl", "",
|
||||
"sceCdReadClock", "sceCdWriteClock", "sceCdReadNVM", "sceCdWriteNVM",
|
||||
"sceCdSetHDMode", "", "", "sceCdPowerOff",
|
||||
"", "", "sceCdReadILinkID", "sceCdWriteILinkID", /*10*/
|
||||
"sceAudioDigitalOut", "sceForbidDVDP", "sceAutoAdjustCtrl", "sceCdReadModelNumber",
|
||||
"sceWriteModelNumber", "sceCdForbidCD", "sceCdBootCertify", "sceCdCancelPOffRdy",
|
||||
"sceCdBlueLEDCtl", "", "sceRm2Read", "sceRemote2_7",//Rm2PortGetConnection?
|
||||
"sceCdBlueLEDCtl", "", "sceRm2Read", "sceRemote2_7", //Rm2PortGetConnection?
|
||||
"sceRemote2_6", "sceCdWriteWakeUpTime", "sceCdReadWakeUpTime", "", /*20*/
|
||||
"sceCdRcBypassCtl", "", "", "",
|
||||
"", "sceCdNoticeGameStart", "", "",
|
||||
|
@ -223,7 +223,8 @@ static const char *sCmdName[0x100]= {
|
|||
};
|
||||
|
||||
// NVM (eeprom) layout info
|
||||
struct NVMLayout {
|
||||
struct NVMLayout
|
||||
{
|
||||
u32 biosVer; // bios version that this eeprom layout is for
|
||||
s32 config0; // offset of 1st config block
|
||||
s32 config1; // offset of 2nd config block
|
||||
|
@ -237,7 +238,7 @@ struct NVMLayout {
|
|||
|
||||
#define NVM_FORMAT_MAX 2
|
||||
static NVMLayout nvmlayouts[NVM_FORMAT_MAX] =
|
||||
{
|
||||
{
|
||||
{0x000, 0x280, 0x300, 0x200, 0x1C8, 0x1C0, 0x1A0, 0x180, 0x198}, // eeproms from bios v0.00 and up
|
||||
{0x146, 0x270, 0x2B0, 0x200, 0x1C8, 0x1E0, 0x1B0, 0x180, 0x198}, // eeproms from bios v1.70 and up
|
||||
};
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#define ENABLE_TIMESTAMPS
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <wx/msw/wrapwin.h>
|
||||
#include <wx/msw/wrapwin.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
|
@ -39,12 +39,11 @@
|
|||
CDVD_API* CDVD = NULL;
|
||||
|
||||
const wxChar* CDVD_SourceLabels[] =
|
||||
{
|
||||
{
|
||||
L"ISO",
|
||||
L"Disc",
|
||||
L"NoDisc",
|
||||
NULL
|
||||
};
|
||||
NULL};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// diskTypeCached
|
||||
|
@ -69,7 +68,7 @@ static OutputIsoFile blockDumpFile;
|
|||
// relying on DEP exceptions -- and a little more reliable too.
|
||||
static void CheckNullCDVD()
|
||||
{
|
||||
pxAssertDev( CDVD != NULL, "Invalid CDVD object state (null pointer exception)" );
|
||||
pxAssertDev(CDVD != NULL, "Invalid CDVD object state (null pointer exception)");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -79,42 +78,46 @@ static int CheckDiskTypeFS(int baseType)
|
|||
{
|
||||
IsoFSCDVD isofs;
|
||||
IsoDirectory rootdir(isofs);
|
||||
try {
|
||||
IsoFile file( rootdir, L"SYSTEM.CNF;1");
|
||||
try
|
||||
{
|
||||
IsoFile file(rootdir, L"SYSTEM.CNF;1");
|
||||
|
||||
int size = file.getLength();
|
||||
|
||||
std::unique_ptr<char[]> buffer(new char[file.getLength() + 1]);
|
||||
file.read(buffer.get(),size);
|
||||
buffer[size]='\0';
|
||||
file.read(buffer.get(), size);
|
||||
buffer[size] = '\0';
|
||||
|
||||
char* pos = strstr(buffer.get(), "BOOT2");
|
||||
if (pos == NULL)
|
||||
{
|
||||
pos = strstr(buffer.get(), "BOOT");
|
||||
if (pos == NULL) return CDVD_TYPE_ILLEGAL;
|
||||
if (pos == NULL)
|
||||
return CDVD_TYPE_ILLEGAL;
|
||||
return CDVD_TYPE_PSCD;
|
||||
}
|
||||
|
||||
return (baseType==CDVD_TYPE_DETCTCD) ? CDVD_TYPE_PS2CD : CDVD_TYPE_PS2DVD;
|
||||
return (baseType == CDVD_TYPE_DETCTCD) ? CDVD_TYPE_PS2CD : CDVD_TYPE_PS2DVD;
|
||||
}
|
||||
catch( Exception::FileNotFound& )
|
||||
catch (Exception::FileNotFound&)
|
||||
{
|
||||
}
|
||||
|
||||
try {
|
||||
IsoFile file( rootdir, L"PSX.EXE;1");
|
||||
try
|
||||
{
|
||||
IsoFile file(rootdir, L"PSX.EXE;1");
|
||||
return CDVD_TYPE_PSCD;
|
||||
}
|
||||
catch( Exception::FileNotFound& )
|
||||
catch (Exception::FileNotFound&)
|
||||
{
|
||||
}
|
||||
|
||||
try {
|
||||
IsoFile file( rootdir, L"VIDEO_TS/VIDEO_TS.IFO;1");
|
||||
try
|
||||
{
|
||||
IsoFile file(rootdir, L"VIDEO_TS/VIDEO_TS.IFO;1");
|
||||
return CDVD_TYPE_DVDV;
|
||||
}
|
||||
catch( Exception::FileNotFound& )
|
||||
catch (Exception::FileNotFound&)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -142,7 +145,7 @@ static int FindDiskType(int mType)
|
|||
static u8 bleh[CD_FRAMESIZE_RAW];
|
||||
cdvdTD td;
|
||||
|
||||
CDVD->getTD(0,&td);
|
||||
CDVD->getTD(0, &td);
|
||||
if (td.lsn > 452849)
|
||||
{
|
||||
iCDType = CDVD_TYPE_DETCTDVDS;
|
||||
|
@ -157,7 +160,7 @@ static int FindDiskType(int mType)
|
|||
//Horrible hack! in CD images position 166 and 171 have block size but not DVD's
|
||||
//It's not always 2048 however (can be 4096)
|
||||
//Test Impossible Mission if thia is changed.
|
||||
if(*(u16*)(bleh+166) == *(u16*)(bleh+171))
|
||||
if (*(u16*)(bleh + 166) == *(u16*)(bleh + 171))
|
||||
iCDType = CDVD_TYPE_DETCTCD;
|
||||
else
|
||||
iCDType = CDVD_TYPE_DETCTDVDS;
|
||||
|
@ -170,16 +173,17 @@ static int FindDiskType(int mType)
|
|||
s32 dlt = 0;
|
||||
u32 l1s = 0;
|
||||
|
||||
if(CDVD->getDualInfo(&dlt,&l1s)==0)
|
||||
if (CDVD->getDualInfo(&dlt, &l1s) == 0)
|
||||
{
|
||||
if (dlt > 0) iCDType = CDVD_TYPE_DETCTDVDD;
|
||||
if (dlt > 0)
|
||||
iCDType = CDVD_TYPE_DETCTDVDD;
|
||||
}
|
||||
}
|
||||
|
||||
switch(iCDType)
|
||||
switch (iCDType)
|
||||
{
|
||||
case CDVD_TYPE_DETCTCD:
|
||||
Console.WriteLn(" * CDVD Disk Open: CD, %d tracks (%d to %d):", tn.etrack-tn.strack+1,tn.strack,tn.etrack);
|
||||
Console.WriteLn(" * CDVD Disk Open: CD, %d tracks (%d to %d):", tn.etrack - tn.strack + 1, tn.strack, tn.etrack);
|
||||
break;
|
||||
|
||||
case CDVD_TYPE_DETCTDVDS:
|
||||
|
@ -192,34 +196,34 @@ static int FindDiskType(int mType)
|
|||
}
|
||||
|
||||
audioTracks = dataTracks = 0;
|
||||
for(int i = tn.strack; i <= tn.etrack; i++)
|
||||
for (int i = tn.strack; i <= tn.etrack; i++)
|
||||
{
|
||||
cdvdTD td,td2;
|
||||
cdvdTD td, td2;
|
||||
|
||||
CDVD->getTD(i,&td);
|
||||
CDVD->getTD(i, &td);
|
||||
|
||||
if (tn.etrack > i)
|
||||
CDVD->getTD(i+1,&td2);
|
||||
CDVD->getTD(i + 1, &td2);
|
||||
else
|
||||
CDVD->getTD(0,&td2);
|
||||
CDVD->getTD(0, &td2);
|
||||
|
||||
int tlength = td2.lsn - td.lsn;
|
||||
|
||||
if (td.type == CDVD_AUDIO_TRACK)
|
||||
{
|
||||
audioTracks++;
|
||||
Console.WriteLn(" * * Track %d: Audio (%d sectors)", i,tlength);
|
||||
Console.WriteLn(" * * Track %d: Audio (%d sectors)", i, tlength);
|
||||
}
|
||||
else
|
||||
{
|
||||
dataTracks++;
|
||||
Console.WriteLn(" * * Track %d: Data (Mode %d) (%d sectors)", i,((td.type==CDVD_MODE1_TRACK)?1:2),tlength);
|
||||
Console.WriteLn(" * * Track %d: Data (Mode %d) (%d sectors)", i, ((td.type == CDVD_MODE1_TRACK) ? 1 : 2), tlength);
|
||||
}
|
||||
}
|
||||
|
||||
if (dataTracks > 0)
|
||||
{
|
||||
iCDType=CheckDiskTypeFS(iCDType);
|
||||
iCDType = CheckDiskTypeFS(iCDType);
|
||||
}
|
||||
|
||||
if (audioTracks > 0)
|
||||
|
@ -227,13 +231,13 @@ static int FindDiskType(int mType)
|
|||
switch (iCDType)
|
||||
{
|
||||
case CDVD_TYPE_PS2CD:
|
||||
iCDType=CDVD_TYPE_PS2CDDA;
|
||||
iCDType = CDVD_TYPE_PS2CDDA;
|
||||
break;
|
||||
case CDVD_TYPE_PSCD:
|
||||
iCDType=CDVD_TYPE_PSCDDA;
|
||||
iCDType = CDVD_TYPE_PSCDDA;
|
||||
break;
|
||||
default:
|
||||
iCDType=CDVD_TYPE_CDDA;
|
||||
iCDType = CDVD_TYPE_CDDA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -258,7 +262,7 @@ static void DetectDiskType()
|
|||
//TODO_CDVD We're not using CDVD plugins anymore but I believe both ISO and Disc use their own
|
||||
//detection system. Possible code reduction here
|
||||
|
||||
switch(baseMediaType)
|
||||
switch (baseMediaType)
|
||||
{
|
||||
#if 0
|
||||
case CDVD_TYPE_CDDA:
|
||||
|
@ -292,7 +296,7 @@ static void DetectDiskType()
|
|||
static wxString m_SourceFilename[3];
|
||||
static CDVD_SourceType m_CurrentSourceType = CDVD_SourceType::NoDisc;
|
||||
|
||||
void CDVDsys_SetFile( CDVD_SourceType srctype, const wxString& newfile )
|
||||
void CDVDsys_SetFile(CDVD_SourceType srctype, const wxString& newfile)
|
||||
{
|
||||
m_SourceFilename[enum_cast(srctype)] = newfile;
|
||||
|
||||
|
@ -304,7 +308,7 @@ void CDVDsys_SetFile( CDVD_SourceType srctype, const wxString& newfile )
|
|||
if (n == wxNOT_FOUND)
|
||||
symName = newfile + L".sym";
|
||||
else
|
||||
symName = newfile.substr(0,n) + L".sym";
|
||||
symName = newfile.substr(0, n) + L".sym";
|
||||
|
||||
wxCharBuffer buf = symName.ToUTF8();
|
||||
symbolMap.LoadNocashSym(buf);
|
||||
|
@ -312,7 +316,7 @@ void CDVDsys_SetFile( CDVD_SourceType srctype, const wxString& newfile )
|
|||
}
|
||||
}
|
||||
|
||||
const wxString& CDVDsys_GetFile( CDVD_SourceType srctype )
|
||||
const wxString& CDVDsys_GetFile(CDVD_SourceType srctype)
|
||||
{
|
||||
return m_SourceFilename[enum_cast(srctype)];
|
||||
}
|
||||
|
@ -322,12 +326,12 @@ CDVD_SourceType CDVDsys_GetSourceType()
|
|||
return m_CurrentSourceType;
|
||||
}
|
||||
|
||||
void CDVDsys_ChangeSource( CDVD_SourceType type )
|
||||
void CDVDsys_ChangeSource(CDVD_SourceType type)
|
||||
{
|
||||
if(CDVD != NULL)
|
||||
if (CDVD != NULL)
|
||||
DoCDVDclose();
|
||||
|
||||
switch( m_CurrentSourceType = type )
|
||||
switch (m_CurrentSourceType = type)
|
||||
{
|
||||
case CDVD_SourceType::Iso:
|
||||
CDVD = &CDVDapi_Iso;
|
||||
|
@ -351,7 +355,7 @@ bool DoCDVDopen()
|
|||
|
||||
// the new disk callback is set on Init also, but just in case the plugin clears it for
|
||||
// some reason on close, we re-send here:
|
||||
CDVD->newDiskCB( cdvdNewDiskCB );
|
||||
CDVD->newDiskCB(cdvdNewDiskCB);
|
||||
|
||||
// Win32 Fail: the old CDVD api expects MBCS on Win32 platforms, but generating a MBCS
|
||||
// from unicode is problematic since we need to know the codepage of the text being
|
||||
|
@ -363,11 +367,12 @@ bool DoCDVDopen()
|
|||
//TODO_CDVD check if ISO and Disc use UTF8
|
||||
|
||||
auto CurrentSourceType = enum_cast(m_CurrentSourceType);
|
||||
int ret = CDVD->open( !m_SourceFilename[CurrentSourceType].IsEmpty() ?
|
||||
static_cast<const char*>(m_SourceFilename[CurrentSourceType].ToUTF8()) : (char*)NULL
|
||||
);
|
||||
int ret = CDVD->open(!m_SourceFilename[CurrentSourceType].IsEmpty() ?
|
||||
static_cast<const char*>(m_SourceFilename[CurrentSourceType].ToUTF8()) :
|
||||
(char*)NULL);
|
||||
|
||||
if( ret == -1 ) return false; // error! (handled by caller)
|
||||
if (ret == -1)
|
||||
return false; // error! (handled by caller)
|
||||
//if( ret == 1 ) throw Exception::CancelEvent(L"User canceled the CDVD plugin's open dialog."); <--- TODO_CDVD is this still needed?
|
||||
|
||||
int cdtype = DoCDVDdetectDiskType();
|
||||
|
@ -378,7 +383,7 @@ bool DoCDVDopen()
|
|||
return true;
|
||||
}
|
||||
|
||||
wxString somepick( Path::GetFilenameWithoutExt( m_SourceFilename[CurrentSourceType] ) );
|
||||
wxString somepick(Path::GetFilenameWithoutExt(m_SourceFilename[CurrentSourceType]));
|
||||
//FWIW Disc serial availability doesn't seem reliable enough, sometimes it's there and sometime it's just null
|
||||
//Shouldn't the serial be available all time? Potentially need to look into Elfreloadinfo() reliability
|
||||
//TODO: Add extra fallback case for CRC.
|
||||
|
@ -393,12 +398,11 @@ bool DoCDVDopen()
|
|||
wxString temp(Path::Combine(g_Conf->CurrentBlockdump, somepick));
|
||||
|
||||
#ifdef ENABLE_TIMESTAMPS
|
||||
wxDateTime curtime( wxDateTime::GetTimeNow() );
|
||||
wxDateTime curtime(wxDateTime::GetTimeNow());
|
||||
|
||||
temp += pxsFmt( L" (%04d-%02d-%02d %02d-%02d-%02d)",
|
||||
temp += pxsFmt(L" (%04d-%02d-%02d %02d-%02d-%02d)",
|
||||
curtime.GetYear(), curtime.GetMonth(), curtime.GetDay(),
|
||||
curtime.GetHour(), curtime.GetMinute(), curtime.GetSecond()
|
||||
);
|
||||
curtime.GetHour(), curtime.GetMinute(), curtime.GetSecond());
|
||||
#endif
|
||||
temp += L".dump";
|
||||
|
||||
|
@ -407,7 +411,7 @@ bool DoCDVDopen()
|
|||
|
||||
blockDumpFile.Create(temp, 2);
|
||||
|
||||
if( blockDumpFile.IsOpened() )
|
||||
if (blockDumpFile.IsOpened())
|
||||
{
|
||||
int blockofs = 0;
|
||||
uint blocksize = CD_FRAMESIZE_RAW;
|
||||
|
@ -416,7 +420,7 @@ bool DoCDVDopen()
|
|||
// hack: Because of limitations of the current cdvd design, we can't query the blocksize
|
||||
// of the underlying media. So lets make a best guess:
|
||||
|
||||
switch(cdtype)
|
||||
switch (cdtype)
|
||||
{
|
||||
case CDVD_TYPE_PS2DVD:
|
||||
case CDVD_TYPE_DVDV:
|
||||
|
@ -437,7 +441,7 @@ void DoCDVDclose()
|
|||
CheckNullCDVD();
|
||||
//blockDumpFile.Close();
|
||||
|
||||
if( CDVD->close != NULL )
|
||||
if (CDVD->close != NULL)
|
||||
CDVD->close();
|
||||
|
||||
DoCDVDresetDiskTypeCache();
|
||||
|
@ -446,7 +450,7 @@ void DoCDVDclose()
|
|||
s32 DoCDVDreadSector(u8* buffer, u32 lsn, int mode)
|
||||
{
|
||||
CheckNullCDVD();
|
||||
int ret = CDVD->readSector(buffer,lsn,mode);
|
||||
int ret = CDVD->readSector(buffer, lsn, mode);
|
||||
|
||||
if (ret == 0 && blockDumpFile.IsOpened())
|
||||
{
|
||||
|
@ -490,7 +494,7 @@ s32 DoCDVDreadTrack(u32 lsn, int mode)
|
|||
|
||||
//DevCon.Warning("CDVD readTrack(lsn=%d,mode=%d)",params lsn, lastReadSize);
|
||||
lastLSN = lsn;
|
||||
return CDVD->readTrack(lsn,mode);
|
||||
return CDVD->readTrack(lsn, mode);
|
||||
}
|
||||
|
||||
s32 DoCDVDgetBuffer(u8* buffer)
|
||||
|
@ -524,7 +528,8 @@ s32 DoCDVDgetBuffer(u8* buffer)
|
|||
s32 DoCDVDdetectDiskType()
|
||||
{
|
||||
CheckNullCDVD();
|
||||
if(diskTypeCached < 0) DetectDiskType();
|
||||
if (diskTypeCached < 0)
|
||||
DetectDiskType();
|
||||
return diskTypeCached;
|
||||
}
|
||||
|
||||
|
@ -563,12 +568,12 @@ s32 CALLBACK NODISCreadSubQ(u32 lsn, cdvdSubQ* subq)
|
|||
return -1;
|
||||
}
|
||||
|
||||
s32 CALLBACK NODISCgetTN(cdvdTN *Buffer)
|
||||
s32 CALLBACK NODISCgetTN(cdvdTN* Buffer)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
s32 CALLBACK NODISCgetTD(u8 Track, cdvdTD *Buffer)
|
||||
s32 CALLBACK NODISCgetTD(u8 Track, cdvdTD* Buffer)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
@ -593,7 +598,7 @@ s32 CALLBACK NODISCdummyS32()
|
|||
return 0;
|
||||
}
|
||||
|
||||
void CALLBACK NODISCnewDiskCB(void (* /* callback */)())
|
||||
void CALLBACK NODISCnewDiskCB(void (*/* callback */)())
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -608,7 +613,7 @@ s32 CALLBACK NODISCgetDualInfo(s32* dualType, u32* _layer1start)
|
|||
}
|
||||
|
||||
CDVD_API CDVDapi_NoDisc =
|
||||
{
|
||||
{
|
||||
NODISCclose,
|
||||
NODISCopen,
|
||||
NODISCreadTrack,
|
||||
|
|
|
@ -116,7 +116,7 @@ enum class CDVD_SourceType : uint8_t
|
|||
|
||||
struct CDVD_API
|
||||
{
|
||||
void (CALLBACK *close)();
|
||||
void(CALLBACK* close)();
|
||||
|
||||
// Don't need init or shutdown. iso/nodisc have no init/shutdown and plugin's
|
||||
// is handled by the PluginManager.
|
||||
|
@ -155,9 +155,9 @@ extern CDVD_API CDVDapi_NoDisc;
|
|||
|
||||
extern const wxChar* CDVD_SourceLabels[];
|
||||
|
||||
extern void CDVDsys_ChangeSource( CDVD_SourceType type );
|
||||
extern void CDVDsys_SetFile( CDVD_SourceType srctype, const wxString& newfile );
|
||||
extern const wxString& CDVDsys_GetFile( CDVD_SourceType srctype );
|
||||
extern void CDVDsys_ChangeSource(CDVD_SourceType type);
|
||||
extern void CDVDsys_SetFile(CDVD_SourceType srctype, const wxString& newfile);
|
||||
extern const wxString& CDVDsys_GetFile(CDVD_SourceType srctype);
|
||||
extern CDVD_SourceType CDVDsys_GetSourceType();
|
||||
|
||||
extern bool DoCDVDopen();
|
||||
|
@ -167,4 +167,3 @@ extern s32 DoCDVDreadTrack(u32 lsn, int mode);
|
|||
extern s32 DoCDVDgetBuffer(u8* buffer);
|
||||
extern s32 DoCDVDdetectDiskType();
|
||||
extern void DoCDVDresetDiskTypeCache();
|
||||
|
||||
|
|
|
@ -66,14 +66,16 @@ void cdvdParseTOC()
|
|||
{
|
||||
tracks[1].start_lba = 0;
|
||||
|
||||
if (!src->GetSectorCount()) {
|
||||
if (!src->GetSectorCount())
|
||||
{
|
||||
curDiskType = CDVD_TYPE_NODISC;
|
||||
strack = 1;
|
||||
etrack = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (src->GetMediaType() >= 0) {
|
||||
if (src->GetMediaType() >= 0)
|
||||
{
|
||||
tracks[1].type = CDVD_MODE1_TRACK;
|
||||
|
||||
strack = 1;
|
||||
|
@ -84,23 +86,28 @@ void cdvdParseTOC()
|
|||
strack = 0xFF;
|
||||
etrack = 0;
|
||||
|
||||
for (auto& entry : src->ReadTOC()) {
|
||||
for (auto& entry : src->ReadTOC())
|
||||
{
|
||||
if (entry.track < 1 || entry.track > 99)
|
||||
continue;
|
||||
strack = std::min(strack, entry.track);
|
||||
etrack = std::max(etrack, entry.track);
|
||||
tracks[entry.track].start_lba = entry.lba;
|
||||
if ((entry.control & 0x0C) == 0x04) {
|
||||
if ((entry.control & 0x0C) == 0x04)
|
||||
{
|
||||
std::array<u8, 2352> buffer;
|
||||
// Byte 15 of a raw CD data sector determines the track mode
|
||||
if (src->ReadSectors2352(entry.lba, 1, buffer.data()) && (buffer[15] & 3) == 2) {
|
||||
if (src->ReadSectors2352(entry.lba, 1, buffer.data()) && (buffer[15] & 3) == 2)
|
||||
{
|
||||
tracks[entry.track].type = CDVD_MODE2_TRACK;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
tracks[entry.track].type = CDVD_MODE1_TRACK;
|
||||
}
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
tracks[entry.track].type = CDVD_AUDIO_TRACK;
|
||||
}
|
||||
fprintf(stderr, "Track %u start sector: %u\n", entry.track, entry.lba);
|
||||
|
@ -119,8 +126,8 @@ std::unique_ptr<IOCtlSrc> src;
|
|||
|
||||
extern u32 g_last_sector_block_lsn;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// keepAliveThread throws a read event regularly to prevent drive spin down //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// keepAliveThread throws a read event regularly to prevent drive spin down //
|
||||
|
||||
void keepAliveThread()
|
||||
{
|
||||
|
@ -130,7 +137,8 @@ void keepAliveThread()
|
|||
std::unique_lock<std::mutex> guard(s_keepalive_lock);
|
||||
|
||||
while (!s_keepalive_cv.wait_for(guard, std::chrono::seconds(30),
|
||||
[]() { return !s_keepalive_is_open; })) {
|
||||
[]() { return !s_keepalive_is_open; }))
|
||||
{
|
||||
|
||||
//printf(" * keepAliveThread: polling drive.\n");
|
||||
if (src->GetMediaType() >= 0)
|
||||
|
@ -147,10 +155,12 @@ bool StartKeepAliveThread()
|
|||
if (s_keepalive_is_open == false)
|
||||
{
|
||||
s_keepalive_is_open = true;
|
||||
try {
|
||||
try
|
||||
{
|
||||
s_keepalive_thread = std::thread(keepAliveThread);
|
||||
}
|
||||
catch (std::system_error&) {
|
||||
catch (std::system_error&)
|
||||
{
|
||||
s_keepalive_is_open = false;
|
||||
}
|
||||
}
|
||||
|
@ -181,16 +191,19 @@ s32 CALLBACK DISCopen(const char* pTitle)
|
|||
GetValidDrive(drive);
|
||||
|
||||
// open device file
|
||||
try {
|
||||
try
|
||||
{
|
||||
src = std::unique_ptr<IOCtlSrc>(new IOCtlSrc(drive));
|
||||
}
|
||||
catch (std::runtime_error& ex) {
|
||||
catch (std::runtime_error& ex)
|
||||
{
|
||||
fputs(ex.what(), stdout);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//setup threading manager
|
||||
if (!cdvdStartThread()) {
|
||||
if (!cdvdStartThread())
|
||||
{
|
||||
src.reset();
|
||||
return -1;
|
||||
}
|
||||
|
@ -212,7 +225,8 @@ s32 CALLBACK DISCreadTrack(u32 lsn, int mode)
|
|||
csector = lsn;
|
||||
cmode = mode;
|
||||
|
||||
if (weAreInNewDiskCB) {
|
||||
if (weAreInNewDiskCB)
|
||||
{
|
||||
int ret = cdvdDirectReadSector(lsn, mode, directReadSectorBuffer);
|
||||
if (ret == 0)
|
||||
lastReadInNewDiskCB = 1;
|
||||
|
@ -234,7 +248,8 @@ s32 CALLBACK DISCgetBuffer(u8* dest)
|
|||
return 0;
|
||||
|
||||
int csize = 2352;
|
||||
switch (cmode) {
|
||||
switch (cmode)
|
||||
{
|
||||
case CDVD_MODE_2048:
|
||||
csize = 2048;
|
||||
break;
|
||||
|
@ -246,7 +261,8 @@ s32 CALLBACK DISCgetBuffer(u8* dest)
|
|||
break;
|
||||
}
|
||||
|
||||
if (lastReadInNewDiskCB) {
|
||||
if (lastReadInNewDiskCB)
|
||||
{
|
||||
lastReadInNewDiskCB = 0;
|
||||
|
||||
memcpy(dest, directReadSectorBuffer, csize);
|
||||
|
@ -294,7 +310,8 @@ s32 CALLBACK DISCgetTN(cdvdTN* Buffer)
|
|||
|
||||
s32 CALLBACK DISCgetTD(u8 Track, cdvdTD* Buffer)
|
||||
{
|
||||
if (Track == 0) {
|
||||
if (Track == 0)
|
||||
{
|
||||
Buffer->lsn = src->GetSectorCount();
|
||||
Buffer->type = 0;
|
||||
return 0;
|
||||
|
@ -316,7 +333,8 @@ s32 CALLBACK DISCgetTOC(void* toc)
|
|||
if (curDiskType == CDVD_TYPE_NODISC)
|
||||
return -1;
|
||||
|
||||
if (curDiskType == CDVD_TYPE_DETCTDVDS || curDiskType == CDVD_TYPE_DETCTDVDD) {
|
||||
if (curDiskType == CDVD_TYPE_DETCTDVDS || curDiskType == CDVD_TYPE_DETCTDVDD)
|
||||
{
|
||||
memset(tocBuff, 0, 2048);
|
||||
|
||||
s32 mt = src->GetMediaType();
|
||||
|
@ -324,7 +342,8 @@ s32 CALLBACK DISCgetTOC(void* toc)
|
|||
if (mt < 0)
|
||||
return -1;
|
||||
|
||||
if (mt == 0) { //single layer
|
||||
if (mt == 0)
|
||||
{ //single layer
|
||||
// fake it
|
||||
tocBuff[0] = 0x04;
|
||||
tocBuff[1] = 0x02;
|
||||
|
@ -338,7 +357,8 @@ s32 CALLBACK DISCgetTOC(void* toc)
|
|||
tocBuff[18] = 0x00;
|
||||
tocBuff[19] = 0x00;
|
||||
}
|
||||
else if (mt == 1) { //PTP
|
||||
else if (mt == 1)
|
||||
{ //PTP
|
||||
u32 layer1start = src->GetLayerBreakAddress() + 0x30000;
|
||||
|
||||
// dual sided
|
||||
|
@ -361,7 +381,8 @@ s32 CALLBACK DISCgetTOC(void* toc)
|
|||
tocBuff[22] = (layer1start >> 8) & 0xff;
|
||||
tocBuff[23] = (layer1start >> 0) & 0xff;
|
||||
}
|
||||
else { //OTP
|
||||
else
|
||||
{ //OTP
|
||||
u32 layer1start = src->GetLayerBreakAddress() + 0x30000;
|
||||
|
||||
// dual sided
|
||||
|
@ -385,7 +406,8 @@ s32 CALLBACK DISCgetTOC(void* toc)
|
|||
tocBuff[27] = (layer1start >> 0) & 0xff;
|
||||
}
|
||||
}
|
||||
else if (curDiskType == CDVD_TYPE_DETCTCD) {
|
||||
else if (curDiskType == CDVD_TYPE_DETCTCD)
|
||||
{
|
||||
// cd toc
|
||||
// (could be replaced by 1 command that reads the full toc)
|
||||
u8 min, sec, frm, i;
|
||||
|
@ -393,7 +415,8 @@ s32 CALLBACK DISCgetTOC(void* toc)
|
|||
cdvdTN diskInfo;
|
||||
cdvdTD trackInfo;
|
||||
memset(tocBuff, 0, 1024);
|
||||
if (DISCgetTN(&diskInfo) == -1) {
|
||||
if (DISCgetTN(&diskInfo) == -1)
|
||||
{
|
||||
diskInfo.etrack = 0;
|
||||
diskInfo.strack = 1;
|
||||
}
|
||||
|
@ -420,7 +443,8 @@ s32 CALLBACK DISCgetTOC(void* toc)
|
|||
|
||||
fprintf(stderr, "Track 0: %u mins %u secs %u frames\n", min, sec, frm);
|
||||
|
||||
for (i = diskInfo.strack; i <= diskInfo.etrack; i++) {
|
||||
for (i = diskInfo.strack; i <= diskInfo.etrack; i++)
|
||||
{
|
||||
err = DISCgetTD(i, &trackInfo);
|
||||
lba_to_msf(trackInfo.lsn, &min, &sec, &frm);
|
||||
tocBuff[i * 10 + 30] = trackInfo.type;
|
||||
|
@ -471,7 +495,8 @@ s32 CALLBACK DISCreadSector(u8* buffer, u32 lsn, int mode)
|
|||
|
||||
s32 CALLBACK DISCgetDualInfo(s32* dualType, u32* _layer1start)
|
||||
{
|
||||
switch (src->GetMediaType()) {
|
||||
switch (src->GetMediaType())
|
||||
{
|
||||
case 1:
|
||||
*dualType = 1;
|
||||
*_layer1start = src->GetLayerBreakAddress() + 1;
|
||||
|
@ -489,7 +514,7 @@ s32 CALLBACK DISCgetDualInfo(s32* dualType, u32* _layer1start)
|
|||
}
|
||||
|
||||
CDVD_API CDVDapi_Disc =
|
||||
{
|
||||
{
|
||||
DISCclose,
|
||||
DISCopen,
|
||||
DISCreadTrack,
|
||||
|
|
|
@ -59,7 +59,8 @@ u32 cdvdSectorHash(u32 lsn)
|
|||
int i = 32;
|
||||
u32 m = CacheSize - 1;
|
||||
|
||||
while (i >= 0) {
|
||||
while (i >= 0)
|
||||
{
|
||||
t ^= lsn & m;
|
||||
lsn >>= CACHE_SIZE;
|
||||
i -= CACHE_SIZE;
|
||||
|
@ -90,7 +91,8 @@ bool cdvdCacheFetch(u32 lsn, u8* data)
|
|||
std::lock_guard<std::mutex> guard(s_cache_lock);
|
||||
u32 entry = cdvdSectorHash(lsn);
|
||||
|
||||
if (Cache[entry].lsn == lsn) {
|
||||
if (Cache[entry].lsn == lsn)
|
||||
{
|
||||
memcpy(data, Cache[entry].data, 2352 * sectors_per_read);
|
||||
return true;
|
||||
}
|
||||
|
@ -101,7 +103,8 @@ bool cdvdCacheFetch(u32 lsn, u8* data)
|
|||
void cdvdCacheReset()
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(s_cache_lock);
|
||||
for (u32 i = 0; i < CacheSize; i++) {
|
||||
for (u32 i = 0; i < CacheSize; i++)
|
||||
{
|
||||
Cache[i].lsn = std::numeric_limits<u32>::max();
|
||||
}
|
||||
}
|
||||
|
@ -113,12 +116,15 @@ bool cdvdReadBlockOfSectors(u32 sector, u8* data)
|
|||
|
||||
// TODO: Is it really necessary to retry if it fails? I'm not sure the
|
||||
// second time is really going to be any better.
|
||||
for (int tries = 0; tries < 2; ++tries) {
|
||||
if (media >= 0) {
|
||||
for (int tries = 0; tries < 2; ++tries)
|
||||
{
|
||||
if (media >= 0)
|
||||
{
|
||||
if (src->ReadSectors2048(sector, count, data))
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
if (src->ReadSectors2352(sector, count, data))
|
||||
return true;
|
||||
}
|
||||
|
@ -137,16 +143,20 @@ bool cdvdUpdateDiscStatus()
|
|||
{
|
||||
bool ready = src->DiscReady();
|
||||
|
||||
if (!ready) {
|
||||
if (!disc_has_changed) {
|
||||
if (!ready)
|
||||
{
|
||||
if (!disc_has_changed)
|
||||
{
|
||||
disc_has_changed = true;
|
||||
curDiskType = CDVD_TYPE_NODISC;
|
||||
curTrayStatus = CDVD_TRAY_OPEN;
|
||||
cdvdCallNewDiscCB();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (disc_has_changed) {
|
||||
else
|
||||
{
|
||||
if (disc_has_changed)
|
||||
{
|
||||
curDiskType = CDVD_TYPE_NODISC;
|
||||
curTrayStatus = CDVD_TRAY_CLOSE;
|
||||
|
||||
|
@ -172,8 +182,10 @@ void cdvdThread()
|
|||
printf(" * CDVD: IO thread started...\n");
|
||||
std::unique_lock<std::mutex> guard(s_notify_lock);
|
||||
|
||||
while (cdvd_is_open) {
|
||||
if (cdvdUpdateDiscStatus()) {
|
||||
while (cdvd_is_open)
|
||||
{
|
||||
if (cdvdUpdateDiscStatus())
|
||||
{
|
||||
// Need to sleep some to avoid an aggressive spin that sucks the cpu dry.
|
||||
s_notify_cv.wait_for(guard, std::chrono::milliseconds(10));
|
||||
prefetches_left = 0;
|
||||
|
@ -193,14 +205,16 @@ void cdvdThread()
|
|||
|
||||
{
|
||||
std::lock_guard<std::mutex> request_guard(s_request_lock);
|
||||
if (!s_request_queue.empty()) {
|
||||
if (!s_request_queue.empty())
|
||||
{
|
||||
request_lsn = s_request_queue.front();
|
||||
s_request_queue.pop();
|
||||
handling_request = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!handling_request) {
|
||||
if (!handling_request)
|
||||
{
|
||||
if (prefetches_left == 0)
|
||||
continue;
|
||||
|
||||
|
@ -211,11 +225,14 @@ void cdvdThread()
|
|||
}
|
||||
|
||||
// Handle request
|
||||
if (!cdvdCacheCheck(request_lsn)) {
|
||||
if (cdvdReadBlockOfSectors(request_lsn, buffer)) {
|
||||
if (!cdvdCacheCheck(request_lsn))
|
||||
{
|
||||
if (cdvdReadBlockOfSectors(request_lsn, buffer))
|
||||
{
|
||||
cdvdCacheUpdate(request_lsn, buffer);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
// If the read fails, further reads are likely to fail too.
|
||||
prefetches_left = 0;
|
||||
continue;
|
||||
|
@ -229,10 +246,12 @@ void cdvdThread()
|
|||
|
||||
// Prefetch
|
||||
u32 next_prefetch_lsn = g_last_sector_block_lsn + sectors_per_read;
|
||||
if (next_prefetch_lsn >= src->GetSectorCount()) {
|
||||
if (next_prefetch_lsn >= src->GetSectorCount())
|
||||
{
|
||||
prefetches_left = 0;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
const u32 max_prefetches = 16;
|
||||
u32 remaining = src->GetSectorCount() - next_prefetch_lsn;
|
||||
prefetches_left = std::min((remaining + sectors_per_read - 1) / sectors_per_read, max_prefetches);
|
||||
|
@ -246,9 +265,12 @@ bool cdvdStartThread()
|
|||
if (cdvd_is_open == false)
|
||||
{
|
||||
cdvd_is_open = true;
|
||||
try {
|
||||
try
|
||||
{
|
||||
s_thread = std::thread(cdvdThread);
|
||||
} catch (std::system_error &) {
|
||||
}
|
||||
catch (std::system_error&)
|
||||
{
|
||||
cdvd_is_open = false;
|
||||
return false;
|
||||
}
|
||||
|
@ -263,7 +285,7 @@ void cdvdStopThread()
|
|||
{
|
||||
cdvd_is_open = false;
|
||||
s_notify_cv.notify_one();
|
||||
if(s_thread.joinable())
|
||||
if (s_thread.joinable())
|
||||
s_thread.join();
|
||||
}
|
||||
|
||||
|
@ -297,7 +319,8 @@ u8* cdvdGetSector(u32 sector, s32 mode)
|
|||
if (cdvdReadBlockOfSectors(sector_block, buffer))
|
||||
cdvdCacheUpdate(sector_block, buffer);
|
||||
|
||||
if (src->GetMediaType() >= 0) {
|
||||
if (src->GetMediaType() >= 0)
|
||||
{
|
||||
u32 offset = 2048 * (sector - sector_block);
|
||||
return buffer + offset;
|
||||
}
|
||||
|
@ -305,7 +328,8 @@ u8* cdvdGetSector(u32 sector, s32 mode)
|
|||
u32 offset = 2352 * (sector - sector_block);
|
||||
u8* data = buffer + offset;
|
||||
|
||||
switch (mode) {
|
||||
switch (mode)
|
||||
{
|
||||
case CDVD_MODE_2048:
|
||||
// Data location depends on CD mode
|
||||
return (data[15] & 3) == 2 ? data + 24 : data + 16;
|
||||
|
@ -321,26 +345,30 @@ s32 cdvdDirectReadSector(u32 sector, s32 mode, u8* buffer)
|
|||
{
|
||||
static u8 data[2352 * sectors_per_read];
|
||||
|
||||
if(src == nullptr)
|
||||
if (src == nullptr)
|
||||
return -1;
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
if (sector >= src->GetSectorCount())
|
||||
return -1;
|
||||
}
|
||||
catch(...) {
|
||||
catch (...)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Align to cache block
|
||||
u32 sector_block = sector & ~(sectors_per_read - 1);
|
||||
|
||||
if (!cdvdCacheFetch(sector_block, data)) {
|
||||
if (!cdvdCacheFetch(sector_block, data))
|
||||
{
|
||||
if (cdvdReadBlockOfSectors(sector_block, data))
|
||||
cdvdCacheUpdate(sector_block, data);
|
||||
}
|
||||
|
||||
if (src->GetMediaType() >= 0) {
|
||||
if (src->GetMediaType() >= 0)
|
||||
{
|
||||
u32 offset = 2048 * (sector - sector_block);
|
||||
memcpy(buffer, data + offset, 2048);
|
||||
return 0;
|
||||
|
@ -349,7 +377,8 @@ s32 cdvdDirectReadSector(u32 sector, s32 mode, u8* buffer)
|
|||
u32 offset = 2352 * (sector - sector_block);
|
||||
u8* bfr = data + offset;
|
||||
|
||||
switch (mode) {
|
||||
switch (mode)
|
||||
{
|
||||
case CDVD_MODE_2048:
|
||||
// Data location depends on CD mode
|
||||
std::memcpy(buffer, (bfr[15] & 3) == 2 ? bfr + 24 : bfr + 16, 2048);
|
||||
|
@ -378,10 +407,12 @@ s32 cdvdRefreshData()
|
|||
//read TOC from device
|
||||
cdvdParseTOC();
|
||||
|
||||
if ((etrack == 0) || (strack > etrack)) {
|
||||
if ((etrack == 0) || (strack > etrack))
|
||||
{
|
||||
curDiskType = CDVD_TYPE_NODISC;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
s32 mt = cdvdGetMediaType();
|
||||
|
||||
if (mt < 0)
|
||||
|
@ -394,7 +425,8 @@ s32 cdvdRefreshData()
|
|||
|
||||
curTrayStatus = CDVD_TRAY_CLOSE;
|
||||
|
||||
switch (curDiskType) {
|
||||
switch (curDiskType)
|
||||
{
|
||||
case CDVD_TYPE_DETCTDVDD:
|
||||
diskTypeName = "Double-Layer DVD";
|
||||
break;
|
||||
|
|
|
@ -44,21 +44,22 @@ s32 CALLBACK ISOopen(const char* pTitle)
|
|||
{
|
||||
ISOclose(); // just in case
|
||||
|
||||
if( (pTitle == NULL) || (pTitle[0] == 0) )
|
||||
if ((pTitle == NULL) || (pTitle[0] == 0))
|
||||
{
|
||||
Console.Error( "CDVDiso Error: No filename specified." );
|
||||
Console.Error("CDVDiso Error: No filename specified.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// The current plugin API doesn't expect exceptions to propagate out of the API
|
||||
// calls, so we need to catch them, log them, and return -1.
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
iso.Open(fromUTF8(pTitle));
|
||||
}
|
||||
catch( BaseException& ex )
|
||||
catch (BaseException& ex)
|
||||
{
|
||||
Console.Error( ex.FormatDiagnosticMessage() );
|
||||
Console.Error(ex.FormatDiagnosticMessage());
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -97,7 +98,7 @@ s32 CALLBACK ISOreadSubQ(u32 lsn, cdvdSubQ* subq)
|
|||
|
||||
subq->pad = 0;
|
||||
|
||||
lba_to_msf(lsn + (2*75), &min, &sec, &frm);
|
||||
lba_to_msf(lsn + (2 * 75), &min, &sec, &frm);
|
||||
subq->discM = itob(min);
|
||||
subq->discS = itob(sec);
|
||||
subq->discF = itob(frm);
|
||||
|
@ -105,7 +106,7 @@ s32 CALLBACK ISOreadSubQ(u32 lsn, cdvdSubQ* subq)
|
|||
return 0;
|
||||
}
|
||||
|
||||
s32 CALLBACK ISOgetTN(cdvdTN *Buffer)
|
||||
s32 CALLBACK ISOgetTN(cdvdTN* Buffer)
|
||||
{
|
||||
Buffer->strack = 1;
|
||||
Buffer->etrack = 1;
|
||||
|
@ -113,7 +114,7 @@ s32 CALLBACK ISOgetTN(cdvdTN *Buffer)
|
|||
return 0;
|
||||
}
|
||||
|
||||
s32 CALLBACK ISOgetTD(u8 Track, cdvdTD *Buffer)
|
||||
s32 CALLBACK ISOgetTD(u8 Track, cdvdTD* Buffer)
|
||||
{
|
||||
if (Track == 0)
|
||||
{
|
||||
|
@ -155,10 +156,7 @@ static void FindLayer1Start()
|
|||
// The volume space size (sector count) is located at bytes 80-87 - 80-83
|
||||
// is the little endian size, 84-87 is the big endian size.
|
||||
const int offset = iso.GetBlockOffset();
|
||||
uint blockresult = buffer[offset + 80]
|
||||
+ (buffer[offset + 81] << 8)
|
||||
+ (buffer[offset + 82] << 16)
|
||||
+ (buffer[offset + 83] << 24);
|
||||
uint blockresult = buffer[offset + 80] + (buffer[offset + 81] << 8) + (buffer[offset + 82] << 16) + (buffer[offset + 83] << 24);
|
||||
|
||||
// If the ISO sector count is larger than the volume size, then we should
|
||||
// have a dual layer DVD. Layer 1 is on a different volume.
|
||||
|
@ -220,12 +218,12 @@ s32 CALLBACK ISOgetTOC(void* toc)
|
|||
if (layer1start < 0)
|
||||
{
|
||||
// fake it
|
||||
tocBuff[ 0] = 0x04;
|
||||
tocBuff[ 1] = 0x02;
|
||||
tocBuff[ 2] = 0xF2;
|
||||
tocBuff[ 3] = 0x00;
|
||||
tocBuff[ 4] = 0x86;
|
||||
tocBuff[ 5] = 0x72;
|
||||
tocBuff[0] = 0x04;
|
||||
tocBuff[1] = 0x02;
|
||||
tocBuff[2] = 0xF2;
|
||||
tocBuff[3] = 0x00;
|
||||
tocBuff[4] = 0x86;
|
||||
tocBuff[5] = 0x72;
|
||||
|
||||
tocBuff[16] = 0x00;
|
||||
tocBuff[17] = 0x03;
|
||||
|
@ -236,12 +234,12 @@ s32 CALLBACK ISOgetTOC(void* toc)
|
|||
else
|
||||
{
|
||||
// dual sided
|
||||
tocBuff[ 0] = 0x24;
|
||||
tocBuff[ 1] = 0x02;
|
||||
tocBuff[ 2] = 0xF2;
|
||||
tocBuff[ 3] = 0x00;
|
||||
tocBuff[ 4] = 0x41;
|
||||
tocBuff[ 5] = 0x95;
|
||||
tocBuff[0] = 0x24;
|
||||
tocBuff[1] = 0x02;
|
||||
tocBuff[2] = 0xF2;
|
||||
tocBuff[3] = 0x00;
|
||||
tocBuff[4] = 0x41;
|
||||
tocBuff[5] = 0x95;
|
||||
|
||||
tocBuff[14] = 0x60; // dual sided, ptp
|
||||
|
||||
|
@ -272,7 +270,8 @@ s32 CALLBACK ISOgetTOC(void* toc)
|
|||
diskInfo.etrack = 0;
|
||||
diskInfo.strack = 1;
|
||||
}
|
||||
if (ISOgetTD(0, &trackInfo) == -1) trackInfo.lsn = 0;
|
||||
if (ISOgetTD(0, &trackInfo) == -1)
|
||||
trackInfo.lsn = 0;
|
||||
|
||||
tocBuff[0] = 0x41;
|
||||
tocBuff[1] = 0x00;
|
||||
|
@ -295,11 +294,11 @@ s32 CALLBACK ISOgetTOC(void* toc)
|
|||
{
|
||||
err = ISOgetTD(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);
|
||||
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
|
||||
|
@ -314,10 +313,12 @@ s32 CALLBACK ISOreadSector(u8* tempbuffer, u32 lsn, int mode)
|
|||
|
||||
int _lsn = lsn;
|
||||
|
||||
if (_lsn < 0) lsn = iso.GetBlockCount() + _lsn;
|
||||
if (lsn >= iso.GetBlockCount()) return -1;
|
||||
if (_lsn < 0)
|
||||
lsn = iso.GetBlockCount() + _lsn;
|
||||
if (lsn >= iso.GetBlockCount())
|
||||
return -1;
|
||||
|
||||
if(mode == CDVD_MODE_2352)
|
||||
if (mode == CDVD_MODE_2352)
|
||||
{
|
||||
iso.ReadSync(tempbuffer, lsn);
|
||||
return 0;
|
||||
|
@ -326,7 +327,7 @@ s32 CALLBACK ISOreadSector(u8* tempbuffer, u32 lsn, int mode)
|
|||
iso.ReadSync(cdbuffer, lsn);
|
||||
|
||||
|
||||
u8 *pbuffer = cdbuffer;
|
||||
u8* pbuffer = cdbuffer;
|
||||
int psize = 0;
|
||||
|
||||
switch (mode)
|
||||
|
@ -361,7 +362,8 @@ s32 CALLBACK ISOreadTrack(u32 lsn, int mode)
|
|||
{
|
||||
int _lsn = lsn;
|
||||
|
||||
if (_lsn < 0) lsn = iso.GetBlockCount() + _lsn;
|
||||
if (_lsn < 0)
|
||||
lsn = iso.GetBlockCount() + _lsn;
|
||||
|
||||
iso.BeginRead2(lsn);
|
||||
|
||||
|
@ -400,12 +402,12 @@ s32 CALLBACK ISOdummyS32()
|
|||
return 0;
|
||||
}
|
||||
|
||||
void CALLBACK ISOnewDiskCB(void(* /* callback */)())
|
||||
void CALLBACK ISOnewDiskCB(void (*/* callback */)())
|
||||
{
|
||||
}
|
||||
|
||||
CDVD_API CDVDapi_Iso =
|
||||
{
|
||||
{
|
||||
ISOclose,
|
||||
|
||||
ISOopen,
|
||||
|
|
|
@ -59,10 +59,10 @@ enum cdrom_registers
|
|||
REPPLAY_ACK = 252,
|
||||
REPPLAY = 253,
|
||||
ASYNC = 254
|
||||
/* don't set 255, it's reserved */
|
||||
/* don't set 255, it's reserved */
|
||||
};
|
||||
|
||||
const char *CmdName[0x100]= {
|
||||
const char* CmdName[0x100] = {
|
||||
"CdlSync", "CdlNop", "CdlSetloc", "CdlPlay",
|
||||
"CdlForward", "CdlBackward", "CdlReadN", "CdlStandby",
|
||||
"CdlStop", "CdlPause", "CdlInit", "CdlMute",
|
||||
|
@ -70,17 +70,16 @@ const char *CmdName[0x100]= {
|
|||
"CdlGetlocL", "CdlGetlocP", "Cdl18", "CdlGetTN",
|
||||
"CdlGetTD", "CdlSeekL", "CdlSeekP", NULL,
|
||||
NULL, "CdlTest", "CdlID", "CdlReadS",
|
||||
"CdlReset", NULL, "CDlReadToc", NULL
|
||||
};
|
||||
"CdlReset", NULL, "CDlReadToc", NULL};
|
||||
|
||||
cdrStruct cdr;
|
||||
s32 LoadCdBios;
|
||||
|
||||
u8 Test04[] = { 0 };
|
||||
u8 Test05[] = { 0 };
|
||||
u8 Test20[] = { 0x98, 0x06, 0x10, 0xC3 };
|
||||
u8 Test22[] = { 0x66, 0x6F, 0x72, 0x20, 0x45, 0x75, 0x72, 0x6F };
|
||||
u8 Test23[] = { 0x43, 0x58, 0x44, 0x32, 0x39 ,0x34, 0x30, 0x51 };
|
||||
u8 Test04[] = {0};
|
||||
u8 Test05[] = {0};
|
||||
u8 Test20[] = {0x98, 0x06, 0x10, 0xC3};
|
||||
u8 Test22[] = {0x66, 0x6F, 0x72, 0x20, 0x45, 0x75, 0x72, 0x6F};
|
||||
u8 Test23[] = {0x43, 0x58, 0x44, 0x32, 0x39, 0x34, 0x30, 0x51};
|
||||
|
||||
//backported from PCSXR
|
||||
// cdr.Stat:
|
||||
|
@ -92,30 +91,30 @@ u8 Test23[] = { 0x43, 0x58, 0x44, 0x32, 0x39 ,0x34, 0x30, 0x51 };
|
|||
#define DiskError 5
|
||||
|
||||
/* Modes flags */
|
||||
#define MODE_SPEED (1<<7) // 0x80
|
||||
#define MODE_STRSND (1<<6) // 0x40 ADPCM on/off
|
||||
#define MODE_SIZE_2340 (1<<5) // 0x20
|
||||
#define MODE_SIZE_2328 (1<<4) // 0x10
|
||||
#define MODE_SIZE_2048 (0<<4) // 0x00
|
||||
#define MODE_SF (1<<3) // 0x08 channel on/off
|
||||
#define MODE_REPORT (1<<2) // 0x04
|
||||
#define MODE_AUTOPAUSE (1<<1) // 0x02
|
||||
#define MODE_CDDA (1<<0) // 0x01
|
||||
#define MODE_SPEED (1 << 7) // 0x80
|
||||
#define MODE_STRSND (1 << 6) // 0x40 ADPCM on/off
|
||||
#define MODE_SIZE_2340 (1 << 5) // 0x20
|
||||
#define MODE_SIZE_2328 (1 << 4) // 0x10
|
||||
#define MODE_SIZE_2048 (0 << 4) // 0x00
|
||||
#define MODE_SF (1 << 3) // 0x08 channel on/off
|
||||
#define MODE_REPORT (1 << 2) // 0x04
|
||||
#define MODE_AUTOPAUSE (1 << 1) // 0x02
|
||||
#define MODE_CDDA (1 << 0) // 0x01
|
||||
|
||||
/* Status flags, to go on cdr.StatP */
|
||||
#define STATUS_PLAY (1<<7) // 0x80
|
||||
#define STATUS_SEEK (1<<6) // 0x40
|
||||
#define STATUS_READ (1<<5) // 0x20
|
||||
#define STATUS_SHELLOPEN (1<<4) // 0x10
|
||||
#define STATUS_UNKNOWN3 (1<<3) // 0x08
|
||||
#define STATUS_UNKNOWN2 (1<<2) // 0x04
|
||||
#define STATUS_ROTATING (1<<1) // 0x02
|
||||
#define STATUS_ERROR (1<<0) // 0x01
|
||||
#define STATUS_PLAY (1 << 7) // 0x80
|
||||
#define STATUS_SEEK (1 << 6) // 0x40
|
||||
#define STATUS_READ (1 << 5) // 0x20
|
||||
#define STATUS_SHELLOPEN (1 << 4) // 0x10
|
||||
#define STATUS_UNKNOWN3 (1 << 3) // 0x08
|
||||
#define STATUS_UNKNOWN2 (1 << 2) // 0x04
|
||||
#define STATUS_ROTATING (1 << 1) // 0x02
|
||||
#define STATUS_ERROR (1 << 0) // 0x01
|
||||
|
||||
/* Errors */
|
||||
#define ERROR_NOTREADY (1<<7) // 0x80
|
||||
#define ERROR_INVALIDCMD (1<<6) // 0x40
|
||||
#define ERROR_INVALIDARG (1<<5) // 0x20
|
||||
#define ERROR_NOTREADY (1 << 7) // 0x80
|
||||
#define ERROR_INVALIDCMD (1 << 6) // 0x40
|
||||
#define ERROR_INVALIDARG (1 << 5) // 0x20
|
||||
|
||||
// 1x = 75 sectors per second
|
||||
// PSXCLK = 1 sec in the ps
|
||||
|
@ -130,7 +129,8 @@ uint sectorSeekReadDelay = 0x800; // for calculated seek delays
|
|||
|
||||
static void AddIrqQueue(u8 irq, u32 ecycle);
|
||||
|
||||
static __fi void StartReading(u32 type) {
|
||||
static __fi void StartReading(u32 type)
|
||||
{
|
||||
cdr.Reading = type;
|
||||
cdr.FirstSector = 1;
|
||||
cdr.Readed = 0xff;
|
||||
|
@ -139,27 +139,33 @@ static __fi void StartReading(u32 type) {
|
|||
sectorSeekReadDelay = shortSectorSeekReadDelay;
|
||||
}
|
||||
|
||||
static __fi void StopReading() {
|
||||
if (cdr.Reading) {
|
||||
static __fi void StopReading()
|
||||
{
|
||||
if (cdr.Reading)
|
||||
{
|
||||
cdr.Reading = 0;
|
||||
psxRegs.interrupt &= ~(1<<IopEvt_CdromRead);
|
||||
psxRegs.interrupt &= ~(1 << IopEvt_CdromRead);
|
||||
}
|
||||
}
|
||||
|
||||
static __fi void StopCdda() {
|
||||
if (cdr.Play) {
|
||||
static __fi void StopCdda()
|
||||
{
|
||||
if (cdr.Play)
|
||||
{
|
||||
cdr.StatP &= ~STATUS_PLAY;
|
||||
cdr.Play = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static __fi void SetResultSize(u8 size) {
|
||||
static __fi void SetResultSize(u8 size)
|
||||
{
|
||||
cdr.ResultP = 0;
|
||||
cdr.ResultC = size;
|
||||
cdr.ResultReady = 1;
|
||||
}
|
||||
|
||||
static void ReadTrack() {
|
||||
static void ReadTrack()
|
||||
{
|
||||
cdr.Prev[0] = itob(cdr.SetSector[0]);
|
||||
cdr.Prev[1] = itob(cdr.SetSector[1]);
|
||||
cdr.Prev[2] = itob(cdr.SetSector[2]);
|
||||
|
@ -170,29 +176,36 @@ static void ReadTrack() {
|
|||
cdr.RErr = DoCDVDreadTrack(msf_to_lsn(cdr.SetSector), CDVD_MODE_2340);
|
||||
}
|
||||
|
||||
static void AddIrqQueue(u8 irq, u32 ecycle) {
|
||||
static void AddIrqQueue(u8 irq, u32 ecycle)
|
||||
{
|
||||
cdr.Irq = irq;
|
||||
if (cdr.Stat) {
|
||||
if (cdr.Stat)
|
||||
{
|
||||
cdr.eCycle = ecycle;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
CDR_INT(ecycle);
|
||||
}
|
||||
}
|
||||
|
||||
void cdrInterrupt() {
|
||||
void cdrInterrupt()
|
||||
{
|
||||
cdvdTD trackInfo;
|
||||
int i;
|
||||
u8 Irq = cdr.Irq;
|
||||
|
||||
if (cdr.Stat) {
|
||||
if (cdr.Stat)
|
||||
{
|
||||
CDR_INT(0x800);
|
||||
return;
|
||||
}
|
||||
|
||||
cdr.Irq = 0xff;
|
||||
cdr.Ctrl&=~0x80;
|
||||
cdr.Ctrl &= ~0x80;
|
||||
|
||||
switch (Irq) {
|
||||
switch (Irq)
|
||||
{
|
||||
case CdlSync:
|
||||
SetResultSize(1);
|
||||
cdr.StatP |= STATUS_ROTATING;
|
||||
|
@ -327,7 +340,7 @@ void cdrInterrupt() {
|
|||
|
||||
case CdlGetlocL:
|
||||
SetResultSize(8);
|
||||
for (i=0; i<8; i++)
|
||||
for (i = 0; i < 8; i++)
|
||||
cdr.Result[i] = cdr.Transfer[i];
|
||||
cdr.Stat = Acknowledge;
|
||||
break;
|
||||
|
@ -350,10 +363,13 @@ void cdrInterrupt() {
|
|||
SetResultSize(3);
|
||||
cdr.StatP |= STATUS_ROTATING;
|
||||
cdr.Result[0] = cdr.StatP;
|
||||
if (CDVD->getTN(&cdr.ResultTN) == -1) {
|
||||
if (CDVD->getTN(&cdr.ResultTN) == -1)
|
||||
{
|
||||
cdr.Stat = DiskError;
|
||||
cdr.Result[0]|= 0x01;
|
||||
} else {
|
||||
cdr.Result[0] |= 0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
cdr.Stat = Acknowledge;
|
||||
cdr.Result[1] = itob(cdr.ResultTN.strack);
|
||||
cdr.Result[2] = itob(cdr.ResultTN.etrack);
|
||||
|
@ -365,10 +381,13 @@ void cdrInterrupt() {
|
|||
cdr.Track = btoi(cdr.Param[0]);
|
||||
SetResultSize(4);
|
||||
cdr.StatP |= STATUS_ROTATING;
|
||||
if (CDVD->getTD(cdr.Track, &trackInfo) == -1) {
|
||||
if (CDVD->getTD(cdr.Track, &trackInfo) == -1)
|
||||
{
|
||||
cdr.Stat = DiskError;
|
||||
cdr.Result[0]|= 0x01;
|
||||
} else {
|
||||
cdr.Result[0] |= 0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
lsn_to_msf(cdr.ResultTD, trackInfo.lsn);
|
||||
cdr.Stat = Acknowledge;
|
||||
cdr.Result[0] = cdr.StatP;
|
||||
|
@ -410,7 +429,8 @@ void cdrInterrupt() {
|
|||
|
||||
case CdlTest:
|
||||
cdr.Stat = Acknowledge;
|
||||
switch (cdr.Param[0]) {
|
||||
switch (cdr.Param[0])
|
||||
{
|
||||
case 0x20: // System Controller ROM Version
|
||||
SetResultSize(4);
|
||||
*(int*)cdr.Result = *(int*)Test20;
|
||||
|
@ -442,10 +462,11 @@ void cdrInterrupt() {
|
|||
cdr.Result[0] = 0x00; // 0x08 and cdr.Result[1]|0x10 : audio cd, enters cd player
|
||||
cdr.Result[1] = 0x00; // 0x80 leads to the menu in the bios, else loads CD
|
||||
|
||||
if (!LoadCdBios) cdr.Result[1] |= 0x80;
|
||||
if (!LoadCdBios)
|
||||
cdr.Result[1] |= 0x80;
|
||||
cdr.Result[2] = 0x00;
|
||||
cdr.Result[3] = 0x00;
|
||||
strncpy((char *)&cdr.Result[4], "PCSX", 4);
|
||||
strncpy((char*)&cdr.Result[4], "PCSX", 4);
|
||||
cdr.Stat = Complete;
|
||||
break;
|
||||
|
||||
|
@ -477,7 +498,8 @@ void cdrInterrupt() {
|
|||
break;
|
||||
|
||||
case READ_ACK:
|
||||
if (!cdr.Reading) return;
|
||||
if (!cdr.Reading)
|
||||
return;
|
||||
|
||||
SetResultSize(1);
|
||||
cdr.StatP |= STATUS_ROTATING;
|
||||
|
@ -510,17 +532,19 @@ void cdrInterrupt() {
|
|||
}
|
||||
|
||||
if (cdr.Stat != NoIntr && cdr.Reg2 != 0x18)
|
||||
psxHu32(0x1070)|= 0x4;
|
||||
psxHu32(0x1070) |= 0x4;
|
||||
|
||||
CDVD_LOG("Cdr Interrupt %x\n", Irq);
|
||||
}
|
||||
|
||||
void cdrReadInterrupt() {
|
||||
void cdrReadInterrupt()
|
||||
{
|
||||
|
||||
if (!cdr.Reading)
|
||||
return;
|
||||
|
||||
if (cdr.Stat) { // CDR_LOG_I("cdrom: read stat hack %02x %x\n", cdr.Irq, cdr.Stat);
|
||||
if (cdr.Stat)
|
||||
{ // CDR_LOG_I("cdrom: read stat hack %02x %x\n", cdr.Irq, cdr.Stat);
|
||||
CDREAD_INT(0x800 * 4); // * 4 reduces dma3 errors lots here
|
||||
return;
|
||||
}
|
||||
|
@ -529,15 +553,15 @@ void cdrReadInterrupt() {
|
|||
|
||||
cdr.OCUP = 1;
|
||||
SetResultSize(1);
|
||||
cdr.StatP |= STATUS_READ|STATUS_ROTATING;
|
||||
cdr.StatP |= STATUS_READ | STATUS_ROTATING;
|
||||
cdr.Result[0] = cdr.StatP;
|
||||
|
||||
if( cdr.RErr == 0 )
|
||||
if (cdr.RErr == 0)
|
||||
{
|
||||
while( (cdr.RErr = DoCDVDgetBuffer(cdr.Transfer)), cdr.RErr == -2 )
|
||||
while ((cdr.RErr = DoCDVDgetBuffer(cdr.Transfer)), cdr.RErr == -2)
|
||||
{
|
||||
// not finished yet ... block on the read until it finishes.
|
||||
Threading::Sleep( 0 );
|
||||
Threading::Sleep(0);
|
||||
Threading::SpinWait();
|
||||
}
|
||||
}
|
||||
|
@ -559,10 +583,12 @@ void cdrReadInterrupt() {
|
|||
|
||||
cdr.SetSector[2]++;
|
||||
|
||||
if (cdr.SetSector[2] == 75) {
|
||||
if (cdr.SetSector[2] == 75)
|
||||
{
|
||||
cdr.SetSector[2] = 0;
|
||||
cdr.SetSector[1]++;
|
||||
if (cdr.SetSector[1] == 60) {
|
||||
if (cdr.SetSector[1] == 60)
|
||||
{
|
||||
cdr.SetSector[1] = 0;
|
||||
cdr.SetSector[0]++;
|
||||
}
|
||||
|
@ -570,17 +596,19 @@ void cdrReadInterrupt() {
|
|||
|
||||
cdr.Readed = 0;
|
||||
|
||||
if ((cdr.Transfer[4+2] & 0x80) && (cdr.Mode & 0x2)) { // EOF
|
||||
if ((cdr.Transfer[4 + 2] & 0x80) && (cdr.Mode & 0x2))
|
||||
{ // EOF
|
||||
DevCon.Warning("CD AutoPausing Read");
|
||||
AddIrqQueue(CdlPause, 0x800);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
ReadTrack();
|
||||
//DevCon.Warning("normal: %d",cdReadTime);
|
||||
CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime);
|
||||
}
|
||||
|
||||
psxHu32(0x1070)|= 0x4;
|
||||
psxHu32(0x1070) |= 0x4;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -596,7 +624,8 @@ cdrRead0:
|
|||
bit 7 - 1 command being processed
|
||||
*/
|
||||
|
||||
u8 cdrRead0(void) {
|
||||
u8 cdrRead0(void)
|
||||
{
|
||||
if (cdr.ResultReady)
|
||||
cdr.Ctrl |= 0x20;
|
||||
else
|
||||
|
@ -608,7 +637,7 @@ u8 cdrRead0(void) {
|
|||
cdr.Ctrl &= ~0x40;
|
||||
|
||||
// what means the 0x10 and the 0x08 bits? i only saw it used by the bios
|
||||
cdr.Ctrl|=0x18;
|
||||
cdr.Ctrl |= 0x18;
|
||||
|
||||
CDVD_LOG("CD0 Read: %x", cdr.Ctrl);
|
||||
return psxHu8(0x1800) = cdr.Ctrl;
|
||||
|
@ -619,12 +648,14 @@ cdrWrite0:
|
|||
0 - to send a command / 1 - to get the result
|
||||
*/
|
||||
|
||||
void cdrWrite0(u8 rt) {
|
||||
void cdrWrite0(u8 rt)
|
||||
{
|
||||
CDVD_LOG("CD0 write: %x", rt);
|
||||
|
||||
cdr.Ctrl = rt | (cdr.Ctrl & ~0x3);
|
||||
|
||||
if (rt == 0) {
|
||||
if (rt == 0)
|
||||
{
|
||||
cdr.ParamP = 0;
|
||||
cdr.ParamC = 0;
|
||||
cdr.ResultReady = 0;
|
||||
|
@ -640,10 +671,13 @@ void setPsxSpeed()
|
|||
cdReadTime = ((PSXCLK / 75) / BIAS) * 2;
|
||||
}
|
||||
|
||||
u8 cdrRead1(void) {
|
||||
if (cdr.ResultReady && cdr.Ctrl & 0x1) {
|
||||
u8 cdrRead1(void)
|
||||
{
|
||||
if (cdr.ResultReady && cdr.Ctrl & 0x1)
|
||||
{
|
||||
psxHu8(0x1801) = cdr.Result[cdr.ResultP++];
|
||||
if (cdr.ResultP == cdr.ResultC) cdr.ResultReady = 0;
|
||||
if (cdr.ResultP == cdr.ResultC)
|
||||
cdr.ResultReady = 0;
|
||||
}
|
||||
else
|
||||
psxHu8(0x1801) = 0;
|
||||
|
@ -652,7 +686,8 @@ u8 cdrRead1(void) {
|
|||
return psxHu8(0x1801);
|
||||
}
|
||||
|
||||
void cdrWrite1(u8 rt) {
|
||||
void cdrWrite1(u8 rt)
|
||||
{
|
||||
int i;
|
||||
|
||||
CDVD_LOG("CD1 write: %x (%s)", rt, CmdName[rt]);
|
||||
|
@ -662,24 +697,30 @@ void cdrWrite1(u8 rt) {
|
|||
//#define CDRCMD_DEBUG
|
||||
#ifdef CDRCMD_DEBUG
|
||||
DevCon.Warning("CD1 write: %x (%s)", rt, CmdName[rt]);
|
||||
if (cdr.ParamC) {
|
||||
if (cdr.ParamC)
|
||||
{
|
||||
DevCon.Warning(" Param[%d] = {", cdr.ParamC);
|
||||
for (i=0;i<cdr.ParamC;i++) DevCon.Warning(" %x,", cdr.Param[i]);
|
||||
for (i = 0; i < cdr.ParamC; i++)
|
||||
DevCon.Warning(" %x,", cdr.Param[i]);
|
||||
DevCon.Warning("}\n");
|
||||
} else DevCon.Warning("\n");
|
||||
}
|
||||
else
|
||||
DevCon.Warning("\n");
|
||||
#endif
|
||||
|
||||
if (cdr.Ctrl & 0x1) return;
|
||||
if (cdr.Ctrl & 0x1)
|
||||
return;
|
||||
|
||||
switch(cdr.Cmd) {
|
||||
switch (cdr.Cmd)
|
||||
{
|
||||
case CdlSync:
|
||||
cdr.Ctrl|= 0x80;
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
AddIrqQueue(cdr.Cmd, 0x800);
|
||||
break;
|
||||
|
||||
case CdlNop:
|
||||
cdr.Ctrl|= 0x80;
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
AddIrqQueue(cdr.Cmd, 0x800);
|
||||
break;
|
||||
|
@ -690,16 +731,19 @@ void cdrWrite1(u8 rt) {
|
|||
// Setloc is memorizing the wanted target, and marks it as unprocessed, and has no other effect
|
||||
// (it doesn't start reading or seeking, and doesn't interrupt or redirect any active reads).
|
||||
int oldSector = msf_to_lsn(cdr.SetSector);
|
||||
for (i = 0; i < 3; i++) cdr.SetSector[i] = btoi(cdr.Param[i]);
|
||||
for (i = 0; i < 3; i++)
|
||||
cdr.SetSector[i] = btoi(cdr.Param[i]);
|
||||
cdr.SetSector[3] = 0;
|
||||
if ((cdr.SetSector[0] | cdr.SetSector[1] | cdr.SetSector[2]) == 0) {
|
||||
*(u32 *)cdr.SetSector = *(u32 *)cdr.SetSectorSeek;
|
||||
if ((cdr.SetSector[0] | cdr.SetSector[1] | cdr.SetSector[2]) == 0)
|
||||
{
|
||||
*(u32*)cdr.SetSector = *(u32*)cdr.SetSectorSeek;
|
||||
}
|
||||
int newSector = msf_to_lsn(cdr.SetSector);
|
||||
|
||||
// sectorSeekReadDelay should lead to sensible random seek results in QA (Aging Disk) test
|
||||
sectorSeekReadDelay = abs(newSector - oldSector) * 100;
|
||||
if (sectorSeekReadDelay < shortSectorSeekReadDelay) sectorSeekReadDelay = shortSectorSeekReadDelay;
|
||||
if (sectorSeekReadDelay < shortSectorSeekReadDelay)
|
||||
sectorSeekReadDelay = shortSectorSeekReadDelay;
|
||||
//DevCon.Warning("CdlSetloc sectorSeekReadDelay: %d", sectorSeekReadDelay);
|
||||
|
||||
cdr.Ctrl |= 0x80;
|
||||
|
@ -710,21 +754,23 @@ void cdrWrite1(u8 rt) {
|
|||
|
||||
case CdlPlay:
|
||||
cdr.Play = 1;
|
||||
cdr.Ctrl|= 0x80;
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
AddIrqQueue(cdr.Cmd, 0x800);
|
||||
break;
|
||||
|
||||
case CdlForward:
|
||||
if (cdr.CurTrack < 0xaa) cdr.CurTrack++;
|
||||
cdr.Ctrl|= 0x80;
|
||||
if (cdr.CurTrack < 0xaa)
|
||||
cdr.CurTrack++;
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
AddIrqQueue(cdr.Cmd, 0x800);
|
||||
break;
|
||||
|
||||
case CdlBackward:
|
||||
if (cdr.CurTrack > 1) cdr.CurTrack--;
|
||||
cdr.Ctrl|= 0x80;
|
||||
if (cdr.CurTrack > 1)
|
||||
cdr.CurTrack--;
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
AddIrqQueue(cdr.Cmd, 0x800);
|
||||
break;
|
||||
|
@ -732,7 +778,7 @@ void cdrWrite1(u8 rt) {
|
|||
case CdlReadN:
|
||||
cdr.Irq = 0;
|
||||
StopReading();
|
||||
cdr.Ctrl|= 0x80;
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
StartReading(1);
|
||||
break;
|
||||
|
@ -740,7 +786,7 @@ void cdrWrite1(u8 rt) {
|
|||
case CdlStandby:
|
||||
StopCdda();
|
||||
StopReading();
|
||||
cdr.Ctrl|= 0x80;
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
AddIrqQueue(cdr.Cmd, 0x800);
|
||||
break;
|
||||
|
@ -748,7 +794,7 @@ void cdrWrite1(u8 rt) {
|
|||
case CdlStop:
|
||||
StopCdda();
|
||||
StopReading();
|
||||
cdr.Ctrl|= 0x80;
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
AddIrqQueue(cdr.Cmd, 0x800);
|
||||
break;
|
||||
|
@ -756,7 +802,7 @@ void cdrWrite1(u8 rt) {
|
|||
case CdlPause:
|
||||
StopCdda();
|
||||
StopReading();
|
||||
cdr.Ctrl|= 0x80;
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
AddIrqQueue(cdr.Cmd, 0x40000);
|
||||
break;
|
||||
|
@ -765,21 +811,21 @@ void cdrWrite1(u8 rt) {
|
|||
case CdlInit:
|
||||
StopCdda();
|
||||
StopReading();
|
||||
cdr.Ctrl|= 0x80;
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
AddIrqQueue(cdr.Cmd, 0x800);
|
||||
break;
|
||||
|
||||
case CdlMute:
|
||||
cdr.Muted = 0;
|
||||
cdr.Ctrl|= 0x80;
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
AddIrqQueue(cdr.Cmd, 0x800);
|
||||
break;
|
||||
|
||||
case CdlDemute:
|
||||
cdr.Muted = 1;
|
||||
cdr.Ctrl|= 0x80;
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
AddIrqQueue(cdr.Cmd, 0x800);
|
||||
break;
|
||||
|
@ -787,7 +833,7 @@ void cdrWrite1(u8 rt) {
|
|||
case CdlSetfilter:
|
||||
cdr.File = cdr.Param[0];
|
||||
cdr.Channel = cdr.Param[1];
|
||||
cdr.Ctrl|= 0x80;
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
AddIrqQueue(cdr.Cmd, 0x800);
|
||||
break;
|
||||
|
@ -796,44 +842,44 @@ void cdrWrite1(u8 rt) {
|
|||
CDVD_LOG("Setmode %x", cdr.Param[0]);
|
||||
|
||||
cdr.Mode = cdr.Param[0];
|
||||
cdr.Ctrl|= 0x80;
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
AddIrqQueue(cdr.Cmd, 0x800);
|
||||
break;
|
||||
|
||||
case CdlGetmode:
|
||||
cdr.Ctrl|= 0x80;
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
AddIrqQueue(cdr.Cmd, 0x800);
|
||||
break;
|
||||
|
||||
case CdlGetlocL:
|
||||
cdr.Ctrl|= 0x80;
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
AddIrqQueue(cdr.Cmd, 0x800);
|
||||
break;
|
||||
|
||||
case CdlGetlocP:
|
||||
cdr.Ctrl|= 0x80;
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
AddIrqQueue(cdr.Cmd, 0x800);
|
||||
break;
|
||||
|
||||
case CdlGetTN:
|
||||
cdr.Ctrl|= 0x80;
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
AddIrqQueue(cdr.Cmd, 0x800);
|
||||
break;
|
||||
|
||||
case CdlGetTD:
|
||||
cdr.Ctrl|= 0x80;
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
AddIrqQueue(cdr.Cmd, 0x800);
|
||||
break;
|
||||
|
||||
case CdlSeekL:
|
||||
((u32 *)cdr.SetSectorSeek)[0] = ((u32 *)cdr.SetSector)[0];
|
||||
cdr.Ctrl|= 0x80;
|
||||
((u32*)cdr.SetSectorSeek)[0] = ((u32*)cdr.SetSector)[0];
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
|
||||
//DevCon.Warning("CdlSeekL delay: %d", sectorSeekReadDelay);
|
||||
|
@ -842,8 +888,8 @@ void cdrWrite1(u8 rt) {
|
|||
break;
|
||||
|
||||
case CdlSeekP:
|
||||
((u32 *)cdr.SetSectorSeek)[0] = ((u32 *)cdr.SetSector)[0];
|
||||
cdr.Ctrl|= 0x80;
|
||||
((u32*)cdr.SetSectorSeek)[0] = ((u32*)cdr.SetSector)[0];
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
|
||||
//DevCon.Warning("CdlSeekP delay: %d", sectorSeekReadDelay);
|
||||
|
@ -852,13 +898,13 @@ void cdrWrite1(u8 rt) {
|
|||
break;
|
||||
|
||||
case CdlTest:
|
||||
cdr.Ctrl|= 0x80;
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
AddIrqQueue(cdr.Cmd, 0x800);
|
||||
break;
|
||||
|
||||
case CdlID:
|
||||
cdr.Ctrl|= 0x80;
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
AddIrqQueue(cdr.Cmd, 0x800);
|
||||
break;
|
||||
|
@ -866,13 +912,13 @@ void cdrWrite1(u8 rt) {
|
|||
case CdlReadS:
|
||||
cdr.Irq = 0;
|
||||
StopReading();
|
||||
cdr.Ctrl|= 0x80;
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
StartReading(2);
|
||||
break;
|
||||
|
||||
case CdlReadToc:
|
||||
cdr.Ctrl|= 0x80;
|
||||
cdr.Ctrl |= 0x80;
|
||||
cdr.Stat = NoIntr;
|
||||
AddIrqQueue(cdr.Cmd, 0x800);
|
||||
break;
|
||||
|
@ -882,15 +928,19 @@ void cdrWrite1(u8 rt) {
|
|||
return;
|
||||
}
|
||||
if (cdr.Stat != NoIntr)
|
||||
iopIntcIrq( 2 );
|
||||
iopIntcIrq(2);
|
||||
}
|
||||
|
||||
u8 cdrRead2(void) {
|
||||
u8 cdrRead2(void)
|
||||
{
|
||||
u8 ret;
|
||||
|
||||
if (cdr.Readed == 0) {
|
||||
if (cdr.Readed == 0)
|
||||
{
|
||||
ret = 0;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = *cdr.pTransfer++;
|
||||
}
|
||||
|
||||
|
@ -898,11 +948,14 @@ u8 cdrRead2(void) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
void cdrWrite2(u8 rt) {
|
||||
void cdrWrite2(u8 rt)
|
||||
{
|
||||
CDVD_LOG("CD2 write: %x", rt);
|
||||
|
||||
if (cdr.Ctrl & 0x1) {
|
||||
switch (rt) {
|
||||
if (cdr.Ctrl & 0x1)
|
||||
{
|
||||
switch (rt)
|
||||
{
|
||||
case 0x07:
|
||||
cdr.ParamP = 0;
|
||||
cdr.ParamC = 0;
|
||||
|
@ -917,59 +970,79 @@ void cdrWrite2(u8 rt) {
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!(cdr.Ctrl & 0x1) && cdr.ParamP < 8) {
|
||||
if (!(cdr.Ctrl & 0x1) && cdr.ParamP < 8)
|
||||
{
|
||||
cdr.Param[cdr.ParamP++] = rt;
|
||||
cdr.ParamC++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u8 cdrRead3(void) {
|
||||
if (cdr.Stat) {
|
||||
u8 cdrRead3(void)
|
||||
{
|
||||
if (cdr.Stat)
|
||||
{
|
||||
if (cdr.Ctrl & 0x1)
|
||||
psxHu8(0x1803) = cdr.Stat | 0xE0;
|
||||
else
|
||||
psxHu8(0x1803) = 0xff;
|
||||
} else psxHu8(0x1803) = 0;
|
||||
}
|
||||
else
|
||||
psxHu8(0x1803) = 0;
|
||||
|
||||
CDVD_LOG("CD3 Read: %x", psxHu8(0x1803));
|
||||
return psxHu8(0x1803);
|
||||
}
|
||||
|
||||
void cdrWrite3(u8 rt) {
|
||||
void cdrWrite3(u8 rt)
|
||||
{
|
||||
CDVD_LOG("CD3 write: %x", rt);
|
||||
|
||||
if (rt == 0x07 && cdr.Ctrl & 0x1) {
|
||||
if (rt == 0x07 && cdr.Ctrl & 0x1)
|
||||
{
|
||||
cdr.Stat = 0;
|
||||
|
||||
if (cdr.Irq == 0xff) { cdr.Irq = 0; return; }
|
||||
if (cdr.Irq) {
|
||||
if (cdr.Irq == 0xff)
|
||||
{
|
||||
cdr.Irq = 0;
|
||||
return;
|
||||
}
|
||||
if (cdr.Irq)
|
||||
{
|
||||
CDR_INT(cdr.eCycle);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (rt == 0x80 && !(cdr.Ctrl & 0x1) && cdr.Readed == 0) {
|
||||
if (rt == 0x80 && !(cdr.Ctrl & 0x1) && cdr.Readed == 0)
|
||||
{
|
||||
cdr.Readed = 1;
|
||||
cdr.pTransfer = cdr.Transfer;
|
||||
|
||||
switch (cdr.Mode&0x30) {
|
||||
switch (cdr.Mode & 0x30)
|
||||
{
|
||||
case 0x10:
|
||||
case 0x00: cdr.pTransfer+=12; break;
|
||||
default: break;
|
||||
case 0x00:
|
||||
cdr.pTransfer += 12;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void psxDma3(u32 madr, u32 bcr, u32 chcr) {
|
||||
void psxDma3(u32 madr, u32 bcr, u32 chcr)
|
||||
{
|
||||
u32 cdsize;
|
||||
|
||||
CDVD_LOG("*** DMA 3 *** %lx addr = %lx size = %lx", chcr, madr, bcr);
|
||||
|
||||
switch (chcr) {
|
||||
switch (chcr)
|
||||
{
|
||||
case 0x11000000:
|
||||
case 0x11400100:
|
||||
if (cdr.Readed == 0) {
|
||||
if (cdr.Readed == 0)
|
||||
{
|
||||
DevCon.Warning("*** DMA 3 *** NOT READY");
|
||||
HW_DMA3_CHCR &= ~0x01000000; //hack
|
||||
psxDmaInterrupt(3); //hack
|
||||
|
@ -978,8 +1051,8 @@ void psxDma3(u32 madr, u32 bcr, u32 chcr) {
|
|||
|
||||
cdsize = (bcr & 0xffff) * 4;
|
||||
memcpy(iopPhysMem(madr), cdr.pTransfer, cdsize);
|
||||
psxCpu->Clear(madr, cdsize/4);
|
||||
cdr.pTransfer+=cdsize;
|
||||
psxCpu->Clear(madr, cdsize / 4);
|
||||
cdr.pTransfer += cdsize;
|
||||
|
||||
break;
|
||||
case 0x41000200:
|
||||
|
@ -994,16 +1067,17 @@ void psxDma3(u32 madr, u32 bcr, u32 chcr) {
|
|||
psxDmaInterrupt(3);
|
||||
}
|
||||
|
||||
void cdrReset() {
|
||||
void cdrReset()
|
||||
{
|
||||
memzero(cdr);
|
||||
cdr.CurTrack=1;
|
||||
cdr.File=1; cdr.Channel=1;
|
||||
cdr.CurTrack = 1;
|
||||
cdr.File = 1;
|
||||
cdr.Channel = 1;
|
||||
cdReadTime = (PSXCLK / 1757) * BIAS;
|
||||
}
|
||||
|
||||
void SaveStateBase::cdrFreeze()
|
||||
{
|
||||
FreezeTag( "cdrom" );
|
||||
FreezeTag("cdrom");
|
||||
Freeze(cdr);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,12 +20,14 @@
|
|||
#include "CDVDaccess.h"
|
||||
|
||||
// Not used.
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
s32 y0, y1;
|
||||
} ADPCM_Decode_t;
|
||||
|
||||
// Not used.
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
s32 freq;
|
||||
s32 nbits;
|
||||
s32 stereo;
|
||||
|
@ -46,7 +48,7 @@ struct cdrStruct
|
|||
u8 StatP;
|
||||
|
||||
u8 Transfer[2352];
|
||||
u8 *pTransfer;
|
||||
u8* pTransfer;
|
||||
|
||||
u8 Prev[4];
|
||||
u8 Param[8];
|
||||
|
|
|
@ -16,32 +16,39 @@
|
|||
#include "PrecompiledHeader.h"
|
||||
#include "ChunksCache.h"
|
||||
|
||||
void ChunksCache::SetLimit(uint megabytes) {
|
||||
void ChunksCache::SetLimit(uint megabytes)
|
||||
{
|
||||
m_limit = (PX_off_t)megabytes * 1024 * 1024;
|
||||
MatchLimit();
|
||||
}
|
||||
|
||||
void ChunksCache::MatchLimit(bool removeAll) {
|
||||
void ChunksCache::MatchLimit(bool removeAll)
|
||||
{
|
||||
std::list<CacheEntry*>::reverse_iterator rit;
|
||||
while (!m_entries.empty() && (removeAll || m_size > m_limit)) {
|
||||
while (!m_entries.empty() && (removeAll || m_size > m_limit))
|
||||
{
|
||||
rit = m_entries.rbegin();
|
||||
m_size -= (*rit)->size;
|
||||
delete(*rit);
|
||||
delete (*rit);
|
||||
m_entries.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void ChunksCache::Take(void* pMallocedSrc, PX_off_t offset, int length, int coverage) {
|
||||
void ChunksCache::Take(void* pMallocedSrc, PX_off_t offset, int length, int coverage)
|
||||
{
|
||||
m_entries.push_front(new CacheEntry(pMallocedSrc, offset, length, coverage));
|
||||
m_size += length;
|
||||
MatchLimit();
|
||||
}
|
||||
|
||||
// By design, succeed only if the entire request is in a single cached chunk
|
||||
int ChunksCache::Read(void* pDest, PX_off_t offset, int length) {
|
||||
for (auto it = m_entries.begin(); it != m_entries.end(); it++) {
|
||||
int ChunksCache::Read(void* pDest, PX_off_t offset, int length)
|
||||
{
|
||||
for (auto it = m_entries.begin(); it != m_entries.end(); it++)
|
||||
{
|
||||
CacheEntry* e = *it;
|
||||
if (e && offset >= e->offset && (offset + length) <= (e->offset + e->coverage)) {
|
||||
if (e && offset >= e->offset && (offset + length) <= (e->offset + e->coverage))
|
||||
{
|
||||
if (it != m_entries.begin())
|
||||
m_entries.splice(m_entries.begin(), m_entries, it); // Move to top (MRU)
|
||||
return CopyAvailable(e->data, e->offset, e->size, pDest, offset, length);
|
||||
|
@ -49,4 +56,3 @@ int ChunksCache::Read(void* pDest, PX_off_t offset, int length) {
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,9 +19,13 @@
|
|||
|
||||
#define CLAMP(val, minval, maxval) (std::min(maxval, std::max(minval, val)))
|
||||
|
||||
class ChunksCache {
|
||||
class ChunksCache
|
||||
{
|
||||
public:
|
||||
ChunksCache(uint initialLimitMb) : m_entries(0), m_size(0), m_limit(initialLimitMb * 1024 * 1024) {};
|
||||
ChunksCache(uint initialLimitMb)
|
||||
: m_entries(0)
|
||||
, m_size(0)
|
||||
, m_limit(initialLimitMb * 1024 * 1024){};
|
||||
~ChunksCache() { Clear(); };
|
||||
void SetLimit(uint megabytes);
|
||||
void Clear() { MatchLimit(true); };
|
||||
|
@ -30,23 +34,28 @@ public:
|
|||
int Read(void* pDest, PX_off_t offset, int length);
|
||||
|
||||
static int CopyAvailable(void* pSrc, PX_off_t srcOffset, int srcSize,
|
||||
void* pDst, PX_off_t dstOffset, int maxCopySize) {
|
||||
void* pDst, PX_off_t dstOffset, int maxCopySize)
|
||||
{
|
||||
int available = CLAMP(maxCopySize, 0, (int)(srcOffset + srcSize - dstOffset));
|
||||
memcpy(pDst, (char*)pSrc + (dstOffset - srcOffset), available);
|
||||
return available;
|
||||
};
|
||||
|
||||
private:
|
||||
class CacheEntry {
|
||||
class CacheEntry
|
||||
{
|
||||
public:
|
||||
CacheEntry(void* pMallocedSrc, PX_off_t offset, int length, int coverage) :
|
||||
data(pMallocedSrc),
|
||||
offset(offset),
|
||||
coverage(coverage),
|
||||
size(length)
|
||||
{};
|
||||
CacheEntry(void* pMallocedSrc, PX_off_t offset, int length, int coverage)
|
||||
: data(pMallocedSrc)
|
||||
, offset(offset)
|
||||
, coverage(coverage)
|
||||
, size(length){};
|
||||
|
||||
~CacheEntry() { if (data) free(data); };
|
||||
~CacheEntry()
|
||||
{
|
||||
if (data)
|
||||
free(data);
|
||||
};
|
||||
|
||||
void* data;
|
||||
PX_off_t offset;
|
||||
|
|
|
@ -20,11 +20,14 @@
|
|||
#include "GzippedFileReader.h"
|
||||
|
||||
// CompressedFileReader factory.
|
||||
AsyncFileReader* CompressedFileReader::GetNewReader(const wxString& fileName) {
|
||||
if (GzippedFileReader::CanHandle(fileName)) {
|
||||
AsyncFileReader* CompressedFileReader::GetNewReader(const wxString& fileName)
|
||||
{
|
||||
if (GzippedFileReader::CanHandle(fileName))
|
||||
{
|
||||
return new GzippedFileReader();
|
||||
}
|
||||
if (CsoFileReader::CanHandle(fileName)) {
|
||||
if (CsoFileReader::CanHandle(fileName))
|
||||
{
|
||||
return new CsoFileReader();
|
||||
}
|
||||
// This is the one which will fail on open.
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
#pragma once
|
||||
|
||||
// Factory - creates an AsyncFileReader derived instance which can read a compressed file
|
||||
class CompressedFileReader {
|
||||
class CompressedFileReader
|
||||
{
|
||||
public:
|
||||
// fileName and its contents may be used to choose the compressed reader.
|
||||
// If no matching handler is found, NULL is returned.
|
||||
|
|
|
@ -24,21 +24,21 @@
|
|||
// Maybe some day we'll convert all file related ops to wxWidgets, which means also the
|
||||
// instances at zlib_indexed.h (which use plain stdio FILE*)
|
||||
#ifdef _WIN32
|
||||
# define PX_wfilename(name_wxstr) (name_wxstr.wc_str())
|
||||
# define PX_fopen_rb(name_wxstr) (_wfopen(PX_wfilename(name_wxstr), L"rb"))
|
||||
#define PX_wfilename(name_wxstr) (name_wxstr.wc_str())
|
||||
#define PX_fopen_rb(name_wxstr) (_wfopen(PX_wfilename(name_wxstr), L"rb"))
|
||||
#else
|
||||
# define PX_wfilename(name_wxstr) (name_wxstr.mbc_str())
|
||||
# define PX_fopen_rb(name_wxstr) (fopen(PX_wfilename(name_wxstr), "rb"))
|
||||
#define PX_wfilename(name_wxstr) (name_wxstr.mbc_str())
|
||||
#define PX_fopen_rb(name_wxstr) (fopen(PX_wfilename(name_wxstr), "rb"))
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# define PX_fseeko _fseeki64
|
||||
# define PX_ftello _ftelli64
|
||||
# define PX_off_t s64 /* __int64 */
|
||||
#define PX_fseeko _fseeki64
|
||||
#define PX_ftello _ftelli64
|
||||
#define PX_off_t s64 /* __int64 */
|
||||
#else
|
||||
# define PX_fseeko fseeko
|
||||
# define PX_ftello ftello
|
||||
# define PX_off_t off_t
|
||||
#define PX_fseeko fseeko
|
||||
#define PX_ftello ftello
|
||||
#define PX_off_t off_t
|
||||
#endif
|
||||
|
||||
/////////// End of complementary utilities for zlib_indexed.c //////////
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
|
||||
// Implementation of CSO compressed ISO reading, based on:
|
||||
// https://github.com/unknownbrackets/maxcso/blob/master/README_CSO.md
|
||||
struct CsoHeader {
|
||||
struct CsoHeader
|
||||
{
|
||||
u8 magic[4];
|
||||
u32 header_size;
|
||||
u64 total_bytes;
|
||||
|
@ -38,13 +39,17 @@ struct CsoHeader {
|
|||
|
||||
static const u32 CSO_READ_BUFFER_SIZE = 256 * 1024;
|
||||
|
||||
bool CsoFileReader::CanHandle(const wxString& fileName) {
|
||||
bool CsoFileReader::CanHandle(const wxString& fileName)
|
||||
{
|
||||
bool supported = false;
|
||||
if (wxFileName::FileExists(fileName) && fileName.Lower().EndsWith(L".cso")) {
|
||||
if (wxFileName::FileExists(fileName) && fileName.Lower().EndsWith(L".cso"))
|
||||
{
|
||||
FILE* fp = PX_fopen_rb(fileName);
|
||||
CsoHeader hdr;
|
||||
if (fp) {
|
||||
if (fread(&hdr, 1, sizeof(hdr), fp) == sizeof(hdr)) {
|
||||
if (fp)
|
||||
{
|
||||
if (fread(&hdr, 1, sizeof(hdr), fp) == sizeof(hdr))
|
||||
{
|
||||
supported = ValidateHeader(hdr);
|
||||
}
|
||||
fclose(fp);
|
||||
|
@ -53,20 +58,25 @@ bool CsoFileReader::CanHandle(const wxString& fileName) {
|
|||
return supported;
|
||||
}
|
||||
|
||||
bool CsoFileReader::ValidateHeader(const CsoHeader& hdr) {
|
||||
if (hdr.magic[0] != 'C' || hdr.magic[1] != 'I' || hdr.magic[2] != 'S' || hdr.magic[3] != 'O') {
|
||||
bool CsoFileReader::ValidateHeader(const CsoHeader& hdr)
|
||||
{
|
||||
if (hdr.magic[0] != 'C' || hdr.magic[1] != 'I' || hdr.magic[2] != 'S' || hdr.magic[3] != 'O')
|
||||
{
|
||||
// Invalid magic, definitely a bad file.
|
||||
return false;
|
||||
}
|
||||
if (hdr.ver > 1) {
|
||||
if (hdr.ver > 1)
|
||||
{
|
||||
Console.Error(L"Only CSOv1 files are supported.");
|
||||
return false;
|
||||
}
|
||||
if ((hdr.frame_size & (hdr.frame_size - 1)) != 0) {
|
||||
if ((hdr.frame_size & (hdr.frame_size - 1)) != 0)
|
||||
{
|
||||
Console.Error(L"CSO frame size must be a power of two.");
|
||||
return false;
|
||||
}
|
||||
if (hdr.frame_size < 2048) {
|
||||
if (hdr.frame_size < 2048)
|
||||
{
|
||||
Console.Error(L"CSO frame size must be at least one sector.");
|
||||
return false;
|
||||
}
|
||||
|
@ -75,33 +85,39 @@ bool CsoFileReader::ValidateHeader(const CsoHeader& hdr) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CsoFileReader::Open(const wxString& fileName) {
|
||||
bool CsoFileReader::Open(const wxString& fileName)
|
||||
{
|
||||
Close();
|
||||
m_filename = fileName;
|
||||
m_src = PX_fopen_rb(m_filename);
|
||||
|
||||
bool success = false;
|
||||
if (m_src && ReadFileHeader() && InitializeBuffers()) {
|
||||
if (m_src && ReadFileHeader() && InitializeBuffers())
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
if (!success)
|
||||
{
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CsoFileReader::ReadFileHeader() {
|
||||
bool CsoFileReader::ReadFileHeader()
|
||||
{
|
||||
CsoHeader hdr = {};
|
||||
|
||||
PX_fseeko(m_src, m_dataoffset, SEEK_SET);
|
||||
if (fread(&hdr, 1, sizeof(hdr), m_src) != sizeof(hdr)) {
|
||||
if (fread(&hdr, 1, sizeof(hdr), m_src) != sizeof(hdr))
|
||||
{
|
||||
Console.Error(L"Failed to read CSO file header.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ValidateHeader(hdr)) {
|
||||
if (!ValidateHeader(hdr))
|
||||
{
|
||||
Console.Error(L"CSO has invalid header.");
|
||||
return false;
|
||||
}
|
||||
|
@ -109,7 +125,8 @@ bool CsoFileReader::ReadFileHeader() {
|
|||
m_frameSize = hdr.frame_size;
|
||||
// Determine the translation from bytes to frame.
|
||||
m_frameShift = 0;
|
||||
for (u32 i = m_frameSize; i > 1; i >>= 1) {
|
||||
for (u32 i = m_frameSize; i > 1; i >>= 1)
|
||||
{
|
||||
++m_frameShift;
|
||||
}
|
||||
|
||||
|
@ -120,14 +137,18 @@ bool CsoFileReader::ReadFileHeader() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CsoFileReader::InitializeBuffers() {
|
||||
bool CsoFileReader::InitializeBuffers()
|
||||
{
|
||||
// Round up, since part of a frame requires a full frame.
|
||||
u32 numFrames = (u32)((m_totalSize + m_frameSize - 1) / m_frameSize);
|
||||
|
||||
// We might read a bit of alignment too, so be prepared.
|
||||
if (m_frameSize + (1 << m_indexShift) < CSO_READ_BUFFER_SIZE) {
|
||||
if (m_frameSize + (1 << m_indexShift) < CSO_READ_BUFFER_SIZE)
|
||||
{
|
||||
m_readBuffer = new u8[CSO_READ_BUFFER_SIZE];
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
m_readBuffer = new u8[m_frameSize + (1 << m_indexShift)];
|
||||
}
|
||||
|
||||
|
@ -137,7 +158,8 @@ bool CsoFileReader::InitializeBuffers() {
|
|||
|
||||
const u32 indexSize = numFrames + 1;
|
||||
m_index = new u32[indexSize];
|
||||
if (fread(m_index, sizeof(u32), indexSize, m_src) != indexSize) {
|
||||
if (fread(m_index, sizeof(u32), indexSize, m_src) != indexSize)
|
||||
{
|
||||
Console.Error(L"Unable to read index data from CSO.");
|
||||
return false;
|
||||
}
|
||||
|
@ -146,7 +168,8 @@ bool CsoFileReader::InitializeBuffers() {
|
|||
m_z_stream->zalloc = Z_NULL;
|
||||
m_z_stream->zfree = Z_NULL;
|
||||
m_z_stream->opaque = Z_NULL;
|
||||
if (inflateInit2(m_z_stream, -15) != Z_OK) {
|
||||
if (inflateInit2(m_z_stream, -15) != Z_OK)
|
||||
{
|
||||
Console.Error("Unable to initialize zlib for CSO decompression.");
|
||||
return false;
|
||||
}
|
||||
|
@ -154,37 +177,45 @@ bool CsoFileReader::InitializeBuffers() {
|
|||
return true;
|
||||
}
|
||||
|
||||
void CsoFileReader::Close() {
|
||||
void CsoFileReader::Close()
|
||||
{
|
||||
m_filename.Empty();
|
||||
#if CSO_USE_CHUNKSCACHE
|
||||
m_cache.Clear();
|
||||
#endif
|
||||
|
||||
if (m_src) {
|
||||
if (m_src)
|
||||
{
|
||||
fclose(m_src);
|
||||
m_src = NULL;
|
||||
}
|
||||
if (m_z_stream) {
|
||||
if (m_z_stream)
|
||||
{
|
||||
inflateEnd(m_z_stream);
|
||||
m_z_stream = NULL;
|
||||
}
|
||||
|
||||
if (m_readBuffer) {
|
||||
if (m_readBuffer)
|
||||
{
|
||||
delete[] m_readBuffer;
|
||||
m_readBuffer = NULL;
|
||||
}
|
||||
if (m_zlibBuffer) {
|
||||
if (m_zlibBuffer)
|
||||
{
|
||||
delete[] m_zlibBuffer;
|
||||
m_zlibBuffer = NULL;
|
||||
}
|
||||
if (m_index) {
|
||||
if (m_index)
|
||||
{
|
||||
delete[] m_index;
|
||||
m_index = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int CsoFileReader::ReadSync(void* pBuffer, uint sector, uint count) {
|
||||
if (!m_src) {
|
||||
int CsoFileReader::ReadSync(void* pBuffer, uint sector, uint count)
|
||||
{
|
||||
if (!m_src)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -197,7 +228,8 @@ int CsoFileReader::ReadSync(void* pBuffer, uint sector, uint count) {
|
|||
int remaining = count * m_blocksize;
|
||||
int bytes = 0;
|
||||
|
||||
while (remaining > 0) {
|
||||
while (remaining > 0)
|
||||
{
|
||||
int readBytes;
|
||||
|
||||
#if CSO_USE_CHUNKSCACHE
|
||||
|
@ -206,16 +238,18 @@ int CsoFileReader::ReadSync(void* pBuffer, uint sector, uint count) {
|
|||
#else
|
||||
readBytes = -1;
|
||||
#endif
|
||||
if (readBytes < 0) {
|
||||
if (readBytes < 0)
|
||||
{
|
||||
readBytes = ReadFromFrame(dest + bytes, pos + bytes, remaining);
|
||||
if (readBytes == 0) {
|
||||
if (readBytes == 0)
|
||||
{
|
||||
// We hit EOF.
|
||||
break;
|
||||
}
|
||||
|
||||
#if CSO_USE_CHUNKSCACHE
|
||||
// Add the bytes into the cache. We need to allocate a buffer for it.
|
||||
void *cached = malloc(readBytes);
|
||||
void* cached = malloc(readBytes);
|
||||
memcpy(cached, dest + bytes, readBytes);
|
||||
m_cache.Take(cached, pos + bytes, readBytes, readBytes);
|
||||
#endif
|
||||
|
@ -228,8 +262,10 @@ int CsoFileReader::ReadSync(void* pBuffer, uint sector, uint count) {
|
|||
return bytes;
|
||||
}
|
||||
|
||||
int CsoFileReader::ReadFromFrame(u8 *dest, u64 pos, int maxBytes) {
|
||||
if (pos >= m_totalSize) {
|
||||
int CsoFileReader::ReadFromFrame(u8* dest, u64 pos, int maxBytes)
|
||||
{
|
||||
if (pos >= m_totalSize)
|
||||
{
|
||||
// Can't read anything passed the end.
|
||||
return 0;
|
||||
}
|
||||
|
@ -248,24 +284,31 @@ int CsoFileReader::ReadFromFrame(u8 *dest, u64 pos, int maxBytes) {
|
|||
const u64 frameRawPos = (u64)index0 << m_indexShift;
|
||||
const u64 frameRawSize = (u64)(index1 - index0) << m_indexShift;
|
||||
|
||||
if (!compressed) {
|
||||
if (!compressed)
|
||||
{
|
||||
// Just read directly, easy.
|
||||
if (PX_fseeko(m_src, m_dataoffset + frameRawPos + offset, SEEK_SET) != 0) {
|
||||
if (PX_fseeko(m_src, m_dataoffset + frameRawPos + offset, SEEK_SET) != 0)
|
||||
{
|
||||
Console.Error("Unable to seek to uncompressed CSO data.");
|
||||
return 0;
|
||||
}
|
||||
return fread(dest, 1, bytes, m_src);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// We don't need to decompress if we already did this same frame last time.
|
||||
if (m_zlibBufferFrame != frame) {
|
||||
if (PX_fseeko(m_src, m_dataoffset + frameRawPos, SEEK_SET) != 0) {
|
||||
if (m_zlibBufferFrame != frame)
|
||||
{
|
||||
if (PX_fseeko(m_src, m_dataoffset + frameRawPos, SEEK_SET) != 0)
|
||||
{
|
||||
Console.Error("Unable to seek to compressed CSO data.");
|
||||
return 0;
|
||||
}
|
||||
// This might be less bytes than frameRawSize in case of padding on the last frame.
|
||||
// This is because the index positions must be aligned.
|
||||
const u32 readRawBytes = fread(m_readBuffer, 1, frameRawSize, m_src);
|
||||
if (!DecompressFrame(frame, readRawBytes)) {
|
||||
if (!DecompressFrame(frame, readRawBytes))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -277,7 +320,8 @@ int CsoFileReader::ReadFromFrame(u8 *dest, u64 pos, int maxBytes) {
|
|||
return bytes;
|
||||
}
|
||||
|
||||
bool CsoFileReader::DecompressFrame(u32 frame, u32 readBufferSize) {
|
||||
bool CsoFileReader::DecompressFrame(u32 frame, u32 readBufferSize)
|
||||
{
|
||||
m_z_stream->next_in = m_readBuffer;
|
||||
m_z_stream->avail_in = readBufferSize;
|
||||
m_z_stream->next_out = m_zlibBuffer;
|
||||
|
@ -285,10 +329,13 @@ bool CsoFileReader::DecompressFrame(u32 frame, u32 readBufferSize) {
|
|||
|
||||
int status = inflate(m_z_stream, Z_FINISH);
|
||||
bool success = status == Z_STREAM_END && m_z_stream->total_out == m_frameSize;
|
||||
if (success) {
|
||||
if (success)
|
||||
{
|
||||
// Our buffer now contains this frame.
|
||||
m_zlibBufferFrame = frame;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Error("Unable to decompress CSO frame using zlib.");
|
||||
m_zlibBufferFrame = (u32)-1;
|
||||
}
|
||||
|
@ -297,17 +344,20 @@ bool CsoFileReader::DecompressFrame(u32 frame, u32 readBufferSize) {
|
|||
return success;
|
||||
}
|
||||
|
||||
void CsoFileReader::BeginRead(void* pBuffer, uint sector, uint count) {
|
||||
void CsoFileReader::BeginRead(void* pBuffer, uint sector, uint count)
|
||||
{
|
||||
// TODO: No async support yet, implement as sync.
|
||||
m_bytesRead = ReadSync(pBuffer, sector, count);
|
||||
}
|
||||
|
||||
int CsoFileReader::FinishRead() {
|
||||
int CsoFileReader::FinishRead()
|
||||
{
|
||||
int res = m_bytesRead;
|
||||
m_bytesRead = -1;
|
||||
return res;
|
||||
}
|
||||
|
||||
void CsoFileReader::CancelRead() {
|
||||
void CsoFileReader::CancelRead()
|
||||
{
|
||||
// TODO: No async read support yet.
|
||||
}
|
||||
|
|
|
@ -35,22 +35,26 @@ static const uint CSO_CHUNKCACHE_SIZE_MB = 200;
|
|||
class CsoFileReader : public AsyncFileReader
|
||||
{
|
||||
DeclareNoncopyableObject(CsoFileReader);
|
||||
|
||||
public:
|
||||
CsoFileReader(void) :
|
||||
m_frameSize(0),
|
||||
m_frameShift(0),
|
||||
m_indexShift(0),
|
||||
m_readBuffer(0),
|
||||
m_zlibBuffer(0),
|
||||
m_zlibBufferFrame(0),
|
||||
m_index(0),
|
||||
m_totalSize(0),
|
||||
m_src(0),
|
||||
m_z_stream(0),
|
||||
CsoFileReader(void)
|
||||
: m_frameSize(0)
|
||||
, m_frameShift(0)
|
||||
, m_indexShift(0)
|
||||
, m_readBuffer(0)
|
||||
, m_zlibBuffer(0)
|
||||
, m_zlibBufferFrame(0)
|
||||
, m_index(0)
|
||||
, m_totalSize(0)
|
||||
, m_src(0)
|
||||
, m_z_stream(0)
|
||||
,
|
||||
#if CSO_USE_CHUNKSCACHE
|
||||
m_cache(CSO_CHUNKCACHE_SIZE_MB),
|
||||
m_cache(CSO_CHUNKCACHE_SIZE_MB)
|
||||
,
|
||||
#endif
|
||||
m_bytesRead(0) {
|
||||
m_bytesRead(0)
|
||||
{
|
||||
m_blocksize = 2048;
|
||||
};
|
||||
|
||||
|
@ -67,7 +71,8 @@ public:
|
|||
|
||||
virtual void Close(void);
|
||||
|
||||
virtual uint GetBlockCount(void) const {
|
||||
virtual uint GetBlockCount(void) const
|
||||
{
|
||||
return (m_totalSize - m_dataoffset) / m_blocksize;
|
||||
};
|
||||
|
||||
|
@ -78,16 +83,16 @@ private:
|
|||
static bool ValidateHeader(const CsoHeader& hdr);
|
||||
bool ReadFileHeader();
|
||||
bool InitializeBuffers();
|
||||
int ReadFromFrame(u8 *dest, u64 pos, int maxBytes);
|
||||
int ReadFromFrame(u8* dest, u64 pos, int maxBytes);
|
||||
bool DecompressFrame(u32 frame, u32 readBufferSize);
|
||||
|
||||
u32 m_frameSize;
|
||||
u8 m_frameShift;
|
||||
u8 m_indexShift;
|
||||
u8* m_readBuffer;
|
||||
u8 *m_zlibBuffer;
|
||||
u8* m_zlibBuffer;
|
||||
u32 m_zlibBufferFrame;
|
||||
u32 *m_index;
|
||||
u32* m_index;
|
||||
u64 m_totalSize;
|
||||
// The actual source cso file handle.
|
||||
FILE* m_src;
|
||||
|
|
|
@ -24,7 +24,8 @@
|
|||
|
||||
#define CLAMP(val, minval, maxval) (std::min(maxval, std::max(minval, val)))
|
||||
|
||||
static s64 fsize(const wxString& filename) {
|
||||
static s64 fsize(const wxString& filename)
|
||||
{
|
||||
if (!wxFileName::FileExists(filename))
|
||||
return -1;
|
||||
|
||||
|
@ -43,17 +44,20 @@ static s64 fsize(const wxString& filename) {
|
|||
// - [GZIP_ID_LEN] GZIP_ID (no \0)
|
||||
// - [sizeof(Access)] index (should be allocated, contains various sizes)
|
||||
// - [rest] the indexed data points (should be allocated, index->list should then point to it)
|
||||
static Access* ReadIndexFromFile(const wxString& filename) {
|
||||
static Access* ReadIndexFromFile(const wxString& filename)
|
||||
{
|
||||
s64 size = fsize(filename);
|
||||
if (size <= 0) {
|
||||
if (size <= 0)
|
||||
{
|
||||
Console.Error(L"Error: Can't open index file: '%s'", WX_STR(filename));
|
||||
return 0;
|
||||
}
|
||||
std::ifstream infile(PX_wfilename(filename), std::ifstream::binary);
|
||||
|
||||
char fileId[GZIP_ID_LEN + 1] = { 0 };
|
||||
char fileId[GZIP_ID_LEN + 1] = {0};
|
||||
infile.read(fileId, GZIP_ID_LEN);
|
||||
if (wxString::From8BitData(GZIP_ID) != wxString::From8BitData(fileId)) {
|
||||
if (wxString::From8BitData(GZIP_ID) != wxString::From8BitData(fileId))
|
||||
{
|
||||
Console.Error(L"Error: Incompatible gzip index, please delete it manually: '%s'", WX_STR(filename));
|
||||
infile.close();
|
||||
return 0;
|
||||
|
@ -63,7 +67,8 @@ static Access* ReadIndexFromFile(const wxString& filename) {
|
|||
infile.read((char*)index, sizeof(Access));
|
||||
|
||||
s64 datasize = size - GZIP_ID_LEN - sizeof(Access);
|
||||
if (datasize != (s64)index->have * sizeof(Point)) {
|
||||
if (datasize != (s64)index->have * sizeof(Point))
|
||||
{
|
||||
Console.Error(L"Error: unexpected size of gzip index, please delete it manually: '%s'.", WX_STR(filename));
|
||||
infile.close();
|
||||
free(index);
|
||||
|
@ -77,8 +82,10 @@ static Access* ReadIndexFromFile(const wxString& filename) {
|
|||
return index;
|
||||
}
|
||||
|
||||
static void WriteIndexToFile(Access* index, const wxString filename) {
|
||||
if (wxFileName::FileExists(filename)) {
|
||||
static void WriteIndexToFile(Access* index, const wxString filename)
|
||||
{
|
||||
if (wxFileName::FileExists(filename))
|
||||
{
|
||||
Console.Warning(L"WARNING: Won't write index - file name exists (please delete it manually): '%s'", WX_STR(filename));
|
||||
return;
|
||||
}
|
||||
|
@ -95,9 +102,12 @@ static void WriteIndexToFile(Access* index, const wxString filename) {
|
|||
outfile.close();
|
||||
|
||||
// Verify
|
||||
if (fsize(filename) != (s64)GZIP_ID_LEN + sizeof(Access) + sizeof(Point) * index->have) {
|
||||
if (fsize(filename) != (s64)GZIP_ID_LEN + sizeof(Access) + sizeof(Point) * index->have)
|
||||
{
|
||||
Console.Warning(L"Warning: Can't write index file to disk: '%s'", WX_STR(filename));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLn(Color_Green, L"OK: Gzip quick access index file saved to disk: '%s'", WX_STR(filename));
|
||||
}
|
||||
}
|
||||
|
@ -112,8 +122,8 @@ static wxString INDEX_TEMPLATE_KEY(L"$(f)");
|
|||
// then it's relative to base (not to cwd)
|
||||
// No checks are performed if the result file name can be created.
|
||||
// If this proves useful, we can move it into Path:: . Right now there's no need.
|
||||
static wxString ApplyTemplate(const wxString &name, const wxDirName &base,
|
||||
const wxString &fileTemplate, const wxString &filename,
|
||||
static wxString ApplyTemplate(const wxString& name, const wxDirName& base,
|
||||
const wxString& fileTemplate, const wxString& filename,
|
||||
bool canEndWithKey)
|
||||
{
|
||||
wxString tem(fileTemplate);
|
||||
|
@ -169,7 +179,8 @@ static void TestTemplate(const wxDirName &base, const wxString &fname, bool canE
|
|||
}
|
||||
*/
|
||||
|
||||
static wxString iso2indexname(const wxString& isoname) {
|
||||
static wxString iso2indexname(const wxString& isoname)
|
||||
{
|
||||
//testTemplate(isoname);
|
||||
wxDirName appRoot = // TODO: have only one of this in PCSX2. Right now have few...
|
||||
(wxDirName)(wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath());
|
||||
|
@ -177,18 +188,21 @@ static wxString iso2indexname(const wxString& isoname) {
|
|||
return ApplyTemplate(L"gzip index", appRoot, g_Conf->GzipIsoIndexTemplate, isoname, false);
|
||||
}
|
||||
|
||||
GzippedFileReader::GzippedFileReader(void) :
|
||||
mBytesRead(0),
|
||||
m_pIndex(0),
|
||||
m_zstates(0),
|
||||
m_src(0),
|
||||
m_cache(GZFILE_CACHE_SIZE_MB) {
|
||||
GzippedFileReader::GzippedFileReader(void)
|
||||
: mBytesRead(0)
|
||||
, m_pIndex(0)
|
||||
, m_zstates(0)
|
||||
, m_src(0)
|
||||
, m_cache(GZFILE_CACHE_SIZE_MB)
|
||||
{
|
||||
m_blocksize = 2048;
|
||||
AsyncPrefetchReset();
|
||||
};
|
||||
|
||||
void GzippedFileReader::InitZstates() {
|
||||
if (m_zstates) {
|
||||
void GzippedFileReader::InitZstates()
|
||||
{
|
||||
if (m_zstates)
|
||||
{
|
||||
delete[] m_zstates;
|
||||
m_zstates = 0;
|
||||
}
|
||||
|
@ -201,11 +215,11 @@ void GzippedFileReader::InitZstates() {
|
|||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
void GzippedFileReader::AsyncPrefetchReset() {};
|
||||
void GzippedFileReader::AsyncPrefetchOpen() {};
|
||||
void GzippedFileReader::AsyncPrefetchClose() {};
|
||||
void GzippedFileReader::AsyncPrefetchChunk(PX_off_t dummy) {};
|
||||
void GzippedFileReader::AsyncPrefetchCancel() {};
|
||||
void GzippedFileReader::AsyncPrefetchReset(){};
|
||||
void GzippedFileReader::AsyncPrefetchOpen(){};
|
||||
void GzippedFileReader::AsyncPrefetchClose(){};
|
||||
void GzippedFileReader::AsyncPrefetchChunk(PX_off_t dummy){};
|
||||
void GzippedFileReader::AsyncPrefetchCancel(){};
|
||||
#else
|
||||
// AsyncPrefetch works as follows:
|
||||
// ater extracting a chunk from the compressed file, ask the OS to asynchronously
|
||||
|
@ -216,12 +230,14 @@ void GzippedFileReader::AsyncPrefetchCancel() {};
|
|||
// This procedure is frequently able to overcome seek time due to fragmentation of the
|
||||
// compressed file on disk without any meaningful penalty.
|
||||
// This system is only enabled for win32 where we have this async read request.
|
||||
void GzippedFileReader::AsyncPrefetchReset() {
|
||||
void GzippedFileReader::AsyncPrefetchReset()
|
||||
{
|
||||
hOverlappedFile = INVALID_HANDLE_VALUE;
|
||||
asyncInProgress = false;
|
||||
}
|
||||
|
||||
void GzippedFileReader::AsyncPrefetchOpen() {
|
||||
void GzippedFileReader::AsyncPrefetchOpen()
|
||||
{
|
||||
hOverlappedFile = CreateFile(
|
||||
m_filename,
|
||||
GENERIC_READ,
|
||||
|
@ -244,7 +260,8 @@ void GzippedFileReader::AsyncPrefetchClose()
|
|||
|
||||
void GzippedFileReader::AsyncPrefetchChunk(PX_off_t start)
|
||||
{
|
||||
if (hOverlappedFile == INVALID_HANDLE_VALUE || asyncInProgress) {
|
||||
if (hOverlappedFile == INVALID_HANDLE_VALUE || asyncInProgress)
|
||||
{
|
||||
Console.Warning(L"Unexpected file handle or progress state. Aborting prefetch.");
|
||||
return;
|
||||
}
|
||||
|
@ -268,7 +285,8 @@ void GzippedFileReader::AsyncPrefetchCancel()
|
|||
if (!asyncInProgress)
|
||||
return;
|
||||
|
||||
if (!CancelIo(hOverlappedFile)) {
|
||||
if (!CancelIo(hOverlappedFile))
|
||||
{
|
||||
Console.Warning("canceling gz prefetch failed. following prefetching will not work.");
|
||||
return;
|
||||
}
|
||||
|
@ -278,11 +296,13 @@ void GzippedFileReader::AsyncPrefetchCancel()
|
|||
#endif /* _WIN32 */
|
||||
|
||||
// TODO: do better than just checking existance and extension
|
||||
bool GzippedFileReader::CanHandle(const wxString& fileName) {
|
||||
bool GzippedFileReader::CanHandle(const wxString& fileName)
|
||||
{
|
||||
return wxFileName::FileExists(fileName) && fileName.Lower().EndsWith(L".gz");
|
||||
}
|
||||
|
||||
bool GzippedFileReader::OkIndex() {
|
||||
bool GzippedFileReader::OkIndex()
|
||||
{
|
||||
if (m_pIndex)
|
||||
return true;
|
||||
|
||||
|
@ -291,9 +311,11 @@ bool GzippedFileReader::OkIndex() {
|
|||
if (indexfile.length() == 0)
|
||||
return false; // iso2indexname(...) will print errors if it can't apply the template
|
||||
|
||||
if (wxFileName::FileExists(indexfile) && (m_pIndex = ReadIndexFromFile(indexfile))) {
|
||||
if (wxFileName::FileExists(indexfile) && (m_pIndex = ReadIndexFromFile(indexfile)))
|
||||
{
|
||||
Console.WriteLn(Color_Green, L"OK: Gzip quick access index read from disk: '%s'", WX_STR(indexfile));
|
||||
if (m_pIndex->span != GZFILE_SPAN_DEFAULT) {
|
||||
if (m_pIndex->span != GZFILE_SPAN_DEFAULT)
|
||||
{
|
||||
Console.Warning(L"Note: This index has %1.1f MB intervals, while the current default for new indexes is %1.1f MB.",
|
||||
(float)m_pIndex->span / 1024 / 1024, (float)GZFILE_SPAN_DEFAULT / 1024 / 1024);
|
||||
Console.Warning(L"It will work fine, but if you want to generate a new index with default intervals, delete this index file.");
|
||||
|
@ -306,16 +328,19 @@ bool GzippedFileReader::OkIndex() {
|
|||
// No valid index file. Generate an index
|
||||
Console.Warning(L"This may take a while (but only once). Scanning compressed file to generate a quick access index...");
|
||||
|
||||
Access *index;
|
||||
Access* index;
|
||||
FILE* infile = PX_fopen_rb(m_filename);
|
||||
int len = build_index(infile, GZFILE_SPAN_DEFAULT, &index);
|
||||
printf("\n"); // build_index prints progress without \n's
|
||||
fclose(infile);
|
||||
|
||||
if (len >= 0) {
|
||||
if (len >= 0)
|
||||
{
|
||||
m_pIndex = index;
|
||||
WriteIndexToFile((Access*)m_pIndex, indexfile);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Error(L"ERROR (%d): index could not be generated for file '%s'", len, WX_STR(m_filename));
|
||||
free_index(index);
|
||||
InitZstates();
|
||||
|
@ -326,10 +351,12 @@ bool GzippedFileReader::OkIndex() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GzippedFileReader::Open(const wxString& fileName) {
|
||||
bool GzippedFileReader::Open(const wxString& fileName)
|
||||
{
|
||||
Close();
|
||||
m_filename = fileName;
|
||||
if (!(m_src = PX_fopen_rb(m_filename)) || !CanHandle(fileName) || !OkIndex()) {
|
||||
if (!(m_src = PX_fopen_rb(m_filename)) || !CanHandle(fileName) || !OkIndex())
|
||||
{
|
||||
Close();
|
||||
return false;
|
||||
};
|
||||
|
@ -338,13 +365,15 @@ bool GzippedFileReader::Open(const wxString& fileName) {
|
|||
return true;
|
||||
};
|
||||
|
||||
void GzippedFileReader::BeginRead(void* pBuffer, uint sector, uint count) {
|
||||
void GzippedFileReader::BeginRead(void* pBuffer, uint sector, uint count)
|
||||
{
|
||||
// No a-sync support yet, implement as sync
|
||||
mBytesRead = ReadSync(pBuffer, sector, count);
|
||||
return;
|
||||
};
|
||||
|
||||
int GzippedFileReader::FinishRead(void) {
|
||||
int GzippedFileReader::FinishRead(void)
|
||||
{
|
||||
int res = mBytesRead;
|
||||
mBytesRead = -1;
|
||||
return res;
|
||||
|
@ -353,7 +382,8 @@ int GzippedFileReader::FinishRead(void) {
|
|||
#define PTT clock_t
|
||||
#define NOW() (clock() / (CLOCKS_PER_SEC / 1000))
|
||||
|
||||
int GzippedFileReader::ReadSync(void* pBuffer, uint sector, uint count) {
|
||||
int GzippedFileReader::ReadSync(void* pBuffer, uint sector, uint count)
|
||||
{
|
||||
PX_off_t offset = (s64)sector * m_blocksize + m_dataoffset;
|
||||
int bytesToRead = count * m_blocksize;
|
||||
int res = _ReadSync(pBuffer, offset, bytesToRead);
|
||||
|
@ -363,7 +393,8 @@ int GzippedFileReader::ReadSync(void* pBuffer, uint sector, uint count) {
|
|||
}
|
||||
|
||||
// If we have a valid and adequate zstate for this span, use it, else, use the index
|
||||
PX_off_t GzippedFileReader::GetOptimalExtractionStart(PX_off_t offset) {
|
||||
PX_off_t GzippedFileReader::GetOptimalExtractionStart(PX_off_t offset)
|
||||
{
|
||||
int span = m_pIndex->span;
|
||||
Czstate& cstate = m_zstates[offset / span];
|
||||
PX_off_t stateOffset = cstate.state.isValid ? cstate.state.out_offset : 0;
|
||||
|
@ -378,7 +409,8 @@ PX_off_t GzippedFileReader::GetOptimalExtractionStart(PX_off_t offset) {
|
|||
return span * (offset / span); // index direct access boundaries
|
||||
}
|
||||
|
||||
int GzippedFileReader::_ReadSync(void* pBuffer, PX_off_t offset, uint bytesToRead) {
|
||||
int GzippedFileReader::_ReadSync(void* pBuffer, PX_off_t offset, uint bytesToRead)
|
||||
{
|
||||
if (!OkIndex())
|
||||
return -1;
|
||||
|
||||
|
@ -387,7 +419,8 @@ int GzippedFileReader::_ReadSync(void* pBuffer, PX_off_t offset, uint bytesToRea
|
|||
|
||||
// Split request to GZFILE_READ_CHUNK_SIZE chunks at GZFILE_READ_CHUNK_SIZE boundaries
|
||||
uint maxInChunk = GZFILE_READ_CHUNK_SIZE - offset % GZFILE_READ_CHUNK_SIZE;
|
||||
if (bytesToRead > maxInChunk) {
|
||||
if (bytesToRead > maxInChunk)
|
||||
{
|
||||
int first = _ReadSync(pBuffer, offset, maxInChunk);
|
||||
if (first != (int)maxInChunk)
|
||||
return first; // EOF or failure
|
||||
|
@ -416,7 +449,8 @@ int GzippedFileReader::_ReadSync(void* pBuffer, PX_off_t offset, uint bytesToRea
|
|||
int spanix = extractOffset / span;
|
||||
AsyncPrefetchCancel();
|
||||
res = extract(m_src, m_pIndex, extractOffset, extracted, size, &(m_zstates[spanix].state));
|
||||
if (res < 0) {
|
||||
if (res < 0)
|
||||
{
|
||||
free(extracted);
|
||||
return res;
|
||||
}
|
||||
|
@ -424,7 +458,8 @@ int GzippedFileReader::_ReadSync(void* pBuffer, PX_off_t offset, uint bytesToRea
|
|||
|
||||
int copied = ChunksCache::CopyAvailable(extracted, extractOffset, res, pBuffer, offset, bytesToRead);
|
||||
|
||||
if (m_zstates[spanix].state.isValid && (extractOffset + res) / span != offset / span) {
|
||||
if (m_zstates[spanix].state.isValid && (extractOffset + res) / span != offset / span)
|
||||
{
|
||||
// The state no longer matches this span.
|
||||
// move the state to the appropriate span because it will be faster than using the index
|
||||
int targetix = (extractOffset + res) / span;
|
||||
|
@ -440,8 +475,10 @@ int GzippedFileReader::_ReadSync(void* pBuffer, PX_off_t offset, uint bytesToRea
|
|||
|
||||
if (size <= GZFILE_READ_CHUNK_SIZE)
|
||||
m_cache.Take(extracted, extractOffset, res, size);
|
||||
else { // split into cacheable chunks
|
||||
for (int i = 0; i < size; i += GZFILE_READ_CHUNK_SIZE) {
|
||||
else
|
||||
{ // split into cacheable chunks
|
||||
for (int i = 0; i < size; i += GZFILE_READ_CHUNK_SIZE)
|
||||
{
|
||||
int available = CLAMP(res - i, 0, GZFILE_READ_CHUNK_SIZE);
|
||||
void* chunk = available ? malloc(available) : 0;
|
||||
if (available)
|
||||
|
@ -462,9 +499,11 @@ int GzippedFileReader::_ReadSync(void* pBuffer, PX_off_t offset, uint bytesToRea
|
|||
return copied;
|
||||
}
|
||||
|
||||
void GzippedFileReader::Close() {
|
||||
void GzippedFileReader::Close()
|
||||
{
|
||||
m_filename.Empty();
|
||||
if (m_pIndex) {
|
||||
if (m_pIndex)
|
||||
{
|
||||
free_index((Access*)m_pIndex);
|
||||
m_pIndex = 0;
|
||||
}
|
||||
|
@ -472,7 +511,8 @@ void GzippedFileReader::Close() {
|
|||
InitZstates(); // results in delete because no index
|
||||
m_cache.Clear();
|
||||
|
||||
if (m_src) {
|
||||
if (m_src)
|
||||
{
|
||||
fclose(m_src);
|
||||
m_src = 0;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ typedef struct zstate Zstate;
|
|||
class GzippedFileReader : public AsyncFileReader
|
||||
{
|
||||
DeclareNoncopyableObject(GzippedFileReader);
|
||||
|
||||
public:
|
||||
GzippedFileReader(void);
|
||||
|
||||
|
@ -40,11 +41,12 @@ public:
|
|||
|
||||
virtual void BeginRead(void* pBuffer, uint sector, uint count);
|
||||
virtual int FinishRead(void);
|
||||
virtual void CancelRead(void) {};
|
||||
virtual void CancelRead(void){};
|
||||
|
||||
virtual void Close(void);
|
||||
|
||||
virtual uint GetBlockCount(void) const {
|
||||
virtual uint GetBlockCount(void) const
|
||||
{
|
||||
// type and formula copied from FlatFileReader
|
||||
// FIXME? : Shouldn't it be uint and (size - m_dataoffset) / m_blocksize ?
|
||||
return (int)((m_pIndex ? m_pIndex->uncompressed_size : 0) / m_blocksize);
|
||||
|
@ -52,12 +54,15 @@ public:
|
|||
|
||||
virtual void SetBlockSize(uint bytes) { m_blocksize = bytes; }
|
||||
virtual void SetDataOffset(int bytes) { m_dataoffset = bytes; }
|
||||
|
||||
private:
|
||||
class Czstate {
|
||||
class Czstate
|
||||
{
|
||||
public:
|
||||
Czstate() { state.isValid = 0; };
|
||||
~Czstate() { Kill(); };
|
||||
void Kill() {
|
||||
void Kill()
|
||||
{
|
||||
if (state.isValid)
|
||||
inflateEnd(&state.strm);
|
||||
state.isValid = 0;
|
||||
|
|
|
@ -22,14 +22,20 @@
|
|||
|
||||
static const char* nameFromType(int type)
|
||||
{
|
||||
switch(type)
|
||||
switch (type)
|
||||
{
|
||||
case ISOTYPE_CD: return "CD";
|
||||
case ISOTYPE_DVD: return "DVD";
|
||||
case ISOTYPE_AUDIO: return "Audio CD";
|
||||
case ISOTYPE_DVDDL: return "DVD9 (dual-layer)";
|
||||
case ISOTYPE_ILLEGAL: return "Illegal media";
|
||||
default: return "Unknown or corrupt";
|
||||
case ISOTYPE_CD:
|
||||
return "CD";
|
||||
case ISOTYPE_DVD:
|
||||
return "DVD";
|
||||
case ISOTYPE_AUDIO:
|
||||
return "Audio CD";
|
||||
case ISOTYPE_DVDDL:
|
||||
return "DVD9 (dual-layer)";
|
||||
case ISOTYPE_ILLEGAL:
|
||||
return "Illegal media";
|
||||
default:
|
||||
return "Unknown or corrupt";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,7 +51,7 @@ int InputIsoFile::ReadSync(u8* dst, uint lsn)
|
|||
return -1;
|
||||
}
|
||||
|
||||
return m_reader->ReadSync(dst+m_blockofs, lsn, 1);
|
||||
return m_reader->ReadSync(dst + m_blockofs, lsn, 1);
|
||||
}
|
||||
|
||||
void InputIsoFile::BeginRead2(uint lsn)
|
||||
|
@ -60,7 +66,7 @@ void InputIsoFile::BeginRead2(uint lsn)
|
|||
return;
|
||||
}
|
||||
|
||||
if(lsn >= m_read_lsn && lsn < (m_read_lsn+m_read_count))
|
||||
if (lsn >= m_read_lsn && lsn < (m_read_lsn + m_read_count))
|
||||
{
|
||||
// Already buffered
|
||||
return;
|
||||
|
@ -69,7 +75,7 @@ void InputIsoFile::BeginRead2(uint lsn)
|
|||
m_read_lsn = lsn;
|
||||
m_read_count = 1;
|
||||
|
||||
if(ReadUnit > 1)
|
||||
if (ReadUnit > 1)
|
||||
{
|
||||
//m_read_lsn = lsn - (lsn % ReadUnit);
|
||||
|
||||
|
@ -93,12 +99,12 @@ int InputIsoFile::FinishRead3(u8* dst, uint mode)
|
|||
int length = 0;
|
||||
int ret = 0;
|
||||
|
||||
if(m_read_inprogress)
|
||||
if (m_read_inprogress)
|
||||
{
|
||||
ret = m_reader->FinishRead();
|
||||
m_read_inprogress = false;
|
||||
|
||||
if(ret < 0)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -128,7 +134,7 @@ int InputIsoFile::FinishRead3(u8* dst, uint mode)
|
|||
|
||||
int diff = m_blockofs - _offset;
|
||||
int ndiff = 0;
|
||||
if(diff > 0)
|
||||
if (diff > 0)
|
||||
{
|
||||
memset(dst, 0, diff);
|
||||
_offset = m_blockofs;
|
||||
|
@ -188,7 +194,7 @@ void InputIsoFile::_init()
|
|||
//
|
||||
// Note that this is a member method, and that it will clobber any existing ISO state.
|
||||
// (assertions are generated in debug mode if the object state is not already closed).
|
||||
bool InputIsoFile::Test( const wxString& srcfile )
|
||||
bool InputIsoFile::Test(const wxString& srcfile)
|
||||
{
|
||||
Close();
|
||||
m_filename = srcfile;
|
||||
|
@ -196,7 +202,7 @@ bool InputIsoFile::Test( const wxString& srcfile )
|
|||
return Open(srcfile, true);
|
||||
}
|
||||
|
||||
bool InputIsoFile::Open( const wxString& srcfile, bool testOnly )
|
||||
bool InputIsoFile::Open(const wxString& srcfile, bool testOnly)
|
||||
{
|
||||
Close();
|
||||
m_filename = srcfile;
|
||||
|
@ -227,7 +233,7 @@ bool InputIsoFile::Open( const wxString& srcfile, bool testOnly )
|
|||
{
|
||||
delete m_reader;
|
||||
|
||||
BlockdumpFileReader *bdr = new BlockdumpFileReader();
|
||||
BlockdumpFileReader* bdr = new BlockdumpFileReader();
|
||||
bdr->Open(m_filename);
|
||||
|
||||
m_blockofs = bdr->GetBlockOffset();
|
||||
|
@ -240,7 +246,7 @@ bool InputIsoFile::Open( const wxString& srcfile, bool testOnly )
|
|||
|
||||
bool detected = Detect();
|
||||
|
||||
if(testOnly)
|
||||
if (testOnly)
|
||||
return detected;
|
||||
|
||||
if (!detected)
|
||||
|
@ -248,7 +254,7 @@ bool InputIsoFile::Open( const wxString& srcfile, bool testOnly )
|
|||
.SetUserMsg(_("Unrecognized ISO image file format"))
|
||||
.SetDiagMsg(L"ISO mounting failed: PCSX2 is unable to identify the ISO image type.");
|
||||
|
||||
if(!isBlockdump && !isCompressed)
|
||||
if (!isBlockdump && !isCompressed)
|
||||
{
|
||||
ReadUnit = MaxReadUnit;
|
||||
|
||||
|
@ -270,10 +276,10 @@ bool InputIsoFile::Open( const wxString& srcfile, bool testOnly )
|
|||
|
||||
Console.WriteLn("Image type = %s", nameFromType(m_type));
|
||||
//Console.WriteLn("Fileparts = %u", m_numparts); // Pointless print, it's 1 unless it says otherwise above
|
||||
DevCon.WriteLn ("blocks = %u", m_blocks);
|
||||
DevCon.WriteLn ("offset = %d", m_offset);
|
||||
DevCon.WriteLn ("blocksize = %u", m_blocksize);
|
||||
DevCon.WriteLn ("blockoffset = %d", m_blockofs);
|
||||
DevCon.WriteLn("blocks = %u", m_blocks);
|
||||
DevCon.WriteLn("offset = %d", m_offset);
|
||||
DevCon.WriteLn("blocksize = %u", m_blocksize);
|
||||
DevCon.WriteLn("blockoffset = %d", m_blockofs);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -302,13 +308,13 @@ bool InputIsoFile::tryIsoType(u32 _size, s32 _offset, s32 _blockofs)
|
|||
m_reader->SetDataOffset(_offset);
|
||||
m_reader->SetBlockSize(_size);
|
||||
|
||||
if(ReadSync(buf, 16) < 0)
|
||||
if (ReadSync(buf, 16) < 0)
|
||||
return false;
|
||||
|
||||
if (strncmp((char*)(buf+25), "CD001", 5)) // Not ISO 9660 compliant
|
||||
if (strncmp((char*)(buf + 25), "CD001", 5)) // Not ISO 9660 compliant
|
||||
return false;
|
||||
|
||||
m_type = (*(u16*)(buf+190) == 2048) ? ISOTYPE_CD : ISOTYPE_DVD;
|
||||
m_type = (*(u16*)(buf + 190) == 2048) ? ISOTYPE_CD : ISOTYPE_DVD;
|
||||
|
||||
return true; // We can deal with this.
|
||||
}
|
||||
|
@ -318,7 +324,7 @@ bool InputIsoFile::tryIsoType(u32 _size, s32 _offset, s32 _blockofs)
|
|||
//
|
||||
//
|
||||
// Returns true if the image is valid/known/supported, or false if not (type == ISOTYPE_ILLEGAL).
|
||||
bool InputIsoFile::Detect( bool readType )
|
||||
bool InputIsoFile::Detect(bool readType)
|
||||
{
|
||||
m_type = ISOTYPE_ILLEGAL;
|
||||
|
||||
|
@ -335,18 +341,28 @@ bool InputIsoFile::Detect( bool readType )
|
|||
|
||||
m_blocks = 17;
|
||||
|
||||
if (tryIsoType(2048, 0, 24)) return true; // ISO 2048
|
||||
if (tryIsoType(2336, 0, 16)) return true; // RAW 2336
|
||||
if (tryIsoType(2352, 0, 0)) return true; // RAW 2352
|
||||
if (tryIsoType(2448, 0, 0)) return true; // RAWQ 2448
|
||||
if (tryIsoType(2048, 0, 24))
|
||||
return true; // ISO 2048
|
||||
if (tryIsoType(2336, 0, 16))
|
||||
return true; // RAW 2336
|
||||
if (tryIsoType(2352, 0, 0))
|
||||
return true; // RAW 2352
|
||||
if (tryIsoType(2448, 0, 0))
|
||||
return true; // RAWQ 2448
|
||||
|
||||
if (tryIsoType(2048, 150 * 2048, 24)) return true; // NERO ISO 2048
|
||||
if (tryIsoType(2352, 150 * 2048, 0)) return true; // NERO RAW 2352
|
||||
if (tryIsoType(2448, 150 * 2048, 0)) return true; // NERO RAWQ 2448
|
||||
if (tryIsoType(2048, 150 * 2048, 24))
|
||||
return true; // NERO ISO 2048
|
||||
if (tryIsoType(2352, 150 * 2048, 0))
|
||||
return true; // NERO RAW 2352
|
||||
if (tryIsoType(2448, 150 * 2048, 0))
|
||||
return true; // NERO RAWQ 2448
|
||||
|
||||
if (tryIsoType(2048, -8, 24)) return true; // ISO 2048
|
||||
if (tryIsoType(2352, -8, 0)) return true; // RAW 2352
|
||||
if (tryIsoType(2448, -8, 0)) return true; // RAWQ 2448
|
||||
if (tryIsoType(2048, -8, 24))
|
||||
return true; // ISO 2048
|
||||
if (tryIsoType(2352, -8, 0))
|
||||
return true; // RAW 2352
|
||||
if (tryIsoType(2448, -8, 0))
|
||||
return true; // RAWQ 2448
|
||||
|
||||
m_offset = 0;
|
||||
m_blocksize = CD_FRAMESIZE_RAW;
|
||||
|
|
|
@ -40,7 +40,7 @@ public:
|
|||
bool IsFile(const wxString& filePath) const;
|
||||
bool IsDir(const wxString& filePath) const;
|
||||
|
||||
u32 GetFileSize( const wxString& filePath ) const;
|
||||
u32 GetFileSize(const wxString& filePath) const;
|
||||
|
||||
IsoFileDescriptor FindFile(const wxString& filePath) const;
|
||||
|
||||
|
|
|
@ -30,13 +30,17 @@
|
|||
|
||||
wxString IsoDirectory::FStype_ToString() const
|
||||
{
|
||||
switch( m_fstype )
|
||||
switch (m_fstype)
|
||||
{
|
||||
case FStype_ISO9660: return L"ISO9660"; break;
|
||||
case FStype_Joliet: return L"Joliet"; break;
|
||||
case FStype_ISO9660:
|
||||
return L"ISO9660";
|
||||
break;
|
||||
case FStype_Joliet:
|
||||
return L"Joliet";
|
||||
break;
|
||||
}
|
||||
|
||||
return wxsFormat( L"Unrecognized Code (0x%x)", m_fstype );
|
||||
return wxsFormat(L"Unrecognized Code (0x%x)", m_fstype);
|
||||
}
|
||||
|
||||
// Used to load the Root directory from an image
|
||||
|
@ -50,27 +54,27 @@ IsoDirectory::IsoDirectory(SectorSource& r)
|
|||
|
||||
m_fstype = FStype_ISO9660;
|
||||
|
||||
while( !done )
|
||||
while (!done)
|
||||
{
|
||||
u8 sector[2048];
|
||||
internalReader.readSector(sector,i);
|
||||
if( memcmp( §or[1], "CD001", 5 ) == 0 )
|
||||
internalReader.readSector(sector, i);
|
||||
if (memcmp(§or[1], "CD001", 5) == 0)
|
||||
{
|
||||
switch (sector[0])
|
||||
{
|
||||
case 0:
|
||||
DevCon.WriteLn( Color_Green, "(IsoFS) Block 0x%x: Boot partition info.", i );
|
||||
DevCon.WriteLn(Color_Green, "(IsoFS) Block 0x%x: Boot partition info.", i);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
DevCon.WriteLn( "(IsoFS) Block 0x%x: Primary partition info.", i );
|
||||
rootDirEntry.Load( sector+156, 38 );
|
||||
DevCon.WriteLn("(IsoFS) Block 0x%x: Primary partition info.", i);
|
||||
rootDirEntry.Load(sector + 156, 38);
|
||||
isValid = true;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Probably means Joliet (long filenames support), which PCSX2 doesn't care about.
|
||||
DevCon.WriteLn( Color_Green, "(IsoFS) Block 0x%x: Extended partition info.", i );
|
||||
DevCon.WriteLn(Color_Green, "(IsoFS) Block 0x%x: Extended partition info.", i);
|
||||
m_fstype = FStype_Joliet;
|
||||
break;
|
||||
|
||||
|
@ -80,26 +84,26 @@ IsoDirectory::IsoDirectory(SectorSource& r)
|
|||
break;
|
||||
|
||||
default:
|
||||
Console.Error( "(IsoFS) Unknown partition type ID=%d, encountered at block 0x%x", sector[0], i );
|
||||
Console.Error("(IsoFS) Unknown partition type ID=%d, encountered at block 0x%x", sector[0], i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sector[9] = 0;
|
||||
Console.Error( "(IsoFS) Invalid partition descriptor encountered at block 0x%x: '%s'", i, §or[1] );
|
||||
Console.Error("(IsoFS) Invalid partition descriptor encountered at block 0x%x: '%s'", i, §or[1]);
|
||||
break; // if no valid root partition was found, an exception will be thrown below.
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
if( !isValid )
|
||||
if (!isValid)
|
||||
throw Exception::FileNotFound(L"IsoFileSystem") // FIXME: Should report the name of the ISO here...
|
||||
.SetDiagMsg(L"IsoFS could not find the root directory on the ISO image.");
|
||||
|
||||
DevCon.WriteLn( L"(IsoFS) Filesystem is " + FStype_ToString() );
|
||||
Init( rootDirEntry );
|
||||
DevCon.WriteLn(L"(IsoFS) Filesystem is " + FStype_ToString());
|
||||
Init(rootDirEntry);
|
||||
}
|
||||
|
||||
// Used to load a specific directory from a file descriptor
|
||||
|
@ -113,7 +117,7 @@ IsoDirectory::IsoDirectory(SectorSource& r, IsoFileDescriptor directoryEntry)
|
|||
void IsoDirectory::Init(const IsoFileDescriptor& directoryEntry)
|
||||
{
|
||||
// parse directory sector
|
||||
IsoFile dataStream (internalReader, directoryEntry);
|
||||
IsoFile dataStream(internalReader, directoryEntry);
|
||||
|
||||
files.clear();
|
||||
|
||||
|
@ -121,18 +125,18 @@ void IsoDirectory::Init(const IsoFileDescriptor& directoryEntry)
|
|||
|
||||
u8 b[257];
|
||||
|
||||
while(remainingSize>=4) // hm hack :P
|
||||
while (remainingSize >= 4) // hm hack :P
|
||||
{
|
||||
b[0] = dataStream.read<u8>();
|
||||
|
||||
if(b[0]==0)
|
||||
if (b[0] == 0)
|
||||
{
|
||||
break; // or continue?
|
||||
}
|
||||
|
||||
remainingSize -= b[0];
|
||||
|
||||
dataStream.read(b+1, b[0]-1);
|
||||
dataStream.read(b + 1, b[0] - 1);
|
||||
|
||||
files.push_back(IsoFileDescriptor(b, b[0]));
|
||||
}
|
||||
|
@ -147,9 +151,10 @@ const IsoFileDescriptor& IsoDirectory::GetEntry(int index) const
|
|||
|
||||
int IsoDirectory::GetIndexOf(const wxString& fileName) const
|
||||
{
|
||||
for(unsigned int i=0;i<files.size();i++)
|
||||
for (unsigned int i = 0; i < files.size(); i++)
|
||||
{
|
||||
if(files[i].name == fileName) return i;
|
||||
if (files[i].name == fileName)
|
||||
return i;
|
||||
}
|
||||
|
||||
throw Exception::FileNotFound(fileName);
|
||||
|
@ -162,11 +167,11 @@ const IsoFileDescriptor& IsoDirectory::GetEntry(const wxString& fileName) const
|
|||
|
||||
IsoFileDescriptor IsoDirectory::FindFile(const wxString& filePath) const
|
||||
{
|
||||
pxAssert( !filePath.IsEmpty() );
|
||||
pxAssert(!filePath.IsEmpty());
|
||||
|
||||
// wxWidgets DOS-style parser should work fine for ISO 9660 path names. Only practical difference
|
||||
// is case sensitivity, and that won't matter for path splitting.
|
||||
wxFileName parts( filePath, wxPATH_DOS );
|
||||
wxFileName parts(filePath, wxPATH_DOS);
|
||||
IsoFileDescriptor info;
|
||||
const IsoDirectory* dir = this;
|
||||
std::unique_ptr<IsoDirectory> deleteme;
|
||||
|
@ -174,16 +179,17 @@ IsoFileDescriptor IsoDirectory::FindFile(const wxString& filePath) const
|
|||
// walk through path ("." and ".." entries are in the directories themselves, so even if the
|
||||
// path included . and/or .., it still works)
|
||||
|
||||
for(uint i=0; i<parts.GetDirCount(); ++i)
|
||||
for (uint i = 0; i < parts.GetDirCount(); ++i)
|
||||
{
|
||||
info = dir->GetEntry(parts.GetDirs()[i]);
|
||||
if(info.IsFile()) throw Exception::FileNotFound( filePath );
|
||||
if (info.IsFile())
|
||||
throw Exception::FileNotFound(filePath);
|
||||
|
||||
deleteme.reset(new IsoDirectory(internalReader, info));
|
||||
dir = deleteme.get();
|
||||
}
|
||||
|
||||
if( !parts.GetFullName().IsEmpty() )
|
||||
if (!parts.GetFullName().IsEmpty())
|
||||
info = dir->GetEntry(parts.GetFullName());
|
||||
|
||||
return info;
|
||||
|
@ -191,19 +197,21 @@ IsoFileDescriptor IsoDirectory::FindFile(const wxString& filePath) const
|
|||
|
||||
bool IsoDirectory::IsFile(const wxString& filePath) const
|
||||
{
|
||||
if( filePath.IsEmpty() ) return false;
|
||||
return (FindFile(filePath).flags&2) != 2;
|
||||
if (filePath.IsEmpty())
|
||||
return false;
|
||||
return (FindFile(filePath).flags & 2) != 2;
|
||||
}
|
||||
|
||||
bool IsoDirectory::IsDir(const wxString& filePath) const
|
||||
{
|
||||
if( filePath.IsEmpty() ) return false;
|
||||
return (FindFile(filePath).flags&2) == 2;
|
||||
if (filePath.IsEmpty())
|
||||
return false;
|
||||
return (FindFile(filePath).flags & 2) == 2;
|
||||
}
|
||||
|
||||
u32 IsoDirectory::GetFileSize( const wxString& filePath ) const
|
||||
u32 IsoDirectory::GetFileSize(const wxString& filePath) const
|
||||
{
|
||||
return FindFile( filePath ).size;
|
||||
return FindFile(filePath).size;
|
||||
}
|
||||
|
||||
IsoFileDescriptor::IsoFileDescriptor()
|
||||
|
@ -216,10 +224,10 @@ IsoFileDescriptor::IsoFileDescriptor()
|
|||
|
||||
IsoFileDescriptor::IsoFileDescriptor(const u8* data, int length)
|
||||
{
|
||||
Load( data, length );
|
||||
Load(data, length);
|
||||
}
|
||||
|
||||
void IsoFileDescriptor::Load( const u8* data, int length )
|
||||
void IsoFileDescriptor::Load(const u8* data, int length)
|
||||
{
|
||||
lba = (u32&)data[2];
|
||||
size = (u32&)data[10];
|
||||
|
@ -236,25 +244,30 @@ void IsoFileDescriptor::Load( const u8* data, int length )
|
|||
|
||||
int fileNameLength = data[32];
|
||||
|
||||
if(fileNameLength==1)
|
||||
if (fileNameLength == 1)
|
||||
{
|
||||
u8 c = data[33];
|
||||
|
||||
switch(c)
|
||||
switch (c)
|
||||
{
|
||||
case 0: name = L"."; break;
|
||||
case 1: name = L".."; break;
|
||||
default: name = (wxChar)c;
|
||||
case 0:
|
||||
name = L".";
|
||||
break;
|
||||
case 1:
|
||||
name = L"..";
|
||||
break;
|
||||
default:
|
||||
name = (wxChar)c;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// copy string and up-convert from ascii to wxChar
|
||||
|
||||
const u8* fnsrc = data+33;
|
||||
const u8* fnend = fnsrc+fileNameLength;
|
||||
const u8* fnsrc = data + 33;
|
||||
const u8* fnend = fnsrc + fileNameLength;
|
||||
|
||||
while( fnsrc != fnend )
|
||||
while (fnsrc != fnend)
|
||||
{
|
||||
name += (wxChar)*fnsrc;
|
||||
++fnsrc;
|
||||
|
|
|
@ -23,4 +23,3 @@ struct ISoFileDescriptor;
|
|||
#include "IsoFileDescriptor.h"
|
||||
#include "IsoDirectory.h"
|
||||
#include "IsoFile.h"
|
||||
|
||||
|
|
|
@ -25,13 +25,13 @@ IsoFSCDVD::IsoFSCDVD()
|
|||
|
||||
bool IsoFSCDVD::readSector(unsigned char* buffer, int lba)
|
||||
{
|
||||
return DoCDVDreadSector(buffer,lba,CDVD_MODE_2048)>=0;
|
||||
return DoCDVDreadSector(buffer, lba, CDVD_MODE_2048) >= 0;
|
||||
}
|
||||
|
||||
int IsoFSCDVD::getNumSectors()
|
||||
{
|
||||
cdvdTD td;
|
||||
CDVD->getTD(0,&td);
|
||||
CDVD->getTD(0, &td);
|
||||
|
||||
return td.lsn;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include "SectorSource.h"
|
||||
|
||||
class IsoFSCDVD: public SectorSource
|
||||
class IsoFSCDVD : public SectorSource
|
||||
{
|
||||
public:
|
||||
IsoFSCDVD();
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
*/
|
||||
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include "IsoFS.h"
|
||||
#include "IsoFile.h"
|
||||
|
@ -47,9 +47,9 @@ void IsoFile::Init()
|
|||
currentSectorNumber = fileEntry.lba;
|
||||
currentOffset = 0;
|
||||
sectorOffset = 0;
|
||||
maxOffset = std::max<u32>( 0, fileEntry.size );
|
||||
maxOffset = std::max<u32>(0, fileEntry.size);
|
||||
|
||||
if(maxOffset > 0)
|
||||
if (maxOffset > 0)
|
||||
internalReader.readSector(currentSector, currentSectorNumber);
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ u32 IsoFile::seek(u32 absoffset)
|
|||
int oldSectorNumber = currentSectorNumber;
|
||||
int newSectorNumber = fileEntry.lba + (int)(endOffset / sectorLength);
|
||||
|
||||
if(oldSectorNumber != newSectorNumber)
|
||||
if (oldSectorNumber != newSectorNumber)
|
||||
{
|
||||
internalReader.readSector(currentSector, newSectorNumber);
|
||||
}
|
||||
|
@ -76,19 +76,19 @@ u32 IsoFile::seek(u32 absoffset)
|
|||
// and fileLength.
|
||||
u32 IsoFile::seek(s64 offset, wxSeekMode ref_position)
|
||||
{
|
||||
switch( ref_position )
|
||||
switch (ref_position)
|
||||
{
|
||||
case wxFromStart:
|
||||
pxAssertDev( offset >= 0 && offset <= (s64)ULONG_MAX, "Invalid seek position from start." );
|
||||
pxAssertDev(offset >= 0 && offset <= (s64)ULONG_MAX, "Invalid seek position from start.");
|
||||
return seek(offset);
|
||||
|
||||
case wxFromCurrent:
|
||||
// truncate negative values to zero, and positive values to 4gb
|
||||
return seek( std::min( std::max<s64>(0, (s64)currentOffset+offset), (s64)ULONG_MAX ) );
|
||||
return seek(std::min(std::max<s64>(0, (s64)currentOffset + offset), (s64)ULONG_MAX));
|
||||
|
||||
case wxFromEnd:
|
||||
// truncate negative values to zero, and positive values to 4gb
|
||||
return seek( std::min( std::max<s64>(0, (s64)fileEntry.size+offset), (s64)ULONG_MAX ) );
|
||||
return seek(std::min(std::max<s64>(0, (s64)fileEntry.size + offset), (s64)ULONG_MAX));
|
||||
|
||||
jNO_DEFAULT;
|
||||
}
|
||||
|
@ -106,9 +106,10 @@ s32 IsoFile::skip(s32 n)
|
|||
{
|
||||
s32 oldOffset = currentOffset;
|
||||
|
||||
if (n<0) return 0;
|
||||
if (n < 0)
|
||||
return 0;
|
||||
|
||||
seek(currentOffset+n);
|
||||
seek(currentOffset + n);
|
||||
|
||||
return currentOffset - oldOffset;
|
||||
}
|
||||
|
@ -136,7 +137,7 @@ void IsoFile::makeDataAvailable()
|
|||
|
||||
u8 IsoFile::readByte()
|
||||
{
|
||||
if(currentOffset >= maxOffset)
|
||||
if (currentOffset >= maxOffset)
|
||||
throw Exception::EndOfStream();
|
||||
|
||||
makeDataAvailable();
|
||||
|
@ -154,7 +155,7 @@ int IsoFile::internalRead(void* dest, int off, int len)
|
|||
size_t slen = len;
|
||||
if (slen > (maxOffset - currentOffset))
|
||||
{
|
||||
slen = (int) (maxOffset - currentOffset);
|
||||
slen = (int)(maxOffset - currentOffset);
|
||||
}
|
||||
|
||||
memcpy((u8*)dest + off, currentSector + sectorOffset, slen);
|
||||
|
@ -169,10 +170,11 @@ int IsoFile::internalRead(void* dest, int off, int len)
|
|||
// returns the number of bytes actually read.
|
||||
s32 IsoFile::read(void* dest, s32 len)
|
||||
{
|
||||
pxAssert( dest != NULL );
|
||||
pxAssert( len >= 0 ); // should we silent-fail on negative length reads? prolly not...
|
||||
pxAssert(dest != NULL);
|
||||
pxAssert(len >= 0); // should we silent-fail on negative length reads? prolly not...
|
||||
|
||||
if( len <= 0 ) return 0;
|
||||
if (len <= 0)
|
||||
return 0;
|
||||
|
||||
int off = 0;
|
||||
|
||||
|
@ -194,7 +196,8 @@ s32 IsoFile::read(void* dest, s32 len)
|
|||
}
|
||||
|
||||
// Read remaining, if any
|
||||
if (len > 0) {
|
||||
if (len > 0)
|
||||
{
|
||||
makeDataAvailable();
|
||||
int lastSector = internalRead(dest, off, len);
|
||||
totalLength += lastSector;
|
||||
|
@ -213,13 +216,13 @@ s32 IsoFile::read(void* dest, s32 len)
|
|||
std::string IsoFile::readLine()
|
||||
{
|
||||
std::string s;
|
||||
s.reserve( 512 );
|
||||
s.reserve(512);
|
||||
|
||||
while( !eof() )
|
||||
while (!eof())
|
||||
{
|
||||
u8 c = read<u8>();
|
||||
|
||||
if((c=='\n') || (c=='\r') || (c==0))
|
||||
if ((c == '\n') || (c == '\r') || (c == 0))
|
||||
break;
|
||||
|
||||
s += c;
|
||||
|
|
|
@ -56,15 +56,15 @@ public:
|
|||
std::string readLine();
|
||||
|
||||
// Tool to read a specific value type, including structs.
|
||||
template< class T >
|
||||
template <class T>
|
||||
T read()
|
||||
{
|
||||
if(sizeof(T)==1)
|
||||
if (sizeof(T) == 1)
|
||||
return (T)readByte();
|
||||
else
|
||||
{
|
||||
T t;
|
||||
read((u8*)&t,sizeof(t));
|
||||
read((u8*)&t, sizeof(t));
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ struct IsoFileDescriptor
|
|||
IsoFileDescriptor();
|
||||
IsoFileDescriptor(const u8* data, int length);
|
||||
|
||||
void Load( const u8* data, int length );
|
||||
void Load(const u8* data, int length);
|
||||
|
||||
bool IsFile() const { return !(flags & 2); }
|
||||
bool IsDir() const { return !IsFile(); }
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
class SectorSource
|
||||
{
|
||||
public:
|
||||
virtual int getNumSectors()=0;
|
||||
virtual bool readSector(unsigned char* buffer, int lba)=0;
|
||||
virtual int getNumSectors() = 0;
|
||||
virtual bool readSector(unsigned char* buffer, int lba) = 0;
|
||||
virtual ~SectorSource() = default;
|
||||
};
|
||||
|
|
|
@ -37,7 +37,7 @@ static const int CD_FRAMESIZE_RAW = 2448;
|
|||
// --------------------------------------------------------------------------------------
|
||||
class InputIsoFile
|
||||
{
|
||||
DeclareNoncopyableObject( InputIsoFile );
|
||||
DeclareNoncopyableObject(InputIsoFile);
|
||||
|
||||
static const uint MaxReadUnit = 128;
|
||||
|
||||
|
@ -80,10 +80,10 @@ public:
|
|||
return m_filename;
|
||||
}
|
||||
|
||||
bool Test( const wxString& srcfile );
|
||||
bool Open( const wxString& srcfile, bool testOnly = false );
|
||||
bool Test(const wxString& srcfile);
|
||||
bool Open(const wxString& srcfile, bool testOnly = false);
|
||||
void Close();
|
||||
bool Detect( bool readType=true );
|
||||
bool Detect(bool readType = true);
|
||||
|
||||
int ReadSync(u8* dst, uint lsn);
|
||||
|
||||
|
@ -99,7 +99,7 @@ protected:
|
|||
|
||||
class OutputIsoFile
|
||||
{
|
||||
DeclareNoncopyableObject( OutputIsoFile );
|
||||
DeclareNoncopyableObject(OutputIsoFile);
|
||||
|
||||
protected:
|
||||
wxString m_filename;
|
||||
|
@ -140,11 +140,11 @@ public:
|
|||
protected:
|
||||
void _init();
|
||||
|
||||
void WriteBuffer( const void* src, size_t size );
|
||||
void WriteBuffer(const void* src, size_t size);
|
||||
|
||||
template< typename T >
|
||||
void WriteValue( const T& data )
|
||||
template <typename T>
|
||||
void WriteValue(const T& data)
|
||||
{
|
||||
WriteBuffer( &data, sizeof(data) );
|
||||
WriteBuffer(&data, sizeof(data));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -34,7 +34,8 @@ std::vector<std::string> GetOpticalDriveList()
|
|||
|
||||
std::vector<std::string> drives;
|
||||
udev_enumerate* enumerate = udev_enumerate_new(udev_context);
|
||||
if (enumerate) {
|
||||
if (enumerate)
|
||||
{
|
||||
udev_enumerate_add_match_subsystem(enumerate, "block");
|
||||
udev_enumerate_add_match_property(enumerate, "ID_CDROM_DVD", "1");
|
||||
udev_enumerate_scan_devices(enumerate);
|
||||
|
@ -62,22 +63,26 @@ std::vector<std::string> GetOpticalDriveList()
|
|||
|
||||
void GetValidDrive(std::string& drive)
|
||||
{
|
||||
if (!drive.empty()) {
|
||||
if (!drive.empty())
|
||||
{
|
||||
#ifdef __linux__
|
||||
int fd = open(drive.c_str(), O_RDONLY | O_NONBLOCK);
|
||||
if (fd != -1) {
|
||||
if (fd != -1)
|
||||
{
|
||||
if (ioctl(fd, CDROM_GET_CAPABILITY, 0) == -1)
|
||||
drive.clear();
|
||||
close(fd);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
drive.clear();
|
||||
}
|
||||
#else
|
||||
drive.clear();
|
||||
#endif
|
||||
}
|
||||
if (drive.empty()) {
|
||||
if (drive.empty())
|
||||
{
|
||||
auto drives = GetOpticalDriveList();
|
||||
if (!drives.empty())
|
||||
drive = drives.front();
|
||||
|
|
|
@ -37,7 +37,8 @@ IOCtlSrc::IOCtlSrc(decltype(m_filename) filename)
|
|||
|
||||
IOCtlSrc::~IOCtlSrc()
|
||||
{
|
||||
if (m_device != -1) {
|
||||
if (m_device != -1)
|
||||
{
|
||||
SetSpindleSpeed(true);
|
||||
close(m_device);
|
||||
}
|
||||
|
@ -113,10 +114,12 @@ bool IOCtlSrc::ReadSectors2352(u32 sector, u32 count, u8* buffer) const
|
|||
char buffer[CD_FRAMESIZE_RAW];
|
||||
} data;
|
||||
|
||||
for (u32 n = 0; n < count; ++n) {
|
||||
for (u32 n = 0; n < count; ++n)
|
||||
{
|
||||
u32 lba = sector + n;
|
||||
lba_to_msf(lba, &data.msf.cdmsf_min0, &data.msf.cdmsf_sec0, &data.msf.cdmsf_frame0);
|
||||
if (ioctl(m_device, CDROMREADRAW, &data) == -1) {
|
||||
if (ioctl(m_device, CDROMREADRAW, &data) == -1)
|
||||
{
|
||||
fprintf(stderr, " * CDVD CDROMREADRAW sector %u failed: %s\n",
|
||||
lba, strerror(errno));
|
||||
return false;
|
||||
|
@ -145,13 +148,15 @@ bool IOCtlSrc::ReadDVDInfo()
|
|||
u32 start_sector = dvdrs.physical.layer[0].start_sector;
|
||||
u32 end_sector = dvdrs.physical.layer[0].end_sector;
|
||||
|
||||
if (dvdrs.physical.layer[0].nlayers == 0) {
|
||||
if (dvdrs.physical.layer[0].nlayers == 0)
|
||||
{
|
||||
// Single layer
|
||||
m_media_type = 0;
|
||||
m_layer_break = 0;
|
||||
m_sectors = end_sector - start_sector + 1;
|
||||
}
|
||||
else if (dvdrs.physical.layer[0].track_path == 0) {
|
||||
else if (dvdrs.physical.layer[0].track_path == 0)
|
||||
{
|
||||
// Dual layer, Parallel Track Path
|
||||
dvdrs.physical.layer_num = 1;
|
||||
ret = ioctl(m_device, DVD_READ_STRUCT, &dvdrs);
|
||||
|
@ -164,7 +169,8 @@ bool IOCtlSrc::ReadDVDInfo()
|
|||
m_layer_break = end_sector - start_sector;
|
||||
m_sectors = end_sector - start_sector + 1 + layer1_end_sector - layer1_start_sector + 1;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
// Dual layer, Opposite Track Path
|
||||
u32 end_sector_layer0 = dvdrs.physical.layer[0].end_sector_l0;
|
||||
m_media_type = 2;
|
||||
|
@ -190,11 +196,12 @@ bool IOCtlSrc::ReadCDInfo()
|
|||
entry.cdte_format = CDROM_LBA;
|
||||
|
||||
m_toc.clear();
|
||||
for (u8 n = header.cdth_trk0; n <= header.cdth_trk1; ++n) {
|
||||
for (u8 n = header.cdth_trk0; n <= header.cdth_trk1; ++n)
|
||||
{
|
||||
entry.cdte_track = n;
|
||||
if (ioctl(m_device, CDROMREADTOCENTRY, &entry) != -1)
|
||||
m_toc.push_back({ static_cast<u32>(entry.cdte_addr.lba), entry.cdte_track,
|
||||
entry.cdte_adr, entry.cdte_ctrl });
|
||||
m_toc.push_back({static_cast<u32>(entry.cdte_addr.lba), entry.cdte_track,
|
||||
entry.cdte_adr, entry.cdte_ctrl});
|
||||
}
|
||||
|
||||
// TODO: Do I need a fallback if this doesn't work?
|
||||
|
@ -218,11 +225,13 @@ bool IOCtlSrc::DiscReady()
|
|||
return false;
|
||||
|
||||
// CDSL_CURRENT must be used - 0 will cause the drive tray to close.
|
||||
if (ioctl(m_device, CDROM_DRIVE_STATUS, CDSL_CURRENT) == CDS_DISC_OK) {
|
||||
if (ioctl(m_device, CDROM_DRIVE_STATUS, CDSL_CURRENT) == CDS_DISC_OK)
|
||||
{
|
||||
if (!m_sectors)
|
||||
Reopen();
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
m_sectors = 0;
|
||||
m_layer_break = 0;
|
||||
m_media_type = 0;
|
||||
|
|
|
@ -20,12 +20,13 @@
|
|||
|
||||
#include <errno.h>
|
||||
|
||||
void pxStream_OpenCheck( const wxStreamBase& stream, const wxString& fname, const wxString& mode )
|
||||
void pxStream_OpenCheck(const wxStreamBase& stream, const wxString& fname, const wxString& mode)
|
||||
{
|
||||
if (stream.IsOk()) return;
|
||||
if (stream.IsOk())
|
||||
return;
|
||||
|
||||
ScopedExcept ex(Exception::FromErrno(fname, errno));
|
||||
ex->SetDiagMsg( pxsFmt(L"Unable to open the file for %s: %s", WX_STR(mode), WX_STR(ex->DiagMsg())) );
|
||||
ex->SetDiagMsg(pxsFmt(L"Unable to open the file for %s: %s", WX_STR(mode), WX_STR(ex->DiagMsg())));
|
||||
ex->Rethrow();
|
||||
}
|
||||
|
||||
|
@ -60,7 +61,7 @@ void OutputIsoFile::Create(const wxString& filename, int version)
|
|||
m_blocksize = 2048;
|
||||
|
||||
m_outstream = std::make_unique<wxFileOutputStream>(m_filename);
|
||||
pxStream_OpenCheck( *m_outstream, m_filename, L"writing" );
|
||||
pxStream_OpenCheck(*m_outstream, m_filename, L"writing");
|
||||
|
||||
Console.WriteLn("isoFile create ok: %s ", WX_STR(m_filename));
|
||||
}
|
||||
|
@ -90,21 +91,21 @@ void OutputIsoFile::WriteSector(const u8* src, uint lsn)
|
|||
if (m_version == 2)
|
||||
{
|
||||
// Find and ignore blocks that have already been dumped:
|
||||
if (std::any_of(std::begin(m_dtable), std::end(m_dtable), [=](const u32 entry) {return entry == lsn;}))
|
||||
if (std::any_of(std::begin(m_dtable), std::end(m_dtable), [=](const u32 entry) { return entry == lsn; }))
|
||||
return;
|
||||
|
||||
m_dtable.push_back(lsn);
|
||||
|
||||
WriteValue<u32>( lsn );
|
||||
WriteValue<u32>(lsn);
|
||||
}
|
||||
else
|
||||
{
|
||||
wxFileOffset ofs = (wxFileOffset)lsn * m_blocksize + m_offset;
|
||||
|
||||
m_outstream->SeekO( ofs );
|
||||
m_outstream->SeekO(ofs);
|
||||
}
|
||||
|
||||
WriteBuffer( src + m_blockofs, m_blocksize );
|
||||
WriteBuffer(src + m_blockofs, m_blocksize);
|
||||
}
|
||||
|
||||
void OutputIsoFile::Close()
|
||||
|
@ -114,17 +115,17 @@ void OutputIsoFile::Close()
|
|||
_init();
|
||||
}
|
||||
|
||||
void OutputIsoFile::WriteBuffer( const void* src, size_t size )
|
||||
void OutputIsoFile::WriteBuffer(const void* src, size_t size)
|
||||
{
|
||||
m_outstream->Write(src, size);
|
||||
if(m_outstream->GetLastError() == wxSTREAM_WRITE_ERROR)
|
||||
if (m_outstream->GetLastError() == wxSTREAM_WRITE_ERROR)
|
||||
{
|
||||
int err = errno;
|
||||
if (!err)
|
||||
throw Exception::BadStream(m_filename).SetDiagMsg(pxsFmt(L"An error occurred while writing %u bytes to file", size));
|
||||
|
||||
ScopedExcept ex(Exception::FromErrno(m_filename, err));
|
||||
ex->SetDiagMsg( pxsFmt(L"An error occurred while writing %u bytes to file: %s", size, WX_STR(ex->DiagMsg())) );
|
||||
ex->SetDiagMsg(pxsFmt(L"An error occurred while writing %u bytes to file: %s", size, WX_STR(ex->DiagMsg())));
|
||||
ex->Rethrow();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,8 @@ std::vector<std::wstring> GetOpticalDriveList()
|
|||
return {};
|
||||
|
||||
std::vector<std::wstring> drives;
|
||||
for (auto p = drive_strings.data(); *p; ++p) {
|
||||
for (auto p = drive_strings.data(); *p; ++p)
|
||||
{
|
||||
if (GetDriveType(p) == DRIVE_CDROM)
|
||||
drives.push_back(p);
|
||||
while (*p)
|
||||
|
@ -35,7 +36,8 @@ std::vector<std::wstring> GetOpticalDriveList()
|
|||
|
||||
void GetValidDrive(std::wstring& drive)
|
||||
{
|
||||
if (drive.empty() || GetDriveType(drive.c_str()) != DRIVE_CDROM) {
|
||||
if (drive.empty() || GetDriveType(drive.c_str()) != DRIVE_CDROM)
|
||||
{
|
||||
auto drives = GetOpticalDriveList();
|
||||
if (drives.empty())
|
||||
{
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include <winioctl.h>
|
||||
#include <ntddcdvd.h>
|
||||
#include <ntddcdrm.h>
|
||||
// "typedef ignored" warning will disappear once we move to the Windows 10 SDK.
|
||||
// "typedef ignored" warning will disappear once we move to the Windows 10 SDK.
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4091)
|
||||
#include <ntddscsi.h>
|
||||
|
@ -38,7 +38,8 @@ IOCtlSrc::IOCtlSrc(decltype(m_filename) filename)
|
|||
|
||||
IOCtlSrc::~IOCtlSrc()
|
||||
{
|
||||
if (m_device != INVALID_HANDLE_VALUE) {
|
||||
if (m_device != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
SetSpindleSpeed(true);
|
||||
CloseHandle(m_device);
|
||||
}
|
||||
|
@ -78,15 +79,17 @@ void IOCtlSrc::SetSpindleSpeed(bool restore_defaults) const
|
|||
// TODO: What speed? Performance seems smoother with a lower speed (less
|
||||
// time required to get up to speed).
|
||||
const USHORT speed = restore_defaults ? 0xFFFF : GetMediaType() >= 0 ? 5540 : 3600;
|
||||
CDROM_SET_SPEED s{ CdromSetSpeed, speed, speed, CdromDefaultRotation };
|
||||
CDROM_SET_SPEED s{CdromSetSpeed, speed, speed, CdromDefaultRotation};
|
||||
|
||||
DWORD unused;
|
||||
if (DeviceIoControl(m_device, IOCTL_CDROM_SET_SPEED, &s, sizeof(s),
|
||||
nullptr, 0, &unused, nullptr)) {
|
||||
nullptr, 0, &unused, nullptr))
|
||||
{
|
||||
if (!restore_defaults)
|
||||
printf(" * CDVD: setSpindleSpeed success (%uKB/s)\n", speed);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
printf(" * CDVD: setSpindleSpeed failed!\n");
|
||||
}
|
||||
}
|
||||
|
@ -117,7 +120,8 @@ bool IOCtlSrc::ReadSectors2048(u32 sector, u32 count, u8* buffer) const
|
|||
LARGE_INTEGER offset;
|
||||
offset.QuadPart = sector * 2048ULL;
|
||||
|
||||
if (!SetFilePointerEx(m_device, offset, nullptr, FILE_BEGIN)) {
|
||||
if (!SetFilePointerEx(m_device, offset, nullptr, FILE_BEGIN))
|
||||
{
|
||||
fprintf(stderr, " * CDVD SetFilePointerEx failed: sector %u: error %u\n",
|
||||
sector, GetLastError());
|
||||
return false;
|
||||
|
@ -125,13 +129,15 @@ bool IOCtlSrc::ReadSectors2048(u32 sector, u32 count, u8* buffer) const
|
|||
|
||||
const DWORD bytes_to_read = 2048 * count;
|
||||
DWORD bytes_read;
|
||||
if (ReadFile(m_device, buffer, bytes_to_read, &bytes_read, nullptr)) {
|
||||
if (ReadFile(m_device, buffer, bytes_to_read, &bytes_read, nullptr))
|
||||
{
|
||||
if (bytes_read == bytes_to_read)
|
||||
return true;
|
||||
fprintf(stderr, " * CDVD ReadFile: sectors %u-%u: %u bytes read, %u bytes expected\n",
|
||||
sector, sector + count - 1, bytes_read, bytes_to_read);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
fprintf(stderr, " * CDVD ReadFile failed: sectors %u-%u: error %u\n",
|
||||
sector, sector + count - 1, GetLastError());
|
||||
}
|
||||
|
@ -168,7 +174,8 @@ bool IOCtlSrc::ReadSectors2352(u32 sector, u32 count, u8* buffer) const
|
|||
|
||||
// Read sectors one by one to avoid reading data from 2 tracks of different
|
||||
// types in the same read (which will fail).
|
||||
for (u32 n = 0; n < count; ++n) {
|
||||
for (u32 n = 0; n < count; ++n)
|
||||
{
|
||||
u32 current_sector = sector + n;
|
||||
sptd.info.Cdb[2] = (current_sector >> 24) & 0xFF;
|
||||
sptd.info.Cdb[3] = (current_sector >> 16) & 0xFF;
|
||||
|
@ -180,7 +187,8 @@ bool IOCtlSrc::ReadSectors2352(u32 sector, u32 count, u8* buffer) const
|
|||
|
||||
DWORD unused;
|
||||
if (DeviceIoControl(m_device, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd,
|
||||
sizeof(sptd), &sptd, sizeof(sptd), &unused, nullptr)) {
|
||||
sizeof(sptd), &sptd, sizeof(sptd), &unused, nullptr))
|
||||
{
|
||||
if (sptd.info.DataTransferLength == 2352)
|
||||
continue;
|
||||
}
|
||||
|
@ -204,7 +212,7 @@ bool IOCtlSrc::ReadDVDInfo()
|
|||
// media specific information seems to be empty, so there's no point reading
|
||||
// any more than that.
|
||||
std::array<u8, 22> buffer;
|
||||
DVD_READ_STRUCTURE dvdrs{ {0}, DvdPhysicalDescriptor, 0, 0 };
|
||||
DVD_READ_STRUCTURE dvdrs{{0}, DvdPhysicalDescriptor, 0, 0};
|
||||
|
||||
if (!DeviceIoControl(m_device, IOCTL_DVD_READ_STRUCTURE, &dvdrs, sizeof(dvdrs),
|
||||
buffer.data(), buffer.size(), &unused, nullptr))
|
||||
|
@ -216,13 +224,15 @@ bool IOCtlSrc::ReadDVDInfo()
|
|||
u32 start_sector = _byteswap_ulong(layer.StartingDataSector);
|
||||
u32 end_sector = _byteswap_ulong(layer.EndDataSector);
|
||||
|
||||
if (layer.NumberOfLayers == 0) {
|
||||
if (layer.NumberOfLayers == 0)
|
||||
{
|
||||
// Single layer
|
||||
m_media_type = 0;
|
||||
m_layer_break = 0;
|
||||
m_sectors = end_sector - start_sector + 1;
|
||||
}
|
||||
else if (layer.TrackPath == 0) {
|
||||
else if (layer.TrackPath == 0)
|
||||
{
|
||||
// Dual layer, Parallel Track Path
|
||||
dvdrs.LayerNumber = 1;
|
||||
if (!DeviceIoControl(m_device, IOCTL_DVD_READ_STRUCTURE, &dvdrs, sizeof(dvdrs),
|
||||
|
@ -235,7 +245,8 @@ bool IOCtlSrc::ReadDVDInfo()
|
|||
m_layer_break = end_sector - start_sector;
|
||||
m_sectors = end_sector - start_sector + 1 + layer1_end_sector - layer1_start_sector + 1;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
// Dual layer, Opposite Track Path
|
||||
u32 end_sector_layer0 = _byteswap_ulong(layer.EndLayerZeroSector);
|
||||
m_media_type = 2;
|
||||
|
@ -261,13 +272,14 @@ bool IOCtlSrc::ReadCDInfo()
|
|||
|
||||
m_toc.clear();
|
||||
size_t track_count = ((toc.Length[0] << 8) + toc.Length[1] - 2) / sizeof(TRACK_DATA);
|
||||
for (size_t n = 0; n < track_count; ++n) {
|
||||
for (size_t n = 0; n < track_count; ++n)
|
||||
{
|
||||
TRACK_DATA& track = toc.TrackData[n];
|
||||
// Exclude the lead-out track descriptor.
|
||||
if (track.TrackNumber == 0xAA)
|
||||
continue;
|
||||
u32 lba = (track.Address[1] << 16) + (track.Address[2] << 8) + track.Address[3];
|
||||
m_toc.push_back({ lba, track.TrackNumber, track.Adr, track.Control });
|
||||
m_toc.push_back({lba, track.TrackNumber, track.Adr, track.Control});
|
||||
}
|
||||
|
||||
GET_LENGTH_INFORMATION info;
|
||||
|
@ -288,11 +300,13 @@ bool IOCtlSrc::DiscReady()
|
|||
|
||||
DWORD unused;
|
||||
if (DeviceIoControl(m_device, IOCTL_STORAGE_CHECK_VERIFY, nullptr, 0,
|
||||
nullptr, 0, &unused, nullptr)) {
|
||||
nullptr, 0, &unused, nullptr))
|
||||
{
|
||||
if (!m_sectors)
|
||||
Reopen();
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
m_sectors = 0;
|
||||
m_layer_break = 0;
|
||||
m_media_type = 0;
|
||||
|
|
|
@ -116,11 +116,12 @@ Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
|
|||
#define CHUNK (64 * 1024) /* file input buffer size */
|
||||
|
||||
#ifdef _WIN32
|
||||
# pragma pack(push, indexData, 1)
|
||||
#pragma pack(push, indexData, 1)
|
||||
#endif
|
||||
|
||||
/* access point entry */
|
||||
struct point {
|
||||
struct point
|
||||
{
|
||||
PX_off_t out; /* corresponding offset in uncompressed data */
|
||||
PX_off_t in; /* offset in input file of first full byte */
|
||||
int bits; /* number of bits (1-7) from byte at in - 1, or 0 */
|
||||
|
@ -134,10 +135,11 @@ __attribute__((packed))
|
|||
typedef struct point Point;
|
||||
|
||||
/* access point list */
|
||||
struct access {
|
||||
struct access
|
||||
{
|
||||
int have; /* number of list entries filled in */
|
||||
int size; /* number of list entries allocated (only used internally during build)*/
|
||||
struct point *list; /* allocated list */
|
||||
struct point* list; /* allocated list */
|
||||
|
||||
s32 span; /* once the index is built, holds the span size used to build it */
|
||||
PX_off_t uncompressed_size; /* filled by build_index */
|
||||
|
@ -150,13 +152,14 @@ __attribute__((packed))
|
|||
typedef struct access Access;
|
||||
|
||||
#ifdef _WIN32
|
||||
# pragma pack(pop, indexData)
|
||||
#pragma pack(pop, indexData)
|
||||
#endif
|
||||
|
||||
/* Deallocate an index built by build_index() */
|
||||
local void free_index(struct access *index)
|
||||
local void free_index(struct access* index)
|
||||
{
|
||||
if (index != NULL) {
|
||||
if (index != NULL)
|
||||
{
|
||||
free(index->list);
|
||||
free(index);
|
||||
}
|
||||
|
@ -164,17 +167,20 @@ local void free_index(struct access *index)
|
|||
|
||||
/* Add an entry to the access point list. If out of memory, deallocate the
|
||||
existing list and return NULL. */
|
||||
local struct access *addpoint(struct access *index, int bits,
|
||||
PX_off_t in, PX_off_t out, unsigned left, unsigned char *window)
|
||||
local struct access* addpoint(struct access* index, int bits,
|
||||
PX_off_t in, PX_off_t out, unsigned left, unsigned char* window)
|
||||
{
|
||||
struct point *next;
|
||||
struct point* next;
|
||||
|
||||
/* if list is empty, create it (start with eight points) */
|
||||
if (index == NULL) {
|
||||
if (index == NULL)
|
||||
{
|
||||
index = (Access*)malloc(sizeof(struct access));
|
||||
if (index == NULL) return NULL;
|
||||
if (index == NULL)
|
||||
return NULL;
|
||||
index->list = (Point*)malloc(sizeof(struct point) << 3);
|
||||
if (index->list == NULL) {
|
||||
if (index->list == NULL)
|
||||
{
|
||||
free(index);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -183,10 +189,12 @@ local struct access *addpoint(struct access *index, int bits,
|
|||
}
|
||||
|
||||
/* if list is full, make it bigger */
|
||||
else if (index->have == index->size) {
|
||||
else if (index->have == index->size)
|
||||
{
|
||||
index->size <<= 1;
|
||||
next = (Point*)realloc(index->list, sizeof(struct point) * index->size);
|
||||
if (next == NULL) {
|
||||
if (next == NULL)
|
||||
{
|
||||
free_index(index);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -216,12 +224,12 @@ local struct access *addpoint(struct access *index, int bits,
|
|||
returns the number of access points on success (>= 1), Z_MEM_ERROR for out
|
||||
of memory, Z_DATA_ERROR for an error in the input file, or Z_ERRNO for a
|
||||
file read error. On success, *built points to the resulting index. */
|
||||
local int build_index(FILE *in, PX_off_t span, struct access **built)
|
||||
local int build_index(FILE* in, PX_off_t span, struct access** built)
|
||||
{
|
||||
int ret;
|
||||
PX_off_t totin, totout, totPrinted; /* our own total counters to avoid 4GB limit */
|
||||
PX_off_t last; /* totout value of last access point */
|
||||
struct access *index; /* access points being generated */
|
||||
struct access* index; /* access points being generated */
|
||||
z_stream strm;
|
||||
unsigned char input[CHUNK];
|
||||
unsigned char window[WINSIZE];
|
||||
|
@ -242,23 +250,28 @@ local int build_index(FILE *in, PX_off_t span, struct access **built)
|
|||
totin = totout = last = totPrinted = 0;
|
||||
index = NULL; /* will be allocated by first addpoint() */
|
||||
strm.avail_out = 0;
|
||||
do {
|
||||
do
|
||||
{
|
||||
/* get some compressed data from input file */
|
||||
strm.avail_in = fread(input, 1, CHUNK, in);
|
||||
if (ferror(in)) {
|
||||
if (ferror(in))
|
||||
{
|
||||
ret = Z_ERRNO;
|
||||
goto build_index_error;
|
||||
}
|
||||
if (strm.avail_in == 0) {
|
||||
if (strm.avail_in == 0)
|
||||
{
|
||||
ret = Z_DATA_ERROR;
|
||||
goto build_index_error;
|
||||
}
|
||||
strm.next_in = input;
|
||||
|
||||
/* process all of that, or until end of stream */
|
||||
do {
|
||||
do
|
||||
{
|
||||
/* reset sliding window if necessary */
|
||||
if (strm.avail_out == 0) {
|
||||
if (strm.avail_out == 0)
|
||||
{
|
||||
strm.avail_out = WINSIZE;
|
||||
strm.next_out = window;
|
||||
}
|
||||
|
@ -287,23 +300,27 @@ local int build_index(FILE *in, PX_off_t span, struct access **built)
|
|||
access point after the last block by checking bit 6 of data_type
|
||||
*/
|
||||
if ((strm.data_type & 128) && !(strm.data_type & 64) &&
|
||||
(totout == 0 || totout - last > span)) {
|
||||
(totout == 0 || totout - last > span))
|
||||
{
|
||||
index = addpoint(index, strm.data_type & 7, totin,
|
||||
totout, strm.avail_out, window);
|
||||
if (index == NULL) {
|
||||
if (index == NULL)
|
||||
{
|
||||
ret = Z_MEM_ERROR;
|
||||
goto build_index_error;
|
||||
}
|
||||
last = totout;
|
||||
}
|
||||
} while (strm.avail_in != 0);
|
||||
if (totin / (50 * 1024 * 1024) != totPrinted / (50 * 1024 * 1024)) {
|
||||
if (totin / (50 * 1024 * 1024) != totPrinted / (50 * 1024 * 1024))
|
||||
{
|
||||
printf("%dMB ", (int)(totin / (1024 * 1024)));
|
||||
totPrinted = totin;
|
||||
}
|
||||
} while (ret != Z_STREAM_END);
|
||||
|
||||
if (index == NULL) {
|
||||
if (index == NULL)
|
||||
{
|
||||
// Could happen if the start of the stream in Z_STREAM_END
|
||||
return 0;
|
||||
}
|
||||
|
@ -318,21 +335,23 @@ local int build_index(FILE *in, PX_off_t span, struct access **built)
|
|||
return index->have;
|
||||
|
||||
/* return error */
|
||||
build_index_error:
|
||||
build_index_error:
|
||||
(void)inflateEnd(&strm);
|
||||
if (index != NULL)
|
||||
free_index(index);
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef struct zstate {
|
||||
typedef struct zstate
|
||||
{
|
||||
PX_off_t out_offset;
|
||||
PX_off_t in_offset;
|
||||
z_stream strm;
|
||||
int isValid;
|
||||
} Zstate;
|
||||
|
||||
static inline PX_off_t getInOffset(zstate *state) {
|
||||
static inline PX_off_t getInOffset(zstate* state)
|
||||
{
|
||||
return state->in_offset;
|
||||
}
|
||||
|
||||
|
@ -343,11 +362,11 @@ static inline PX_off_t getInOffset(zstate *state) {
|
|||
should not return a data error unless the file was modified since the index
|
||||
was generated. extract() may also return Z_ERRNO if there is an error on
|
||||
reading or seeking the input file. */
|
||||
local int extract(FILE *in, struct access *index, PX_off_t offset,
|
||||
unsigned char *buf, int len, zstate *state)
|
||||
local int extract(FILE* in, struct access* index, PX_off_t offset,
|
||||
unsigned char* buf, int len, zstate* state)
|
||||
{
|
||||
int ret, skip;
|
||||
struct point *here;
|
||||
struct point* here;
|
||||
unsigned char input[CHUNK];
|
||||
unsigned char discard[WINSIZE];
|
||||
int isEnd = 0;
|
||||
|
@ -356,20 +375,24 @@ local int extract(FILE *in, struct access *index, PX_off_t offset,
|
|||
if (len < 0 || state == nullptr)
|
||||
return 0;
|
||||
|
||||
if (state->isValid && offset != state->out_offset) {
|
||||
if (state->isValid && offset != state->out_offset)
|
||||
{
|
||||
// state doesn't match offset, free allocations before strm is overwritten
|
||||
inflateEnd(&state->strm);
|
||||
state->isValid = 0;
|
||||
}
|
||||
state->out_offset = offset;
|
||||
|
||||
if (state->isValid) {
|
||||
if (state->isValid)
|
||||
{
|
||||
state->isValid = 0; // we took control over strm. revalidate when/if we give it back
|
||||
PX_fseeko(in, state->in_offset, SEEK_SET);
|
||||
state->strm.avail_in = 0;
|
||||
offset = 0;
|
||||
skip = 1;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
/* find where in stream to start */
|
||||
here = index->list;
|
||||
ret = index->have;
|
||||
|
@ -388,9 +411,11 @@ local int extract(FILE *in, struct access *index, PX_off_t offset,
|
|||
ret = PX_fseeko(in, here->in - (here->bits ? 1 : 0), SEEK_SET);
|
||||
if (ret == -1)
|
||||
goto extract_ret;
|
||||
if (here->bits) {
|
||||
if (here->bits)
|
||||
{
|
||||
ret = getc(in);
|
||||
if (ret == -1) {
|
||||
if (ret == -1)
|
||||
{
|
||||
ret = ferror(in) ? Z_ERRNO : Z_DATA_ERROR;
|
||||
goto extract_ret;
|
||||
}
|
||||
|
@ -404,34 +429,42 @@ local int extract(FILE *in, struct access *index, PX_off_t offset,
|
|||
skip = 1; /* while skipping to offset */
|
||||
}
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
/* define where to put uncompressed data, and how much */
|
||||
if (offset == 0 && skip) { /* at offset now */
|
||||
if (offset == 0 && skip)
|
||||
{ /* at offset now */
|
||||
state->strm.avail_out = len;
|
||||
state->strm.next_out = buf;
|
||||
skip = 0; /* only do this once */
|
||||
}
|
||||
if (offset > WINSIZE) { /* skip WINSIZE bytes */
|
||||
if (offset > WINSIZE)
|
||||
{ /* skip WINSIZE bytes */
|
||||
state->strm.avail_out = WINSIZE;
|
||||
state->strm.next_out = discard;
|
||||
offset -= WINSIZE;
|
||||
}
|
||||
else if (offset != 0) { /* last skip */
|
||||
else if (offset != 0)
|
||||
{ /* last skip */
|
||||
state->strm.avail_out = (unsigned)offset;
|
||||
state->strm.next_out = discard;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
/* uncompress until avail_out filled, or end of stream */
|
||||
do {
|
||||
if (state->strm.avail_in == 0) {
|
||||
do
|
||||
{
|
||||
if (state->strm.avail_in == 0)
|
||||
{
|
||||
state->in_offset = PX_ftello(in);
|
||||
state->strm.avail_in = fread(input, 1, CHUNK, in);
|
||||
if (ferror(in)) {
|
||||
if (ferror(in))
|
||||
{
|
||||
ret = Z_ERRNO;
|
||||
goto extract_ret;
|
||||
}
|
||||
if (state->strm.avail_in == 0) {
|
||||
if (state->strm.avail_in == 0)
|
||||
{
|
||||
ret = Z_DATA_ERROR;
|
||||
goto extract_ret;
|
||||
}
|
||||
|
@ -461,10 +494,12 @@ local int extract(FILE *in, struct access *index, PX_off_t offset,
|
|||
|
||||
/* clean up and return bytes read or error */
|
||||
extract_ret:
|
||||
if (ret == len && !isEnd) {
|
||||
if (ret == len && !isEnd)
|
||||
{
|
||||
state->out_offset += len;
|
||||
state->isValid = 1;
|
||||
} else
|
||||
}
|
||||
else
|
||||
inflateEnd(&state->strm);
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -32,7 +32,7 @@ Dialogs::DriveSelectorDialog::DriveSelectorDialog(wxWindow* parent, wxString cur
|
|||
driveList.Add(i);
|
||||
}
|
||||
|
||||
choiceDrive = new wxChoice(this, wxID_ANY, wxDefaultPosition, { 240, 40 }, driveList);
|
||||
choiceDrive = new wxChoice(this, wxID_ANY, wxDefaultPosition, {240, 40}, driveList);
|
||||
|
||||
int driveIndex = choiceDrive->FindString(curDrive);
|
||||
if (driveIndex != wxNOT_FOUND)
|
||||
|
|
|
@ -25,7 +25,7 @@ DriveList::DriveList()
|
|||
}
|
||||
|
||||
DriveListManager::DriveListManager(wxMenu* menu)
|
||||
: m_Menu( menu )
|
||||
: m_Menu(menu)
|
||||
{
|
||||
m_Menu->Append(MenuId_DriveListRefresh, _("&Refresh"));
|
||||
m_Menu->AppendSeparator();
|
||||
|
@ -78,13 +78,13 @@ void DriveListManager::RefreshList()
|
|||
}
|
||||
}
|
||||
|
||||
void DriveListManager::OnChangedSelection( wxCommandEvent& evt )
|
||||
void DriveListManager::OnChangedSelection(wxCommandEvent& evt)
|
||||
{
|
||||
uint index = m_Items.size();
|
||||
|
||||
for (uint i = 0; i < m_Items.size(); i++)
|
||||
{
|
||||
if( (m_Items.at(i)->itemPtr != NULL) && (m_Items.at(i)->itemPtr->GetId() == evt.GetId()) )
|
||||
if ((m_Items.at(i)->itemPtr != NULL) && (m_Items.at(i)->itemPtr->GetId() == evt.GetId()))
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
|
@ -103,8 +103,7 @@ void DriveListManager::OnChangedSelection( wxCommandEvent& evt )
|
|||
SwapOrReset_Disc(m_Menu->GetWindow(), paused_core, m_Items.at(index)->driveLetter);
|
||||
}
|
||||
|
||||
void DriveListManager::OnRefreshClicked( wxCommandEvent& evt )
|
||||
void DriveListManager::OnRefreshClicked(wxCommandEvent& evt)
|
||||
{
|
||||
RefreshList();
|
||||
}
|
||||
|
||||
|
|
|
@ -27,8 +27,8 @@ protected:
|
|||
|
||||
DriveListItem() { itemPtr = NULL; }
|
||||
|
||||
DriveListItem( const wxString& src )
|
||||
: driveLetter( src )
|
||||
DriveListItem(const wxString& src)
|
||||
: driveLetter(src)
|
||||
{
|
||||
itemPtr = NULL;
|
||||
}
|
||||
|
@ -45,8 +45,8 @@ public:
|
|||
|
||||
protected:
|
||||
void ClearList();
|
||||
void OnChangedSelection( wxCommandEvent& evt );
|
||||
void OnRefreshClicked( wxCommandEvent& evt );
|
||||
void OnChangedSelection(wxCommandEvent& evt);
|
||||
void OnRefreshClicked(wxCommandEvent& evt);
|
||||
};
|
||||
|
||||
struct DriveList
|
||||
|
|
Loading…
Reference in New Issue