[Scummvm-git-logs] scummvm master -> f187dfe04486dea30b1de9c723171464811061a8
mduggan
mgithub at guarana.org
Mon Nov 30 23:17:35 UTC 2020
This automated email contains information about 10 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
93c7fd831f ULTIMA8: Correct 16-dir movement tables
c32a594a24 ULTIMA8: Tiny cleanup - const and whitespace
cb7a2bea13 ULTIMA8: Add assertion about direction being valid
7a08388180 ULTIMA8: Add some more known animation flags
33159f447f ULTIMA8: Add crusader detonate bomb key
01c520c81a ULTIMA8: Add crusader isKneeling intrinsic
394455e9eb ULTIMA8: Process crusader usecode anims correctly
6ead0fedf8 ULTIMA8: Update gravity process for Crusader
c6c0f42d4b ULTIMA8: Make I_avatarStoleSomething behavior more closely match original
f187dfe044 ULTIMA8: UC machine updates from disassembly
Commit: 93c7fd831f22875cf6275e90e61ca73879667d4e
https://github.com/scummvm/scummvm/commit/93c7fd831f22875cf6275e90e61ca73879667d4e
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-01T08:13:48+09:00
Commit Message:
ULTIMA8: Correct 16-dir movement tables
Changed paths:
engines/ultima/ultima8/misc/direction_util.h
diff --git a/engines/ultima/ultima8/misc/direction_util.h b/engines/ultima/ultima8/misc/direction_util.h
index 7c9c71f2b5..927f9dab21 100644
--- a/engines/ultima/ultima8/misc/direction_util.h
+++ b/engines/ultima/ultima8/misc/direction_util.h
@@ -36,7 +36,11 @@ namespace Ultima8 {
inline int Direction_XFactor(Direction dir) {
static const int _x_fact[] = { 0, +1, +1, +1, 0, -1, -1, -1 };
- static const int _x_fact16[] = { 0, +1, +2, +2, +2, +2, +2, +1, 0, -1, -2, -2, -2, -2, -2, -1 };
+ //static const int _x_fact16[] = { 0, +1, +2, +2, +2, +2, +2, +1, 0, -1, -2, -2, -2, -2, -2, -1 };
+ // TODO: AnimPrimativeProcess uses the below table.. what's the other table for?
+ // (same for y)
+ static const int _x_fact16[] = { 0, +1, +1, +2, +1, +2, +1, +1, 0, -1, -1, -2, -1, -2, -1, -1 };
+
if (GAME_IS_U8)
return _x_fact[(int)dir / 2];
else
@@ -45,7 +49,9 @@ inline int Direction_XFactor(Direction dir) {
inline int Direction_YFactor(Direction dir) {
static const int _y_fact[] = { -1, -1, 0, +1, +1, +1, 0, -1 };
- static const int _y_fact16[] = { -2, -2, -2, -1, 0, +1, +2, +2, +2, +2, +2, +1, 0, -1, -2, -2 };
+ //static const int _y_fact16[] = { -2, -2, -2, -1, 0, +1, +2, +2, +2, +2, +2, +1, 0, -1, -2, -2 };
+ static const int _y_fact16[] = { -1, -2, -1, -1, 0, +1, +1, +2, +1, +2, +1, +1, 0, -1, -1, -2 };
+
if (GAME_IS_U8)
return _y_fact[(int)dir / 2];
else
@@ -174,8 +180,14 @@ inline Direction Direction_OneRight(Direction dir, DirectionMode mode) {
}
inline Direction Direction_TurnByDelta(Direction dir, int delta, DirectionMode mode) {
- assert(delta == 1 || delta == -1);
- return delta == 1 ? Direction_OneRight(dir, mode) : Direction_OneLeft(dir, mode);
+ if (delta > 0) {
+ for (int i = 0; i < delta; i++)
+ dir = Direction_OneRight(dir, mode);
+ } else if (delta < 0) {
+ for (int i = 0; i < -delta; i++)
+ dir = Direction_OneLeft(dir, mode);
+ }
+ return dir;
}
//! Get a turn delta (-1 for left, +1 for right) to turn the fastest
Commit: c32a594a2481b1e9984b512a680522e73c097e67
https://github.com/scummvm/scummvm/commit/c32a594a2481b1e9984b512a680522e73c097e67
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-01T08:13:48+09:00
Commit Message:
ULTIMA8: Tiny cleanup - const and whitespace
Changed paths:
engines/ultima/ultima8/world/actors/main_actor.cpp
diff --git a/engines/ultima/ultima8/world/actors/main_actor.cpp b/engines/ultima/ultima8/world/actors/main_actor.cpp
index 95201d8fbd..f9c00ae945 100644
--- a/engines/ultima/ultima8/world/actors/main_actor.cpp
+++ b/engines/ultima/ultima8/world/actors/main_actor.cpp
@@ -592,11 +592,12 @@ void MainActor::getWeaponOverlay(const WeaponOverlayFrame *&frame, uint32 &shape
shape = weaponinfo->_overlayShape;
- WpnOvlayDat *wpnovlay = GameData::get_instance()->getWeaponOverlay();
+ const WpnOvlayDat *wpnovlay = GameData::get_instance()->getWeaponOverlay();
frame = wpnovlay->getOverlayFrame(action, weaponinfo->_overlayType,
_direction, _animFrame);
- if (frame == 0) shape = 0;
+ if (frame == nullptr)
+ shape = 0;
}
int16 MainActor::getMaxEnergy() {
Commit: cb7a2bea13b2321a723287dd30b3f0e3ad317b13
https://github.com/scummvm/scummvm/commit/cb7a2bea13b2321a723287dd30b3f0e3ad317b13
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-01T08:13:48+09:00
Commit Message:
ULTIMA8: Add assertion about direction being valid
Changed paths:
engines/ultima/ultima8/world/actors/weapon_overlay.h
diff --git a/engines/ultima/ultima8/world/actors/weapon_overlay.h b/engines/ultima/ultima8/world/actors/weapon_overlay.h
index 48732e2acf..44fb6f7cdd 100644
--- a/engines/ultima/ultima8/world/actors/weapon_overlay.h
+++ b/engines/ultima/ultima8/world/actors/weapon_overlay.h
@@ -57,6 +57,8 @@ struct AnimWeaponOverlay {
if (type >= _overlay.size())
return nullptr;
+ assert(direction != dir_invalid);
+
uint32 diroff;
if (_overlay[type]._dirCount == 8)
diroff = static_cast<uint32>(direction) / 2;
Commit: 7a08388180ad808905e9d568de4beb13f218e90c
https://github.com/scummvm/scummvm/commit/7a08388180ad808905e9d568de4beb13f218e90c
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-01T08:13:48+09:00
Commit Message:
ULTIMA8: Add some more known animation flags
Changed paths:
engines/ultima/ultima8/world/actors/anim_action.h
diff --git a/engines/ultima/ultima8/world/actors/anim_action.h b/engines/ultima/ultima8/world/actors/anim_action.h
index f6dcf78db5..0e7ddc218f 100644
--- a/engines/ultima/ultima8/world/actors/anim_action.h
+++ b/engines/ultima/ultima8/world/actors/anim_action.h
@@ -118,10 +118,12 @@ public:
AAF_LOOPING = 0x0004,
AAF_UNSTOPPABLE = 0x0008,
AAF_LOOPING2 = 0x0010, // CHECKME: guessing at this flag
+ AAF_LOOPING3 = 0x0040, // CHECKME: Crusader triggers a new anim in the terminate if this flag is set and the start point was null
AAF_HANGING = 0x0080,
+ AAF_CRUS_ROTATED = 0x1000,
AAF_CRUS_16DIRS = 0x4000, // Crusader
AAF_DESTROYACTOR = 0x8000, // destroy actor after animation finishes
- AAF_UNKFLAGS = 0x3F60
+ AAF_UNKFLAGS = 0x3F20
};
private:
Commit: 33159f447fde38e06c5ad7c3f8bf3e437781867e
https://github.com/scummvm/scummvm/commit/33159f447fde38e06c5ad7c3f8bf3e437781867e
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-01T08:13:48+09:00
Commit Message:
ULTIMA8: Add crusader detonate bomb key
Changed paths:
engines/ultima/ultima8/meta_engine.cpp
engines/ultima/ultima8/meta_engine.h
engines/ultima/ultima8/misc/debugger.cpp
engines/ultima/ultima8/misc/debugger.h
engines/ultima/ultima8/world/actors/main_actor.cpp
engines/ultima/ultima8/world/actors/main_actor.h
diff --git a/engines/ultima/ultima8/meta_engine.cpp b/engines/ultima/ultima8/meta_engine.cpp
index 0e27560cd2..2a82b11893 100644
--- a/engines/ultima/ultima8/meta_engine.cpp
+++ b/engines/ultima/ultima8/meta_engine.cpp
@@ -80,6 +80,7 @@ static const KeybindingRecord CRUSADER_KEYS[] = {
{ ACTION_NEXT_INVENTORY, "NEXT_INVENTORY", "Next Inventory Item", "MainActor::nextInvItem", nullptr, "i", nullptr },
{ ACTION_USE_INVENTORY, "USE_INVENTORY", "Use Inventroy Item", "MainActor::useInventoryItem", nullptr, "u", nullptr },
{ ACTION_USE_MEDIKIT, "USE_MEDIKIT", "Use Medical Kit", "MainActor::useMedikit", nullptr, "M", nullptr },
+ { ACTION_DETONATE_BOMB, "DETONATE_BOMB", "Detonate Bomb", "MainActor::detonateBomb", nullptr, "b", nullptr },
{ ACTION_SELECT_ITEMS, "SELECT_ITEM", "Select Item", "ItemSelectionProcess::startSelection", nullptr, "s", nullptr },
{ ACTION_USE_SELECTION, "USE_SELECTION", "Use Selection", "ItemSelectionProcess::useSelectedItem", nullptr, "RETURN", nullptr },
{ ACTION_ATTACK, "ATTACK", "Attack", "AvatarMoverProcess::tryAttack", nullptr, "SPACE", nullptr },
diff --git a/engines/ultima/ultima8/meta_engine.h b/engines/ultima/ultima8/meta_engine.h
index 9f0054a54a..ad6b44d659 100644
--- a/engines/ultima/ultima8/meta_engine.h
+++ b/engines/ultima/ultima8/meta_engine.h
@@ -29,17 +29,21 @@ namespace Ultima {
namespace Ultima8 {
enum KeybindingAction {
- ACTION_QUICKSAVE, ACTION_SAVE, ACTION_LOAD, ACTION_BEDROLL, ACTION_COMBAT, ACTION_BACKPACK,
- ACTION_KEYRING, ACTION_MINIMAP, ACTION_RECALL, ACTION_INVENTORY, ACTION_NEXT_WEAPON,
- ACTION_NEXT_INVENTORY, ACTION_USE_INVENTORY, ACTION_USE_MEDIKIT, ACTION_SELECT_ITEMS,
- ACTION_USE_SELECTION, ACTION_MENU, ACTION_CLOSE_GUMPS, ACTION_HIGHLIGHT_ITEMS,
- ACTION_TOGGLE_TOUCHING, ACTION_JUMP, ACTION_TURN_LEFT, ACTION_TURN_RIGHT,
- ACTION_MOVE_FORWARD, ACTION_MOVE_BACK, ACTION_MOVE_UP, ACTION_MOVE_DOWN, ACTION_MOVE_LEFT,
- ACTION_MOVE_RIGHT, ACTION_MOVE_RUN, ACTION_MOVE_STEP, ACTION_ATTACK, ACTION_CAMERA_AVATAR,
+ ACTION_QUICKSAVE, ACTION_SAVE, ACTION_LOAD, ACTION_BEDROLL, ACTION_COMBAT,
+ ACTION_BACKPACK, ACTION_KEYRING, ACTION_MINIMAP, ACTION_RECALL,
+ ACTION_INVENTORY, ACTION_NEXT_WEAPON, ACTION_NEXT_INVENTORY,
+ ACTION_USE_INVENTORY, ACTION_USE_MEDIKIT, ACTION_SELECT_ITEMS,
+ ACTION_DETONATE_BOMB, ACTION_USE_SELECTION, ACTION_MENU,
+ ACTION_CLOSE_GUMPS, ACTION_HIGHLIGHT_ITEMS, ACTION_TOGGLE_TOUCHING,
+ ACTION_JUMP, ACTION_TURN_LEFT, ACTION_TURN_RIGHT, ACTION_MOVE_FORWARD,
+ ACTION_MOVE_BACK, ACTION_MOVE_UP, ACTION_MOVE_DOWN, ACTION_MOVE_LEFT,
+ ACTION_MOVE_RIGHT, ACTION_MOVE_RUN, ACTION_MOVE_STEP, ACTION_ATTACK,
+ ACTION_CAMERA_AVATAR,
- ACTION_CHEAT_MODE, ACTION_CLIPPING, ACTION_DEC_SORT_ORDER, ACTION_INC_SORT_ORDER,
- ACTION_QUICK_MOVE_ASCEND, ACTION_QUICK_MOVE_DESCEND,
- ACTION_QUICK_MOVE_UP, ACTION_QUICK_MOVE_DOWN, ACTION_QUICK_MOVE_LEFT, ACTION_QUICK_MOVE_RIGHT,
+ ACTION_CHEAT_MODE, ACTION_CLIPPING, ACTION_DEC_SORT_ORDER,
+ ACTION_INC_SORT_ORDER, ACTION_QUICK_MOVE_ASCEND, ACTION_QUICK_MOVE_DESCEND,
+ ACTION_QUICK_MOVE_UP, ACTION_QUICK_MOVE_DOWN, ACTION_QUICK_MOVE_LEFT,
+ ACTION_QUICK_MOVE_RIGHT,
#ifndef RELEASE_BUILD
ACTION_TOGGLE_PAINT, ACTION_ENGINE_STATS, ACTION_FRAME_BY_FRAME,
diff --git a/engines/ultima/ultima8/misc/debugger.cpp b/engines/ultima/ultima8/misc/debugger.cpp
index f2abb028c9..dda3bf0442 100644
--- a/engines/ultima/ultima8/misc/debugger.cpp
+++ b/engines/ultima/ultima8/misc/debugger.cpp
@@ -153,6 +153,7 @@ Debugger::Debugger() : Shared::Debugger() {
registerCmd("MainActor::nextInvItem", WRAP_METHOD(Debugger, cmdNextInventory));
registerCmd("MainActor::useInventoryItem", WRAP_METHOD(Debugger, cmdUseInventoryItem));
registerCmd("MainActor::useMedikit", WRAP_METHOD(Debugger, cmdUseMedikit));
+ registerCmd("MainActor::detonateBomb", WRAP_METHOD(Debugger, cmdDetonateBomb));
registerCmd("MainActor::toggleCombat", WRAP_METHOD(Debugger, cmdToggleCombat));
registerCmd("ItemSelectionProcess::startSelection", WRAP_METHOD(Debugger, cmdStartSelection));
registerCmd("ItemSelectionProcess::useSelectedItem", WRAP_METHOD(Debugger, cmdUseSelection));
@@ -1157,6 +1158,16 @@ bool Debugger::cmdUseMedikit(int argc, const char **argv) {
return false;
}
+bool Debugger::cmdDetonateBomb(int argc, const char **argv) {
+ if (Ultima8Engine::get_instance()->isAvatarInStasis()) {
+ debugPrintf("Can't detonate bomb: avatarInStasis\n");
+ return false;
+ }
+ MainActor *av = getMainActor();
+ av->detonateBomb();
+ return false;
+}
+
bool Debugger::cmdUseInventory(int argc, const char **argv) {
if (Ultima8Engine::get_instance()->isAvatarInStasis()) {
debugPrintf("Can't use inventory: avatarInStasis\n");
diff --git a/engines/ultima/ultima8/misc/debugger.h b/engines/ultima/ultima8/misc/debugger.h
index 325c956dbb..fe1616318a 100644
--- a/engines/ultima/ultima8/misc/debugger.h
+++ b/engines/ultima/ultima8/misc/debugger.h
@@ -222,6 +222,7 @@ private:
bool cmdToggleCombat(int argc, const char **argv);
bool cmdUseInventoryItem(int argc, const char **argv);
bool cmdUseMedikit(int argc, const char **argv);
+ bool cmdDetonateBomb(int argc, const char **argv);
bool cmdStartSelection(int argc, const char **argv);
bool cmdUseSelection(int argc, const char **argv);
diff --git a/engines/ultima/ultima8/world/actors/main_actor.cpp b/engines/ultima/ultima8/world/actors/main_actor.cpp
index f9c00ae945..3e20a54b3b 100644
--- a/engines/ultima/ultima8/world/actors/main_actor.cpp
+++ b/engines/ultima/ultima8/world/actors/main_actor.cpp
@@ -933,6 +933,20 @@ int MainActor::receiveShieldHit(int damage, uint16 damage_type) {
return damage;
}
+void MainActor::detonateBomb() {
+ // search area for shape 0x55F (1375) - DETPAC
+ UCList uclist(2);
+ LOOPSCRIPT(script, LS_SHAPE_EQUAL(0x55F));
+ CurrentMap *currentmap = World::get_instance()->getCurrentMap();
+ currentmap->areaSearch(&uclist, script, sizeof(script), nullptr,
+ 0x800, true, _x, _y);
+ for (unsigned int i = 0; i < uclist.getSize(); ++i) {
+ Item *founditem = getItem(uclist.getuint16(i));
+ founditem->callUsecodeEvent_use();
+ }
+ return;
+}
+
} // End of namespace Ultima8
} // End of namespace Ultima
diff --git a/engines/ultima/ultima8/world/actors/main_actor.h b/engines/ultima/ultima8/world/actors/main_actor.h
index 31866f684e..76f3b50ead 100644
--- a/engines/ultima/ultima8/world/actors/main_actor.h
+++ b/engines/ultima/ultima8/world/actors/main_actor.h
@@ -139,6 +139,9 @@ public:
//! Check if we can absorb a hit with the shield. Returns the modified damage value.
int receiveShieldHit(int damage, uint16 damage_type) override;
+ //! Detonate used bomb
+ void detonateBomb();
+
bool loadData(Common::ReadStream *rs, uint32 version);
void saveData(Common::WriteStream *ws) override;
Commit: 01c520c81a2f372ae34d1f4d4ffdbd2033730e8c
https://github.com/scummvm/scummvm/commit/01c520c81a2f372ae34d1f4d4ffdbd2033730e8c
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-01T08:13:48+09:00
Commit Message:
ULTIMA8: Add crusader isKneeling intrinsic
Changed paths:
engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
engines/ultima/ultima8/usecode/remorse_intrinsics.h
engines/ultima/ultima8/world/actors/actor.cpp
engines/ultima/ultima8/world/actors/actor.h
diff --git a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
index ca50c3e7c3..1f652fa083 100644
--- a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
+++ b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
@@ -95,9 +95,9 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
"void Item::I_pop(Item *)", // same code as U8
"void Item::I_andStatus(Item *, uint16 status)", // part of same coff set 01A, 031, 069, 06E, 099, 0B2, 0BF, 0C1, 0C3, 0E9, 0FC, 101, 104, 106, 108, 10A, 10C, 10E, 110, 114, 117, 11A, 128, 132
"void Item::I_receiveHit(Item *, other, dir, damage, damagetype)", // based on disasm
- "byte Actor::I_isBusy(4 bytes)", // same code as U8
+ "byte Actor::I_isBusy(Actor *)", // same code as U8
"int16 Item::I_getDirFromTo16(x1, y1, x2, y2)",
- "byte Actor::I_isKneeling(Item *)",
+ "byte Actor::I_isKneeling(Actor *)",
"int16 Actor::I_doAnim(12 bytes)", // v. similar code to U8
"byte MainActor::I_addItemCru(4 bytes)", // same coff as 0B8
"void AudioProcess::I_stopSFXCru(Item *, int16 sndno)",
diff --git a/engines/ultima/ultima8/usecode/remorse_intrinsics.h b/engines/ultima/ultima8/usecode/remorse_intrinsics.h
index 2a03054c04..08994a618d 100644
--- a/engines/ultima/ultima8/usecode/remorse_intrinsics.h
+++ b/engines/ultima/ultima8/usecode/remorse_intrinsics.h
@@ -91,7 +91,7 @@ Intrinsic RemorseIntrinsics[] = {
Item::I_receiveHit, // void Intrinsic032(12 bytes)
Actor::I_isBusy, // int Intrinsic033(4 bytes)
Item::I_getDirFromTo16,
- 0, // TODO: Actor::I_getSomeFlagProbablyCrouch(Actor *)
+ Actor::I_isKneeling,
Actor::I_doAnim, // void Intrinsic036(12 bytes)
MainActor::I_addItemCru, // int Intrinsic037(4 bytes)
AudioProcess::I_stopSFXCru, // takes Item *, sndno (from disasm)
diff --git a/engines/ultima/ultima8/world/actors/actor.cpp b/engines/ultima/ultima8/world/actors/actor.cpp
index 1f36c6385d..4c2768efe9 100644
--- a/engines/ultima/ultima8/world/actors/actor.cpp
+++ b/engines/ultima/ultima8/world/actors/actor.cpp
@@ -2385,5 +2385,12 @@ uint32 Actor::I_turnToward(const uint8 *args, unsigned int /*argsize*/) {
return actor->turnTowardDir(Direction_FromUsecodeDir(dir));
}
+uint32 Actor::I_isKneeling(const uint8 *args, unsigned int /*argsize*/) {
+ ARG_ACTOR_FROM_PTR(actor);
+ if (!actor) return 0;
+
+ return actor->hasFlags(ACT_KNEELING) ? 1 : 0;
+}
+
} // End of namespace Ultima8
} // End of namespace Ultima
diff --git a/engines/ultima/ultima8/world/actors/actor.h b/engines/ultima/ultima8/world/actors/actor.h
index eb9e1f56ef..5a97a25bc9 100644
--- a/engines/ultima/ultima8/world/actors/actor.h
+++ b/engines/ultima/ultima8/world/actors/actor.h
@@ -348,6 +348,7 @@ public:
INTRINSIC(I_getLastActivityNo);
INTRINSIC(I_getCurrentActivityNo);
INTRINSIC(I_turnToward);
+ INTRINSIC(I_isKneeling);
enum ActorFlags {
ACT_INVINCIBLE = 0x000001, // flags from npcdata byte 0x1B
Commit: 394455e9ebe85d6006aa5ab52146a6328ae96d50
https://github.com/scummvm/scummvm/commit/394455e9ebe85d6006aa5ab52146a6328ae96d50
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-01T08:13:48+09:00
Commit Message:
ULTIMA8: Process crusader usecode anims correctly
Changed paths:
engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
engines/ultima/ultima8/graphics/anim_dat.cpp
engines/ultima/ultima8/world/actors/actor.cpp
engines/ultima/ultima8/world/actors/animation.h
diff --git a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
index 1f652fa083..130fa293b1 100644
--- a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
+++ b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
@@ -55,7 +55,7 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
"int16 Actor::I_GetNPCDataField0x63_00B(Actor *)", // Some unknown value set for NPCs based on Q of egg.
"void Ultima8Engine::I_setAvatarInStasis(int)",
"byte Item::I_getDirToItem(Item *, itemno)", // based on disasm
- "int16 Actor::I_turnToward(Actor *, direction, unk)", // TODO: work out what unk is
+ "int16 Actor::I_turnToward(Actor *, direction, dir_16)",
"void I_playFlic(void), int16 I_playFlic(Item *, char *name, int16 sizex, int16 sizey)",
// 0010
"int16 Item::I_getQLo(Item *)", // same as 02B based on same coff as 02B, 066, 084, 0A1, 0AE, 0D9, 0EA
diff --git a/engines/ultima/ultima8/graphics/anim_dat.cpp b/engines/ultima/ultima8/graphics/anim_dat.cpp
index b264a2f0be..8b56e93156 100644
--- a/engines/ultima/ultima8/graphics/anim_dat.cpp
+++ b/engines/ultima/ultima8/graphics/anim_dat.cpp
@@ -75,6 +75,7 @@ uint32 AnimDat::getActionNumberForSequence(Animation::Sequence action, const Act
altfire = (wpninfo && (wpninfo->_overlayShape == 0x36e || wpninfo->_overlayShape == 0x33b));
}
+ //
// For crusader the actions have different IDs. Rather than
// rewrite everything, we just translate them here for all the ones
// we want to use programmatically. There are more, but they are
@@ -82,7 +83,13 @@ uint32 AnimDat::getActionNumberForSequence(Animation::Sequence action, const Act
//
// We also translate based on weapon. See the function at 1128:2104
//
- // TODO: Also handle kneeling weapon animations
+ // First, if the animation is >= 0x1000 then it's from the usecode -
+ // use directly and don't translate.
+ //
+ const uint32 action_int = static_cast<uint32>(action);
+ if (action_int >= 0x1000)
+ return action_int - 0x1000;
+
switch (action) {
case Animation::stand:
return 0;
@@ -130,12 +137,8 @@ uint32 AnimDat::getActionNumberForSequence(Animation::Sequence action, const Act
return 0;
case Animation::lookRight:
return 0;
- case Animation::teleportInReplacement:
- return Animation::teleportIn;
- case Animation::teleportOutReplacement:
- return Animation::teleportOut;
default:
- return static_cast<uint32>(action);
+ return action_int;
}
}
}
diff --git a/engines/ultima/ultima8/world/actors/actor.cpp b/engines/ultima/ultima8/world/actors/actor.cpp
index 4c2768efe9..d4ce99005a 100644
--- a/engines/ultima/ultima8/world/actors/actor.cpp
+++ b/engines/ultima/ultima8/world/actors/actor.cpp
@@ -1679,17 +1679,12 @@ uint32 Actor::I_doAnim(const uint8 *args, unsigned int /*argsize*/) {
if (!actor) return 0;
//
- // HACK: In Crusader, anims 32 and 33 are teleport in/out. In U8 they are
- // turn left/right. We want to remap those numbers in most cases, but when
- // they come out of usecode we don't want to remap them. Here we give them
- // temporary values so we can set them back later.
+ // HACK: In Crusader, we do translation on the animations so we want to remap
+ // most of them, but for direct commands from the usecode we add 0x1000 for
+ // no remapping
//
if (GAME_IS_CRUSADER) {
- Animation::Sequence seq = static_cast<Animation::Sequence>(anim);
- if (seq == Animation::teleportIn)
- anim = static_cast<uint16>(Animation::teleportInReplacement);
- else if (seq == Animation::teleportOut)
- anim = static_cast<uint16>(Animation::teleportOutReplacement);
+ anim += 0x1000;
}
return actor->doAnim(static_cast<Animation::Sequence>(anim), Direction_FromUsecodeDir(dir));
@@ -2379,10 +2374,18 @@ uint32 Actor::I_turnToward(const uint8 *args, unsigned int /*argsize*/) {
if (!actor) return 0;
ARG_UINT16(dir);
- ARG_UINT16(unk);
- warning("Actor::I_turnToward: Ignoring unknown param %d", unk);
+ ARG_UINT16(dir16);
- return actor->turnTowardDir(Direction_FromUsecodeDir(dir));
+ Direction newdir = Direction_FromUsecodeDir(dir);
+ Direction curdir = actor->getDir();
+ Direction oneleft = Direction_OneLeft(curdir, dirmode_16dirs);
+ Direction oneright = Direction_OneRight(curdir, dirmode_16dirs);
+
+ if (curdir == newdir ||
+ (!dir16 && (newdir == oneleft || newdir == oneright)))
+ return 0;
+
+ return actor->turnTowardDir(newdir);
}
uint32 Actor::I_isKneeling(const uint8 *args, unsigned int /*argsize*/) {
diff --git a/engines/ultima/ultima8/world/actors/animation.h b/engines/ultima/ultima8/world/actors/animation.h
index 9b9ba3feb7..739cc36a7b 100644
--- a/engines/ultima/ultima8/world/actors/animation.h
+++ b/engines/ultima/ultima8/world/actors/animation.h
@@ -136,8 +136,8 @@ enum Sequence {
slowCombatRollLeft = 61,
slowCombatRollRight = 62,
finishFiring = 63,
- teleportInReplacement = 0x1020, //!< See notes in Actor::I_doAnim
- teleportOutReplacement = 0x1021 //!< See notes in Actor::I_doAnim
+ teleportInReplacement = 0x1020, //!< See notes in Actor::receiveHitCru
+ teleportOutReplacement = 0x1021 //!< See notes in Actor::receiveHitCru
};
enum Result {
Commit: 6ead0fedf8ee616e7a25d6a461ab537b134dfc24
https://github.com/scummvm/scummvm/commit/6ead0fedf8ee616e7a25d6a461ab537b134dfc24
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-01T08:13:48+09:00
Commit Message:
ULTIMA8: Update gravity process for Crusader
Changed paths:
engines/ultima/ultima8/world/gravity_process.cpp
engines/ultima/ultima8/world/gravity_process.h
engines/ultima/ultima8/world/item.cpp
diff --git a/engines/ultima/ultima8/world/gravity_process.cpp b/engines/ultima/ultima8/world/gravity_process.cpp
index 8caeb3c423..66f017def6 100644
--- a/engines/ultima/ultima8/world/gravity_process.cpp
+++ b/engines/ultima/ultima8/world/gravity_process.cpp
@@ -20,13 +20,16 @@
*
*/
+#include "ultima/ultima8/world/gravity_process.h"
+
+#include "ultima/ultima8/audio/audio_process.h"
+#include "ultima/ultima8/kernel/kernel.h"
+#include "ultima/ultima8/kernel/core_app.h"
#include "ultima/ultima8/misc/pent_include.h"
#include "ultima/ultima8/misc/direction.h"
-#include "ultima/ultima8/world/gravity_process.h"
#include "ultima/ultima8/world/actors/actor.h"
-#include "ultima/ultima8/audio/audio_process.h"
+#include "ultima/ultima8/world/actors/actor_anim_process.h"
#include "ultima/ultima8/world/current_map.h"
-#include "ultima/ultima8/kernel/kernel.h"
#include "ultima/ultima8/world/world.h"
#include "ultima/ultima8/world/get_object.h"
@@ -302,39 +305,81 @@ void GravityProcess::fallStopped() {
Actor *actor = getActor(_itemNum);
if (actor && !actor->isDead()) {
int height = actor->getFallStart() - actor->getZ();
+ if (GAME_IS_U8)
+ actorFallStoppedU8(actor, height);
+ else
+ actorFallStoppedCru(actor, height);
+ }
+}
- if (height >= 80) {
- int damage = 0;
+void GravityProcess::actorFallStoppedU8(Actor *actor, int height) {
+ if (height >= 80) {
+ int damage = 0;
- if (height < 104) {
- // medium fall: take some damage
- damage = (height - 72) / 4;
- } else {
- // high fall: die
- damage = actor->getHP();
- }
+ if (height < 104) {
+ // medium fall: take some damage
+ damage = (height - 72) / 4;
+ } else {
+ // high fall: die
+ damage = actor->getHP();
+ }
- actor->receiveHit(0, actor->getDir(), damage,
- WeaponInfo::DMG_FALLING | WeaponInfo::DMG_PIERCE);
+ actor->receiveHit(0, actor->getDir(), damage,
+ WeaponInfo::DMG_FALLING | WeaponInfo::DMG_PIERCE);
- // 'ooof'
- AudioProcess *audioproc = AudioProcess::get_instance();
- if (audioproc) audioproc->playSFX(51, 250, _itemNum, 0); // CONSTANT!
- }
+ // 'ooof'
+ AudioProcess *audioproc = AudioProcess::get_instance();
+ if (audioproc) audioproc->playSFX(51, 250, _itemNum, 0); // CONSTANT!
+ }
- if (!actor->isDead() && actor->getLastAnim() != Animation::die) {
+ if (!actor->isDead() && actor->getLastAnim() != Animation::die) {
+ Kernel *kernel = Kernel::get_instance();
- // play land animation, overriding other animations
- Kernel::get_instance()->killProcesses(_itemNum, 0xF0, false); // CONSTANT!
- ProcId lpid = actor->doAnim(Animation::land, dir_current);
+ // play land animation, overriding other animations
+ kernel->killProcesses(_itemNum, ActorAnimProcess::ACTOR_ANIM_PROC_TYPE, false); // CONSTANT!
+ ProcId lpid = actor->doAnim(Animation::land, dir_current);
- if (actor->isInCombat()) {
- // need to get back to a combat stance to prevent weapon from
- // being drawn again
- ProcId spid = actor->doAnim(Animation::combatStand, dir_current);
- Process *sp = Kernel::get_instance()->getProcess(spid);
- sp->waitFor(lpid);
- }
+ if (actor->isInCombat()) {
+ // need to get back to a combat stance to prevent weapon from
+ // being drawn again
+ ProcId spid = actor->doAnim(Animation::combatStand, dir_current);
+ Process *sp = kernel->getProcess(spid);
+ sp->waitFor(lpid);
+ }
+ }
+}
+
+void GravityProcess::actorFallStoppedCru(Actor *actor, int height) {
+ Animation::Sequence lastanim = actor->getLastAnim();
+ Kernel *kernel = Kernel::get_instance();
+
+ if (height / 8 > 2 &&
+ (lastanim != Animation::anotherJump &&
+ lastanim != Animation::slowCombatRollLeft &&
+ lastanim != Animation::slowCombatRollRight &&
+ lastanim != Animation::combatRollLeft &&
+ lastanim != Animation::combatRollRight &&
+ lastanim != Animation::run &&
+ lastanim != Animation::jumpForward &&
+ lastanim != Animation::unknownAnim30 &&
+ lastanim != Animation::runWithLargeWeapon)) {
+ // play land animation, overriding other animations
+ kernel->killProcesses(_itemNum, ActorAnimProcess::ACTOR_ANIM_PROC_TYPE, false); // CONSTANT!
+ ProcId lpid = actor->doAnim(Animation::jumpLanding, dir_current);
+
+ Animation::Sequence nextanim = actor->isInCombat() ? Animation::combatStand : Animation::stand;
+ ProcId spid = actor->doAnim(nextanim, dir_current);
+ Process *sp = kernel->getProcess(spid);
+ sp->waitFor(lpid);
+
+ // 'ooof' (Note: same sound no is used in No Remorse and No Regret)
+ AudioProcess *audioproc = AudioProcess::get_instance();
+ if (audioproc) audioproc->playSFX(0x8f, 250, _itemNum, 0); // CONSTANT!
+ } else {
+ Process *currentanim = kernel->findProcess(_itemNum, ActorAnimProcess::ACTOR_ANIM_PROC_TYPE);
+ if (currentanim) {
+ // TODO: Is this the right thing?
+ currentanim->wakeUp(0);
}
}
}
diff --git a/engines/ultima/ultima8/world/gravity_process.h b/engines/ultima/ultima8/world/gravity_process.h
index 9297e17d65..ed25e1dd4c 100644
--- a/engines/ultima/ultima8/world/gravity_process.h
+++ b/engines/ultima/ultima8/world/gravity_process.h
@@ -29,6 +29,7 @@ namespace Ultima {
namespace Ultima8 {
class Item;
+class Actor;
class GravityProcess : public Process {
public:
@@ -55,6 +56,9 @@ public:
protected:
void fallStopped();
+ void actorFallStoppedU8(Actor *actor, int height);
+ void actorFallStoppedCru(Actor *actor, int height);
+
int _gravity;
int _xSpeed, _ySpeed, _zSpeed;
};
diff --git a/engines/ultima/ultima8/world/item.cpp b/engines/ultima/ultima8/world/item.cpp
index f35230a73f..bc1249a54c 100644
--- a/engines/ultima/ultima8/world/item.cpp
+++ b/engines/ultima/ultima8/world/item.cpp
@@ -1893,13 +1893,17 @@ GravityProcess *Item::ensureGravityProcess() {
}
void Item::fall() {
- if (_flags & FLG_HANGING || getShapeInfo()->is_fixed()) {
+ const ShapeInfo *info = getShapeInfo();
+ if (_flags & FLG_HANGING || info->is_fixed() ||
+ (info->_weight == 0 && GAME_IS_CRUSADER)) {
// can't fall
return;
}
+ int gravity = GAME_IS_CRUSADER ? 2 : 4; //!! constants
+
GravityProcess *p = ensureGravityProcess();
- p->setGravity(4); //!! constant
+ p->setGravity(gravity);
}
void Item::grab() {
Commit: c6c0f42d4b76955ccbae1fb10bcbc1fd56338e55
https://github.com/scummvm/scummvm/commit/c6c0f42d4b76955ccbae1fb10bcbc1fd56338e55
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-01T08:14:45+09:00
Commit Message:
ULTIMA8: Make I_avatarStoleSomething behavior more closely match original
Changed paths:
engines/ultima/ultima8/world/item.cpp
diff --git a/engines/ultima/ultima8/world/item.cpp b/engines/ultima/ultima8/world/item.cpp
index bc1249a54c..69f2d51157 100644
--- a/engines/ultima/ultima8/world/item.cpp
+++ b/engines/ultima/ultima8/world/item.cpp
@@ -2853,9 +2853,9 @@ uint32 Item::I_avatarStoleSomething(const uint8 *args, unsigned int /*argsize*/)
ARG_ITEM_FROM_PTR(item);
if (!item) return 0;
- // Check if dead to match original game behavior here..
+ // Abort if npc && dead to match original game behavior
Actor *actor = dynamic_cast<Actor *>(item);
- if (!actor || actor->isDead())
+ if (actor && actor->isDead())
return 0;
ARG_UINT16(arg);
Commit: f187dfe04486dea30b1de9c723171464811061a8
https://github.com/scummvm/scummvm/commit/f187dfe04486dea30b1de9c723171464811061a8
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-01T08:14:58+09:00
Commit Message:
ULTIMA8: UC machine updates from disassembly
Mostly updates to comments:
* Remove questions which were confirmed by looking at disasm
* Add notes on unimplemented (unused) opcodes
Still some questions left.
Changed paths:
engines/ultima/ultima8/usecode/uc_machine.cpp
diff --git a/engines/ultima/ultima8/usecode/uc_machine.cpp b/engines/ultima/ultima8/usecode/uc_machine.cpp
index 2022865189..8f49ed5b4d 100644
--- a/engines/ultima/ultima8/usecode/uc_machine.cpp
+++ b/engines/ultima/ultima8/usecode/uc_machine.cpp
@@ -223,33 +223,33 @@ void UCMachine::execProcess(UCProcess *p) {
LOGPF(("pop dword\t%s = %08Xh\n", print_bp(si8a), ui32a));
break;
- case 0x03:
+ case 0x03: {
// 03 xx yy
// pop yy bytes into bp+xx
- {
si8a = static_cast<int8>(cs.readByte());
uint8 size = cs.readByte();
uint8 buf[256];
p->_stack.pop(buf, size);
p->_stack.assign(p->_bp + si8a, buf, size);
LOGPF(("pop huge\t%s %i\n", print_bp(si8a), size));
+ break;
}
- break;
+
+ // 0x04 ASSIGN_MEMBER_CHAR (Unused)
+ // 0x05 ASSIGN_MEMBER_INT (Unused)
+ // 0x06 ASSIGN_MEMBER_LONG (Unused)
+ // 0x07 ASSIGN_MEMBER_HUGE (Unused)
case 0x08:
// 08
- // pop 32bits into result register
- //! what is this result register exactly??
- //! probably a member of the Process?
- //! is the result in 0x08 and 0x6D the same var?
+ // pop 32bits into process result register
LOGPF(("pop dword\tprocess result\n"));
p->_result = p->_stack.pop4();
break;
- case 0x09:
+ case 0x09: {
// 09 xx yy zz
// pop yy bytes into an element of list bp+xx (or slist if zz set)
- {
si8a = static_cast<int8>(cs.readByte());
ui32a = cs.readByte();
si8b = static_cast<int8>(cs.readByte());
@@ -278,8 +278,8 @@ void UCMachine::execProcess(UCProcess *p) {
l->assign(ui16a, p->_stack.access());
p->_stack.addSP(ui32a);
}
+ break;
}
- break;
// PUSH opcodes
@@ -307,10 +307,9 @@ void UCMachine::execProcess(UCProcess *p) {
LOGPF(("push dword\t%08Xh\n", ui32a));
break;
- case 0x0D:
+ case 0x0D: {
// 0D xx xx yy ... yy 00
// push string (yy ... yy) of length xx xx onto the stack
- {
ui16a = cs.readUint16LE();
char *str = new char[ui16a + 1];
cs.read(str, ui16a);
@@ -325,7 +324,6 @@ void UCMachine::execProcess(UCProcess *p) {
}
}
-
LOGPF(("push string\t\"%s\"\n", str));
ui16b = cs.readByte();
if (ui16b != 0) {
@@ -335,14 +333,13 @@ void UCMachine::execProcess(UCProcess *p) {
}
p->_stack.push2(assignString(str));
delete[] str;
+ break;
}
- break;
- case 0x0E:
+ case 0x0E: {
// 0E xx yy
// pop yy values of size xx and push the resulting list
// (list is created in reverse order)
- {
ui16a = cs.readByte();
ui16b = cs.readByte();
UCList *l = new UCList(ui16a, ui16b);
@@ -354,18 +351,16 @@ void UCMachine::execProcess(UCProcess *p) {
p->_stack.addSP(ui16a * (ui16b + 1));
p->_stack.push2(assignList(l));
LOGPF(("create list\t%02X (%02X)\n", ui16b, ui16a));
+ break;
}
- break;
// Usecode function and intrinsic calls
-
- case 0x0F:
+ case 0x0F: {
// 0F xx yyyy
// intrinsic call. xx is number of argument bytes
// (includes this pointer, if present)
// NB: do not actually pop these argument bytes
- {
uint16 arg_bytes = cs.readByte();
uint16 func = cs.readUint16LE();
LOGPF(("calli\t\t%04Xh (%02Xh arg bytes) %s\n", func, arg_bytes, _convUse->intrinsics()[func]));
@@ -413,8 +408,6 @@ void UCMachine::execProcess(UCProcess *p) {
delete[] argbuf;
}
-
-
// REALLY MAJOR HACK:
// see docs/u8bugs.txt and
// https://sourceforge.net/tracker/index.php?func=detail&aid=1018748&group_id=53819&atid=471709
@@ -422,18 +415,17 @@ void UCMachine::execProcess(UCProcess *p) {
// 0xD0 = setAvatarInStasis
_globals->setEntries(0, 1, 1);
}
-
+ break;
}
- break;
+ // 0x10 NEAR_ROUTINE_CALL (Unused in U8 and Crusader)
- case 0x11:
+ case 0x11: {
// 11 xx xx yy yy
// Ultima 8:
// call the function at offset yy yy of class xx xx
// Crusader:
// call function number yy yy of class xx xx
- {
uint16 new_classid = cs.readUint16LE();
uint16 new_offset = cs.readUint16LE();
LOGPF(("call\t\t%04X:%04X\n", new_classid, new_offset));
@@ -452,8 +444,8 @@ void UCMachine::execProcess(UCProcess *p) {
cs.seek(p->_ip);
// Resume execution
+ break;
}
- break;
case 0x12:
// 12
@@ -464,8 +456,7 @@ void UCMachine::execProcess(UCProcess *p) {
case 0x13:
// 13
- // pop 32bits into temp register
- // NB: 0x13 isn't used AFAIK, but this is a 'logical' guess
+ // pop 32bits into temp register. (Not actually used in U8 or Crusader)
p->_temp32 = p->_stack.pop4();
LOGPF(("pop long\t\ttemp = %08X\n", p->_temp32));
break;
@@ -490,7 +481,6 @@ void UCMachine::execProcess(UCProcess *p) {
LOGPF(("add long\n"));
break;
-
case 0x16:
// 16
// pop two strings from the stack and push the concatenation
@@ -508,11 +498,10 @@ void UCMachine::execProcess(UCProcess *p) {
LOGPF(("concat\t\t= %s\n", _stringHeap[ui16b].c_str()));
break;
- case 0x17:
+ case 0x17: {
// 17
// pop two lists from the stack and push the 'sum' of the lists
// (freeing the originals)
- {
ui16a = p->_stack.pop2();
ui16b = p->_stack.pop2();
UCList *listA = getList(ui16a);
@@ -545,8 +534,9 @@ void UCMachine::execProcess(UCProcess *p) {
}
}
LOGPF(("append\n"));
+ break;
}
- break;
+ // 0x18 EXCLUSIVE_ADD_LIST (Unused in U8 and Crusader)
case 0x19: {
// 19 02
@@ -573,11 +563,9 @@ void UCMachine::execProcess(UCProcess *p) {
break;
}
case 0x1A: {
- // 1A
+ // 1A 02
// subtract string list
- // NB: this one takes a length parameter in crusader. (not in U8)!!
- // (or rather, it seems it takes one after all? -wjp,20030511)
- ui32a = cs.readByte(); // elementsize
+ ui32a = cs.readByte(); // elementsize (always 02)
ui32a = 2;
ui16a = p->_stack.pop2();
ui16b = p->_stack.pop2();
@@ -596,9 +584,9 @@ void UCMachine::execProcess(UCProcess *p) {
}
case 0x1B: {
// 1B xx
- // pop two lists from the stack and remove the 2nd from the 1st
+ // pop two lists from the stack of element size xx and
+ // remove the 2nd from the 1st
// (free the originals? order?)
- // only occurs in crusader.
ui32a = cs.readByte(); // elementsize
ui16a = p->_stack.pop2();
ui16b = p->_stack.pop2();
@@ -681,9 +669,8 @@ void UCMachine::execProcess(UCProcess *p) {
case 0x22:
// 22
- // 16 bit mod (order?)
- // is this a C-style %?
- // or return values between 0 and si16a-1 ?
+ // 16 bit mod, b % a
+ // Appears to be C-style %
si16a = static_cast<int16>(p->_stack.pop2());
si16b = static_cast<int16>(p->_stack.pop2());
if (si16a != 0) {
@@ -697,8 +684,7 @@ void UCMachine::execProcess(UCProcess *p) {
case 0x23:
// 23
- // 32 bit mod (order)?
- // also see 0x22
+ // 32 bit mod
si32a = static_cast<int16>(p->_stack.pop4());
si32b = static_cast<int16>(p->_stack.pop4());
if (si32a != 0) {
@@ -736,7 +722,6 @@ void UCMachine::execProcess(UCProcess *p) {
LOGPF(("cmp long\n"));
break;
-
case 0x26:
// 26
// compare two strings
@@ -752,6 +737,7 @@ void UCMachine::execProcess(UCProcess *p) {
LOGPF(("strcmp\n"));
break;
+ // 0x27 EQUALS_HUGE (Unused in U8 and Crusader)
case 0x28:
// 28
@@ -869,22 +855,21 @@ void UCMachine::execProcess(UCProcess *p) {
LOGPF(("not\n"));
break;
-
case 0x31:
// 31
- // 32 bit boolean not (both input and output 32 bit?)
+ // 32 bit boolean not (not used in U8 or Crusader)
ui32a = p->_stack.pop4();
if (!ui32a) {
- p->_stack.push4(1);
+ p->_stack.push2(1);
} else {
- p->_stack.push4(0);
+ p->_stack.push2(0);
}
LOGPF(("not long\n"));
break;
case 0x32:
// 32
- // 16 bit boolean and
+ // 16 bit logical and
ui16a = p->_stack.pop2();
ui16b = p->_stack.pop2();
if (ui16a && ui16b) {
@@ -897,7 +882,7 @@ void UCMachine::execProcess(UCProcess *p) {
case 0x33:
// 33
- // 32 bit boolean and
+ // 32 bit logical and (not used in U8 or Crusader)
ui32a = p->_stack.pop4();
ui32b = p->_stack.pop4();
if (ui32a && ui32b) {
@@ -910,7 +895,7 @@ void UCMachine::execProcess(UCProcess *p) {
case 0x34:
// 34
- // 16 bit boolean or
+ // 16 bit logical or
ui16a = p->_stack.pop2();
ui16b = p->_stack.pop2();
if (ui16a || ui16b) {
@@ -923,7 +908,7 @@ void UCMachine::execProcess(UCProcess *p) {
case 0x35:
// 35
- // 32 bit boolean or
+ // 32 bit logical or (not used in U8 or Crusader)
ui32a = p->_stack.pop4();
ui32b = p->_stack.pop4();
if (ui32a || ui32b) {
@@ -949,7 +934,7 @@ void UCMachine::execProcess(UCProcess *p) {
case 0x37:
// 37
- // 32 bit not-equal
+ // 32 bit not-equal (only used in Crusader)
si32a = static_cast<int16>(p->_stack.pop4());
si32b = static_cast<int16>(p->_stack.pop4());
if (si32a != si32b) {
@@ -960,7 +945,6 @@ void UCMachine::execProcess(UCProcess *p) {
LOGPF(("ne long\n"));
break;
-
case 0x38: {
// 38 xx yy
// is element (size xx) in list? (or slist if yy is true)
@@ -1040,8 +1024,7 @@ void UCMachine::execProcess(UCProcess *p) {
case 0x3D:
// 3D
- // 16 bit right shift
- // !! sign-extend or not?
+ // 16 bit right shift (sign-extended - game uses SAR opcode)
// operand order is different between U8 and crusader!
if (GAME_IS_U8) {
si16a = static_cast<int16>(p->_stack.pop2());
@@ -1081,23 +1064,20 @@ void UCMachine::execProcess(UCProcess *p) {
LOGPF(("push dword\t%s = %08Xh\n", print_bp(si8a), ui32a));
break;
- case 0x41:
+ case 0x41: {
// 41 xx
// push the string local var xx
// duplicating the string?
- {
si8a = static_cast<int8>(cs.readByte());
ui16a = p->_stack.access2(p->_bp + si8a);
p->_stack.push2(duplicateString(ui16a));
LOGPF(("push string\t%s\n", print_bp(si8a)));
+ break;
}
- break;
-
- case 0x42:
+ case 0x42: {
// 42 xx yy
// push the list (with yy size elements) at BP+xx
// duplicating the list?
- {
si8a = static_cast<int8>(cs.readByte());
ui16a = cs.readByte();
ui16b = p->_stack.access2(p->_bp + si8a);
@@ -1114,16 +1094,13 @@ void UCMachine::execProcess(UCProcess *p) {
p->_stack.push2(newlistid);
LOGPF(("push list\t%s (%04X, copy %04X, %d elements)\n",
print_bp(si8a), ui16b, newlistid, l->getSize()));
+ break;
}
- break;
-
- case 0x43:
+ case 0x43: {
// 43 xx
// push the stringlist local var xx
// duplicating the list, duplicating the strings in the list
- {
si8a = static_cast<int8>(cs.readByte());
-//!U8 ui16a = cs.readByte();
ui16a = 2;
ui16b = p->_stack.access2(p->_bp + si8a);
UCList *l = new UCList(ui16a);
@@ -1137,10 +1114,9 @@ void UCMachine::execProcess(UCProcess *p) {
}
p->_stack.push2(assignList(l));
LOGPF(("push slist\t%s\n", print_bp(si8a)));
+ break;
}
- break;
-
- case 0x44:
+ case 0x44: {
// 44 xx yy
// push element from the second last var pushed onto the stack
// (a list/slist), indexed by the last element pushed onto the list
@@ -1150,7 +1126,6 @@ void UCMachine::execProcess(UCProcess *p) {
// duplicate string if YY? yy = 1 only occurs
// in two places in U8: once it pops into temp afterwards,
// once it is indeed freed. So, guessing we should duplicate.
- {
ui32a = cs.readByte();
ui32b = cs.readByte();
ui16a = p->_stack.pop2() - 1; // index
@@ -1176,9 +1151,8 @@ void UCMachine::execProcess(UCProcess *p) {
}
}
LOGPF(("push element\t%02X slist==%02X\n", ui32a, ui32b));
+ break;
}
- break;
-
case 0x45:
// 45 xx yy
// push huge of size yy from BP+xx
@@ -1188,6 +1162,12 @@ void UCMachine::execProcess(UCProcess *p) {
LOGPF(("push huge\t%s %02X\n", print_bp(si8a), ui16b));
break;
+ // 0x46 BYTE_MEMBER_REFERENCE (Unused)
+ // 0x47 INT_MEMBER_REFERENCE (Unused)
+ // 0x48 LONG_MEMBER_REFERENCE (Unused)
+ // 0x49 HUGE_MEMBER_REFERENCE (Unused)
+ // 0x4a THIS_REFERENCE (Unused)
+
case 0x4B:
// 4B xx
// push 32 bit pointer address of BP+XX
@@ -1196,12 +1176,11 @@ void UCMachine::execProcess(UCProcess *p) {
LOGPF(("push addr\t%s\n", print_bp(si8a)));
break;
- case 0x4C:
+ case 0x4C: {
// 4C xx
// indirect push,
// pops a 32 bit pointer off the stack and pushes xx bytes
// from the location referenced by the pointer
- {
ui16a = cs.readByte();
ui32a = p->_stack.pop4();
@@ -1217,15 +1196,14 @@ void UCMachine::execProcess(UCProcess *p) {
} else {
LOGPF(("\n"));
}
+ break;
}
- break;
- case 0x4D:
+ case 0x4D: {
// 4D xx
// indirect pop
// pops a 32 bit pointer off the stack and pushes xx bytes
// from the location referenced by the pointer
- {
ui16a = cs.readByte();
ui32a = p->_stack.pop4();
@@ -1236,8 +1214,8 @@ void UCMachine::execProcess(UCProcess *p) {
}
LOGPF(("pop indirect\t%02Xh bytes\n", ui16a));
+ break;
}
- break;
case 0x4E:
// 4E xx xx yy
@@ -1275,7 +1253,6 @@ void UCMachine::execProcess(UCProcess *p) {
case 0x50:
// 50
// return from function
-
if (p->ret()) { // returning from process
LOGPF(("ret\t\tfrom process\n"));
p->terminateDeferred();
@@ -1330,19 +1307,19 @@ void UCMachine::execProcess(UCProcess *p) {
cede = true;
break;
- case 0x54:
+ case 0x54: {
// 54 01 01
// implies
- // this seems to link two processes (two pids are popped)
- // the '01 01' variety most likely causes one process
- // to wait for the other to finish.
- // the first _pid pushed is often the current _pid in U8
-
- // question: can multiple processes be waiting for a single proc?
- // can a process be waiting for multiple processes?
+ // Links two processes (two pids are popped) a and b, meaning
+ // b->waitfor(a)
+ //
+ // In the disassembly, '01 01' is the number of processes to
+ // pop, but in practice only ever appears as 01 01.
+ //
+ // pid a is often the current pid in U8
// 'implies' seems to push a value too, although it is very
- // often ignored. It looks like it's a _pid, but which one?
+ // often ignored. It looks like it's a pid, but which one?
// additionally, it is possible that 'implies' puts the result
// of a process in the 'process result' variable,
@@ -1351,11 +1328,10 @@ void UCMachine::execProcess(UCProcess *p) {
// 0x6D (push process result) only seems to occur soon after
// an 'implies'
- {
cs.readUint16LE(); // skip the 01 01
ui16a = p->_stack.pop2();
ui16b = p->_stack.pop2();
- p->_stack.push2(ui16a); //!! which _pid do we need to push!?
+ p->_stack.push2(ui16a); //!! which pid do we need to push!?
LOGPF(("implies\n"));
Process *proc = Kernel::get_instance()->getProcess(ui16b);
@@ -1381,17 +1357,19 @@ void UCMachine::execProcess(UCProcess *p) {
if ((ui16a && !proc2) || (ui16b && !proc))
error = true;
}
+ break;
}
- break;
- case 0x57:
+ // 0x55: AND_IMPLIES (only does push 0x402 in disasm, unused in U8 and Crusader)
+ // 0x56: OR_IMPLIES (only does push 0x404 in disasm, unused in U8 and Crusader)
+
+ case 0x57: {
// 57 aa tt xx xx yy yy
// spawn process function yyyy in class xxxx
// aa = number of arg bytes pushed (not including this pointer which is 4 bytes)
// tt = sizeof this pointer object
// only remove the this pointer from stack (4 bytes)
// put PID of spawned process in temp
- {
int arg_bytes = cs.readByte();
int this_size = cs.readByte();
uint16 classid = cs.readUint16LE();
@@ -1411,6 +1389,9 @@ void UCMachine::execProcess(UCProcess *p) {
this_size,
p->_stack.access(),
arg_bytes);
+ // Note: order of execution of this process and the new one is
+ // relevant. Currently, the spawned processes is executed once
+ // immediately, after which the current process resumes
p->_temp32 = Kernel::get_instance()->addProcessExec(newproc);
#ifdef DEBUG
@@ -1421,25 +1402,14 @@ void UCMachine::execProcess(UCProcess *p) {
<< Std::dec << Std::endl;
}
#endif
-
-
- // Note: order of execution of this process and the new one is
- // relevant. Currently, the spawned processes is executed once
- // immediately, after which the current process resumes
-
-
- // cede = true;
+ break;
}
- break;
-
- case 0x58:
+ case 0x58: {
// 58 xx xx yy yy zz zz tt uu
// spawn inline process function yyyy in class xxxx at offset zzzz
// tt = size of this pointer
- // uu = unknown (occurring values: 00, 02, 05)
-
- {
+ // uu = unknown (occurring values: 00, 02, 05) - seems unused in original
uint16 classid = cs.readUint16LE();
uint16 offset = cs.readUint16LE();
uint16 delta = cs.readUint16LE();
@@ -1455,6 +1425,7 @@ void UCMachine::execProcess(UCProcess *p) {
UCProcess *newproc = new UCProcess(classid, offset + delta,
thisptr, this_size);
+ // as with 'spawn', run the spawned process once immediately
uint16 newpid = Kernel::get_instance()->addProcessExec(newproc);
#ifdef DEBUG
@@ -1464,19 +1435,13 @@ void UCMachine::execProcess(UCProcess *p) {
<< ", offset " << p->_ip << Std::dec << Std::endl;
}
#endif
-
- // as with 'spawn', run execute the spawned process once
- // immediately
-
- p->_stack.push2(newpid); //! push _pid of newproc?
-
- // cede = true;
+ p->_stack.push2(newpid); //! push pid of new proc
+ break;
}
- break;
case 0x59:
// 59
- // push process id
+ // push current process id
p->_stack.push2(p->_pid);
LOGPF(("push\t\tpid = %04Xh\n", p->_pid));
break;
@@ -1494,6 +1459,28 @@ void UCMachine::execProcess(UCProcess *p) {
}
break;
+ case 0x5B:
+ // 5B xx xx
+ // debug line no xx xx
+ ui16a = cs.readUint16LE(); // source line number
+ debug(10, "ignore debug opcode %02X: line offset %d", opcode, ui16a);
+ LOGPF(("line number %d\n", ui16a));
+ break;
+
+ case 0x5C: {
+ // 5C xx xx char[9]
+ // debug line no xx xx in class str
+ ui16a = cs.readUint16LE(); // source line number
+ char name[10] = {0};
+ for (int x = 0; x < 9; x++) {
+ // skip over class name and null terminator
+ name[x] = cs.readByte();
+ }
+ LOGPF(("line number %s %d\n", name, ui16a));
+ debug(10, "ignore debug opcode %02X: %s line offset %d", opcode, name, ui16a);
+ break;
+ }
+
case 0x5D:
// 5D
// push 8 bit value returned from function call
@@ -1590,6 +1577,8 @@ void UCMachine::execProcess(UCProcess *p) {
LOGPF(("free slist\t%s = %04x\n", print_sp(si8a), ui16a));
break;
+ // 0x68 COPY_STRING (unused in U8 and Crusader)
+
case 0x69:
// 69 xx
// push the string in var BP+xx as 32 bit pointer
@@ -1599,6 +1588,8 @@ void UCMachine::execProcess(UCProcess *p) {
LOGPF(("str to ptr\t%s\n", print_bp(si8a)));
break;
+ // 0x6A Convert pointer to string (unused in U8 and Crusader)
+
case 0x6B:
// 6B
// pop a string and push 32 bit pointer to string
@@ -1662,9 +1653,7 @@ void UCMachine::execProcess(UCProcess *p) {
case 0x6D:
// 6D
- // push 32bit result of process
- // (of which process? pop anything?)
- // (also see comment for 0x54 'implies')
+ // push 32bit result of current process
LOGPF(("push dword\tprocess result\n"));
p->_stack.push4(p->_result);
break;
@@ -1678,7 +1667,6 @@ void UCMachine::execProcess(UCProcess *p) {
LOGPF(("move sp\t\t%s%02Xh\n", si8a < 0 ? "-" : "", si8a < 0 ? -si8a : si8a));
break;
-
case 0x6F:
// 6F xx
// push 32 pointer address of SP-xx
@@ -1698,12 +1686,11 @@ void UCMachine::execProcess(UCProcess *p) {
// we expect SP to be at the end of that area when 0x73 is executed
// a 'loop script' (created by 0x74) is used to select items
- case 0x70:
+ case 0x70: {
// 70 xx yy zz
// loop something. Stores 'current object' in var xx
// yy == num bytes in string
// zz == type
- {
si16a = cs.readSByte();
uint32 scriptsize = cs.readByte();
uint32 searchtype = cs.readByte();
@@ -1835,10 +1822,12 @@ void UCMachine::execProcess(UCProcess *p) {
}
// Intentional fall-through
- case 0x73:
+ // 0x71 SEARCH_RECURSIVE (Unused)
+ // 0x72 SEARCH_SURFACE (Unused)
+
+ case 0x73: {
// 73
// next loop object. pushes false if end reached
- {
unsigned int sp = p->_stack.getSP();
uint16 itemlistID = p->_stack.access2(sp);
UCList *itemlist = getList(itemlistID);
@@ -1889,8 +1878,8 @@ void UCMachine::execProcess(UCProcess *p) {
if (opcode == 0x73) { // because of the fall-through
LOGPF(("loopnext\n"));
}
+ break;
}
- break;
case 0x74:
// 74 xx
@@ -2039,23 +2028,8 @@ void UCMachine::execProcess(UCProcess *p) {
error = true;
break;
- case 0x5B: {
- ui16a = cs.readUint16LE(); // source line number
- debug(10, "ignore debug opcode %02X: line offset %d", opcode, ui16a);
- LOGPF(("line number %d\n", ui16a));
- break;
- }
- case 0x5C: {
- ui16a = cs.readUint16LE(); // source line number
- char name[10] = {0};
- for (int x = 0; x < 9; x++) {
- // skip over class name and null terminator
- name[x] = cs.readByte();
- }
- LOGPF(("line number %s %d\n", name, ui16a));
- debug(10, "ignore debug opcode %02X: %s line offset %d", opcode, name, ui16a);
- break;
- }
+ // 0x7B REGRESS (Unused)
+
default:
perr.Print("unhandled opcode %02X\n", opcode);
More information about the Scummvm-git-logs
mailing list