VCRUISE: Add say cycle ops and some item infos

This commit is contained in:
elasota 2024-02-08 19:58:53 -05:00
parent e9000d2a8e
commit 0867fd9126
4 changed files with 109 additions and 21 deletions

View File

@ -41,17 +41,17 @@ const AD2044ItemInfo g_ad2044ItemInfos[kNumAD2044Items] = {
{0, 0, false, 0}, // 14
{0, 0, false, 0}, // 15
{0, 0, false, 0}, // 16
{0, 0, false, 0}, // 17
{0, 0, true, 0x128}, // 18
{0, 0, false, 0}, // 17
{0x3D70D2EC, 0x98382A38, true, 0x128}, // 18 spoon
{0, 0, false, 0}, // 19
{0, 0, false, 0}, // 20
{0, 0, false, 0}, // 21
{0, 0, false, 0}, // 22
{0, 0, false, 0}, // 23
{0, 0, false, 0}, // 24
{0, 0, true, 0x134}, // 24 cigarettes (filled)
{0, 0, false, 0}, // 25
{0, 0, false, 0}, // 26
{0, 0, false, 0}, // 27
{0, 0, true, 0x137}, // 27 matches
{0, 0, false, 0}, // 28
{0, 0, false, 0}, // 29
{0, 0, false, 0}, // 30
@ -78,13 +78,13 @@ const AD2044ItemInfo g_ad2044ItemInfos[kNumAD2044Items] = {
{0, 0, false, 0}, // 51
{0, 0, false, 0}, // 52
{0, 0, false, 0}, // 53
{0x83d54448, 0x839911EF, 0, 0}, // 54
{0x83d54448, 0x839911EF, 0, 0}, // 54 goaler (sic)
{0, 0, false, 0}, // 55
{0, 0, false, 0}, // 56
{0, 0, false, 0}, // 57
{0, 0, false, 0}, // 58
{0, 0, false, 0}, // 59
{0, 0, false, 0x170}, // 60
{0, 0, false, 0x170}, // 60 mirror
{0, 0, false, 0}, // 61
{0, 0, false, 0}, // 62
{0, 0, false, 0}, // 63
@ -92,12 +92,12 @@ const AD2044ItemInfo g_ad2044ItemInfos[kNumAD2044Items] = {
{0, 0, false, 0}, // 65
{0, 0, false, 0}, // 66
{0, 0, false, 0}, // 67
{0, 0, false, 0}, // 68
{0, 0, false, 0}, // 69
{0, 0, true, 0x178}, // 68 cigarette
{0, 0, true, 0x179}, // 69 cigarette (lit)
{0, 0, false, 0}, // 70
{0, 0, false, 0}, // 71
{0, 0, false, 0}, // 72
{0, 0, false, 0}, // 73
{0, 0, true, 0x183}, // 73 cigarettes (1 missing)
};
} // End of namespace VCruise

View File

@ -3179,14 +3179,16 @@ void Runtime::loadAD2044ExecutableResources() {
_ad2044Graphics->finishLoading();
Common::HashMap<uint32, uint32> stringHashToFilePos;
Common::HashMap<uint32, Common::Pair<uint32, uint> > stringHashToFilePosAndLength;
for (const AD2044ItemInfo &itemInfo : g_ad2044ItemInfos) {
stringHashToFilePos[itemInfo.enNameCRC] = 0;
stringHashToFilePos[itemInfo.plNameCRC] = 0;
if (_language == Common::PL_POL)
stringHashToFilePosAndLength[itemInfo.plNameCRC] = Common::Pair<uint32, uint>(0, 0);
else
stringHashToFilePosAndLength[itemInfo.enNameCRC] = Common::Pair<uint32, uint>(0, 0);
}
stringHashToFilePos.erase(0);
stringHashToFilePosAndLength.erase(0);
// Scan for strings
Common::CRC32 crc;
@ -3200,9 +3202,9 @@ void Runtime::loadAD2044ExecutableResources() {
uint32 strLength = i - strStartPos;
rollingCRC = crc.finalize(rollingCRC);
if (strLength != 0) {
Common::HashMap<uint32, uint32>::iterator it = stringHashToFilePos.find(rollingCRC);
if (it != stringHashToFilePos.end())
it->_value = strStartPos;
Common::HashMap<uint32, Common::Pair<uint32, uint> >::iterator it = stringHashToFilePosAndLength.find(rollingCRC);
if (it != stringHashToFilePosAndLength.end())
it->_value = Common::Pair<uint32, uint> (strStartPos, strLength);
}
#if 1
@ -3216,6 +3218,34 @@ void Runtime::loadAD2044ExecutableResources() {
} else
rollingCRC = crc.processByte(b, rollingCRC);
}
_ad2044ItemNames.clear();
_ad2044ItemNames.reserve(ARRAYSIZE(g_ad2044ItemInfos));
for (const AD2044ItemInfo &itemInfo : g_ad2044ItemInfos) {
Common::String itemInfoUTF8;
uint32 hash = itemInfo.enNameCRC;
if (_language == Common::PL_POL)
hash = itemInfo.plNameCRC;
if (hash != 0) {
Common::HashMap<uint32, Common::Pair<uint32, uint> >::const_iterator strIt = stringHashToFilePosAndLength.find(hash);
if (strIt != stringHashToFilePosAndLength.end()) {
uint32 filePos = strIt->_value.first;
uint length = strIt->_value.second;
if (length > 0) {
Common::String str(reinterpret_cast<const char *>(&exeContents[filePos]), length);
itemInfoUTF8 = str.decode(Common::CodePage::kWindows1250).encode(Common::kUtf8);
}
}
}
_ad2044ItemNames.push_back(itemInfoUTF8);
}
}
void Runtime::findWaves() {

View File

@ -1236,11 +1236,13 @@ private:
void scriptOpSound(ScriptArg_t arg);
void scriptOpISound(ScriptArg_t arg);
void scriptOpUSound(ScriptArg_t arg);
void scriptOpSayCycle_AD2044(const StackInt_t *values, uint numValues);
void scriptOpSay2K(ScriptArg_t arg);
void scriptOpSay3K(ScriptArg_t arg);
void scriptOpRGet(ScriptArg_t arg);
void scriptOpRSet(ScriptArg_t arg);
void scriptOpEndRSet(ScriptArg_t arg);
void scriptOpStop(ScriptArg_t arg);
Common::Array<Common::SharedPtr<AnimatedCursor> > _cursors; // Cursors indexed as CURSOR_CUR_##
Common::Array<Common::SharedPtr<AnimatedCursor> > _cursorsShort; // Cursors indexed as CURSOR_#
@ -1544,6 +1546,7 @@ private:
Common::String _subtitleText;
Common::SharedPtr<AD2044Graphics> _ad2044Graphics;
Common::Array<Common::String> _ad2044ItemNames;
};
} // End of namespace VCruise

