mirror of https://github.com/AxioDL/nod.git
Removed direct stdio usage
This commit is contained in:
parent
9ce2e0a3b2
commit
df5e8d068c
|
@ -31,7 +31,7 @@ public:
|
||||||
struct IWriteStream
|
struct IWriteStream
|
||||||
{
|
{
|
||||||
virtual ~IWriteStream() {}
|
virtual ~IWriteStream() {}
|
||||||
virtual uint64_t write(void* buf, uint64_t length)=0;
|
virtual uint64_t write(const void* buf, uint64_t length)=0;
|
||||||
};
|
};
|
||||||
virtual std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset=0) const=0;
|
virtual std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset=0) const=0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,6 +13,7 @@ class IFileIO
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~IFileIO() {}
|
virtual ~IFileIO() {}
|
||||||
|
virtual bool exists()=0;
|
||||||
virtual uint64_t size()=0;
|
virtual uint64_t size()=0;
|
||||||
|
|
||||||
struct IWriteStream
|
struct IWriteStream
|
||||||
|
@ -27,6 +28,7 @@ public:
|
||||||
struct IReadStream
|
struct IReadStream
|
||||||
{
|
{
|
||||||
virtual ~IReadStream() {}
|
virtual ~IReadStream() {}
|
||||||
|
virtual void seek(int64_t offset, int whence)=0;
|
||||||
virtual uint64_t read(void* buf, uint64_t length)=0;
|
virtual uint64_t read(void* buf, uint64_t length)=0;
|
||||||
virtual uint64_t copyToDisc(struct IPartWriteStream& discio, uint64_t length)=0;
|
virtual uint64_t copyToDisc(struct IPartWriteStream& discio, uint64_t length)=0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -294,9 +294,16 @@ static inline bool CheckFreeSpace(const SystemChar* path, size_t reqSz)
|
||||||
{
|
{
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
ULARGE_INTEGER freeBytes;
|
ULARGE_INTEGER freeBytes;
|
||||||
if (!GetDiskFreeSpaceExW(path, &freeBytes, nullptr, nullptr))
|
wchar_t buf[1024];
|
||||||
LogModule.report(LogVisor::FatalError, "GetDiskFreeSpaceExW %s: %d", path, GetLastError());
|
wchar_t* end;
|
||||||
return reqSz < freeBytes;
|
DWORD ret = GetFullPathNameW(path, 1024, buf, &end);
|
||||||
|
if (!ret || ret > 1024)
|
||||||
|
LogModule.report(LogVisor::FatalError, _S("GetFullPathNameW %s"), path);
|
||||||
|
if (end)
|
||||||
|
end[0] = L'\0';
|
||||||
|
if (!GetDiskFreeSpaceExW(buf, &freeBytes, nullptr, nullptr))
|
||||||
|
LogModule.report(LogVisor::FatalError, _S("GetDiskFreeSpaceExW %s: %d"), path, GetLastError());
|
||||||
|
return reqSz < freeBytes.QuadPart;
|
||||||
#else
|
#else
|
||||||
struct statvfs svfs;
|
struct statvfs svfs;
|
||||||
if (statvfs(path, &svfs))
|
if (statvfs(path, &svfs))
|
||||||
|
|
|
@ -181,16 +181,14 @@ public:
|
||||||
header.write(*ws);
|
header.write(*ws);
|
||||||
|
|
||||||
ws = beginWriteStream(0x2440);
|
ws = beginWriteStream(0x2440);
|
||||||
FILE* fp = Fopen(apploaderIn, _S("rb"), FileLockType::Read);
|
std::unique_ptr<IFileIO::IReadStream> rs = NewFileIO(apploaderIn)->beginReadStream();
|
||||||
if (!fp)
|
|
||||||
LogModule.report(LogVisor::FatalError, _S("unable to open %s for reading"), apploaderIn);
|
|
||||||
char buf[8192];
|
char buf[8192];
|
||||||
size_t xferSz = 0;
|
size_t xferSz = 0;
|
||||||
SystemString apploaderName(apploaderIn);
|
SystemString apploaderName(apploaderIn);
|
||||||
++m_parent.m_progressIdx;
|
++m_parent.m_progressIdx;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
size_t rdSz = fread(buf, 1, 8192, fp);
|
size_t rdSz = rs->read(buf, 8192);
|
||||||
if (!rdSz)
|
if (!rdSz)
|
||||||
break;
|
break;
|
||||||
ws->write(buf, rdSz);
|
ws->write(buf, rdSz);
|
||||||
|
@ -200,7 +198,6 @@ public:
|
||||||
"apploader flows into user area (one or the other is too big)");
|
"apploader flows into user area (one or the other is too big)");
|
||||||
m_parent.m_progressCB(m_parent.m_progressIdx, apploaderName, xferSz);
|
m_parent.m_progressCB(m_parent.m_progressIdx, apploaderName, xferSz);
|
||||||
}
|
}
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
size_t fstOff = ROUND_UP_32(xferSz);
|
size_t fstOff = ROUND_UP_32(xferSz);
|
||||||
size_t fstSz = sizeof(FSTNode) * m_buildNodes.size();
|
size_t fstSz = sizeof(FSTNode) * m_buildNodes.size();
|
||||||
|
@ -234,7 +231,7 @@ public:
|
||||||
|
|
||||||
bool DiscBuilderGCN::buildFromDirectory(const SystemChar* dirIn, const SystemChar* dolIn,
|
bool DiscBuilderGCN::buildFromDirectory(const SystemChar* dirIn, const SystemChar* dolIn,
|
||||||
const SystemChar* apploaderIn)
|
const SystemChar* apploaderIn)
|
||||||
{
|
{
|
||||||
m_fileIO->beginWriteStream();
|
m_fileIO->beginWriteStream();
|
||||||
|
|
||||||
if (!CheckFreeSpace(m_outPath, 0x57058000))
|
if (!CheckFreeSpace(m_outPath, 0x57058000))
|
||||||
|
|
|
@ -2,11 +2,6 @@
|
||||||
#include "NOD/Util.hpp"
|
#include "NOD/Util.hpp"
|
||||||
#include "NOD/IDiscIO.hpp"
|
#include "NOD/IDiscIO.hpp"
|
||||||
|
|
||||||
#if _WIN32
|
|
||||||
#define ftello _ftelli64
|
|
||||||
#define fseeko _fseeki64
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace NOD
|
namespace NOD
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -20,60 +15,132 @@ public:
|
||||||
class ReadStream : public IReadStream
|
class ReadStream : public IReadStream
|
||||||
{
|
{
|
||||||
friend class DiscIOISO;
|
friend class DiscIOISO;
|
||||||
|
#if _WIN32
|
||||||
|
HANDLE fp;
|
||||||
|
ReadStream(HANDLE fpin)
|
||||||
|
: fp(fpin) {}
|
||||||
|
~ReadStream() {CloseHandle(fp);}
|
||||||
|
#else
|
||||||
FILE* fp;
|
FILE* fp;
|
||||||
ReadStream(FILE* fpin)
|
ReadStream(FILE* fpin)
|
||||||
: fp(fpin) {}
|
: fp(fpin) {}
|
||||||
~ReadStream() {fclose(fp);}
|
~ReadStream() {fclose(fp);}
|
||||||
|
#endif
|
||||||
public:
|
public:
|
||||||
|
#if _WIN32
|
||||||
|
uint64_t read(void* buf, uint64_t length)
|
||||||
|
{
|
||||||
|
DWORD ret = 0;
|
||||||
|
ReadFile(fp, buf, length, &ret, nullptr);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
uint64_t position() const
|
||||||
|
{
|
||||||
|
LARGE_INTEGER liOfs={0};
|
||||||
|
LARGE_INTEGER liNew={0};
|
||||||
|
SetFilePointerEx(fp, liOfs, &liNew, FILE_CURRENT);
|
||||||
|
return liNew.QuadPart;
|
||||||
|
}
|
||||||
|
void seek(int64_t offset, int whence)
|
||||||
|
{
|
||||||
|
LARGE_INTEGER li;
|
||||||
|
li.QuadPart = offset;
|
||||||
|
SetFilePointerEx(fp, li, nullptr, whence);
|
||||||
|
}
|
||||||
|
#else
|
||||||
uint64_t read(void* buf, uint64_t length)
|
uint64_t read(void* buf, uint64_t length)
|
||||||
{return fread(buf, 1, length, fp);}
|
{return fread(buf, 1, length, fp);}
|
||||||
uint64_t position() const
|
uint64_t position() const
|
||||||
{return ftello(fp);}
|
{return ftello(fp);}
|
||||||
void seek(int64_t offset, int whence)
|
void seek(int64_t offset, int whence)
|
||||||
{fseeko(fp, offset, whence);}
|
{FSeek(fp, offset, whence);}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
std::unique_ptr<IReadStream> beginReadStream(uint64_t offset) const
|
std::unique_ptr<IReadStream> beginReadStream(uint64_t offset) const
|
||||||
{
|
{
|
||||||
#if NOD_UCS2
|
HANDLE fp = CreateFileW(filepath.c_str(), GENERIC_READ, FILE_SHARE_READ,
|
||||||
FILE* fp = _wfopen(filepath.c_str(), L"rb");
|
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
|
if (fp == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
LogModule.report(LogVisor::Error, _S("Unable to open '%s' for reading"), filepath.c_str());
|
||||||
|
return std::unique_ptr<IReadStream>();
|
||||||
|
}
|
||||||
|
LARGE_INTEGER li;
|
||||||
|
li.QuadPart = offset;
|
||||||
|
SetFilePointerEx(fp, li, nullptr, FILE_BEGIN);
|
||||||
|
return std::unique_ptr<IReadStream>(new ReadStream(fp));
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
|
std::unique_ptr<IReadStream> beginReadStream(uint64_t offset) const
|
||||||
|
{
|
||||||
FILE* fp = fopen(filepath.c_str(), "rb");
|
FILE* fp = fopen(filepath.c_str(), "rb");
|
||||||
#endif
|
|
||||||
if (!fp)
|
if (!fp)
|
||||||
{
|
{
|
||||||
LogModule.report(LogVisor::Error, _S("Unable to open '%s' for reading"), filepath.c_str());
|
LogModule.report(LogVisor::Error, _S("Unable to open '%s' for reading"), filepath.c_str());
|
||||||
return std::unique_ptr<IReadStream>();
|
return std::unique_ptr<IReadStream>();
|
||||||
}
|
}
|
||||||
fseeko(fp, offset, SEEK_SET);
|
FSeek(fp, offset, SEEK_SET);
|
||||||
return std::unique_ptr<IReadStream>(new ReadStream(fp));
|
return std::unique_ptr<IReadStream>(new ReadStream(fp));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
class WriteStream : public IWriteStream
|
class WriteStream : public IWriteStream
|
||||||
{
|
{
|
||||||
friend class DiscIOISO;
|
friend class DiscIOISO;
|
||||||
|
#if _WIN32
|
||||||
|
HANDLE fp;
|
||||||
|
WriteStream(HANDLE fpin)
|
||||||
|
: fp(fpin) {}
|
||||||
|
~WriteStream() {CloseHandle(fp);}
|
||||||
|
#else
|
||||||
FILE* fp;
|
FILE* fp;
|
||||||
WriteStream(FILE* fpin)
|
WriteStream(FILE* fpin)
|
||||||
: fp(fpin) {}
|
: fp(fpin) {}
|
||||||
~WriteStream() {fclose(fp);}
|
~WriteStream() {fclose(fp);}
|
||||||
|
#endif
|
||||||
public:
|
public:
|
||||||
uint64_t write(void* buf, uint64_t length)
|
uint64_t write(const void* buf, uint64_t length)
|
||||||
{return fwrite(buf, 1, length, fp);}
|
{
|
||||||
|
#if _WIN32
|
||||||
|
DWORD ret = 0;
|
||||||
|
WriteFile(fp, buf, length, &ret, nullptr);
|
||||||
|
return ret;
|
||||||
|
#else
|
||||||
|
return fwrite(buf, 1, length, fp);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const
|
std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const
|
||||||
{
|
{
|
||||||
#if NOD_UCS2
|
HANDLE fp = CreateFileW(filepath.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE,
|
||||||
FILE* fp = _wfopen(filepath.c_str(), L"wb");
|
nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
|
if (fp == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
LogModule.report(LogVisor::Error, _S("Unable to open '%s' for writing"), filepath.c_str());
|
||||||
|
return std::unique_ptr<IWriteStream>();
|
||||||
|
}
|
||||||
|
LARGE_INTEGER li;
|
||||||
|
li.QuadPart = offset;
|
||||||
|
SetFilePointerEx(fp, li, nullptr, FILE_BEGIN);
|
||||||
|
return std::unique_ptr<IWriteStream>(new WriteStream(fp));
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
|
std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const
|
||||||
|
{
|
||||||
FILE* fp = fopen(filepath.c_str(), "wb");
|
FILE* fp = fopen(filepath.c_str(), "wb");
|
||||||
#endif
|
|
||||||
if (!fp)
|
if (!fp)
|
||||||
{
|
{
|
||||||
LogModule.report(LogVisor::Error, _S("Unable to open '%s' for writing"), filepath.c_str());
|
LogModule.report(LogVisor::Error, _S("Unable to open '%s' for writing"), filepath.c_str());
|
||||||
return std::unique_ptr<IWriteStream>();
|
return std::unique_ptr<IWriteStream>();
|
||||||
}
|
}
|
||||||
fseeko(fp, offset, SEEK_SET);
|
FSeek(fp, offset, SEEK_SET);
|
||||||
return std::unique_ptr<IWriteStream>(new WriteStream(fp));
|
return std::unique_ptr<IWriteStream>(new WriteStream(fp));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<IDiscIO> NewDiscIOISO(const SystemChar* path)
|
std::unique_ptr<IDiscIO> NewDiscIOISO(const SystemChar* path)
|
||||||
|
|
|
@ -2,11 +2,7 @@
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "NOD/Util.hpp"
|
#include "NOD/Util.hpp"
|
||||||
#include "NOD/IDiscIO.hpp"
|
#include "NOD/IDiscIO.hpp"
|
||||||
|
#include "NOD/IFileIO.hpp"
|
||||||
#if _WIN32
|
|
||||||
#define ftello _ftelli64
|
|
||||||
#define fseeko _fseeki64
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace NOD
|
namespace NOD
|
||||||
{
|
{
|
||||||
|
@ -77,16 +73,13 @@ class DiscIOWBFS : public IDiscIO
|
||||||
|
|
||||||
} wbfs;
|
} wbfs;
|
||||||
|
|
||||||
static int _wbfsReadSector(FILE* fp, uint32_t lba, uint32_t count, void* buf)
|
static int _wbfsReadSector(IFileIO::IReadStream& rs, uint32_t lba, uint32_t count, void* buf)
|
||||||
{
|
{
|
||||||
uint64_t off = lba;
|
uint64_t off = lba;
|
||||||
off*=512ULL;
|
off*=512ULL;
|
||||||
if (fseeko(fp, off, SEEK_SET))
|
rs.seek(off, SEEK_SET);
|
||||||
|
if (rs.read(buf, count*512ULL) != count*512ULL)
|
||||||
{
|
{
|
||||||
LogModule.report(LogVisor::FatalError, "error seeking in disc partition: %" PRId64 " %d", off, count);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (fread(buf, count*512ULL, 1, fp) != 1){
|
|
||||||
LogModule.report(LogVisor::FatalError, "error reading disc");
|
LogModule.report(LogVisor::FatalError, "error reading disc");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -98,23 +91,20 @@ public:
|
||||||
: filepath(fpin)
|
: filepath(fpin)
|
||||||
{
|
{
|
||||||
/* Temporary file handle to read LBA table */
|
/* Temporary file handle to read LBA table */
|
||||||
#if NOD_UCS2
|
std::unique_ptr<IFileIO> fio = NewFileIO(filepath);
|
||||||
FILE* fp = _wfopen(filepath.c_str(), L"rb");
|
std::unique_ptr<IFileIO::IReadStream> rs = fio->beginReadStream();
|
||||||
#else
|
|
||||||
FILE* fp = fopen(filepath.c_str(), "rb");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
WBFS* p = &wbfs;
|
WBFS* p = &wbfs;
|
||||||
WBFSHead tmpHead;
|
WBFSHead tmpHead;
|
||||||
if (fread(&tmpHead, 1, sizeof(tmpHead), fp) != sizeof(tmpHead))
|
if (rs->read(&tmpHead, sizeof(tmpHead)) != sizeof(tmpHead))
|
||||||
LogModule.report(LogVisor::FatalError, "unable to read WBFS head");
|
LogModule.report(LogVisor::FatalError, "unable to read WBFS head");
|
||||||
fseek(fp, 0, SEEK_SET);
|
|
||||||
unsigned hd_sector_size = 1 << tmpHead.hd_sec_sz_s;
|
unsigned hd_sector_size = 1 << tmpHead.hd_sec_sz_s;
|
||||||
unsigned num_hd_sector = SBig(tmpHead.n_hd_sec);
|
unsigned num_hd_sector = SBig(tmpHead.n_hd_sec);
|
||||||
|
|
||||||
wbfsHead.reset(new uint8_t[hd_sector_size]);
|
wbfsHead.reset(new uint8_t[hd_sector_size]);
|
||||||
WBFSHead* head = (WBFSHead*)wbfsHead.get();
|
WBFSHead* head = (WBFSHead*)wbfsHead.get();
|
||||||
if (fread(head, 1, hd_sector_size, fp) != hd_sector_size)
|
rs->seek(0, SEEK_SET);
|
||||||
|
if (rs->read(head, hd_sector_size) != hd_sector_size)
|
||||||
LogModule.report(LogVisor::FatalError, "unable to read WBFS head");
|
LogModule.report(LogVisor::FatalError, "unable to read WBFS head");
|
||||||
|
|
||||||
//constants, but put here for consistancy
|
//constants, but put here for consistancy
|
||||||
|
@ -123,7 +113,7 @@ public:
|
||||||
p->n_wii_sec = (num_hd_sector/0x8000)*hd_sector_size;
|
p->n_wii_sec = (num_hd_sector/0x8000)*hd_sector_size;
|
||||||
p->n_wii_sec_per_disc = 143432*2;//support for double layers discs..
|
p->n_wii_sec_per_disc = 143432*2;//support for double layers discs..
|
||||||
p->part_lba = 0;
|
p->part_lba = 0;
|
||||||
_wbfsReadSector(fp, p->part_lba, 1, head);
|
_wbfsReadSector(*rs, p->part_lba, 1, head);
|
||||||
if (hd_sector_size && head->hd_sec_sz_s != size_to_shift(hd_sector_size)) {
|
if (hd_sector_size && head->hd_sec_sz_s != size_to_shift(hd_sector_size)) {
|
||||||
LogModule.report(LogVisor::FatalError, "hd sector size doesn't match");
|
LogModule.report(LogVisor::FatalError, "hd sector size doesn't match");
|
||||||
}
|
}
|
||||||
|
@ -157,7 +147,7 @@ public:
|
||||||
wbfsDiscInfo.reset(new uint8_t[p->disc_info_sz]);
|
wbfsDiscInfo.reset(new uint8_t[p->disc_info_sz]);
|
||||||
if (!wbfsDiscInfo)
|
if (!wbfsDiscInfo)
|
||||||
LogModule.report(LogVisor::FatalError, "allocating memory");
|
LogModule.report(LogVisor::FatalError, "allocating memory");
|
||||||
_wbfsReadSector(fp, p->part_lba+1, disc_info_sz_lba, wbfsDiscInfo.get());
|
_wbfsReadSector(*rs, p->part_lba+1, disc_info_sz_lba, wbfsDiscInfo.get());
|
||||||
p->n_disc_open++;
|
p->n_disc_open++;
|
||||||
//for(i=0;i<p->n_wbfs_sec_per_disc;i++)
|
//for(i=0;i<p->n_wbfs_sec_per_disc;i++)
|
||||||
// printf("%d,",wbfs_ntohs(d->header->wlba_table[i]));
|
// printf("%d,",wbfs_ntohs(d->header->wlba_table[i]));
|
||||||
|
@ -168,19 +158,18 @@ public:
|
||||||
{
|
{
|
||||||
friend class DiscIOWBFS;
|
friend class DiscIOWBFS;
|
||||||
const DiscIOWBFS& m_parent;
|
const DiscIOWBFS& m_parent;
|
||||||
FILE* fp;
|
std::unique_ptr<IFileIO::IReadStream> fp;
|
||||||
uint64_t m_offset;
|
uint64_t m_offset;
|
||||||
std::unique_ptr<uint8_t[]> m_tmpBuffer;
|
std::unique_ptr<uint8_t[]> m_tmpBuffer;
|
||||||
|
|
||||||
ReadStream(const DiscIOWBFS& parent, FILE* fpin, uint64_t offset)
|
ReadStream(const DiscIOWBFS& parent, std::unique_ptr<IFileIO::IReadStream>&& fpin, uint64_t offset)
|
||||||
: m_parent(parent),
|
: m_parent(parent),
|
||||||
fp(fpin),
|
fp(std::move(fpin)),
|
||||||
m_offset(offset),
|
m_offset(offset),
|
||||||
m_tmpBuffer(new uint8_t[parent.wbfs.hd_sec_sz]) {}
|
m_tmpBuffer(new uint8_t[parent.wbfs.hd_sec_sz]) {}
|
||||||
~ReadStream() {fclose(fp);}
|
|
||||||
|
|
||||||
int wbfsReadSector(uint32_t lba, uint32_t count, void* buf)
|
int wbfsReadSector(uint32_t lba, uint32_t count, void* buf)
|
||||||
{return DiscIOWBFS::_wbfsReadSector(fp, lba, count, buf);}
|
{return DiscIOWBFS::_wbfsReadSector(*fp, lba, count, buf);}
|
||||||
|
|
||||||
int wbfsDiscRead(uint32_t offset, uint8_t *data, uint64_t len)
|
int wbfsDiscRead(uint32_t offset, uint8_t *data, uint64_t len)
|
||||||
{
|
{
|
||||||
|
@ -279,46 +268,15 @@ public:
|
||||||
m_offset += offset;
|
m_offset += offset;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<IReadStream> beginReadStream(uint64_t offset) const
|
std::unique_ptr<IReadStream> beginReadStream(uint64_t offset) const
|
||||||
{
|
{
|
||||||
#if NOD_UCS2
|
return std::unique_ptr<IReadStream>(new ReadStream(*this, NewFileIO(filepath)->beginReadStream(), offset));
|
||||||
FILE* fp = _wfopen(filepath.c_str(), L"rb");
|
|
||||||
#else
|
|
||||||
FILE* fp = fopen(filepath.c_str(), "rb");
|
|
||||||
#endif
|
|
||||||
if (!fp)
|
|
||||||
{
|
|
||||||
LogModule.report(LogVisor::Error, _S("Unable to open '%s' for reading"), filepath.c_str());
|
|
||||||
return std::unique_ptr<IReadStream>();
|
|
||||||
}
|
|
||||||
return std::unique_ptr<IReadStream>(new ReadStream(*this, fp, offset));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class WriteStream : public IWriteStream
|
|
||||||
{
|
|
||||||
friend class DiscIOWBFS;
|
|
||||||
FILE* fp;
|
|
||||||
WriteStream(FILE* fpin)
|
|
||||||
: fp(fpin) {}
|
|
||||||
~WriteStream() {fclose(fp);}
|
|
||||||
public:
|
|
||||||
uint64_t write(void* buf, uint64_t length)
|
|
||||||
{return fwrite(buf, 1, length, fp);}
|
|
||||||
};
|
|
||||||
std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const
|
std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const
|
||||||
{
|
{
|
||||||
#if NOD_UCS2
|
return std::unique_ptr<IWriteStream>();
|
||||||
FILE* fp = _wfopen(filepath.c_str(), L"wb");
|
|
||||||
#else
|
|
||||||
FILE* fp = fopen(filepath.c_str(), "wb");
|
|
||||||
#endif
|
|
||||||
if (!fp)
|
|
||||||
{
|
|
||||||
LogModule.report(LogVisor::Error, _S("Unable to open '%s' for writing"), filepath.c_str());
|
|
||||||
return std::unique_ptr<IWriteStream>();
|
|
||||||
}
|
|
||||||
fseeko(fp, offset, SEEK_SET);
|
|
||||||
return std::unique_ptr<IWriteStream>(new WriteStream(fp));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -342,10 +342,7 @@ public:
|
||||||
|
|
||||||
void writeOutPartitionHeader(const SystemChar* pathOut) const
|
void writeOutPartitionHeader(const SystemChar* pathOut) const
|
||||||
{
|
{
|
||||||
FILE* fp = Fopen(pathOut, _S("wb"), FileLockType::Write);
|
std::unique_ptr<IFileIO::IWriteStream> ws = NewFileIO(pathOut)->beginWriteStream();
|
||||||
if (!fp)
|
|
||||||
LogModule.report(LogVisor::FatalError, _S("unable to open %s for writing"), pathOut);
|
|
||||||
|
|
||||||
uint64_t h3Off;
|
uint64_t h3Off;
|
||||||
{
|
{
|
||||||
std::unique_ptr<IDiscIO::IReadStream> rs = m_parent.getDiscIO().beginReadStream(m_offset + 0x2B4);
|
std::unique_ptr<IDiscIO::IReadStream> rs = m_parent.getDiscIO().beginReadStream(m_offset + 0x2B4);
|
||||||
|
@ -363,11 +360,9 @@ public:
|
||||||
{
|
{
|
||||||
size_t rdSz = NOD::min(rem, size_t(8192ul));
|
size_t rdSz = NOD::min(rem, size_t(8192ul));
|
||||||
rs->read(buf, rdSz);
|
rs->read(buf, rdSz);
|
||||||
fwrite(buf, 1, rdSz, fp);
|
ws->write(buf, rdSz);
|
||||||
rem -= rdSz;
|
rem -= rdSz;
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -910,8 +905,19 @@ bool DiscBuilderWii::buildFromDirectory(const SystemChar* dirIn, const SystemCha
|
||||||
|
|
||||||
/* Fill image to end */
|
/* Fill image to end */
|
||||||
ws = m_fileIO->beginWriteStream(filledSz);
|
ws = m_fileIO->beginWriteStream(filledSz);
|
||||||
for (size_t i=0 ; i<DISC_CAPACITY-filledSz ; ++i)
|
uint8_t fillBuf[512];
|
||||||
ws->write("\xff", 1);
|
memset(fillBuf, 0xff, 512);
|
||||||
|
for (size_t i=DISC_CAPACITY-filledSz ; i>0 ;)
|
||||||
|
{
|
||||||
|
if (i >= 512)
|
||||||
|
{
|
||||||
|
ws->write(fillBuf, 512);
|
||||||
|
i -= 512;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ws->write(fillBuf, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,57 +24,115 @@ public:
|
||||||
FileIOFILE(const SystemChar* path)
|
FileIOFILE(const SystemChar* path)
|
||||||
: m_path(path) {}
|
: m_path(path) {}
|
||||||
|
|
||||||
uint64_t size()
|
bool exists()
|
||||||
{
|
{
|
||||||
#if NOD_UCS2
|
#if _WIN32
|
||||||
FILE* fp = _wfopen(m_path.c_str(), L"rb");
|
HANDLE fp = CreateFileW(m_path.c_str(), GENERIC_READ, FILE_SHARE_READ,
|
||||||
|
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
|
if (fp == INVALID_HANDLE_VALUE)
|
||||||
|
return false;
|
||||||
|
CloseHandle(fp);
|
||||||
|
return true;
|
||||||
#else
|
#else
|
||||||
FILE* fp = fopen(m_path.c_str(), "rb");
|
FILE* fp = fopen(m_path.c_str(), "rb");
|
||||||
|
if (!fp)
|
||||||
|
return false;
|
||||||
|
fclose(fp);
|
||||||
|
return true;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t size()
|
||||||
|
{
|
||||||
|
#if _WIN32
|
||||||
|
HANDLE fp = CreateFileW(m_path.c_str(), GENERIC_READ, FILE_SHARE_READ,
|
||||||
|
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
|
if (fp == INVALID_HANDLE_VALUE)
|
||||||
|
return 0;
|
||||||
|
LARGE_INTEGER sz;
|
||||||
|
if (!GetFileSizeEx(fp, &sz))
|
||||||
|
{
|
||||||
|
CloseHandle(fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
CloseHandle(fp);
|
||||||
|
return sz.QuadPart;
|
||||||
|
#else
|
||||||
|
FILE* fp = fopen(m_path.c_str(), "rb");
|
||||||
if (!fp)
|
if (!fp)
|
||||||
return 0;
|
return 0;
|
||||||
fseeko(fp, 0, SEEK_END);
|
FSeek(fp, 0, SEEK_END);
|
||||||
uint64_t result = ftello(fp);
|
uint64_t result = ftello(fp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return result;
|
return result;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WriteStream : public IFileIO::IWriteStream
|
struct WriteStream : public IFileIO::IWriteStream
|
||||||
{
|
{
|
||||||
uint8_t buf[0x7c00];
|
uint8_t buf[0x7c00];
|
||||||
|
#if _WIN32
|
||||||
|
HANDLE fp;
|
||||||
|
#else
|
||||||
FILE* fp;
|
FILE* fp;
|
||||||
|
#endif
|
||||||
WriteStream(const SystemString& path)
|
WriteStream(const SystemString& path)
|
||||||
{
|
{
|
||||||
#if NOD_UCS2
|
#if _WIN32
|
||||||
fp = _wfopen(path.c_str(), L"wb");
|
fp = CreateFileW(path.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE,
|
||||||
|
nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
|
if (fp == INVALID_HANDLE_VALUE)
|
||||||
|
goto FailLoc;
|
||||||
#else
|
#else
|
||||||
fp = fopen(path.c_str(), "wb");
|
fp = fopen(path.c_str(), "wb");
|
||||||
#endif
|
|
||||||
if (!fp)
|
if (!fp)
|
||||||
LogModule.report(LogVisor::Error, _S("unable to open '%s' for writing"), path.c_str());
|
goto FailLoc;
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
FailLoc:
|
||||||
|
LogModule.report(LogVisor::FatalError, _S("unable to open '%s' for writing"), path.c_str());
|
||||||
}
|
}
|
||||||
WriteStream(const SystemString& path, uint64_t offset)
|
WriteStream(const SystemString& path, uint64_t offset)
|
||||||
{
|
{
|
||||||
#if NOD_UCS2
|
#if _WIN32
|
||||||
fp = _wfopen(path.c_str(), L"ab");
|
fp = CreateFileW(path.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE,
|
||||||
fclose(fp);
|
nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
fp = _wfopen(path.c_str(), L"r+b");
|
if (fp == INVALID_HANDLE_VALUE)
|
||||||
|
goto FailLoc;
|
||||||
|
LARGE_INTEGER lioffset;
|
||||||
|
lioffset.QuadPart = offset;
|
||||||
|
SetFilePointerEx(fp, lioffset, nullptr, FILE_BEGIN);
|
||||||
#else
|
#else
|
||||||
fp = fopen(path.c_str(), "ab");
|
fp = fopen(path.c_str(), "ab");
|
||||||
|
if (!fp)
|
||||||
|
goto FailLoc;
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
fp = fopen(path.c_str(), "r+b");
|
fp = fopen(path.c_str(), "r+b");
|
||||||
#endif
|
|
||||||
if (!fp)
|
if (!fp)
|
||||||
LogModule.report(LogVisor::Error, _S("unable to open '%s' for writing"), path.c_str());
|
goto FailLoc;
|
||||||
FSeek(fp, offset, SEEK_SET);
|
FSeek(fp, offset, SEEK_SET);
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
FailLoc:
|
||||||
|
LogModule.report(LogVisor::FatalError, _S("unable to open '%s' for writing"), path.c_str());
|
||||||
}
|
}
|
||||||
~WriteStream()
|
~WriteStream()
|
||||||
{
|
{
|
||||||
|
#if _WIN32
|
||||||
|
CloseHandle(fp);
|
||||||
|
#else
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
uint64_t write(const void* buf, uint64_t length)
|
uint64_t write(const void* buf, uint64_t length)
|
||||||
{
|
{
|
||||||
|
#if _WIN32
|
||||||
|
DWORD ret = 0;
|
||||||
|
WriteFile(fp, buf, length, &ret, nullptr);
|
||||||
|
return ret;
|
||||||
|
#else
|
||||||
return fwrite(buf, 1, length, fp);
|
return fwrite(buf, 1, length, fp);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
uint64_t copyFromDisc(IPartReadStream& discio, uint64_t length)
|
uint64_t copyFromDisc(IPartReadStream& discio, uint64_t length)
|
||||||
{
|
{
|
||||||
|
@ -85,12 +143,12 @@ public:
|
||||||
uint64_t readSz = discio.read(buf, thisSz);
|
uint64_t readSz = discio.read(buf, thisSz);
|
||||||
if (thisSz != readSz)
|
if (thisSz != readSz)
|
||||||
{
|
{
|
||||||
LogModule.report(LogVisor::Error, "unable to read enough from disc");
|
LogModule.report(LogVisor::FatalError, "unable to read enough from disc");
|
||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
if (fwrite(buf, 1, readSz, fp) != readSz)
|
if (write(buf, readSz) != readSz)
|
||||||
{
|
{
|
||||||
LogModule.report(LogVisor::Error, "unable to write in file");
|
LogModule.report(LogVisor::FatalError, "unable to write in file");
|
||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
length -= thisSz;
|
length -= thisSz;
|
||||||
|
@ -110,40 +168,81 @@ public:
|
||||||
|
|
||||||
struct ReadStream : public IFileIO::IReadStream
|
struct ReadStream : public IFileIO::IReadStream
|
||||||
{
|
{
|
||||||
|
#if _WIN32
|
||||||
|
HANDLE fp;
|
||||||
|
#else
|
||||||
FILE* fp;
|
FILE* fp;
|
||||||
|
#endif
|
||||||
uint8_t buf[0x7c00];
|
uint8_t buf[0x7c00];
|
||||||
ReadStream(const SystemString& path)
|
ReadStream(const SystemString& path)
|
||||||
{
|
{
|
||||||
#if NOD_UCS2
|
#if _WIN32
|
||||||
fp = _wfopen(path.c_str(), L"rb");
|
fp = CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ,
|
||||||
|
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
|
if (fp == INVALID_HANDLE_VALUE)
|
||||||
|
goto FailLoc;
|
||||||
#else
|
#else
|
||||||
fp = fopen(path.c_str(), "rb");
|
fp = fopen(path.c_str(), "rb");
|
||||||
#endif
|
|
||||||
if (!fp)
|
if (!fp)
|
||||||
LogModule.report(LogVisor::Error, _S("unable to open '%s' for reading"), path.c_str());
|
goto FailLoc;
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
FailLoc:
|
||||||
|
LogModule.report(LogVisor::FatalError, _S("unable to open '%s' for reading"), path.c_str());
|
||||||
}
|
}
|
||||||
ReadStream(const SystemString& path, uint64_t offset)
|
ReadStream(const SystemString& path, uint64_t offset)
|
||||||
: ReadStream(path)
|
: ReadStream(path)
|
||||||
{
|
{
|
||||||
|
#if _WIN32
|
||||||
|
LARGE_INTEGER lioffset;
|
||||||
|
lioffset.QuadPart = offset;
|
||||||
|
SetFilePointerEx(fp, lioffset, nullptr, FILE_BEGIN);
|
||||||
|
#else
|
||||||
FSeek(fp, offset, SEEK_SET);
|
FSeek(fp, offset, SEEK_SET);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
~ReadStream()
|
||||||
|
{
|
||||||
|
#if _WIN32
|
||||||
|
CloseHandle(fp);
|
||||||
|
#else
|
||||||
|
fclose(fp);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
void seek(int64_t offset, int whence)
|
||||||
|
{
|
||||||
|
#if _WIN32
|
||||||
|
LARGE_INTEGER li;
|
||||||
|
li.QuadPart = offset;
|
||||||
|
SetFilePointerEx(fp, li, nullptr, whence);
|
||||||
|
#else
|
||||||
|
FSeek(fp, offset, whence);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
~ReadStream() {fclose(fp);}
|
|
||||||
uint64_t read(void* buf, uint64_t length)
|
uint64_t read(void* buf, uint64_t length)
|
||||||
{return fread(buf, 1, length, fp);}
|
{
|
||||||
|
#if _WIN32
|
||||||
|
DWORD ret = 0;
|
||||||
|
ReadFile(fp, buf, length, &ret, nullptr);
|
||||||
|
return ret;
|
||||||
|
#else
|
||||||
|
return fread(buf, 1, length, fp);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
uint64_t copyToDisc(IPartWriteStream& discio, uint64_t length)
|
uint64_t copyToDisc(IPartWriteStream& discio, uint64_t length)
|
||||||
{
|
{
|
||||||
uint64_t written = 0;
|
uint64_t written = 0;
|
||||||
while (length)
|
while (length)
|
||||||
{
|
{
|
||||||
uint64_t thisSz = MIN(0x7c00, length);
|
uint64_t thisSz = MIN(0x7c00, length);
|
||||||
if (fread(buf, 1, thisSz, fp) != thisSz)
|
if (read(buf, thisSz) != thisSz)
|
||||||
{
|
{
|
||||||
LogModule.report(LogVisor::Error, "unable to read enough from file");
|
LogModule.report(LogVisor::FatalError, "unable to read enough from file");
|
||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
if (discio.write(buf, thisSz) != thisSz)
|
if (discio.write(buf, thisSz) != thisSz)
|
||||||
{
|
{
|
||||||
LogModule.report(LogVisor::Error, "unable to write enough to disc");
|
LogModule.report(LogVisor::FatalError, "unable to write enough to disc");
|
||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
length -= thisSz;
|
length -= thisSz;
|
||||||
|
|
32
lib/NOD.cpp
32
lib/NOD.cpp
|
@ -2,10 +2,6 @@
|
||||||
#include "NOD/NOD.hpp"
|
#include "NOD/NOD.hpp"
|
||||||
#include "NOD/DiscBase.hpp"
|
#include "NOD/DiscBase.hpp"
|
||||||
|
|
||||||
#if _WIN32
|
|
||||||
#define fseeko _fseeki64
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace NOD
|
namespace NOD
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -17,49 +13,41 @@ std::unique_ptr<IDiscIO> NewDiscIOWBFS(const SystemChar* path);
|
||||||
std::unique_ptr<DiscBase> OpenDiscFromImage(const SystemChar* path, bool& isWii)
|
std::unique_ptr<DiscBase> OpenDiscFromImage(const SystemChar* path, bool& isWii)
|
||||||
{
|
{
|
||||||
/* Temporary file handle to determine image type */
|
/* Temporary file handle to determine image type */
|
||||||
#if NOD_UCS2
|
std::unique_ptr<IFileIO> fio = NewFileIO(path);
|
||||||
FILE* fp = _wfopen(path, L"rb");
|
if (!fio->exists())
|
||||||
#else
|
|
||||||
FILE* fp = fopen(path, "rb");
|
|
||||||
#endif
|
|
||||||
if (!fp)
|
|
||||||
{
|
{
|
||||||
LogModule.report(LogVisor::Error, _S("Unable to open '%s'"), path);
|
LogModule.report(LogVisor::Error, _S("Unable to open '%s'"), path);
|
||||||
return std::unique_ptr<DiscBase>();
|
return std::unique_ptr<DiscBase>();
|
||||||
}
|
}
|
||||||
|
std::unique_ptr<IFileIO::IReadStream> rs = fio->beginReadStream();
|
||||||
|
|
||||||
isWii = false;
|
isWii = false;
|
||||||
std::unique_ptr<IDiscIO> discIO;
|
std::unique_ptr<IDiscIO> discIO;
|
||||||
uint32_t magic;
|
uint32_t magic = 0;
|
||||||
fread(&magic, 1, 4, fp);
|
if (rs->read(&magic, 4) != 4)
|
||||||
|
LogModule.report(LogVisor::FatalError, _S("Unable to read magic from '%s'"), path);
|
||||||
|
|
||||||
if (magic == NOD::SBig((uint32_t)'WBFS'))
|
if (magic == NOD::SBig((uint32_t)'WBFS'))
|
||||||
{
|
{
|
||||||
fclose(fp);
|
|
||||||
discIO = NewDiscIOWBFS(path);
|
discIO = NewDiscIOWBFS(path);
|
||||||
isWii = true;
|
isWii = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fseeko(fp, 0x18, SEEK_SET);
|
rs->seek(0x18, SEEK_SET);
|
||||||
fread(&magic, 1, 4, fp);
|
rs->read(&magic, 4);
|
||||||
magic = NOD::SBig(magic);
|
magic = NOD::SBig(magic);
|
||||||
if (magic == 0x5D1C9EA3)
|
if (magic == 0x5D1C9EA3)
|
||||||
{
|
{
|
||||||
fclose(fp);
|
|
||||||
discIO = NewDiscIOISO(path);
|
discIO = NewDiscIOISO(path);
|
||||||
isWii = true;
|
isWii = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fread(&magic, 1, 4, fp);
|
rs->read(&magic, 4);
|
||||||
magic = NOD::SBig(magic);
|
magic = NOD::SBig(magic);
|
||||||
if (magic == 0xC2339F3D)
|
if (magic == 0xC2339F3D)
|
||||||
{
|
|
||||||
fclose(fp);
|
|
||||||
discIO = NewDiscIOISO(path);
|
discIO = NewDiscIOISO(path);
|
||||||
}
|
|
||||||
else
|
|
||||||
fclose(fp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue