The previous workaround value chosen to fix U8 bug #12913 really locked up
Crusader too long (>10 s), so there's no clean solution here that works for
both games it seems. Revert the threshold back for Crusader games only, and
keep the high threshold for U8. I hope the next time I touch this line is to
remove it because I work out the root cause of the problem :|
This fixes#12917.
The usecode "push byte" opcodes (0x0A and 0x5D) always push 16 bits on the
stack, but the ARG_UINT8 macro was only removing 1 byte. Most of the time this
went unnoticed because the UINT8 was the last argument in most cases (eg, a z
val), or unused.
This led to an inconsistency where sometimes z values were being popped with
ARG_UINT16 and sometimes ARG_UINT8. The original games do not support z values
beyond 254, so this should always be UINT8.
Additionaly, a while back "push byte" was fixed so it always sign extends, but
this could result in a case where we pop incorrect values. For example, a high
Z value could get sign-extended on push, and then popped back as a UINT16,
giving a z of 64000ish.
Fix by always moving the SP by 2 bytes, only use the first one.
Correcting this also fixes the strange color ordering I thought was needed for
I_jumpToAllGivenColor in Crusader: No Regret, where actually it should have
been popping the values as 16-bit instead of 8-bit.
The original game allows you to turn while retreating, but that was not
previously possible.
To make the turn always possible, step() now does not wait for the movement
animation. This should work as AvatarMoverProcess::run terminates early if the
Avatar is busy.
There were two differences to the original which caused occasional targeting
mishaps:
1. The reticle and actual shots were using different starting positions for
the shot (Avatar centre vs Avatar corner)
2. Z difference was not being taken into account when finding the "best" target
This fixes both problems.
The `shieldCost` field from the firetype table should be used to subtract from
shields, not the weapon damage. Normally shieldCost is a larger value, so it
affects game difficulty a lot.
The NPCs should get randomly harder weapons at No Remorse difficulty level, but
this never happened because I missed a line in the original to reset the "alt"
weapon type in this case.
After rechecking, the original game has expendable BA-40 ammo on every
difficulty above *1*, not *2*. Confirmed in dosbox and the disassembly
(function at 13c8:2975).
Bug #12880. The BA-40 should consume ammo in the higher 2 difficulty levels
for Crusader: No Remorse. A similar change is probably needed for No Regret,
but it will be done separately.
As reported in #12913, the current process loop detection can incorrectly fire
on certain U8 map transitions. Bump the threshold way up to avoid problems.
This will result in a nasty pause in Crusader: No Remorse Map 3, but it's
better than breaking U8.
Because the games have different global sizes, the logic for when to print a
pop-to-global warning was wrong. It should warn for size > 2 in Crusader
(where the globals are *bytes*), or if the size popped doesn't fit in
the number of *bits* for U8.
A few people have not noticed that the GOG version includes a CD image and some
files need to be taken from there. This should help those people.
The same problem will happen for anyone who has an old install of the game and
forgets that it uses some files from the CD.
In the original game, while walking or running even a very brief tap on the
arrow key will always result in a turn. Now we do that too by remembering a
tap happened.
Fixes Mordea disappearing during wake-up game event (#12803).
The proper fix here is maybe to never let items fall below 0, which I think is
how the originals work, but that could have significant other impacts I'm not
sure about, so for now just refine the workaround.
The Journey Onwards menu option would not actually load a savegame if the user
selected it from the main menu; it would just start a new game. Changed this to
loading the savegame in the last slot used for saving. This fixes bug #12531.
The yes/no dialog would not pass a pointer to itself as a data parameter to the
callback when an otherwise unhandled key was pressed. Events::callback needs
this pointer to clear the dialog and would dereference the null data parameter.
Fixed this by adding the missing parameter. This fixes bug #12533.
The original has 2 ways to start a new game:
1. start from dos -> intro movies -> difficulty menu -> voice mail movie
-> game
2. playing game (press esc) -> game menu (new game) -> difficulty menu
-> voice mail movie -> game
We now match those sequences correctly.
There is one difference still - if you have a saved game, we will by default
load that. Previously the game jumped straight into that, but since there is
now no other way to see the intro movies again, now they are always shown
first. So the 3rd flow is (if you have a save game):
3. start scummvm -> intro movies -> game
Since some people might want to just jump straight into the game, I also added
a skip_intro config file setting which will skip the movies in this case.
Fixes#12758.
Some music transitions are intended to play on top of the currently playing
track (mostly fade-outs). ScummVM would stop the current track and then play
the transition. This commit changes this so it overlays the transitions like
the original interpreter does.
The music transition numbers from the song info data were incorrectly parsed.
For overlaid transition numbers starting with !, the first character is
skipped when parsing the number, but this was also done for instant transition
numbers which do not start with !, resulting in incorrect numbers. Also, the
overlaid transition numbers were 1 lower than what the music process was
expecting.
After a transition was started, the music process' run method would immediately
stop the transition and start the next track. This is fixed by waiting for the
transition to finish before starting the next track.
Silencer is the player-character and so should probably be capitalized - I had
capitalized it in other places in the code and comments.
Also added a I18N comment so translators know what it is.
When showing the ScummVM menu using Ctrl-F5, gameplay in Ultima 8 would pause,
but MIDI music would continue to play (AdLib would pause) and sound effects
would finish playing as well. This commit pauses all music and digital audio
when the ScummVM menu is shown.
In the Ultima 8 intro, the last music track fades out in the original
interpreter, but in ScummVM it stopped abruptly. This seems to be because the
SKF_SlowStopMusic action was not fully implemented. This commit adds an
implementation to this action, which restores the fade-out in the intro.
The SFX and speech user volume controls for Ultima 8 did not work because
digital audio was played using the plain sound type instead of SFX or speech.
To distinguish between the two, a flag was added to the AudioChannel::playSample
function to indicate if the sample is a sound effect or speech.
Ultima 8 uses MIDI, but the MIDI configuration tabs were disabled. This commit
enables the MIDI configuration by removing the GUIO_NOMIDI flag from the
detection entries.
To make the Ultima 8 AdLib music sound like the original interpreter, the
MidiPlayer class has been updated to use the Miles MIDI drivers. This allows
the game's AdLib instruments to be used. Because the Audio::MidiPlayer does not
work well with the Miles drivers, I've removed the dependency on this class and
implemented the necessary functionality in the Ultima 8 MidiPlayer.
This also makes the code independent of the user's locale (being
dependent on that by accident can lead to difficult to track down bugs)
The list of whitespace used now is what the C standard guarantees as
minimal set of characters accepted by `isspace` as whitespace.
This employs a "lazy" approach: the "format" for the credits stays
exactly as it was, i.e., perl code. Of course one may want to change
this to another format (e.g. YAML, JSON, XML; or also shell script or
AWK, like `configure.engine` uses). But I deliberately kept it simple,
to get a minimal change that is easy to verify. Any further changes to
e.g. the format can be layered atop this.
Previously we set the camera process to follow the robot, but it should snap to
the robot's location and then use the SnapProcess to update location in chunks.
There were some small differences from the original as to when attacks should
be triggered from Pace and Guard. This should improve them to be more like
original.
Color 0 on the palette is not black in all versions of the game, so we need to
force the background color. This is not a super-efficient way to do it, but it
works ok.