diff options
Diffstat (limited to 'engines/hugo/file.cpp')
-rw-r--r-- | engines/hugo/file.cpp | 237 |
1 files changed, 114 insertions, 123 deletions
diff --git a/engines/hugo/file.cpp b/engines/hugo/file.cpp index fa8d5b9947..c3e59b19c9 100644 --- a/engines/hugo/file.cpp +++ b/engines/hugo/file.cpp @@ -39,17 +39,20 @@ #include "hugo/schedule.h" #include "hugo/display.h" #include "hugo/util.h" +#include "hugo/object.h" namespace Hugo { -FileManager::FileManager(HugoEngine &vm) : _vm(vm) { +FileManager::FileManager(HugoEngine *vm) : _vm(vm) { } FileManager::~FileManager() { } +/** +* Convert 4 planes (RGBI) data to 8-bit DIB format +* Return original plane data ptr +*/ byte *FileManager::convertPCC(byte *p, uint16 y, uint16 bpl, image_pt dataPtr) { -// Convert 4 planes (RGBI) data to 8-bit DIB format -// Return original plane data ptr debugC(2, kDebugFile, "convertPCC(byte *p, %d, %d, image_pt data_p)", y, bpl); dataPtr += y * bpl * 8; // Point to correct DIB line @@ -64,10 +67,12 @@ byte *FileManager::convertPCC(byte *p, uint16 y, uint16 bpl, image_pt dataPtr) { return p; } +/** +* Read a pcx file of length len. Use supplied seq_p and image_p or +* allocate space if NULL. Name used for errors. Returns address of seq_p +* Set first TRUE to initialize b_index (i.e. not reading a sequential image in file). +*/ seq_t *FileManager::readPCX(Common::File &f, seq_t *seqPtr, byte *imagePtr, bool firstFl, const char *name) { -// Read a pcx file of length len. Use supplied seq_p and image_p or -// allocate space if NULL. Name used for errors. Returns address of seq_p -// Set first TRUE to initialize b_index (i.e. not reading a sequential image in file). debugC(1, kDebugFile, "readPCX(..., %s)", name); // Read in the PCC header and check consistency @@ -96,7 +101,7 @@ seq_t *FileManager::readPCX(Common::File &f, seq_t *seqPtr, byte *imagePtr, bool if ((seqPtr = (seq_t *)malloc(sizeof(seq_t))) == 0) Utils::Error(HEAP_ERR, "%s", name); } - + // Find size of image data in 8-bit DIB format // Note save of x2 - marks end of valid data before garbage uint16 bytesPerLine4 = PCC_header.bytesPerLine * 4; // 4-bit bpl @@ -136,14 +141,16 @@ seq_t *FileManager::readPCX(Common::File &f, seq_t *seqPtr, byte *imagePtr, bool return seqPtr; } +/** +* Read object file of PCC images into object supplied +*/ void FileManager::readImage(int objNum, object_t *objPtr) { -// Read object file of PCC images into object supplied debugC(1, kDebugFile, "readImage(%d, object_t *objPtr)", objNum); if (!objPtr->seqNumb) // This object has no images return; - if (_vm.isPacked()) { + if (_vm->isPacked()) { _objectsArchive.seek((uint32)objNum * sizeof(objBlock_t), SEEK_SET); objBlock_t objBlock; // Info on file within database @@ -153,10 +160,10 @@ void FileManager::readImage(int objNum, object_t *objPtr) { _objectsArchive.seek(objBlock.objOffset, SEEK_SET); } else { char *buf = (char *) malloc(2048 + 1); // Buffer for file access - strcat(strcat(strcpy(buf, _vm._picDir), _vm._arrayNouns[objPtr->nounIndex][0]), OBJEXT); + strcat(strcat(strcpy(buf, _vm->_picDir), _vm->_arrayNouns[objPtr->nounIndex][0]), OBJEXT); if (!_objectsArchive.open(buf)) { - warning("File %s not found, trying again with %s%s", buf, _vm._arrayNouns[objPtr->nounIndex][0], OBJEXT); - strcat(strcpy(buf, _vm._arrayNouns[objPtr->nounIndex][0]), OBJEXT); + warning("File %s not found, trying again with %s%s", buf, _vm->_arrayNouns[objPtr->nounIndex][0], OBJEXT); + strcat(strcpy(buf, _vm->_arrayNouns[objPtr->nounIndex][0]), OBJEXT); if (!_objectsArchive.open(buf)) Utils::Error(FILE_ERR, "%s", buf); } @@ -170,12 +177,12 @@ void FileManager::readImage(int objNum, object_t *objPtr) { for (int k = 0; k < objPtr->seqList[j].imageNbr; k++) { // each image if (k == 0) { // First image // Read this image - allocate both seq and image memory - seqPtr = readPCX(_objectsArchive, 0, 0, firstFl, _vm._arrayNouns[objPtr->nounIndex][0]); + seqPtr = readPCX(_objectsArchive, 0, 0, firstFl, _vm->_arrayNouns[objPtr->nounIndex][0]); objPtr->seqList[j].seqPtr = seqPtr; firstFl = false; } else { // Subsequent image // Read this image - allocate both seq and image memory - seqPtr->nextSeqPtr = readPCX(_objectsArchive, 0, 0, firstFl, _vm._arrayNouns[objPtr->nounIndex][0]); + seqPtr->nextSeqPtr = readPCX(_objectsArchive, 0, 0, firstFl, _vm->_arrayNouns[objPtr->nounIndex][0]); seqPtr = seqPtr->nextSeqPtr; } @@ -203,6 +210,7 @@ void FileManager::readImage(int objNum, object_t *objPtr) { } } } + assert(seqPtr); seqPtr->nextSeqPtr = objPtr->seqList[j].seqPtr; // loop linked list to head } @@ -221,17 +229,19 @@ void FileManager::readImage(int objNum, object_t *objPtr) { warning("Unexpected cycling: %d", objPtr->cycling); } - if (!_vm.isPacked()) + if (!_vm->isPacked()) _objectsArchive.close(); } +/** +* Read sound (or music) file data. Call with SILENCE to free-up +* any allocated memory. Also returns size of data +*/ sound_pt FileManager::getSound(int16 sound, uint16 *size) { -// Read sound (or music) file data. Call with SILENCE to free-up -// any allocated memory. Also returns size of data debugC(1, kDebugFile, "getSound(%d, %d)", sound, *size); // No more to do if SILENCE (called for cleanup purposes) - if (sound == _vm._soundSilence) + if (sound == _vm->_soundSilence) return 0; // Open sounds file @@ -258,7 +268,7 @@ sound_pt FileManager::getSound(int16 sound, uint16 *size) { // Allocate memory for sound or music, if possible sound_pt soundPtr = (byte *)malloc(s_hdr[sound].size); // Ptr to sound data if (soundPtr == 0) { - Utils::Warn("%s", "Low on memory"); + warning("Low on memory"); return 0; } @@ -272,8 +282,10 @@ sound_pt FileManager::getSound(int16 sound, uint16 *size) { return soundPtr; } +/** +* Return whether file exists or not +*/ bool FileManager::fileExists(char *filename) { -// Return whether file exists or not Common::File f; if (f.open(filename)) { f.close(); @@ -282,48 +294,21 @@ bool FileManager::fileExists(char *filename) { return false; } -void FileManager::saveSeq(object_t *obj) { -// Save sequence number and image number in given object - debugC(1, kDebugFile, "saveSeq"); - - bool found = false; - for (int j = 0; !found && (j < obj->seqNumb); j++) { - seq_t *q = obj->seqList[j].seqPtr; - for (int k = 0; !found && (k < obj->seqList[j].imageNbr); k++) { - if (obj->currImagePtr == q) { - found = true; - obj->curSeqNum = j; - obj->curImageNum = k; - } else { - q = q->nextSeqPtr; - } - } - } -} - -void FileManager::restoreSeq(object_t *obj) { -// Set up cur_seq_p from stored sequence and image number in object - debugC(1, kDebugFile, "restoreSeq"); - - seq_t *q = obj->seqList[obj->curSeqNum].seqPtr; - for (int j = 0; j < obj->curImageNum; j++) - q = q->nextSeqPtr; - obj->currImagePtr = q; -} - +/** +* Save game to supplied slot (-1 is INITFILE) +*/ void FileManager::saveGame(int16 slot, const char *descrip) { -// Save game to supplied slot (-1 is INITFILE) debugC(1, kDebugFile, "saveGame(%d, %s)", slot, descrip); // Get full path of saved game file - note test for INITFILE Common::String path; // Full path of saved game if (slot == -1) - path = _vm._initFilename; + path = _vm->_initFilename; else - path = Common::String::printf(_vm._saveFilename.c_str(), slot); + path = Common::String::format(_vm->_saveFilename.c_str(), slot); - Common::WriteStream *out = _vm.getSaveFileManager()->openForSaving(path); + Common::WriteStream *out = _vm->getSaveFileManager()->openForSaving(path); if (!out) { warning("Can't create file '%s', game not saved", path.c_str()); return; @@ -336,19 +321,19 @@ void FileManager::saveGame(int16 slot, const char *descrip) { out->write(descrip, DESCRIPLEN); // Save objects - for (int i = 0; i < _vm._numObj; i++) { + for (int i = 0; i < _vm->_numObj; i++) { // Save where curr_seq_p is pointing to - saveSeq(&_vm._objects[i]); - out->write(&_vm._objects[i], sizeof(object_t)); + _vm->_object->saveSeq(&_vm->_object->_objects[i]); + out->write(&_vm->_object->_objects[i], sizeof(object_t)); } - const status_t &gameStatus = _vm.getGameStatus(); + const status_t &gameStatus = _vm->getGameStatus(); // Save whether hero image is swapped - out->write(&_vm._heroImage, sizeof(_vm._heroImage)); + out->write(&_vm->_heroImage, sizeof(_vm->_heroImage)); // Save score - int score = _vm.getScore(); + int score = _vm->getScore(); out->write(&score, sizeof(score)); // Save story mode @@ -361,16 +346,16 @@ void FileManager::saveGame(int16 slot, const char *descrip) { out->write(&gameStatus.gameOverFl, sizeof(gameStatus.gameOverFl)); // Save screen states - out->write(_vm._screenStates, sizeof(*_vm._screenStates) * _vm._numScreens); + out->write(_vm->_screenStates, sizeof(*_vm->_screenStates) * _vm->_numScreens); // Save points table - out->write(_vm._points, sizeof(point_t) * _vm._numBonuses); + out->write(_vm->_points, sizeof(point_t) * _vm->_numBonuses); // Now save current time and all current events in event queue - _vm.scheduler().saveEvents(out); + _vm->_scheduler->saveEvents(out); // Save palette table - _vm.screen().savePal(out); + _vm->_screen->savePal(out); // Save maze status out->write(&_maze, sizeof(maze_t)); @@ -380,22 +365,24 @@ void FileManager::saveGame(int16 slot, const char *descrip) { delete out; } +/** +* Restore game from supplied slot number (-1 is INITFILE) +*/ void FileManager::restoreGame(int16 slot) { -// Restore game from supplied slot number (-1 is INITFILE) debugC(1, kDebugFile, "restoreGame(%d)", slot); // Initialize new-game status - _vm.initStatus(); + _vm->initStatus(); // Get full path of saved game file - note test for INITFILE Common::String path; // Full path of saved game if (slot == -1) - path = _vm._initFilename; + path = _vm->_initFilename; else - path = Common::String::printf(_vm._saveFilename.c_str(), slot); + path = Common::String::format(_vm->_saveFilename.c_str(), slot); - Common::SeekableReadStream *in = _vm.getSaveFileManager()->openForLoading(path); + Common::SeekableReadStream *in = _vm->getSaveFileManager()->openForLoading(path); if (!in) return; @@ -411,13 +398,13 @@ void FileManager::restoreGame(int16 slot) { in->seek(DESCRIPLEN, SEEK_CUR); // If hero image is currently swapped, swap it back before restore - if (_vm._heroImage != HERO) - _vm.scheduler().swapImages(HERO, _vm._heroImage); + if (_vm->_heroImage != HERO) + _vm->_object->swapImages(HERO, _vm->_heroImage); // Restore objects, retain current seqList which points to dynamic mem // Also, retain cmnd_t pointers - for (int i = 0; i < _vm._numObj; i++) { - object_t *p = &_vm._objects[i]; + for (int i = 0; i < _vm->_numObj; i++) { + object_t *p = &_vm->_object->_objects[i]; seqList_t seqList[MAX_SEQUENCES]; memcpy(seqList, p->seqList, sizeof(seqList_t)); uint16 cmdIndex = p->cmdIndex; @@ -426,37 +413,37 @@ void FileManager::restoreGame(int16 slot) { memcpy(p->seqList, seqList, sizeof(seqList_t)); } - in->read(&_vm._heroImage, sizeof(_vm._heroImage)); + in->read(&_vm->_heroImage, sizeof(_vm->_heroImage)); // If hero swapped in saved game, swap it - int heroImg = _vm._heroImage; + int heroImg = _vm->_heroImage; if (heroImg != HERO) - _vm.scheduler().swapImages(HERO, _vm._heroImage); - _vm._heroImage = heroImg; + _vm->_object->swapImages(HERO, _vm->_heroImage); + _vm->_heroImage = heroImg; - status_t &gameStatus = _vm.getGameStatus(); + status_t &gameStatus = _vm->getGameStatus(); int score; in->read(&score, sizeof(score)); - _vm.setScore(score); + _vm->setScore(score); in->read(&gameStatus.storyModeFl, sizeof(gameStatus.storyModeFl)); in->read(&gameStatus.jumpExitFl, sizeof(gameStatus.jumpExitFl)); in->read(&gameStatus.gameOverFl, sizeof(gameStatus.gameOverFl)); - in->read(_vm._screenStates, sizeof(*_vm._screenStates) * _vm._numScreens); + in->read(_vm->_screenStates, sizeof(*_vm->_screenStates) * _vm->_numScreens); // Restore points table - in->read(_vm._points, sizeof(point_t) * _vm._numBonuses); + in->read(_vm->_points, sizeof(point_t) * _vm->_numBonuses); // Restore ptrs to currently loaded objects - for (int i = 0; i < _vm._numObj; i++) - restoreSeq(&_vm._objects[i]); + for (int i = 0; i < _vm->_numObj; i++) + _vm->_object->restoreSeq(&_vm->_object->_objects[i]); // Now restore time of the save and the event queue - _vm.scheduler().restoreEvents(in); + _vm->_scheduler->restoreEvents(in); // Restore palette and change it if necessary - _vm.screen().restorePal(in); + _vm->_screen->restorePal(in); // Restore maze status in->read(&_maze, sizeof(maze_t)); @@ -464,62 +451,50 @@ void FileManager::restoreGame(int16 slot) { delete in; } +/** +* Initialize the size of a saved game (from the fixed initial game). +* If status.initsave is TRUE, or the initial saved game is not found, +* force a save to create one. Normally the game will be shipped with +* the initial game file but useful to force a write during development +* when the size is changeable. +* The net result is a valid INITFILE, with status.savesize initialized. +*/ void FileManager::initSavedGame() { -// Initialize the size of a saved game (from the fixed initial game). -// If status.initsave is TRUE, or the initial saved game is not found, -// force a save to create one. Normally the game will be shipped with -// the initial game file but useful to force a write during development -// when the size is changeable. -// The net result is a valid INITFILE, with status.savesize initialized. debugC(1, kDebugFile, "initSavedGame"); // Force save of initial game - if (_vm.getGameStatus().initSaveFl) + if (_vm->getGameStatus().initSaveFl) saveGame(-1, ""); // If initial game doesn't exist, create it - Common::SeekableReadStream *in = _vm.getSaveFileManager()->openForLoading(_vm._initFilename); + Common::SeekableReadStream *in = _vm->getSaveFileManager()->openForLoading(_vm->_initFilename); if (!in) { saveGame(-1, ""); - in = _vm.getSaveFileManager()->openForLoading(_vm._initFilename); + in = _vm->getSaveFileManager()->openForLoading(_vm->_initFilename); if (!in) { - Utils::Error(WRITE_ERR, "%s", _vm._initFilename.c_str()); + Utils::Error(WRITE_ERR, "%s", _vm->_initFilename.c_str()); return; } } // Must have an open saved game now - _vm.getGameStatus().saveSize = in->size(); + _vm->getGameStatus().saveSize = in->size(); delete in; // Check sanity - maybe disk full or path set to read-only drive? - if (_vm.getGameStatus().saveSize == -1) - Utils::Error(WRITE_ERR, "%s", _vm._initFilename.c_str()); -} - -void FileManager::openPlaybackFile(bool playbackFl, bool recordFl) { - debugC(1, kDebugFile, "openPlaybackFile(%d, %d)", (playbackFl) ? 1 : 0, (recordFl) ? 1 : 0); - - if (playbackFl) { - if (!(fpb = fopen(PBFILE, "r+b"))) - Utils::Error(FILE_ERR, "%s", PBFILE); - } else if (recordFl) { - fpb = fopen(PBFILE, "wb"); - } - pbdata.time = 0; // Say no key available -} - -void FileManager::closePlaybackFile() { - fclose(fpb); + if (_vm->getGameStatus().saveSize == -1) + Utils::Error(WRITE_ERR, "%s", _vm->_initFilename.c_str()); } +/** +* Read the encrypted text from the boot file and print it +*/ void FileManager::printBootText() { -// Read the encrypted text from the boot file and print it debugC(1, kDebugFile, "printBootText"); Common::File ofp; if (!ofp.open(BOOTFILE)) { - if (_vm._gameVariant == 3) { + if (_vm->_gameVariant == 3) { //TODO initialize properly _boot structure warning("printBootText - Skipping as H1 Dos may be a freeware"); return; @@ -551,14 +526,16 @@ void FileManager::printBootText() { ofp.close(); } +/** +* Reads boot file for program environment. Fatal error if not there or +* file checksum is bad. De-crypts structure while checking checksum +*/ void FileManager::readBootFile() { -// Reads boot file for program environment. Fatal error if not there or -// file checksum is bad. De-crypts structure while checking checksum debugC(1, kDebugFile, "readBootFile"); Common::File ofp; if (!ofp.open(BOOTFILE)) { - if (_vm._gameVariant == 3) { + if (_vm->_gameVariant == 3) { //TODO initialize properly _boot structure warning("readBootFile - Skipping as H1 Dos may be a freeware"); return; @@ -589,8 +566,10 @@ void FileManager::readBootFile() { Utils::Error(GEN_ERR, "%s", "Program startup file invalid"); } +/** +* Returns address of uif_hdr[id], reading it in if first call +*/ uif_hdr_t *FileManager::getUIFHeader(uif_t id) { -// Returns address of uif_hdr[id], reading it in if first call debugC(1, kDebugFile, "getUIFHeader(%d)", id); static bool firstFl = true; @@ -617,8 +596,10 @@ uif_hdr_t *FileManager::getUIFHeader(uif_t id) { return &UIFHeader[id]; } +/** +* Read uif item into supplied buffer. +*/ void FileManager::readUIFItem(int16 id, byte *buf) { -// Read uif item into supplied buffer. debugC(1, kDebugFile, "readUIFItem(%d, ...)", id); // Open uif file to read data @@ -645,10 +626,11 @@ void FileManager::readUIFItem(int16 id, byte *buf) { ip.close(); } +/** +* Simple instructions given when F1 pressed twice in a row +* Only in DOS versions +*/ void FileManager::instructions() { -// Simple instructions given when F1 pressed twice in a row -// Only in DOS versions - Common::File f; if (!f.open(HELPFILE)) { warning("help.dat not found"); @@ -672,5 +654,14 @@ void FileManager::instructions() { f.close(); } +/** +* Read the uif image file (inventory icons) +*/ +void FileManager::readUIFImages() { + debugC(1, kDebugFile, "readUIFImages"); + + readUIFItem(UIF_IMAGES, _vm->_screen->getGUIBuffer()); // Read all uif images +} + } // End of namespace Hugo |