home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 February / chip_20022115.iso / amiga / chipgame / scummvm_aga.lha / ScummVM_AGA / src / saveload.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2002-01-05  |  17.7 KB  |  662 lines

  1. /* ScummVM - Scumm Interpreter
  2.  * Copyright (C) 2001  Ludvig Strigeus
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  *
  18.  * $Header: /cvsroot/scummvm/scummvm/saveload.cpp,v 1.11 2001/11/09 18:54:14 strigeus Exp $
  19.  *
  20.  */
  21.  
  22. #include "stdafx.h"
  23. #include "scumm.h"
  24.  
  25. struct SaveGameHeader {
  26.     uint32 type;
  27.     uint32 size;
  28.     uint32 ver;
  29.     char name[32];
  30. };
  31.  
  32. #define CURRENT_VER 4
  33.  
  34. bool Scumm::saveState(int slot, bool compat) {
  35.     char filename[256];
  36.     FILE *out;
  37.     SaveGameHeader hdr;
  38.     Serializer ser;
  39.  
  40.     makeSavegameName(filename, slot, compat);
  41.     
  42.     out = fopen(filename,"wb");
  43.     if (out==NULL)
  44.         return false;
  45.  
  46.     memcpy(hdr.name, _saveLoadName, sizeof(hdr.name));
  47.         
  48.     hdr.type = MKID('SCVM');
  49.     hdr.size = 0;
  50.     hdr.ver = CURRENT_VER;
  51.     
  52.     fwrite(&hdr, sizeof(hdr), 1, out);
  53.  
  54.     ser._saveLoadStream = out;
  55.     ser._saveOrLoad = true;
  56.     saveOrLoad(&ser);
  57.  
  58.     fclose(out);
  59.     debug(1,"State saved as '%s'", filename);
  60.     return true;
  61. }
  62.  
  63. bool Scumm::loadState(int slot, bool compat) {
  64.     char filename[256];
  65.      FILE *out;
  66.     int i,j;
  67.     SaveGameHeader hdr;
  68.     Serializer ser;
  69.     int sb,sh;
  70.  
  71.     makeSavegameName(filename, slot, compat);
  72.     out = fopen(filename,"rb");
  73.  
  74.     if (out==NULL)
  75.         return false;
  76.  
  77.     fread(&hdr, sizeof(hdr), 1, out);
  78.     if (hdr.type != MKID('SCVM')) {
  79.         warning("Invalid savegame '%s'", filename);
  80.         fclose(out);
  81.         return false;
  82.     }
  83.  
  84.     if (hdr.ver != CURRENT_VER) {
  85.         warning("Invalid version of '%s'", filename);
  86.         fclose(out);
  87.         return false;
  88.     }
  89.  
  90.     memcpy(_saveLoadName, hdr.name, sizeof(hdr.name));
  91.     
  92.     CHECK_HEAP
  93.  
  94.     openRoom(-1);
  95.     memset(_inventory, 0, sizeof(_inventory[0])*_numInventory);
  96.  
  97.     /* Nuke all resources */
  98.     for (i=1; i<=16; i++)
  99.         if (i!=rtTemp && i!=rtBuffer)
  100.             for(j=0; j<res.num[i]; j++) {
  101.                 nukeResource(i,j);
  102.                 res.flags[i][j] = 0;
  103.             }
  104.  
  105.     initScummVars();
  106.     
  107.     ser._saveLoadStream = out;
  108.     ser._saveOrLoad = false;
  109.     saveOrLoad(&ser);
  110.     fclose(out);
  111.  
  112.     sb = _screenB;
  113.     sh = _screenH;
  114.  
  115.     gdi._mask_left = -1;
  116.     
  117.     initScreens(0, 0, 320, 200);
  118.     _screenEffectFlag = 1;
  119.     unkVirtScreen4(129);
  120.  
  121.     initScreens(0, sb, 320, sh);
  122.  
  123.     _completeScreenRedraw = true;
  124.     setDirtyColors(0,255);
  125.  
  126.     _lastCodePtr = NULL;
  127.  
  128.     _drawObjectQueNr = 0;
  129.     _verbMouseOver = 0;
  130.  
  131.     initBGBuffers();
  132.  
  133.     CHECK_HEAP
  134.  
  135.     debug(1,"State loaded from '%s'", filename);
  136.  
  137.     return true;
  138. }
  139.  
  140. void Scumm::makeSavegameName(char *out, int slot, bool compatible) {
  141.     sprintf(out, "%s.%c%.2d", _exe_name, compatible ? 'c': 's', slot);
  142. }
  143.  
  144. bool Scumm::getSavegameName(int slot, char *desc) {
  145.     char filename[256];
  146.     FILE *out;
  147.     SaveGameHeader hdr;
  148.     bool result;
  149.     int len;
  150.  
  151.     makeSavegameName(filename, slot, false);
  152.     out = fopen(filename,"rb");    
  153.     if (out==NULL) {
  154.         strcpy(desc,"");
  155.         return false;
  156.     }
  157.     len = fread(&hdr, sizeof(hdr), 1, out);
  158.     fclose(out);
  159.  
  160.     if (len!=1 || hdr.type != MKID('SCVM')) {
  161.         strcpy(desc, "Invalid savegame");
  162.         return false;
  163.     }
  164.     
  165.     if (hdr.ver != CURRENT_VER) {
  166.         strcpy(desc, "Invalid version");
  167.         return false;
  168.     }
  169.     
  170.     memcpy(desc, hdr.name, sizeof(hdr.name));
  171.     desc[sizeof(hdr.name)-1] = 0;
  172.     return true;
  173. }
  174.  
  175. #define OFFS(type,item) ((int)(&((type*)0)->item))
  176. #define SIZE(type,item) sizeof(((type*)0)->item)
  177. #define MKLINE(type,item,saveas) {OFFS(type,item),saveas,SIZE(type,item)}
  178. #define MKARRAY(type,item,saveas,num) {OFFS(type,item),128|saveas,SIZE(type,item)}, {num,0,0}
  179. #define MKEND() {0xFFFF,0xFF,0xFF}
  180.  
  181. void Scumm::saveOrLoad(Serializer *s) {
  182.     const SaveLoadEntry objectEntries[] = {
  183.         MKLINE(ObjectData,offs_obim_to_room,sleUint32),
  184.         MKLINE(ObjectData,offs_obcd_to_room,sleUint32),
  185.         MKLINE(ObjectData,walk_x,sleUint16),
  186.         MKLINE(ObjectData,walk_y,sleUint16),
  187.         MKLINE(ObjectData,obj_nr,sleUint16),
  188.         MKLINE(ObjectData,x_pos,sleInt16),
  189.         MKLINE(ObjectData,y_pos,sleInt16),
  190.         MKLINE(ObjectData,numstrips,sleUint16),
  191.         MKLINE(ObjectData,height,sleUint16),
  192.         MKLINE(ObjectData,actordir,sleByte),
  193.         MKLINE(ObjectData,parentstate,sleByte),
  194.         MKLINE(ObjectData,parent,sleByte),
  195.         MKLINE(ObjectData,ownerstate,sleByte),
  196.         MKLINE(ObjectData,fl_object_index,sleByte),
  197.         MKLINE(ObjectData,unk_3,sleByte),
  198.         MKEND()
  199.     };
  200.  
  201.     const SaveLoadEntry actorEntries[] = {
  202.         MKLINE(Actor,x,sleInt16),
  203.         MKLINE(Actor,y,sleInt16),
  204.         MKLINE(Actor,top,sleInt16),
  205.         MKLINE(Actor,bottom,sleInt16),
  206.         MKLINE(Actor,elevation,sleInt16),
  207.         MKLINE(Actor,width,sleUint16),
  208.         MKLINE(Actor,facing,sleByte),
  209.         MKLINE(Actor,costume,sleUint16),
  210.         MKLINE(Actor,room,sleByte),
  211.         MKLINE(Actor,talkColor,sleByte),
  212.         MKLINE(Actor,scalex,sleByte),
  213.         MKLINE(Actor,scaley,sleByte),
  214.         MKLINE(Actor,charset,sleByte),
  215.         MKARRAY(Actor,sound[0],sleByte, 8),
  216.         MKLINE(Actor,newDirection,sleByte),
  217.         MKLINE(Actor,moving,sleByte),
  218.         MKLINE(Actor,ignoreBoxes,sleByte),
  219.         MKLINE(Actor,neverZClip,sleByte),
  220.         MKLINE(Actor,initFrame,sleByte),
  221.         MKLINE(Actor,walkFrame,sleByte),
  222.         MKLINE(Actor,standFrame,sleByte),
  223.         MKLINE(Actor,talkFrame1,sleByte),
  224.         MKLINE(Actor,talkFrame2,sleByte),
  225.         MKLINE(Actor,speedx,sleUint16),
  226.         MKLINE(Actor,speedy,sleUint16),
  227.         MKLINE(Actor,cost.animCounter1,sleUint16),
  228.         MKLINE(Actor,cost.animCounter2,sleByte),
  229.         MKARRAY(Actor,palette[0],sleByte,32),
  230.         MKLINE(Actor,mask,sleByte),
  231.         MKLINE(Actor,visible,sleByte),
  232.         MKLINE(Actor,animIndex,sleByte),
  233.         MKLINE(Actor,animSpeed,sleByte),
  234.         MKLINE(Actor,animProgress,sleByte),
  235.         MKLINE(Actor,walkbox,sleByte),
  236.         MKLINE(Actor,needRedraw,sleByte),
  237.         MKLINE(Actor,needBgReset,sleByte),
  238.         MKLINE(Actor,costumeNeedsInit,sleByte),
  239.  
  240.         MKLINE(Actor,new_1,sleInt16),
  241.         MKLINE(Actor,new_2,sleInt16),
  242.         MKLINE(Actor,new_3,sleByte),
  243.  
  244.         MKLINE(Actor,walkdata.destx,sleInt16),
  245.         MKLINE(Actor,walkdata.desty,sleInt16),
  246.         MKLINE(Actor,walkdata.destbox,sleByte),
  247.         MKLINE(Actor,walkdata.destdir,sleByte),
  248.         MKLINE(Actor,walkdata.curbox,sleByte),
  249.         MKLINE(Actor,walkdata.field_7,sleByte),
  250.         MKLINE(Actor,walkdata.x,sleInt16),
  251.         MKLINE(Actor,walkdata.y,sleInt16),
  252.         MKLINE(Actor,walkdata.newx,sleInt16),
  253.         MKLINE(Actor,walkdata.newy,sleInt16),
  254.         MKLINE(Actor,walkdata.XYFactor,sleInt32),
  255.         MKLINE(Actor,walkdata.YXFactor,sleInt32),
  256.         MKLINE(Actor,walkdata.xfrac,sleUint16),
  257.         MKLINE(Actor,walkdata.yfrac,sleUint16),
  258.  
  259.         MKLINE(Actor,cost.hdr,sleUint16),
  260.         MKARRAY(Actor,cost.a[0],sleUint16,16),
  261.         MKARRAY(Actor,cost.b[0],sleUint16,16),
  262.         MKARRAY(Actor,cost.c[0],sleUint16,16),
  263.         MKARRAY(Actor,cost.d[0],sleUint16,16),
  264.         MKEND()
  265.     };
  266.  
  267.     const SaveLoadEntry verbEntries[] = {
  268.         MKLINE(VerbSlot,x,sleInt16),
  269.         MKLINE(VerbSlot,y,sleInt16),
  270.         MKLINE(VerbSlot,right,sleInt16),
  271.         MKLINE(VerbSlot,bottom,sleInt16),
  272.         MKLINE(VerbSlot,oldleft,sleInt16),
  273.         MKLINE(VerbSlot,oldtop,sleInt16),
  274.         MKLINE(VerbSlot,oldright,sleInt16),
  275.         MKLINE(VerbSlot,oldbottom,sleInt16),
  276.         MKLINE(VerbSlot,verbid,sleByte),
  277.         MKLINE(VerbSlot,color,sleByte),
  278.         MKLINE(VerbSlot,hicolor,sleByte),
  279.         MKLINE(VerbSlot,dimcolor,sleByte),
  280.         MKLINE(VerbSlot,bkcolor,sleByte),
  281.         MKLINE(VerbSlot,type,sleByte),
  282.         MKLINE(VerbSlot,charset_nr,sleByte),
  283.         MKLINE(VerbSlot,curmode,sleByte),
  284.         MKLINE(VerbSlot,saveid,sleByte),
  285.         MKLINE(VerbSlot,key,sleByte),
  286.         MKLINE(VerbSlot,center,sleByte),
  287.         MKLINE(VerbSlot,field_1B,sleByte),
  288.         MKLINE(VerbSlot,imgindex,sleUint16),
  289.         MKEND()
  290.     };
  291.     
  292.     const SaveLoadEntry mainEntries[] = {
  293.         MKLINE(Scumm,_scrWidthIn8Unit,sleUint16),
  294.         MKLINE(Scumm,_scrHeight,sleUint16),
  295.         MKLINE(Scumm,_ENCD_offs,sleUint32),
  296.         MKLINE(Scumm,_EXCD_offs,sleUint32),
  297.         MKLINE(Scumm,_IM00_offs,sleUint32),
  298.         MKLINE(Scumm,_CLUT_offs,sleUint32),
  299.         MKLINE(Scumm,_EPAL_offs,sleUint32),
  300.         MKLINE(Scumm,_PALS_offs,sleUint32),
  301.         MKLINE(Scumm,_curPalIndex,sleByte),
  302.         MKLINE(Scumm,_currentRoom,sleByte),
  303.         MKLINE(Scumm,_roomResource,sleByte),
  304.         MKLINE(Scumm,_numObjectsInRoom,sleByte),
  305.         MKLINE(Scumm,_currentScript,sleByte),
  306.         MKARRAY(Scumm,_localScriptList[0],sleUint32,0x39),
  307.         MKARRAY(Scumm,vm.localvar[0][0],sleUint16,NUM_SCRIPT_SLOT*17),
  308.         MKARRAY(Scumm,_resourceMapper[0],sleByte,128),
  309.         MKARRAY(Scumm,charset._colorMap[0],sleByte,16),
  310.         MKARRAY(Scumm,_charsetData[0][0],sleByte,10*16),
  311.         MKLINE(Scumm,_curExecScript,sleUint16),
  312.  
  313.         MKLINE(Scumm,camera._destPos,sleInt16),
  314.         MKLINE(Scumm,camera._curPos,sleInt16),
  315.         MKLINE(Scumm,camera._lastPos,sleInt16),
  316.         MKLINE(Scumm,_screenStartStrip,sleInt16),
  317.         MKLINE(Scumm,_screenEndStrip,sleInt16),
  318.         MKLINE(Scumm,camera._mode,sleByte),
  319.         MKLINE(Scumm,camera._follows,sleByte),
  320.         MKLINE(Scumm,camera._leftTrigger,sleInt16),
  321.         MKLINE(Scumm,camera._rightTrigger,sleInt16),
  322.         MKLINE(Scumm,camera._movingToActor,sleUint16),
  323.  
  324.         MKLINE(Scumm,_actorToPrintStrFor,sleByte),
  325.         MKLINE(Scumm,_charsetColor,sleByte),
  326.         MKLINE(Scumm,charset._bufPos,sleByte),
  327.         MKLINE(Scumm,_haveMsg,sleByte),
  328.         MKLINE(Scumm,_useTalkAnims,sleByte),
  329.  
  330.         MKLINE(Scumm,_talkDelay,sleInt16),
  331.         MKLINE(Scumm,_defaultTalkDelay,sleInt16),
  332.         MKLINE(Scumm,_numInMsgStack,sleInt16),
  333.         MKLINE(Scumm,_sentenceIndex,sleByte),
  334.  
  335.         MKLINE(Scumm,vm.cutSceneStackPointer,sleByte),
  336.         MKARRAY(Scumm,vm.cutScenePtr[0],sleUint32,5),
  337.         MKARRAY(Scumm,vm.cutSceneScript[0],sleByte,5),
  338.         MKARRAY(Scumm,vm.cutSceneData[0],sleInt16,5),
  339.         MKLINE(Scumm,vm.cutSceneScriptIndex,sleInt16),
  340.         
  341.         /* nest */
  342.         MKLINE(Scumm,_numNestedScripts,sleByte),
  343.         MKLINE(Scumm,_userPut,sleByte),
  344.         MKLINE(Scumm,_cursorState,sleByte),
  345.         MKLINE(Scumm,gdi._cursorActive,sleByte),
  346.         MKLINE(Scumm,gdi._currentCursor,sleByte),
  347.  
  348.         MKLINE(Scumm,_doEffect,sleByte),
  349.         MKLINE(Scumm,_switchRoomEffect,sleByte),
  350.         MKLINE(Scumm,_newEffect,sleByte),
  351.         MKLINE(Scumm,_switchRoomEffect2,sleByte),
  352.         MKLINE(Scumm,_BgNeedsRedraw,sleByte),
  353.  
  354.         MKARRAY(Scumm,actorDrawBits[0],sleUint16,200),
  355.         MKLINE(Scumm,gdi._transparency,sleByte),
  356.         MKARRAY(Scumm,_currentPalette[0],sleByte,768),
  357.         /* virtscr */
  358.  
  359.         MKARRAY(Scumm,charset._buffer[0],sleByte,256),
  360.  
  361.         MKLINE(Scumm,_egoPositioned,sleByte),
  362.  
  363.         MKARRAY(Scumm,gdi._imgBufOffs[0],sleUint16,4),
  364.         MKLINE(Scumm,gdi._numZBuffer,sleByte),
  365.  
  366.         MKLINE(Scumm,_screenEffectFlag,sleByte),
  367.  
  368.         MKLINE(Scumm,_randSeed1,sleUint32),
  369.         MKLINE(Scumm,_randSeed2,sleUint32),
  370.  
  371.         MKLINE(Scumm,_shakeMode,sleInt16),
  372.  
  373.         MKLINE(Scumm,_keepText,sleByte),
  374.  
  375.         MKLINE(Scumm,_screenB,sleUint16),
  376.         MKLINE(Scumm,_screenH,sleUint16),
  377.  
  378.         MKARRAY(Scumm,cost._transEffect[0],sleByte,256),
  379.  
  380.         MKEND()
  381.     };
  382.  
  383.     const SaveLoadEntry scriptSlotEntries[] = {
  384.         MKLINE(ScriptSlot,offs,sleUint32),
  385.         MKLINE(ScriptSlot,delay,sleInt32),
  386.         MKLINE(ScriptSlot,number,sleUint16),
  387.         MKLINE(ScriptSlot,newfield,sleUint16),
  388.         MKLINE(ScriptSlot,status,sleByte),
  389.         MKLINE(ScriptSlot,type,sleByte),
  390.         MKLINE(ScriptSlot,unk1,sleByte),
  391.         MKLINE(ScriptSlot,unk2,sleByte),
  392.         MKLINE(ScriptSlot,freezeCount,sleByte),
  393.         MKLINE(ScriptSlot,didexec,sleByte),
  394.         MKLINE(ScriptSlot,cutsceneOverride,sleByte),
  395.         MKLINE(ScriptSlot,unk5,sleByte),
  396.         MKEND()
  397.     };
  398.  
  399.     const SaveLoadEntry nestedScriptEntries[] = {
  400.         MKLINE(NestedScript,number,sleUint16),
  401.         MKLINE(NestedScript,type,sleByte),
  402.         MKLINE(NestedScript,slot,sleByte),
  403.         MKEND()
  404.     };
  405.  
  406.     const SaveLoadEntry sentenceTabEntries[] = {
  407.         MKLINE(SentenceTab,unk5,sleUint8),
  408.         MKLINE(SentenceTab,unk2,sleUint8),
  409.         MKLINE(SentenceTab,unk4,sleUint16),
  410.         MKLINE(SentenceTab,unk3,sleUint16),
  411.         MKLINE(SentenceTab,unk,sleUint8),
  412.         MKEND()
  413.     };
  414.  
  415.     const SaveLoadEntry stringTabEntries[] = {
  416.         MKLINE(StringTab,t_xpos,sleInt16),
  417.         MKLINE(StringTab,t_ypos,sleInt16),
  418.         MKLINE(StringTab,t_center,sleByte),
  419.         MKLINE(StringTab,t_overhead,sleByte),
  420.         MKLINE(StringTab,t_no_talk_anim,sleByte),
  421.         MKLINE(StringTab,t_right,sleInt16),
  422.         MKLINE(StringTab,t_color,sleInt16),
  423.         MKLINE(StringTab,t_charset,sleInt16),
  424.         MKLINE(StringTab,xpos,sleInt16),
  425.         MKLINE(StringTab,ypos,sleInt16),
  426.         MKLINE(StringTab,center,sleInt16),
  427.         MKLINE(StringTab,overhead,sleInt16),
  428.         MKLINE(StringTab,no_talk_anim,sleInt16),
  429.         MKLINE(StringTab,right,sleInt16),
  430.         MKEND()
  431.     };
  432.  
  433.     const SaveLoadEntry colorCycleEntries[] = {
  434.         MKLINE(ColorCycle,delay,sleUint16),
  435.         MKLINE(ColorCycle,counter,sleUint16),
  436.         MKLINE(ColorCycle,flags,sleUint16),
  437.         MKLINE(ColorCycle,start,sleByte),
  438.         MKLINE(ColorCycle,end,sleByte),
  439.         MKEND()
  440.     };
  441.  
  442.     int i,j;
  443.     
  444.     s->saveLoadEntries(this,mainEntries);
  445.  
  446.     s->saveLoadArrayOf(actor+1, 12, sizeof(actor[0]), actorEntries);
  447.     s->saveLoadArrayOf(vm.slot, NUM_SCRIPT_SLOT, sizeof(vm.slot[0]), scriptSlotEntries);
  448.     s->saveLoadArrayOf(_objs, _numLocalObjects, sizeof(_objs[0]), objectEntries);
  449.     s->saveLoadArrayOf(_verbs, _numVerbs, sizeof(_verbs[0]), verbEntries);
  450.     s->saveLoadArrayOf(vm.nest, 16, sizeof(vm.nest[0]), nestedScriptEntries);
  451.     s->saveLoadArrayOf(sentence, 6, sizeof(sentence[0]), sentenceTabEntries);
  452.     s->saveLoadArrayOf(string, 6, sizeof(string[0]), stringTabEntries);
  453.     s->saveLoadArrayOf(_colorCycle, 16, sizeof(_colorCycle[0]), colorCycleEntries);
  454.  
  455.     for (i=1; i<=16; i++)
  456.         if (res.mode[i]==0)
  457.             for(j=1; j<res.num[i]; j++)
  458.                 saveLoadResource(s,i,j);
  459.  
  460.     s->saveLoadArrayOf(_objectFlagTable, _numGlobalObjects, sizeof(_objectFlagTable[0]), sleByte);
  461.     s->saveLoadArrayOf(_classData, _numGlobalObjects, sizeof(_classData[0]), sleUint32);
  462.     s->saveLoadArrayOf(_vars, _numVariables, sizeof(_vars[0]), sleInt16);
  463.     s->saveLoadArrayOf(_bitVars, _numBitVariables>>3, 1, sleByte);
  464.  
  465.     /* Save or load a list of the locked objects */
  466.     if (s->isSaving()) {
  467.         for (i=1; i<=16; i++)
  468.             for(j=1; j<res.num[i]; j++) {
  469.                 if (res.flags[i][j]&0x80) {
  470.                     s->saveByte(i);
  471.                     s->saveWord(j);
  472.                 }
  473.             }
  474.         s->saveByte(0xFF);
  475.     } else {
  476.         int r;
  477.         while ((r = s->loadByte()) != 0xFF) {
  478.             res.flags[r][s->loadWord()] |= 0x80;
  479.         }
  480.     }
  481. }
  482.  
  483. void Scumm::saveLoadResource(Serializer *ser, int type, int index) {
  484.     byte *ptr;
  485.     uint32 size,sizele;
  486.     byte flag;
  487.  
  488.     /* don't save/load these resource types */
  489.     if (type==13 || type==12 || type==10 || res.mode[type])
  490.         return;
  491.  
  492.     if (ser->isSaving()) {
  493.         ptr = res.address[type][index];
  494.         if (ptr==NULL) {
  495.             ser->saveUint32(0);
  496.             return;
  497.         }
  498.  
  499.         size = ((ResHeader*)ptr)->size;
  500.  
  501.         ser->saveUint32(size);
  502.         ser->saveLoadBytes(ptr+sizeof(ResHeader),size);
  503.  
  504.         if (type==5) {
  505.             ser->saveWord(_inventory[index]);
  506.         }
  507.     } else {
  508.         size = ser->loadUint32();
  509.         if (size) {
  510.             createResource(type, index, size);
  511.             ser->saveLoadBytes(getResourceAddress(type, index), size);
  512.             if (type==5) {
  513.                 _inventory[index] = ser->loadWord();
  514.             }
  515.         }
  516.     }
  517. }
  518.  
  519. void Serializer::saveLoadBytes(void *b, int len) {
  520.     if (_saveOrLoad)
  521.         fwrite(b, 1, len, _saveLoadStream);
  522.     else
  523.         fread(b, 1, len, _saveLoadStream);
  524. }
  525.  
  526. void Serializer::saveUint32(uint32 d) {
  527.     uint32 e = FROM_LE_32(d);
  528.     saveLoadBytes(&e,4);
  529. }
  530.  
  531. void Serializer::saveWord(uint16 d) {
  532.     uint16 e = FROM_LE_16(d);
  533.     saveLoadBytes(&e,2);
  534. }
  535.  
  536. void Serializer::saveByte(byte b) {
  537.     saveLoadBytes(&b,1);
  538. }
  539.  
  540. uint32 Serializer::loadUint32() {
  541.     uint32 e;
  542.     saveLoadBytes(&e,4);
  543.     return FROM_LE_32(e);
  544. }
  545.  
  546. uint16 Serializer::loadWord() {
  547.     uint16 e;
  548.     saveLoadBytes(&e,2);
  549.     return FROM_LE_16(e);
  550. }
  551.  
  552. byte Serializer::loadByte() {
  553.     byte e;
  554.     saveLoadBytes(&e,1);
  555.     return e;
  556. }
  557.  
  558. void Serializer::saveLoadArrayOf(void *b, int len, int datasize, byte filetype) {
  559.     byte *at = (byte*)b;
  560.     uint32 data;
  561.  
  562.     /* speed up byte arrays */
  563.     if (datasize==1 && filetype==sleByte) {
  564.         saveLoadBytes(b, len);
  565.         return;
  566.     }
  567.  
  568.     while (--len>=0) {
  569.         if (_saveOrLoad) {
  570.             /* saving */
  571.             if (datasize==1) {
  572.                 data = *(byte*)at;
  573.                 at += 1;
  574.             } else if (datasize==2) {
  575.                 data = *(uint16*)at;
  576.                 at += 2;
  577.             } else if (datasize==4) {
  578.                 data = *(uint32*)at;
  579.                 at += 4;
  580.             } else {
  581.                 error("saveLoadArrayOf: invalid size %d", datasize);
  582.             }
  583.             switch(filetype) {
  584.             case sleByte: saveByte(data); break;
  585.             case sleUint16:
  586.             case sleInt16:saveWord(data); break;
  587.             case sleInt32:
  588.             case sleUint32:saveUint32(data); break;
  589.             default:
  590.                 error("saveLoadArrayOf: invalid filetype %d", filetype);
  591.             }
  592.         } else {
  593.             /* loading */
  594.             switch(filetype) {
  595.             case sleByte: data = loadByte(); break;
  596.             case sleUint16: data = loadWord(); break;
  597.             case sleInt16: data = (int16)loadWord(); break;
  598.             case sleUint32: data = loadUint32(); break;
  599.             case sleInt32: data = (int32)loadUint32(); break;
  600.             default:
  601.                 error("saveLoadArrayOf: invalid filetype %d", filetype);
  602.             }
  603.             if (datasize==1) {
  604.                 *(byte*)at = data;
  605.                 at += 1;
  606.             } else if (datasize==2) {
  607.                 *(uint16*)at = data;
  608.                 at += 2;
  609.             } else if (datasize==4) {
  610.                 *(uint32*)at = data;
  611.                 at += 4;
  612.             } else {
  613.                 error("saveLoadArrayOf: invalid size %d", datasize);
  614.             }
  615.         }
  616.     }
  617. }
  618.  
  619. void Serializer::saveLoadArrayOf(void *b, int num, int datasize, const SaveLoadEntry *sle) {
  620.     byte *data = (byte*)b;
  621.     while (--num) {
  622.         saveLoadEntries(data, sle);        
  623.         data += datasize;
  624.     }
  625. }
  626.  
  627.  
  628. void Serializer::saveLoadEntries(void *d, const SaveLoadEntry *sle) {
  629.     int replen;
  630.     byte type;
  631.     byte *at;
  632.  
  633.     int size;
  634.     int value;
  635.     
  636.     while(sle->offs != 0xFFFF) {
  637.         at = (byte*)d + sle->offs;
  638.         size = sle->size;
  639.         type = sle->type;
  640.         
  641.         if (size==0xFF) {
  642.             if (_saveOrLoad) {
  643.                 /* save reference */
  644.                 saveWord((*_save_ref)(_ref_me, type, *((void**)at)));
  645.             } else {
  646.                 /* load reference */
  647.                 *((void**)at) = (*_load_ref)(_ref_me, type, loadWord());
  648.             }
  649.         } else {
  650.             replen = 1;
  651.             if (type&128) {
  652.                 sle++;
  653.                 replen = sle->offs;
  654.                 type&=~128;
  655.             }
  656.             saveLoadArrayOf(at, replen, size, type);
  657.             sle++;
  658.         }
  659.     }
  660. }
  661.  
  662.