Home
Memoirs of a Gamer
Movies I watched
Guidebook
Code Projects
Links
At the heart of the engine is the virtual machine. The virtual machine is basically a collection of subsystems that are tied together via a bytecode interpreter. These subsystems are:
Beyond these subsystems there is the bytecode interpreter which has the following configuration
Object | Table Count |
Script File Segments | 10 |
Integer Variables | 256 |
Integer Stack | 256 |
String Variables | 16 |
Inventory Table | 128 |
Room Tracker Table | 1008 |
Script files are block loaded into the appropriate segment as requested. When execution begins the VM tracks which segment is currently executing, the beginning and ending of the current script, and the current program counter. There is also a limited execution stack that is used to track when call instructions are executed.
We start with the script header which follows the following structure:
Offset | Size | Value |
00 | 02 | Should always be the hex value 6353h |
02 | 01 | Title Index |
03 | 01 | Variable Count |
04 | 01 | Event Count |
05 | 01 | Start Event Index |
06 | 02 | String Count |
08 | 02 | Events Table Offset |
0A | 02 | Bytecode Segment Size |
0C | 02 | Bytecode Segment Offset |
0E | 02 | String Table Offset |
10 | 02 | String Data Size |
12 | 02 | String Data Offset |
14 | 01 | Array Size |
15 | 01 | Reserved |
16 | 02 | Array Data Offset |
The Title Index identifies the entry in the String Table that contains
the game's title. A value of -1 implies no Title.
The Start Event Index
identifies the entry in the Events that defines the event to be executed
upon loading the script. A value of -1 implies no Start Event.
The Events table is composed of 6 byte records following the format:
Offset | Size | Value |
00 | 02 | Bytecode Offset |
02 | 02 | Bytecode Length |
04 | 01 | Name Index |
05 | 01 | Reserved |
The Bytecode segment contains all of the events' bytecode blocks strung together with no empty spaces between events.
The String Table is a simple array of 16 bit integers describing the offsets of each string in within the String Data segment. Strings are delimited by null terminator characters.
The String Data segment contains all strings with a null terminator character inserted after each string. All strings are stored as ASCII characters.
The Array Data segment is a simple array of 16 bit integers that can be referenced by the Bytecode instructions.
The GDK comes with a decompiler called Descriptor which is found in the same folder as the Scriptor compiler tool. Usage:
descriptor game.cns |
There are several system registers that can be accessed by using a series of pseudo variables that are dot notation extensions of the internal sys object. They are as follows:
ID | Name | Accessibility | Category |
0 | sys.ThisRoom | Read | Room |
1 | sys.LastRoom | Read | Room |
2 | sys.FirstTime | Read | Room |
3 | sys.Score | Read/Write | Score |
4 | sys.MaxScore | Read/Write | Score |
5 | sys.Random | Read/Write | Math |
6 | sys.Controlled | Write | Flags |
7 | sys.Typing | Write | Flags |
8 | sys.Physics | Write | Flags |
9 | sys.SlowType | Write | Flags |
10 | sys.Spr_Id | Write | Sprites |
11 | sys.Spr_X | Read | Sprites |
12 | sys.Spr_Y | Read | Sprites |
13 | sys.Spr_Dir | Read | Sprites |
14 | sys.Spr_Priority | Read/Write | Sprites |
15 | sys.Spr_Map | Read | Sprites |
16 | sys.Spr_Completed | Read | Sprites |
17 | sys.Spr_Slot | Write | Sprites |
18 | sys.Spr_Pal | Write | Sprites |
19 | sys.Time | Read | Math |
20 | sys.ShowScore | Write | Flags |
Let's break these down by category.
There's 3 Room related registers, ThisRoom, LastRoom, and FirstTime. They are read only and their purposes are fairly straight forward.
Then we have the score related registers for current Score and the MaxScore. They are exactly as their names suggest. An important note to bare in mind is that the Score register will force a refresh of the score marker on the screen if the ShowScore register is set. No such functionality is attached to MaxScore.
Next we have our 2 Math registers: Random and Time.
Now let's look at the environment flags. All flags are intended as simple write only boolean values. Like other parts of the engine, true is defined by what's not false and false is always defined as 0. Their behavior is mostly self explanatory, but for clarity's sake we'll list them here:
NOTE:Slow Type causes the printing subsystem to type one character to the screen at a time, allowing for a vsync event between each character. Disabled by default. Disabling this feature causes strings to be printed as quickly as possible.
The last set of system registers are for the Sprite subsystem and are discussed in detail here.