Difference between revisions of "Riven resources"
m (TOC) |
(this page just borrows the other pages and puts them together into a single page) |
||
Line 1: | Line 1: | ||
{{Riven}} | {{Riven}} | ||
− | This | + | This document talks about Riven resources controlling the game path and world; actually, it tries to document every resource other than [[Riven SFXE resources|SFXE]], [[Riven tBMP resources|tBMP]], [[Riven tWAV resources|tWAV]] and [[Riven tMOV resources|tMOV]]. |
− | + | ==Notes on stack switching== | |
− | + | The current stack can be changed from scripts using a special script command (27). For example, when the player activates a MagLev first the car movie is played, and then command 27 is called to change the current stack to the new island. This command is also used in the "Play Riven" button. However, most linking books actually change stack simply by moving to another card which has no buttons and no scripts. Apparently, there is some hardcoded mechanism inside the engine which triggers the stack change when one of these "special" cards is entered. These cards are listed here. | |
− | + | {| border=1 cellpadding=4 cellspacing=0 style="border:1px #000 solid;border-collapse:collapse;" | |
− | + | |- style="background:#CCC" | |
− | + | ! Stack !! Card ID !! Target stack !! Target card | |
− | + | |- | |
− | + | |bspit||447||ospit||1 | |
− | + | |- | |
− | + | |gspit||178||ospit||1 | |
− | + | |- | |
− | + | |jspit||228||rspit||3 | |
− | + | |- | |
− | + | |jspit||344||ospit||1 | |
− | + | |- | |
+ | |ospit||58||pspit||43 | ||
+ | |- | ||
+ | |ospit||62||jspit||341 | ||
+ | |- | ||
+ | |ospit||67||gspit||175 | ||
+ | |- | ||
+ | |ospit||72||bspit||444 | ||
+ | |- | ||
+ | |ospit||76||tspit||387 | ||
+ | |- | ||
+ | |pspit||46||ospit||1 | ||
+ | |- | ||
+ | |rspit||13||jspit||215 | ||
+ | |- | ||
+ | |tspit||392||ospit||1 | ||
+ | |} | ||
− | + | ==BLST, FLST, MLST, PLST, SLST== | |
− | + | These resources are lists and begin with an unsigned short telling the number of records. Then the records follow, and their structure depends on the resource type. There is one of these resources for each card; their ID matches the corresponding CARD resource ID. | |
− | + | ||
− | + | ===[[Riven BLST resources|BLST]]=== | |
+ | {{:Riven BLST resources}} | ||
+ | ===[[Riven FLST resources|FLST]]=== | ||
+ | {{:Riven FLST resources}} | ||
+ | ===[[Riven MLST resources|MLST]]=== | ||
+ | {{:Riven MLST resources}} | ||
+ | ===[[Riven PLST resources|PLST]]=== | ||
+ | {{:Riven PLST resources}} | ||
+ | ===[[Riven SLST resources|SLST]]=== | ||
+ | {{:Riven SLST resources}} | ||
+ | ==[[Riven HSPT resources|HSPT]]== | ||
+ | {{:Riven HSPT resources}} | ||
+ | ==[[Riven CARD resources|CARD]]== | ||
+ | {{:Riven CARD resources}} | ||
+ | ==[[Riven NAME resources|NAME]]== | ||
+ | {{:Riven NAME resources}} | ||
+ | ==[[Riven RMAP resources|RMAP]]== | ||
+ | {{:Riven RMAP resources}} | ||
+ | ==[[Riven VARS resources|VARS]]== | ||
+ | {{:Riven VARS resources}} | ||
+ | ==[[Riven VERS resources|VERS]]== | ||
+ | {{:Riven VERS resources}} | ||
+ | ==[[Riven ZIPS resources|ZIPS]]== | ||
+ | {{:Riven ZIPS resources}} |
Revision as of 04:35, 6 February 2008
Riven | |||
Mohawk | Overview | ||
BLST | CARD | FLST | HSPT |
MLST | NAME | PLST | RMAP |
SFXE | SLST | tBMP | tMOV |
tWAV | VARS | VERS | ZIPS |
Scripts | Variables | ||
External commands |
This document talks about Riven resources controlling the game path and world; actually, it tries to document every resource other than SFXE, tBMP, tWAV and tMOV.
Contents
Notes on stack switching
The current stack can be changed from scripts using a special script command (27). For example, when the player activates a MagLev first the car movie is played, and then command 27 is called to change the current stack to the new island. This command is also used in the "Play Riven" button. However, most linking books actually change stack simply by moving to another card which has no buttons and no scripts. Apparently, there is some hardcoded mechanism inside the engine which triggers the stack change when one of these "special" cards is entered. These cards are listed here.
Stack | Card ID | Target stack | Target card |
---|---|---|---|
bspit | 447 | ospit | 1 |
gspit | 178 | ospit | 1 |
jspit | 228 | rspit | 3 |
jspit | 344 | ospit | 1 |
ospit | 58 | pspit | 43 |
ospit | 62 | jspit | 341 |
ospit | 67 | gspit | 175 |
ospit | 72 | bspit | 444 |
ospit | 76 | tspit | 387 |
pspit | 46 | ospit | 1 |
rspit | 13 | jspit | 215 |
tspit | 392 | ospit | 1 |
BLST, FLST, MLST, PLST, SLST
These resources are lists and begin with an unsigned short telling the number of records. Then the records follow, and their structure depends on the resource type. There is one of these resources for each card; their ID matches the corresponding CARD resource ID.
BLST
They control which hotspots should be enabled and which disabled within the card.
Each BLST resource is a list of records; it starts with an unsigned short record count, followed by that many records. The record size is 6 bytes and follows this structure:
unsigned short | index | Record index, starting from 1 |
unsigned short | enabled | Hotspot state, 0 or 1 |
unsigned short | hotspot_id | Matches the blst_id field of the corresponding hotspot record |
BLST records must be "activated" from scripts, with command 43. Note that hotspots may exist without an associated BLST record. In that case, unless they are marked as Zip Mode hotspots and Zip Mode is off, they should just be enabled when entering the card.
FLST
They seem to specify which SFXE resource each card must use.
Each FLST resource is a list of records; it starts with an unsigned short record count, followed by that many records. The record size is 6 bytes:
unsigned short | index | Record index, starting from 1 |
unsigned short | sfxe_id | Resource ID of the corresponding SFXE |
unsigned short | u0 |
u0 is always zero. Changing it seems to have no effect.
FLST resources are very often empty (meaning no SFXE for that card) or with just one record.
MLST
Movie lists: they specify the movies to be used in the card and their placement.
Each MLST resource is a list of records; it starts with an unsigned short record count, followed by that many records. This is the record structure:
unsigned short | index | index of the record (starting at 1) |
unsigned short | movie_id | Resource ID of the corresponding tMOV movie |
unsigned short | code | Used by script commands to reference the movie record |
unsigned short | left | Movie position within the game window (pixels) |
unsigned short | top | |
unsigned short | u0[3] | |
unsigned short | loop | 0 or 1, 1 means the movie must loop forever |
unsigned short | volume | Volume of the movie sound track (details still unknown) |
unsigned short | u1 |
As for unknown fields: u0 seems always 0000 0000 ffff and u1 seems always 1. Changing them produces no observable effects.
PLST
PLSTs are bitmap lists: they tell which bitmap to draw and where to draw it within the card.
Each PLST resource is a list of records; it starts with an unsigned short record count, followed by that many records. The record structure is:
unsigned short | index | Record index, starting from 1 |
unsigned short | bitmap_id | Resource ID of the corresponding tBMP bitmap |
unsigned short | left | Rectangle to draw the bitmap into, in pixels |
unsigned short | top | |
unsigned short | right | |
unsigned short | bottom |
Like in BLSTs, the records must be "activated" from a script, using command 39. The first record is automatically enabled when entering the card, though: some cards have no PLST activation commands at all.
SLST
They contain ambient sound info for the card. Ambient sounds are arbitrary mixes of a number of sounds (for example wind + steam flowing in a pipe). Sounds are read from tWAV resources stored in the associated *_sounds.mhk archive (not in the same archive storing the SLST resource). For example, a SLST resource in a_Data will point to tWAV sounds stored in a_Sounds, not a_Data.
Each SLST resource is a list of records; it starts with an unsigned short record count, followed by that many records. The record structure is:
unsigned short | index | Record index, starting from 1 |
unsigned short | sound_count | How many sounds to mix |
unsigned short | sound_ids[sound_count] | tWAV resource IDs of the sounds to use |
unsigned short | fade_flags | |
unsigned short | loop | If set to 1, the mix loops forever |
unsigned short | global_volume | Volume of the resulting sound mix |
unsigned short | u0 | |
unsigned short | u1 | |
unsigned short | volumes[sound_count] | Volume for each sound component |
unsigned short | balances[sound_count] | Balance for each sound component (<0 left, 0 center, >0 right) |
unsigned short | u2[sound_count] |
fade_flags is a bit field controlling how to fade the sound channels when the record is activated. Bit 0 controls the fading out of any previous playing sound, bit 1 controls the fading in of the sound specified by the new record. For example, 3 would cause both sounds to fade, while 0 would suddenly stop the previous sound and immediately start the new one.
Volume ranges are not known exactly, values as high as 355 have been observed. Riven apparently keeps "scale factors" for sound volumes in its Riven.ini file (VolumeDivisorWin and VolumeDivisorMac).
u0 is usually 0 or 1, and changing it seems to do nothing. u1 is 0; giving it a non-zero value prevents sounds from playing. u2[] seems always 255 or 256 (for every sound component) and changing it seems to do nothing.
The first record is automatically enabled when entering the card, so it doesn't need to be activated from scripts.
Riven sound logic
This is an explanation of the Riven sound logic as it is currently understood.
Riven seems to maintain a set of playing sounds. Each sound has attributes, such as volume, panning, and fade flags. When an SLST record is activated, the set of playing sounds is updated with the set of sounds specified by the SLST record.
- Any sound present in the currently playing set and the SLST record set keep on playing, but their volume and pan attributes are updated.
- Any sound not present in the currently playing set but present in the SLST record gets added to the set of currently playing sounds. Appropriate fade-in is applied if specified by the sound flags.
- Any sound present in the currently playing set but not present in the SLST record gets removed from the set of currently playing sounds. Appropriate fade-out is applied if specified by the sound flags.
In-data-archive sounds ("instant sounds", or "foreground sounds") are kept in a separate set, since they never loop. They should not block script execution.
HSPT
These contain hotspots, sort of invisible buttons within cards that respond to mouse clicks (and other events) by performing actions described by attached scripts.
Each HSPT resource is a list of records and starts with an unsigned short equal to the number of records. Due to the attached scripts, HSPT records can have different size and there is no way to know it without fully decoding the record. Each record has the following structure:
unsigned short | blst_id | Links the hotspot to a BLST resource record |
short | name_rec | If ≥ 0, record index in NAME resource 2 to provide a name for the hotspot |
short | left | Hotspot rectangle within the game window, in pixels |
short | top | |
short | right | |
short | bottom | |
unsigned short | u0 | |
unsigned short | mouse_cursor | Cursor icon to set when the mouse rolls over this hotspot |
unsigned short | index | Record index starting from 1 |
short | u1 | |
unsigned short | u2 | |
variable size | script |
Hotspot rectangles can fall outside the game window (in any direction) and often two or more hotspots overlap. There are even cases with left > right (card 371, t_Data). When more hotspots overlap, the hotspot "on top" is the one with the largest index value.
Cursor icon values are listed on the right.
u0 seems always zero and changing it seems to leave Riven indifferent. u1 is very very often -1 but not always. u2 is 0 for ordinary hotspots, 1 for Zip Mode ones: the engine disables all Zip Mode hotspots when Zip Mode is off.
For info on the attached script see the scripts section.
CARD
CARD resources describe general properties of cards and associate a command script to each card. There is one CARD resource for each card, and its ID matches the card ID.
short | name_rec | If ≥ 0, record index in NAME resource 1 to provide a name for the card |
unsigned short | zip_mode_place | |
variable size | script |
zip_mode_place is usually 0; it's 1 when the card name is one of the special names used in ZIPS records. I think that if zip_mode_place = 1 then Riven stores the card name and ID in a new ZIPS record when the card is accessed, so that the place will be accessible using Zip Mode later.
For info on the attached script see the scripts section.
NAME
They contain a list of strings with an associated value, and their purpose is to store names for variables, cards, hotspots and other entities. They have the following structure:
unsigned short | field_count |
unsigned short | string_offsets[field_count] |
unsigned short | values[field_count] |
char* | strings |
strings is a list of zero-terminated strings. You can access string n by looking at string_offsets[n], which is the offset starting from strings (not from the beginning of resource data). The meaning of values[] is not yet known, but it seem to go from 0 to field_count-1 (not in sequential order). This field apparently has no function (the record index is important, instead).
In saved games there's only one NAME resource; it stores the name of each variable in the VARS (the record index in the NAME matches the one in the VARS).
In data files there are more NAMEs:
- ID 1 stores card names.
- ID 2 stores hotspot names.
- ID 3 stores external command names.
- ID 4 stores variable names. In this case, the record index is equal to the number used in script commands to access the variable.
- ID 5 stores stack names and it's used by command 27 to change island.
RMAP
There's just one RMAP resource per Mohawk file. Its function is to assign a unique code to each card. The resource is just a block of records, each having the following structure:
unsigned long | card_code |
The corresponding card is the one with resource ID equal to the record index, so the record count in the RMAP is equal to the greatest ID of CARD resources. The card code is used when going to another stack with command 27: it specifies the destination card in the new stack.
If you are familiar with the Riven debug shell, the CyanCardID value is exactly the card code specified in the RMAP resource.
VARS
The VARS resource is found in Riven saved game files (there is just one). It stores the state of every game variable. The data is just an array of 12-byte records, each representing a variable, with this structure:
unsigned long | u0 | |
unsigned long | type | 0 = unknown, 1 = integer |
unsigned long | value | Saved variable value |
u0 starts from 2, and seems to grow when going on with the game.
Fortunately, saved games contain a NAME resource that labels most variables in the VARS resource. The VARS record index simply matches the NAME one.
The number of records is not constant. If you save different games in different places then new records will appear, usually with u1 = 0 and strange values. However, "known" variables (dome combination, telescope levers state etc) are always at the same record.
VERS
This is found only in saved game files, and should just contain version information.
In the CD version, it contains the following 4 bytes, which probably means "version 1.0":
However, in the DVD version, it contains the following 4 bytes, which probably means "version 1.1":
ZIPS
Found only in saved games, this resource contains a list of visited locations to support the "Zip Mode". It starts with an unsigned short telling how many records will follow. Then, each record contains the following data:
unsigned short | name_len |
char | name[name_len] |
unsigned short | card_id |
Each record is linked to a card: card_id tells its ID, and name is equal to the card name. Zip Mode hotspots share the same name, so when they are clicked the target card ID can be known by looking up in the ZIPS. If the user already visited that card, the record will be there and the hotspot will be able to go to that card.