CDVD: clang-format

This commit is contained in:
Gauvain 'GovanifY' Roussel-Tarbouriech 2020-09-06 07:03:49 +02:00 committed by refractionpcsx2
parent c4fa3e3304
commit f9be4286bd
40 changed files with 2343 additions and 1890 deletions

View File

@ -22,8 +22,8 @@
enum isoFlags
{
ISOFLAGS_BLOCKDUMP_V2 = 0x0004,
ISOFLAGS_BLOCKDUMP_V3 = 0x0020
ISOFLAGS_BLOCKDUMP_V2 = 0x0004,
ISOFLAGS_BLOCKDUMP_V3 = 0x0020
};
static const uint BlockDumpHeaderSize = 16;
@ -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_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)
@ -127,25 +128,25 @@ int BlockdumpFileReader::ReadSync(void* pBuffer, uint lsn, uint count)
if (m_dtable[i] != lsn)
continue;
// We store the LSN (u32) along with each block inside of blockdumps, so the
// seek position ends up being based on (m_blocksize + 4) instead of just m_blocksize.
// We store the LSN (u32) along with each block inside of blockdumps, so the
// seek position ends up being based on (m_blocksize + 4) instead of just m_blocksize.
#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

View File

@ -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;
}
@ -47,10 +47,10 @@ static __fi void lsn_to_msf(u8* Time, s32 lsn)
u8 m, s, f;
lsn += 150;
m = lsn / 4500; // minuten
lsn = lsn - m * 4500; // minuten rest
s = lsn / 75; // sekunden
f = lsn - (s * 75); // sekunden rest
m = lsn / 4500; // minuten
lsn = lsn - m * 4500; // minuten rest
s = lsn / 75; // sekunden
f = lsn - (s * 75); // sekunden rest
Time[0] = itob(m);
Time[1] = itob(s);
Time[2] = itob(f);
@ -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;
@ -107,7 +109,7 @@ struct cdvdStruct {
u32 Sector;
int nSectors;
int Readed; // change to bool. --arcum42
int Readed; // change to bool. --arcum42
int Reading; // same here.
int ReadMode;
int BlockSize; // Total bytes transfered at 1x speed
@ -121,18 +123,18 @@ struct cdvdStruct {
u8 KeyXor;
u8 decSet;
u8 mg_buffer[65536];
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
u32 SeekToSector; // Holds the destination sector during seek operations.
u32 ReadTime; // Avg. time to read one block of data (in Iop cycles)
bool Spinning; // indicates if the Cdvd is spinning or needs a spinup delay
u8 TrayTimeout;
u8 Action; // the currently scheduled emulated action
u32 SeekToSector; // Holds the destination sector during seek operations.
u32 ReadTime; // Avg. time to read one block of data (in Iop cycles)
bool Spinning; // indicates if the Cdvd is spinning or needs a spinup delay
};

View File

@ -40,29 +40,29 @@ 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
};
/* is cdvd.Status only for NCMDS? (linuzappz) */
/* cdvd.Status is a construction site as of now (rama)*/
/* cdvd.Status is a construction site as of now (rama)*/
enum cdvdStatus
{
//CDVD_STATUS_NONE = 0x00, // not sure ;)
//CDVD_STATUS_SEEK_COMPLETE = 0x0A,
CDVD_STATUS_STOP = 0x00,
CDVD_STATUS_TRAY_OPEN = 0x01, // confirmed to be tray open
CDVD_STATUS_SPIN = 0x02,
CDVD_STATUS_READ = 0x06,
CDVD_STATUS_PAUSE = 0x0A, // neutral value. Recommended to never rely on this.
CDVD_STATUS_SEEK = 0x12,
CDVD_STATUS_EMERGENCY = 0x20,
CDVD_STATUS_STOP = 0x00,
CDVD_STATUS_TRAY_OPEN = 0x01, // confirmed to be tray open
CDVD_STATUS_SPIN = 0x02,
CDVD_STATUS_READ = 0x06,
CDVD_STATUS_PAUSE = 0x0A, // neutral value. Recommended to never rely on this.
CDVD_STATUS_SEEK = 0x12,
CDVD_STATUS_EMERGENCY = 0x20,
};
enum cdvdready
@ -70,19 +70,19 @@ enum cdvdready
CDVD_NOTREADY = 0x00,
CDVD_READY1 = 0x40,
CDVD_READY2 = 0x4e // This is used in a few places for some reason.
//It would be worth checking if this was just a typo made at some point.
//It would be worth checking if this was just a typo made at some point.
};
// Cdvd actions tell the emulator how and when to respond to certain requests.
// 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,19 +104,19 @@ 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]
{
4371, // CD-ROM
14764, // Single-layer DVD-ROM
13360 // dual-layer DVD-ROM [currently unused]
};
// 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]
{
8, // CD-ROM
16, // single-layer DVD-ROM
16, // dual-layer DVD-ROM [currently unused]
};
// Note: DVD read times are modified to be faster, because games seem to be a lot more
@ -128,20 +128,20 @@ static const uint tbl_ContigiousSeekDelta[3] =
//Silent Hill 2 videos starve of data and stall.
//So let's double that until the cause of the slow data rate is known.
static const uint PSX_CD_READSPEED = 153600 * 2; // 1 Byte Time @ x1 (150KB = cd x 1)
static const uint PSX_CD_READSPEED = 153600 * 2; // 1 Byte Time @ x1 (150KB = cd x 1)
static const uint PSX_DVD_READSPEED = 1382400 + 256000; // normal is 1 Byte Time @ x1 (1350KB = dvd x 1).
// 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",
@ -162,31 +162,31 @@ static const char *nCmdName[0x100]= {
enum nCmds
{
N_CD_SYNC = 0x00, // CdSync
N_CD_NOP = 0x01, // CdNop
N_CD_STANDBY = 0x02, // CdStandby
N_CD_STOP = 0x03, // CdStop
N_CD_PAUSE = 0x04, // CdPause
N_CD_SEEK = 0x05, // CdSeek
N_CD_READ = 0x06, // CdRead
N_CD_READ_CDDA = 0x07, // CdReadCDDA
N_DVD_READ = 0x08, // DvdRead
N_CD_GET_TOC = 0x09, // CdGetToc & cdvdman_call19
N_CMD_B = 0x0B, // CdReadKey
N_CD_READ_KEY = 0x0C, // CdReadKey
N_CD_READ_XCDDA = 0x0E, // CdReadXCDDA
N_CD_SYNC = 0x00, // CdSync
N_CD_NOP = 0x01, // CdNop
N_CD_STANDBY = 0x02, // CdStandby
N_CD_STOP = 0x03, // CdStop
N_CD_PAUSE = 0x04, // CdPause
N_CD_SEEK = 0x05, // CdSeek
N_CD_READ = 0x06, // CdRead
N_CD_READ_CDDA = 0x07, // CdReadCDDA
N_DVD_READ = 0x08, // DvdRead
N_CD_GET_TOC = 0x09, // CdGetToc & cdvdman_call19
N_CMD_B = 0x0B, // CdReadKey
N_CD_READ_KEY = 0x0C, // CdReadKey
N_CD_READ_XCDDA = 0x0E, // CdReadXCDDA
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,23 +223,24 @@ static const char *sCmdName[0x100]= {
};
// NVM (eeprom) layout info
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
s32 config2; // offset of 3rd config block
s32 consoleId; // offset of console id (?)
s32 ilinkId; // offset of ilink id (ilink mac address)
s32 modelNum; // offset of ps2 model number (eg "SCPH-70002")
s32 regparams; // offset of RegionParams for PStwo
s32 mac; // offset of the value written to 0xFFFE0188 and 0xFFFE018C on PStwo
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
s32 config2; // offset of 3rd config block
s32 consoleId; // offset of console id (?)
s32 ilinkId; // offset of ilink id (ilink mac address)
s32 modelNum; // offset of ps2 model number (eg "SCPH-70002")
s32 regparams; // offset of RegionParams for PStwo
s32 mac; // offset of the value written to 0xFFFE0188 and 0xFFFE018C on PStwo
};
#define NVM_FORMAT_MAX 2
#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
{
{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
};
#endif

View File

@ -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
};
{
L"ISO",
L"Disc",
L"NoDisc",
NULL};
// ----------------------------------------------------------------------------
// diskTypeCached
@ -58,7 +57,7 @@ static int diskTypeCached = -1;
// used to bridge the gap between the old getBuffer api and the new getBuffer2 api.
int lastReadSize;
u32 lastLSN; // needed for block dumping
u32 lastLSN; // needed for block dumping
// Records last read block length for block dumping
//static int plsn = 0;
@ -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;
@ -153,11 +156,11 @@ static int FindDiskType(int mType)
{
//const cdVolDesc& volDesc = (cdVolDesc&)bleh;
//if(volDesc.rootToc.tocSize == 2048)
//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:
@ -289,10 +293,10 @@ static void DetectDiskType()
diskTypeCached = FindDiskType(mType);
}
static wxString m_SourceFilename[3];
static CDVD_SourceType m_CurrentSourceType = CDVD_SourceType::NoDisc;
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,26 +326,26 @@ 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;
break;
break;
case CDVD_SourceType::Disc:
CDVD = &CDVDapi_Disc;
break;
break;
case CDVD_SourceType::NoDisc:
CDVD = &CDVDapi_NoDisc;
break;
break;
jNO_DEFAULT;
jNO_DEFAULT;
}
}
@ -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)",
curtime.GetYear(), curtime.GetMonth(), curtime.GetDay(),
curtime.GetHour(), curtime.GetMinute(), curtime.GetSecond()
);
temp += pxsFmt(L" (%04d-%02d-%02d %02d-%02d-%02d)",
curtime.GetYear(), curtime.GetMonth(), curtime.GetDay(),
curtime.GetHour(), curtime.GetMinute(), curtime.GetSecond());
#endif
temp += L".dump";
@ -407,23 +411,23 @@ bool DoCDVDopen()
blockDumpFile.Create(temp, 2);
if( blockDumpFile.IsOpened() )
if (blockDumpFile.IsOpened())
{
int blockofs = 0;
uint blocksize = CD_FRAMESIZE_RAW;
uint blocks = td.lsn;
int blockofs = 0;
uint blocksize = CD_FRAMESIZE_RAW;
uint blocks = td.lsn;
// 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:
case CDVD_TYPE_DETCTDVDS:
case CDVD_TYPE_DETCTDVDD:
blocksize = 2048;
break;
break;
}
blockDumpFile.WriteHeader(blockofs, blocksize, blocks);
}
@ -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())
{
@ -474,23 +478,23 @@ s32 DoCDVDreadTrack(u32 lsn, int mode)
// lastReadSize is needed for block dumps
switch (mode)
{
case CDVD_MODE_2352:
lastReadSize = 2352;
break;
case CDVD_MODE_2340:
lastReadSize = 2340;
break;
case CDVD_MODE_2328:
lastReadSize = 2328;
break;
case CDVD_MODE_2048:
lastReadSize = 2048;
break;
case CDVD_MODE_2352:
lastReadSize = 2352;
break;
case CDVD_MODE_2340:
lastReadSize = 2340;
break;
case CDVD_MODE_2328:
lastReadSize = 2328;
break;
case CDVD_MODE_2048:
lastReadSize = 2048;
break;
}
//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,22 +613,22 @@ s32 CALLBACK NODISCgetDualInfo(s32* dualType, u32* _layer1start)
}
CDVD_API CDVDapi_NoDisc =
{
NODISCclose,
NODISCopen,
NODISCreadTrack,
NODISCgetBuffer,
NODISCreadSubQ,
NODISCgetTN,
NODISCgetTD,
NODISCgetTOC,
NODISCgetDiskType,
NODISCgetTrayStatus,
NODISCdummyS32,
NODISCdummyS32,
{
NODISCclose,
NODISCopen,
NODISCreadTrack,
NODISCgetBuffer,
NODISCreadSubQ,
NODISCgetTN,
NODISCgetTD,
NODISCgetTOC,
NODISCgetDiskType,
NODISCgetTrayStatus,
NODISCdummyS32,
NODISCdummyS32,
NODISCnewDiskCB,
NODISCnewDiskCB,
NODISCreadSector,
NODISCgetDualInfo,
NODISCreadSector,
NODISCgetDualInfo,
};

View File

@ -109,14 +109,14 @@ typedef void(CALLBACK* _CDVDnewDiskCB)(void (*callback)());
enum class CDVD_SourceType : uint8_t
{
Iso, // use built in ISO api
Disc, // use built in Disc api
NoDisc, // use built in CDVDnull
Iso, // use built in ISO api
Disc, // use built in Disc api
NoDisc, // use built in CDVDnull
};
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.
@ -124,22 +124,22 @@ struct CDVD_API
// Don't need plugin specific things like freeze, test, or other stuff here.
// Those are handled by the plugin manager specifically.
_CDVDopen open;
_CDVDreadTrack readTrack;
_CDVDgetBuffer getBuffer;
_CDVDreadSubQ readSubQ;
_CDVDgetTN getTN;
_CDVDgetTD getTD;
_CDVDgetTOC getTOC;
_CDVDgetDiskType getDiskType;
_CDVDopen open;
_CDVDreadTrack readTrack;
_CDVDgetBuffer getBuffer;
_CDVDreadSubQ readSubQ;
_CDVDgetTN getTN;
_CDVDgetTD getTD;
_CDVDgetTOC getTOC;
_CDVDgetDiskType getDiskType;
_CDVDgetTrayStatus getTrayStatus;
_CDVDctrlTrayOpen ctrlTrayOpen;
_CDVDctrlTrayOpen ctrlTrayOpen;
_CDVDctrlTrayClose ctrlTrayClose;
_CDVDnewDiskCB newDiskCB;
_CDVDnewDiskCB newDiskCB;
// special functions, not in external interface yet
_CDVDreadSector readSector;
_CDVDgetDualInfo getDualInfo;
_CDVDreadSector readSector;
_CDVDgetDualInfo getDualInfo;
};
// ----------------------------------------------------------------------------
@ -147,7 +147,7 @@ struct CDVD_API
// for direct CDVD plugin invocation, and add universal block dumping features.
// ----------------------------------------------------------------------------
extern CDVD_API* CDVD; // currently active CDVD access mode api (either Iso, NoDisc, or Disc)
extern CDVD_API* CDVD; // currently active CDVD access mode api (either Iso, NoDisc, or Disc)
extern CDVD_API CDVDapi_Iso;
extern CDVD_API CDVDapi_Disc;
@ -155,16 +155,15 @@ 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();
extern void DoCDVDclose();
extern s32 DoCDVDreadSector(u8* buffer, u32 lsn, int mode);
extern s32 DoCDVDreadTrack(u32 lsn, int mode);
extern s32 DoCDVDgetBuffer(u8* buffer);
extern s32 DoCDVDdetectDiskType();
extern s32 DoCDVDreadSector(u8* buffer, u32 lsn, int mode);
extern s32 DoCDVDreadTrack(u32 lsn, int mode);
extern s32 DoCDVDgetBuffer(u8* buffer);
extern s32 DoCDVDdetectDiskType();
extern void DoCDVDresetDiskTypeCache();

