IsoFile/IsoFS code conformance stuffs:

* Converted new code to use PCSX2/wxWidgets types and utility/helpers.
 * use u32 where appropriate (as defined by ISO 9660), and removed s64 stuff since it's not supported by the file format anyway.
 * general fixups to conform better to general C++ style error and object handling.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2165 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-11-08 17:29:12 +00:00
parent e0f455a57a
commit c6b14bd7f0
11 changed files with 665 additions and 698 deletions

View File

@ -71,54 +71,37 @@ static void CheckNullCDVD()
// //
static int CheckDiskTypeFS(int baseType) static int CheckDiskTypeFS(int baseType)
{ {
IsoFSCDVD isofs;
IsoDirectory rootdir(isofs);
try { try {
IsoFSCDVD isofs; IsoFile file( rootdir, L"SYSTEM.CNF;1");
IsoDirectory fsroot(&isofs);
try {
// Will throw exception if the file was not found
IsoFile file = fsroot.OpenFile("SYSTEM.CNF;1");
int size = file.getLength(); int size = file.getLength();
char buffer[256]; //if the file is longer...it should be shorter :D char buffer[256]; //if the file is longer...it should be shorter :D
file.read((u8*)buffer,size); file.read((u8*)buffer,size);
buffer[size]='\0'; buffer[size]='\0';
char* pos = strstr(buffer, "BOOT2"); char* pos = strstr(buffer, "BOOT2");
if (pos == NULL) if (pos == NULL)
{
pos = strstr(buffer, "BOOT");
if (pos == NULL) return CDVD_TYPE_ILLEGAL;
return CDVD_TYPE_PSCD;
}
return (baseType==CDVD_TYPE_DETCTCD) ? CDVD_TYPE_PS2CD : CDVD_TYPE_PS2DVD;
}
catch( ... )
{ {
} pos = strstr(buffer, "BOOT");
if (pos == NULL) return CDVD_TYPE_ILLEGAL;
try {
fsroot.FindFile("PSX.EXE;1");
return CDVD_TYPE_PSCD; return CDVD_TYPE_PSCD;
} }
catch( ... )
{
}
try { return (baseType==CDVD_TYPE_DETCTCD) ? CDVD_TYPE_PS2CD : CDVD_TYPE_PS2DVD;
fsroot.FindFile("VIDEO_TS/VIDEO_TS.IFO;1");
return CDVD_TYPE_DVDV;
}
catch( ... )
{
}
} }
catch( ... ) catch( Exception::FileNotFound& )
{ {
} }
if( rootdir.IsFile(L"PSX.EXE;1") )
return CDVD_TYPE_PSCD;
if( rootdir.IsFile(L"VIDEO_TS/VIDEO_TS.IFO;1") )
return CDVD_TYPE_DVDV;
return CDVD_TYPE_ILLEGAL; // << Only for discs which aren't ps2 at all. return CDVD_TYPE_ILLEGAL; // << Only for discs which aren't ps2 at all.
} }

View File

@ -0,0 +1,30 @@
#pragma once
class IsoDirectory
{
public:
SectorSource& internalReader;
std::vector<IsoFileDescriptor> files;
public:
IsoDirectory(SectorSource& r);
IsoDirectory(SectorSource& r, IsoFileDescriptor directoryEntry);
~IsoDirectory() throw();
SectorSource& GetReader() const { return internalReader; }
bool Exists(const wxString& filePath) const;
bool IsFile(const wxString& filePath) const;
bool IsDir(const wxString& filePath) const;
u32 GetFileSize( const wxString& filePath ) const;
IsoFileDescriptor FindFile(const wxString& filePath) const;
protected:
const IsoFileDescriptor& GetEntry(const wxString& fileName) const;
const IsoFileDescriptor& GetEntry(int index) const;
void Init(const IsoFileDescriptor& directoryEntry);
int GetIndexOf(const wxString& fileName) const;
};

View File

