Add an interface to read multiple blocks at once.

This commit is contained in:
Unknown W. Brackets 2014-11-02 19:50:26 -08:00
parent bf50baf698
commit 9c5ad44000
2 changed files with 42 additions and 27 deletions

View file

@ -31,6 +31,15 @@ class BlockDevice
public:
virtual ~BlockDevice() {}
virtual bool ReadBlock(int blockNumber, u8 *outPtr) = 0;
virtual bool ReadBlocks(int minBlock, int count, u8 *outPtr) {
for (int b = 0; b < count; ++b) {
if (!ReadBlock(minBlock + b, outPtr)) {
return false;
}
outPtr += GetBlockSize();
}
return true;
}
int GetBlockSize() const { return 2048;} // forced, it cannot be changed by subclasses
virtual u32 GetNumBlocks() = 0;
};

View file

@ -18,6 +18,7 @@
#include <cstring>
#include <cstdio>
#include <ctype.h>
#include <algorithm>
#include "Common/Common.h"
#include "Common/CommonTypes.h"
@ -494,10 +495,10 @@ int ISOFileSystem::Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outd
u32 size = (u32)desc.pathTableLengthLE;
u8 *out = Memory::GetPointer(outdataPtr);
while (size >= 2048) {
blockDevice->ReadBlock(block++, out);
out += 2048;
}
int blocks = size / blockDevice->GetBlockSize();
blockDevice->ReadBlocks(block, blocks, out);
size -= blocks * blockDevice->GetBlockSize();
out += blocks * blockDevice->GetBlockSize();
// The remaining (or, usually, only) partial sector.
if (size > 0) {
@ -527,12 +528,9 @@ size_t ISOFileSystem::ReadFile(u32 handle, u8 *pointer, s64 size)
if (e.isBlockSectorMode)
{
// Whole sectors! Shortcut to this simple code.
for (int i = 0; i < size; i++)
{
blockDevice->ReadBlock(e.seekPos, pointer + i * 2048);
e.seekPos++;
}
return (size_t)size;
blockDevice->ReadBlocks(e.seekPos, (int)size, pointer);
e.seekPos += (int)size;
return (int)size;
}
u32 positionOnIso;
@ -559,29 +557,37 @@ size_t ISOFileSystem::ReadFile(u32 handle, u8 *pointer, s64 size)
}
//okay, we have size and position, let's rock
u32 totalRead = 0;
const int firstBlockOffset = positionOnIso & 2047;
const int firstBlockSize = firstBlockOffset == 0 ? 0 : (int)std::min(size, 2048LL - firstBlockOffset);
const int lastBlockSize = (size - firstBlockSize) & 2047;
const s64 middleSize = size - firstBlockSize - lastBlockSize;
int secNum = positionOnIso / 2048;
int posInSector = positionOnIso & 2047;
s64 remain = size;
u8 theSector[2048];
while (remain > 0)
{
blockDevice->ReadBlock(secNum, theSector);
size_t bytesToCopy = 2048 - posInSector;
if ((s64)bytesToCopy > remain)
bytesToCopy = (size_t)remain;
_dbg_assert_msg_(FILESYS, (middleSize & 2047) == 0, "Remaining size should be aligned");
memcpy(pointer, theSector + posInSector, bytesToCopy);
totalRead += (u32)bytesToCopy;
pointer += bytesToCopy;
remain -= bytesToCopy;
posInSector = 0;
secNum++;
if (firstBlockSize != 0)
{
blockDevice->ReadBlock(secNum++, theSector);
memcpy(pointer, theSector + firstBlockOffset, firstBlockSize);
pointer += firstBlockSize;
}
if (middleSize != 0)
{
const u32 sectors = (u32)(middleSize / 2048);
blockDevice->ReadBlocks(secNum, sectors, pointer);
secNum += sectors;
pointer += middleSize;
}
if (lastBlockSize != 0)
{
blockDevice->ReadBlock(secNum++, theSector);
memcpy(pointer, theSector, lastBlockSize);
pointer += lastBlockSize;
}
e.seekPos += (unsigned int)size;
return totalRead;
return (size_t)size;
}
else
{