The VM has been treating the entire area between the frame pointer and
the stack pointer as temp variables for the current function. There are
two problems with this:
1. The VM hasn't been updating the frame pointer correctly when multiple
methods are called within the same send/self/super instruction.
2. The VM has been recalculating the number of temp variables on every
instruction as the difference between the two pointers.
This is incorrect, as this changes with almost every instruction in
ways have nothing to do with the number of temp variables allocated
by the link instruction. Meanwhile, the VM has not been recording
the number of variables allocated by the link instruction.
The first discrepancy caused scripts to behave differently than in SSCI
when reading parameters out of bounds in certain situations.
It also prevented our uninitialized variable detection from detecting
certain reads. The second made the temp-count used for out of bounds
detection too large, made debugger output such as `stack` incorrect,
and made stepping through the link instruction in the debugger appear
to do nothing until stepping through the following instruction.
When multiple methods are called by a send/self/super instruction, each
method's link instruction increases the stack pointer further.
Method B's variables appear after method A's. The VM has been setting
the stack pointer correctly but it kept using the previous frame
pointer, so method B would re-use method A's stack area instead of the
area the VM had just allocated for B. If a script correctly initializes
variables before using them and doesn't use out of bounds parameters or
temp variables then this discrepancy doesn't make a difference.
But a lot of scripts do these bad things and accidentally rely on the
undefined values they read.
Now we update the frame pointer correctly when "carrying over" to
subsequent method calls from the same send/self/super instruction.
This matches SSCI behavior. We also now record the number of temp
variables that have been allocated by the link instruction and use
that instead of incorrectly recalculating on every instruction.
Fixes the KQ6 black widow lockup, and other KQ6 music bugs, where
scripts call Sound:fade without the required fourth parameter.
Sound:fade expects a fourth parameter, so reads it out of bounds,
and passes it as the stop-after-completion boolean to kDoSoundFade.
Scripts that called Sound:fade as the only method in a send got the same
results as in SSCI, but scripts that called Sound:play first didn't.
Fixes bugs #5625#5653#6120#6210#6252#13944
Allows testing the speed throttler for possible improvements
and to demonstrate what it affects and what it doesn't.
`speed_throttle 0` disables kGameIsRestarting throttling.
(Except for game-specific workarounds.)
This command is possible due to several recent cleanups of other
throttling mechanisms that overlapped and were absorbed by this one.
While constantly evaluating the stack when debugging please consider:
* adding a "st" alias to the "stack" command which also nicely represents the stack based addresses such as: `ST:0000`.
* I introduced a previous alias for evaluating registers with the addition to "reg" so I'm hoping this is reasonable.
When debugging, I'm constantly inspecting the SCI VM registers and thought this would be a great command to have an alias for.
I am proposing the following alias: `reg` for the command `registers` and also updated the help docs.
These commands have already been implemented by a previous committer.
This commit simply adds the commands to the console debug `help` command for the SCI engine.
Fixes several problems with the SoundResource class:
- Constructor doesn't fully initialize object if resource doesn't exist
- Destructor crashes if object not fully initialized
- Constructor has no mechanism to report failure
- Callers believe failure is reported by constructor returning null
- SoundCommandParser::initSoundResource attempts to pre-detect failure
insufficiently in the absence of a formal mechanism.
SoundResource now always fully initializes, the destructor no longer
accesses uninitialized memory, and an exists() method has been added
which callers now test.
SQ6 Mac can now progress past the main menu.
reg32_t was a transitive solution, before reg_t's were
adapted to use 32-bit addresses internally, and before
support for SCI3 was added. It was introduced as another
way to handle large script offsets in SCI3, and was only
used for the program counter (PC). It's no longer
needed, as we now support SCI3 script offsets using
reg_t's, so we can use make_reg32 in all cases where
we need to access offsets over 64KB
This flag is removed for a few reasons:
* Engines universally set this flag to true for widths > 320,
which made it redundant everywhere;
* This flag functioned primarily as a "force 1x scaler" flag,
since its behaviour was almost completely undocumented and users
would need to figure out that they'd need an explicit non-default
scaler set to get a scaler to operate at widths > 320;
* (Most importantly) engines should not be in the business of
deciding how the backend may choose to render its virtual screen.
The choice of rendering behaviour belongs to the user, and the
backend, in that order.
A nearby future commit restores the default1x scaler behaviour in
the SDL backend code for the moment, but in the future it is my
hope that there will be a better configuration UI to allow users
to specify how they want scaling to work for high resolutions.
See matchKernelBreakpointPattern() for samples. The main envisioned use is
DoSound*,!DoSoundUpdateCues
to match all DoSound sub-functions except DoSoundUpdateCues.