View File

@ -30,6 +30,23 @@
namespace VCruise {
struct AD2044UnusualAnimationRules {
enum Type {
kTypeLoop, // Loop the animation
kTypePlayFirstFrameOnly,
};
uint roomNumber;
uint screenNumber;
uint interactionID;
uint8 animLookupID;
Type ruleType;
};
AD2044UnusualAnimationRules g_unusualAnimationRules[] = {
{87, 0x69, 0xa3, 0xa5, AD2044UnusualAnimationRules::kTypePlayFirstFrameOnly},
};
#ifdef PEEK_STACK
#error "PEEK_STACK is already defined"
#endif
@ -2084,7 +2101,7 @@ void Runtime::scriptOpAnimAD2044(bool isForward) {
bool found = false;
for (const AD2044AnimationDef &def : _ad2044AnimationDefs) {
if (static_cast<StackInt_t>(def.lookupID) == stackArgs[0]) {
if (def.roomID == _roomNumber && static_cast<StackInt_t>(def.lookupID) == stackArgs[0]) {
animationID = isForward ? def.fwdAnimationID : def.revAnimationID;
found = true;
break;
@ -2127,13 +2144,46 @@ void Runtime::scriptOpAnimReverse(ScriptArg_t arg) {
}
OPCODE_STUB(AnimKForward)
OPCODE_STUB(Say2K)
OPCODE_STUB(Say3K)
void Runtime::scriptOpNoUpdate(ScriptArg_t arg) {
}
OPCODE_STUB(NoClear)
void Runtime::scriptOpNoClear(ScriptArg_t arg) {
}
void Runtime::scriptOpSayCycle_AD2044(const StackInt_t *values, uint numValues) {
// Checking the scripts, there don't appear to be any cycles that can't be tracked from
// the first value, so just use that.
uint &cyclePosRef = _sayCycles[static_cast<uint32>(values[0])];
Common::String soundName = Common::String::format("%02i-%08i", static_cast<int>(_disc * 10u + 1u), static_cast<int>(values[cyclePosRef]));
cyclePosRef = (cyclePosRef + 1u) % numValues;
StackInt_t soundID = 0;
SoundInstance *cachedSound = nullptr;
resolveSoundByName(soundName, true, soundID, cachedSound);
if (cachedSound) {
TriggeredOneShot oneShot;
oneShot.soundID = soundID;
oneShot.uniqueSlot = _disc;
triggerSound(kSoundLoopBehaviorNo, *cachedSound, 100, 0, false, true);
}
}
void Runtime::scriptOpSay2K(ScriptArg_t arg) {
TAKE_STACK_INT(2);
scriptOpSayCycle_AD2044(stackArgs, 2);
}
void Runtime::scriptOpSay3K(ScriptArg_t arg) {
TAKE_STACK_INT(3);
scriptOpSayCycle_AD2044(stackArgs, 3);
}
void Runtime::scriptOpSay1_AD2044(ScriptArg_t arg) {
TAKE_STACK_INT(1);
@ -2252,7 +2302,7 @@ void Runtime::scriptOpRSet(ScriptArg_t arg) {
}
}
error("Couldn't resolve item ID for script item %i", static_cast<int>(stackArgs[0]));
error("Couldn't resolve item ID for script item 0x%x", static_cast<int>(stackArgs[0]));
}
void Runtime::scriptOpEndRSet(ScriptArg_t arg) {
@ -2261,6 +2311,9 @@ void Runtime::scriptOpEndRSet(ScriptArg_t arg) {
returnFromExaminingItem();
}
void Runtime::scriptOpStop(ScriptArg_t arg) {
terminateScript();
}
// Unused Schizm ops
// Only used in fnRandomBirds and fnRandomMachines in Room 60, both of which are unused
@ -2521,7 +2574,9 @@ bool Runtime::runScript() {
DISPATCH_OP(RSet);
DISPATCH_OP(EndRSet);
DISPATCH_OP(Say2K);
DISPATCH_OP(Say3K);
DISPATCH_OP(Stop);
default:
error("Unimplemented opcode %i", static_cast<int>(instr.op));