View File

@ -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,19 +248,21 @@ s32 CALLBACK DISCgetBuffer(u8* dest)
return 0;
int csize = 2352;
switch (cmode) {
case CDVD_MODE_2048:
csize = 2048;
break;
case CDVD_MODE_2328:
csize = 2328;
break;
case CDVD_MODE_2340:
csize = 2340;
break;
switch (cmode)
{
case CDVD_MODE_2048:
csize = 2048;
break;
case CDVD_MODE_2328:
csize = 2328;
break;
case CDVD_MODE_2340:
csize = 2340;
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,40 +495,41 @@ s32 CALLBACK DISCreadSector(u8* buffer, u32 lsn, int mode)
s32 CALLBACK DISCgetDualInfo(s32* dualType, u32* _layer1start)
{
switch (src->GetMediaType()) {
case 1:
*dualType = 1;
*_layer1start = src->GetLayerBreakAddress() + 1;
return 0;
case 2:
*dualType = 2;
*_layer1start = src->GetLayerBreakAddress() + 1;
return 0;
case 0:
*dualType = 0;
*_layer1start = 0;
return 0;
switch (src->GetMediaType())
{
case 1:
*dualType = 1;
*_layer1start = src->GetLayerBreakAddress() + 1;
return 0;
case 2:
*dualType = 2;
*_layer1start = src->GetLayerBreakAddress() + 1;
return 0;
case 0:
*dualType = 0;
*_layer1start = 0;
return 0;
}
return -1;
}
CDVD_API CDVDapi_Disc =
{
DISCclose,
DISCopen,
DISCreadTrack,
DISCgetBuffer,
DISCreadSubQ,
DISCgetTN,
DISCgetTD,
DISCgetTOC,
DISCgetDiskType,
DISCgetTrayStatus,
DISCctrlTrayOpen,
DISCctrlTrayClose,
{
DISCclose,
DISCopen,
DISCreadTrack,
DISCgetBuffer,
DISCreadSubQ,
DISCgetTN,
DISCgetTD,
DISCgetTOC,
DISCgetDiskType,
DISCgetTrayStatus,
DISCctrlTrayOpen,
DISCctrlTrayClose,
DISCnewDiskCB,
DISCnewDiskCB,
DISCreadSector,
DISCgetDualInfo,
DISCreadSector,
DISCgetDualInfo,
};

View File

@ -25,7 +25,7 @@
const u32 sectors_per_read = 16;
static_assert(sectors_per_read > 1 && !(sectors_per_read & (sectors_per_read - 1)),
"sectors_per_read must by a power of 2");
"sectors_per_read must by a power of 2");
struct SectorInfo
{
@ -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,14 +328,15 @@ u8* cdvdGetSector(u32 sector, s32 mode)
u32 offset = 2352 * (sector - sector_block);
u8* data = buffer + offset;
switch (mode) {
case CDVD_MODE_2048:
// Data location depends on CD mode
return (data[15] & 3) == 2 ? data + 24 : data + 16;
case CDVD_MODE_2328:
return data + 24;
case CDVD_MODE_2340:
return data + 12;
switch (mode)
{
case CDVD_MODE_2048:
// Data location depends on CD mode
return (data[15] & 3) == 2 ? data + 24 : data + 16;
case CDVD_MODE_2328:
return data + 24;
case CDVD_MODE_2340:
return data + 12;
}
return data;
}
@ -321,26 +345,30 @@ s32 cdvdDirectReadSector(u32 sector, s32 mode, u8* buffer)
{
static u8 data[2352 * sectors_per_read];
if(src == nullptr)
return -1;
if (src == nullptr)
return -1;
try {
if (sector >= src->GetSectorCount())
return -1;
}
catch(...) {
return -1;
}
try
{
if (sector >= src->GetSectorCount())
return -1;
}
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,20 +377,21 @@ s32 cdvdDirectReadSector(u32 sector, s32 mode, u8* buffer)
u32 offset = 2352 * (sector - sector_block);
u8* bfr = data + offset;
switch (mode) {
case CDVD_MODE_2048:
// Data location depends on CD mode
std::memcpy(buffer, (bfr[15] & 3) == 2 ? bfr + 24 : bfr + 16, 2048);
return 0;
case CDVD_MODE_2328:
memcpy(buffer, bfr + 24, 2328);
return 0;
case CDVD_MODE_2340:
memcpy(buffer, bfr + 12, 2340);
return 0;
default:
memcpy(buffer, bfr, 2352);
return 0;
switch (mode)
{
case CDVD_MODE_2048:
// Data location depends on CD mode
std::memcpy(buffer, (bfr[15] & 3) == 2 ? bfr + 24 : bfr + 16, 2048);
return 0;
case CDVD_MODE_2328:
memcpy(buffer, bfr + 24, 2328);
return 0;
case CDVD_MODE_2340:
memcpy(buffer, bfr + 12, 2340);
return 0;
default:
memcpy(buffer, bfr, 2352);
return 0;
}
}
@ -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,19 +425,20 @@ s32 cdvdRefreshData()
curTrayStatus = CDVD_TRAY_CLOSE;
switch (curDiskType) {
case CDVD_TYPE_DETCTDVDD:
diskTypeName = "Double-Layer DVD";
break;
case CDVD_TYPE_DETCTDVDS:
diskTypeName = "Single-Layer DVD";
break;
case CDVD_TYPE_DETCTCD:
diskTypeName = "CD-ROM";
break;
case CDVD_TYPE_NODISC:
diskTypeName = "No Disc";
break;
switch (curDiskType)
{
case CDVD_TYPE_DETCTDVDD:
diskTypeName = "Double-Layer DVD";
break;
case CDVD_TYPE_DETCTDVDS:
diskTypeName = "Single-Layer DVD";
break;
case CDVD_TYPE_DETCTCD:
diskTypeName = "CD-ROM";
break;
case CDVD_TYPE_NODISC:
diskTypeName = "No Disc";
break;
}
printf(" * CDVD: Disk Type: %s\n", diskTypeName);

View File

@ -42,23 +42,24 @@ void CALLBACK ISOclose()
s32 CALLBACK ISOopen(const char* pTitle)
{
ISOclose(); // just in case
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;
}
@ -77,7 +78,7 @@ s32 CALLBACK ISOopen(const char* pTitle)
layer1start = -1;
layer1searched = false;
return 0;
}
@ -85,27 +86,27 @@ s32 CALLBACK ISOreadSubQ(u32 lsn, cdvdSubQ* subq)
{
// fake it
u8 min, sec, frm;
subq->ctrl = 4;
subq->mode = 1;
subq->trackNum = itob(1);
subq->ctrl = 4;
subq->mode = 1;
subq->trackNum = itob(1);
subq->trackIndex = itob(1);
lba_to_msf(lsn, &min, &sec, &frm);
subq->trackM = itob(min);
subq->trackS = itob(sec);
subq->trackF = itob(frm);
subq->trackM = itob(min);
subq->trackS = itob(sec);
subq->trackF = itob(frm);
subq->pad = 0;
subq->pad = 0;
lba_to_msf(lsn + (2*75), &min, &sec, &frm);
subq->discM = itob(min);
subq->discS = itob(sec);
subq->discF = itob(frm);
lba_to_msf(lsn + (2 * 75), &min, &sec, &frm);
subq->discM = itob(min);
subq->discS = itob(sec);
subq->discF = itob(frm);
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
@ -258,7 +256,7 @@ s32 CALLBACK ISOgetTOC(void* toc)
}
}
else if ((type == CDVD_TYPE_CDDA) || (type == CDVD_TYPE_PS2CDDA) ||
(type == CDVD_TYPE_PS2CD) || (type == CDVD_TYPE_PSCDDA) || (type == CDVD_TYPE_PSCD))
(type == CDVD_TYPE_PS2CD) || (type == CDVD_TYPE_PSCDDA) || (type == CDVD_TYPE_PSCD))
{
// cd toc
// (could be replaced by 1 command that reads the full toc)
@ -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;
@ -325,16 +326,16 @@ s32 CALLBACK ISOreadSector(u8* tempbuffer, u32 lsn, int mode)
iso.ReadSync(cdbuffer, lsn);
u8 *pbuffer = cdbuffer;
u8* pbuffer = cdbuffer;
int psize = 0;
switch (mode)
{
//case CDVD_MODE_2352:
//case CDVD_MODE_2352:
// Unreachable due to shortcut above.
// pxAssume(false);
// break;
// pxAssume(false);
// break;
case CDVD_MODE_2340:
pbuffer += 12;
@ -348,8 +349,8 @@ s32 CALLBACK ISOreadSector(u8* tempbuffer, u32 lsn, int mode)
pbuffer += 24;
psize = 2048;
break;
jNO_DEFAULT
jNO_DEFAULT
}
memcpy(tempbuffer, pbuffer, psize);
@ -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,28 +402,28 @@ s32 CALLBACK ISOdummyS32()
return 0;
}
void CALLBACK ISOnewDiskCB(void(* /* callback */)())
void CALLBACK ISOnewDiskCB(void (*/* callback */)())
{
}
CDVD_API CDVDapi_Iso =
{
ISOclose,
{
ISOclose,
ISOopen,
ISOreadTrack,
ISOgetBuffer,
ISOreadSubQ,
ISOgetTN,
ISOgetTD,
ISOgetTOC,
ISOgetDiskType,
ISOdummyS32, // trayStatus
ISOdummyS32, // trayOpen
ISOdummyS32, // trayClose
ISOopen,
ISOreadTrack,
ISOgetBuffer,
ISOreadSubQ,
ISOgetTN,
ISOgetTD,
ISOgetTOC,
ISOgetDiskType,
ISOdummyS32, // trayStatus
ISOdummyS32, // trayOpen
ISOdummyS32, // trayClose
ISOnewDiskCB,
ISOnewDiskCB,
ISOreadSector,
ISOgetDualInfo,
ISOreadSector,
ISOgetDualInfo,
};

View File

@ -24,142 +24,148 @@
enum cdrom_registers
{
CdlSync = 0,
CdlNop = 1,
CdlSetloc = 2,
CdlPlay = 3,
CdlForward = 4,
CdlBackward = 5,
CdlReadN = 6,
CdlStandby = 7,
CdlStop = 8,
CdlPause = 9,
CdlInit = 10,
CdlMute = 11,
CdlDemute = 12,
CdlSetfilter = 13,
CdlSetmode = 14,
CdlGetmode = 15,
CdlGetlocL = 16,
CdlGetlocP = 17,
Cdl18 = 18,
CdlGetTN = 19,
CdlGetTD = 20,
CdlSeekL = 21,
CdlSeekP = 22,
CdlTest = 25,
CdlID = 26,
CdlReadS = 27,
CdlReset = 28,
CdlReadToc = 30,
CdlSync = 0,
CdlNop = 1,
CdlSetloc = 2,
CdlPlay = 3,
CdlForward = 4,
CdlBackward = 5,
CdlReadN = 6,
CdlStandby = 7,
CdlStop = 8,
CdlPause = 9,
CdlInit = 10,
CdlMute = 11,
CdlDemute = 12,
CdlSetfilter = 13,
CdlSetmode = 14,
CdlGetmode = 15,
CdlGetlocL = 16,
CdlGetlocP = 17,
Cdl18 = 18,
CdlGetTN = 19,
CdlGetTD = 20,
CdlSeekL = 21,
CdlSeekP = 22,
CdlTest = 25,
CdlID = 26,
CdlReadS = 27,
CdlReset = 28,
CdlReadToc = 30,
AUTOPAUSE = 249,
READ_ACK = 250,
READ = 251,
REPPLAY_ACK = 252,
REPPLAY = 253,
ASYNC = 254
/* don't set 255, it's reserved */
AUTOPAUSE = 249,
READ_ACK = 250,
READ = 251,
REPPLAY_ACK = 252,
REPPLAY = 253,
ASYNC = 254
/* don't set 255, it's reserved */
};
const char *CmdName[0x100]= {
"CdlSync", "CdlNop", "CdlSetloc", "CdlPlay",
"CdlForward", "CdlBackward", "CdlReadN", "CdlStandby",
"CdlStop", "CdlPause", "CdlInit", "CdlMute",
"CdlDemute", "CdlSetfilter", "CdlSetmode", "CdlGetmode",
"CdlGetlocL", "CdlGetlocP", "Cdl18", "CdlGetTN",
"CdlGetTD", "CdlSeekL", "CdlSeekP", NULL,
NULL, "CdlTest", "CdlID", "CdlReadS",
"CdlReset", NULL, "CDlReadToc", NULL
};
const char* CmdName[0x100] = {
"CdlSync", "CdlNop", "CdlSetloc", "CdlPlay",
"CdlForward", "CdlBackward", "CdlReadN", "CdlStandby",
"CdlStop", "CdlPause", "CdlInit", "CdlMute",
"CdlDemute", "CdlSetfilter", "CdlSetmode", "CdlGetmode",
"CdlGetlocL", "CdlGetlocP", "Cdl18", "CdlGetTN",
"CdlGetTD", "CdlSeekL", "CdlSeekP", NULL,
NULL, "CdlTest", "CdlID", "CdlReadS",
"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
//backported from PCSXR
// cdr.Stat:
#define NoIntr 0
#define DataReady 1
#define Complete 2
#define Acknowledge 3
#define DataEnd 4
#define DiskError 5
#define NoIntr 0
#define DataReady 1
#define Complete 2
#define Acknowledge 3
#define DataEnd 4
#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
// so (PSXCLK / 75) / BIAS = cdr read time (linuzappz)
u32 cdReadTime; // = ((PSXCLK / 75) / BIAS);
#define CDR_INT(eCycle) PSX_INT(IopEvt_Cdrom, eCycle)
#define CDR_INT(eCycle) PSX_INT(IopEvt_Cdrom, eCycle)
#define CDREAD_INT(eCycle) PSX_INT(IopEvt_CdromRead, eCycle)
const uint shortSectorSeekReadDelay = 1000; // delay for reads/seeks that may or may not have a seek action preceeding it
uint sectorSeekReadDelay = 0x800; // for calculated seek delays
uint sectorSeekReadDelay = 0x800; // for calculated seek delays
static void AddIrqQueue(u8 irq, u32 ecycle);
static __fi void StartReading(u32 type) {
cdr.Reading = type;
cdr.FirstSector = 1;
cdr.Readed = 0xff;
static __fi void StartReading(u32 type)
{
cdr.Reading = type;
cdr.FirstSector = 1;
cdr.Readed = 0xff;
//DevCon.Warning("ReadN/ReadS delay: %d", sectorSeekReadDelay);
AddIrqQueue(READ_ACK, sectorSeekReadDelay);
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) {
cdr.ResultP = 0;
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;
@ -252,7 +265,7 @@ void cdrInterrupt() {
cdr.StatP &= ~STATUS_ROTATING;
cdr.Result[0] = cdr.StatP;
cdr.Stat = Complete;
// cdr.Stat = Acknowledge;
// cdr.Stat = Acknowledge;
break;
case CdlPause:
@ -276,7 +289,7 @@ void cdrInterrupt() {
cdr.Result[0] = cdr.StatP;
cdr.Stat = Acknowledge;
AddIrqQueue(CdlInit + 0x20, 0x800);
break;
break;
case CdlInit + 0x20:
SetResultSize(1);
@ -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;
@ -439,13 +459,14 @@ void cdrInterrupt() {
case CdlID + 0x20:
SetResultSize(8);
cdr.Result[0] = 0x00; // 0x08 and cdr.Result[1]|0x10 : audio cd, enters cd player
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;
@ -687,19 +728,22 @@ void cdrWrite1(u8 rt) {
case CdlSetloc:
{
//StopReading();
// Setloc is memorizing the wanted target, and marks it as unprocessed, and has no other effect
// 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;
@ -880,17 +926,21 @@ void cdrWrite1(u8 rt) {
default:
DevCon.Warning("Unknown CD Cmd: %x\n", cdr.Cmd);
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,13 +948,16 @@ 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.ParamP = 0;
cdr.ParamC = 0;
cdr.ResultReady = 0;
cdr.Ctrl = 0;
@ -917,69 +970,89 @@ 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
psxDmaInterrupt(3); //hack
return;
}
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);
}

View File

@ -20,18 +20,20 @@
#include "CDVDaccess.h"
// Not used.
typedef struct {
s32 y0, y1;
typedef struct
{
s32 y0, y1;
} ADPCM_Decode_t;
// Not used.
typedef struct {
s32 freq;
s32 nbits;
s32 stereo;
s32 nsamples;
ADPCM_Decode_t left, right;
s16 pcm[16384];
typedef struct
{
s32 freq;
s32 nbits;
s32 stereo;
s32 nsamples;
ADPCM_Decode_t left, right;
s16 pcm[16384];
} xa_decode_t;
struct cdrStruct
@ -46,7 +48,7 @@ struct cdrStruct
u8 StatP;
u8 Transfer[2352];
u8 *pTransfer;
u8* pTransfer;
u8 Prev[4];
u8 Param[8];
@ -87,12 +89,12 @@ struct cdrStruct
extern cdrStruct cdr;
void cdrReset();
void cdrInterrupt();
void cdrReadInterrupt();
u8 cdrRead0(void);
u8 cdrRead1(void);
u8 cdrRead2(void);
u8 cdrRead3(void);
void cdrInterrupt();
void cdrReadInterrupt();
u8 cdrRead0(void);
u8 cdrRead1(void);
u8 cdrRead2(void);
u8 cdrRead3(void);
void setPsxSpeed();
void cdrWrite0(u8 rt);
void cdrWrite1(u8 rt);

View File

@ -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;
}

View File

@ -19,34 +19,43 @@
#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); };
void Take(void* pMallocedSrc, PX_off_t offset, int length, int coverage);
int Read(void* pDest, PX_off_t offset, int length);
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;

View File

@ -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.

View File

@ -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.

View File

@ -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 //////////

View File

@ -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.
}

View File

@ -35,28 +35,32 @@ 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;
};
virtual ~CsoFileReader(void) { Close(); };
static bool CanHandle(const wxString& fileName);
static bool CanHandle(const wxString& fileName);
virtual bool Open(const wxString& fileName);
virtual int ReadSync(void* pBuffer, uint sector, uint count);
@ -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;

View File

@ -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;
@ -37,23 +38,26 @@ static s64 fsize(const wxString& filename) {
}
#define GZIP_ID "PCSX2.index.gzip.v1|"
#define GZIP_ID_LEN (sizeof(GZIP_ID) - 1) /* sizeof includes the \0 terminator */
#define GZIP_ID_LEN (sizeof(GZIP_ID) - 1) /* sizeof includes the \0 terminator */
// File format is:
// - [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,22 +122,22 @@ 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,
bool canEndWithKey)
static wxString ApplyTemplate(const wxString& name, const wxDirName& base,
const wxString& fileTemplate, const wxString& filename,
bool canEndWithKey)
{
wxString tem(fileTemplate);
wxString key = INDEX_TEMPLATE_KEY;
tem = tem.Trim(true).Trim(false); // both sides
size_t first = tem.find(key);
if (first == wxString::npos // not found
|| first != tem.rfind(key) // more than one instance
|| !canEndWithKey && first == tem.length() - key.length())
if (first == wxString::npos // not found
|| first != tem.rfind(key) // more than one instance
|| !canEndWithKey && first == tem.length() - key.length())
{
Console.Error(L"Invalid %s template '%s'.\n"
L"Template must contain exactly one '%s' and must not end with it. Abotring.",
WX_STR(name), WX_STR(tem), WX_STR(key));
L"Template must contain exactly one '%s' and must not end with it. Abotring.",
WX_STR(name), WX_STR(tem), WX_STR(key));
return L"";
}
@ -169,26 +179,30 @@ 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());
(wxDirName)(wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath());
//TestTemplate(appRoot, isoname, false);
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,11 +311,13 @@ 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);
(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.");
Console.Warning(L"(smaller intervals mean bigger index file and quicker but more frequent decompressions)");
}
@ -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)
@ -454,17 +491,19 @@ int GzippedFileReader::_ReadSync(void* pBuffer, PX_off_t offset, uint bytesToRea
int duration = NOW() - s;
if (duration > 10)
Console.WriteLn(Color_Gray, L"gunzip: chunk #%5d-%2d : %1.2f MB - %d ms",
(int)(offset / 4 / 1024 / 1024),
(int)(offset % (4 * 1024 * 1024) / GZFILE_READ_CHUNK_SIZE),
(float)size / 1024 / 1024,
duration);
(int)(offset / 4 / 1024 / 1024),
(int)(offset % (4 * 1024 * 1024) / GZFILE_READ_CHUNK_SIZE),
(float)size / 1024 / 1024,
duration);
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;
}

View File

@ -21,30 +21,32 @@ typedef struct zstate Zstate;
#include "ChunksCache.h"
#include "zlib_indexed.h"
#define GZFILE_SPAN_DEFAULT (1048576L * 4) /* distance between direct access points when creating a new index */
#define GZFILE_READ_CHUNK_SIZE (256 * 1024) /* zlib extraction chunks size (at 0-based boundaries) */
#define GZFILE_CACHE_SIZE_MB 200 /* cache size for extracted data. must be at least GZFILE_READ_CHUNK_SIZE (in MB)*/
#define GZFILE_SPAN_DEFAULT (1048576L * 4) /* distance between direct access points when creating a new index */
#define GZFILE_READ_CHUNK_SIZE (256 * 1024) /* zlib extraction chunks size (at 0-based boundaries) */
#define GZFILE_CACHE_SIZE_MB 200 /* cache size for extracted data. must be at least GZFILE_READ_CHUNK_SIZE (in MB)*/
class GzippedFileReader : public AsyncFileReader
{
DeclareNoncopyableObject(GzippedFileReader);
public:
GzippedFileReader(void);
virtual ~GzippedFileReader(void) { Close(); };
static bool CanHandle(const wxString& fileName);
static bool CanHandle(const wxString& fileName);
virtual bool Open(const wxString& fileName);
virtual int ReadSync(void* pBuffer, uint sector, uint count);
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;
@ -65,15 +70,15 @@ private:
Zstate state;
};
bool OkIndex(); // Verifies that we have an index, or try to create one
bool OkIndex(); // Verifies that we have an index, or try to create one
PX_off_t GetOptimalExtractionStart(PX_off_t offset);
int _ReadSync(void* pBuffer, PX_off_t offset, uint bytesToRead);
void InitZstates();
int _ReadSync(void* pBuffer, PX_off_t offset, uint bytesToRead);
void InitZstates();
int mBytesRead; // Temp sync read result when simulating async read
Access* m_pIndex; // Quick access index
int mBytesRead; // Temp sync read result when simulating async read
Access* m_pIndex; // Quick access index
Czstate* m_zstates;
FILE* m_src;
FILE* m_src;
ChunksCache m_cache;

View File

@ -22,15 +22,21 @@
static const char* nameFromType(int 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";
}
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";
}
}
int InputIsoFile::ReadSync(u8* dst, uint lsn)
@ -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,33 +99,33 @@ 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;
}
switch (mode)
{
case CDVD_MODE_2352:
_offset = 0;
length = 2352;
break;
case CDVD_MODE_2340:
_offset = 12;
length = 2340;
break;
case CDVD_MODE_2328:
_offset = 24;
length = 2328;
break;
case CDVD_MODE_2048:
_offset = 24;
length = 2048;
break;
case CDVD_MODE_2352:
_offset = 0;
length = 2352;
break;
case CDVD_MODE_2340:
_offset = 12;
length = 2340;
break;
case CDVD_MODE_2328:
_offset = 24;
length = 2328;
break;
case CDVD_MODE_2048:
_offset = 24;
length = 2048;
break;
}
int end1 = m_blockofs + m_blocksize;
@ -128,12 +134,12 @@ 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;
}
else
else
{
ndiff = -diff;
diff = 0;
@ -143,7 +149,7 @@ int InputIsoFile::FinishRead3(u8* dst, uint mode)
uint read_offset = (m_current_lsn - m_read_lsn) * m_blocksize;
memcpy(dst + diff, m_readbuffer + ndiff + read_offset, length);
if (m_type == ISOTYPE_CD && diff >= 12)
{
lsn_to_msf(dst + diff - 12, m_current_lsn);
@ -165,14 +171,14 @@ InputIsoFile::~InputIsoFile()
void InputIsoFile::_init()
{
m_type = ISOTYPE_ILLEGAL;
m_flags = 0;
m_type = ISOTYPE_ILLEGAL;
m_flags = 0;
m_offset = 0;
m_blockofs = 0;
m_blocksize = 0;
m_blocks = 0;
m_offset = 0;
m_blockofs = 0;
m_blocksize = 0;
m_blocks = 0;
m_read_inprogress = false;
m_read_count = 0;
ReadUnit = 0;
@ -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;
@ -209,7 +215,7 @@ bool InputIsoFile::Open( const wxString& srcfile, bool testOnly )
m_reader = CompressedFileReader::GetNewReader(m_filename);
isCompressed = m_reader != NULL;
// If it wasn't compressed, let's open it has a FlatFileReader.
// If it wasn't compressed, let's open it has a FlatFileReader.
if (!isCompressed)
{
// Allow write sharing of the iso based on the ini settings.
@ -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();
@ -239,25 +245,25 @@ bool InputIsoFile::Open( const wxString& srcfile, bool testOnly )
}
bool detected = Detect();
if(testOnly)
if (testOnly)
return detected;
if (!detected)
throw Exception::BadStream()
.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;
m_reader->SetDataOffset(m_offset);
m_reader->SetBlockSize(m_blocksize);
// Returns the original reader if single-part or a Multipart reader otherwise
AsyncFileReader* m_reader_old = m_reader;
m_reader = MultipartFileReader::DetectMultipart(m_reader);
m_reader = MultipartFileReader::DetectMultipart(m_reader);
if (m_reader != m_reader_old) // Not the same object the old one need to be deleted
delete m_reader_old;
}
@ -268,12 +274,12 @@ bool InputIsoFile::Open( const wxString& srcfile, bool testOnly )
ConsoleIndentScope indent;
Console.WriteLn("Image type = %s", nameFromType(m_type));
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;
}
@ -282,7 +288,7 @@ void InputIsoFile::Close()
{
delete m_reader;
m_reader = NULL;
_init();
}
@ -295,20 +301,20 @@ bool InputIsoFile::tryIsoType(u32 _size, s32 _offset, s32 _blockofs)
{
static u8 buf[2456];
m_blocksize = _size;
m_offset = _offset;
m_blockofs = _blockofs;
m_blocksize = _size;
m_offset = _offset;
m_blockofs = _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.
}
@ -316,14 +322,14 @@ bool InputIsoFile::tryIsoType(u32 _size, s32 _offset, s32 _blockofs)
// based on florin's CDVDbin detection code :)
// Parameter:
//
//
//
// 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;
AsyncFileReader* headpart = m_reader;
// First sanity check: no sane CD image has less than 16 sectors, since that's what
// we need simply to contain a TOC. So if the file size is not large enough to
// accommodate that, it is NOT a CD image --->
@ -335,24 +341,34 @@ 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;
m_blockofs = 0;
m_type = ISOTYPE_AUDIO;
m_offset = 0;
m_blocksize = CD_FRAMESIZE_RAW;
m_blockofs = 0;
m_type = ISOTYPE_AUDIO;
m_reader->SetDataOffset(m_offset);
m_reader->SetBlockSize(m_blocksize);

View File

@ -17,16 +17,16 @@
enum IsoFS_Type
{
FStype_ISO9660 = 1,
FStype_Joliet = 2,
FStype_ISO9660 = 1,
FStype_Joliet = 2,
};
class IsoDirectory
{
public:
SectorSource& internalReader;
std::vector<IsoFileDescriptor> files;
IsoFS_Type m_fstype;
SectorSource& internalReader;
std::vector<IsoFileDescriptor> files;
IsoFS_Type m_fstype;
public:
IsoDirectory(SectorSource& r);
@ -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;

View File

@ -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,56 +54,56 @@ IsoDirectory::IsoDirectory(SectorSource& r)
m_fstype = FStype_ISO9660;
while( !done )
while (!done)
{
u8 sector[2048];
internalReader.readSector(sector,i);
if( memcmp( &sector[1], "CD001", 5 ) == 0 )
internalReader.readSector(sector, i);
if (memcmp(&sector[1], "CD001", 5) == 0)
{
switch (sector[0])
{
case 0:
DevCon.WriteLn( Color_Green, "(IsoFS) Block 0x%x: Boot partition info.", i );
break;
switch (sector[0])
{
case 0:
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 );
isValid = true;
break;
case 1:
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 );
m_fstype = FStype_Joliet;
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);
m_fstype = FStype_Joliet;
break;
case 0xff:
// Null terminator. End of partition information.
done = true;
break;
break;
default:
Console.Error( "(IsoFS) Unknown partition type ID=%d, encountered at block 0x%x", sector[0], i );
break;
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, &sector[1] );
break; // if no valid root partition was found, an exception will be thrown below.
Console.Error("(IsoFS) Invalid partition descriptor encountered at block 0x%x: '%s'", i, &sector[1]);
break; // if no valid root partition was found, an exception will be thrown below.
}
++i;
}
if( !isValid )
throw Exception::FileNotFound(L"IsoFileSystem") // FIXME: Should report the name of the ISO here...
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,70 +197,77 @@ 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()
{
lba = 0;
size = 0;
lba = 0;
size = 0;
flags = 0;
memset(&date, 0, sizeof(date));
}
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];
lba = (u32&)data[2];
size = (u32&)data[10];
date.year = data[18] + 1900;
date.month = data[19];
date.day = data[20];
date.hour = data[21];
date.minute = data[22];
date.second = data[23];
date.year = data[18] + 1900;
date.month = data[19];
date.day = data[20];
date.hour = data[21];
date.minute = data[22];
date.second = data[23];
date.gmtOffset = data[24];
flags = data[25];
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;

View File

@ -23,4 +23,3 @@ struct ISoFileDescriptor;
#include "IsoFileDescriptor.h"
#include "IsoDirectory.h"
#include "IsoFile.h"

View File

@ -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;
}

View File

@ -19,7 +19,7 @@
#include "SectorSource.h"
class IsoFSCDVD: public SectorSource
class IsoFSCDVD : public SectorSource
{
public:
IsoFSCDVD();
@ -27,5 +27,5 @@ public:
virtual bool readSector(unsigned char* buffer, int lba);
virtual int getNumSectors();
virtual int getNumSectors();
};

View File

@ -14,7 +14,7 @@
*/
#include "PrecompiledHeader.h"
#include "PrecompiledHeader.h"
#include "IsoFS.h"
#include "IsoFile.h"
@ -44,12 +44,12 @@ void IsoFile::Init()
{
//pxAssertDev( fileEntry.IsFile(), "IsoFile Error: Filename points to a directory." );
currentSectorNumber = fileEntry.lba;
currentOffset = 0;
sectorOffset = 0;
maxOffset = std::max<u32>( 0, fileEntry.size );
currentSectorNumber = fileEntry.lba;
currentOffset = 0;
sectorOffset = 0;
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,24 +76,24 @@ 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;
jNO_DEFAULT;
}
return 0; // unreachable
return 0; // unreachable
}
void IsoFile::reset()
@ -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;

