Ticket #8624: dialog_save_alternative.patch

File dialog_save_alternative.patch, 8.1 KB (added by SF/tobigun, 14 years ago)
  • ../../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/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;
     
    11611249                        result = 5; // failed to load
    11621250                break;
    11631251        case 0x80: // save
    1164                 //if (saveState(slot, _saveTemporaryState))
    1165                 //      result = 0; // sucess
    1166                 //else
     1252                // Save dialogs of old SCUMM games except Loom are cutscene, hence
     1253                // we can easily break the cutscene and save the state after the cutscene
     1254                // has terminated. Loom doesn't use cutscene so we would run inside an endless
     1255                // loop.
     1256                if (_game.version <= 3 && _game.id != GID_LOOM) {
     1257                        char name[32];
     1258                        if (_game.version <= 2) {
     1259                                // use generic name
     1260                                sprintf(name, "Game %c", 'A'+slot-1);
     1261                        } else {
     1262                                // use name entered by the user
     1263                                char* ptr;
     1264                                int firstSlot = (_game.id == GID_LOOM) ? RESID_SAVENAME1_LOOM : RESID_SAVENAME1;
     1265                                ptr = (char*)getStringAddress(slot + firstSlot - 1);
     1266                                strncpy(name, ptr, sizeof(name));
     1267                        }
     1268                        // HACK: works without a temporary savegame but does not behave
     1269                        // like the original SAVE-dialog (does not work with LOOM)
     1270                        if (_game.id == GID_INDY3)
     1271                                saveIQPoints();
     1272                        abortCutscene();
     1273                        getScriptEntryPoint();
     1274                        requestSave(slot, name, false);
     1275                        // we do not have to return a result actually because we have already
     1276                        // jumped to the end of the cutscene.
     1277                } else {
     1278                        //if (saveState(slot, _saveTemporaryState))
     1279                        //      result = 0; // sucess
     1280                        //else
    11671281                        result = 2; // failed to save
     1282                }
    11681283                break;
    11691284        case 0xC0: // test if save exists
    11701285                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.