mirror of https://github.com/PCSX2/pcsx2.git
189 lines
3.9 KiB
C++
189 lines
3.9 KiB
C++
/* PCSX2 - PS2 Emulator for PCs
|
|
* Copyright (C) 2002-2014 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 "AsyncFileReader.h"
|
|
#include "IopCommon.h"
|
|
#include "IsoFileFormats.h"
|
|
|
|
#include <errno.h>
|
|
|
|
enum isoFlags
|
|
{
|
|
ISOFLAGS_BLOCKDUMP_V2 = 0x0004,
|
|
ISOFLAGS_BLOCKDUMP_V3 = 0x0020
|
|
};
|
|
|
|
static const uint BlockDumpHeaderSize = 16;
|
|
|
|
bool BlockdumpFileReader::DetectBlockdump(AsyncFileReader* reader)
|
|
{
|
|
uint oldbs = reader->GetBlockSize();
|
|
|
|
reader->SetBlockSize(1);
|
|
|
|
char buf[5] = {0};
|
|
reader->ReadSync(buf, 0, 4);
|
|
|
|
bool isbd = (strncmp(buf, "BDV2", 4) == 0);
|
|
|
|
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)
|
|
{
|
|
Close();
|
|
}
|
|
|
|
bool BlockdumpFileReader::Open(const wxString& fileName)
|
|
{
|
|
char buf[32];
|
|
|
|
m_filename = fileName;
|
|
|
|
m_file = new wxFileInputStream( m_filename );
|
|
|
|
m_file->SeekI(0);
|
|
m_file->Read(buf, 4);
|
|
|
|
if (strncmp(buf, "BDV2", 4) != 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//m_flags = ISOFLAGS_BLOCKDUMP_V2;
|
|
m_file->Read(&m_blocksize, sizeof(m_blocksize));
|
|
m_file->Read(&m_blocks, sizeof(m_blocks));
|
|
m_file->Read(&m_blockofs, sizeof(m_blockofs));
|
|
|
|
wxFileOffset flen = m_file->GetLength();
|
|
static const wxFileOffset datalen = flen - BlockDumpHeaderSize;
|
|
|
|
pxAssert( (datalen % (m_blocksize + 4)) == 0);
|
|
|
|
m_dtablesize = datalen / (m_blocksize + 4);
|
|
m_dtable = std::unique_ptr<u32[]>(new u32[m_dtablesize]);
|
|
|
|
m_file->SeekI(BlockDumpHeaderSize);
|
|
|
|
u32 bs = 1024*1024;
|
|
u32 off = 0;
|
|
u32 has = 0;
|
|
int i = 0;
|
|
|
|
std::unique_ptr<u8[]> buffer(new u8[bs]);
|
|
do {
|
|
m_file->Read(buffer.get(), bs);
|
|
has = m_file->LastRead();
|
|
|
|
while (i < m_dtablesize && off < has)
|
|
{
|
|
m_dtable[i++] = *reinterpret_cast<u32*>(buffer.get() + off);
|
|
off += 4;
|
|
off += m_blocksize;
|
|
}
|
|
|
|
off -= has;
|
|
|
|
} while(has == bs);
|
|
|
|
return true;
|
|
}
|
|
|
|
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)
|
|
{
|
|
bool ok = false;
|
|
for (int i = 0; i < m_dtablesize; ++i)
|
|
{
|
|
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.
|
|
|
|
#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 );
|
|
#else
|
|
m_file->SeekI( BlockDumpHeaderSize + (i * (m_blocksize + 4)) + 4 );
|
|
#endif
|
|
|
|
m_file->Read( dst, m_blocksize );
|
|
|
|
ok = true;
|
|
break;
|
|
}
|
|
|
|
if(!ok)
|
|
{
|
|
Console.WriteLn("Block %u not found in dump", lsn);
|
|
return -1;
|
|
}
|
|
|
|
count--;
|
|
lsn++;
|
|
dst += m_blocksize;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void BlockdumpFileReader::BeginRead(void* pBuffer, uint sector, uint count)
|
|
{
|
|
m_lresult = ReadSync(pBuffer, sector, count);
|
|
}
|
|
|
|
int BlockdumpFileReader::FinishRead(void)
|
|
{
|
|
return m_lresult;
|
|
}
|
|
|
|
void BlockdumpFileReader::CancelRead(void)
|
|
{
|
|
}
|
|
|
|
void BlockdumpFileReader::Close(void)
|
|
{
|
|
if(m_file)
|
|
{
|
|
delete m_file;
|
|
m_file = NULL;
|
|
}
|
|
}
|
|
|
|
uint BlockdumpFileReader::GetBlockCount(void) const
|
|
{
|
|
return m_blocks;
|
|
}
|