View File

@ -24,14 +24,14 @@ public:
static const int sectorLength = 2048;
protected:
SectorSource& internalReader;
IsoFileDescriptor fileEntry;
SectorSource& internalReader;
IsoFileDescriptor fileEntry;
u32 currentOffset;
u32 maxOffset;
int currentSectorNumber;
u8 currentSector[sectorLength];
u8 currentSector[sectorLength];
int sectorOffset;
public:
@ -51,26 +51,26 @@ public:
const IsoFileDescriptor& getEntry();
u8 readByte();
s32 read(void* dest, s32 len);
u8 readByte();
s32 read(void* dest, s32 len);
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;
}
}
protected:
void makeDataAvailable();
int internalRead(void* dest, int off, int len);
int internalRead(void* dest, int off, int len);
void Init();
};

View File

@ -19,25 +19,25 @@ struct IsoFileDescriptor
{
struct FileDate // not 1:1 with iso9660 date struct
{
s32 year;
u8 month;
u8 day;
u8 hour;
u8 minute;
u8 second;
u8 gmtOffset; // Offset from Greenwich Mean Time in number of 15 min intervals from -48 (West) to + 52 (East)
s32 year;
u8 month;
u8 day;
u8 hour;
u8 minute;
u8 second;
u8 gmtOffset; // Offset from Greenwich Mean Time in number of 15 min intervals from -48 (West) to + 52 (East)
} date;
u32 lba;
u32 size;
int flags;
u32 lba;
u32 size;
int flags;
wxString name;
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(); }

