Skip to content

Engine Restrictions

Mike Roibu edited this page Jan 9, 2023 · 2 revisions

These restrictions are baked into the game engine/interpreter itself (both ScummVM and original usually); an updated version of the interpreter could remove these restrictions but keeping compatibility with the original game would be tough.

  1. Resolution is 640px by 400px.
    1. The bottom 48 pixels are the inventory menu, but it can be hidden via flags.
    2. The drawable backdrop (largest room width/height) is defined at the game level but can be larger than the screen (it will scroll). (The value may need to be specifically 1996 x 544 which is what the original game uses.)
  2. The in-game font is hard-coded into the game engine.
    1. There are separate fonts for the few languages the game was localised to
    2. Some of the languages (French) also have special logic attached
    3. This font is used for everything (options menu, quit dialog, conversation menu, action menu, speech entries)
    4. The rendered text is drawn with two colours from the loaded palette (one fill - generally used, one border - generally black)
  3. Hiding the inventory menu generally works, however:
    1. Entering/leaving conversations with the inventory menu hidden will cause a crash.
    2. Un-hiding the inventory menu will cause incorrect drawing to the screen until the screen is cleared or a redraw is forced.
  4. The Z-depth for positions is calculated differently in the two systems:
    1. When drawn, a sprite scaling table is built (in a set of 250 steps in either direction) that leads to particular Width/Height values
    2. When clicking on the screen, the Z value is used directly (dividing against the "even" Z-depth at 160) that leads to different Width/Height values
  5. The colour palette for each screen is limited to less than 255 colours, with lots of specific restrictions:
    1. Colour 0 is reserved for transparency, and always stays transparent when drawn.
    2. Colour 64 is reserved for sprite markers, and always stays transparent when drawn.
    3. Colour 255 is reserved for two uses: on room images it is used for room width markers (stays transparent when drawn), otherwise it is available as a colour to be used for UI text/hover colours.
    4. Colours 1-254 can all be used for room images (with 255 as the room width marker).
    5. Colours 193-255 can be used for sprite images (with specific fixed values below).
    6. Colour 210 is always used for the inventory background (and should match the inventory sprites).
    7. Colour 214 is always used for the text colour in the conversation section.
    8. Colour 217 is always used to draw the money amount in the inventory; setting it to the same as the inventory background colour will effectively remove it.
    9. Colour 248 is always used for the action menu background (and should match the action menu sprite).
    10. Colour 249 is always used for the action menu text when not hovered (colour 255 is always used when hovered).
    11. The palette is set per room image, but includes the sprite colours, therefore there is a limited number of sprite colours that have to cover all potential sprites that want to be on the screen (and the indexes of the sprite colours cannot change between screens because the sprite image data remains the same).
  6. The number of resources in each game is limited strictly (however there may be limitations that also lower the count below this):
    1. 100 Room Images
    2. 30 Sequences
    3. 50 Sprite Images
    4. 100 Icon Images
    5. 80 Room Info entries (which means 20 room images may not be usable)
    6. 150 Programs
    7. 50 Music tracks
    8. 120 Sounds
  7. There are certain resources that are fixed and always automatically used (potentially also with some restrictions):
    1. Sprite Image 18 is used as the background of the Action menu (in a particular pattern)
    2. Sprite Image 19 is used as the background of the Conversation menu (in a particular pattern)
    3. Sprite Image 12 is used as the background of the Inventory 1 (overwhelmingly the one used)
    4. Sprite Image 13 is used as the background of the Inventory 2 (only used in certain scenarios)
    5. Sprite Image 14 is used as the background of the Inventory 3 (only used in one particular scenario)
    6. Icon Image 0 is used as the default mouse cursor (when not grabbing an item)
    7. Icon Image 1 is used as the mouse cursor when grabbing money specifically
    8. The other Icon Images are used as the mouse cursor or when drawing the inventory to represent the relevant inventory item ID
    9. Program 90 is always loaded by default when a new game is started
  8. Resource sizes are limited in some respects:
    1. Sprite Image 18 must be 42x120 pixels
    2. Sprite Image 19 must be 152x80 pixels
    3. Sprite Images 12-14 must be 640x48 pixels
    4. All Icon Images must be 58x42 pixels
    5. All Programs must be under 61440 bytes long
    6. All Sequences must be under 16000 bytes long
  9. Programs (of which there is only one loaded at a time) contain a lot of general data, and have some restrictions:
    1. The first Rect is used as the default clipping rectangle for the screen so should generally be (0, 0, 640, 400)
    2. The first Point is generally ignored and left at (0, 0)
    3. There should always be the relevant Hitboxes set to each valid inventory item for any item you may have access to at that point in the game
  10. Sequences contain animation and movement data and are not tied to specific sprite images explicitly, but have some restrictions:
    1. Only animation 1 may have Y/Z movement values; any other animation will have its Y/Z movement ignored but X working as normal.
    2. Animation 0 is always used as the idle/standing animation and should have a single frame (idle animations are done via separate calls)
    3. Animation 1 is always used as the movement animation and dictates the speed of movement (factored against the Z value shrinking/increasing the amount)
    4. Vertically flipping a part is specified in the data but not implemented (at least in ScummVM) or used in the original game
    5. Part data references a specific index within a sprite sheet, which means it is not usable with a sprite sheet unless tailored to it (same format/layout)
    6. Each animation may have at most 15 frames
    7. Each animation has a direction attached, and direction 3 (left) always flips the image horizontally/movement X value
    8. Y movement values are ignored in the data, instead Z movement values are used and the decision over whether to move on Y or Z is done based on delta of either
  11. A large number of instructions in the interpreter language have been implemented with assumptions like "the current key character is ID 0" or "the current inventory is 0" (some may only be in ScummVM, in which case they were not used in the original game).
  12. Key Characters in a scene have some restrictions:
    1. Key Character 0 is generally the player character, needs to exist (or else lots of things will fail), and is the one that runs the main game script
    2. Instructions like InitChar (which would remove a character) cannot be run against Key Character 0 without unintended consequences (like restarting the game script or asserts)
    3. Some instructions target one Key Character and the next one (e.g. setting the parameter to Key Character 1 would then mean the second target is Key Character 2)
    4. Key Characters may have a Character Script Offset defined in the current running Program which allows them to run a game script themselves; this script will run in the background after the main game script pauses, and is allowed to specifically restart running once done
    5. Non-0 Key Character scripts may have unintended consequences if they run some instructions (because they assume the current running script is the main one, or that the current character is 0)
  13. There is a Key Character-based inventory system (not for inventory items) with some restrictions:
    1. Each Key Character has 4 "counted" inventory amounts (e.g. you own X of 1) that are settable/gettable via SetInventoryItem/GetInventoryItem instructions; they are not used anywhere else and the original game does not seem to use them
    2. Each Key Character also has a "money" inventory amount (technically the 5th "counted" inventory amount) that is settable/gettable via SetInventoryItem/GetInventoryItem and other ways, is automatically rendered to the inventory and is usable in various interactions; the original game effectively stops using it after the first 10 minutes of gameplay
  14. There is an inventory system for 100 inventory items (not including money/Key Character inventory) with some restrictions:
    1. There are 2 main inventory lists that map loosely to the first two Key Characters; inventory 0 is generally the one that is used automatically
    2. There is an additional third inventory list that is restricted to fewer items (6) and is only used via a particular instruction for a particular interaction in the original game
    3. Each inventory list maps to the relevant fixed sprite
    4. The main inventory lists can contain up to 100 items and each store a scroll state that allows scrolling left/right; only 6 items may be accessible at one time
    5. In addition there is a main inventory mapping that points to which inventory list contains each item (if any), so no item duplication should be possible
    6. The process of moving an item from one main inventory list to another is full of issues and bugs and could lead to duplicated or broken items
    7. The 100 inventory items directly map to the 100 icons in the game but otherwise only have an ID (no menu/actions/description)
    8. The 100 inventory items only indirectly get an action menu/description/etc only when paired with a configured inventory Hitbox in the current running Program
  15. There is a Flag system used for logic and interaction that has a number of restrictions:
    1. Flag 600 is updated off-cycle to be the key code of the most recently pressed key (when key events are being handled)
    2. There are a large number of fixed flags that enable/disable various functionality, some of which are updated via explicit instructions like StartPaletteFadeIn, others that are set as flag values directly
    3. Flags 200 to 299 are all set to 0 (or specific values for 291, 292, 293, 294) whenever a new Program is loaded; they are the only ones suitable for transient Program-specific storage
    4. Flag 911 would in the original game engine run some logic for loading external data files, this is not implemented in ScummVM
  16. Gameplay limitations:
    1. Only 32 Key Characters may be initialised at any one time; with 0 (and potentially 1) being reserved for various purposes
    2. Only 7 Sprite Images may be loaded for use as any Key Character's sprite sheet at any one time; the same sheet may be used for multiple characters via Sequence data
    3. Only 7 Sequences may be loaded for use as any Key Character's animation/character data at any one time; the combination with the sprite sheet could create a limited set of 32 Key Characters that share enough sprite sheets/animations
    4. Loaded Sprites and Sequences 6 and 7 are always cleared when loading a new Room Image, but the others are not
    5. Only 40 potential Conversation Choices may exist under any particular Conversation (stopping and starting a new Conversation is a workaround)
    6. Only 15 simultaneous lines of dialogue may be in play at once before an assert triggers
    7. When animating the main Key Character (0), the part referenced on the sprite sheet may not be of index higher than 134 (e.g. if the sprite sheet has 10 x 20 objects on it, objects above 134 would assert when drawing); this limitation is strictly limited to the main Key Character (0) - potentially only an issue in ScummVM
    8. The main Key Character (0) starts with 25 "money" already set when starting a new game.
    9. When the Action Menu is open, the game suspends all processing of the game script/re-rendering/etc and runs a minimised gameplay loop only waiting for a selection
    10. There are a large number of workarounds in ScummVM code (that do not exist in the original game engine) specifically set to target the original game and its bugs
    11. Saving/loading involves saving the entire game state up to and including loaded Program, Flags, etc
  17. Movement limitations:
    1. The loaded Program determines the list of Points and Walks that Key Characters can use to move around, not the loaded room; usually each Program will have one "main" room then but disconnected graphs should technically work
    2. When a movement is attempted from one Point to another Point, the graph of Walks is ordered (and this ordering is saved as state in the Walk list) and used to find the shortest route
    3. Based on the Walk graph ordering data (when choosing to move) or a delta of position (when following, etc), a desired direction of the Key Character movement is determined, and they are set to animation 1 with the specified direction; no movement happens as a result yet
    4. Only based on the current animation and its movement data, a Key Character will move in whatever direction its animation specifies (whether it is towards or away from the target point) in a single direction (X, Y or Z)
    5. If a Key Character has moved and the movement is towards a specific Point, then after this movement an adjustment is made to correct all 3 coordinates (X/Y/Z) such as to 'interpolate' its movement along the Walk graph
    6. Two points with the same X and Y (occupy the same space), but different Z (different depths), can have a Walk assigned; walking along this line will mean the character becomes smaller/larger
    7. A Walk may have a Clipping Rectangle assigned (stops character being drawn outside it while walking on that line), or an Area assigned (after Key Character is drawn while walking on that line, that background Area is also redrawn on top); these two effects can give 3D-like hiding/partial transparency of room objects based on depth
    8. The speed of a Walk is dependent on the smallest delta of any of its coordinates due to how the adjustment happens; so two points that are 200 points away in X and 200 points away in Y; you might move nearly instantly from one to the other if they're only 2 points away in Z. But if you make the Z value be the same, it'll take a lot longer.

Clone this wiki locally