Ticket #8624: dialog_save.patch

File dialog_save.patch, 11.3 KB (added by SF/tobigun, 14 years ago)
  • ../../engines/scumm/input.cpp

     
    499499
    500500        // Alt-F5 brings up the original save/load dialog.
    501501
    502         if (lastKeyHit == 440 && _game.version > 2 && _game.version < 8) {
    503                 lastKeyHit = saveloadkey;
    504                 saveloadkey = -1;
     502        if (lastKeyHit == 440) {
     503                if(_game.version <= 3)
     504                        prepareSavegame();
     505                if(_game.version > 2 && _game.version < 8) {
     506                        lastKeyHit = saveloadkey;
     507                        saveloadkey = -1;
     508                }
    505509        }
    506510
    507511        if (lastKeyHit == saveloadkey) {
  • ../../engines/scumm/intern.h

     
    8282        int getWordVararg(int *ptr);
    8383        void saveVars();
    8484        void loadVars();
     85        void saveIQPoints();
     86        void loadIQPoints();
    8587
    8688        virtual int getVar();
    8789        virtual int getVarOrDirectByte(byte mask);
  • ../../engines/scumm/saveload.cpp

     
    8484        _saveLoadFlag = 2;              // 2 for load
    8585}
    8686
     87static bool saveSaveGameHeader(Common::OutSaveFile *out, SaveGameHeader &hdr) {
     88        hdr.type = MKID_BE('SCVM');
     89        hdr.size = 0;
     90        hdr.ver = CURRENT_VER;
     91
     92        out->writeUint32BE(hdr.type);
     93        out->writeUint32LE(hdr.size);
     94        out->writeUint32LE(hdr.ver);
     95        out->write(hdr.name, sizeof(hdr.name));
     96        return true;
     97}
     98
    8799bool ScummEngine::saveState(int slot, bool compat) {
    88100        char filename[256];
    89101        Common::OutSaveFile *out;
     
    95107                return false;
    96108
    97109        memcpy(hdr.name, _saveLoadName, sizeof(hdr.name));
    98 
    99         hdr.type = MKID_BE('SCVM');
    100         hdr.size = 0;
    101         hdr.ver = CURRENT_VER;
    102 
    103         out->writeUint32BE(hdr.type);
    104         out->writeUint32LE(hdr.size);
    105         out->writeUint32LE(hdr.ver);
    106         out->write(hdr.name, sizeof(hdr.name));
     110        saveSaveGameHeader(out, hdr);
    107111        saveThumbnail(out);
    108112        saveInfos(out);
    109113
     
    429433        return true;
    430434}
    431435
     436void ScummEngine::prepareSavegame() {
     437        saveState(0, true);
     438}
     439
     440bool ScummEngine::savePreparedSavegame(int slot, char *desc) {
     441        return copyRenameSavegame(0, true, slot, false, desc);
     442}
     443
     444bool ScummEngine::copyRenameSavegame(int oldSlot, bool oldTemporary, int newSlot, bool newTemporary, char *desc) {
     445        bool result;
     446        uint32 nread;
     447        byte buffer[1024];
     448        char oldFilename[256];
     449        char newFilename[256];
     450        Common::InSaveFile *in;
     451        Common::OutSaveFile *out;
     452        SaveGameHeader hdr;
     453
     454        makeSavegameName(oldFilename, oldSlot, oldTemporary);
     455        if (!(in = _saveFileMan->openForLoading(oldFilename)))
     456                return false;
     457
     458        if (!loadSaveGameHeader(in, hdr)) {
     459                warning("Invalid savegame '%s'", oldFilename);
     460                delete in;
     461                return false;
     462        }
     463
     464        if (hdr.ver != CURRENT_VER) {
     465                warning("Incompatible savegame '%s'", oldFilename);
     466                delete in;
     467                return false;
     468        }
     469
     470        makeSavegameName(newFilename, newSlot, newTemporary);
     471        if (!(out = _saveFileMan->openForSaving(newFilename))) {
     472                delete in;
     473                return false;
     474        }
     475
     476        memset(hdr.name, 0, sizeof(hdr.name));
     477        strncpy(hdr.name, desc, sizeof(hdr.name)-1);
     478        saveSaveGameHeader(out, hdr);
     479       
     480        // copy bytes
     481        result = true;
     482        while (nread = in->read(buffer, sizeof(buffer))) {
     483                uint32 nwritten = out->write(buffer, nread);
     484                if (nwritten < nread) {
     485                        result = false;
     486                        break;
     487                }
     488        }
     489
     490        out->finalize();
     491        if (out->ioFailed()) {
     492                result = false;
     493        }
     494        delete in;
     495        delete out;
     496
     497        return result;
     498}
     499
    432500Graphics::Surface *ScummEngine::loadThumbnailFromSlot(int slot) {
    433501        char filename[256];
    434502        Common::InSaveFile *in;
  • ../../engines/scumm/script_v5.cpp

     
    870870
    871871void ScummEngine_v5::saveVars() {
    872872        int a, b;
     873        static char filename[256];
    873874
    874         // FIXME: This opcode is currently a stub. It is needed for at least two things:
    875         // * storing save game names in Indy 3 (and maybe others)
    876         // * storing the global IQ (Indy Quotient) in Indy 3
    877         // The former is not so important as we have our own save system, but the
    878         // latter one of course is a desirable feature.
    879         // So implementing this would be nice indeed. Not sure what the filename
    880         // should be -- either base it on the target name, or base it on the gameid.
    881         // Both approaches have their merits, though.
    882 
    883875        while ((_opcode = fetchScriptByte()) != 0) {
    884876                switch (_opcode & 0x1F) {
    885877                case 0x01: // write a range of variables
     
    892884                case 0x02: // write a range of string variables
    893885                        a = getVarOrDirectByte(PARAM_1);
    894886                        b = getVarOrDirectByte(PARAM_2);
    895                         debug(0, "stub saveVars: strings %d -> %d", a, b);
     887
     888                        if (_game.version == 3 && (_game.id == GID_INDY3 || _game.id == GID_ZAK || _game.id == GID_LOOM)) {
     889                                if (a == RESID_IQ_EPISODE && b == RESID_IQ_EPISODE) {
     890                                        if (_game.id == GID_INDY3) {
     891                                                saveIQPoints();
     892                                        }
     893                                        break;
     894                                }
     895                                // FIXME: changing savegame-names not supported
     896                        } else {
     897                                debug(0, "stub saveVars: strings %d -> %d", a, b);
     898                        }
    896899                        break;
    897900                case 0x03: // open file
    898901                        a = resStrLen(_scriptPointer);
    899                         debug(0, "stub saveVars to %s", _scriptPointer);
     902                        strncpy(filename, (char*)_scriptPointer, a);
     903                        filename[a] = '\0';
    900904                        _scriptPointer += a + 1;
    901905                        break;
    902906                case 0x04:
    903907                        return;
    904908                case 0x1F: // close file
    905                         debug(0, "stub saveVars close file");
     909                        filename[0] = '\0';
    906910                        return;
    907911                }
    908912        }
     
    910914
    911915void ScummEngine_v5::loadVars() {
    912916        int a, b;
     917        static char filename[256];
    913918
    914         // FIXME: See ScummEngine_v5::saveVars
    915 
    916 //      Common::hexdump(_scriptPointer, 64);
    917919        while ((_opcode = fetchScriptByte()) != 0) {
    918920                switch (_opcode & 0x1F) {
    919921                case 0x01: // read a range of variables
     
    926928                case 0x02: // read a range of string variables
    927929                        a = getVarOrDirectByte(PARAM_1);
    928930                        b = getVarOrDirectByte(PARAM_2);
    929                         debug(0, "stub loadVars: strings %d -> %d", a, b);
     931
     932                        if (_game.version == 3 && (_game.id == GID_INDY3 || _game.id == GID_ZAK || _game.id == GID_LOOM)) {
     933                                int slot;
     934                                int slotSize;
     935                                byte* slotContent;
     936                                int savegameId;
     937                                char name[32];
     938                                bool avail_saves[100];
     939
     940                                if (a == RESID_IQ_SERIES && b == RESID_IQ_SERIES) {
     941                                        // Zak256 loads the IQ script-slot but does not use it -> ignore it
     942                                        if(_game.id == GID_INDY3) {
     943                                                loadIQPoints();
     944                                        }
     945                                        break;
     946                                }
     947                               
     948                                listSavegames(avail_saves, ARRAYSIZE(avail_saves));                                                     
     949                                for (slot = a; slot <= b; ++slot) {
     950                                        slotSize = getResourceSize(rtString, slot);
     951                                        slotContent = getResourceAddress(rtString, slot);
     952
     953                                        // load savegame names
     954                                        savegameId = slot - a + 1;
     955                                        if (avail_saves[savegameId] && getSavegameName(savegameId, name)) {
     956                                                int pos;
     957                                                char *ptr = name;
     958                                                // slotContent ends with {'\0','@'} -> max. length = slotSize-2
     959                                                for (pos = 0; pos < slotSize - 2; ++pos) {
     960                                                        if (!ptr[pos])
     961                                                                break;
     962                                                        // replace special characters
     963                                                        if(ptr[pos] >= 32 && ptr[pos] <= 122 && ptr[pos] != 64)
     964                                                                slotContent[pos] = ptr[pos];
     965                                                        else
     966                                                                slotContent[pos] = '_';
     967                                                }
     968                                                slotContent[pos] = '\0';                                               
     969                                        } else {
     970                                                slotContent[0] = '\0';
     971                                        }
     972                                }
     973                        } else {
     974                                debug(0, "stub loadVars: strings %d -> %d", a, b);
     975                        }
    930976                        break;
    931977                case 0x03: // open file
    932978                        a = resStrLen(_scriptPointer);
    933                         debug(0, "stub loadVars from %s", _scriptPointer);
     979                        strncpy(filename, (char*)_scriptPointer, a);
     980                        filename[a] = '\0';
    934981                        _scriptPointer += a + 1;
    935982                        break;
    936983                case 0x04:
    937984                        return;
    938985                case 0x1F: // close file
    939                         debug(0, "stub loadVars close file");
     986                        filename[0] = '\0';
    940987                        return;
    941988                }
    942989        }
    943990}
    944991
     992void ScummEngine_v5::saveIQPoints() {
     993        // save series IQ-points
     994        Common::OutSaveFile *file;
     995        char filename[256];
     996
     997        sprintf(filename, "%s.iq", _targetName.c_str());
     998        file = _saveFileMan->openForSaving(filename);
     999        if (file != NULL) {
     1000                int size = getResourceSize(rtString, RESID_IQ_EPISODE);
     1001                byte *ptr = getResourceAddress(rtString, RESID_IQ_EPISODE);
     1002                file->write(ptr, size);
     1003                delete file;
     1004        }
     1005}
     1006
     1007void ScummEngine_v5::loadIQPoints() {
     1008        // load series IQ-points
     1009        Common::InSaveFile *file;
     1010        char filename[256];
     1011
     1012        sprintf(filename, "%s.iq", _targetName.c_str());
     1013        file = _saveFileMan->openForLoading(filename);
     1014        if (file != NULL) {
     1015                int size = getResourceSize(rtString, RESID_IQ_SERIES);
     1016                byte *ptr = getResourceAddress(rtString, RESID_IQ_SERIES);
     1017                byte *tmp = (byte*)malloc(size);
     1018                int nread = file->read(tmp, size);
     1019                if (nread == size) {
     1020                        memcpy(ptr, tmp, size);
     1021                }
     1022                free(tmp);
     1023                delete file;
     1024        }
     1025}
     1026
    9451027void ScummEngine_v5::o5_expression() {
    9461028        int dst, i;
    9471029
     
    11241206void ScummEngine_v5::o5_saveLoadGame() {
    11251207        getResultPos();
    11261208        byte a = getVarOrDirectByte(PARAM_1);
    1127         byte slot = (a & 0x1F) + 1;
     1209        byte slot = a & 0x1F;
    11281210        byte result = 0;
    11291211
     1212        if (_game.version <= 2) {
     1213                // Slot numbers in older games start with 0, in newer games with 1
     1214                slot++;
     1215        }
     1216
    11301217        if ((_game.id == GID_MANIAC) && (_game.version <= 1)) {
    11311218                // Convert older load/save screen
    11321219                // 1 Load
     
    11451232                result = 100;
    11461233                break;
    11471234        case 0x20: // drive
    1148                 if (_game.id == GID_INDY3) {
    1149                         // 0 = hard drive
    1150                         // 1 = disk drive
    1151                         result = 0;
     1235                if (_game.version <= 3) {
     1236                        // 0 = ???
     1237                        // [1,2] = disk drive [A:,B:]
     1238                        // 3 = hard drive
     1239                        result = 3;
    11521240                } else {
    11531241                        // set current drive
    11541242                        result = 1;
    11551243                }
    11561244                break;
    11571245        case 0x40: // load
    1158                 if (loadState(slot, _saveTemporaryState))
     1246                if (loadState(slot, false))
    11591247                        result = 3; // sucess
    11601248                else
    11611249                        result = 5; // failed to load
    11621250                break;
    11631251        case 0x80: // save
    1164                 //if (saveState(slot, _saveTemporaryState))
    1165                 //      result = 0; // sucess
    1166                 //else
     1252                if (_game.version <= 3) {
     1253                        char name[32];
     1254                        if (_game.version <= 2) {
     1255                                // use generic name
     1256                                sprintf(name, "Game %c", 'A'+slot-1);
     1257                        } else {
     1258                                // use name entered by the user
     1259                                char* ptr;
     1260                                int firstSlot = (_game.id == GID_LOOM) ? RESID_SAVENAME1_LOOM : RESID_SAVENAME1;
     1261                                ptr = (char*)getStringAddress(slot + firstSlot - 1);
     1262                                strncpy(name, ptr, sizeof(name));
     1263                        }
     1264
     1265                        if(savePreparedSavegame(slot, name))
     1266                                result = 0;
     1267                        else
     1268                                result = 2;
     1269                } else {
    11671270                        result = 2; // failed to save
     1271                }
    11681272                break;
    11691273        case 0xC0: // test if save exists
    11701274                Common::InSaveFile *file;
  • ../../engines/scumm/scumm.h

     
    328328        rtNumTypes = 22
    329329};
    330330
     331enum ResIds {
     332        RESID_IQ_EPISODE = 7,
     333        RESID_IQ_SERIES = 9,
     334        RESID_SAVENAME1 = 10,
     335        RESID_SAVENAME1_LOOM = 9,
     336};
    331337
    332338
     339
    333340/**
    334341 * The 'resource manager' class. Currently doesn't really deserve to be called
    335342 * a 'class', at least until somebody gets around to OOfying this more.
     
    620627        void requestSave(int slot, const char *name, bool temporary = false);
    621628        void requestLoad(int slot);
    622629
     630        void prepareSavegame();
     631        bool savePreparedSavegame(int slot, char *desc);
     632        bool copyRenameSavegame(int oldSlot, bool oldTemporary, int newSlot, bool newTemporary, char *desc);
     633
    623634// thumbnail + info stuff
    624635public:
    625636        Graphics::Surface *loadThumbnailFromSlot(int slot);