View File

@ -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;
};

View File

@ -30,66 +30,66 @@ enum isoType
ISOTYPE_DVDDL
};
static const int CD_FRAMESIZE_RAW = 2448;
static const int CD_FRAMESIZE_RAW = 2448;
// --------------------------------------------------------------------------------------
// isoFile
// --------------------------------------------------------------------------------------
class InputIsoFile
{
DeclareNoncopyableObject( InputIsoFile );
static const uint MaxReadUnit = 128;
DeclareNoncopyableObject(InputIsoFile);
static const uint MaxReadUnit = 128;
protected:
uint ReadUnit;
uint ReadUnit;
protected:
wxString m_filename;
AsyncFileReader* m_reader;
wxString m_filename;
AsyncFileReader* m_reader;
u32 m_current_lsn;
u32 m_current_lsn;
isoType m_type;
u32 m_flags;
isoType m_type;
u32 m_flags;
s32 m_offset;
s32 m_blockofs;
u32 m_blocksize;
s32 m_offset;
s32 m_blockofs;
u32 m_blocksize;
// total number of blocks in the ISO image (including all parts)
u32 m_blocks;
bool m_read_inprogress;
uint m_read_lsn;
uint m_read_count;
u8 m_readbuffer[MaxReadUnit * CD_FRAMESIZE_RAW];
public:
u32 m_blocks;
bool m_read_inprogress;
uint m_read_lsn;
uint m_read_count;
u8 m_readbuffer[MaxReadUnit * CD_FRAMESIZE_RAW];
public:
InputIsoFile();
virtual ~InputIsoFile();
bool IsOpened() const;
isoType GetType() const { return m_type; }
uint GetBlockCount() const { return m_blocks; }
int GetBlockOffset() const { return m_blockofs; }
isoType GetType() const { return m_type; }
uint GetBlockCount() const { return m_blocks; }
int GetBlockOffset() const { return m_blockofs; }
const wxString& GetFilename() const
{
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);
void BeginRead2(uint lsn);
int FinishRead3(u8* dest, uint mode);
protected:
void _init();
@ -99,32 +99,32 @@ protected:
class OutputIsoFile
{
DeclareNoncopyableObject( OutputIsoFile );
DeclareNoncopyableObject(OutputIsoFile);
protected:
wxString m_filename;
wxString m_filename;
u32 m_version;
u32 m_version;
s32 m_offset;
s32 m_blockofs;
u32 m_blocksize;
s32 m_offset;
s32 m_blockofs;
u32 m_blocksize;
// total number of blocks in the ISO image (including all parts)
u32 m_blocks;
u32 m_blocks;
// dtable is used when reading blockdumps
std::vector<u32> m_dtable;
std::unique_ptr<wxFileOutputStream> m_outstream;
public:
std::unique_ptr<wxFileOutputStream> m_outstream;
public:
OutputIsoFile();
virtual ~OutputIsoFile();
bool IsOpened() const;
u32 GetBlockSize() const;
const wxString& GetFilename() const
{
return m_filename;
@ -136,15 +136,15 @@ public:
void WriteHeader(int blockofs, uint blocksize, uint blocks);
void WriteSector(const u8* src, uint lsn);
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));
}
};

View File

@ -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();

View File

@ -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);
}
@ -97,10 +98,10 @@ bool IOCtlSrc::ReadSectors2048(u32 sector, u32 count, u8* buffer) const
if (bytes_read == -1)
fprintf(stderr, " * CDVD read sectors %u-%u failed: %s\n",
sector, sector + count - 1, strerror(errno));
sector, sector + count - 1, strerror(errno));
else
fprintf(stderr, " * CDVD read sectors %u-%u: %zd bytes read, %zd bytes expected\n",
sector, sector + count - 1, bytes_read, bytes_to_read);
sector, sector + count - 1, bytes_read, bytes_to_read);
return false;
}
@ -113,12 +114,14 @@ 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));
lba, strerror(errno));
return false;
}
memcpy(buffer, data.buffer, CD_FRAMESIZE_RAW);
@ -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;

View File

@ -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();
}
@ -41,12 +42,12 @@ OutputIsoFile::~OutputIsoFile()
void OutputIsoFile::_init()
{
m_version = 0;
m_version = 0;
m_offset = 0;
m_blockofs = 0;
m_blocksize = 0;
m_blocks = 0;
m_offset = 0;
m_blockofs = 0;
m_blocksize = 0;
m_blocks = 0;
}
void OutputIsoFile::Create(const wxString& filename, int version)
@ -54,13 +55,13 @@ void OutputIsoFile::Create(const wxString& filename, int version)
Close();
m_filename = filename;
m_version = version;
m_offset = 0;
m_blockofs = 24;
m_blocksize = 2048;
m_version = version;
m_offset = 0;
m_blockofs = 24;
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));
}
@ -68,9 +69,9 @@ void OutputIsoFile::Create(const wxString& filename, int version)
// Generates format header information for blockdumps.
void OutputIsoFile::WriteHeader(int _blockofs, uint _blocksize, uint _blocks)
{
m_blocksize = _blocksize;
m_blocks = _blocks;
m_blockofs = _blockofs;
m_blocksize = _blocksize;
m_blocks = _blocks;
m_blockofs = _blockofs;
Console.WriteLn("blockoffset = %d", m_blockofs);
Console.WriteLn("blocksize = %u", m_blocksize);
@ -88,23 +89,23 @@ void OutputIsoFile::WriteHeader(int _blockofs, uint _blocksize, uint _blocks)
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();
}
}

