MOHAWK: Riven: Patch prison island dome switch sound change
Fixes #9958.
This commit is contained in:
parent
6edb991bf9
commit
69dc56ad0f
5 changed files with 98 additions and 4 deletions
|
@ -72,6 +72,7 @@ MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescriptio
|
||||||
_inventory = nullptr;
|
_inventory = nullptr;
|
||||||
|
|
||||||
DebugMan.addDebugChannel(kRivenDebugScript, "Script", "Track Script Execution");
|
DebugMan.addDebugChannel(kRivenDebugScript, "Script", "Track Script Execution");
|
||||||
|
DebugMan.addDebugChannel(kRivenDebugPatches, "Patches", "Track Script Patching");
|
||||||
|
|
||||||
// NOTE: We can never really support CD swapping. All of the music files
|
// NOTE: We can never really support CD swapping. All of the music files
|
||||||
// (*_Sounds.mhk) are stored on disc 1. They are copied to the hard drive
|
// (*_Sounds.mhk) are stored on disc 1. They are copied to the hard drive
|
||||||
|
|
|
@ -65,7 +65,8 @@ enum {
|
||||||
|
|
||||||
// Engine Debug Flags
|
// Engine Debug Flags
|
||||||
enum {
|
enum {
|
||||||
kRivenDebugScript = (1 << 0)
|
kRivenDebugScript = (1 << 0),
|
||||||
|
kRivenDebugPatches = (1 << 1)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ZipMode {
|
struct ZipMode {
|
||||||
|
|
|
@ -63,6 +63,12 @@ void RivenCard::loadCardResource(uint16 id) {
|
||||||
_zipModePlace = inStream->readUint16BE();
|
_zipModePlace = inStream->readUint16BE();
|
||||||
_scripts = _vm->_scriptMan->readScripts(inStream);
|
_scripts = _vm->_scriptMan->readScripts(inStream);
|
||||||
|
|
||||||
|
// Apply script patches for this card
|
||||||
|
uint32 globalId = _vm->getStack()->getCardGlobalId(id);
|
||||||
|
for (uint i = 0; i < _scripts.size(); i++) {
|
||||||
|
_scripts[i].script->applyCardPatches(_vm, globalId, _scripts[i].type);
|
||||||
|
}
|
||||||
|
|
||||||
delete inStream;
|
delete inStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -249,6 +249,53 @@ const char *RivenScript::getTypeName(uint16 type) {
|
||||||
return names[type];
|
return names[type];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RivenScript::applyCardPatches(MohawkEngine_Riven *vm, uint32 cardGlobalId, int scriptType) {
|
||||||
|
bool shouldApplyPatches = false;
|
||||||
|
|
||||||
|
// On Prison Island when pressing the dome viewer switch to close the dome,
|
||||||
|
// the game schedules an ambient sound change using kRivenCommandStoreMovieOpcode
|
||||||
|
// but does not play the associated video in a blocking way. The stored opcode
|
||||||
|
// is not immediately used, stays in memory and may be triggered by some
|
||||||
|
// other action. (Bug #9958)
|
||||||
|
// We replace kRivenCommandStoreMovieOpcode by kRivenCommandActivateSLST
|
||||||
|
// to make the ambient sound change happen immediately.
|
||||||
|
//
|
||||||
|
// Script before patch:
|
||||||
|
// playMovieBlocking(3); // Dome closing
|
||||||
|
// playMovie(4); // Dome spinning up
|
||||||
|
// activatePLST(2); // Dome closed
|
||||||
|
// playMovieBlocking(4); // Dome spinning up
|
||||||
|
// storeMovieOpcode(1, 0, 0, 40, 2); // Schedule ambient sound change to "dome spinning"
|
||||||
|
// after movie 1 finishes blocking playback
|
||||||
|
// playMovie(1); // Dome spinning
|
||||||
|
//
|
||||||
|
// Script after patch:
|
||||||
|
// playMovieBlocking(3); // Dome closing
|
||||||
|
// playMovie(4); // Dome spinning up
|
||||||
|
// activatePLST(2); // Dome closed
|
||||||
|
// playMovieBlocking(4); // Dome spinning up
|
||||||
|
// activateSLST(2); // Ambient sound change to "dome spinning"
|
||||||
|
// playMovie(1); // Dome spinning
|
||||||
|
if (cardGlobalId == 0x1AC1 && scriptType == kCardEnterScript) {
|
||||||
|
shouldApplyPatches = true;
|
||||||
|
for (uint i = 0; i < _commands.size(); i++) {
|
||||||
|
if (_commands[i]->getType() == kRivenCommandStoreMovieOpcode) {
|
||||||
|
RivenSimpleCommand::ArgumentArray arguments;
|
||||||
|
arguments.push_back(2);
|
||||||
|
_commands[i] = RivenCommandPtr(new RivenSimpleCommand(vm, kRivenCommandActivateSLST, arguments));
|
||||||
|
debugC(kRivenDebugPatches, "Applied immediate ambient sound patch to card %x", cardGlobalId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldApplyPatches) {
|
||||||
|
for (uint i = 0; i < _commands.size(); i++) {
|
||||||
|
_commands[i]->applyCardPatches(cardGlobalId, scriptType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RivenScriptPtr &operator+=(RivenScriptPtr &lhs, const RivenScriptPtr &rhs) {
|
RivenScriptPtr &operator+=(RivenScriptPtr &lhs, const RivenScriptPtr &rhs) {
|
||||||
if (rhs) {
|
if (rhs) {
|
||||||
*lhs += *rhs;
|
*lhs += *rhs;
|
||||||
|
@ -691,6 +738,10 @@ void RivenSimpleCommand::execute() {
|
||||||
(this->*(_opcodes[_type].proc)) (_type, _arguments);
|
(this->*(_opcodes[_type].proc)) (_type, _arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RivenCommandType RivenSimpleCommand::getType() const {
|
||||||
|
return _type;
|
||||||
|
}
|
||||||
|
|
||||||
RivenSwitchCommand::RivenSwitchCommand(MohawkEngine_Riven *vm) :
|
RivenSwitchCommand::RivenSwitchCommand(MohawkEngine_Riven *vm) :
|
||||||
RivenCommand(vm),
|
RivenCommand(vm),
|
||||||
_variableId(0) {
|
_variableId(0) {
|
||||||
|
@ -768,6 +819,16 @@ void RivenSwitchCommand::execute() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RivenCommandType RivenSwitchCommand::getType() const {
|
||||||
|
return kRivenCommandSwitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RivenSwitchCommand::applyCardPatches(uint32 globalId, int scriptType) {
|
||||||
|
for (uint i = 0; i < _branches.size(); i++) {
|
||||||
|
_branches[i].script->applyCardPatches(_vm, globalId, scriptType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RivenStackChangeCommand::RivenStackChangeCommand(MohawkEngine_Riven *vm, uint16 stackId, uint32 globalCardId, bool byStackId) :
|
RivenStackChangeCommand::RivenStackChangeCommand(MohawkEngine_Riven *vm, uint16 stackId, uint32 globalCardId, bool byStackId) :
|
||||||
RivenCommand(vm),
|
RivenCommand(vm),
|
||||||
_stackId(stackId),
|
_stackId(stackId),
|
||||||
|
@ -813,6 +874,10 @@ void RivenStackChangeCommand::dump(byte tabs) {
|
||||||
debugN("changeStack(%d, %d);\n", _stackId, _cardId);
|
debugN("changeStack(%d, %d);\n", _stackId, _cardId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RivenCommandType RivenStackChangeCommand::getType() const {
|
||||||
|
return kRivenCommandChangeStack;
|
||||||
|
}
|
||||||
|
|
||||||
RivenTimerCommand::RivenTimerCommand(MohawkEngine_Riven *vm, const Common::SharedPtr<RivenStack::TimerProc> &timerProc) :
|
RivenTimerCommand::RivenTimerCommand(MohawkEngine_Riven *vm, const Common::SharedPtr<RivenStack::TimerProc> &timerProc) :
|
||||||
RivenCommand(vm),
|
RivenCommand(vm),
|
||||||
_timerProc(timerProc) {
|
_timerProc(timerProc) {
|
||||||
|
@ -828,4 +893,8 @@ void RivenTimerCommand::dump(byte tabs) {
|
||||||
debugN("doTimer();\n");
|
debugN("doTimer();\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RivenCommandType RivenTimerCommand::getType() const {
|
||||||
|
return kRivenCommandTimer;
|
||||||
|
}
|
||||||
|
|
||||||
} // End of namespace Mohawk
|
} // End of namespace Mohawk
|
||||||
|
|
|
@ -87,7 +87,8 @@ enum RivenCommandType {
|
||||||
kRivenCommandActivateBLST = 43,
|
kRivenCommandActivateBLST = 43,
|
||||||
kRivenCommandActivateFLST = 44,
|
kRivenCommandActivateFLST = 44,
|
||||||
kRivenCommandZipMode = 45,
|
kRivenCommandZipMode = 45,
|
||||||
kRivenCommandActivateMLST = 46
|
kRivenCommandActivateMLST = 46,
|
||||||
|
kRivenCommandTimer = 1001
|
||||||
};
|
};
|
||||||
|
|
||||||
class MohawkEngine_Riven;
|
class MohawkEngine_Riven;
|
||||||
|
@ -127,6 +128,9 @@ public:
|
||||||
/** Print script details to the standard output */
|
/** Print script details to the standard output */
|
||||||
void dumpScript(byte tabs);
|
void dumpScript(byte tabs);
|
||||||
|
|
||||||
|
/** Apply patches to card script to fix bugs in the original game scripts */
|
||||||
|
void applyCardPatches(MohawkEngine_Riven *vm, uint32 cardGlobalId, int scriptType);
|
||||||
|
|
||||||
/** Append the commands of the other script to this script */
|
/** Append the commands of the other script to this script */
|
||||||
RivenScript &operator+=(const RivenScript &other);
|
RivenScript &operator+=(const RivenScript &other);
|
||||||
|
|
||||||
|
@ -249,6 +253,12 @@ public:
|
||||||
/** Execute the command */
|
/** Execute the command */
|
||||||
virtual void execute() = 0;
|
virtual void execute() = 0;
|
||||||
|
|
||||||
|
/** Get the command's type */
|
||||||
|
virtual RivenCommandType getType() const = 0;
|
||||||
|
|
||||||
|
/** Apply card patches for the command's sub-scripts */
|
||||||
|
virtual void applyCardPatches(uint32 globalId, int scriptType) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MohawkEngine_Riven *_vm;
|
MohawkEngine_Riven *_vm;
|
||||||
};
|
};
|
||||||
|
@ -263,21 +273,24 @@ protected:
|
||||||
class RivenSimpleCommand : public RivenCommand {
|
class RivenSimpleCommand : public RivenCommand {
|
||||||
public:
|
public:
|
||||||
static RivenSimpleCommand *createFromStream(MohawkEngine_Riven *vm, RivenCommandType type, Common::ReadStream *stream);
|
static RivenSimpleCommand *createFromStream(MohawkEngine_Riven *vm, RivenCommandType type, Common::ReadStream *stream);
|
||||||
|
|
||||||
|
typedef Common::Array<uint16> ArgumentArray;
|
||||||
|
|
||||||
|
RivenSimpleCommand(MohawkEngine_Riven *vm, RivenCommandType type, const ArgumentArray &arguments);
|
||||||
virtual ~RivenSimpleCommand();
|
virtual ~RivenSimpleCommand();
|
||||||
|
|
||||||
// RivenCommand API
|
// RivenCommand API
|
||||||
virtual void dump(byte tabs) override;
|
virtual void dump(byte tabs) override;
|
||||||
virtual void execute() override;
|
virtual void execute() override;
|
||||||
|
virtual RivenCommandType getType() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef Common::Array<uint16> ArgumentArray;
|
|
||||||
typedef void (RivenSimpleCommand::*OpcodeProcRiven)(uint16 op, const ArgumentArray &args);
|
typedef void (RivenSimpleCommand::*OpcodeProcRiven)(uint16 op, const ArgumentArray &args);
|
||||||
struct RivenOpcode {
|
struct RivenOpcode {
|
||||||
OpcodeProcRiven proc;
|
OpcodeProcRiven proc;
|
||||||
const char *desc;
|
const char *desc;
|
||||||
};
|
};
|
||||||
|
|
||||||
RivenSimpleCommand(MohawkEngine_Riven *vm, RivenCommandType type, const ArgumentArray &arguments);
|
|
||||||
|
|
||||||
void setupOpcodes();
|
void setupOpcodes();
|
||||||
Common::String describe() const;
|
Common::String describe() const;
|
||||||
|
@ -342,6 +355,8 @@ public:
|
||||||
// RivenCommand API
|
// RivenCommand API
|
||||||
virtual void dump(byte tabs) override;
|
virtual void dump(byte tabs) override;
|
||||||
virtual void execute() override;
|
virtual void execute() override;
|
||||||
|
virtual RivenCommandType getType() const override;
|
||||||
|
virtual void applyCardPatches(uint32 globalId, int scriptType) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RivenSwitchCommand(MohawkEngine_Riven *vm);
|
RivenSwitchCommand(MohawkEngine_Riven *vm);
|
||||||
|
@ -372,6 +387,7 @@ public:
|
||||||
// RivenCommand API
|
// RivenCommand API
|
||||||
virtual void dump(byte tabs) override;
|
virtual void dump(byte tabs) override;
|
||||||
virtual void execute() override;
|
virtual void execute() override;
|
||||||
|
virtual RivenCommandType getType() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint16 _stackId;
|
uint16 _stackId;
|
||||||
|
@ -392,6 +408,7 @@ public:
|
||||||
// RivenCommand API
|
// RivenCommand API
|
||||||
virtual void dump(byte tabs) override;
|
virtual void dump(byte tabs) override;
|
||||||
virtual void execute() override;
|
virtual void execute() override;
|
||||||
|
virtual RivenCommandType getType() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Common::SharedPtr<RivenStack::TimerProc> _timerProc;
|
Common::SharedPtr<RivenStack::TimerProc> _timerProc;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue