/* Only implemented to the extent necessary to match data sections. */ #include "nw4r/snd/snd_DvdSoundArchive.h" #include "nw4r/ut/ut_DvdLockedFileStream.h" #include #include namespace nw4r { namespace snd { class DvdSoundArchive::DvdFileStream : public ut::DvdLockedFileStream { public: DvdFileStream(const DVDFileInfo* pFileInfo, u32 offset, u32 size); DvdFileStream(s32 entrynum, u32 offset, u32 size); virtual s32 Read(void* pDst, u32 size); // at 0x14 virtual void Seek(s32 offset, u32 origin); // at 0x44 virtual u32 Tell() const { return ut::DvdFileStream::Tell() - mOffset; } // at 0x58 virtual u32 GetSize() const { return mSize; } // at 0x40 private: s32 mOffset; // at 0x70 s32 mSize; // at 0x74 }; DvdSoundArchive::DvdSoundArchive() : mOpen(false) {} DvdSoundArchive::~DvdSoundArchive() { Close(); } bool DvdSoundArchive::Open(s32 entrynum) { if (!DVDFastOpen(entrynum, &mFileInfo)) { return false; } mOpen = true; return LoadFileHeader(); } bool DvdSoundArchive::Open(const char* pPath) { s32 entrynum = DVDConvertPathToEntrynum(pPath); if (entrynum < 0) { return false; } if (!Open(entrynum)) { return false; } char extRoot[FILE_PATH_MAX]; for (int i = std::strlen(pPath) - 1; i >= 0; i--) { if ((pPath[i] == '/' || pPath[i] == '\\')) { if (i >= FILE_PATH_MAX + 1) { return false; } std::strncpy(extRoot, pPath, i); extRoot[i] = '\0'; SetExternalFileRoot(extRoot); break; } } return true; } void DvdSoundArchive::Close() { if (mOpen) { DVDClose(&mFileInfo); mOpen = false; } Shutdown(); } ut::FileStream* DvdSoundArchive::OpenStream(void* pBuffer, int size, u32 offset, u32 length) const { if (!mOpen) { return NULL; } if (size < sizeof(DvdFileStream)) { return NULL; } return new (pBuffer) DvdFileStream(&mFileInfo, offset, length); } ut::FileStream* DvdSoundArchive::OpenExtStream(void* pBuffer, int size, const char* pExtPath, u32 offset, u32 length) const { if (!mOpen) { return NULL; } if (size < sizeof(DvdFileStream)) { return NULL; } s32 entrynum = DVDConvertPathToEntrynum(pExtPath); if (entrynum < 0) { return NULL; } return new (pBuffer) DvdFileStream(entrynum, offset, length); } int DvdSoundArchive::detail_GetRequiredStreamBufferSize() const { return sizeof(DvdFileStream); } bool DvdSoundArchive::LoadFileHeader() { u8 headerArea[detail::SoundArchiveFile::HEADER_AREA_SIZE]; static const u32 headerAlignSize = ROUND_UP(sizeof(detail::SoundArchiveFile::Header), 32); void* pFile = ut::RoundUp(headerArea, 32); s32 bytesRead = DVDReadPrio(&mFileInfo, pFile, headerAlignSize, 0, DVD_PRIO_MEDIUM); if (bytesRead != headerAlignSize) { return false; } mFileReader.Init(pFile); Setup(&mFileReader); return true; } bool DvdSoundArchive::LoadHeader(void* pBuffer, u32 size) { u32 infoSize = mFileReader.GetInfoChunkSize(); s32 infoOffset = mFileReader.GetInfoChunkOffset(); if (size < infoSize) { return false; } s32 bytesRead = DVDReadPrio(&mFileInfo, pBuffer, infoSize, infoOffset, DVD_PRIO_MEDIUM); if (bytesRead != infoSize) { return false; } mFileReader.SetInfoChunk(pBuffer, infoSize); return true; } bool DvdSoundArchive::LoadLabelStringData(void* pBuffer, u32 size) { u32 labelSize = mFileReader.GetLabelStringChunkSize(); s32 labelOffset = mFileReader.GetLabelStringChunkOffset(); if (size < labelSize) { return false; } s32 bytesRead = DVDReadPrio(&mFileInfo, pBuffer, labelSize, labelOffset, DVD_PRIO_MEDIUM); if (bytesRead != labelSize) { return false; } mFileReader.SetStringChunk(pBuffer, labelSize); return true; } DvdSoundArchive::DvdFileStream::DvdFileStream(const DVDFileInfo* pFileInfo, u32 offset, u32 size) : DvdLockedFileStream(pFileInfo, false), mOffset(offset), mSize(size) { ut::DvdFileStream::Seek(mOffset, SEEKORG_BEG); } DvdSoundArchive::DvdFileStream::DvdFileStream(s32 entrynum, u32 offset, u32 size) : DvdLockedFileStream(entrynum), mOffset(offset), mSize(size) { ut::DvdFileStream::Seek(mOffset, SEEKORG_BEG); } s32 DvdSoundArchive::DvdFileStream::Read(void* pDst, u32 size) { u32 endOffset = mOffset + mSize; u32 startOffset = ut::DvdFileStream::Tell(); if (startOffset + size > endOffset) { size = ut::RoundUp(endOffset - ut::DvdFileStream::Tell(), 32); } return DvdLockedFileStream::Read(pDst, size); } void DvdSoundArchive::DvdFileStream::Seek(s32 offset, u32 origin) { switch (origin) { case SEEKORG_BEG: { offset += mOffset; break; } case SEEKORG_CUR: { offset += ut::DvdFileStream::Tell(); break; } case SEEKORG_END: { offset = mOffset + mSize - offset; break; } default: { return; } } if (offset < mOffset) { offset = mOffset; } else if (offset > mOffset + mSize) { offset = mOffset + mSize; } ut::DvdFileStream::Seek(offset, SEEKORG_BEG); } }}