View File

@ -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())
{

View File

@ -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);
}
@ -53,15 +54,15 @@ bool IOCtlSrc::Reopen()
// SPTI only works if the device is opened with GENERIC_WRITE access.
m_device = CreateFile(m_filename.c_str(), GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ, nullptr, OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN, nullptr);
FILE_SHARE_READ, nullptr, OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN, nullptr);
if (m_device == INVALID_HANDLE_VALUE)
return false;
DWORD unused;
// Required to read from layer 1 of Dual layer DVDs
DeviceIoControl(m_device, FSCTL_ALLOW_EXTENDED_DASD_IO, nullptr, 0, nullptr,
0, &unused, nullptr);
0, &unused, nullptr);
if (ReadDVDInfo() || ReadCDInfo())
SetSpindleSpeed(false);
@ -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,23 +120,26 @@ 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());
sector, GetLastError());
return false;
}
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);
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());
sector, sector + count - 1, GetLastError());
}
return false;
@ -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,10 +212,10 @@ 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))
buffer.data(), buffer.size(), &unused, nullptr))
return false;
auto& layer = *reinterpret_cast<DVD_LAYER_DESCRIPTOR*>(
@ -216,17 +224,19 @@ 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),
buffer.data(), buffer.size(), &unused, nullptr))
buffer.data(), buffer.size(), &unused, nullptr))
return false;
u32 layer1_start_sector = _byteswap_ulong(layer.StartingDataSector);
u32 layer1_end_sector = _byteswap_ulong(layer.EndDataSector);
@ -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;
@ -256,23 +267,24 @@ bool IOCtlSrc::ReadCDInfo()
CDROM_TOC toc;
if (!DeviceIoControl(m_device, IOCTL_CDROM_READ_TOC_EX, &toc_ex,
sizeof(toc_ex), &toc, sizeof(toc), &unused, nullptr))
sizeof(toc_ex), &toc, sizeof(toc), &unused, nullptr))
return false;
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;
if (!DeviceIoControl(m_device, IOCTL_DISK_GET_LENGTH_INFO, nullptr, 0, &info,
sizeof(info), &unused, nullptr))
sizeof(info), &unused, nullptr))
return false;
m_sectors = static_cast<u32>(info.Length.QuadPart / 2048);
@ -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;

View File

