mirror of https://github.com/PCSX2/pcsx2.git
CDVD: clang-format
This commit is contained in:
parent
c4fa3e3304
commit
f9be4286bd
|
@ -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
|
@ -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
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -16,32 +16,39 @@
|
|||
#include "PrecompiledHeader.h"
|
||||
#include "ChunksCache.h"
|
||||
|
||||
void ChunksCache::SetLimit(uint megabytes) {
|
||||
void ChunksCache::SetLimit(uint megabytes)
|
||||
{
|
||||
m_limit = (PX_off_t)megabytes * 1024 * 1024;
|
||||
MatchLimit();
|
||||
}
|
||||
|
||||
void ChunksCache::MatchLimit(bool removeAll) {
|
||||
void ChunksCache::MatchLimit(bool removeAll)
|
||||
{
|
||||
std::list<CacheEntry*>::reverse_iterator rit;
|
||||
while (!m_entries.empty() && (removeAll || m_size > m_limit)) {
|
||||
while (!m_entries.empty() && (removeAll || m_size > m_limit))
|
||||
{
|
||||
rit = m_entries.rbegin();
|
||||
m_size -= (*rit)->size;
|
||||
delete(*rit);
|
||||
delete (*rit);
|
||||
m_entries.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void ChunksCache::Take(void* pMallocedSrc, PX_off_t offset, int length, int coverage) {
|
||||
void ChunksCache::Take(void* pMallocedSrc, PX_off_t offset, int length, int coverage)
|
||||
{
|
||||
m_entries.push_front(new CacheEntry(pMallocedSrc, offset, length, coverage));
|
||||
m_size += length;
|
||||
MatchLimit();
|
||||
}
|
||||
|
||||
// By design, succeed only if the entire request is in a single cached chunk
|
||||
int ChunksCache::Read(void* pDest, PX_off_t offset, int length) {
|
||||
for (auto it = m_entries.begin(); it != m_entries.end(); it++) {
|
||||
int ChunksCache::Read(void* pDest, PX_off_t offset, int length)
|
||||
{
|
||||
for (auto it = m_entries.begin(); it != m_entries.end(); it++)
|
||||
{
|
||||
CacheEntry* e = *it;
|
||||
if (e && offset >= e->offset && (offset + length) <= (e->offset + e->coverage)) {
|
||||
if (e && offset >= e->offset && (offset + length) <= (e->offset + e->coverage))
|
||||
{
|
||||
if (it != m_entries.begin())
|
||||
m_entries.splice(m_entries.begin(), m_entries, it); // Move to top (MRU)
|
||||
return CopyAvailable(e->data, e->offset, e->size, pDest, offset, length);
|
||||
|
@ -49,4 +56,3 @@ int ChunksCache::Read(void* pDest, PX_off_t offset, int length) {
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,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;
|
||||
|
|
|
@ -20,11 +20,14 @@
|
|||
#include "GzippedFileReader.h"
|
||||
|
||||
// CompressedFileReader factory.
|
||||
AsyncFileReader* CompressedFileReader::GetNewReader(const wxString& fileName) {
|
||||
if (GzippedFileReader::CanHandle(fileName)) {
|
||||
AsyncFileReader* CompressedFileReader::GetNewReader(const wxString& fileName)
|
||||
{
|
||||
if (GzippedFileReader::CanHandle(fileName))
|
||||
{
|
||||
return new GzippedFileReader();
|
||||
}
|
||||
if (CsoFileReader::CanHandle(fileName)) {
|
||||
if (CsoFileReader::CanHandle(fileName))
|
||||
{
|
||||
return new CsoFileReader();
|
||||
}
|
||||
// This is the one which will fail on open.
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
#pragma once
|
||||
|
||||
// Factory - creates an AsyncFileReader derived instance which can read a compressed file
|
||||
class CompressedFileReader {
|
||||
class CompressedFileReader
|
||||
{
|
||||
public:
|
||||
// fileName and its contents may be used to choose the compressed reader.
|
||||
// If no matching handler is found, NULL is returned.
|
||||
|
|
|
@ -24,21 +24,21 @@
|
|||
// Maybe some day we'll convert all file related ops to wxWidgets, which means also the
|
||||
// instances at zlib_indexed.h (which use plain stdio FILE*)
|
||||
#ifdef _WIN32
|
||||
# define PX_wfilename(name_wxstr) (name_wxstr.wc_str())
|
||||
# define PX_fopen_rb(name_wxstr) (_wfopen(PX_wfilename(name_wxstr), L"rb"))
|
||||
#define PX_wfilename(name_wxstr) (name_wxstr.wc_str())
|
||||
#define PX_fopen_rb(name_wxstr) (_wfopen(PX_wfilename(name_wxstr), L"rb"))
|
||||
#else
|
||||
# define PX_wfilename(name_wxstr) (name_wxstr.mbc_str())
|
||||
# define PX_fopen_rb(name_wxstr) (fopen(PX_wfilename(name_wxstr), "rb"))
|
||||
#define PX_wfilename(name_wxstr) (name_wxstr.mbc_str())
|
||||
#define PX_fopen_rb(name_wxstr) (fopen(PX_wfilename(name_wxstr), "rb"))
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# define PX_fseeko _fseeki64
|
||||
# define PX_ftello _ftelli64
|
||||
# define PX_off_t s64 /* __int64 */
|
||||
#define PX_fseeko _fseeki64
|
||||
#define PX_ftello _ftelli64
|
||||
#define PX_off_t s64 /* __int64 */
|
||||
#else
|
||||
# define PX_fseeko fseeko
|
||||
# define PX_ftello ftello
|
||||
# define PX_off_t off_t
|
||||
#define PX_fseeko fseeko
|
||||
#define PX_ftello ftello
|
||||
#define PX_off_t off_t
|
||||
#endif
|
||||
|
||||
/////////// End of complementary utilities for zlib_indexed.c //////////
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
|
||||
// Implementation of CSO compressed ISO reading, based on:
|
||||
// https://github.com/unknownbrackets/maxcso/blob/master/README_CSO.md
|
||||
struct CsoHeader {
|
||||
struct CsoHeader
|
||||
{
|
||||
u8 magic[4];
|
||||
u32 header_size;
|
||||
u64 total_bytes;
|
||||
|
@ -38,13 +39,17 @@ struct CsoHeader {
|
|||
|
||||
static const u32 CSO_READ_BUFFER_SIZE = 256 * 1024;
|
||||
|
||||
bool CsoFileReader::CanHandle(const wxString& fileName) {
|
||||
bool CsoFileReader::CanHandle(const wxString& fileName)
|
||||
{
|
||||
bool supported = false;
|
||||
if (wxFileName::FileExists(fileName) && fileName.Lower().EndsWith(L".cso")) {
|
||||
if (wxFileName::FileExists(fileName) && fileName.Lower().EndsWith(L".cso"))
|
||||
{
|
||||
FILE* fp = PX_fopen_rb(fileName);
|
||||
CsoHeader hdr;
|
||||
if (fp) {
|
||||
if (fread(&hdr, 1, sizeof(hdr), fp) == sizeof(hdr)) {
|
||||
if (fp)
|
||||
{
|
||||
if (fread(&hdr, 1, sizeof(hdr), fp) == sizeof(hdr))
|
||||
{
|
||||
supported = ValidateHeader(hdr);
|
||||
}
|
||||
fclose(fp);
|
||||
|
@ -53,20 +58,25 @@ bool CsoFileReader::CanHandle(const wxString& fileName) {
|
|||
return supported;
|
||||
}
|
||||
|
||||
bool CsoFileReader::ValidateHeader(const CsoHeader& hdr) {
|
||||
if (hdr.magic[0] != 'C' || hdr.magic[1] != 'I' || hdr.magic[2] != 'S' || hdr.magic[3] != 'O') {
|
||||
bool CsoFileReader::ValidateHeader(const CsoHeader& hdr)
|
||||
{
|
||||
if (hdr.magic[0] != 'C' || hdr.magic[1] != 'I' || hdr.magic[2] != 'S' || hdr.magic[3] != 'O')
|
||||
{
|
||||
// Invalid magic, definitely a bad file.
|
||||
return false;
|
||||
}
|
||||
if (hdr.ver > 1) {
|
||||
if (hdr.ver > 1)
|
||||
{
|
||||
Console.Error(L"Only CSOv1 files are supported.");
|
||||
return false;
|
||||
}
|
||||
if ((hdr.frame_size & (hdr.frame_size - 1)) != 0) {
|
||||
if ((hdr.frame_size & (hdr.frame_size - 1)) != 0)
|
||||
{
|
||||
Console.Error(L"CSO frame size must be a power of two.");
|
||||
return false;
|
||||
}
|
||||
if (hdr.frame_size < 2048) {
|
||||
if (hdr.frame_size < 2048)
|
||||
{
|
||||
Console.Error(L"CSO frame size must be at least one sector.");
|
||||
return false;
|
||||
}
|
||||
|
@ -75,33 +85,39 @@ bool CsoFileReader::ValidateHeader(const CsoHeader& hdr) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CsoFileReader::Open(const wxString& fileName) {
|
||||
bool CsoFileReader::Open(const wxString& fileName)
|
||||
{
|
||||
Close();
|
||||
m_filename = fileName;
|
||||
m_src = PX_fopen_rb(m_filename);
|
||||
|
||||
bool success = false;
|
||||
if (m_src && ReadFileHeader() && InitializeBuffers()) {
|
||||
if (m_src && ReadFileHeader() && InitializeBuffers())
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
if (!success)
|
||||
{
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CsoFileReader::ReadFileHeader() {
|
||||
bool CsoFileReader::ReadFileHeader()
|
||||
{
|
||||
CsoHeader hdr = {};
|
||||
|
||||
PX_fseeko(m_src, m_dataoffset, SEEK_SET);
|
||||
if (fread(&hdr, 1, sizeof(hdr), m_src) != sizeof(hdr)) {
|
||||
if (fread(&hdr, 1, sizeof(hdr), m_src) != sizeof(hdr))
|
||||
{
|
||||
Console.Error(L"Failed to read CSO file header.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ValidateHeader(hdr)) {
|
||||
if (!ValidateHeader(hdr))
|
||||
{
|
||||
Console.Error(L"CSO has invalid header.");
|
||||
return false;
|
||||
}
|
||||
|
@ -109,7 +125,8 @@ bool CsoFileReader::ReadFileHeader() {
|
|||
m_frameSize = hdr.frame_size;
|
||||
// Determine the translation from bytes to frame.
|
||||
m_frameShift = 0;
|
||||
for (u32 i = m_frameSize; i > 1; i >>= 1) {
|
||||
for (u32 i = m_frameSize; i > 1; i >>= 1)
|
||||
{
|
||||
++m_frameShift;
|
||||
}
|
||||
|
||||
|
@ -120,14 +137,18 @@ bool CsoFileReader::ReadFileHeader() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CsoFileReader::InitializeBuffers() {
|
||||
bool CsoFileReader::InitializeBuffers()
|
||||
{
|
||||
// Round up, since part of a frame requires a full frame.
|
||||
u32 numFrames = (u32)((m_totalSize + m_frameSize - 1) / m_frameSize);
|
||||
|
||||
// We might read a bit of alignment too, so be prepared.
|
||||
if (m_frameSize + (1 << m_indexShift) < CSO_READ_BUFFER_SIZE) {
|
||||
if (m_frameSize + (1 << m_indexShift) < CSO_READ_BUFFER_SIZE)
|
||||
{
|
||||
m_readBuffer = new u8[CSO_READ_BUFFER_SIZE];
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
m_readBuffer = new u8[m_frameSize + (1 << m_indexShift)];
|
||||
}
|
||||
|
||||
|
@ -137,7 +158,8 @@ bool CsoFileReader::InitializeBuffers() {
|
|||
|
||||
const u32 indexSize = numFrames + 1;
|
||||
m_index = new u32[indexSize];
|
||||
if (fread(m_index, sizeof(u32), indexSize, m_src) != indexSize) {
|
||||
if (fread(m_index, sizeof(u32), indexSize, m_src) != indexSize)
|
||||
{
|
||||
Console.Error(L"Unable to read index data from CSO.");
|
||||
return false;
|
||||
}
|
||||
|
@ -146,7 +168,8 @@ bool CsoFileReader::InitializeBuffers() {
|
|||
m_z_stream->zalloc = Z_NULL;
|
||||
m_z_stream->zfree = Z_NULL;
|
||||
m_z_stream->opaque = Z_NULL;
|
||||
if (inflateInit2(m_z_stream, -15) != Z_OK) {
|
||||
if (inflateInit2(m_z_stream, -15) != Z_OK)
|
||||
{
|
||||
Console.Error("Unable to initialize zlib for CSO decompression.");
|
||||
return false;
|
||||
}
|
||||
|
@ -154,37 +177,45 @@ bool CsoFileReader::InitializeBuffers() {
|
|||
return true;
|
||||
}
|
||||
|
||||
void CsoFileReader::Close() {
|
||||
void CsoFileReader::Close()
|
||||
{
|
||||
m_filename.Empty();
|
||||
#if CSO_USE_CHUNKSCACHE
|
||||
m_cache.Clear();
|
||||
#endif
|
||||
|
||||
if (m_src) {
|
||||
if (m_src)
|
||||
{
|
||||
fclose(m_src);
|
||||
m_src = NULL;
|
||||
}
|
||||
if (m_z_stream) {
|
||||
if (m_z_stream)
|
||||
{
|
||||
inflateEnd(m_z_stream);
|
||||
m_z_stream = NULL;
|
||||
}
|
||||
|
||||
if (m_readBuffer) {
|
||||
if (m_readBuffer)
|
||||
{
|
||||
delete[] m_readBuffer;
|
||||
m_readBuffer = NULL;
|
||||
}
|
||||
if (m_zlibBuffer) {
|
||||
if (m_zlibBuffer)
|
||||
{
|
||||
delete[] m_zlibBuffer;
|
||||
m_zlibBuffer = NULL;
|
||||
}
|
||||
if (m_index) {
|
||||
if (m_index)
|
||||
{
|
||||
delete[] m_index;
|
||||
m_index = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int CsoFileReader::ReadSync(void* pBuffer, uint sector, uint count) {
|
||||
if (!m_src) {
|
||||
int CsoFileReader::ReadSync(void* pBuffer, uint sector, uint count)
|
||||
{
|
||||
if (!m_src)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -197,7 +228,8 @@ int CsoFileReader::ReadSync(void* pBuffer, uint sector, uint count) {
|
|||
int remaining = count * m_blocksize;
|
||||
int bytes = 0;
|
||||
|
||||
while (remaining > 0) {
|
||||
while (remaining > 0)
|
||||
{
|
||||
int readBytes;
|
||||
|
||||
#if CSO_USE_CHUNKSCACHE
|
||||
|
@ -206,16 +238,18 @@ int CsoFileReader::ReadSync(void* pBuffer, uint sector, uint count) {
|
|||
#else
|
||||
readBytes = -1;
|
||||
#endif
|
||||
if (readBytes < 0) {
|
||||
if (readBytes < 0)
|
||||
{
|
||||
readBytes = ReadFromFrame(dest + bytes, pos + bytes, remaining);
|
||||
if (readBytes == 0) {
|
||||
if (readBytes == 0)
|
||||
{
|
||||
// We hit EOF.
|
||||
break;
|
||||
}
|
||||
|
||||
#if CSO_USE_CHUNKSCACHE
|
||||
// Add the bytes into the cache. We need to allocate a buffer for it.
|
||||
void *cached = malloc(readBytes);
|
||||
void* cached = malloc(readBytes);
|
||||
memcpy(cached, dest + bytes, readBytes);
|
||||
m_cache.Take(cached, pos + bytes, readBytes, readBytes);
|
||||
#endif
|
||||
|
@ -228,8 +262,10 @@ int CsoFileReader::ReadSync(void* pBuffer, uint sector, uint count) {
|
|||
return bytes;
|
||||
}
|
||||
|
||||
int CsoFileReader::ReadFromFrame(u8 *dest, u64 pos, int maxBytes) {
|
||||
if (pos >= m_totalSize) {
|
||||
int CsoFileReader::ReadFromFrame(u8* dest, u64 pos, int maxBytes)
|
||||
{
|
||||
if (pos >= m_totalSize)
|
||||
{
|
||||
// Can't read anything passed the end.
|
||||
return 0;
|
||||
}
|
||||
|
@ -248,24 +284,31 @@ int CsoFileReader::ReadFromFrame(u8 *dest, u64 pos, int maxBytes) {
|
|||
const u64 frameRawPos = (u64)index0 << m_indexShift;
|
||||
const u64 frameRawSize = (u64)(index1 - index0) << m_indexShift;
|
||||
|
||||
if (!compressed) {
|
||||
if (!compressed)
|
||||
{
|
||||
// Just read directly, easy.
|
||||
if (PX_fseeko(m_src, m_dataoffset + frameRawPos + offset, SEEK_SET) != 0) {
|
||||
if (PX_fseeko(m_src, m_dataoffset + frameRawPos + offset, SEEK_SET) != 0)
|
||||
{
|
||||
Console.Error("Unable to seek to uncompressed CSO data.");
|
||||
return 0;
|
||||
}
|
||||
return fread(dest, 1, bytes, m_src);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// We don't need to decompress if we already did this same frame last time.
|
||||
if (m_zlibBufferFrame != frame) {
|
||||
if (PX_fseeko(m_src, m_dataoffset + frameRawPos, SEEK_SET) != 0) {
|
||||
if (m_zlibBufferFrame != frame)
|
||||
{
|
||||
if (PX_fseeko(m_src, m_dataoffset + frameRawPos, SEEK_SET) != 0)
|
||||
{
|
||||
Console.Error("Unable to seek to compressed CSO data.");
|
||||
return 0;
|
||||
}
|
||||
// This might be less bytes than frameRawSize in case of padding on the last frame.
|
||||
// This is because the index positions must be aligned.
|
||||
const u32 readRawBytes = fread(m_readBuffer, 1, frameRawSize, m_src);
|
||||
if (!DecompressFrame(frame, readRawBytes)) {
|
||||
if (!DecompressFrame(frame, readRawBytes))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -277,7 +320,8 @@ int CsoFileReader::ReadFromFrame(u8 *dest, u64 pos, int maxBytes) {
|
|||
return bytes;
|
||||
}
|
||||
|
||||
bool CsoFileReader::DecompressFrame(u32 frame, u32 readBufferSize) {
|
||||
bool CsoFileReader::DecompressFrame(u32 frame, u32 readBufferSize)
|
||||
{
|
||||
m_z_stream->next_in = m_readBuffer;
|
||||
m_z_stream->avail_in = readBufferSize;
|
||||
m_z_stream->next_out = m_zlibBuffer;
|
||||
|
@ -285,10 +329,13 @@ bool CsoFileReader::DecompressFrame(u32 frame, u32 readBufferSize) {
|
|||
|
||||
int status = inflate(m_z_stream, Z_FINISH);
|
||||
bool success = status == Z_STREAM_END && m_z_stream->total_out == m_frameSize;
|
||||
if (success) {
|
||||
if (success)
|
||||
{
|
||||
// Our buffer now contains this frame.
|
||||
m_zlibBufferFrame = frame;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Error("Unable to decompress CSO frame using zlib.");
|
||||
m_zlibBufferFrame = (u32)-1;
|
||||
}
|
||||
|
@ -297,17 +344,20 @@ bool CsoFileReader::DecompressFrame(u32 frame, u32 readBufferSize) {
|
|||
return success;
|
||||
}
|
||||
|
||||
void CsoFileReader::BeginRead(void* pBuffer, uint sector, uint count) {
|
||||
void CsoFileReader::BeginRead(void* pBuffer, uint sector, uint count)
|
||||
{
|
||||
// TODO: No async support yet, implement as sync.
|
||||
m_bytesRead = ReadSync(pBuffer, sector, count);
|
||||
}
|
||||
|
||||
int CsoFileReader::FinishRead() {
|
||||
int CsoFileReader::FinishRead()
|
||||
{
|
||||
int res = m_bytesRead;
|
||||
m_bytesRead = -1;
|
||||
return res;
|
||||
}
|
||||
|
||||
void CsoFileReader::CancelRead() {
|
||||
void CsoFileReader::CancelRead()
|
||||
{
|
||||
// TODO: No async read support yet.
|
||||
}
|
||||
|
|
|
@ -35,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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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( §or[1], "CD001", 5 ) == 0 )
|
||||
internalReader.readSector(sector, i);
|
||||
if (memcmp(§or[1], "CD001", 5) == 0)
|
||||
{
|
||||
switch (sector[0])
|
||||
{
|
||||
case 0:
|
||||
DevCon.WriteLn( Color_Green, "(IsoFS) Block 0x%x: Boot partition info.", i );
|
||||
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, §or[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, §or[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;
|
||||
|
|
|
@ -23,4 +23,3 @@ struct ISoFileDescriptor;
|
|||
#include "IsoFileDescriptor.h"
|
||||
#include "IsoDirectory.h"
|
||||
#include "IsoFile.h"
|
||||
|
||||
|
|
|
@ -25,13 +25,13 @@ IsoFSCDVD::IsoFSCDVD()
|
|||
|
||||
bool IsoFSCDVD::readSector(unsigned char* buffer, int lba)
|
||||
{
|
||||
return DoCDVDreadSector(buffer,lba,CDVD_MODE_2048)>=0;
|
||||
return DoCDVDreadSector(buffer, lba, CDVD_MODE_2048) >= 0;
|
||||
}
|
||||
|
||||
int IsoFSCDVD::getNumSectors()
|
||||
{
|
||||
cdvdTD td;
|
||||
CDVD->getTD(0,&td);
|
||||
CDVD->getTD(0, &td);
|
||||
|
||||
return td.lsn;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include "SectorSource.h"
|
||||
|
||||
class IsoFSCDVD: public SectorSource
|
||||
class IsoFSCDVD : public SectorSource
|
||||
{
|
||||
public:
|
||||
IsoFSCDVD();
|
||||
|
@ -27,5 +27,5 @@ public:
|
|||
|
||||
virtual bool readSector(unsigned char* buffer, int lba);
|
||||
|
||||
virtual int getNumSectors();
|
||||
virtual int getNumSectors();
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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(); }
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -34,7 +34,8 @@ std::vector<std::string> GetOpticalDriveList()
|
|||
|
||||
std::vector<std::string> drives;
|
||||
udev_enumerate* enumerate = udev_enumerate_new(udev_context);
|
||||
if (enumerate) {
|
||||
if (enumerate)
|
||||
{
|
||||
udev_enumerate_add_match_subsystem(enumerate, "block");
|
||||
udev_enumerate_add_match_property(enumerate, "ID_CDROM_DVD", "1");
|
||||
udev_enumerate_scan_devices(enumerate);
|
||||
|
@ -62,22 +63,26 @@ std::vector<std::string> GetOpticalDriveList()
|
|||
|
||||
void GetValidDrive(std::string& drive)
|
||||
{
|
||||
if (!drive.empty()) {
|
||||
if (!drive.empty())
|
||||
{
|
||||
#ifdef __linux__
|
||||
int fd = open(drive.c_str(), O_RDONLY | O_NONBLOCK);
|
||||
if (fd != -1) {
|
||||
if (fd != -1)
|
||||
{
|
||||
if (ioctl(fd, CDROM_GET_CAPABILITY, 0) == -1)
|
||||
drive.clear();
|
||||
close(fd);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
drive.clear();
|
||||
}
|
||||
#else
|
||||
drive.clear();
|
||||
#endif
|
||||
}
|
||||
if (drive.empty()) {
|
||||
if (drive.empty())
|
||||
{
|
||||
auto drives = GetOpticalDriveList();
|
||||
if (!drives.empty())
|
||||
drive = drives.front();
|
||||
|
|
|
@ -37,7 +37,8 @@ IOCtlSrc::IOCtlSrc(decltype(m_filename) filename)
|
|||
|
||||
IOCtlSrc::~IOCtlSrc()
|
||||
{
|
||||
if (m_device != -1) {
|
||||
if (m_device != -1)
|
||||
{
|
||||
SetSpindleSpeed(true);
|
||||
close(m_device);
|
||||
}
|
||||
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,8 @@ std::vector<std::wstring> GetOpticalDriveList()
|
|||
return {};
|
||||
|
||||
std::vector<std::wstring> drives;
|
||||
for (auto p = drive_strings.data(); *p; ++p) {
|
||||
for (auto p = drive_strings.data(); *p; ++p)
|
||||
{
|
||||
if (GetDriveType(p) == DRIVE_CDROM)
|
||||
drives.push_back(p);
|
||||
while (*p)
|
||||
|
@ -35,7 +36,8 @@ std::vector<std::wstring> GetOpticalDriveList()
|
|||
|
||||
void GetValidDrive(std::wstring& drive)
|
||||
{
|
||||
if (drive.empty() || GetDriveType(drive.c_str()) != DRIVE_CDROM) {
|
||||
if (drive.empty() || GetDriveType(drive.c_str()) != DRIVE_CDROM)
|
||||
{
|
||||
auto drives = GetOpticalDriveList();
|
||||
if (drives.empty())
|
||||
{
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include <winioctl.h>
|
||||
#include <ntddcdvd.h>
|
||||
#include <ntddcdrm.h>
|
||||
// "typedef ignored" warning will disappear once we move to the Windows 10 SDK.
|
||||
// "typedef ignored" warning will disappear once we move to the Windows 10 SDK.
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4091)
|
||||
#include <ntddscsi.h>
|
||||
|
@ -38,7 +38,8 @@ IOCtlSrc::IOCtlSrc(decltype(m_filename) filename)
|
|||
|
||||
IOCtlSrc::~IOCtlSrc()
|
||||
{
|
||||
if (m_device != INVALID_HANDLE_VALUE) {
|
||||
if (m_device != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
SetSpindleSpeed(true);
|
||||
CloseHandle(m_device);
|
||||
}
|
||||
|
@ -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;
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -32,7 +32,7 @@ Dialogs::DriveSelectorDialog::DriveSelectorDialog(wxWindow* parent, wxString cur
|
|||
driveList.Add(i);
|
||||
}
|
||||
|
||||
choiceDrive = new wxChoice(this, wxID_ANY, wxDefaultPosition, { 240, 40 }, driveList);
|
||||
choiceDrive = new wxChoice(this, wxID_ANY, wxDefaultPosition, {240, 40}, driveList);
|
||||
|
||||
int driveIndex = choiceDrive->FindString(curDrive);
|
||||
if (driveIndex != wxNOT_FOUND)
|
||||
|
|
|
@ -25,7 +25,7 @@ DriveList::DriveList()
|
|||
}
|
||||
|
||||
DriveListManager::DriveListManager(wxMenu* menu)
|
||||
: m_Menu( menu )
|
||||
: m_Menu(menu)
|
||||
{
|
||||
m_Menu->Append(MenuId_DriveListRefresh, _("&Refresh"));
|
||||
m_Menu->AppendSeparator();
|
||||
|
@ -78,13 +78,13 @@ void DriveListManager::RefreshList()
|
|||
}
|
||||
}
|
||||
|
||||
void DriveListManager::OnChangedSelection( wxCommandEvent& evt )
|
||||
void DriveListManager::OnChangedSelection(wxCommandEvent& evt)
|
||||
{
|
||||
uint index = m_Items.size();
|
||||
|
||||
for (uint i = 0; i < m_Items.size(); i++)
|
||||
{
|
||||
if( (m_Items.at(i)->itemPtr != NULL) && (m_Items.at(i)->itemPtr->GetId() == evt.GetId()) )
|
||||
if ((m_Items.at(i)->itemPtr != NULL) && (m_Items.at(i)->itemPtr->GetId() == evt.GetId()))
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
|
@ -103,8 +103,7 @@ void DriveListManager::OnChangedSelection( wxCommandEvent& evt )
|
|||
SwapOrReset_Disc(m_Menu->GetWindow(), paused_core, m_Items.at(index)->driveLetter);
|
||||
}
|
||||
|
||||
void DriveListManager::OnRefreshClicked( wxCommandEvent& evt )
|
||||
void DriveListManager::OnRefreshClicked(wxCommandEvent& evt)
|
||||
{
|
||||
RefreshList();
|
||||
}
|
||||
|
||||
|
|
|
@ -27,8 +27,8 @@ protected:
|
|||
|
||||
DriveListItem() { itemPtr = NULL; }
|
||||
|
||||
DriveListItem( const wxString& src )
|
||||
: driveLetter( src )
|
||||
DriveListItem(const wxString& src)
|
||||
: driveLetter(src)
|
||||
{
|
||||
itemPtr = NULL;
|
||||
}
|
||||
|
@ -45,8 +45,8 @@ public:
|
|||
|
||||
protected:
|
||||
void ClearList();
|
||||
void OnChangedSelection( wxCommandEvent& evt );
|
||||
void OnRefreshClicked( wxCommandEvent& evt );
|
||||
void OnChangedSelection(wxCommandEvent& evt);
|
||||
void OnRefreshClicked(wxCommandEvent& evt);
|
||||
};
|
||||
|
||||
struct DriveList
|
||||
|
|
Loading…
Reference in New Issue