mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
- common has no wx left except for Path. - pcsx2core only has it in a few places (memory cards and path related stuff).
247 lines
5.4 KiB
C++
247 lines
5.4 KiB
C++
/* PCSX2 - PS2 Emulator for PCs
|
|
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
|
*
|
|
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
|
* ation, either version 3 of the License, or (at your option) any later version.
|
|
*
|
|
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with PCSX2.
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
|
|
#include "PrecompiledHeader.h"
|
|
#include "common/Assertions.h"
|
|
#include "common/Exceptions.h"
|
|
|
|
#include "IsoFS.h"
|
|
#include "IsoFile.h"
|
|
|
|
#include <cstdio>
|
|
|
|
IsoFile::IsoFile(SectorSource& reader, const std::string_view& filename)
|
|
: internalReader(reader)
|
|
, fileEntry(IsoDirectory(reader).FindFile(filename))
|
|
{
|
|
Init();
|
|
}
|
|
|
|
IsoFile::IsoFile(const IsoDirectory& dir, const std::string_view& filename)
|
|
: internalReader(dir.GetReader())
|
|
, fileEntry(dir.FindFile(filename))
|
|
{
|
|
Init();
|
|
}
|
|
|
|
IsoFile::IsoFile(SectorSource& reader, const IsoFileDescriptor& fileEntry)
|
|
: internalReader(reader)
|
|
, fileEntry(fileEntry)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
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);
|
|
|
|
if (maxOffset > 0)
|
|
internalReader.readSector(currentSector, currentSectorNumber);
|
|
}
|
|
|
|
u32 IsoFile::seek(u32 absoffset)
|
|
{
|
|
u32 endOffset = absoffset;
|
|
|
|
int oldSectorNumber = currentSectorNumber;
|
|
int newSectorNumber = fileEntry.lba + (int)(endOffset / sectorLength);
|
|
|
|
if (oldSectorNumber != newSectorNumber)
|
|
{
|
|
internalReader.readSector(currentSector, newSectorNumber);
|
|
}
|
|
|
|
currentOffset = endOffset;
|
|
currentSectorNumber = newSectorNumber;
|
|
sectorOffset = (int)(currentOffset % sectorLength);
|
|
|
|
return currentOffset;
|
|
}
|
|
|
|
// Returns the new offset in the file. Out-of-bounds seeks are automatically truncated at 0
|
|
// and fileLength.
|
|
u32 IsoFile::seek(s64 offset, int mode)
|
|
{
|
|
switch (mode)
|
|
{
|
|
case SEEK_SET:
|
|
pxAssertDev(offset >= 0 && offset <= (s64)ULONG_MAX, "Invalid seek position from start.");
|
|
return seek(offset);
|
|
|
|
case SEEK_CUR:
|
|
// truncate negative values to zero, and positive values to 4gb
|
|
return seek(std::min(std::max<s64>(0, (s64)currentOffset + offset), (s64)ULONG_MAX));
|
|
|
|
case SEEK_END:
|
|
// 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));
|
|
|
|
jNO_DEFAULT;
|
|
}
|
|
|
|
return 0; // unreachable
|
|
}
|
|
|
|
void IsoFile::reset()
|
|
{
|
|
seek(0);
|
|
}
|
|
|
|
// Returns the number of bytes actually skipped.
|
|
s32 IsoFile::skip(s32 n)
|
|
{
|
|
s32 oldOffset = currentOffset;
|
|
|
|
if (n < 0)
|
|
return 0;
|
|
|
|
seek(currentOffset + n);
|
|
|
|
return currentOffset - oldOffset;
|
|
}
|
|
|
|
u32 IsoFile::getSeekPos() const
|
|
{
|
|
return currentOffset;
|
|
}
|
|
|
|
bool IsoFile::eof() const
|
|
{
|
|
return (currentOffset == maxOffset);
|
|
}
|
|
|
|
// loads the current sector index into the CurrentSector buffer.
|
|
void IsoFile::makeDataAvailable()
|
|
{
|
|
if (sectorOffset >= sectorLength)
|
|
{
|
|
currentSectorNumber++;
|
|
internalReader.readSector(currentSector, currentSectorNumber);
|
|
sectorOffset -= sectorLength;
|
|
}
|
|
}
|
|
|
|
u8 IsoFile::readByte()
|
|
{
|
|
if (currentOffset >= maxOffset)
|
|
throw Exception::EndOfStream();
|
|
|
|
makeDataAvailable();
|
|
|
|
currentOffset++;
|
|
|
|
return currentSector[sectorOffset++];
|
|
}
|
|
|
|
// Reads data from a single sector at a time. Reads cannot cross sector boundaries.
|
|
int IsoFile::internalRead(void* dest, int off, int len)
|
|
{
|
|
if (len > 0)
|
|
{
|
|
size_t slen = len;
|
|
if (slen > (maxOffset - currentOffset))
|
|
{
|
|
slen = (int)(maxOffset - currentOffset);
|
|
}
|
|
|
|
memcpy((u8*)dest + off, currentSector + sectorOffset, slen);
|
|
|
|
sectorOffset += slen;
|
|
currentOffset += slen;
|
|
return slen;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// 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...
|
|
|
|
if (len <= 0)
|
|
return 0;
|
|
|
|
int off = 0;
|
|
|
|
int totalLength = 0;
|
|
|
|
int firstSector = internalRead(dest, off, std::min(len, sectorLength - sectorOffset));
|
|
off += firstSector;
|
|
len -= firstSector;
|
|
totalLength += firstSector;
|
|
|
|
// Read whole sectors
|
|
while ((len >= sectorLength) && (currentOffset < maxOffset))
|
|
{
|
|
makeDataAvailable();
|
|
int n = internalRead(dest, off, sectorLength);
|
|
off += n;
|
|
len -= n;
|
|
totalLength += n;
|
|
}
|
|
|
|
// Read remaining, if any
|
|
if (len > 0)
|
|
{
|
|
makeDataAvailable();
|
|
int lastSector = internalRead(dest, off, len);
|
|
totalLength += lastSector;
|
|
}
|
|
|
|
return totalLength;
|
|
}
|
|
|
|
// Reads data until it reaches a newline character (either \n, \r, or ASCII-Z). The caller is
|
|
// 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;
|
|
}
|