Difference between revisions of "SCUMM/V5 opcodes"
Jestar jokin (talk | contribs) (→SCUMM V5 opcodes: Formatting, added basic branches, arithmetic) |
m (behaviour -> behavior) |
||
(56 intermediate revisions by 2 users not shown) | |||
Line 3: | Line 3: | ||
{| border="1" cellpadding="2" width=100% | {| border="1" cellpadding="2" width=100% | ||
|- style="background:whitesmoke" | |||
|- | |Term||Description | ||
|- | |||
|opcode||The instruction's opcode, with the appropriate bits set according to the parameters. | |opcode||The instruction's opcode, with the appropriate bits set according to the parameters. | ||
|- | |||
|aux||An aux opcode that stores parameter bits and no other information. (the base aux opcode is usually $01, but can differ for each instruction) | |||
|- | |||
|sub-opcode||An aux opcode that indicates a specific function to perform (e.g. the "wait" instruction has sub-opcodes to "wait for message", "wait for actor" etc), as well as storing parameter bits if necessary. | |||
|- | |- | ||
|result||A result pointer. (A standard word pointer, always a LE word.) | |result||A result pointer. (A standard word pointer, always a LE word.) | ||
|- | |- | ||
|var||A | |var||A variable pointer. Same as above, but is not written to. Because this is always a variable, the opcode is not affected like it would be with a normal parameter (described below). | ||
|- | |- | ||
|value[8]||An 8-bit constant (a byte). | |value[8]||An 8-bit constant (a byte). | ||
Line 17: | Line 22: | ||
|value[p8]||An 8-bit parameter. This may be encoded as a word LE if it's a pointer, or a byte if it's a constant. | |value[p8]||An 8-bit parameter. This may be encoded as a word LE if it's a pointer, or a byte if it's a constant. | ||
|- | |- | ||
|value[p16]||A 16-bit parameter. This is always encoded as a word LE. | |value[p16]||A 16-bit parameter. This is always encoded as a word LE, and may be a pointer or constant. | ||
|- | |- | ||
|value[v16]||A variable number of word LE parameters. These are encoded as a sequence of aux[8] param[p16]; param; aux contains the parameter bit to describe param. A byte of $FF terminates the sequence. | |value[v16]||A variable number of word LE parameters. These are encoded as a sequence of aux[8] param[p16]; param; aux contains the parameter bit to describe param (and is always $01, ignoring the parameter bits). A byte of $FF terminates the sequence. (actually always shown as "value[v16]...") | ||
|- | |- | ||
|value[o]||The offset word for parameter value. This is only encoded if needed, but always at the position indicated. If not specified, the offset word occurs immediately after the parameter. | |value[o]||The offset word for parameter value. This is only encoded if needed, but always at the position indicated. If not specified, the offset word occurs immediately after the parameter. | ||
|- | |- | ||
| | |value[c]||An ASCII character. Because some instructions use null-terminated strings and some use $FF, the exact format of a string is described in the instruction. Almost always appears as "value[c]..." | ||
|- | |- | ||
| | |term...||One or more terms. | ||
|} | |} | ||
Of course, due to the non-orthogonality of the opcodes, there are lots of exceptions. | Of course, due to the non-orthogonality of the opcodes, there are lots of exceptions. | ||
==actorFollowCamera ($52)== | ==actorFollowCamera ($52)== | ||
===Encoding=== | |||
opcode actor[p8] | |||
===Operation=== | |||
Sets the camera to follow the given actor? | |||
==actorFromPos ($15)== | ==actorFromPos ($15)== | ||
== | ===Encoding=== | ||
opcode result x[p16] y[p16] | |||
===Operation=== | |||
Returns the actor located at the given co-ordinates. | |||
==actorOps ($13)== | |||
parameters depend on auxiliary opcode; terminated by $FF | |||
===Encoding=== | |||
opcode actor[p8] sub-opcode... $FF | |||
sub-opcodes: | |||
$00 arg1[p8] | |||
$01 costume[p8] | |||
$02 xspeed[p8] yspeed[p8] | |||
$03 sound[p8] | |||
$04 walkframe[p8] | |||
$05 starttalk[p8] endtalk[p8] | |||
$06 standframe[p8] | |||
$07 arg1[p8] arg2[p8] arg3[p8] | |||
$08 | |||
$09 elevation[p16] | |||
$0A | |||
$0B index[p8] value[p8] | |||
$0C color[p8] | |||
$0D name[c]... $00 | |||
$0E initframe[p8] | |||
$10 width[p8] | |||
$11 xscale[p8] yscale[p8] | |||
$12 | |||
$13 zplane[p8] | |||
$14 | |||
$15 | |||
$16 animspeed[p8] | |||
$17 shadow[p8] | |||
===Operation=== | |||
Miscellaneous actions on actors. | |||
{| border="1" cellpadding="2" width=100% | |||
|- style="background:whitesmoke" | |||
|Opcode||Meaning||Description | |||
|- | |||
|$00||dummy||A dummy case, does nothing (in ScummVM). | |||
|- | |||
|$01||SO_COSTUME||Sets the actor's costume. | |||
|- | |||
|$02||SO_STEP_DIST||Sets the actor's walking speed for x and y. | |||
|- | |||
|$03||SO_SOUND||Associates a sound with the actor (footsteps?) | |||
|- | |||
|$04||SO_WALK_ANIMATION||Sets the current frame of the walking animation. | |||
|- | |||
|$05||SO_TALK_ANIMATION||Sets the start and stop frames of the talking animation. | |||
|- | |||
|$06||SO_STAND_ANIMATION||Sets the current frame of the standing animation. | |||
|- | |||
|$07||SO_ANIMATION||Unknown; seems to be unused in ScummVM. | |||
|- | |||
|$08||SO_DEFAULT||Initializes actor. | |||
|- | |||
|$09||SO_ELEVATION||Sets the actor's elevation to the given value. | |||
|- | |||
|$0A||SO_ANIMATION_DEFAULT||Initializes the actor's animation frames.<br>Init frame = 1<br>Walk frame = 2<br>Stand frame = 3<br>Talk start frame = 4<br>Talk stop frame = 5 | |||
|- | |||
|$0B||SO_PALETTE||Sets the color at the given index to a new value (another entry in the color lookup table/CLUT). Index must be between 0 and 31 (the number of colors in a costume). | |||
|- | |||
|$0C||SO_TALK_COLOR||Sets the actor's talk color. | |||
|- | |||
|$0D||SO_ACTOR_NAME||Sets the actor's name to the given null-terminated string. | |||
|- | |||
|$0E||SO_INIT_ANIMATION||Sets the current frame of the initial animation. | |||
|- | |||
|$10||SO_ACTOR_WIDTH||Sets the actor's width. | |||
|- | |||
|$11||SO_ACTOR_SCALE||Sets the actor's X and Y scales. | |||
|- | |||
|$12||SO_NEVER_ZCLIP||Turns off all Z-clipping for the actor. | |||
|- | |||
|$13||SO_ALWAYS_ZCLIP||Forces the actor's Z-clipping for the given Z-plane? | |||
|- | |||
|$14||SO_IGNORE_BOXES||Ignores boxes, turns off Z-clipping, and puts actor somewhere if the actor is in the current room? | |||
|- | |||
|$15||SO_FOLLOW_BOXES||Follows boxes, turns off Z-clipping, and puts actor somewhere if the actor is in the current room? | |||
|- | |||
|$16||SO_ANIMATION_SPEED||Sets the animation speed. | |||
|- | |||
|$17||SO_SHADOW||Sets the shadow mode. | |||
|} | |||
===Variants=== | |||
In SCUMM V3 and V4, the opcode values are slightly different. | |||
{| border="1" cellpadding="2" width=50% | |||
|- style="background:whitesmoke" | |||
|Opcode||Meaning | |||
|- | |||
|$00||dummy | |||
|- | |||
|$01||SO_COSTUME | |||
|- | |||
|$04||SO_STEP_DIST | |||
|- | |||
|$05||SO_SOUND | |||
|- | |||
|$06||SO_WALK_ANIMATION | |||
|- | |||
|$07||SO_TALK_ANIMATION | |||
|- | |||
|$08||SO_STAND_ANIMATION | |||
|- | |||
|$09||SO_ANIMATION | |||
|- | |||
|$0A||SO_DEFAULT | |||
|- | |||
|$0B||SO_ELEVATION | |||
|- | |||
|$0C||SO_ANIMATION_DEFAULT | |||
|- | |||
|$0D||SO_PALETTE | |||
|- | |||
|$0E||SO_TALK_COLOR | |||
|- | |||
|$0F||SO_ACTOR_NAME | |||
|- | |||
|$10||SO_INIT_ANIMATION | |||
|- | |||
|$12||SO_ACTOR_WIDTH | |||
|- | |||
|$13||SO_ACTOR_SCALE | |||
|- | |||
|$14||SO_IGNORE_BOXES | |||
|} | |||
Also in V3 and V4, sub-opcode $13 (SO_ACTOR_SCALE) only takes one parameter, so X and Y scaling is done at a 1:1 ratio. | |||
==actorSetClass ($5D)== | ==actorSetClass ($5D)== | ||
===Encoding=== | |||
opcode object[p16] classes[v16]... | |||
===Operation=== | |||
Makes object inherit from all of the given classes. A class of "0" will clear all of the object's existing class data. | |||
==add ($5A)== | ==add ($5A)== | ||
===Encoding=== | ===Encoding=== | ||
opcode result value[p16] | |||
===Operation=== | ===Operation=== | ||
result := result + value | |||
The variable pointed to by result is read, value is added to it, and the result written back. | The variable pointed to by result is read, value is added to it, and the result written back. | ||
==and ($17)== | ==and ($17)== | ||
one parameter, uses result | one parameter, uses result | ||
===Encoding=== | ===Encoding=== | ||
opcode result value[p16] | |||
===Operation=== | ===Operation=== | ||
result := result and value | |||
The variable pointed to by result is read, logically ANDed with value, and the result written back. | The variable pointed to by result is read, logically ANDed with value, and the result written back. | ||
==animateActor ($11)== | ==animateActor ($11)== | ||
== | ===Encoding=== | ||
opcode actor[p8] anim[p8] | |||
===Operation=== | |||
Starts the given animation for the given actor. | |||
==breakHere ($80)== | |||
no parameters | |||
===Encoding=== | |||
opcode | |||
===Operation=== | |||
Deschedules the currently running thread. Execution continues at the next instruction when the thread's next timeslot comes around. | |||
==chainScript ($42)== | |||
one parameter plus varargs | |||
===Encoding=== | ===Encoding=== | ||
opcode script[p8] args[v16]... | |||
===Operation=== | ===Operation=== | ||
Miscellaneous actions on | Replaces the currently running script with another one. The current script is terminated immediately and the new script (determined by the given script ID), is executed in the same thread. The new script has its local variables initialised to the list args. Uninitialised variables have undefined values. | ||
==cursorCommand ($2C)== | |||
parameters depend on auxiliary opcode | |||
===Encoding=== | |||
opcode sub-opcode | |||
sub-opcode can be any of the following: | |||
$01 | |||
... $01 through $08 take the same arguments ... | |||
$08 | |||
$0A cursornum[p8] charletter[p8] | |||
$0B index[p8] x[p8] y[p8] | |||
$0C cursor[p8] | |||
$0D charset[p8] | |||
$0E colors[v16]... | |||
===Operation=== | |||
Miscellaneous actions on cursors & charsets. | |||
{| border="1" cellpadding="2" width=100% | {| border="1" cellpadding="2" width=100% | ||
|- style="background: | |- style="background:whitesmoke" | ||
|Opcode||Meaning||Description | |Opcode||Meaning||Description | ||
|- | |- | ||
|$01|| | |$01||SO_CURSOR_ON||Turns the cursor on. | ||
|- | |||
|$02||SO_CURSOR_OFF||Turns the cursor off. | |||
|- | |||
|$03||SO_USERPUT_ON||Enables user input. | |||
|- | |||
|$04||SO_USERPUT_OFF||Disables user input. | |||
|- | |||
|$05||SO_CURSOR_SOFT_ON||Increments the cursor's state? | |||
|- | |||
|$06||SO_CURSOR_SOFT_OFF||Decrements the cursor's state? | |||
|- | |||
|$07||SO_USERPUT_SOFT_ON||Increments "user input" counter (when greater than 0, user input is enabled). | |||
|- | |||
|$08||SO_USERPUT_SOFT_OFF||Decrements "user input" counter (when 0 or less, user input is disabled). | |||
|- | |||
|$0A||SO_CURSOR_IMAGE||Changes the cursor image to a new one, based on image in a character set. Only used in Loom. | |||
|- | |- | ||
|$ | |$0B||SO_CURSOR_HOTSPOT||Changes the hotspot of a cursor. Only used in Loom. | ||
|- | |- | ||
|$ | |$0C||SO_CURSOR_SET||Changes the current cursor. Must be between 0 and 3 inclusive. | ||
|- | |- | ||
|$ | |$0D||SO_CHARSET_SET||Initializes the given character set. | ||
|- | |- | ||
|$ | |$0E||SO_CHARSET_COLORS||Initializes the character set data & colors to the given arguments? Must have 16 arguments? | ||
|} | |} | ||
== | ===Variants=== | ||
In SCUMM V3, sub-opcode $0E performs a different function, to load/initialize a character set. | |||
opcode $0E arg1[p8] arg2[p8] | |||
== | ==cutScene ($40)== | ||
===Encoding=== | ===Encoding=== | ||
opcode args[v16]... | |||
===Operation=== | ===Operation=== | ||
??? If required, runs a script passing the given arguments. Cutscene data given by the first argument? | |||
==debug ($6B)== | ==debug ($6B)== | ||
one parameter, no result | one parameter, no result | ||
===Encoding=== | ===Encoding=== | ||
opcode param[p16] | |||
===Operation=== | ===Operation=== | ||
Passes the parameter to the interpreter's debugger. What this does is entirely platform-specific (and may do nothing). | Passes the parameter to the interpreter's debugger. What this does is entirely platform-specific (and may do nothing). | ||
==decrement ($C6)== | ==decrement ($C6)== | ||
no parameters, uses result | no parameters, uses result | ||
===Encoding=== | ===Encoding=== | ||
opcode result | |||
===Operation=== | ===Operation=== | ||
result := result - 1 | |||
Reads the variable pointed to by result, decrements it, and writes it back. | Reads the variable pointed to by result, decrements it, and writes it back. | ||
==delay ($2E)== | ==delay ($2E)== | ||
one constant parameter | one constant parameter | ||
===Encoding=== | ===Encoding=== | ||
opcode param[24] | |||
===Operation=== | ===Operation=== | ||
Suspends the current thread for the appropriate number of 1/60ths of a second. Yes, that really is a 24-bit LE constant. | Suspends the current thread for the appropriate number of 1/60ths of a second. Yes, that really is a 24-bit LE constant. | ||
==delayVariable ($2B)== | |||
one constant parameter | one constant parameter | ||
===Encoding=== | ===Encoding=== | ||
opcode var | |||
===Operation=== | ===Operation=== | ||
var is dereferenced and the current thread suspended for that number of 1/60ths of a second. | |||
==divide ($5B)== | ==divide ($5B)== | ||
one parameter, uses result | one parameter, uses result | ||
===Encoding=== | ===Encoding=== | ||
opcode result value[p16] | |||
===Operation=== | ===Operation=== | ||
result := result / value | |||
The variable pointed to by result is read, divided by value, and the result written back. If value is zero, the result is undefined (and the interpeter may halt with an error). | The variable pointed to by result is read, divided by value, and the result written back. If value is zero, the result is undefined (and the interpeter may halt with an error). | ||
==doSentence ($19)== | ==doSentence ($19)== | ||
===Encoding=== | |||
opcode verb[p8] objectA[p16] objectB[p16] | |||
===Operation=== | |||
Performs a verb sentence action, e.g. "Use monkey on hydrant". If verb is $FE, the current sentence script is stopped, status cleared etc. | |||
==drawBox ($3F)== | ==drawBox ($3F)== | ||
two parameters, does not use result, supplementary opcode byte with three more subsequent parameters | two parameters, does not use result, supplementary opcode byte with three more subsequent parameters | ||
===Encoding=== | ===Encoding=== | ||
opcode left[p16] top[p16] auxopcode[8] right[p16] bottom[p16] color[p8] | |||
===Operation=== | ===Operation=== | ||
Draws a solid box on the backbuffer from (left, top) | Draws a solid box on the backbuffer from (left, top) to (right, bottom) in the given color. | ||
The only part of auxopcode that is relevant are the parameter bits. The rest of the opcode is ignored. However, the aux opcode's initial value is $05. | |||
==drawObject ($05)== | ==drawObject ($05)== | ||
==dummy ($ | ===Encoding=== | ||
opcode object[p16] sub-opcode | |||
sub-opcodes: | |||
$01 xpos[p16] ypos[p16] | |||
$02 state[p16] | |||
$FF | |||
===Operation=== | |||
{| border="1" cellpadding="2" width=100% | |||
|- style="background:whitesmoke" | |||
|Opcode||Meaning||Description | |||
|- | |||
|$01||Draw At||Moves the given object to the given co-ordinates, and adds it to the drawing queue. | |||
|- | |||
|$02||Set State||Sets the state of the object, adds it to the drawing queue. | |||
|- | |||
|$FF||Draw||Does not change the object's position (or state?), still adds it to the drawing queue. | |||
|} | |||
===Variants=== | |||
Small header games (v3 and v4) only support the parameters used with sub-opcode $01, e.g: | |||
opcode object[p16] xpos[p16] ypos[p16] | |||
Accordingly, they have three parameter bits, and hence more possible opcodes. | |||
==dummy ($A7)== | |||
===Encoding=== | |||
opcode | |||
===Operation=== | |||
V5 specific - The KIXX XL release of Monkey Island 2 (Amiga disk) used this opcode as a dummy, in order to remove copy protection and keep level selection. | |||
===Variants=== | |||
In SCUMM V3 and V4, this opcode is used for the saveLoadVars instruction. | |||
==endCutScene ($C0)== | ==endCutScene ($C0)== | ||
===Encoding=== | |||
opcode | |||
===Operation=== | |||
Ends the cutscene, performing cleanup if necessary. | |||
==equalZero ($28)== | ==equalZero ($28)== | ||
jumps | jumps | ||
===Encoding=== | ===Encoding=== | ||
opcode var target[16] | |||
===Operation=== | ===Operation=== | ||
unless (var == 0) goto target | |||
Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer. | Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer. | ||
==expression ($AC)== | ==expression ($AC)== | ||
===Encoding=== | |||
opcode result subopcode... $FF | |||
sub-opcodes: | |||
$01 value[p16] | |||
$02 | |||
... $02 through $05 take the same arguments ... | |||
$05 | |||
$06 nested-opcode | |||
===Operation=== | |||
Expression mode operates on a stack. Values are pushed on, and operators are applied to the top two items on the stack. | |||
{| border="1" cellpadding="2" width=100% | |||
|- style="background:whitesmoke" | |||
|Opcode||Meaning||Description | |||
|- | |||
|$01||Value||Pushes a value onto the top of the stack. | |||
|- | |||
|$02||Add||stack[top - 1] + stack[top] | |||
|- | |||
|$03||Subtract||stack[top - 1] - stack[top] | |||
|- | |||
|$04||Multiply||stack[top - 1] * stack[top] | |||
|- | |||
|$05||Divide||stack[top - 1] / stack[top] (if stack[top] is 0 an error occurs) | |||
|- | |||
|$06||Nested Opcode||An entire instruction that returns a result, such as getActorScale. This is interpreted like a normal opcode, but the result is pushed onto the expression stack. (The opcode is passed the special "VAR_RESULT" parameter for "result") | |||
|} | |||
==faceActor ($09)== | ==faceActor ($09)== | ||
===Encoding=== | |||
opcode actor[p8] object[p16] | |||
===Operation=== | |||
Dereferences actor, tells actor to face object (presumably based on X/Y co-ordinates). | |||
==findInventory ($3D)== | ==findInventory ($3D)== | ||
===Encoding=== | |||
opcode result owner[p8] index[p8] | |||
===Operation=== | |||
object := owner.inventory[index] | |||
Searches for all objects owned by owner (an actor or object), and returns the one at the given index (offset). | |||
==findObject ($35)== | ==findObject ($35)== | ||
===Encoding=== | |||
opcode result x[p8] y[p8] | |||
===Operation=== | |||
Returns the first "touchable" local object at the given co-ordinates. Will not match on the bottom or right-hand edges of an object. | |||
==freezeScripts ($60)== | ==freezeScripts ($60)== | ||
===Encoding=== | |||
opcode flag[p8] | |||
===Operation=== | |||
Freezes all scripts (by setting the high bit on each script's status). If flag is >= $80, all freeze resistent scripts will also be frozen. If flag is 0, all scripts are unfrozen. Freezing effects are cumulative - i.e. if script A is frozen twice, and unfrozen once, it will still be frozen until it is unfrozen a second time. A script's frozen status is indicated by the high bit. | |||
==getActorCostume ($71)== | ==getActorCostume ($71)== | ||
===Encoding=== | |||
opcode result actor[p8] | |||
===Operation=== | |||
Returns the actor's current costume. | |||
==getActorElevation ($06)== | ==getActorElevation ($06)== | ||
===Encoding=== | |||
opcode result actor[p8] | |||
===Operation=== | |||
Returns the actor's current elevation. | |||
==getActorFacing ($63)== | ==getActorFacing ($63)== | ||
===Encoding=== | |||
opcode result actor[p8] | |||
===Operation=== | |||
Returns the current direction the actor is facing. | |||
==getActorMoving ($56)== | ==getActorMoving ($56)== | ||
===Encoding=== | |||
opcode result actor[p8] | |||
===Operation=== | |||
Returns the actor's moving status (0 or 1). | |||
==getActorRoom ($03)== | ==getActorRoom ($03)== | ||
===Encoding=== | |||
opcode result actor[p8] | |||
===Operation=== | |||
Returns the room the actor currently occupies? | |||
==getActorScale ($3B)== | ==getActorScale ($3B)== | ||
===Encoding=== | |||
opcode result actor[p8] | |||
===Operation=== | |||
Returns the actor's current scale. | |||
===Variants=== | |||
In Indy3, this opcode is used for waitForActor. | |||
==getActorWalkBox ($7B)== | ==getActorWalkBox ($7B)== | ||
===Encoding=== | |||
opcode result actor[p8] | |||
===Operation=== | |||
Returns the actor's walkbox. | |||
==getActorWidth ($6C)== | ==getActorWidth ($6C)== | ||
===Encoding=== | |||
opcode result actor[p8] | |||
===Operation=== | |||
Returns the actor's width. | |||
==getActorX ($43)== | ==getActorX ($43)== | ||
===Encoding=== | |||
opcode result actor[p16] | |||
===Operation=== | |||
Returns the actor's current X co-ordinate. | |||
===Variants=== | |||
In Indy3, actor is only one byte. | |||
opcode result actor[p8] | |||
==getActorY ($23)== | ==getActorY ($23)== | ||
===Encoding=== | |||
opcode result actor[p16] | |||
===Operation=== | |||
Returns the actor's current Y co-ordinate. | |||
===Variants=== | |||
In Indy3, actor is only one byte. | |||
opcode result actor[p8] | |||
==getAnimCounter ($22)== | ==getAnimCounter ($22)== | ||
===Encoding=== | |||
opcode result actor[p8] | |||
===Operation=== | |||
Returns the actor's animation counter. | |||
===Variants=== | |||
This opcode is used for saveLoadGame in SCUMM V3. | |||
==getClosestObjActor ($66)== | ==getClosestObjActor ($66)== | ||
===Encoding=== | |||
opcode result actor[p16] | |||
===Operation=== | |||
Returns the object closest to the actor. Items that are more than 255 units (pixels in newer games, characters in older games) away from the actor will not be detected. | |||
==getDist ($34)== | ==getDist ($34)== | ||
===Encoding=== | |||
opcode result objA[p16] objB[p16] | |||
===Operation=== | |||
Returns the distance between two actors/objects (objA and objB). | |||
==getInventoryCount ($31)== | ==getInventoryCount ($31)== | ||
===Encoding=== | |||
opcode result actor[p8] | |||
===Operation=== | |||
Returns the number of items in an actor's inventory? | |||
==getObjectOwner ($10)== | ==getObjectOwner ($10)== | ||
===Encoding=== | |||
opcode result object[p16] | |||
===Operation=== | |||
Returns the owner of an object. | |||
==getObjectState ($0F)== | ==getObjectState ($0F)== | ||
===Encoding=== | |||
opcode result object[p16] | |||
===Operation=== | |||
Returns the state of the object. | |||
===Variants=== | |||
In small header games, this opcode is used for the "ifState" instruction. | |||
==getRandomNumber ($16)== | ==getRandomNumber ($16)== | ||
===Encoding=== | |||
opcode result seed[p8] | |||
===Operation=== | |||
Returns a new random number based on the given seed. | |||
==getScriptRunning ($68)== | ==getScriptRunning ($68)== | ||
===Encoding=== | |||
opcode result script[p8] | |||
===Operation=== | |||
Returns 1 if the given script is running, 0 if it's not. | |||
==getStringWidth ($67)== | |||
===Encoding=== | |||
opcode result strptr[p8] | |||
===Operation=== | |||
Gets the length of the string pointed to by strptr (either a variable or direct byte), stores the returned value in result. | |||
==getVerbEntryPoint ($0B)== | ==getVerbEntryPoint ($0B)== | ||
===Encoding=== | |||
opcode result object[p16] verb[p16] | |||
===Operation=== | |||
Returns the entry point for the response code/script for when the given verb is applied to the given object? i.e. gets the start of the script to run for the specific user interaction. | |||
==ifClassOfIs ($1D)== | ==ifClassOfIs ($1D)== | ||
jumps | jumps | ||
===Encoding=== | ===Encoding=== | ||
opcode value[p16] args[v16]... target[16] | |||
===Operation=== | ===Operation=== | ||
unless (value.class is one of [args.class]) goto target | |||
Compares the value's class with all classes given in args. | Compares the value's class with all classes given in args. | ||
Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer. | Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer. | ||
==ifNotState ($2F) (V3-4)== | |||
This opcode is not present in SCUMM V5. | |||
===Encoding=== | |||
opcode object[p16] state[p8] target[16] | |||
===Operation=== | |||
unless (getState(object) != state) goto target | |||
==ifState ($0F) (V3-4)== | |||
This opcode is not present in SCUMM V5. | |||
===Encoding=== | |||
opcode object[p16] state[p8] target[16] | |||
===Operation=== | |||
unless (getState(object) == state) goto target | |||
==increment ($46)== | ==increment ($46)== | ||
no parameters, uses result | no parameters, uses result | ||
===Encoding=== | ===Encoding=== | ||
opcode result | |||
===Operation=== | ===Operation=== | ||
result := result + 1 | |||
Reads the variable pointed to by result, increments it, and writes it back. | Reads the variable pointed to by result, increments it, and writes it back. | ||
==isActorInBox ($1F)== | ==isActorInBox ($1F)== | ||
===Encoding=== | |||
opcode actor[p8] box[p8] target[16] | |||
===Operation=== | |||
Unless the actor's co-ordinates are within the bounds of the given box, jump to target. | |||
Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer. | |||
==isEqual ($48)== | ==isEqual ($48)== | ||
===Encoding=== | ===Encoding=== | ||
opcode var value[p16] target[16] | |||
===Operation=== | ===Operation=== | ||
unless (value == var) goto target | |||
Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer. | Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer. | ||
==isGreater ($78)== | ==isGreater ($78)== | ||
===Encoding=== | ===Encoding=== | ||
opcode var value[p16] target[16] | |||
===Operation=== | ===Operation=== | ||
unless (value > var) goto target | |||
Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer. | Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer. | ||
==isGreaterEqual ($04)== | ==isGreaterEqual ($04)== | ||
===Encoding=== | ===Encoding=== | ||
opcode var value[p16] target[16] | |||
===Operation=== | ===Operation=== | ||
unless (value >= var) goto target | |||
Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer. | Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer. | ||
==isLess ($44)== | ==isLess ($44)== | ||
===Encoding=== | ===Encoding=== | ||
opcode var value[p16] target[16] | |||
===Operation=== | ===Operation=== | ||
unless (value < var) goto target | |||
Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer. | Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer. | ||
==isNotEqual ($08)== | ==isNotEqual ($08)== | ||
===Encoding=== | ===Encoding=== | ||
opcode var value[p16] target[16] | |||
===Operation=== | ===Operation=== | ||
unless (value != var) goto target | |||
Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer. | Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer. | ||
==isSoundRunning ($7C)== | ==isSoundRunning ($7C)== | ||
===Encoding=== | |||
opcode result sound[p8] | |||
===Operation=== | |||
Returns 1 if sound is running, returns 0 if sound is not running or if the given sound is 0. | |||
==jumpRelative ($18)== | ==jumpRelative ($18)== | ||
jumps | jumps | ||
===Encoding=== | ===Encoding=== | ||
opcode target[16] | |||
===Operation=== | ===Operation=== | ||
PC := PC + target | |||
The inline constant target is read as a signed word and added to the program counter after the instruction has been read. Therefore, if target is zero, the instruction will do nothing; if target is -3, an infinite loop will result. | The inline constant target is read as a signed word and added to the program counter after the instruction has been read. Therefore, if target is zero, the instruction will do nothing; if target is -3, an infinite loop will result. | ||
==lessOrEqual ($38)== | ==lessOrEqual ($38)== | ||
jumps | jumps | ||
===Encoding=== | ===Encoding=== | ||
opcode var value[p16] target[16] | |||
===Operation=== | ===Operation=== | ||
unless (value <= var) goto target | |||
Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer. | Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer. | ||
==lights ($70)== | ==lights ($70)== | ||
===Encoding=== | |||
opcode arg1[p8] arg2[8] arg3[8] | |||
===Operation=== | |||
If arg3 is 0, the "current lights" variable is set to arg1. | |||
If arg3 is 1, the size of the "flashlight" light is determined by arg1 and arg2, for width and height in stripes (which are equivalent to 8 pixels each; see [[SCUMM/Technical Reference/Image resources]]). | |||
==loadRoom ($72)== | ==loadRoom ($72)== | ||
===Encoding=== | |||
opcode room[p8] | |||
===Operation=== | |||
Loads the given room into memory. | |||
==loadRoomWithEgo ($24)== | ==loadRoomWithEgo ($24)== | ||
===Encoding=== | |||
opcode object[p16] room[p8] x[16] y[16] | |||
===Operation=== | |||
Places the Ego actor in room at object's position. If x is not -1, Ego will start moving towards the given x and y co-ordinates. If object is not in the given room an error will occur. | |||
(I think...) | |||
==matrixOp ($30)== | ==matrixOp ($30)== | ||
===Encoding=== | |||
opcode sub-opcode | |||
sub-opcodes: | |||
$01 box[p8] val[p8] | |||
$02 box[p8] val[p8] | |||
$03 box[p8] val[p8] | |||
$04 | |||
===Operation=== | |||
This instruction manipulates boxes. | |||
{| border="1" cellpadding="2" width=100% | |||
|- style="background:whitesmoke" | |||
|Opcode||Meaning||Description | |||
|- | |||
|$01||setBoxFlags||Sets the box's flags to the given value. | |||
|- | |||
|$02||setBoxScale||Sets the box's scale. | |||
|- | |||
|$03||setBoxScale||Sets the box's scale to ((val - 1) OR $8000). | |||
|- | |||
|$04||createBoxMatrix||Initializes the matrix of boxes, by determining the distances and shortest paths between boxes. | |||
|} | |||
===Variants=== | |||
SCUMM V3 only has the one instruction, which behaves like setBoxFlags: | |||
opcode box[p8] val[8] | |||
==move ($1A)== | ==move ($1A)== | ||
===Encoding=== | ===Encoding=== | ||
opcode result value[p16] | |||
===Operation=== | ===Operation=== | ||
result := value | |||
Value is moved into result. | Value is moved into result. | ||
==multiply ($1B)== | ==multiply ($1B)== | ||
===Encoding=== | ===Encoding=== | ||
opcode result value[p16] | |||
===Operation=== | ===Operation=== | ||
result := result * value | |||
The variable pointed to by result is read, multiplied by value, and written back. | The variable pointed to by result is read, multiplied by value, and written back. | ||
==notEqualZero ($A8)== | ==notEqualZero ($A8)== | ||
===Encoding=== | ===Encoding=== | ||
opcode var target[16] | |||
===Operation=== | ===Operation=== | ||
unless (var != 0) goto target | |||
Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer. | Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer. | ||
==oldRoomEffect ($5C) (V3-4)== | |||
This opcode/instruction not present in SCUMM V5. | |||
===Encoding=== | |||
opcode sub-opcode | |||
sub-opcodes: | |||
$03 effect[p16] | |||
$?? effect[p16] | |||
===Operation=== | |||
Performs like sub-opcode SO_ROOM_FADE of the roomOps instruction (fade in if effect != 0, otherwise fade out). | |||
This information may not be correct; descumm says if the sub-opcode is 3, to "set" the effect, but if the sub-opcode is anything else to fade in with the given effect. | |||
===Variants=== | |||
FM-Towns SCUMM V3 performs a different effect, not fully implemented in ScummVM. At the moment ScummVM just forces a redraw of the screen background. | |||
==or ($57)== | ==or ($57)== | ||
one parameter, uses result | one parameter, uses result | ||
===Encoding=== | ===Encoding=== | ||
opcode result value[p16] | |||
===Operation=== | ===Operation=== | ||
result := result or value | |||
The variable pointed to by result is read, logically ORed with value, and the result written back. | The variable pointed to by result is read, logically ORed with value, and the result written back. | ||
== | ==override ($58)== | ||
===Encoding=== | |||
opcode sub-opcode | |||
sub-opcodes: | |||
$00 | |||
$01 $18 target[16] | |||
== | ===Operation=== | ||
If the sub-opcode is 0, marks the end of an override section.<br> | |||
If the sub-opcode is not 0, marks the beginning of an override section. The instruction is immediately followed by a "jumpRelative" instruction.<br> | |||
Overrides are used by cutscenes; if a cutscene is skipped (if the user presses the ESC key), the script will jump by the given target (offset from the beginOverride instruction). | |||
== | ==panCameraTo ($12)== | ||
== | ===Encoding=== | ||
opcode x[p16] | |||
== | ===Operation=== | ||
Starts the camera panning to the given x co-ordinate. | |||
== | ==pickupObject ($25) (v5)== | ||
This instruction is only present in SCUMM V5. | |||
== | ===Encoding=== | ||
opcode object[p16] room[p8] | |||
== | ===Operation=== | ||
Adds the given object (located in the given room) to the Ego actor's inventory. | |||
== | ===Variants=== | ||
In SCUMM V3 and V4, this opcode is used for drawObject. | |||
== | ==pickupObject ($50) (V3-4)== | ||
This opcode/instruction is not present in SCUMM V5. | |||
== | ===Encoding=== | ||
opcode object[p16] | |||
== | ===Operation=== | ||
Adds the given object (located in the given room) to the Ego actor's inventory. If object < 1, an error is raised. If the object is not found or the object is already in the inventory, this function ends gracefully. | |||
==print ($14)== | |||
===Encoding=== | ===Encoding=== | ||
opcode actor[p8] sub-opcode | |||
sub-opcodes | |||
$00 xpos[p16] ypos[p16] | |||
$01 color[p8] | |||
$02 right[p16] | |||
$03 width[p16] height[p16] | |||
$04 | |||
$06 | |||
$07 | |||
$08 offset[p16] delay[p16] | |||
$0F string[c]... $FF | |||
===Operation=== | ===Operation=== | ||
Sets text properties and displays dialogue. | |||
{| border="1" cellpadding="2" width=100% | |||
|- style="background:whitesmoke" | |||
|Opcode||Meaning||Description | |||
|- | |||
|$00||SO_AT||Sets the position of the text that follows. | |||
|- | |||
|$01||SO_COLOR||Sets the color of the text. | |||
|- | |||
|$02||SO_CLIPPED||Clips the text's right-hand side (for wrapping?). | |||
|- | |||
|$03||SO_ERASE||Erases characters (not used in ScummVM). | |||
|- | |||
|$04||SO_CENTER||Centres the text. | |||
|- | |||
|$06||SO_LEFT||Left-aligns the text. | |||
|- | |||
|$07||SO_OVERHEAD||Overhead-aligns the text. | |||
|- | |||
|$0F||SO_TEXTSTRING||Prints the text string that follows. Terminated by $FF. | |||
|} | |||
===Variants=== | |||
In SCUMM V3, text function $06 sets the height of the text: | |||
$06 height[p16] | |||
In Loom CD (SCUMM V4), there is an additional text function $08 (SO_SAY_VOICE), which plays a portion of the CD audio track. | |||
$08 offset[p16] delay[p16] | |||
== | ==printEgo ($D8)== | ||
== | ===Encoding=== | ||
opcode sub-opcode | |||
== | ===Operation=== | ||
Exactly the same as print, except the actor is implicitly Ego. See the entry for "print" for further explanation. | |||
==pseudoRoom ($CC)== | |||
===Encoding=== | ===Encoding=== | ||
opcode val[8] res[8]... $00 | |||
===Operation=== | ===Operation=== | ||
forall (res) { | |||
if (res >= $80) { | |||
_resourceMapper[res & $7F] := val | |||
} | |||
} | |||
What does this actually do? We may never know. | |||
It looks like res values always have the high bit set, e.g. 0x01 becomes 0x81. | |||
==putActor ($01)== | |||
===Encoding=== | |||
opcode actor[p8] x[p16] y[p16] | |||
== | ===Operation=== | ||
Puts the actor at the given co-ordinates. | |||
== | ==putActorAtObject ($0E)== | ||
== | ===Encoding=== | ||
opcode actor[p8] object[p16] | |||
== | ===Operation=== | ||
Puts the actor at the given object's position. If the object can not be found, a default position is returned (the centre of the screen in ScummVM). | |||
== | ==putActorInRoom ($2D)== | ||
===Encoding=== | ===Encoding=== | ||
opcode actor[p8] room[p8] | |||
===Operation=== | ===Operation=== | ||
Puts the actor in the given room. | |||
==resourceRoutines ($0C)== | |||
== | ===Encoding=== | ||
opcode sub-opcode | |||
sub-opcodes: | |||
$01 resID[p8] | |||
... $01 through $10 take the same arguments ... | |||
$10 resID[p8] | |||
$11 | |||
$12 resID[p8] | |||
$13 resID[p8] | |||
$14 room[p8] object[p16] | |||
== | ===Operation=== | ||
resID is unique only within the resource type (e.g. script 11 will not conflict with sound 11). | |||
== | {| border="1" cellpadding="2" width=100% | ||
|- style="background:whitesmoke" | |||
|Opcode||Meaning||Description | |||
|- | |||
|$01||SO_LOAD_SCRIPT||Loads the given script into memory. | |||
|- | |||
|$02||SO_LOAD_SOUND||Loads the given sound into memory. | |||
|- | |||
|$03||SO_LOAD_COSTUME||Loads the given costume into memory. | |||
|- | |||
|$04||SO_LOAD_ROOM||Loads the given room into memory. | |||
|- | |||
|$05||SO_NUKE_SCRIPT||Obliterates the given script from memory. | |||
|- | |||
|$06||SO_NUKE_SOUND||Obliterates the given sound from memory. | |||
|- | |||
|$07||SO_NUKE_COSTUME||Obliterates the given costume from memory. | |||
|- | |||
|$08||SO_NUKE_ROOM||Obliterates the given room from memory. | |||
|- | |||
|$09||SO_LOCK_SCRIPT||Locks the given script. | |||
|- | |||
|$0A||SO_LOCK_SOUND||Locks the given sound. | |||
|- | |||
|$0B||SO_LOCK_COSTUME||Locks the given costume. | |||
|- | |||
|$0C||SO_LOCK_ROOM||Locks the given room. | |||
|- | |||
|$0D||SO_UNLOCK_SCRIPT||Unlocks the given script. | |||
|- | |||
|$0E||SO_UNLOCK_SOUND||Unlocks the given sound. | |||
|- | |||
|$0F||SO_UNLOCK_COSTUME||Unlocks the given costume. | |||
|- | |||
|$10||SO_UNLOCK_ROOM||Unlocks the given room. | |||
|- | |||
|$11||SO_CLEAR_HEAP||Clears the heap. | |||
|- | |||
|$12||SO_LOAD_CHARSET||Loads the given character set into memory. | |||
|- | |||
|$13||SO_NUKE_CHARSET||Obliterates the given character set from memory. | |||
|- | |||
|$14||SO_LOAD_OBJECT||Loads the given object from the given room resource. | |||
|} | |||
== | ===Variants=== | ||
FM-Towns games add the following sub-opcodes (these are not confirmed nor implemented in ScummVM): | |||
{| border="1" cellpadding="2" width=100% | |||
|- style="background:whitesmoke" | |||
|Opcode||Meaning||Description | |||
|- | |||
|$20||Unknown||Does nothing, not used in-game. | |||
|- | |||
|$21||Unknown||Does nothing, not used in-game. | |||
|- | |||
|$23||CD Volume||Possibly changes the volume of CD tracks (Loom CD). Takes 1 byte. | |||
|- | |||
|$24||Sound Volume||Sets the loudness of a sound resource. Used in Indy3 and Zak. Takes 2 bytes (left/right volumes?). | |||
|- | |||
|$25||Sound Pitch||Sets the pitch of a sound resource. Used in Indy3 and Zak. Takes 1 byte (pitch = "foo" - "center" semitones. Center is at $32 in the sound resource.) | |||
|} | |||
==roomOps ($33)== | |||
===Encoding=== | |||
opcode sub-opcode | |||
sub-opcodes: | |||
$01 minX[p16] maxX[p16] | |||
$03 b[p16] h[p16] | |||
$04 red[p16] green[p16] blue[p16] aux index[p8] | |||
$05 | |||
$06 | |||
$07 scale1[p8] y1[p8] aux scale2[p8] y2[p8] aux slot[p8] | |||
$08 scale[p8] startcolor[p8] endcolor[p8] | |||
$09 loadflag[p8] loadslot[p8] | |||
$0A effect[p16] | |||
$0B redscale[p16] greenscale[p16] bluescale[p16] aux startcolor[p8] endcolor[p8] | |||
$0C redscale[p16] greenscale[p16] bluescale[p16] aux startcolor[p8] endcolor[p8] | |||
$0D resID[p8] filename[c]... $00 | |||
$0E resID[p8] filename[c]... $00 | |||
$0F resID[p8] aux start[p8] end[p8] aux time[p8] | |||
$10 colindex[p8] delay[p8] | |||
===Operation=== | |||
{| border="1" cellpadding="2" width=100% | |||
|- style="background:whitesmoke" | |||
|Opcode||Meaning||Description | |||
{| border="1" | |||
|- | |- | ||
| | |$01||SO_ROOM_SCROLL||Clamps the given arguments so scrolling does not extend past the width of the room or screen. | ||
| | |||
| | |||
|- | |- | ||
| | |$03||SO_ROOM_SCREEN||Initialises a screen. | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | |$04||SO_ROOM_PALETTE||Adjusts the room's palette. Aux opcode's initial value is $04. | ||
| | |||
| | |||
|- | |- | ||
| | |$05||SO_ROOM_SHAKE_ON||Starts the room shaking. | ||
| | |||
| | |||
|- | |- | ||
| | |$06||SO_ROOM_SHAKE_OFF||Ends the room shaking. | ||
| | |||
| | |||
|- | |- | ||
| | |$07||SO_ROOM_SCALE||Sets the room's y scales? (slot is 1 greater than actual slot?) | ||
| | |||
| | |||
|- | |- | ||
| | |$08||SO_ROOM_INTENSITY||Lightens/darkens the room's palette. | ||
| | |||
| | |||
|- | |- | ||
| | |$09||SO_ROOM_SAVEGAME||Saves temporary state of the room/game? | ||
| | |||
| | |||
|- | |- | ||
| | |$0A||SO_ROOM_FADE||If effect is 0, fades in the room. Otherwise, fades out with the given effect (taken from the high byte of effect).<br>1 = iris effect<br>2 = box wipe (upper-left to bottom-right)<br>3 = box wipe (upper-right to bottem-left)<br>4 = inverse box wipe. | ||
| | |||
| | |||
|- | |- | ||
| | |$0B||SO_RGB_ROOM_INTENSITY||Lightens/darkens the room's palette, with different scales for red, green and blue. Aux opcode's initial value is $0B. | ||
| | |||
| | |||
|- | |- | ||
| | |$0C||SO_ROOM_SHADOW||Lightens/darkens the shadow palette, with different scales for red, green, and blue. | ||
| | |||
| | |||
|- | |- | ||
| | |$0D||SO_SAVE_STRING||Saves a string resource to the given file? | ||
| | |||
| | |||
|- | |- | ||
| | |$0E||SO_LOAD_STRING||Loads a string resource from a given file? | ||
| | |||
| | |||
|- | |- | ||
| | |$0F||SO_ROOM_TRANSFORM||Manipulates palettes, strings? | ||
| | |||
| | |||
|- | |- | ||
| | |$10||SO_CYCLE_SPEED||Starts color cycling with delay? colIndex is between 0 and 16 | ||
| | |} | ||
| | |||
===Variants=== | |||
|style=" | SCUMM V3 (non-PC Engine) encodes the arguments before the sub-opcode: | ||
opcode arg1[p16] arg2[p16] sub-opcode | |||
Small header games (V3 and V4) include an extra sub-opcode, $02 (SO_ROOM_COLOR), which adjusts the room's palette: | |||
opcode $02 color[p16] index[p16] | |||
... or for V3 games ... | |||
opcode color[p16] index[p16] $02 | |||
In small header games, sub-opcode $04 (SO_ROOM_PALETTE) affects the shadow palette, and only accepts two arguments, a "room color slot" (palette entry? between 0 and 256) and an index: | |||
opcode $04 color[p16] index[p16] | |||
... or for V3 games ... | |||
opcode color[p16] index[p16] $04 | |||
In FM-Towns games, sub-opcode $0A performs a different function and has its own sub-opcodes (some unknown and all not yet implemented in ScummVM): | |||
opcode $0A sub-opcode | |||
{| border="1" cellpadding="2" width=100% | |||
|- style="background:whitesmoke" | |||
|Opcode||Meaning||Description | |||
|- | |- | ||
| | |$08||||compose kMainVirtScreen over a screen buffer | ||
| | |||
| | |||
|- | |- | ||
| | |$09||||call 0x110:0x20 _ax=0x601 _edx=2 | ||
| | |||
| | |||
|- | |- | ||
| | |$0A||||call 0x110:0x20 _ax=0x601 _edx=3 | ||
| | |||
| | |||
|- | |- | ||
| | |$0B||||clear screen 0x1C:0x45000 sizeof(640 * 320) | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | |$0C||||call 0x110:0x20 _ax=0x601 _edx=0 | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | |$0D||||call 0x110:0x20 _ax=0x601 _edx=1 | ||
| | |||
| | |||
|- | |- | ||
| | |$10||||enable clearing of a screen buffer in drawBitmap() | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | |$11||||disable clearing of a screen buffer in drawBitmap() | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | |$12||||clear a screen buffer | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | |$13||||enable palette operations (palManipulate(), cyclePalette() etc.) | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | |$14||||disable palette operations | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | |$15||||disable clearing of screen 0x1C:0x5000 sizeof(640 * 320) in initScreens() | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | |$16||||enable clearing of screen 0x1C:0x5000 sizeof(640 * 320) in initScreens() | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | |$1E||||Unknown | ||
|} | |||
| | |||
|style=" | ==saveLoadGame ($22) (V3-4)== | ||
This instruction is not present in SCUMM V5; its opcode is used for "getAnimCounter". | |||
===Encoding=== | |||
opcode result arg1[p8] | |||
===Operation=== | |||
The slot is determined by taking the lower 5 bits of arg1. The upper 3 bits determine an aux opcode, that performs an action described in the table below. | |||
{| border="1" cellpadding="2" width=100% | |||
|- style="background:whitesmoke" | |||
|Opcode||Meaning||Description | |||
|- | |- | ||
| | |$00||Num. Available Slots||Returns the number of save slots available. | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | |$20||Drive||In V3, returns the type of drive (0 = ???, 1 = A or B [floppy], 2 = hard drive).<br>In V4, sets the current drive (returns 1). | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | |$40||Load Game||Loads a game from the given slot (returns 3 if successful, 5 otherwise). | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | |$80||Save Game||Saves a game to the given slot (returns 0 if successful, 2 otherwise). | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | |$C0||Test For Game||Tests if a save exists in the given slot (returns 6 if so, 7 otherwise). | ||
| | |} | ||
| | |||
|style=" | ==saveLoadVars ($A7) (V3-4)== | ||
This instruction is not present in SCUMM V5; its opcode is used as a dummy. | |||
===Encoding=== | |||
opcode sub-opcode | |||
sub-opcodes: | |||
$01 sub-sub-opcode... $00 | |||
$02 sub-sub-opcode... $00 | |||
$01 (save) sub-sub-opcodes: | |||
$01 resultA resultB | |||
$02 arg1[p8] arg2[p8] | |||
$03 filename[c]... $00 | |||
$04 | |||
$1F | |||
$02 (load) sub-sub-opcodes: | |||
$01 resultA resultB | |||
$02 arg1[p8] arg2[p8] | |||
$03 filename[c]... $00 | |||
$04 | |||
$1F | |||
===Operation=== | |||
{| border="1" cellpadding="2" width=100% | |||
|- style="background:whitesmoke" | |||
|Opcode||Meaning||Description | |||
|- | |- | ||
| | |$01||SO_SAVE_VARS||Saves variables (for saving games?) | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | |$02?||SO_RESTORE_VERBS||Loads variables (for saving games?)<br>(I have not verified that restore vars is $02, as the ScummVM code only compares to $01.) | ||
| | |} | ||
| | {| border="1" cellpadding="2" width=100% | ||
|style=" | |- style="background:whitesmoke" | ||
|Opcode||Meaning||Description | |||
|- | |- | ||
| | |$01||Write Vars||Writes a range of variables. | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | |$02||Write Strings||Writes a range of string variables. | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | |$03||Open File||Opens a file for writing. | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | |$04||Dummy||Does nothing. | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | |$1F||Close File||Closes the last opened file. | ||
|style=" | |} | ||
| | |||
| | {| border="1" cellpadding="2" width=100% | ||
| | |- style="background:whitesmoke" | ||
|Opcode||Meaning||Description | |||
|- | |- | ||
| | |$01||Read Vars||Reads a range of variables. | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | |$02||Read Strings||Reads a range of string variables. | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | |$03||Open File||Opens a file for reading. | ||
| | |||
| | |||
|- | |- | ||
| | |$04||Dummy||Does nothing. | ||
| | |||
| | |||
|- | |- | ||
| | |$1F||Close File||Closes the last opened file. | ||
| | |} | ||
| | |||
|style=" | ==saveRestoreVerbs ($AB)== | ||
===Encoding=== | |||
opcode sub-opcode | |||
sub-opcodes: | |||
$01 start[p8] end[p8] mode[p8] | |||
$02 start[p8] end[p8] mode[p8] | |||
$03 start[p8] end[p8] mode[p8] | |||
===Operation=== | |||
{| border="1" cellpadding="2" width=100% | |||
|- style="background:whitesmoke" | |||
|Opcode||Meaning||Description | |||
|- | |- | ||
| | |$01||SO_SAVE_VERBS||For all verbs between start and end, sets the "saveid" to mode. | ||
| | |||
| | |||
|- | |- | ||
| | |$02||SO_RESTORE_VERBS||For all verbs between start and end and matching mode, kills any existing verb, sets the saveid to 0 and generally inits the verb. | ||
| | |||
| | |||
|- | |- | ||
| | |$03||SO_DELETE_VERBS||For all verbs between start and end and matching mode, kills any existing verb. | ||
|style=" | |} | ||
| | |||
| | |||
| | ==setCameraAt ($32)== | ||
===Encoding=== | |||
opcode x[p16] | |||
===Operation=== | |||
Sets the camera's x position. | |||
==setObjectName ($54)== | |||
===Encoding=== | |||
opcode object[p16] name[c]... $00 | |||
===Operation=== | |||
Sets the given object's name. | |||
==setOwnerOf ($29)== | |||
===Encoding=== | |||
opcode object[p16] owner[p8] | |||
===Operation=== | |||
Sets the owner of the object. | |||
==setState ($07)== | |||
===Encoding=== | |||
opcode object[p16] state[p8] | |||
===Operation=== | |||
Sets the state of the object. | |||
==setVarRange ($26)== | |||
non-standard encoding | |||
===Encoding=== | |||
opcode result number[8] values[8]... | |||
or | |||
opcode result number[8] values[16]... | |||
===Operation=== | |||
for (i = 0; i < number; i++) { | |||
*result + i := values[i]; | |||
} | |||
This sets a number of variables to the given parameters. The starting variable is given as "result", and the number of variables to modify is given as "number". This is followed by the same number of values, which will be put into the variable locations. The values are constants, and can be either 16-bit, if the highest bit of the opcode is set, i.e. $A6; or 8-bit, if the highest bit of the opcode is not set, i.e. $26. Note that all values are affected by the opcode's high bit; you can't mix 8 and 16-bit values. | |||
descumm example: | |||
setVarRange(Var[178],9,[0,0,0,0,0,0,0,0,0]); | |||
This sets variables 178 to 186 (inclusive) to 0. | |||
==soundKludge ($4C)== | |||
===Encoding=== | |||
opcode items[v16]... | |||
===Operation=== | |||
If the first item is -1, the existing sound queue is processed. Otherwise, the list of items is added to the queue. | |||
===Variants=== | |||
In SCUMM V3 and V4 (small header) games, this opcode is used for the WaitForSentence instruction. | |||
==startMusic ($02)== | |||
===Encoding=== | |||
opcode music[p8] | |||
===Operation=== | |||
Adds the music in to the queue to be played. | |||
===Variants=== | |||
In FM-Towns (SCUMM V3) games, this instruction performs different functions (some kind of Audio CD status query function; some partially implemented in ScummVM): | |||
opcode result sub-opcode | |||
{| border="1" cellpadding="2" width=100% | |||
|- style="background:whitesmoke" | |||
|Opcode||Meaning||Description | |||
|- | |||
|$00||Is Playing||Returns true if a CD audio track is currently playing. | |||
|- | |||
|$FC||Unpause CD||Unpauses the CD audio track. | |||
|- | |||
|$FD||Pause CD||Pauses the CD audio track. | |||
|- | |||
|$FE||Get CD Sound||Returns the current CD sound. | |||
|- | |- | ||
| | |$FF||CD Volume||Might return the the current CD volume in FM-Towns Loom. | ||
| | |||
| | |||
|- | |- | ||
| | |other||Track Length||Returns the track length in seconds. | ||
|style=" | |} | ||
| | |||
| | |||
|style=" | ==startObject ($37)== | ||
===Encoding=== | |||
opcode object[p16] script[p8] args[v16]... | |||
===Operation=== | |||
Starts the object's script (OBCD blocks), passing the given arguments. | |||
==startScript ($0A)== | |||
one parameter plus varargs, extra encoding in opcode | |||
===Encoding=== | |||
opcode script[p8] args[v16]... | |||
===Operation=== | |||
Spawns a new thread running the code in script script. The new script has its local variables initialised to the list args. Uninitialised variables have undefined values. | |||
The opcode carries extra information: | |||
{| border="1" cellpadding="2" width=10% | |||
|- style="background:whitesmoke" | |||
|7||6||5||4 0 | |||
|- | |||
|P1||R||F||$0A | |||
|} | |||
P1 = standard parameter bit<br> | |||
R = indicates that the script is recursive<br> | |||
F = indicates that the script is freeze resistant (a call to freezeScripts will skip this script, unless the "force freeze" bit of the freezeScripts opcode is set). | |||
==startSound ($1C)== | |||
===Encoding=== | |||
opcode sound[p8] | |||
===Operation=== | |||
Adds the given sound to the sound queue to be played. | |||
==stopMusic ($20)== | |||
===Encoding=== | |||
opcode | |||
===Operation=== | |||
Stops all sounds. | |||
==stopObjectCode ($A0 or $00)== | |||
===Encoding=== | |||
opcode | |||
===Operation=== | |||
Marks the calling script as dead, to be later pruned from the thread pool. Cleans up residual arrays. Should always be the last instruction in a script. | |||
$A0 is used in local and global scripts (LSCR and SCRP blocks in the V5 resource files), $00 is used in room entry, room exit, and verb/object scripts (ENCD, EXCD, VERB blocks). | |||
==stopObjectScript ($6E)== | |||
===Encoding=== | |||
opcode script[p16] | |||
===Operation=== | |||
Marks the given object script as dead, to be later pruned from the thread pool. Cleans up residual arrays. | |||
==stopScript ($62)== | |||
===Encoding=== | |||
opcode script[p8] | |||
===Operation=== | |||
Marks the given script as dead, to be later pruned from the thread pool. Cleans up residual arrays. | |||
==stopSound ($3C)== | |||
===Encoding=== | |||
opcode sound[p8] | |||
===Operation=== | |||
Stops the given sound. | |||
==stringOps ($27)== | |||
parameters depend on sub-opcode | |||
===Encoding=== | |||
opcode sub-opcode | |||
sub-opcodes: | |||
$01 stringID[p8] string[c]... $00 | |||
$02 destID[p8] srcID[p8] | |||
$03 stringID[p8] index[p8] char[c] | |||
$04 result stringID[p8] index[p8] | |||
$05 stringID[p8] size[p8] | |||
===Operation=== | |||
Miscellaneous actions on strings (Arrays, referred to by resource number). | |||
{| border="1" cellpadding="2" width=100% | |||
|- style="background:whitesmoke" | |||
|Opcode||Meaning||Description | |||
|- | |- | ||
| | |$01||Load String||Loads the inline null-terminated string into the resource slot given by stringID. | ||
| | |||
| | |||
|- | |- | ||
| | |$02||Copy String||Creates a duplicate of the string at resource slot srcID into destID. The old string at destID is lost. | ||
| | |||
| | |||
|- | |- | ||
| | |$03||Write Character||Writes char at the given index (offset) of the string resource located at slot stringID. Out of bounds accesses cause undefined behavior. | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | |$04||Read Character||Reads a byte (character) at the given index (offset) of the string resource located at slot stringID, and writes it to result. Out of bounds accesses cause undefined behavior. | ||
| | |||
| | |||
|- | |- | ||
| | |$05||New String||Allocates or frees a string (Array), located at resource slot stringID. The string is initialised to size; if size is zero, the string is freed. | ||
| | |} | ||
| | |||
|style=" | ==subtract ($3A)== | ||
===Encoding=== | |||
opcode result value[p16] | |||
===Operation=== | |||
result := result - value | |||
The variable pointed to by result is read, value is subtracted from it, and the result written back. | |||
==systemOps ($98)== | |||
===Encoding=== | |||
opcode sub-opcode | |||
sub-opcodes: | |||
$01 | |||
$02 | |||
$03 | |||
===Operation=== | |||
{| border="1" cellpadding="2" width=100% | |||
|- style="background:whitesmoke" | |||
|Opcode||Meaning||Description | |||
|- | |- | ||
| | |$01||SO_RESTART||Restarts the game. | ||
| | |||
| | |||
|- | |- | ||
| | |$02||SO_PAUSE||Pauses/unpauses the game. | ||
| | |||
| | |||
|- | |- | ||
| | |$03||SO_QUIT||Quits the game. | ||
| | |} | ||
| | |||
|style=" | ==verbOps ($7A)== | ||
===Encoding=== | |||
opcode verbID[p8] sub-opcode... $FF | |||
sub-opcodes: | |||
$01 object[p16] | |||
$02 name[c]... $00 | |||
$03 color[p8] | |||
$04 hicolor[p8] | |||
$05 left[p16] top[p16] | |||
$06 | |||
$07 | |||
$08 | |||
$09 | |||
$10 color[p8] | |||
$11 | |||
$12 key[p8] | |||
$13 | |||
$14 stringID[p16] | |||
$16 object[p16] room[p8] | |||
$17 color[p8] | |||
===Operation=== | |||
{| border="1" cellpadding="2" width=100% | |||
|- style="background:whitesmoke" | |||
|Opcode||Meaning||Description | |||
|- | |- | ||
| | |$01||SO_VERB_IMAGE||Assigns an object (image) to a verb. | ||
| | |||
| | |||
|- | |- | ||
| | |$02||SO_VERB_NAME||Assigns the in-line name to the verb slot. | ||
| | |||
| | |||
|- | |- | ||
| | |$03||SO_VERB_COLOR||Sets the color of the verb. | ||
| | |||
| | |||
|- | |- | ||
| | |$04||SO_VERB_HICOLOR||Sets the highlight color of the verb. | ||
| | |||
| | |||
|- | |- | ||
| | |$05||SO_VERB_AT||Sets the verb's top-left co-ordinates. | ||
| | |||
| | |||
|- | |- | ||
| | |$06||SO_VERB_ON||Makes this verb active. | ||
| | |||
| | |||
|- | |- | ||
| | |$07||SO_VERB_OFF||Makes this verb inactive. | ||
| | |||
| | |||
|- | |- | ||
| | |$08||SO_VERB_DELETE||Kills this verb. | ||
| | |||
| | |||
|- | |- | ||
| | |$09||SO_VERB_NEW||Creates a verb in the slot for the given verbID. If the slot is 0 (verb doesn't already exist), will add it to the next unusued slot; if this exceeds the global maximum number of verbs an error will be raised. | ||
| | |||
| | |||
|- | |- | ||
| | |$10||SO_VERB_DIMCOLOR||Sets the dim color of the verb. | ||
| | |||
| | |||
|- | |- | ||
| | |$11||SO_VERB_DIM||Dims this verb. | ||
| | |||
| | |||
|- | |- | ||
| | |$12||SO_VERB_KEY||Sets the key code (maybe ASCII char?) associated with this verb. | ||
| | |||
| | |||
|- | |- | ||
| | |$13||SO_VERB_CENTER||Centres the verb? | ||
| | |||
| | |||
|- | |- | ||
| | |$14||SO_VERB_NAME_STR||Loads the given string resource into the verb's slot. If either the string resource or verb slot is not found (0), the verb resource is nuked. | ||
| | |||
| | |||
|- | |- | ||
| | |$16||Assign Object||Assigns an object from the given room to the verb (if the object's image index is not already assigned to the given object). | ||
| | |||
| | |||
|- | |- | ||
| | |$17||Set Back Color||Sets the background color of the verb? | ||
| | |} | ||
| | |||
|style=" | ==wait ($AE)== | ||
===Encoding=== | |||
opcode sub-opcode | |||
sub-opcodes: | |||
$01 actor[p8] | |||
$02 | |||
$03 | |||
$04 | |||
===Operation=== | |||
{| border="1" cellpadding="2" width=100% | |||
|- style="background:whitesmoke" | |||
|Opcode||Meaning||Description | |||
|- | |- | ||
| | |$01||SO_WAIT_FOR_ACTOR||If the given actor is moving, breaks and resumes at this instruction again. | ||
| | |||
| | |||
|- | |- | ||
| | |$02||SO_WAIT_FOR_MESSAGE||If the global variable VAR_HAVE_MSG (Var[3]) is not zero, breaks and resumes at this instruction again. | ||
| | |||
| | |||
|- | |- | ||
| | |$03||SO_WAIT_FOR_CAMERA||If the camera has not reached its destination x position, breaks and resumes at this instruction again. | ||
| | |||
| | |||
|- | |- | ||
| | |$04||SO_WAIT_FOR_SENTENCE||If there is a sentence present?, breaks and resumes at this instruction again | ||
| | |||
| | |||
|} | |} | ||
===Variants=== | |||
In Indy3 (non-Macintosh), this opcode only acts as SO_WAIT_FOR_MESSAGE and omits the sub-opcode. | |||
opcode | |||
==walkActorTo ($1E)== | |||
===Encoding=== | |||
opcode actor[p8] x[p16] y[p16] | |||
===Operation=== | |||
Sets the actor to begin walking to the given position. | |||
==walkActorToActor ($0D)== | |||
===Encoding=== | |||
opcode walker[p8] walkee[p8] distance[8] | |||
===Operation=== | |||
Walks walker towards walkee's position by the given distance. Walker and walkee are both actors. | |||
==walkActorToObject ($36)== | |||
===Encoding=== | |||
opcode actor[p8] object[p16] | |||
===Operation=== | |||
Sets the actor to begin walking to the given object's position. | |||
=Variables= | |||
A number of variables are reserved for use by the SPUTM/SCUMM engine. Here is a list of known variables and their corresponding numbers, taken from the ScummVM source code. | |||
VAR_RESULT = 0; // descumm claims var 0 is the result var (for expressions) | |||
VAR_KEYPRESS = 0; // script_v5_.cpp claims var 0 is for keypresses... | |||
VAR_EGO = 1; | |||
VAR_CAMERA_POS_X = 2; | |||
VAR_HAVE_MSG = 3; | |||
VAR_ROOM = 4; | |||
VAR_OVERRIDE = 5; | |||
VAR_MACHINE_SPEED = 6; | |||
VAR_ME = 7; | |||
VAR_NUM_ACTOR = 8; | |||
VAR_CURRENT_LIGHTS = 9; | |||
VAR_CURRENTDRIVE = 10; | |||
VAR_TMR_1 = 11; | |||
VAR_TMR_2 = 12; | |||
VAR_TMR_3 = 13; | |||
VAR_MUSIC_TIMER = 14; | |||
VAR_ACTOR_RANGE_MIN = 15; | |||
VAR_ACTOR_RANGE_MAX = 16; | |||
VAR_CAMERA_MIN_X = 17; | |||
VAR_CAMERA_MAX_X = 18; | |||
VAR_TIMER_NEXT = 19; | |||
VAR_VIRT_MOUSE_X = 20; | |||
VAR_VIRT_MOUSE_Y = 21; | |||
VAR_ROOM_RESOURCE = 22; | |||
VAR_LAST_SOUND = 23; | |||
VAR_CUTSCENEEXIT_KEY = 24; | |||
VAR_TALK_ACTOR = 25; | |||
VAR_CAMERA_FAST_X = 26; | |||
VAR_SCROLL_SCRIPT = 27; | |||
VAR_ENTRY_SCRIPT = 28; | |||
VAR_ENTRY_SCRIPT2 = 29; | |||
VAR_EXIT_SCRIPT = 30; | |||
VAR_EXIT_SCRIPT2 = 31; | |||
VAR_VERB_SCRIPT = 32; | |||
VAR_SENTENCE_SCRIPT = 33; | |||
VAR_INVENTORY_SCRIPT = 34; | |||
VAR_CUTSCENE_START_SCRIPT = 35; | |||
VAR_CUTSCENE_END_SCRIPT = 36; | |||
VAR_CHARINC = 37; | |||
VAR_WALKTO_OBJ = 38; | |||
VAR_DEBUGMODE = 39; | |||
VAR_HEAPSPACE = 40; | |||
VAR_RESTART_KEY = 42; | |||
VAR_PAUSE_KEY = 43; | |||
VAR_MOUSE_X = 44; | |||
VAR_MOUSE_Y = 45; | |||
VAR_TIMER = 46; | |||
VAR_TIMER_TOTAL = 47; | |||
VAR_SOUNDCARD = 48; | |||
VAR_VIDEOMODE = 49; | |||
VAR_MAINMENU_KEY = 50; | |||
VAR_FIXEDDISK = 51; | |||
VAR_CURSORSTATE = 52; | |||
VAR_USERPUT = 53; | |||
VAR_V5_TALK_STRING_Y = 54; | |||
VAR_SOUNDRESULT = 56; | |||
VAR_TALKSTOP_KEY = 57; | |||
VAR_FADE_DELAY = 59; | |||
VAR_NOSUBTITLES = 60; | |||
VAR_SOUNDPARAM = 64; | |||
VAR_SOUNDPARAM2 = 65; | |||
VAR_SOUNDPARAM3 = 66; | |||
VAR_INPUTMODE = 67; // 1 is keyboard, 2 is joystick, 3 is mouse | |||
VAR_MEMORY_PERFORMANCE = 68; | |||
VAR_VIDEO_PERFORMANCE = 69; | |||
VAR_ROOM_FLAG = 70; | |||
VAR_GAME_LOADED = 71; | |||
VAR_NEW_ROOM = 72; | |||
=Table of Parameters= | |||
Please see the wiki page [[SCUMM/V5_opcodes/Table]] for a concise rendition of the above information (with a few omissions dues to the complexity of the instructions). |
Latest revision as of 03:05, 23 January 2011
SCUMM V5 opcodes
The following conventions are used in the encoding descriptions.
Term | Description |
opcode | The instruction's opcode, with the appropriate bits set according to the parameters. |
aux | An aux opcode that stores parameter bits and no other information. (the base aux opcode is usually $01, but can differ for each instruction) |
sub-opcode | An aux opcode that indicates a specific function to perform (e.g. the "wait" instruction has sub-opcodes to "wait for message", "wait for actor" etc), as well as storing parameter bits if necessary. |
result | A result pointer. (A standard word pointer, always a LE word.) |
var | A variable pointer. Same as above, but is not written to. Because this is always a variable, the opcode is not affected like it would be with a normal parameter (described below). |
value[8] | An 8-bit constant (a byte). |
value[16] | A 16-bit constant (a word LE). |
value[p8] | An 8-bit parameter. This may be encoded as a word LE if it's a pointer, or a byte if it's a constant. |
value[p16] | A 16-bit parameter. This is always encoded as a word LE, and may be a pointer or constant. |
value[v16] | A variable number of word LE parameters. These are encoded as a sequence of aux[8] param[p16]; param; aux contains the parameter bit to describe param (and is always $01, ignoring the parameter bits). A byte of $FF terminates the sequence. (actually always shown as "value[v16]...") |
value[o] | The offset word for parameter value. This is only encoded if needed, but always at the position indicated. If not specified, the offset word occurs immediately after the parameter. |
value[c] | An ASCII character. Because some instructions use null-terminated strings and some use $FF, the exact format of a string is described in the instruction. Almost always appears as "value[c]..." |
term... | One or more terms. |
Of course, due to the non-orthogonality of the opcodes, there are lots of exceptions.
actorFollowCamera ($52)
Encoding
opcode actor[p8]
Operation
Sets the camera to follow the given actor?
actorFromPos ($15)
Encoding
opcode result x[p16] y[p16]
Operation
Returns the actor located at the given co-ordinates.
actorOps ($13)
parameters depend on auxiliary opcode; terminated by $FF
Encoding
opcode actor[p8] sub-opcode... $FF
sub-opcodes:
$00 arg1[p8] $01 costume[p8] $02 xspeed[p8] yspeed[p8] $03 sound[p8] $04 walkframe[p8] $05 starttalk[p8] endtalk[p8] $06 standframe[p8] $07 arg1[p8] arg2[p8] arg3[p8] $08 $09 elevation[p16] $0A $0B index[p8] value[p8] $0C color[p8] $0D name[c]... $00 $0E initframe[p8] $10 width[p8] $11 xscale[p8] yscale[p8] $12 $13 zplane[p8] $14 $15 $16 animspeed[p8] $17 shadow[p8]
Operation
Miscellaneous actions on actors.
Opcode | Meaning | Description |
$00 | dummy | A dummy case, does nothing (in ScummVM). |
$01 | SO_COSTUME | Sets the actor's costume. |
$02 | SO_STEP_DIST | Sets the actor's walking speed for x and y. |
$03 | SO_SOUND | Associates a sound with the actor (footsteps?) |
$04 | SO_WALK_ANIMATION | Sets the current frame of the walking animation. |
$05 | SO_TALK_ANIMATION | Sets the start and stop frames of the talking animation. |
$06 | SO_STAND_ANIMATION | Sets the current frame of the standing animation. |
$07 | SO_ANIMATION | Unknown; seems to be unused in ScummVM. |
$08 | SO_DEFAULT | Initializes actor. |
$09 | SO_ELEVATION | Sets the actor's elevation to the given value. |
$0A | SO_ANIMATION_DEFAULT | Initializes the actor's animation frames. Init frame = 1 Walk frame = 2 Stand frame = 3 Talk start frame = 4 Talk stop frame = 5 |
$0B | SO_PALETTE | Sets the color at the given index to a new value (another entry in the color lookup table/CLUT). Index must be between 0 and 31 (the number of colors in a costume). |
$0C | SO_TALK_COLOR | Sets the actor's talk color. |
$0D | SO_ACTOR_NAME | Sets the actor's name to the given null-terminated string. |
$0E | SO_INIT_ANIMATION | Sets the current frame of the initial animation. |
$10 | SO_ACTOR_WIDTH | Sets the actor's width. |
$11 | SO_ACTOR_SCALE | Sets the actor's X and Y scales. |
$12 | SO_NEVER_ZCLIP | Turns off all Z-clipping for the actor. |
$13 | SO_ALWAYS_ZCLIP | Forces the actor's Z-clipping for the given Z-plane? |
$14 | SO_IGNORE_BOXES | Ignores boxes, turns off Z-clipping, and puts actor somewhere if the actor is in the current room? |
$15 | SO_FOLLOW_BOXES | Follows boxes, turns off Z-clipping, and puts actor somewhere if the actor is in the current room? |
$16 | SO_ANIMATION_SPEED | Sets the animation speed. |
$17 | SO_SHADOW | Sets the shadow mode. |
Variants
In SCUMM V3 and V4, the opcode values are slightly different.
Opcode | Meaning |
$00 | dummy |
$01 | SO_COSTUME |
$04 | SO_STEP_DIST |
$05 | SO_SOUND |
$06 | SO_WALK_ANIMATION |
$07 | SO_TALK_ANIMATION |
$08 | SO_STAND_ANIMATION |
$09 | SO_ANIMATION |
$0A | SO_DEFAULT |
$0B | SO_ELEVATION |
$0C | SO_ANIMATION_DEFAULT |
$0D | SO_PALETTE |
$0E | SO_TALK_COLOR |
$0F | SO_ACTOR_NAME |
$10 | SO_INIT_ANIMATION |
$12 | SO_ACTOR_WIDTH |
$13 | SO_ACTOR_SCALE |
$14 | SO_IGNORE_BOXES |
Also in V3 and V4, sub-opcode $13 (SO_ACTOR_SCALE) only takes one parameter, so X and Y scaling is done at a 1:1 ratio.
actorSetClass ($5D)
Encoding
opcode object[p16] classes[v16]...
Operation
Makes object inherit from all of the given classes. A class of "0" will clear all of the object's existing class data.
add ($5A)
Encoding
opcode result value[p16]
Operation
result := result + value
The variable pointed to by result is read, value is added to it, and the result written back.
and ($17)
one parameter, uses result
Encoding
opcode result value[p16]
Operation
result := result and value
The variable pointed to by result is read, logically ANDed with value, and the result written back.
animateActor ($11)
Encoding
opcode actor[p8] anim[p8]
Operation
Starts the given animation for the given actor.
breakHere ($80)
no parameters
Encoding
opcode
Operation
Deschedules the currently running thread. Execution continues at the next instruction when the thread's next timeslot comes around.
chainScript ($42)
one parameter plus varargs
Encoding
opcode script[p8] args[v16]...
Operation
Replaces the currently running script with another one. The current script is terminated immediately and the new script (determined by the given script ID), is executed in the same thread. The new script has its local variables initialised to the list args. Uninitialised variables have undefined values.
cursorCommand ($2C)
parameters depend on auxiliary opcode
Encoding
opcode sub-opcode
sub-opcode can be any of the following:
$01 ... $01 through $08 take the same arguments ... $08 $0A cursornum[p8] charletter[p8] $0B index[p8] x[p8] y[p8] $0C cursor[p8] $0D charset[p8] $0E colors[v16]...
Operation
Miscellaneous actions on cursors & charsets.
Opcode | Meaning | Description |
$01 | SO_CURSOR_ON | Turns the cursor on. |
$02 | SO_CURSOR_OFF | Turns the cursor off. |
$03 | SO_USERPUT_ON | Enables user input. |
$04 | SO_USERPUT_OFF | Disables user input. |
$05 | SO_CURSOR_SOFT_ON | Increments the cursor's state? |
$06 | SO_CURSOR_SOFT_OFF | Decrements the cursor's state? |
$07 | SO_USERPUT_SOFT_ON | Increments "user input" counter (when greater than 0, user input is enabled). |
$08 | SO_USERPUT_SOFT_OFF | Decrements "user input" counter (when 0 or less, user input is disabled). |
$0A | SO_CURSOR_IMAGE | Changes the cursor image to a new one, based on image in a character set. Only used in Loom. |
$0B | SO_CURSOR_HOTSPOT | Changes the hotspot of a cursor. Only used in Loom. |
$0C | SO_CURSOR_SET | Changes the current cursor. Must be between 0 and 3 inclusive. |
$0D | SO_CHARSET_SET | Initializes the given character set. |
$0E | SO_CHARSET_COLORS | Initializes the character set data & colors to the given arguments? Must have 16 arguments? |
Variants
In SCUMM V3, sub-opcode $0E performs a different function, to load/initialize a character set.
opcode $0E arg1[p8] arg2[p8]
cutScene ($40)
Encoding
opcode args[v16]...
Operation
??? If required, runs a script passing the given arguments. Cutscene data given by the first argument?
debug ($6B)
one parameter, no result
Encoding
opcode param[p16]
Operation
Passes the parameter to the interpreter's debugger. What this does is entirely platform-specific (and may do nothing).
decrement ($C6)
no parameters, uses result
Encoding
opcode result
Operation
result := result - 1
Reads the variable pointed to by result, decrements it, and writes it back.
delay ($2E)
one constant parameter
Encoding
opcode param[24]
Operation
Suspends the current thread for the appropriate number of 1/60ths of a second. Yes, that really is a 24-bit LE constant.
delayVariable ($2B)
one constant parameter
Encoding
opcode var
Operation
var is dereferenced and the current thread suspended for that number of 1/60ths of a second.
divide ($5B)
one parameter, uses result
Encoding
opcode result value[p16]
Operation
result := result / value
The variable pointed to by result is read, divided by value, and the result written back. If value is zero, the result is undefined (and the interpeter may halt with an error).
doSentence ($19)
Encoding
opcode verb[p8] objectA[p16] objectB[p16]
Operation
Performs a verb sentence action, e.g. "Use monkey on hydrant". If verb is $FE, the current sentence script is stopped, status cleared etc.
drawBox ($3F)
two parameters, does not use result, supplementary opcode byte with three more subsequent parameters
Encoding
opcode left[p16] top[p16] auxopcode[8] right[p16] bottom[p16] color[p8]
Operation
Draws a solid box on the backbuffer from (left, top) to (right, bottom) in the given color.
The only part of auxopcode that is relevant are the parameter bits. The rest of the opcode is ignored. However, the aux opcode's initial value is $05.
drawObject ($05)
Encoding
opcode object[p16] sub-opcode
sub-opcodes:
$01 xpos[p16] ypos[p16] $02 state[p16] $FF
Operation
Opcode | Meaning | Description |
$01 | Draw At | Moves the given object to the given co-ordinates, and adds it to the drawing queue. |
$02 | Set State | Sets the state of the object, adds it to the drawing queue. |
$FF | Draw | Does not change the object's position (or state?), still adds it to the drawing queue. |
Variants
Small header games (v3 and v4) only support the parameters used with sub-opcode $01, e.g:
opcode object[p16] xpos[p16] ypos[p16]
Accordingly, they have three parameter bits, and hence more possible opcodes.
dummy ($A7)
Encoding
opcode
Operation
V5 specific - The KIXX XL release of Monkey Island 2 (Amiga disk) used this opcode as a dummy, in order to remove copy protection and keep level selection.
Variants
In SCUMM V3 and V4, this opcode is used for the saveLoadVars instruction.
endCutScene ($C0)
Encoding
opcode
Operation
Ends the cutscene, performing cleanup if necessary.
equalZero ($28)
jumps
Encoding
opcode var target[16]
Operation
unless (var == 0) goto target
Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer.
expression ($AC)
Encoding
opcode result subopcode... $FF
sub-opcodes:
$01 value[p16] $02 ... $02 through $05 take the same arguments ... $05 $06 nested-opcode
Operation
Expression mode operates on a stack. Values are pushed on, and operators are applied to the top two items on the stack.
Opcode | Meaning | Description |
$01 | Value | Pushes a value onto the top of the stack. |
$02 | Add | stack[top - 1] + stack[top] |
$03 | Subtract | stack[top - 1] - stack[top] |
$04 | Multiply | stack[top - 1] * stack[top] |
$05 | Divide | stack[top - 1] / stack[top] (if stack[top] is 0 an error occurs) |
$06 | Nested Opcode | An entire instruction that returns a result, such as getActorScale. This is interpreted like a normal opcode, but the result is pushed onto the expression stack. (The opcode is passed the special "VAR_RESULT" parameter for "result") |
faceActor ($09)
Encoding
opcode actor[p8] object[p16]
Operation
Dereferences actor, tells actor to face object (presumably based on X/Y co-ordinates).
findInventory ($3D)
Encoding
opcode result owner[p8] index[p8]
Operation
object := owner.inventory[index]
Searches for all objects owned by owner (an actor or object), and returns the one at the given index (offset).
findObject ($35)
Encoding
opcode result x[p8] y[p8]
Operation
Returns the first "touchable" local object at the given co-ordinates. Will not match on the bottom or right-hand edges of an object.
freezeScripts ($60)
Encoding
opcode flag[p8]
Operation
Freezes all scripts (by setting the high bit on each script's status). If flag is >= $80, all freeze resistent scripts will also be frozen. If flag is 0, all scripts are unfrozen. Freezing effects are cumulative - i.e. if script A is frozen twice, and unfrozen once, it will still be frozen until it is unfrozen a second time. A script's frozen status is indicated by the high bit.
getActorCostume ($71)
Encoding
opcode result actor[p8]
Operation
Returns the actor's current costume.
getActorElevation ($06)
Encoding
opcode result actor[p8]
Operation
Returns the actor's current elevation.
getActorFacing ($63)
Encoding
opcode result actor[p8]
Operation
Returns the current direction the actor is facing.
getActorMoving ($56)
Encoding
opcode result actor[p8]
Operation
Returns the actor's moving status (0 or 1).
getActorRoom ($03)
Encoding
opcode result actor[p8]
Operation
Returns the room the actor currently occupies?
getActorScale ($3B)
Encoding
opcode result actor[p8]
Operation
Returns the actor's current scale.
Variants
In Indy3, this opcode is used for waitForActor.
getActorWalkBox ($7B)
Encoding
opcode result actor[p8]
Operation
Returns the actor's walkbox.
getActorWidth ($6C)
Encoding
opcode result actor[p8]
Operation
Returns the actor's width.
getActorX ($43)
Encoding
opcode result actor[p16]
Operation
Returns the actor's current X co-ordinate.
Variants
In Indy3, actor is only one byte.
opcode result actor[p8]
getActorY ($23)
Encoding
opcode result actor[p16]
Operation
Returns the actor's current Y co-ordinate.
Variants
In Indy3, actor is only one byte.
opcode result actor[p8]
getAnimCounter ($22)
Encoding
opcode result actor[p8]
Operation
Returns the actor's animation counter.
Variants
This opcode is used for saveLoadGame in SCUMM V3.
getClosestObjActor ($66)
Encoding
opcode result actor[p16]
Operation
Returns the object closest to the actor. Items that are more than 255 units (pixels in newer games, characters in older games) away from the actor will not be detected.
getDist ($34)
Encoding
opcode result objA[p16] objB[p16]
Operation
Returns the distance between two actors/objects (objA and objB).
getInventoryCount ($31)
Encoding
opcode result actor[p8]
Operation
Returns the number of items in an actor's inventory?
getObjectOwner ($10)
Encoding
opcode result object[p16]
Operation
Returns the owner of an object.
getObjectState ($0F)
Encoding
opcode result object[p16]
Operation
Returns the state of the object.
Variants
In small header games, this opcode is used for the "ifState" instruction.
getRandomNumber ($16)
Encoding
opcode result seed[p8]
Operation
Returns a new random number based on the given seed.
getScriptRunning ($68)
Encoding
opcode result script[p8]
Operation
Returns 1 if the given script is running, 0 if it's not.
getStringWidth ($67)
Encoding
opcode result strptr[p8]
Operation
Gets the length of the string pointed to by strptr (either a variable or direct byte), stores the returned value in result.
getVerbEntryPoint ($0B)
Encoding
opcode result object[p16] verb[p16]
Operation
Returns the entry point for the response code/script for when the given verb is applied to the given object? i.e. gets the start of the script to run for the specific user interaction.
ifClassOfIs ($1D)
jumps
Encoding
opcode value[p16] args[v16]... target[16]
Operation
unless (value.class is one of [args.class]) goto target
Compares the value's class with all classes given in args.
Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer.
ifNotState ($2F) (V3-4)
This opcode is not present in SCUMM V5.
Encoding
opcode object[p16] state[p8] target[16]
Operation
unless (getState(object) != state) goto target
ifState ($0F) (V3-4)
This opcode is not present in SCUMM V5.
Encoding
opcode object[p16] state[p8] target[16]
Operation
unless (getState(object) == state) goto target
increment ($46)
no parameters, uses result
Encoding
opcode result
Operation
result := result + 1
Reads the variable pointed to by result, increments it, and writes it back.
isActorInBox ($1F)
Encoding
opcode actor[p8] box[p8] target[16]
Operation
Unless the actor's co-ordinates are within the bounds of the given box, jump to target.
Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer.
isEqual ($48)
Encoding
opcode var value[p16] target[16]
Operation
unless (value == var) goto target
Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer.
isGreater ($78)
Encoding
opcode var value[p16] target[16]
Operation
unless (value > var) goto target
Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer.
isGreaterEqual ($04)
Encoding
opcode var value[p16] target[16]
Operation
unless (value >= var) goto target
Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer.
isLess ($44)
Encoding
opcode var value[p16] target[16]
Operation
unless (value < var) goto target
Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer.
isNotEqual ($08)
Encoding
opcode var value[p16] target[16]
Operation
unless (value != var) goto target
Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer.
isSoundRunning ($7C)
Encoding
opcode result sound[p8]
Operation
Returns 1 if sound is running, returns 0 if sound is not running or if the given sound is 0.
jumpRelative ($18)
jumps
Encoding
opcode target[16]
Operation
PC := PC + target
The inline constant target is read as a signed word and added to the program counter after the instruction has been read. Therefore, if target is zero, the instruction will do nothing; if target is -3, an infinite loop will result.
lessOrEqual ($38)
jumps
Encoding
opcode var value[p16] target[16]
Operation
unless (value <= var) goto target
Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer.
lights ($70)
Encoding
opcode arg1[p8] arg2[8] arg3[8]
Operation
If arg3 is 0, the "current lights" variable is set to arg1. If arg3 is 1, the size of the "flashlight" light is determined by arg1 and arg2, for width and height in stripes (which are equivalent to 8 pixels each; see SCUMM/Technical Reference/Image resources).
loadRoom ($72)
Encoding
opcode room[p8]
Operation
Loads the given room into memory.
loadRoomWithEgo ($24)
Encoding
opcode object[p16] room[p8] x[16] y[16]
Operation
Places the Ego actor in room at object's position. If x is not -1, Ego will start moving towards the given x and y co-ordinates. If object is not in the given room an error will occur. (I think...)
matrixOp ($30)
Encoding
opcode sub-opcode
sub-opcodes:
$01 box[p8] val[p8] $02 box[p8] val[p8] $03 box[p8] val[p8] $04
Operation
This instruction manipulates boxes.
Opcode | Meaning | Description |
$01 | setBoxFlags | Sets the box's flags to the given value. |
$02 | setBoxScale | Sets the box's scale. |
$03 | setBoxScale | Sets the box's scale to ((val - 1) OR $8000). |
$04 | createBoxMatrix | Initializes the matrix of boxes, by determining the distances and shortest paths between boxes. |
Variants
SCUMM V3 only has the one instruction, which behaves like setBoxFlags:
opcode box[p8] val[8]
move ($1A)
Encoding
opcode result value[p16]
Operation
result := value
Value is moved into result.
multiply ($1B)
Encoding
opcode result value[p16]
Operation
result := result * value
The variable pointed to by result is read, multiplied by value, and written back.
notEqualZero ($A8)
Encoding
opcode var target[16]
Operation
unless (var != 0) goto target
Target is a byte offset (measured from after this instruction), which will be added to the instruction pointer.
oldRoomEffect ($5C) (V3-4)
This opcode/instruction not present in SCUMM V5.
Encoding
opcode sub-opcode
sub-opcodes:
$03 effect[p16] $?? effect[p16]
Operation
Performs like sub-opcode SO_ROOM_FADE of the roomOps instruction (fade in if effect != 0, otherwise fade out).
This information may not be correct; descumm says if the sub-opcode is 3, to "set" the effect, but if the sub-opcode is anything else to fade in with the given effect.
Variants
FM-Towns SCUMM V3 performs a different effect, not fully implemented in ScummVM. At the moment ScummVM just forces a redraw of the screen background.
or ($57)
one parameter, uses result
Encoding
opcode result value[p16]
Operation
result := result or value
The variable pointed to by result is read, logically ORed with value, and the result written back.
override ($58)
Encoding
opcode sub-opcode
sub-opcodes:
$00 $01 $18 target[16]
Operation
If the sub-opcode is 0, marks the end of an override section.
If the sub-opcode is not 0, marks the beginning of an override section. The instruction is immediately followed by a "jumpRelative" instruction.
Overrides are used by cutscenes; if a cutscene is skipped (if the user presses the ESC key), the script will jump by the given target (offset from the beginOverride instruction).
panCameraTo ($12)
Encoding
opcode x[p16]
Operation
Starts the camera panning to the given x co-ordinate.
pickupObject ($25) (v5)
This instruction is only present in SCUMM V5.
Encoding
opcode object[p16] room[p8]
Operation
Adds the given object (located in the given room) to the Ego actor's inventory.
Variants
In SCUMM V3 and V4, this opcode is used for drawObject.
pickupObject ($50) (V3-4)
This opcode/instruction is not present in SCUMM V5.
Encoding
opcode object[p16]
Operation
Adds the given object (located in the given room) to the Ego actor's inventory. If object < 1, an error is raised. If the object is not found or the object is already in the inventory, this function ends gracefully.
print ($14)
Encoding
opcode actor[p8] sub-opcode
sub-opcodes
$00 xpos[p16] ypos[p16] $01 color[p8] $02 right[p16] $03 width[p16] height[p16] $04 $06 $07 $08 offset[p16] delay[p16] $0F string[c]... $FF
Operation
Sets text properties and displays dialogue.
Opcode | Meaning | Description |
$00 | SO_AT | Sets the position of the text that follows. |
$01 | SO_COLOR | Sets the color of the text. |
$02 | SO_CLIPPED | Clips the text's right-hand side (for wrapping?). |
$03 | SO_ERASE | Erases characters (not used in ScummVM). |
$04 | SO_CENTER | Centres the text. |
$06 | SO_LEFT | Left-aligns the text. |
$07 | SO_OVERHEAD | Overhead-aligns the text. |
$0F | SO_TEXTSTRING | Prints the text string that follows. Terminated by $FF. |
Variants
In SCUMM V3, text function $06 sets the height of the text:
$06 height[p16]
In Loom CD (SCUMM V4), there is an additional text function $08 (SO_SAY_VOICE), which plays a portion of the CD audio track.
$08 offset[p16] delay[p16]
printEgo ($D8)
Encoding
opcode sub-opcode
Operation
Exactly the same as print, except the actor is implicitly Ego. See the entry for "print" for further explanation.
pseudoRoom ($CC)
Encoding
opcode val[8] res[8]... $00
Operation
forall (res) { if (res >= $80) { _resourceMapper[res & $7F] := val } }
What does this actually do? We may never know.
It looks like res values always have the high bit set, e.g. 0x01 becomes 0x81.
putActor ($01)
Encoding
opcode actor[p8] x[p16] y[p16]
Operation
Puts the actor at the given co-ordinates.
putActorAtObject ($0E)
Encoding
opcode actor[p8] object[p16]
Operation
Puts the actor at the given object's position. If the object can not be found, a default position is returned (the centre of the screen in ScummVM).
putActorInRoom ($2D)
Encoding
opcode actor[p8] room[p8]
Operation
Puts the actor in the given room.
resourceRoutines ($0C)
Encoding
opcode sub-opcode
sub-opcodes:
$01 resID[p8] ... $01 through $10 take the same arguments ... $10 resID[p8] $11 $12 resID[p8] $13 resID[p8] $14 room[p8] object[p16]
Operation
resID is unique only within the resource type (e.g. script 11 will not conflict with sound 11).
Opcode | Meaning | Description |
$01 | SO_LOAD_SCRIPT | Loads the given script into memory. |
$02 | SO_LOAD_SOUND | Loads the given sound into memory. |
$03 | SO_LOAD_COSTUME | Loads the given costume into memory. |
$04 | SO_LOAD_ROOM | Loads the given room into memory. |
$05 | SO_NUKE_SCRIPT | Obliterates the given script from memory. |
$06 | SO_NUKE_SOUND | Obliterates the given sound from memory. |
$07 | SO_NUKE_COSTUME | Obliterates the given costume from memory. |
$08 | SO_NUKE_ROOM | Obliterates the given room from memory. |
$09 | SO_LOCK_SCRIPT | Locks the given script. |
$0A | SO_LOCK_SOUND | Locks the given sound. |
$0B | SO_LOCK_COSTUME | Locks the given costume. |
$0C | SO_LOCK_ROOM | Locks the given room. |
$0D | SO_UNLOCK_SCRIPT | Unlocks the given script. |
$0E | SO_UNLOCK_SOUND | Unlocks the given sound. |
$0F | SO_UNLOCK_COSTUME | Unlocks the given costume. |
$10 | SO_UNLOCK_ROOM | Unlocks the given room. |
$11 | SO_CLEAR_HEAP | Clears the heap. |
$12 | SO_LOAD_CHARSET | Loads the given character set into memory. |
$13 | SO_NUKE_CHARSET | Obliterates the given character set from memory. |
$14 | SO_LOAD_OBJECT | Loads the given object from the given room resource. |
Variants
FM-Towns games add the following sub-opcodes (these are not confirmed nor implemented in ScummVM):
Opcode | Meaning | Description |
$20 | Unknown | Does nothing, not used in-game. |
$21 | Unknown | Does nothing, not used in-game. |
$23 | CD Volume | Possibly changes the volume of CD tracks (Loom CD). Takes 1 byte. |
$24 | Sound Volume | Sets the loudness of a sound resource. Used in Indy3 and Zak. Takes 2 bytes (left/right volumes?). |
$25 | Sound Pitch | Sets the pitch of a sound resource. Used in Indy3 and Zak. Takes 1 byte (pitch = "foo" - "center" semitones. Center is at $32 in the sound resource.) |
roomOps ($33)
Encoding
opcode sub-opcode
sub-opcodes:
$01 minX[p16] maxX[p16] $03 b[p16] h[p16] $04 red[p16] green[p16] blue[p16] aux index[p8] $05 $06 $07 scale1[p8] y1[p8] aux scale2[p8] y2[p8] aux slot[p8] $08 scale[p8] startcolor[p8] endcolor[p8] $09 loadflag[p8] loadslot[p8] $0A effect[p16] $0B redscale[p16] greenscale[p16] bluescale[p16] aux startcolor[p8] endcolor[p8] $0C redscale[p16] greenscale[p16] bluescale[p16] aux startcolor[p8] endcolor[p8] $0D resID[p8] filename[c]... $00 $0E resID[p8] filename[c]... $00 $0F resID[p8] aux start[p8] end[p8] aux time[p8] $10 colindex[p8] delay[p8]
Operation
Opcode | Meaning | Description |
$01 | SO_ROOM_SCROLL | Clamps the given arguments so scrolling does not extend past the width of the room or screen. |
$03 | SO_ROOM_SCREEN | Initialises a screen. |
$04 | SO_ROOM_PALETTE | Adjusts the room's palette. Aux opcode's initial value is $04. |
$05 | SO_ROOM_SHAKE_ON | Starts the room shaking. |
$06 | SO_ROOM_SHAKE_OFF | Ends the room shaking. |
$07 | SO_ROOM_SCALE | Sets the room's y scales? (slot is 1 greater than actual slot?) |
$08 | SO_ROOM_INTENSITY | Lightens/darkens the room's palette. |
$09 | SO_ROOM_SAVEGAME | Saves temporary state of the room/game? |
$0A | SO_ROOM_FADE | If effect is 0, fades in the room. Otherwise, fades out with the given effect (taken from the high byte of effect). 1 = iris effect 2 = box wipe (upper-left to bottom-right) 3 = box wipe (upper-right to bottem-left) 4 = inverse box wipe. |
$0B | SO_RGB_ROOM_INTENSITY | Lightens/darkens the room's palette, with different scales for red, green and blue. Aux opcode's initial value is $0B. |
$0C | SO_ROOM_SHADOW | Lightens/darkens the shadow palette, with different scales for red, green, and blue. |
$0D | SO_SAVE_STRING | Saves a string resource to the given file? |
$0E | SO_LOAD_STRING | Loads a string resource from a given file? |
$0F | SO_ROOM_TRANSFORM | Manipulates palettes, strings? |
$10 | SO_CYCLE_SPEED | Starts color cycling with delay? colIndex is between 0 and 16 |
Variants
SCUMM V3 (non-PC Engine) encodes the arguments before the sub-opcode:
opcode arg1[p16] arg2[p16] sub-opcode
Small header games (V3 and V4) include an extra sub-opcode, $02 (SO_ROOM_COLOR), which adjusts the room's palette:
opcode $02 color[p16] index[p16] ... or for V3 games ... opcode color[p16] index[p16] $02
In small header games, sub-opcode $04 (SO_ROOM_PALETTE) affects the shadow palette, and only accepts two arguments, a "room color slot" (palette entry? between 0 and 256) and an index:
opcode $04 color[p16] index[p16] ... or for V3 games ... opcode color[p16] index[p16] $04
In FM-Towns games, sub-opcode $0A performs a different function and has its own sub-opcodes (some unknown and all not yet implemented in ScummVM):
opcode $0A sub-opcode
Opcode | Meaning | Description |
$08 | compose kMainVirtScreen over a screen buffer | |
$09 | call 0x110:0x20 _ax=0x601 _edx=2 | |
$0A | call 0x110:0x20 _ax=0x601 _edx=3 | |
$0B | clear screen 0x1C:0x45000 sizeof(640 * 320) | |
$0C | call 0x110:0x20 _ax=0x601 _edx=0 | |
$0D | call 0x110:0x20 _ax=0x601 _edx=1 | |
$10 | enable clearing of a screen buffer in drawBitmap() | |
$11 | disable clearing of a screen buffer in drawBitmap() | |
$12 | clear a screen buffer | |
$13 | enable palette operations (palManipulate(), cyclePalette() etc.) | |
$14 | disable palette operations | |
$15 | disable clearing of screen 0x1C:0x5000 sizeof(640 * 320) in initScreens() | |
$16 | enable clearing of screen 0x1C:0x5000 sizeof(640 * 320) in initScreens() | |
$1E | Unknown |
saveLoadGame ($22) (V3-4)
This instruction is not present in SCUMM V5; its opcode is used for "getAnimCounter".
Encoding
opcode result arg1[p8]
Operation
The slot is determined by taking the lower 5 bits of arg1. The upper 3 bits determine an aux opcode, that performs an action described in the table below.
Opcode | Meaning | Description |
$00 | Num. Available Slots | Returns the number of save slots available. |
$20 | Drive | In V3, returns the type of drive (0 = ???, 1 = A or B [floppy], 2 = hard drive). In V4, sets the current drive (returns 1). |
$40 | Load Game | Loads a game from the given slot (returns 3 if successful, 5 otherwise). |
$80 | Save Game | Saves a game to the given slot (returns 0 if successful, 2 otherwise). |
$C0 | Test For Game | Tests if a save exists in the given slot (returns 6 if so, 7 otherwise). |
saveLoadVars ($A7) (V3-4)
This instruction is not present in SCUMM V5; its opcode is used as a dummy.
Encoding
opcode sub-opcode
sub-opcodes:
$01 sub-sub-opcode... $00 $02 sub-sub-opcode... $00
$01 (save) sub-sub-opcodes:
$01 resultA resultB $02 arg1[p8] arg2[p8] $03 filename[c]... $00 $04 $1F
$02 (load) sub-sub-opcodes:
$01 resultA resultB $02 arg1[p8] arg2[p8] $03 filename[c]... $00 $04 $1F
Operation
Opcode | Meaning | Description |
$01 | SO_SAVE_VARS | Saves variables (for saving games?) |
$02? | SO_RESTORE_VERBS | Loads variables (for saving games?) (I have not verified that restore vars is $02, as the ScummVM code only compares to $01.) |
Opcode | Meaning | Description |
$01 | Write Vars | Writes a range of variables. |
$02 | Write Strings | Writes a range of string variables. |
$03 | Open File | Opens a file for writing. |
$04 | Dummy | Does nothing. |
$1F | Close File | Closes the last opened file. |
Opcode | Meaning | Description |
$01 | Read Vars | Reads a range of variables. |
$02 | Read Strings | Reads a range of string variables. |
$03 | Open File | Opens a file for reading. |
$04 | Dummy | Does nothing. |
$1F | Close File | Closes the last opened file. |
saveRestoreVerbs ($AB)
Encoding
opcode sub-opcode
sub-opcodes:
$01 start[p8] end[p8] mode[p8] $02 start[p8] end[p8] mode[p8] $03 start[p8] end[p8] mode[p8]
Operation
Opcode | Meaning | Description |
$01 | SO_SAVE_VERBS | For all verbs between start and end, sets the "saveid" to mode. |
$02 | SO_RESTORE_VERBS | For all verbs between start and end and matching mode, kills any existing verb, sets the saveid to 0 and generally inits the verb. |
$03 | SO_DELETE_VERBS | For all verbs between start and end and matching mode, kills any existing verb. |
setCameraAt ($32)
Encoding
opcode x[p16]
Operation
Sets the camera's x position.
setObjectName ($54)
Encoding
opcode object[p16] name[c]... $00
Operation
Sets the given object's name.
setOwnerOf ($29)
Encoding
opcode object[p16] owner[p8]
Operation
Sets the owner of the object.
setState ($07)
Encoding
opcode object[p16] state[p8]
Operation
Sets the state of the object.
setVarRange ($26)
non-standard encoding
Encoding
opcode result number[8] values[8]...
or
opcode result number[8] values[16]...
Operation
for (i = 0; i < number; i++) { *result + i := values[i]; }
This sets a number of variables to the given parameters. The starting variable is given as "result", and the number of variables to modify is given as "number". This is followed by the same number of values, which will be put into the variable locations. The values are constants, and can be either 16-bit, if the highest bit of the opcode is set, i.e. $A6; or 8-bit, if the highest bit of the opcode is not set, i.e. $26. Note that all values are affected by the opcode's high bit; you can't mix 8 and 16-bit values.
descumm example:
setVarRange(Var[178],9,[0,0,0,0,0,0,0,0,0]);
This sets variables 178 to 186 (inclusive) to 0.
soundKludge ($4C)
Encoding
opcode items[v16]...
Operation
If the first item is -1, the existing sound queue is processed. Otherwise, the list of items is added to the queue.
Variants
In SCUMM V3 and V4 (small header) games, this opcode is used for the WaitForSentence instruction.
startMusic ($02)
Encoding
opcode music[p8]
Operation
Adds the music in to the queue to be played.
Variants
In FM-Towns (SCUMM V3) games, this instruction performs different functions (some kind of Audio CD status query function; some partially implemented in ScummVM):
opcode result sub-opcode
Opcode | Meaning | Description |
$00 | Is Playing | Returns true if a CD audio track is currently playing. |
$FC | Unpause CD | Unpauses the CD audio track. |
$FD | Pause CD | Pauses the CD audio track. |
$FE | Get CD Sound | Returns the current CD sound. |
$FF | CD Volume | Might return the the current CD volume in FM-Towns Loom. |
other | Track Length | Returns the track length in seconds. |
startObject ($37)
Encoding
opcode object[p16] script[p8] args[v16]...
Operation
Starts the object's script (OBCD blocks), passing the given arguments.
startScript ($0A)
one parameter plus varargs, extra encoding in opcode
Encoding
opcode script[p8] args[v16]...
Operation
Spawns a new thread running the code in script script. The new script has its local variables initialised to the list args. Uninitialised variables have undefined values.
The opcode carries extra information:
7 | 6 | 5 | 4 0 |
P1 | R | F | $0A |
P1 = standard parameter bit
R = indicates that the script is recursive
F = indicates that the script is freeze resistant (a call to freezeScripts will skip this script, unless the "force freeze" bit of the freezeScripts opcode is set).
startSound ($1C)
Encoding
opcode sound[p8]
Operation
Adds the given sound to the sound queue to be played.
stopMusic ($20)
Encoding
opcode
Operation
Stops all sounds.
stopObjectCode ($A0 or $00)
Encoding
opcode
Operation
Marks the calling script as dead, to be later pruned from the thread pool. Cleans up residual arrays. Should always be the last instruction in a script.
$A0 is used in local and global scripts (LSCR and SCRP blocks in the V5 resource files), $00 is used in room entry, room exit, and verb/object scripts (ENCD, EXCD, VERB blocks).
stopObjectScript ($6E)
Encoding
opcode script[p16]
Operation
Marks the given object script as dead, to be later pruned from the thread pool. Cleans up residual arrays.
stopScript ($62)
Encoding
opcode script[p8]
Operation
Marks the given script as dead, to be later pruned from the thread pool. Cleans up residual arrays.
stopSound ($3C)
Encoding
opcode sound[p8]
Operation
Stops the given sound.
stringOps ($27)
parameters depend on sub-opcode
Encoding
opcode sub-opcode
sub-opcodes:
$01 stringID[p8] string[c]... $00 $02 destID[p8] srcID[p8] $03 stringID[p8] index[p8] char[c] $04 result stringID[p8] index[p8] $05 stringID[p8] size[p8]
Operation
Miscellaneous actions on strings (Arrays, referred to by resource number).
Opcode | Meaning | Description |
$01 | Load String | Loads the inline null-terminated string into the resource slot given by stringID. |
$02 | Copy String | Creates a duplicate of the string at resource slot srcID into destID. The old string at destID is lost. |
$03 | Write Character | Writes char at the given index (offset) of the string resource located at slot stringID. Out of bounds accesses cause undefined behavior. |
$04 | Read Character | Reads a byte (character) at the given index (offset) of the string resource located at slot stringID, and writes it to result. Out of bounds accesses cause undefined behavior. |
$05 | New String | Allocates or frees a string (Array), located at resource slot stringID. The string is initialised to size; if size is zero, the string is freed. |
subtract ($3A)
Encoding
opcode result value[p16]
Operation
result := result - value
The variable pointed to by result is read, value is subtracted from it, and the result written back.
systemOps ($98)
Encoding
opcode sub-opcode
sub-opcodes:
$01 $02 $03
Operation
Opcode | Meaning | Description |
$01 | SO_RESTART | Restarts the game. |
$02 | SO_PAUSE | Pauses/unpauses the game. |
$03 | SO_QUIT | Quits the game. |
verbOps ($7A)
Encoding
opcode verbID[p8] sub-opcode... $FF
sub-opcodes:
$01 object[p16] $02 name[c]... $00 $03 color[p8] $04 hicolor[p8] $05 left[p16] top[p16] $06 $07 $08 $09 $10 color[p8] $11 $12 key[p8] $13 $14 stringID[p16] $16 object[p16] room[p8] $17 color[p8]
Operation
Opcode | Meaning | Description |
$01 | SO_VERB_IMAGE | Assigns an object (image) to a verb. |
$02 | SO_VERB_NAME | Assigns the in-line name to the verb slot. |
$03 | SO_VERB_COLOR | Sets the color of the verb. |
$04 | SO_VERB_HICOLOR | Sets the highlight color of the verb. |
$05 | SO_VERB_AT | Sets the verb's top-left co-ordinates. |
$06 | SO_VERB_ON | Makes this verb active. |
$07 | SO_VERB_OFF | Makes this verb inactive. |
$08 | SO_VERB_DELETE | Kills this verb. |
$09 | SO_VERB_NEW | Creates a verb in the slot for the given verbID. If the slot is 0 (verb doesn't already exist), will add it to the next unusued slot; if this exceeds the global maximum number of verbs an error will be raised. |
$10 | SO_VERB_DIMCOLOR | Sets the dim color of the verb. |
$11 | SO_VERB_DIM | Dims this verb. |
$12 | SO_VERB_KEY | Sets the key code (maybe ASCII char?) associated with this verb. |
$13 | SO_VERB_CENTER | Centres the verb? |
$14 | SO_VERB_NAME_STR | Loads the given string resource into the verb's slot. If either the string resource or verb slot is not found (0), the verb resource is nuked. |
$16 | Assign Object | Assigns an object from the given room to the verb (if the object's image index is not already assigned to the given object). |
$17 | Set Back Color | Sets the background color of the verb? |
wait ($AE)
Encoding
opcode sub-opcode
sub-opcodes:
$01 actor[p8] $02 $03 $04
Operation
Opcode | Meaning | Description |
$01 | SO_WAIT_FOR_ACTOR | If the given actor is moving, breaks and resumes at this instruction again. |
$02 | SO_WAIT_FOR_MESSAGE | If the global variable VAR_HAVE_MSG (Var[3]) is not zero, breaks and resumes at this instruction again. |
$03 | SO_WAIT_FOR_CAMERA | If the camera has not reached its destination x position, breaks and resumes at this instruction again. |
$04 | SO_WAIT_FOR_SENTENCE | If there is a sentence present?, breaks and resumes at this instruction again |
Variants
In Indy3 (non-Macintosh), this opcode only acts as SO_WAIT_FOR_MESSAGE and omits the sub-opcode.
opcode
walkActorTo ($1E)
Encoding
opcode actor[p8] x[p16] y[p16]
Operation
Sets the actor to begin walking to the given position.
walkActorToActor ($0D)
Encoding
opcode walker[p8] walkee[p8] distance[8]
Operation
Walks walker towards walkee's position by the given distance. Walker and walkee are both actors.
walkActorToObject ($36)
Encoding
opcode actor[p8] object[p16]
Operation
Sets the actor to begin walking to the given object's position.
Variables
A number of variables are reserved for use by the SPUTM/SCUMM engine. Here is a list of known variables and their corresponding numbers, taken from the ScummVM source code.
VAR_RESULT = 0; // descumm claims var 0 is the result var (for expressions) VAR_KEYPRESS = 0; // script_v5_.cpp claims var 0 is for keypresses... VAR_EGO = 1; VAR_CAMERA_POS_X = 2; VAR_HAVE_MSG = 3; VAR_ROOM = 4; VAR_OVERRIDE = 5; VAR_MACHINE_SPEED = 6; VAR_ME = 7; VAR_NUM_ACTOR = 8; VAR_CURRENT_LIGHTS = 9; VAR_CURRENTDRIVE = 10; VAR_TMR_1 = 11; VAR_TMR_2 = 12; VAR_TMR_3 = 13; VAR_MUSIC_TIMER = 14; VAR_ACTOR_RANGE_MIN = 15; VAR_ACTOR_RANGE_MAX = 16; VAR_CAMERA_MIN_X = 17; VAR_CAMERA_MAX_X = 18; VAR_TIMER_NEXT = 19; VAR_VIRT_MOUSE_X = 20; VAR_VIRT_MOUSE_Y = 21; VAR_ROOM_RESOURCE = 22; VAR_LAST_SOUND = 23; VAR_CUTSCENEEXIT_KEY = 24; VAR_TALK_ACTOR = 25; VAR_CAMERA_FAST_X = 26; VAR_SCROLL_SCRIPT = 27; VAR_ENTRY_SCRIPT = 28; VAR_ENTRY_SCRIPT2 = 29; VAR_EXIT_SCRIPT = 30; VAR_EXIT_SCRIPT2 = 31; VAR_VERB_SCRIPT = 32; VAR_SENTENCE_SCRIPT = 33; VAR_INVENTORY_SCRIPT = 34; VAR_CUTSCENE_START_SCRIPT = 35; VAR_CUTSCENE_END_SCRIPT = 36; VAR_CHARINC = 37; VAR_WALKTO_OBJ = 38; VAR_DEBUGMODE = 39; VAR_HEAPSPACE = 40; VAR_RESTART_KEY = 42; VAR_PAUSE_KEY = 43; VAR_MOUSE_X = 44; VAR_MOUSE_Y = 45; VAR_TIMER = 46; VAR_TIMER_TOTAL = 47; VAR_SOUNDCARD = 48; VAR_VIDEOMODE = 49; VAR_MAINMENU_KEY = 50; VAR_FIXEDDISK = 51; VAR_CURSORSTATE = 52; VAR_USERPUT = 53; VAR_V5_TALK_STRING_Y = 54; VAR_SOUNDRESULT = 56; VAR_TALKSTOP_KEY = 57; VAR_FADE_DELAY = 59; VAR_NOSUBTITLES = 60; VAR_SOUNDPARAM = 64; VAR_SOUNDPARAM2 = 65; VAR_SOUNDPARAM3 = 66; VAR_INPUTMODE = 67; // 1 is keyboard, 2 is joystick, 3 is mouse VAR_MEMORY_PERFORMANCE = 68; VAR_VIDEO_PERFORMANCE = 69; VAR_ROOM_FLAG = 70; VAR_GAME_LOADED = 71; VAR_NEW_ROOM = 72;
Table of Parameters
Please see the wiki page SCUMM/V5_opcodes/Table for a concise rendition of the above information (with a few omissions dues to the complexity of the instructions).