Skip to content

Commit c050d93

Browse files
committed
pit: document VM command parsing
...partially
1 parent 969cd9a commit c050d93

File tree

1 file changed

+86
-1
lines changed

1 file changed

+86
-1
lines changed

nds/pit/scripting_commands.md

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,89 @@
1-
# VM commands
1+
# AlphaDream VM documentation
2+
3+
This is documentation for the specific VM used in Partners in Time.
4+
The VMs used in the rest of the M&L series are similar, but not identical.
5+
6+
Huge thanks to the people at [BIS-docs](https://mnl-modding.github.io/BIS-docs/) for helping me figure this stuff out ❤️
7+
8+
# Command parsing
9+
Before parsing even begins, the VM has a table with command opcode attributes.
10+
It is not yet know exactly what these attributes look like, but they play a critical role in command parsing.
11+
The table is constant and never changes.
12+
13+
Note in the following pseudo-code, `vm.read()` consumes 16 bits of data from the program.
14+
See [variable addressing modes](#variable-addressing-modes) for information on `vm.readVariables()`.
15+
[Command structs](#command-struct) are roughly read like this:
16+
```go
17+
// Read command metadata
18+
command.opcode = vm.read()
19+
attributes := vm.getAttributes(opcode)
20+
if attributes.hasResult {
21+
command.result = vm.read()
22+
}
23+
if attributes.hasFlags {
24+
command.flags = cm.read()
25+
}
26+
27+
// Read arguments
28+
for i := 0; i < attributes.numArguments; i++ {
29+
if command.flags & (1 << i) == 0 {
30+
command.arguments[i] = vm.read()
31+
} else {
32+
command.arguments[i] = vm.readVariable(vm.read());
33+
}
34+
}
35+
```
36+
37+
## Variable addressing modes
38+
When reading a VM variable, the top 4 bits of the variable are not used for the address, but for addressing mode.
39+
Here is a list of known addressing modes:
40+
41+
### `0x0000`: 0
42+
This addressing mode always returns 0.
43+
44+
### `0x1000`: value from manager
45+
Reads a value from the script manager.
46+
Maybe from the stack? not sure...
47+
`return (u32*)(scriptManager)[1 + variable];`
48+
49+
### `0x2000`: boolean flag
50+
Reads a single bit from a bitlist.
51+
Almost identical to `0xE000` + `0xF000`, but only has 12 bits for bit index.
52+
The bitlist read from is also not the same.
53+
54+
### `0x3000`: field specific
55+
Calls to a function that is only valid when overlay 0 (field program) is loaded.
56+
If jumped to in battle, will probably crash the game completely.
57+
Unknown exactly what happens and what is returned.
58+
59+
### `0x4000`: battle specific
60+
Same as `0x3000`, but for battles.
61+
Unknown what is returned from this method (more research needed).
62+
63+
### `0x5000` through `0xD000`: TBD
64+
**More research needed!**
65+
66+
## `0xE000` and `0xF000`: boolean flag
67+
Reads a single bit from a bitlist.
68+
The purpose of this bitlist is currently unknown.
69+
The value in the lower 13 (yes 13, not 12. That's why both E and F) is the bit index.
70+
71+
## Data types
72+
73+
### Command struct
74+
A command in the PiT VM looks like this:
75+
```C
76+
struct VmCommand {
77+
0x00: u16, opcode // The command opcode
78+
0x02: u16, result // The variable to store the result at
79+
0x04: u16, flags // Determines if an argument is an immediate or not
80+
0x06: u16, _ // unknown
81+
0x08: [16]i32, arguments // Command arguments
82+
0x48: u16, _ // unknown
83+
}
84+
```
85+
86+
# Command opcodes
287

388
All instructions return a status of `0` to the interpreter, unless otherwise noted.
489

0 commit comments

Comments
 (0)