aboutsummaryrefslogtreecommitdiff
path: root/engines/parallaction/disk.cpp
diff options
context:
space:
mode:
authorNicola Mettifogo2007-07-26 20:22:51 +0000
committerNicola Mettifogo2007-07-26 20:22:51 +0000
commit2b219db314319484b6eaf34d3bdac09e81e6acbe (patch)
treea5e43ab3da970d42c6012d195044d83e8eced954 /engines/parallaction/disk.cpp
parentf89e907998d1dd2a1ab4e73b0fdf457d70878ee3 (diff)
downloadscummvm-rg350-2b219db314319484b6eaf34d3bdac09e81e6acbe.tar.gz
scummvm-rg350-2b219db314319484b6eaf34d3bdac09e81e6acbe.tar.bz2
scummvm-rg350-2b219db314319484b6eaf34d3bdac09e81e6acbe.zip
Merged archive.cpp into disk.cpp.
svn-id: r28221
Diffstat (limited to 'engines/parallaction/disk.cpp')
-rw-r--r--engines/parallaction/disk.cpp175
1 files changed, 175 insertions, 0 deletions
diff --git a/engines/parallaction/disk.cpp b/engines/parallaction/disk.cpp
index 4070f41e1c..c972827dc6 100644
--- a/engines/parallaction/disk.cpp
+++ b/engines/parallaction/disk.cpp
@@ -37,6 +37,181 @@ namespace Audio {
namespace Parallaction {
+
+// HACK: Several archives ('de', 'en', 'fr' and 'disk0') in the multi-lingual
+// Amiga version of Nippon Safes, and one archive ('fr') in the Amiga Demo of
+// Nippon Safes used different internal offsets than all the other archives.
+//
+// When an archive is opened in the Amiga demo, its size is checked against
+// SIZEOF_SMALL_ARCHIVE to detect when the smaller archive is used.
+//
+// When an archive is opened in Amiga multi-lingual version, the header is
+// checked again NDOS to detect when a smaller archive is used.
+//
+#define SIZEOF_SMALL_ARCHIVE 12778
+
+#define ARCHIVE_FILENAMES_OFS 0x16
+
+#define NORMAL_ARCHIVE_FILES_NUM 384
+#define SMALL_ARCHIVE_FILES_NUM 180
+
+#define NORMAL_ARCHIVE_SIZES_OFS 0x3016
+#define SMALL_ARCHIVE_SIZES_OFS 0x1696
+
+#define NORMAL_ARCHIVE_DATA_OFS 0x4000
+#define SMALL_ARCHIVE_DATA_OFS 0x1966
+
+Archive::Archive() {
+ resetArchivedFile();
+}
+
+void Archive::open(const char *file) {
+ debugC(1, kDebugDisk, "Archive::open(%s)", file);
+
+ if (_archive.isOpen())
+ close();
+
+ char path[PATH_LEN];
+
+ strcpy(path, file);
+ if (!_archive.open(path))
+ error("archive '%s' not found", path);
+
+ _archiveName = file;
+
+ bool isSmallArchive = false;
+ if (_vm->getPlatform() == Common::kPlatformAmiga) {
+ if (_vm->getFeatures() & GF_DEMO) {
+ isSmallArchive = _archive.size() == SIZEOF_SMALL_ARCHIVE;
+ } else if (_vm->getFeatures() & GF_LANG_MULT) {
+ isSmallArchive = (_archive.readUint32BE() != MKID_BE('NDOS'));
+ }
+ }
+
+ _numFiles = (isSmallArchive) ? SMALL_ARCHIVE_FILES_NUM : NORMAL_ARCHIVE_FILES_NUM;
+
+ _archive.seek(ARCHIVE_FILENAMES_OFS);
+ _archive.read(_archiveDir, _numFiles*32);
+
+ _archive.seek((isSmallArchive) ? SMALL_ARCHIVE_SIZES_OFS : NORMAL_ARCHIVE_SIZES_OFS);
+
+ uint32 dataOffset = (isSmallArchive) ? SMALL_ARCHIVE_DATA_OFS : NORMAL_ARCHIVE_DATA_OFS;
+ for (uint16 i = 0; i < _numFiles; i++) {
+ _archiveOffsets[i] = dataOffset;
+ _archiveLenghts[i] = _archive.readUint32BE();
+ dataOffset += _archiveLenghts[i];
+ }
+
+ return;
+}
+
+
+void Archive::close() {
+ if (!_archive.isOpen()) return;
+
+ resetArchivedFile();
+
+ _archive.close();
+ _archiveName.clear();
+}
+
+Common::String Archive::name() const {
+ return _archiveName;
+}
+
+bool Archive::openArchivedFile(const char *filename) {
+ debugC(3, kDebugDisk, "Archive::openArchivedFile(%s)", filename);
+
+ resetArchivedFile();
+
+ debugC(3, kDebugDisk, "Archive::openArchivedFile(%s)", filename);
+
+ if (!_archive.isOpen())
+ error("Archive::openArchivedFile: the archive is not open");
+
+ uint16 i = 0;
+ for ( ; i < _numFiles; i++) {
+ if (!scumm_stricmp(_archiveDir[i], filename)) break;
+ }
+ if (i == _numFiles) return false;
+
+ debugC(9, kDebugDisk, "Archive::openArchivedFile: '%s' found in slot %i", filename, i);
+
+ _file = true;
+
+ _fileOffset = _archiveOffsets[i];
+ _fileCursor = _archiveOffsets[i];
+ _fileEndOffset = _archiveOffsets[i] + _archiveLenghts[i];
+
+ _archive.seek(_fileOffset);
+
+ return true;
+}
+
+void Archive::resetArchivedFile() {
+ _file = false;
+ _fileCursor = 0;
+ _fileOffset = 0;
+ _fileEndOffset = 0;
+}
+
+void Archive::closeArchivedFile() {
+ resetArchivedFile();
+}
+
+
+uint32 Archive::size() const {
+ return (_file == true ? _fileEndOffset - _fileOffset : 0);
+}
+
+uint32 Archive::pos() const {
+ return (_file == true ? _fileCursor - _fileOffset : 0 );
+}
+
+bool Archive::eos() const {
+ return (_file == true ? _fileCursor == _fileEndOffset : true );
+}
+
+void Archive::seek(int32 offs, int whence) {
+ assert(_file == true && _fileCursor <= _fileEndOffset);
+
+ switch (whence) {
+ case SEEK_CUR:
+ _fileCursor += offs;
+ break;
+ case SEEK_SET:
+ _fileCursor = _fileOffset + offs;
+ break;
+ case SEEK_END:
+ _fileCursor = _fileEndOffset - offs;
+ break;
+ }
+ assert(_fileCursor <= _fileEndOffset && _fileCursor >= _fileOffset);
+
+ _archive.seek(_fileCursor, SEEK_SET);
+}
+
+uint32 Archive::read(void *dataPtr, uint32 dataSize) {
+// printf("read(%i, %i)\n", file->_cursor, file->_endOffset);
+ if (_file == false)
+ error("Archive::read: no archived file is currently open");
+
+ if (_fileCursor >= _fileEndOffset)
+ error("can't read beyond end of archived file");
+
+ if (_fileEndOffset - _fileCursor < dataSize)
+ dataSize = _fileEndOffset - _fileCursor;
+
+ int32 readBytes = _archive.read(dataPtr, dataSize);
+ _fileCursor += readBytes;
+
+ return readBytes;
+}
+
+
+
+
+
/*
This stream class is just a wrapper around Archive, so
deallocation is not a problem. In fact, this class doesn't