Ticket #9033: v0_mm_anim_2.patch

File v0_mm_anim_2.patch, 12.9 KB (added by SF/segra, 15 years ago)

Improved Patch

  • engines/scumm/actor.cpp

     
    527527        if (_moving & MF_TURN) {
    528528                new_dir = updateActorDirection(false);
    529529                // FIXME: is this correct?
    530                 if (_facing != new_dir)
     530                if (_facing != new_dir) {
     531                       
     532                        // Actor never stops walking when an object has been selected without this
     533                        if(_vm->_game.version ==0)
     534                                _moving = 0;
     535                       
    531536                        setDirection(new_dir);
    532                 else
     537
     538                } else
    533539                        _moving = 0;
    534540                return;
    535541        }
     
    817823        if (_costume == 0)
    818824                return;
    819825
     826        // V0 MM
     827        if(_vm->_game.version == 0) {
     828                if(_moving)
     829                        _vm->_costumeLoader->costumeDecodeData(this, _walkFrame, 0);
     830                else
     831                        _vm->_costumeLoader->costumeDecodeData(this, _standFrame, 0);
     832                _needRedraw = true;
     833                return;
     834        }
     835
    820836        // Update the costume for the new direction (and mark the actor for redraw)
    821837        aMask = 0x8000;
    822838        for (i = 0; i < 16; i++, aMask >>= 1) {
     
    12241240
    12251241        _vm->ensureResourceLoaded(rtCostume, _costume);
    12261242
    1227         if (_vm->_game.version <= 2) {
     1243        if (_vm->_game.version == 0) {
    12281244                _cost.reset();
    12291245                startAnimActor(_standFrame);
     1246        } else if (_vm->_game.version <= 2) {
     1247                _cost.reset();
     1248                startAnimActor(_standFrame);
    12301249                startAnimActor(_initFrame);
    12311250                startAnimActor(_talkStopFrame);
    12321251        } else {
     
    13801399        Actor** end = _sortedActors + numactors;
    13811400        for (Actor** ac = _sortedActors; ac != end; ++ac) {
    13821401                Actor* a = *ac;
     1402               
     1403                // V0 MM: 0x057B
     1404                if (_game.version == 0) {
     1405                        ActorC64 *A = (ActorC64*) a;
     1406                        if((A->_speaking & 1))
     1407                                A->_speaking ^= 0xFE;
     1408                }
    13831409                // Draw and animate the actors, except those w/o a costume.
    13841410                // Note: We could 'optimize' this a little bit by only putting
    13851411                // actors with a costume into the _sortedActors array in the
     
    15721598                // we need to shift it 8 pixels to the left
    15731599                if (_facing == 90)
    15741600                        bcr->_actorX -= 8;
     1601        } else if (_vm->_game.version == 0) {
     1602                        bcr->_actorX += 12;
    15751603        } else if (_vm->_game.version <= 2) {
    15761604                // HACK: We have to adjust the x position by one strip (8 pixels) in
    15771605                // V2 games. However, it is not quite clear to me why. And to fully
     
    17031731        case 4:                         // turn to new direction
    17041732                turnToDirection(dir);
    17051733                break;
     1734        case 64:
     1735                if(_vm->_game.version == 0) {
     1736                        _moving &= ~MF_TURN;
     1737                        setDirection(dir);
     1738                        break;
     1739                }
    17061740        default:
    17071741                if (_vm->_game.version <= 2)
    17081742                        startAnimActor(anim / 4);
     
    21672201        }
    21682202}
    21692203
    2170 static const char* v0ActorNames[7] = {
     2204static const char* v0ActorNames[0x19] = {
    21712205        "Syd",
    21722206        "Razor",
    21732207        "Dave",
    21742208        "Michael",
    21752209        "Bernard",
    21762210        "Wendy",
    2177         "Jeff"
     2211        "Jeff",
     2212        "",
     2213        "Dr Fred",
     2214        "Nurse Edna",
     2215        "Weird Ed",
     2216        "Dead Cousin Ted",
     2217        "Purple Tentacle",
     2218        "Green Tentacle",
     2219        "Meteor",
     2220        "Plant",
     2221        "",
     2222        "",
     2223        "",
     2224        "",
     2225        "",
     2226        "",
     2227        "Sandy"
    21782228};
    21792229
    21802230const byte *Actor::getActorName() {
    2181         const byte *ptr;
     2231        const byte *ptr = NULL;
    21822232
    21832233        if (_vm->_game.version == 0) {
    2184                 ptr = (const byte *)v0ActorNames[_number - 1];
     2234                if(_number)
     2235                        ptr = (const byte *)v0ActorNames[_number - 1];
    21852236        } else {
    21862237                ptr = _vm->getResourceAddress(rtActorName, _number);
    21872238        }
  • engines/scumm/actor.h

     
    380380
    381381class ActorC64 : public Actor_v2 {
    382382public:
    383         // FIXME: This flag is never saved, which might lead to broken save states.
     383        // FIXME: These vars are never saved, which might lead to broken save states.
    384384        byte _miscflags;
     385        byte _speaking, _speakingPrev;
     386        byte _costCommand, _costFrame;
    385387
    386388public:
    387         ActorC64(ScummEngine *scumm, int id) : Actor_v2(scumm, id) {}
     389        ActorC64(ScummEngine *scumm, int id) : Actor_v2(scumm, id) { _speaking = _speakingPrev = _costCommand = _costFrame = 0; }
    388390        virtual void initActor(int mode) {
    389391                Actor_v2::initActor(mode);
    390392                if (mode == -1) {
  • engines/scumm/costume.cpp

     
    10401040        if (limb >= 8)
    10411041                return 0;
    10421042
     1043        if(a->_cost.start[limb] == 0xFFFF )
     1044                return 0;
     1045
    10431046        if (limb == 0) {
    10441047                _draw_top = 200;
    10451048                _draw_bottom = 0;
    10461049        }
     1050       
     1051        bool flipped    = (a->_cost.start[limb] & 0x80) != 0;
     1052        byte frameStart = _loaded._frameOffsets[ a->_cost.frame[limb] ];
     1053        byte frame              = _loaded._frameOffsets[ frameStart + a->_cost.curpos[limb] ];
     1054        if(frame == 0xFF)
     1055                return 0;
    10471056
    1048         // TODO:
    1049         // get out how animations are handled
    1050         byte state = a->_moving != 0 ? 0 : 1;
    1051         byte unk1 = (_loaded._animCmds + (state*32) + newDirToOldDir(a->getFacing()) * 8)[limb];
    1052         byte unk2 = _loaded._frameOffsets[_loaded._frameOffsets[limb] + (unk1 & 0x7f)];
    1053         bool flipped = (unk1 & 0x80) != 0;
     1057        byte ptrLow = _loaded._baseptr[frame];
     1058        byte ptrHigh = ptrLow + _loaded._dataOffsets[4];
     1059        int frameOffset = (_loaded._baseptr[ptrHigh] << 8) + _loaded._baseptr[ptrLow + 2];                      // 0x23EF / 0x2400
    10541060
    1055         byte p1 = _loaded._frameOffsets[unk2];
    1056         byte temp1 = _loaded._baseptr[p1];
    1057         byte temp2 = temp1 + _loaded._dataOffsets[4];
    1058         int offL = _loaded._baseptr[temp1 + 2];
    1059         int offH = _loaded._baseptr[temp2];
    1060         int off = (offH << 8) + offL;
     1061        const byte *data = _loaded._baseptr + frameOffset;
    10611062
    1062         const byte *data = _loaded._baseptr + off;
    1063 
    10641063        // Set up the palette data
    10651064        byte palette[4] = { 0, 0, 0, 0 };
    10661065        if (_vm->getCurrentLights() & LIGHTMODE_actor_use_colors) {
     
    10771076        int offsetY = *data++;
    10781077        // these two fields seems to be most times zero
    10791078        // byte6 was one time 255 in one costume I tried
    1080 //      int byte5 = *data++;
    1081 //      int byte6 = *data++;
     1079        int byte5 = *data++;            // 0x1F80                       // This value is never used
     1080        int byte6 = *data++;            // 0x1F86                       // This value is subtracted from ?actor drawy? at 0x2383
    10821081//      debug(3, "byte5: %d", byte5);
    10831082//      debug(3, "byte6: %d", byte6);
    1084         data += 2;
    10851083
    10861084        if (!width || !height)
    10871085                return 0;
     
    10961094                xpos += offsetX * 8;
    10971095        }
    10981096
    1099         // + 4 could be commented, because maybe the _actorX position is
    1100         // wrong, I looked at the scumm-c64 interpreter by lloyd
    1101         // and there Bernhard is directly on the right in the intro
    1102         // but here in ScummVM he is 4 pixel left of the other position.
    1103         xpos += _actorX - (a->_width / 2) + 4;
    1104         ypos += _actorY - _loaded._maxHeight;
     1097        xpos += _actorX - (a->_width / 2);
     1098        ypos += (_actorY - _loaded._maxHeight) + 1;             // +1 as we appear to be 1 pixel away from the original interpreter
    11051099
    11061100        // This code is very similar to procC64()
    11071101        for (int y = 0; y < height; ++y) {
     
    11351129
    11361130        _draw_top = MIN(_draw_top, ypos);
    11371131        _draw_bottom = MAX(_draw_bottom, ypos+height);
    1138         // if +4 above is NOT commented, here "+(flipped ? 4 : 0)" can be commented out
    1139         // and other way round
    1140         _vm->markRectAsDirty(kMainVirtScreen, xpos, xpos+(width*8)/*+(flipped ? 4 : 0)*/, ypos, ypos+height, _actorID);
     1132        _vm->markRectAsDirty(kMainVirtScreen, xpos, xpos+(width*8), ypos, ypos+height, _actorID);
    11411133
    11421134        return 0;
    11431135}
     
    11511143
    11521144void C64CostumeLoader::loadCostume(int id) {
    11531145        const byte *ptr = _vm->getResourceAddress(rtCostume, id);
     1146
    11541147        _id = id;
    11551148        _baseptr = ptr + 9;
    11561149
     
    11651158        _animCmds = _baseptr + READ_LE_UINT16(ptr + 7);
    11661159
    11671160        _maxHeight = 0;
    1168         for (int i = 0; i < 8; ++i) {
    1169                 int pid = _frameOffsets[_frameOffsets[i]];
    1170                 byte p1 = _frameOffsets[pid];
    1171                 byte b = _baseptr[p1];
    1172                 byte c = b + _dataOffsets[4];
    1173                 int offL = _baseptr[b + 2];
    1174                 int offH = _baseptr[c];
    1175                 int off = (offH << 8) + offL;
    1176                 const byte *data = _baseptr + off;
     1161}
    11771162
    1178                 if (data[3] > _maxHeight) {
    1179                         _maxHeight = data[3];           // data[3] is libs's Y offset
     1163void C64CostumeLoader::frameUpdate(ActorC64 *a, int cmd ) {
     1164        byte limbFrames = 0;
     1165
     1166        // Each costume-command has 8 limbs  (0x2622)
     1167        cmd <<= 3;
     1168
     1169        for(int limb = 0, pos = 0; limb < 8; ++limb, pos=0) {
     1170
     1171                // get a limb frames ptr from the costume command
     1172                limbFrames = ((_animCmds + cmd)[limb]);
     1173               
     1174                // Dont change limb if entry is invalid
     1175                if(limbFrames == 0xFF)
     1176                        continue;
     1177
     1178                // Has limb frames ptr changed since last update?
     1179                if(a->_cost.start[limb] == limbFrames)
     1180                        continue;
     1181
     1182                // Set new limb command addresses
     1183                a->_cost.start[limb]    = limbFrames;
     1184                a->_cost.frame[limb]    = _frameOffsets[limb] + (limbFrames & 0x7f);                    // limb animation-frames ptr
     1185
     1186                // Get first entry of a limbs' frames
     1187                byte frameStart = _frameOffsets[ a->_cost.frame[limb] ];
     1188
     1189                // Loop each frame in this limb until we reach the end marker
     1190                while( pos != 0xFF ) {  // This is just so we dont overflow
     1191                        byte frame = _frameOffsets[frameStart + pos];
     1192
     1193                        // Each animation-frame until we find end
     1194                        if( frame == 0xFF )
     1195                                break;
     1196                       
     1197                        //
     1198                        byte ptrLow = _baseptr[frame];
     1199                        byte ptrHigh = ptrLow + _dataOffsets[4];
     1200                        int  frameOffset = (_baseptr[ptrHigh] << 8) + _baseptr[ptrLow + 2];                     // 0x23EF / 0x2400
     1201
     1202                        const byte *data = _baseptr + frameOffset;
     1203                       
     1204                        if(data[3] > _maxHeight)
     1205                                _maxHeight = data[3] + 1;
     1206
     1207                        ++pos;
    11801208                }
     1209
     1210                // Set ending position of limb frames
     1211                a->_cost.end[limb]              = pos-1;
     1212                a->_cost.curpos[limb]   = 0;
    11811213        }
    1182         ++_maxHeight;
    11831214}
    11841215
     1216// based on 0x2BCA, doesn't match disassembly because 'oldDir' variable
     1217// is not the same value as stored in the original interpreter
     1218int C64CostumeLoader::dirToDirStop( int oldDir ) {
     1219        switch(oldDir) {
     1220                case 0:
     1221                        return 4;       // Left
     1222                case 1:
     1223                        return 5;       // Right
     1224                case 2:
     1225                        return 6;       // Face Camera
     1226                case 3:
     1227                        return 7;       // Face Away
     1228        }
     1229        // shouldnt' be reached
     1230        return 4;
     1231}
     1232
     1233void C64CostumeLoader::actorSpeak(ActorC64 *a, int &cmd) {
     1234
     1235        if( (a->_speaking & 0x80) )
     1236                cmd += 0x0C;
     1237        else
     1238                cmd += 0x10;
     1239}
     1240
    11851241void C64CostumeLoader::costumeDecodeData(Actor *a, int frame, uint usemask) {
     1242        ActorC64 *A = (ActorC64*) a;
     1243        int               dir = newDirToOldDir(a->getFacing());
     1244        int               command = dir;
     1245       
     1246        loadCostume( a->_costume );
     1247
     1248        // Enable/Disable speaking flag
     1249        if(frame == a->_talkStartFrame) {
     1250                A->_speaking = 1;
     1251                return;
     1252        }
     1253        if(frame == a->_talkStopFrame) {
     1254                A->_speaking = 0;
     1255                return;
     1256        }
     1257
     1258        // Different command for stand frame
     1259        if(frame == a->_standFrame )
     1260                command = dirToDirStop(dir);   
     1261
     1262        // Update the limb frames
     1263        frameUpdate( A, command );
     1264
     1265        // Keep current command/frame mode
     1266        A->_costCommand = dir;
     1267        A->_costFrame = frame;
     1268
     1269        // Update 'speaking' frames?
     1270        if(A->_speaking) {
     1271                command = dir;  // Incase standing frame was set as cmd
     1272                actorSpeak(A, command);
     1273
     1274                // Update the limb speak frames
     1275                frameUpdate( A, command );
     1276        }
    11861277}
    11871278
    11881279byte C64CostumeLoader::increaseAnims(Actor *a) {
    1189         return 0;
    1190 }
     1280        ActorC64 *A = (ActorC64*) a;
     1281       
     1282        // check if the actor speak flag has changed since last frame increase
     1283        if(  A->_speaking != A->_speakingPrev ) {
     1284                int cmd = A->_costCommand;
     1285                A->_speakingPrev = A->_speaking;
    11911286
    1192 byte C64CostumeLoader::increaseAnim(Actor *a, int slot) {
    1193         return 0;
     1287                // Update to use speak frame
     1288                if(A->_speaking & 0x80) {
     1289                        actorSpeak( A, cmd );
     1290
     1291                } else {
     1292                        // Update to use stand frame
     1293                        if(A->_costFrame == A->_standFrame)
     1294                                cmd = dirToDirStop(cmd);
     1295                }
     1296
     1297                // Update the limb frames
     1298                frameUpdate( A, cmd );
     1299        }
     1300
     1301        // increase each frame pos
     1302        for(int limb=0; limb < 8; ++limb) {
     1303                if( a->_cost.curpos[limb] < a->_cost.end[limb] )
     1304                        a->_cost.curpos[limb]++;
     1305                else
     1306                        a->_cost.curpos[limb] = 0;
     1307        }
     1308
     1309        return 1;
    11941310}
    11951311
    1196 
    11971312} // End of namespace Scumm
  • engines/scumm/costume.h

     
    7373
    7474class C64CostumeLoader : public ClassicCostumeLoader {
    7575public:
    76         C64CostumeLoader(ScummEngine *vm) : ClassicCostumeLoader(vm) {}
     76        C64CostumeLoader(ScummEngine *vm) : ClassicCostumeLoader(vm) { }
    7777        void loadCostume(int id);
    7878        void costumeDecodeData(Actor *a, int frame, uint usemask);
    7979        byte increaseAnims(Actor *a);
    8080
    8181        int _maxHeight;
     82
    8283protected:
    83         byte increaseAnim(Actor *a, int slot);
     84        void    actorSpeak(ActorC64 *a, int &cmd );
     85        int             dirToDirStop( int oldDir );
     86        void    frameUpdate(ActorC64 *A, int cmd );
     87       
    8488};
    8589
    8690class ClassicCostumeRenderer : public BaseCostumeRenderer {
  • engines/scumm/script_v0.cpp

     
    666666        int unk = fetchScriptByte();
    667667        debug(0,"o_animateActor: unk %d", unk);
    668668
    669         Actor *a = derefActor(act, "o_animateActor");
     669        ActorC64 *a = (ActorC64*) derefActor(act, "o_animateActor");
     670
     671        // 0x6993
     672        if(anim == 0xFE) {
     673                a->_speaking = 0x80;    // Enabled, but not switching
     674                return;
     675        }
     676        // 0x69A3
     677        if(anim == 0xFD) {
     678                a->_speaking = 0x00;
     679                return;
     680        }
     681
    670682        a->animateActor(anim);
    671683}
    672684
     
    738750        byte act = getVarOrDirectByte(PARAM_1);
    739751        byte mask = getVarOrDirectByte(PARAM_2);
    740752        byte mod = getVarOrDirectByte(PARAM_3);
     753       
     754        // 0x63ED
     755        if(act >= _numActors)
     756                return;
    741757
    742758        ActorC64 *a = (ActorC64 *)derefActor(act, "o_setActorBitVar");
     759
    743760        if (mod)
    744761                a->_miscflags |= mask;
    745762        else