diff options
author | Benjamin Haisch | 2008-04-30 20:36:19 +0000 |
---|---|---|
committer | Benjamin Haisch | 2008-04-30 20:36:19 +0000 |
commit | 7509d66caf516d87f938f66a20f4ce81367a8305 (patch) | |
tree | 3ce463b2c13d8d0c1ad5259279f49e3e4f10a300 | |
parent | e866aefdfdf7386cd3f5c94a058dd329c44b8fde (diff) | |
download | scummvm-rg350-7509d66caf516d87f938f66a20f4ce81367a8305.tar.gz scummvm-rg350-7509d66caf516d87f938f66a20f4ce81367a8305.tar.bz2 scummvm-rg350-7509d66caf516d87f938f66a20f4ce81367a8305.zip |
Implemented savegame loading/saving and sprite clipping
Fixed bug in Screen::printTextEx
Implemented opcodes:
- o1_DRAWTEXT
- o1_DRAWMENU
- o1_MENUCOUNT
- o1_SAVEGAME
- o1_LOADGAME
- o1_GAMENAME
svn-id: r31794
-rw-r--r-- | engines/made/database.cpp | 84 | ||||
-rw-r--r-- | engines/made/database.h | 5 | ||||
-rw-r--r-- | engines/made/screen.cpp | 47 | ||||
-rw-r--r-- | engines/made/scriptfuncs.cpp | 91 |
4 files changed, 189 insertions, 38 deletions
diff --git a/engines/made/database.cpp b/engines/made/database.cpp index 7c6afda197..d5c45fa1b9 100644 --- a/engines/made/database.cpp +++ b/engines/made/database.cpp @@ -23,8 +23,10 @@ * */ +#include "common/system.h" #include "common/endian.h" #include "common/util.h" +#include "common/savefile.h" #include "made/database.h" @@ -222,8 +224,7 @@ void GameDatabase::load(Common::SeekableReadStream &sourceS) { uint32 objectsSize = sourceS.readUint32LE(); _mainCodeObjectIndex = sourceS.readUint16LE(); - debug(2, "objectIndexOffs = %08X; objectCount = %d; gameStateOffs = %08X; gameStateSize = %d; objectsOffs = %08X; objectsSize = %d\n", - objectIndexOffs, objectCount, gameStateOffs, _gameStateSize, objectsOffs, objectsSize); + //debug(2, "objectIndexOffs = %08X; objectCount = %d; gameStateOffs = %08X; gameStateSize = %d; objectsOffs = %08X; objectsSize = %d\n", objectIndexOffs, objectCount, gameStateOffs, _gameStateSize, objectsOffs, objectsSize); _gameState = new byte[_gameStateSize]; sourceS.seek(gameStateOffs); @@ -241,14 +242,14 @@ void GameDatabase::load(Common::SeekableReadStream &sourceS) { // Constant objects are loaded from disk, while variable objects exist // in the _gameState buffer. - debug(2, "obj(%04X) ofs = %08X\n", i, objectOffsets[i]); + //debug(2, "obj(%04X) ofs = %08X\n", i, objectOffsets[i]); if (objectOffsets[i] & 1) { - debug(2, "-> const %08X\n", objectsOffs + objectOffsets[i] - 1); + //debug(2, "-> const %08X\n", objectsOffs + objectOffsets[i] - 1); sourceS.seek(objectsOffs + objectOffsets[i] - 1); obj->load(sourceS); } else { - debug(2, "-> var\n"); + //debug(2, "-> var\n"); obj->load(_gameState + objectOffsets[i]); } _objects.push_back(obj); @@ -256,6 +257,79 @@ void GameDatabase::load(Common::SeekableReadStream &sourceS) { } +bool GameDatabase::getSavegameDescription(const char *filename, Common::String &description) { + + Common::InSaveFile *in; + + if (!(in = g_system->getSavefileManager()->openForLoading(filename))) { + return false; + } + + char desc[64]; + + in->skip(4); // TODO: Verify marker 'SGAM' + in->skip(4); // TODO: Verify size + in->skip(2); // TODO: Verify version + in->read(desc, 64); + description = desc; + + printf("description = %s\n", description.c_str()); fflush(stdout); + + delete in; + + return true; + +} + +int16 GameDatabase::savegame(const char *filename, const char *description, int16 version) { + + Common::OutSaveFile *out; + + if (!(out = g_system->getSavefileManager()->openForSaving(filename))) { + warning("Can't create file '%s', game not saved", filename); + return 6; + } + + uint32 size = 4 + 4 + 2 + _gameStateSize; + char desc[64]; + + strncpy(desc, description, 64); + + out->writeUint32BE(MKID_BE('SGAM')); + out->writeUint32LE(size); + out->writeUint16LE(version); + out->write(desc, 64); + out->write(_gameState, _gameStateSize); + + delete out; + + return 0; + +} + +int16 GameDatabase::loadgame(const char *filename, int16 version) { + + Common::InSaveFile *in; + + if (!(in = g_system->getSavefileManager()->openForLoading(filename))) { + warning("Can't open file '%s', game not loaded", filename); + return 1; + } + + //uint32 expectedSize = 4 + 4 + 2 + _gameStateSize; + + in->skip(4); // TODO: Verify marker 'SGAM' + in->skip(4); // TODO: Verify size + in->skip(2); // TODO: Verify version + in->skip(64); // skip savegame description + in->read(_gameState, _gameStateSize); + + delete in; + + return 0; + +} + int16 GameDatabase::getVar(int16 index) { return (int16)READ_LE_UINT16(_gameState + index * 2); } diff --git a/engines/made/database.h b/engines/made/database.h index 5e88b0919f..c5d3916e25 100644 --- a/engines/made/database.h +++ b/engines/made/database.h @@ -30,6 +30,7 @@ #include "common/util.h" #include "common/file.h" #include "common/stream.h" +#include "common/str.h" #include "made/redreader.h" @@ -78,6 +79,10 @@ public: void open(const char *filename); void openFromRed(const char *redFilename, const char *filename); + bool getSavegameDescription(const char *filename, Common::String &description); + int16 savegame(const char *filename, const char *description, int16 version); + int16 loadgame(const char *filename, int16 version); + Object *getObject(int16 index) const { if (index >= 1) return _objects[index - 1]; diff --git a/engines/made/screen.cpp b/engines/made/screen.cpp index ad1627c6df..74053e70a2 100644 --- a/engines/made/screen.cpp +++ b/engines/made/screen.cpp @@ -92,23 +92,41 @@ void Screen::clearScreen() { _screen1->fillRect(Common::Rect(0, 0, 320, 200), 0); _screen2->fillRect(Common::Rect(0, 0, 320, 200), 0); _needPalette = true; - //_vm->_system->clearScreen(); } void Screen::drawSurface(Graphics::Surface *sourceSurface, int x, int y, const ClipInfo &clipInfo) { - byte *source = (byte*)sourceSurface->getBasePtr(0, 0); - byte *dest = (byte*)clipInfo.destSurface->getBasePtr(x, y); + byte *source, *dest; + int startX = 0; + int startY = 0; + int clipWidth = sourceSurface->w; + int clipHeight = sourceSurface->h; + + if (x < 0) { + startX = -x; + clipWidth -= startX; + x = 0; + } - // FIXME: Implement actual clipping - if (x + sourceSurface->w > clipInfo.destSurface->w || y + sourceSurface->h > clipInfo.destSurface->h) { - debug(2, "CLIPPING PROBLEM: x = %d; y = %d; w = %d; h = %d; x+w = %d; y+h = %d\n", - x, y, sourceSurface->w, sourceSurface->h, x + sourceSurface->w, y + sourceSurface->h); - return; + if (y < 0) { + startY = -y; + clipHeight -= startY; + y = 0; } - for (int16 yc = 0; yc < sourceSurface->h; yc++) { - for (int16 xc = 0; xc < sourceSurface->w; xc++) { + if (x + clipWidth > clipInfo.x + clipInfo.w) { + clipWidth = clipInfo.x + clipInfo.w - x; + } + + if (y + clipHeight > clipInfo.y + clipInfo.h) { + clipHeight = clipInfo.y + clipInfo.h - y; + } + + source = (byte*)sourceSurface->getBasePtr(startX, startY); + dest = (byte*)clipInfo.destSurface->getBasePtr(x, y); + + for (int16 yc = 0; yc < clipHeight; yc++) { + for (int16 xc = 0; xc < clipWidth; xc++) { if (source[xc]) dest[xc] = source[xc]; } @@ -133,7 +151,7 @@ void Screen::setRGBPalette(byte *palRGB, int start, int count) { } uint16 Screen::updateChannel(uint16 channelIndex) { - return 0; + return channelIndex; } void Screen::deleteChannel(uint16 channelIndex) { @@ -303,10 +321,6 @@ void Screen::drawAnimFrame(uint16 animIndex, int16 x, int16 y, int16 frameNum, u } uint16 Screen::drawPic(uint16 index, int16 x, int16 y, uint16 flag1, uint16 flag2) { - - //HACK (until clipping is implemented) - if (y > 200) y = 0; - drawFlex(index, x, y, flag1, flag2, _clipInfo1); return 0; } @@ -624,7 +638,6 @@ void Screen::printText(const char *text) { linePos = 1; x = _textRect.left; } else if (c == 32) { - // TODO: Word-wrap int wrapPos = textPos + 1; int wrapX = x + charWidth; while (wrapPos < textLen && text[wrapPos] != 0 && text[wrapPos] != 32 && text[wrapPos] >= 28) { @@ -682,6 +695,7 @@ void Screen::printTextEx(const char *text, int16 x, int16 y, int16 fontNum, int1 int16 oldFontNum = _currentFontNum; Common::Rect oldTextRect; + ClipInfo oldFontDrawCtx = _fontDrawCtx; _fontDrawCtx = clipInfo; @@ -693,6 +707,7 @@ void Screen::printTextEx(const char *text, int16 x, int16 y, int16 fontNum, int1 printText(text); setTextRect(oldTextRect); setFont(oldFontNum); + _fontDrawCtx = oldFontDrawCtx; } diff --git a/engines/made/scriptfuncs.cpp b/engines/made/scriptfuncs.cpp index 5ab748953b..4b2d7e696b 100644 --- a/engines/made/scriptfuncs.cpp +++ b/engines/made/scriptfuncs.cpp @@ -408,9 +408,9 @@ int16 ScriptFunctionsRtz::o1_FONT(int16 argc, int16 *argv) { } int16 ScriptFunctionsRtz::o1_DRAWTEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_DRAWTEXT"); Object *obj = _vm->_dat->getObject(argv[argc - 1]); - warning("argc = %d; drawText = %s", argc, obj->getString()); + const char *text = obj->getString(); + _vm->_screen->printText(text); return 0; } @@ -420,7 +420,6 @@ int16 ScriptFunctionsRtz::o1_HOMETEXT(int16 argc, int16 *argv) { } int16 ScriptFunctionsRtz::o1_TEXTRECT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_TEXTRECT"); int16 x1 = CLIP<int16>(argv[4], 1, 318); int16 y1 = CLIP<int16>(argv[3], 1, 198); int16 x2 = CLIP<int16>(argv[2], 1, 318); @@ -536,7 +535,9 @@ int16 ScriptFunctionsRtz::o1_CDPLAYSEG(int16 argc, int16 *argv) { } int16 ScriptFunctionsRtz::o1_PRINTF(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_PRINTF"); + Object *obj = _vm->_dat->getObject(argv[argc - 1]); + const char *text = obj->getString(); + debug(4, "--> text = %s", text); return 0; } @@ -556,7 +557,7 @@ int16 ScriptFunctionsRtz::o1_SNDENERGY(int16 argc, int16 *argv) { int16 ScriptFunctionsRtz::o1_CLEARTEXT(int16 argc, int16 *argv) { warning("Unimplemented opcode: o1_CLEARTEXT"); - return 0; + return 1; } int16 ScriptFunctionsRtz::o1_ANIMTEXT(int16 argc, int16 *argv) { @@ -746,33 +747,89 @@ int16 ScriptFunctionsRtz::o1_READMENU(int16 argc, int16 *argv) { } int16 ScriptFunctionsRtz::o1_DRAWMENU(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_DRAWMENU"); + int16 menuIndex = argv[1]; + int16 textIndex = argv[0]; + MenuResource *menu = _vm->_res->getMenu(menuIndex); + if (menu) { + const char *text = menu->getString(textIndex); + if (text) + _vm->_screen->printText(text); + _vm->_res->freeResource(menu); + } return 0; } int16 ScriptFunctionsRtz::o1_MENUCOUNT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_MENUCOUNT"); - return 0; + int16 menuIndex = argv[0]; + int16 count = 0; + MenuResource *menu = _vm->_res->getMenu(menuIndex); + if (menu) { + count = menu->getCount(); + _vm->_res->freeResource(menu); + } + return count; } int16 ScriptFunctionsRtz::o1_SAVEGAME(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_SAVEGAME"); - return 0; + + int16 saveNum = argv[2]; + int16 descObjectIndex = argv[1]; + int16 version = argv[0]; + + if (saveNum > 999) + return 6; + + Object *obj = _vm->_dat->getObject(descObjectIndex); + const char *description = obj->getString(); + + // TODO: Use better filename + char filename[256]; + snprintf(filename, 256, "rtz.%03d", saveNum); + + return _vm->_dat->savegame(filename, description, version); + } int16 ScriptFunctionsRtz::o1_LOADGAME(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_LOADGAME"); - return 0; + + int16 saveNum = argv[1]; + int16 version = argv[0]; + + if (saveNum > 999) + return 1; + + // TODO: Use better filename + char filename[256]; + snprintf(filename, 256, "rtz.%03d", saveNum); + + return _vm->_dat->loadgame(filename, version); + } int16 ScriptFunctionsRtz::o1_GAMENAME(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_GAMENAME"); - warning("GAMENAME: 1) %d\n", argv[2]); - warning("GAMENAME: 2) %d\n", argv[1]); - warning("GAMENAME: 3) %d\n", argv[0]); + int16 descObjectIndex = argv[2]; + int16 saveNum = argv[1]; + int16 version = argv[0]; + Common::String description; + + if (saveNum > 999) + return 1; + + // TODO: Use better filename + char filename[256]; + snprintf(filename, 256, "rtz.%03d", saveNum); + + Object *obj = _vm->_dat->getObject(descObjectIndex); + + if (_vm->_dat->getSavegameDescription(filename, description)) { + obj->setString(description.c_str()); + return 0; + } else { + obj->setString(""); + return 1; + } - return 0; } int16 ScriptFunctionsRtz::o1_SHAKESCREEN(int16 argc, int16 *argv) { |