@ -112,19 +112,20 @@ Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
#define local static
//#define SPAN (1048576L) /* desired distance between access points */
#define WINSIZE 32768U /* sliding window size */
#define CHUNK (64 * 1024) /* file input buffer size */
#define WINSIZE 32768U /* sliding window size */
#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 {
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 */
unsigned char window[WINSIZE]; /* preceding 32K of uncompressed data */
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 */
unsigned char window[WINSIZE]; /* preceding 32K of uncompressed data */
}
#ifndef _WIN32
__attribute__((packed))
@ -134,13 +135,14 @@ __attribute__((packed))
typedef struct point Point;
/* access point list */
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 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 */
s32 span; /* once the index is built, holds the span size used to build it */
PX_off_t uncompressed_size; /* filled by build_index */
s32 span; /* once the index is built, holds the span size used to build it */
PX_off_t uncompressed_size; /* filled by build_index */
}
#ifndef _WIN32
__attribute__((packed))
@ -150,62 +152,68 @@ __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) {
free(index->list);
free(index);
}
if (index != NULL)
{
free(index->list);
free(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) {
index = (Access*)malloc(sizeof(struct access));
if (index == NULL) return NULL;
index->list = (Point*)malloc(sizeof(struct point) << 3);
if (index->list == NULL) {
free(index);
return NULL;
}
index->size = 8;
index->have = 0;
}
/* if list is empty, create it (start with eight points) */
if (index == NULL)
{
index = (Access*)malloc(sizeof(struct access));
if (index == NULL)
return NULL;
index->list = (Point*)malloc(sizeof(struct point) << 3);
if (index->list == NULL)
{
free(index);
return NULL;
}
index->size = 8;
index->have = 0;
}
/* if list is full, make it bigger */
else if (index->have == index->size) {
index->size <<= 1;
next = (Point*)realloc(index->list, sizeof(struct point) * index->size);
if (next == NULL) {
free_index(index);
return NULL;
}
index->list = next;
}
/* if list is full, make it bigger */
else if (index->have == index->size)
{
index->size <<= 1;
next = (Point*)realloc(index->list, sizeof(struct point) * index->size);
if (next == NULL)
{
free_index(index);
return NULL;
}
index->list = next;
}
/* fill in entry and increment how many we have */
next = index->list + index->have;
next->bits = bits;
next->in = in;
next->out = out;
if (left)
memcpy(next->window, window + WINSIZE - left, left);
if (left < WINSIZE)
memcpy(next->window + left, window, WINSIZE - left);
index->have++;
/* fill in entry and increment how many we have */
next = index->list + index->have;
next->bits = bits;
next->in = in;
next->out = out;
if (left)
memcpy(next->window, window + WINSIZE - left, left);
if (left < WINSIZE)
memcpy(next->window + left, window, WINSIZE - left);
index->have++;
/* return list, possibly reallocated */
return index;
/* return list, possibly reallocated */
return index;
}
/* Make one entire pass through the compressed stream and build an index, with
@ -216,68 +224,73 @@ 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 */
z_stream strm;
unsigned char input[CHUNK];
unsigned char window[WINSIZE];
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 */
z_stream strm;
unsigned char input[CHUNK];
unsigned char window[WINSIZE];
/* initialize inflate */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit2(&strm, 47); /* automatic zlib or gzip decoding */
if (ret != Z_OK)
return ret;
/* initialize inflate */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit2(&strm, 47); /* automatic zlib or gzip decoding */
if (ret != Z_OK)
return ret;
/* inflate the input, maintain a sliding window, and build an index -- this
/* inflate the input, maintain a sliding window, and build an index -- this
also validates the integrity of the compressed data using the check
information at the end of the gzip or zlib stream */
totin = totout = last = totPrinted = 0;
index = NULL; /* will be allocated by first addpoint() */
strm.avail_out = 0;
do {
/* get some compressed data from input file */
strm.avail_in = fread(input, 1, CHUNK, in);
if (ferror(in)) {
ret = Z_ERRNO;
goto build_index_error;
}
if (strm.avail_in == 0) {
ret = Z_DATA_ERROR;
goto build_index_error;
}
strm.next_in = input;
totin = totout = last = totPrinted = 0;
index = NULL; /* will be allocated by first addpoint() */
strm.avail_out = 0;
do
{
/* get some compressed data from input file */
strm.avail_in = fread(input, 1, CHUNK, in);
if (ferror(in))
{
ret = Z_ERRNO;
goto build_index_error;
}
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 {
/* reset sliding window if necessary */
if (strm.avail_out == 0) {
strm.avail_out = WINSIZE;
strm.next_out = window;
}
/* process all of that, or until end of stream */
do
{
/* reset sliding window if necessary */
if (strm.avail_out == 0)
{
strm.avail_out = WINSIZE;
strm.next_out = window;
}
/* inflate until out of input, output, or at end of block --
/* inflate until out of input, output, or at end of block --
update the total input and output counters */
totin += strm.avail_in;
totout += strm.avail_out;
ret = inflate(&strm, Z_BLOCK); /* return at end of block */
totin -= strm.avail_in;
totout -= strm.avail_out;
if (ret == Z_NEED_DICT)
ret = Z_DATA_ERROR;
if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR)
goto build_index_error;
if (ret == Z_STREAM_END)
break;
totin += strm.avail_in;
totout += strm.avail_out;
ret = inflate(&strm, Z_BLOCK); /* return at end of block */
totin -= strm.avail_in;
totout -= strm.avail_out;
if (ret == Z_NEED_DICT)
ret = Z_DATA_ERROR;
if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR)
goto build_index_error;
if (ret == Z_STREAM_END)
break;
/* if at end of block, consider adding an index entry (note that if
/* if at end of block, consider adding an index entry (note that if
data_type indicates an end-of-block, then all of the
uncompressed data from that block has been delivered, and none
of the compressed data after that block has been consumed,
@ -286,53 +299,59 @@ local int build_index(FILE *in, PX_off_t span, struct access **built)
index always has at least one access point; we avoid creating an
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)) {
index = addpoint(index, strm.data_type & 7, totin,
totout, strm.avail_out, window);
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)) {
printf("%dMB ", (int)(totin / (1024 * 1024)));
totPrinted = totin;
}
} while (ret != Z_STREAM_END);
if ((strm.data_type & 128) && !(strm.data_type & 64) &&
(totout == 0 || totout - last > span))
{
index = addpoint(index, strm.data_type & 7, totin,
totout, strm.avail_out, window);
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))
{
printf("%dMB ", (int)(totin / (1024 * 1024)));
totPrinted = totin;
}
} while (ret != Z_STREAM_END);
if (index == NULL) {
// Could happen if the start of the stream in Z_STREAM_END
return 0;
}
if (index == NULL)
{
// Could happen if the start of the stream in Z_STREAM_END
return 0;
}
/* clean up and return index (release unused entries in list) */
(void)inflateEnd(&strm);
index->list = (Point*)realloc(index->list, sizeof(struct point) * index->have);
index->size = index->have;
index->span = span;
index->uncompressed_size = totout;
*built = index;
return index->have;
/* clean up and return index (release unused entries in list) */
(void)inflateEnd(&strm);
index->list = (Point*)realloc(index->list, sizeof(struct point) * index->have);
index->size = index->have;
index->span = span;
index->uncompressed_size = totout;
*built = index;
return index->have;
/* return error */
build_index_error:
(void)inflateEnd(&strm);
if (index != NULL)
free_index(index);
return ret;
/* return error */
build_index_error:
(void)inflateEnd(&strm);
if (index != NULL)
free_index(index);
return ret;
}
typedef struct zstate {
PX_off_t out_offset;
PX_off_t in_offset;
z_stream strm;
int isValid;
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,131 +362,147 @@ 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;
unsigned char input[CHUNK];
unsigned char discard[WINSIZE];
int isEnd = 0;
int ret, skip;
struct point* here;
unsigned char input[CHUNK];
unsigned char discard[WINSIZE];
int isEnd = 0;
/* proceed only if something reasonable to do */
if (len < 0 || state == nullptr)
return 0;
/* proceed only if something reasonable to do */
if (len < 0 || state == nullptr)
return 0;
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 && 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) {
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 {
/* find where in stream to start */
here = index->list;
ret = index->have;
while (--ret && here[1].out <= offset)
here++;
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
{
/* find where in stream to start */
here = index->list;
ret = index->have;
while (--ret && here[1].out <= offset)
here++;
/* initialize file and inflate state to start there */
state->strm.zalloc = Z_NULL;
state->strm.zfree = Z_NULL;
state->strm.opaque = Z_NULL;
state->strm.avail_in = 0;
state->strm.next_in = Z_NULL;
ret = inflateInit2(&state->strm, -15); /* raw inflate */
if (ret != Z_OK)
return ret;
ret = PX_fseeko(in, here->in - (here->bits ? 1 : 0), SEEK_SET);
if (ret == -1)
goto extract_ret;
if (here->bits) {
ret = getc(in);
if (ret == -1) {
ret = ferror(in) ? Z_ERRNO : Z_DATA_ERROR;
goto extract_ret;
}
inflatePrime(&state->strm, here->bits, ret >> (8 - here->bits));
}
inflateSetDictionary(&state->strm, here->window, WINSIZE);
/* initialize file and inflate state to start there */
state->strm.zalloc = Z_NULL;
state->strm.zfree = Z_NULL;
state->strm.opaque = Z_NULL;
state->strm.avail_in = 0;
state->strm.next_in = Z_NULL;
ret = inflateInit2(&state->strm, -15); /* raw inflate */
if (ret != Z_OK)
return ret;
ret = PX_fseeko(in, here->in - (here->bits ? 1 : 0), SEEK_SET);
if (ret == -1)
goto extract_ret;
if (here->bits)
{
ret = getc(in);
if (ret == -1)
{
ret = ferror(in) ? Z_ERRNO : Z_DATA_ERROR;
goto extract_ret;
}
inflatePrime(&state->strm, here->bits, ret >> (8 - here->bits));
}
inflateSetDictionary(&state->strm, here->window, WINSIZE);
/* skip uncompressed bytes until offset reached, then satisfy request */
offset -= here->out;
state->strm.avail_in = 0;
skip = 1; /* while skipping to offset */
}
/* skip uncompressed bytes until offset reached, then satisfy request */
offset -= here->out;
state->strm.avail_in = 0;
skip = 1; /* while skipping to offset */
}
do {
/* define where to put uncompressed data, and how much */
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 */
state->strm.avail_out = WINSIZE;
state->strm.next_out = discard;
offset -= WINSIZE;
}
else if (offset != 0) { /* last skip */
state->strm.avail_out = (unsigned)offset;
state->strm.next_out = discard;
offset = 0;
}
do
{
/* define where to put uncompressed data, and how much */
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 */
state->strm.avail_out = WINSIZE;
state->strm.next_out = discard;
offset -= WINSIZE;
}
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) {
state->in_offset = PX_ftello(in);
state->strm.avail_in = fread(input, 1, CHUNK, in);
if (ferror(in)) {
ret = Z_ERRNO;
goto extract_ret;
}
if (state->strm.avail_in == 0) {
ret = Z_DATA_ERROR;
goto extract_ret;
}
state->strm.next_in = input;
}
uint prev_in = state->strm.avail_in;
ret = inflate(&state->strm, Z_NO_FLUSH); /* normal inflate */
state->in_offset += (prev_in - state->strm.avail_in);
if (ret == Z_NEED_DICT)
ret = Z_DATA_ERROR;
if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR)
goto extract_ret;
if (ret == Z_STREAM_END)
break;
} while (state->strm.avail_out != 0);
/* uncompress until avail_out filled, or end of stream */
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))
{
ret = Z_ERRNO;
goto extract_ret;
}
if (state->strm.avail_in == 0)
{
ret = Z_DATA_ERROR;
goto extract_ret;
}
state->strm.next_in = input;
}
uint prev_in = state->strm.avail_in;
ret = inflate(&state->strm, Z_NO_FLUSH); /* normal inflate */
state->in_offset += (prev_in - state->strm.avail_in);
if (ret == Z_NEED_DICT)
ret = Z_DATA_ERROR;
if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR)
goto extract_ret;
if (ret == Z_STREAM_END)
break;
} while (state->strm.avail_out != 0);
/* if reach end of stream, then don't keep trying to get more */
if (ret == Z_STREAM_END)
break;
/* if reach end of stream, then don't keep trying to get more */
if (ret == Z_STREAM_END)
break;
/* do until offset reached and requested data read, or stream ends */
} while (skip);
/* do until offset reached and requested data read, or stream ends */
} while (skip);
isEnd = ret == Z_STREAM_END;
/* compute number of uncompressed bytes read after offset */
ret = skip ? 0 : len - state->strm.avail_out;
isEnd = ret == Z_STREAM_END;
/* compute number of uncompressed bytes read after offset */
ret = skip ? 0 : len - state->strm.avail_out;
/* clean up and return bytes read or error */
/* clean up and return bytes read or error */
extract_ret:
if (ret == len && !isEnd) {
state->out_offset += len;
state->isValid = 1;
} else
inflateEnd(&state->strm);
if (ret == len && !isEnd)
{
state->out_offset += len;
state->isValid = 1;
}
else
inflateEnd(&state->strm);
return ret;
return ret;
}
#endif /* __ZLIB_INDEXED_H__ */
#endif /* __ZLIB_INDEXED_H__ */

View File

@ -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)

View File

@ -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();
}

View File

@ -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