Ticket #9033: v0_mm_anim_2.patch
File v0_mm_anim_2.patch, 12.9 KB (added by , 15 years ago) |
---|
-
engines/scumm/actor.cpp
527 527 if (_moving & MF_TURN) { 528 528 new_dir = updateActorDirection(false); 529 529 // 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 531 536 setDirection(new_dir); 532 else 537 538 } else 533 539 _moving = 0; 534 540 return; 535 541 } … … 817 823 if (_costume == 0) 818 824 return; 819 825 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 820 836 // Update the costume for the new direction (and mark the actor for redraw) 821 837 aMask = 0x8000; 822 838 for (i = 0; i < 16; i++, aMask >>= 1) { … … 1224 1240 1225 1241 _vm->ensureResourceLoaded(rtCostume, _costume); 1226 1242 1227 if (_vm->_game.version <= 2) {1243 if (_vm->_game.version == 0) { 1228 1244 _cost.reset(); 1229 1245 startAnimActor(_standFrame); 1246 } else if (_vm->_game.version <= 2) { 1247 _cost.reset(); 1248 startAnimActor(_standFrame); 1230 1249 startAnimActor(_initFrame); 1231 1250 startAnimActor(_talkStopFrame); 1232 1251 } else { … … 1380 1399 Actor** end = _sortedActors + numactors; 1381 1400 for (Actor** ac = _sortedActors; ac != end; ++ac) { 1382 1401 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 } 1383 1409 // Draw and animate the actors, except those w/o a costume. 1384 1410 // Note: We could 'optimize' this a little bit by only putting 1385 1411 // actors with a costume into the _sortedActors array in the … … 1572 1598 // we need to shift it 8 pixels to the left 1573 1599 if (_facing == 90) 1574 1600 bcr->_actorX -= 8; 1601 } else if (_vm->_game.version == 0) { 1602 bcr->_actorX += 12; 1575 1603 } else if (_vm->_game.version <= 2) { 1576 1604 // HACK: We have to adjust the x position by one strip (8 pixels) in 1577 1605 // V2 games. However, it is not quite clear to me why. And to fully … … 1703 1731 case 4: // turn to new direction 1704 1732 turnToDirection(dir); 1705 1733 break; 1734 case 64: 1735 if(_vm->_game.version == 0) { 1736 _moving &= ~MF_TURN; 1737 setDirection(dir); 1738 break; 1739 } 1706 1740 default: 1707 1741 if (_vm->_game.version <= 2) 1708 1742 startAnimActor(anim / 4); … … 2167 2201 } 2168 2202 } 2169 2203 2170 static const char* v0ActorNames[ 7] = {2204 static const char* v0ActorNames[0x19] = { 2171 2205 "Syd", 2172 2206 "Razor", 2173 2207 "Dave", 2174 2208 "Michael", 2175 2209 "Bernard", 2176 2210 "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" 2178 2228 }; 2179 2229 2180 2230 const byte *Actor::getActorName() { 2181 const byte *ptr ;2231 const byte *ptr = NULL; 2182 2232 2183 2233 if (_vm->_game.version == 0) { 2184 ptr = (const byte *)v0ActorNames[_number - 1]; 2234 if(_number) 2235 ptr = (const byte *)v0ActorNames[_number - 1]; 2185 2236 } else { 2186 2237 ptr = _vm->getResourceAddress(rtActorName, _number); 2187 2238 } -
engines/scumm/actor.h
380 380 381 381 class ActorC64 : public Actor_v2 { 382 382 public: 383 // FIXME: Th is flag isnever saved, which might lead to broken save states.383 // FIXME: These vars are never saved, which might lead to broken save states. 384 384 byte _miscflags; 385 byte _speaking, _speakingPrev; 386 byte _costCommand, _costFrame; 385 387 386 388 public: 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; } 388 390 virtual void initActor(int mode) { 389 391 Actor_v2::initActor(mode); 390 392 if (mode == -1) { -
engines/scumm/costume.cpp
1040 1040 if (limb >= 8) 1041 1041 return 0; 1042 1042 1043 if(a->_cost.start[limb] == 0xFFFF ) 1044 return 0; 1045 1043 1046 if (limb == 0) { 1044 1047 _draw_top = 200; 1045 1048 _draw_bottom = 0; 1046 1049 } 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; 1047 1056 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 1054 1060 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; 1061 1062 1062 const byte *data = _loaded._baseptr + off;1063 1064 1063 // Set up the palette data 1065 1064 byte palette[4] = { 0, 0, 0, 0 }; 1066 1065 if (_vm->getCurrentLights() & LIGHTMODE_actor_use_colors) { … … 1077 1076 int offsetY = *data++; 1078 1077 // these two fields seems to be most times zero 1079 1078 // 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 1082 1081 // debug(3, "byte5: %d", byte5); 1083 1082 // debug(3, "byte6: %d", byte6); 1084 data += 2;1085 1083 1086 1084 if (!width || !height) 1087 1085 return 0; … … 1096 1094 xpos += offsetX * 8; 1097 1095 } 1098 1096 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 1105 1099 1106 1100 // This code is very similar to procC64() 1107 1101 for (int y = 0; y < height; ++y) { … … 1135 1129 1136 1130 _draw_top = MIN(_draw_top, ypos); 1137 1131 _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); 1141 1133 1142 1134 return 0; 1143 1135 } … … 1151 1143 1152 1144 void C64CostumeLoader::loadCostume(int id) { 1153 1145 const byte *ptr = _vm->getResourceAddress(rtCostume, id); 1146 1154 1147 _id = id; 1155 1148 _baseptr = ptr + 9; 1156 1149 … … 1165 1158 _animCmds = _baseptr + READ_LE_UINT16(ptr + 7); 1166 1159 1167 1160 _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 } 1177 1162 1178 if (data[3] > _maxHeight) { 1179 _maxHeight = data[3]; // data[3] is libs's Y offset 1163 void 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; 1180 1208 } 1209 1210 // Set ending position of limb frames 1211 a->_cost.end[limb] = pos-1; 1212 a->_cost.curpos[limb] = 0; 1181 1213 } 1182 ++_maxHeight;1183 1214 } 1184 1215 1216 // based on 0x2BCA, doesn't match disassembly because 'oldDir' variable 1217 // is not the same value as stored in the original interpreter 1218 int 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 1233 void C64CostumeLoader::actorSpeak(ActorC64 *a, int &cmd) { 1234 1235 if( (a->_speaking & 0x80) ) 1236 cmd += 0x0C; 1237 else 1238 cmd += 0x10; 1239 } 1240 1185 1241 void 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 } 1186 1277 } 1187 1278 1188 1279 byte 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; 1191 1286 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; 1194 1310 } 1195 1311 1196 1197 1312 } // End of namespace Scumm -
engines/scumm/costume.h
73 73 74 74 class C64CostumeLoader : public ClassicCostumeLoader { 75 75 public: 76 C64CostumeLoader(ScummEngine *vm) : ClassicCostumeLoader(vm) { }76 C64CostumeLoader(ScummEngine *vm) : ClassicCostumeLoader(vm) { } 77 77 void loadCostume(int id); 78 78 void costumeDecodeData(Actor *a, int frame, uint usemask); 79 79 byte increaseAnims(Actor *a); 80 80 81 81 int _maxHeight; 82 82 83 protected: 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 84 88 }; 85 89 86 90 class ClassicCostumeRenderer : public BaseCostumeRenderer { -
engines/scumm/script_v0.cpp
666 666 int unk = fetchScriptByte(); 667 667 debug(0,"o_animateActor: unk %d", unk); 668 668 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 670 682 a->animateActor(anim); 671 683 } 672 684 … … 738 750 byte act = getVarOrDirectByte(PARAM_1); 739 751 byte mask = getVarOrDirectByte(PARAM_2); 740 752 byte mod = getVarOrDirectByte(PARAM_3); 753 754 // 0x63ED 755 if(act >= _numActors) 756 return; 741 757 742 758 ActorC64 *a = (ActorC64 *)derefActor(act, "o_setActorBitVar"); 759 743 760 if (mod) 744 761 a->_miscflags |= mask; 745 762 else