@ -1,188 +1,182 @@
#include "PrecompiledHeader.h"
#include "PrecompiledHeader.h"
#include "IsoFS.h" #include "IsoFS.h"
#include "IsoFile.h"
#include <vector>
//////////////////////////////////////////////////////////////////////////
using namespace std; // IsoDirectory
//////////////////////////////////////////////////////////////////////////
void Tokenize(const string& str, vector<string>& tokens, const string& delimiters = " ")
{ // Used to load the Root directory from an image
string::size_type lastPos = str.find_first_not_of(delimiters, 0); IsoDirectory::IsoDirectory(SectorSource& r) :
string::size_type pos = str.find_first_of(delimiters, lastPos); internalReader(r)
{
while (string::npos != pos || string::npos != lastPos) u8 sector[2048];
{
tokens.push_back(str.substr(lastPos, pos - lastPos)); internalReader.readSector(sector,16);
lastPos = str.find_first_not_of(delimiters, pos);
pos = str.find_first_of(delimiters, lastPos); IsoFileDescriptor rootDirEntry(sector+156,38);
}
} Init(rootDirEntry);
}
//////////////////////////////////////////////////////////////////////////
// IsoDirectory // Used to load a specific directory from a file descriptor
////////////////////////////////////////////////////////////////////////// IsoDirectory::IsoDirectory(SectorSource& r, IsoFileDescriptor directoryEntry) :
internalReader(r)
IsoDirectory::IsoDirectory(SectorSource* r) {
{ Init(directoryEntry);
byte sector[2048]; }
r->readSector(sector,16); IsoDirectory::~IsoDirectory() throw()
{
IsoFileDescriptor rootDirEntry(sector+156,38); }
Init(r, rootDirEntry); void IsoDirectory::Init(const IsoFileDescriptor& directoryEntry)
} {
// parse directory sector
IsoDirectory::IsoDirectory(SectorSource* r, IsoFileDescriptor directoryEntry) IsoFile dataStream (internalReader, directoryEntry);
{
Init(r, directoryEntry); files.clear();
}
int remainingSize = directoryEntry.size;
void IsoDirectory::Init(SectorSource* r, IsoFileDescriptor directoryEntry)
{ u8 b[257];
// parse directory sector
IsoFile dataStream (r, directoryEntry); while(remainingSize>=4) // hm hack :P
{
internalReader = r; b[0] = dataStream.read<u8>();
files.clear(); if(b[0]==0)
{
int remainingSize = directoryEntry.size; break; // or continue?
}
byte b[257];
remainingSize -= b[0];
while(remainingSize>=4) // hm hack :P
{ dataStream.read(b+1, b[0]-1);
b[0] = dataStream.read<byte>();
files.push_back(IsoFileDescriptor(b, b[0]));
if(b[0]==0) }
{
break; // or continue? b[0] = 0;
} }
remainingSize-=b[0]; const IsoFileDescriptor& IsoDirectory::GetEntry(int index) const
{
dataStream.read(b+1, b[0]-1); return files[index];
}
IsoFileDescriptor file(b,b[0]);
files.push_back(file); int IsoDirectory::GetIndexOf(const wxString& fileName) const
} {
for(unsigned int i=0;i<files.size();i++)
b[0] = 0; {
} if(files[i].name == fileName) return i;
}
IsoFileDescriptor IsoDirectory::GetEntry(int index)
{ throw Exception::FileNotFound( fileName );
return files[index]; }
}
const IsoFileDescriptor& IsoDirectory::GetEntry(const wxString& fileName) const
int IsoDirectory::GetIndexOf(string fileName) {
{ return GetEntry(GetIndexOf(fileName));
for(unsigned int i=0;i<files.size();i++) }
{
string file = files[i].name; IsoFileDescriptor IsoDirectory::FindFile(const wxString& filePath) const
if(file.compare(fileName)==0) {
{ pxAssert( !filePath.IsEmpty() );
return i;
} // 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 );
throw Exception::FileNotFound( fileName.c_str() ); IsoFileDescriptor info;
} const IsoDirectory* dir = this;
ScopedPtr<IsoDirectory> deleteme;
IsoFileDescriptor IsoDirectory::GetEntry(string fileName)
{ // walk through path ("." and ".." entries are in the directories themselves, so even if the
return GetEntry(GetIndexOf(fileName)); // path included . and/or .., it still works)
}
for(uint i=0; i<parts.GetDirCount(); ++i)
IsoFileDescriptor IsoDirectory::FindFile(string filePath) {
{ info = dir->GetEntry(parts.GetDirs()[i]);
IsoFileDescriptor info; if(info.IsFile()) throw Exception::FileNotFound( filePath );
IsoDirectory dir = *this;
dir = deleteme = new IsoDirectory(internalReader, info);
// this was supposed to be a vector<string>, but this damn hotfix kills stl }
// if you have the Windows SDK 6.1 installed after vs2008 sp1
vector<string> path; if( !parts.GetFullName().IsEmpty() )
info = dir->GetEntry(parts.GetFullName());
Tokenize(filePath,path,"\\/");
return info;
// walk through path ("." and ".." entries are in the directories themselves, so even if the path included . and/or .., it should still work) }
for(int i=0;i<path.size();i++)
{ bool IsoDirectory::IsFile(const wxString& filePath) const
string pathName = path[i]; {
info = dir.GetEntry(pathName); if( filePath.IsEmpty() ) return false;
if((info.flags&2)==2) // if it's a directory return (FindFile(filePath).flags&2) != 2;
{ }
dir = IsoDirectory(internalReader, info);
} bool IsoDirectory::IsDir(const wxString& filePath) const
} {
if( filePath.IsEmpty() ) return false;
return info; return (FindFile(filePath).flags&2) == 2;
} }
IsoFile IsoDirectory::OpenFile(string filePath) u32 IsoDirectory::GetFileSize( const wxString& filePath ) const
{ {
IsoFileDescriptor info = FindFile(filePath); return FindFile( filePath ).size;
if((info.flags&2)==2) // if it's a directory }
{
throw Exception::InvalidArgument("Filename points to a directory."); IsoFileDescriptor::IsoFileDescriptor()
} {
lba = 0;
return IsoFile(internalReader, info); size = 0;
} flags = 0;
}
IsoDirectory::~IsoDirectory(void)
{ IsoFileDescriptor::IsoFileDescriptor(const u8* data, int length)
} {
lba = (u32&)data[2];
////////////////////////////////////////////////////////////////////////// size = (u32&)data[10];
// IsoFileDescriptor
////////////////////////////////////////////////////////////////////////// date.year = data[18] + 1900;
date.month = data[19];
IsoFileDescriptor::IsoFileDescriptor() date.day = data[20];
{ date.hour = data[21];
lba = 0; date.minute = data[22];
size = 0; date.second = data[23];
flags = 0; date.gmtOffset = data[24];
name = "";
} flags = data[25];
IsoFileDescriptor::IsoFileDescriptor(const byte* data, int length) // This assert probably means a coder error, but let's fall back on a runtime exception
{ // in release builds since, most likely, the error is "recoverable" form a user standpoint.
lba = *(const int*)(data+2); if( !pxAssertDev( (lba>=0) && (length>=0), "Invalid ISO file descriptor data encountered." ) )
size = *(const int*)(data+10); throw Exception::BadStream();
date.year = data[18] + 1900;
date.month = data[19]; int fileNameLength = data[32];
date.day = data[20];
date.hour = data[21]; if(fileNameLength==1)
date.minute = data[22]; {
date.second = data[23]; u8 c = data[33];
date.gmtOffset = data[24];
switch(c)
flags = data[25]; {
case 0: name = L"."; break;
if((lba<0)||(length<0)) case 1: name = L".."; break;
{ default: name = (wxChar)c;
// would be nice to have some exceptio nthis fits in }
throw Exception::InvalidOperation("WTF?! Size or lba < 0?!"); }
} else
{
int fileNameLength = data[32]; // copy string and up-convert from ascii to wxChar
name.clear(); const u8* fnsrc = data+33;
const u8* fnend = fnsrc+fileNameLength;
if(fileNameLength==1)
{ while( fnsrc != fnend )
char c = *(const char*)(data+33); {
name += (wxChar)*fnsrc;
switch(c) ++fnsrc;
{ }
case 0: name = "."; break; }
case 1: name = ".."; break; }
default: name.append(1,c);
}
}
else if (fileNameLength>0)
name.append((const char*)(data+33),fileNameLength);
}

View File

@ -1,38 +1,11 @@
#pragma once #pragma once
#include <vector> class IsoFile;
#include <string> class IsoDirectory;
struct ISoFileDescriptor;
#include "IsoFileDescriptor.h"
#include "IsoFile.h" #include "SectorSource.h"
#include "IsoFileDescriptor.h"
class IsoDirectory #include "IsoDirectory.h"
{ #include "ISoFile.h"
public:
std::vector<IsoFileDescriptor> files;
SectorSource* internalReader;
protected:
void Init(SectorSource* r, IsoFileDescriptor directoryEntry);
public:
// Used to load the Root directory from an image
IsoDirectory(SectorSource* r);
// Used to load a specific directory from a file descriptor
IsoDirectory(SectorSource* r, IsoFileDescriptor directoryEntry);
IsoFileDescriptor GetEntry(std::string fileName);
IsoFileDescriptor GetEntry(int index);
int GetIndexOf(std::string fileName);
// Tool. For OpenFile.
IsoFileDescriptor FindFile(std::string filePath);
IsoFile OpenFile(std::string filePath);
~IsoDirectory(void);
};

View File

@ -1,24 +1,24 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "IsoFSCDVD.h" #include "IsoFSCDVD.h"
#include "../CDVDaccess.h" #include "../CDVDaccess.h"
IsoFSCDVD::IsoFSCDVD() IsoFSCDVD::IsoFSCDVD()
{ {
} }
bool IsoFSCDVD::readSector(unsigned char* buffer, int lba) 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() int IsoFSCDVD::getNumSectors()
{ {
cdvdTD td; cdvdTD td;
CDVD->getTD(0,&td); CDVD->getTD(0,&td);
return td.lsn; return td.lsn;
} }
IsoFSCDVD::~IsoFSCDVD(void) IsoFSCDVD::~IsoFSCDVD(void)
{ {
} }

View File

@ -1,17 +1,16 @@
#pragma once #pragma once
#include <stdio.h> #include <stdio.h>
#include "SectorSource.h" #include "SectorSource.h"
class IsoFSCDVD: public SectorSource class IsoFSCDVD: public SectorSource
{ {
public: public:
IsoFSCDVD(); IsoFSCDVD();
virtual ~IsoFSCDVD() throw();
virtual bool readSector(unsigned char* buffer, int lba);
virtual bool readSector(unsigned char* buffer, int lba);
virtual int getNumSectors();
virtual int getNumSectors();
virtual ~IsoFSCDVD(void); };
};

View File

@ -1,217 +1,225 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "IsoFile.h"
using namespace std;
IsoFile::IsoFile(SectorSource* reader, IsoFileDescriptor fileEntry)
: fileEntry(fileEntry)
{
internalReader = reader;
currentSectorNumber=fileEntry.lba;
currentOffset = 0;
sectorOffset = 0;
maxOffset = fileEntry.size;
if(maxOffset>0)
reader->readSector(currentSector,currentSectorNumber);
}
void IsoFile::seek(s64 offset)
{
s64 endOffset = offset;
#ifdef __LINUX__ #include "IsoFS.h"
if (offset<0) throw "Seek offset out of bounds."; #include "IsoFile.h"
#else
if(offset<0) IsoFile::IsoFile(SectorSource& reader, const wxString& filename)
throw new exception("Seek offset out of bounds."); : internalReader(reader)
#endif , fileEntry(IsoDirectory(reader).FindFile(filename))
{
int oldSectorNumber = currentSectorNumber; Init();
s64 newOffset = endOffset; }
int newSectorNumber = fileEntry.lba + (int)(newOffset / sectorLength);
if(oldSectorNumber != newSectorNumber) IsoFile::IsoFile(const IsoDirectory& dir, const wxString& filename)
{ : internalReader(dir.GetReader())
internalReader->readSector(currentSector, newSectorNumber); , fileEntry(dir.FindFile(filename))
} {
currentOffset = newOffset; Init();
currentSectorNumber = newSectorNumber; }
sectorOffset = (int)(currentOffset % sectorLength);
} IsoFile::IsoFile(SectorSource& reader, const IsoFileDescriptor& fileEntry)
: internalReader(reader)
void IsoFile::seek(s64 offset, int ref_position) , fileEntry(fileEntry)
{ {
if(ref_position == SEEK_SET) Init();
seek(offset); }
if(ref_position == SEEK_CUR) void IsoFile::Init()
seek(currentOffset+offset); {
//pxAssertDev( fileEntry.IsFile(), "IsoFile Error: Filename points to a directory." );
if(ref_position == SEEK_END)
seek(fileEntry.size+offset); currentSectorNumber = fileEntry.lba;
} currentOffset = 0;
sectorOffset = 0;
void IsoFile::reset() maxOffset = std::max<u32>( 0, fileEntry.size );
{
seek(0); if(maxOffset > 0)
} internalReader.readSector(currentSector, currentSectorNumber);
}
s64 IsoFile::skip(s64 n)
{ IsoFile::~IsoFile() throw()
s64 oldOffset = currentOffset; {
}
if(n<0)
return n; u32 IsoFile::seek(u32 absoffset)
{
seek(currentOffset+n); u32 endOffset = absoffset;
return currentOffset-oldOffset; int oldSectorNumber = currentSectorNumber;
} u32 newOffset = endOffset;
int newSectorNumber = fileEntry.lba + (int)(newOffset / sectorLength);
s64 IsoFile::getFilePointer() if(oldSectorNumber != newSectorNumber)
{ {
return currentOffset; internalReader.readSector(currentSector, newSectorNumber);
} }
currentOffset = newOffset;
bool IsoFile::eof() currentSectorNumber = newSectorNumber;
{ sectorOffset = (int)(currentOffset % sectorLength);
return (currentOffset == maxOffset);
} return currentOffset;
}
void IsoFile::makeDataAvailable()
{ u32 IsoFile::seek(s32 offset, wxSeekMode ref_position)
if (sectorOffset >= sectorLength) { {
currentSectorNumber++; switch( ref_position )
internalReader->readSector(currentSector, currentSectorNumber); {
sectorOffset -= sectorLength; case wxFromStart:
} pxAssertDev( offset > 0, "Invalid seek position from start." );
} return seek(offset);
int IsoFile::read() case wxFromCurrent:
{ // truncate negative values to zero
if(currentOffset >= maxOffset) return seek( std::max<u32>(0, currentOffset+offset) );
throw Exception::EndOfStream();
case wxFromEnd:
makeDataAvailable(); // truncate negative values to zero
return seek( std::max<u32>(0, fileEntry.size+offset) );
currentOffset++;
jNO_DEFAULT;
return currentSector[sectorOffset++]; }
}
return 0; // unreachable
int IsoFile::internalRead(byte* b, int off, int len) }
{
if (len > 0) void IsoFile::reset()
{ {
if (len > (maxOffset - currentOffset)) seek(0);
{ }
len = (int) (maxOffset - currentOffset);
} // Returns the number of bytes actually skipped.
s32 IsoFile::skip(s32 n)
memcpy(b + off, currentSector + sectorOffset, len); {
s32 oldOffset = currentOffset;
sectorOffset += len;
currentOffset += len; if(n<0)
} return 0;
return len; seek(currentOffset+n);
}
return currentOffset-oldOffset;
int IsoFile::read(byte* b, int len) }
{
if (b == NULL) u32 IsoFile::getSeekPos() const
{ {
throw Exception::ObjectIsNull("b"); return currentOffset;
} }
if (len < 0) bool IsoFile::eof() const
{ {
throw Exception::InvalidOperation("off<0 or len<0."); return (currentOffset == maxOffset);
} }
int off=0; // loads the current sector index into the CurrentSector buffer.
void IsoFile::makeDataAvailable()
int totalLength = 0; {
if (sectorOffset >= sectorLength)
int firstSector = internalRead(b, off, min(len, sectorLength - sectorOffset)); {
off += firstSector; currentSectorNumber++;
len -= firstSector; internalReader.readSector(currentSector, currentSectorNumber);
totalLength += firstSector; sectorOffset -= sectorLength;
}
// Read whole sectors }
while ((len >= sectorLength) && (currentOffset < maxOffset))
{ u8 IsoFile::readByte()
makeDataAvailable(); {
int n = internalRead(b, off, sectorLength); if(currentOffset >= maxOffset)
off += n; throw Exception::EndOfStream();
len -= n;
totalLength += n; makeDataAvailable();
}
currentOffset++;
// Read remaining, if any
if (len > 0) { return currentSector[sectorOffset++];
makeDataAvailable(); }
int lastSector = internalRead(b, off, len);
totalLength += lastSector; // Reads data from a single sector at a time. Reads cannot cross sector boundaries.
} int IsoFile::internalRead(void* dest, int off, int len)
{
return totalLength; if (len > 0)
} {
size_t slen = len;
string IsoFile::readLine() if (slen > (maxOffset - currentOffset))
{ {
string s; slen = (int) (maxOffset - currentOffset);
char c; }
s.clear(); memcpy_fast((u8*)dest + off, currentSector + sectorOffset, slen);
do {
if(eof()) sectorOffset += slen;
break; currentOffset += slen;
return slen;
c = read(); }
return 0;
if((c=='\n')||(c=='\r')||(c==0)) }
break;
// returns the number of bytes actually read.
s.append(1,c); s32 IsoFile::read(void* dest, s32 len)
} while(true); {
pxAssert( dest != NULL );
return s; pxAssert( len >= 0 ); // should we silent-fail on negative length reads? prolly not...
}
if( len <= 0 ) return 0;
wstring IsoFile::readLineW()
{ int off = 0;
wstring s;
wchar_t c; int totalLength = 0;
s.clear(); int firstSector = internalRead(dest, off, std::min(len, sectorLength - sectorOffset));
do { off += firstSector;
if(eof()) len -= firstSector;
break; totalLength += firstSector;
c = read<wchar_t>(); // Read whole sectors
while ((len >= sectorLength) && (currentOffset < maxOffset))
if((c==L'\n')||(c==L'\r')||(c==0)) {
break; makeDataAvailable();
int n = internalRead(dest, off, sectorLength);
s.append(1,c); off += n;
} while(true); len -= n;
totalLength += n;
return s; }
}
// Read remaining, if any
s64 IsoFile::getLength() if (len > 0) {
{ makeDataAvailable();
return maxOffset; int lastSector = internalRead(dest, off, len);
} totalLength += lastSector;
}
const IsoFileDescriptor& IsoFile::getEntry()
{ return totalLength;
return fileEntry; }
}
// Reads data until it reaches a newline character (either \n, \r, or ASCII-Z). The caller is
IsoFile::~IsoFile(void) // responsible for handling files with DOS-style newlines (CR/LF pairs), if needed. The resulting
{ // string has no newlines.
//
} // Read data is unformatted 8 bit / Ascii. If the source file is known to be UTF8, use the fromUTF8()
// conversion helper provided by PCSX2 utility classes.
//
std::string IsoFile::readLine()
{
std::string s;
s.reserve( 512 );
while( !eof() )
{
u8 c = read<u8>();
if((c=='\n') || (c=='\r') || (c==0))
break;
s += c;
}
return s;
}
u32 IsoFile::getLength()
{
return maxOffset;
}
const IsoFileDescriptor& IsoFile::getEntry()
{
return fileEntry;
}

View File

@ -1,63 +1,61 @@
#pragma once #pragma once
#include "IsoFileDescriptor.h" #include "IsoFileDescriptor.h"
#include "SectorSource.h" #include "SectorSource.h"
class IsoFile class IsoFile
{ {
public: public:
static const int sectorLength = 2048; static const int sectorLength = 2048;
private: protected:
IsoFileDescriptor fileEntry; SectorSource& internalReader;
IsoFileDescriptor fileEntry;
s64 currentOffset;
s64 maxOffset; u32 currentOffset;
u32 maxOffset;
int currentSectorNumber;
byte currentSector[sectorLength]; int currentSectorNumber;
int sectorOffset; u8 currentSector[sectorLength];
int sectorOffset;
SectorSource* internalReader;
public:
void makeDataAvailable(); IsoFile(const IsoDirectory& dir, const wxString& filename);
int internalRead(byte* b, int off, int len); IsoFile(SectorSource& reader, const wxString& filename);
IsoFile(SectorSource& reader, const IsoFileDescriptor& fileEntry);
public: virtual ~IsoFile() throw();
IsoFile(SectorSource* reader, IsoFileDescriptor fileEntry); u32 seek(u32 absoffset);
u32 seek(s32 offset, wxSeekMode ref_position);
void seek(s64 offset); void reset();
void seek(s64 offset, int ref_position);
void reset(); s32 skip(s32 n);
u32 getSeekPos() const;
s64 skip(s64 n); u32 getLength();
s64 getFilePointer(); bool eof() const;
bool eof(); const IsoFileDescriptor& getEntry();
int read();
int read(byte* b, int len); u8 readByte();
s32 read(void* dest, s32 len);
// Tool to read a specific value type, including structs. std::string readLine();
template<class T>
T read() // Tool to read a specific value type, including structs.
{ template< class T >
if(sizeof(T)==1) T read()
return (T)read(); {
else if(sizeof(T)==1)
{ return (T)readByte();
T t; else
read((byte*)&t,sizeof(t)); {
return t; T t;
} read((u8*)&t,sizeof(t));
} return t;
}
std::string readLine(); // Assume null-termination }
std::wstring readLineW(); // (this one too)
protected:
s64 getLength(); void makeDataAvailable();
int internalRead(void* dest, int off, int len);
const IsoFileDescriptor& getEntry(); void Init();
};
~IsoFile(void);
};

View File

@ -1,32 +1,27 @@
#pragma once #pragma once
#include <string> struct IsoFileDescriptor
{
typedef unsigned char byte; struct FileDate // not 1:1 with iso9660 date struct
{
class IsoFileDescriptor s32 year;
{ u8 month;
public: u8 day;
struct FileDate // not 1:1 with iso9660 date struct u8 hour;
{ u8 minute;
int year; u8 second;
byte month; u8 gmtOffset; // Offset from Greenwich Mean Time in number of 15 min intervals from -48 (West) to + 52 (East)
byte day;
byte hour; } date;
byte minute;
byte second; u32 lba;
byte gmtOffset; // Offset from Greenwich Mean Time in number of 15 min intervals from -48 (West) to + 52 (East) u32 size;
int flags;
} date; wxString name;
int lba; IsoFileDescriptor();
int size; IsoFileDescriptor(const u8* data, int length);
int flags;
std::string name; //[128+1]; bool IsFile() const { return !(flags & 2); }
bool IsDir() const { return !IsFile(); }
IsoFileDescriptor(); };
IsoFileDescriptor(const byte* data, int length);
~IsoFileDescriptor(void) {}
};

View File

@ -1,9 +1,9 @@
#pragma once #pragma once
class SectorSource class SectorSource
{ {
public: public:
virtual int getNumSectors()=0; virtual int getNumSectors()=0;
virtual bool readSector(unsigned char* buffer, int lba)=0; virtual bool readSector(unsigned char* buffer, int lba)=0;
virtual ~SectorSource(void) {}; virtual ~SectorSource() throw() {}
}; };

View File

@ -19,11 +19,12 @@
//#include "CDVD/IsoFSdrv.h" //#include "CDVD/IsoFSdrv.h"
#include "DebugTools/Debug.h" #include "DebugTools/Debug.h"
#include "GS.h" // for sending game crc to mtgs #include "GS.h" // for sending game crc to mtgs
#include "CDVD/IsoFS/IsoFSCDVD.h" #include "CDVD/IsoFS/IsoFSCDVD.h"
#include "CDVD/IsoFS/IsoFS.h" #include "CDVD/IsoFS/IsoFS.h"
using namespace std; using namespace std;
extern void InitPatch(wxString crc); extern void InitPatch(const wxString& crc);
u32 ElfCRC; u32 ElfCRC;
@ -329,16 +330,10 @@ struct ElfObject
(strnicmp( work, "cdrom1:", strlen("cdromN:")) == 0)) (strnicmp( work, "cdrom1:", strlen("cdromN:")) == 0))
{ {
IsoFSCDVD isofs; IsoFSCDVD isofs;
IsoDirectory fsroot(&isofs); IsoFile file( isofs, fromUTF8(work) );
// Will throw exception if the file was not found //int size = file.getLength();
IsoFile file = fsroot.OpenFile(work + strlen("cdromN:")); rsize = file.read(data.GetPtr(), data.GetSizeInBytes());
int size = file.getLength();
rsize = file.read((u8*)data.GetPtr(), data.GetSizeInBytes());
//if (fi < 0) throw Exception::FileNotFound( filename );
} }
else else
{ {
@ -509,24 +504,16 @@ void ElfApplyPatches()
// Fetches the CRC of the game bound to the CDVD plugin. // Fetches the CRC of the game bound to the CDVD plugin.
u32 loadElfCRC( const char* filename ) u32 loadElfCRC( const char* filename )
{ {
IsoFSCDVD isofs;
IsoDirectory fsroot(&isofs);
IsoFileDescriptor desc;
u32 crcval = 0; u32 crcval = 0;
Console.WriteLn("loadElfCRC: %s", filename); Console.WriteLn("loadElfCRC: %s", filename);
int mylen = strlen( "cdromN:" );
try { IsoFSCDVD isofs;
int mylen = strlen( "cdromN:" ); const int filesize = IsoDirectory(isofs).GetFileSize( fromUTF8(filename) );
desc = fsroot.FindFile( filename + mylen );
DevCon.WriteLn( "loadElfFile: %d bytes", desc.size ); DevCon.WriteLn( "loadElfFile: %d bytes", filesize );
crcval = ElfObject( fromUTF8( filename ), desc.size ).GetCRC(); crcval = ElfObject( fromUTF8(filename), filesize ).GetCRC();
Console.WriteLn( "loadElfFile: %s; CRC = %8.8X", filename, crcval ); Console.WriteLn( "loadElfFile: %s; CRC = %8.8X", filename, crcval );
}
catch( ... )
{
}
return crcval; return crcval;
} }
@ -548,9 +535,8 @@ void loadElfFile(const wxString& filename)
s64 elfsize; s64 elfsize;
Console.WriteLn( L"loadElfFile: " + filename ); Console.WriteLn( L"loadElfFile: " + filename );
const wxCharBuffer buffer( filename.ToUTF8() ); const wxCharBuffer fnptr( filename.ToUTF8() );
const char* fnptr = buffer.data(); bool useCdvdSource = false;
bool useCdvdSource=false;
if( !filename.StartsWith( L"cdrom0:" ) && !filename.StartsWith( L"cdrom1:" ) ) if( !filename.StartsWith( L"cdrom0:" ) && !filename.StartsWith( L"cdrom1:" ) )
{ {
@ -562,21 +548,9 @@ void loadElfFile(const wxString& filename)
DevCon.WriteLn("Loading from a CD rom or CD image"); DevCon.WriteLn("Loading from a CD rom or CD image");
useCdvdSource = true; useCdvdSource = true;
IsoFileDescriptor desc; Console.WriteLn(L"loadElfCRC: " + filename);
try IsoFSCDVD isofs;
{ elfsize = IsoDirectory( isofs ).GetFileSize( fromUTF8(fnptr) );
IsoFSCDVD isofs;
IsoDirectory fsroot(&isofs);
Console.WriteLn(L"loadElfCRC: " + filename);
desc = fsroot.FindFile(fnptr + strlen( "cdromN:" ));
}
catch( ... )
{
throw Exception::FileNotFound( filename, wxLt("ELF file was not found on the CDVD source media.") );
}
elfsize = desc.size;
} }
if( elfsize > 0xfffffff ) if( elfsize > 0xfffffff )
@ -632,51 +606,64 @@ void loadElfFile(const wxString& filename)
// 2 - PS2 CD // 2 - PS2 CD
int GetPS2ElfName( wxString& name ) int GetPS2ElfName( wxString& name )
{ {
char buffer[g_MaxPath];//if a file is longer...it should be shorter :D char buffer[512];
try { try {
IsoFSCDVD isofs; IsoFSCDVD isofs;
IsoDirectory fsroot(&isofs); IsoFile file( isofs, L"SYSTEM.CNF;1");
try { int size = file.getLength();
// Will throw exception if the file was not found if( size == 0 ) return 0;
IsoFile file = fsroot.OpenFile("SYSTEM.CNF;1");
int size = file.getLength(); file.read( buffer, size );
buffer[size] = '\0';
}
catch( Exception::FileNotFound& )
{
return 0; // no SYSTEM.CNF, not a PS1/PS2 disc.
}
char buffer[256]; //if the file is longer...it should be shorter :D int retype = 0;
file.read((u8*)buffer,size); wxArrayString lines;
buffer[size]='\0'; SplitString( lines, fromUTF8((char*)buffer), L"\n" );
char* pos = strstr(buffer, "BOOT2"); for( uint i=0; i<lines.GetCount(); ++i )
if (pos == NULL) {
{ ParsedAssignmentString parts( lines[i] );
pos = strstr(buffer, "BOOT");
if (pos==NULL) {
Console.Error("PCSX2 Boot Error: This is not a Playstation or PS2 game!");
return 0;
}
return 1;
}
pos+=strlen("BOOT2"); if( parts.rvalue.IsEmpty() )
while (pos && *pos && pos<&buffer[g_MaxPath]
&& (*pos<'A' || (*pos>'Z' && *pos<'a') || *pos>'z'))
pos++;
if (!pos || *pos==0)
return 0;
// the filename is everything up to the first CR/LF/tab.. ?
// Or up to any whitespace? (I'm opting for first CRLF/tab, although the old code
// apparently stopped on spaces too) --air
name = wxStringTokenizer( fromUTF8( pos ) ).GetNextToken();
}
catch( ... )
{ {
Console.Error( "(GetElfName) Unusual or malformed entry in SYSTEM.CNF ignored:" );
Console.WriteLn( L"\t" + lines[i] );
continue;
}
if( parts.lvalue == L"BOOT2" )
{
Console.WriteLn( Color_StrongBlue, L"(GetElfName) Detected PS2 Disc = " + name );
name = parts.rvalue;
retype = 2;
}
else if( parts.lvalue == L"BOOT" )
{
Console.WriteLn( Color_StrongBlue, L"(GetElfName) Detected PSX/PSone Disc = " + name );
name = parts.rvalue;
retype = 1;
}
else if( parts.lvalue == L"VMODE" )
{
Console.WriteLn( Color_StrongBlue, L"(GetElfName) Disc region type = " + parts.rvalue );
}
else if( parts.lvalue == L"VER" )
{
Console.WriteLn( Color_StrongBlue, L"(GetElfName) Software version = " + parts.rvalue );
} }
} }
catch( ... )
if( retype == 0 )
{ {
Console.Error("(GetElfName) Disc image is *not* a Playstation or PS2 game!");
return 0;
} }
#ifdef PCSX2_DEVBUILD #ifdef PCSX2_DEVBUILD