MADE: support games "Richard Scarry's B* Neighborhood Disc Ever!" - #7855
MADE: support games "Richard Scarry's B* Neighborhood Disc Ever!"#7855greg-kennedy wants to merge 14 commits into
Conversation
Print byte-arrays and word-arrays, attempting to detect ASCII in byte-arrays as well. Dump object contents as ASCII.
Add initial support for MADE engine games using V3.10 of the interpreter. This version is used for edutainment game "Richard Scarry's Best Neighborhood Disc Ever!" and its demo, but also for the MacOS port of Return to Zork (in big-endian). The demo of RSBESTNDE is somewhat playable, but some outstanding issues remain: * changes to the PMV movie format * three new extended opcodes, of which "MovieCall" and "SoundFile" are used extensively
MADE V3.1 games add a layer of RLE compression to video frames. Decompressing these first (according to the flags fields) allows RSBESTNDE / RSBUSYNDE to play videos correctly.
Add support for two external script function calls added by V3.1 games. * CursorXY: warp mouse cursor to the provided X/Y coordinates * SoundFile: load, decompress and play externally named sound file
sfMovieCall extension requires the ability to play one frame at a time. Split play() into separate load / decode / close, and wrap the previous behavion in play() by calling the new sub-functions.
Adds support for the sfMovieCall script function, which plays a movie, but also executes a script function on every frame. This makes the full versions of RSBUSYNDE / RSBESTNDE playable.
|
This is a re-do of my PR #7844 which I closed to change branch names, and focus more on just the Richard Scarry games rather than 3.1 as a whole. I did read the comments there and left some replies - let me know if any of those are unclear or warrant changes.
|
RLE decompression output size is unpredictable and the previous calculation for fixed buffers was incorrect in most cases. Use dynamic arrays instead, with static scope so they do not need to be re-allocated or deleted on every frame. Also silences a warning about A/V sync on the first frame of every movie.
Some scripts (specifically, sfMovieCall-invoked) want to read arguments passed in. A new ScriptInterpreter has no call frame setup, and so attempting to read args would peek out-of-bounds, returning uninitialized data instead. This commit changes runScript to set up a correct-looking call frame on the stack before executing, where args are put on the stack at the expected place. sfMovieCall sends one argument to the sub-function now, which is the ID of the playing movie. It isn't clear to me if this is correct or not: the script seems to check the value with ">= 0", so perhaps it is meant to be the remaining frame-count of the movie or the duration left. Regardless, sending a predictable positive value every time instead of uninitialized garbage fixes intermittent errors with RSBESTNDE / RSBUSYNDE skipping every movie at the first frame.
Screen mask is only used with V2 games and not needed here. Fixes up some other minor GID checked behaviors as well.
110b679 to
a540b3f
Compare
df245c8 to
e471f2a
Compare
PMV frame sizes are not always constant during a movie, and a smaller frame should blit to the top-left corner of the previous frame, leaving the right or bottom margin untouched. Change decompressMovieImage to accept a width and height argument, then use those when blitting. Fixes corrupted screen in RSBESTNDE (Demo) credits. Also removes `static` scope from byte arrays in RLE decompression functions. They are now allocated as-needed each frame and freed after use.
e471f2a to
35128dd
Compare
fusefib
left a comment
There was a problem hiding this comment.
First, great job putting this together and - as far as I see - in good working order. It's good if this gets in IMO.
I included a small file just to better highlight the small items of concern, there may be better solutions or some points may be invalid.
| close(); | ||
| } | ||
|
|
||
| return !aborted; |
There was a problem hiding this comment.
This may have to better account for load or decode failure? If load() fails, or decode_frame() breaks early, aborted is still false so play() reports successful completion.
There was a problem hiding this comment.
I'm going to leave this as-is, it matches the previous behavior. _aborted is only used to signal early user cancel. From the script's point of view, a movie that fails to load (or decode) looks like a movie that played all the way through uninterrupted.
Make some items auto-scope (stack) so they are cleaned up properly, consolidate PMVPlayer::load() error handling, fix movie frame number counting, call stopSound() before sfSoundFile
28d1d0c to
94932ef
Compare
| } | ||
|
|
||
|
|
||
| int ObjectV3_1::load(Common::SeekableReadStream &source) { |
There was a problem hiding this comment.
How is that different from ObjectV3::load()? Can't these two be merged?
There was a problem hiding this comment.
The diff. is in size calculation and the objects are laid out differently internally. V3 objects size field is 2 bytes (here "count1" and "count2" where count1 is the number of key/value properties on this object (class) and count2 is storage space assigned for values of inherited properties from parent objects. V3_1 simplifies this, size field is instead int16 which is a flat count of the number of key/value int16. Compare lines 202-203 to line 276.
The property lookup is also very different, V3 objects require looking for property ID on a Parent and then cross-ref. that to some storage area on the Child, whereas V3_1 is just a plain search, everything is right there on the obj. or it isn't.
I guess these could be merged with some kind of "sub version" flag but I am not sure that is any clearer to follow.
Some simplification based on PR feedback: GameDatabaseV3 now will accept both 3.00 and 3.10 files, differentiated by version ID loaded from file. Fixes MHED parsing in PMV to read framerate from correct field, eliminating sound sample rate patch as it is no longer needed with the correct frameDelay. sfMovieCall passes movie frame number to callback function instead of movie ID, this seems to match what the original engines do.
MADE: support games "Richard Scarry's B* Neighborhood Disc Ever!"
Adds some support for "version 3.1" MADE engine games (as determined
by internal text in
MADE.EXE:"MADE 386 CD-ROM Alpha V3.10 - Copyright (c) 1993, Activision")
Version 3.1 is used in a small handful of games: this PR focuses
on adding support for two previously un-emulated edutainment
titles "Richard Scarry's Best Neighborhood Disc Ever!"
and "Richard Scarry's Busiest Neighborhood Disc Ever!"
There is also a demo of Best Neighborhood Ever, available on
the 1.1 Activision CD for "Return to Zork". It is supported as well.
Getting these games working required the following changes:
are decompressed and then passed to the existing PMVPlayer, when indicated by flags.