The Koota virtual machine runs Koota bytecode. It has the concept of memory, which is a randomly-accessible field of opcodes, and an output, which is where the generation result is.
At all times, the virtual machine is at a memory address or offset, which is
an unsigned 16-bit number (aka C unsigned short
). The offset points to a
memory location; therefore, the maximum amount of memory possible is 64 KiB
(65536 bytes), which should be enough for any reasonable pattern. In every
occasion, this offset is encoded big-endian.
The virtual machine’s starting offset is always 0x0000
.
There is also the concept of a call stack. Offsets are stored in that stack
by call
to be used when ret
is executed. The maximum length of the call
stack is 256.
Koota bytecode has the following opcodes:
Opcode | Mnemonic | Description |
---|---|---|
0x00 |
halt |
Halts the machine, stopping word generation. |
0x01 |
jump |
Jumps to the given offset. |
0x02 |
put |
Puts the given character in the output. |
0x03 |
pick |
Randomly picks an offset in the given list and jumps to it. |
0x04 |
call |
Calls subroutine. |
0x05 |
ret |
Returns from subroutine. |
0x06 |
jrnd |
Randomly jumps to the given offset. |
With these few opcodes, any Koota pattern can be “bytecodified”. In the following section, they will be explained in more detail.
- Arguments: none
- Total length: 1 byte
When this opcode is run, the machine halts, with the generated word in the output.
- Arguments: an offset (2 bytes)
- Total length: 3 bytes
When this opcode is run, the virtual machine’s offset becomes the offset argument, and execution continues from there.
- Arguments: an UTF-8 character (1 to 4 bytes)
- Total length: 2 to 5 bytes
When this opcode is run, the virtual machine places the given character at the end of its output.
- Arguments: an offset (2 bytes)
- Total length: 3 bytes
When this opcode is run, the given offset is taken as the start pointer of a
list of offsets, with the first element representing the length of the list.
Then, an offset in that list is randomly picked, and that offset is jump
ed
to.
- Arguments: an offset (2 bytes)
- Total length: 3 bytes
When this opcode is run, the current offset plus one (i.e. the offset that
would be ran if the call
wasn’t there) is pushed to the call stack, and the
given offset is jump
ed to. If the call stack is full (256 entries), then the
virtual machine must halt
.
- Arguments: none
- Total length: 1 byte
When this opcode is run, the topmost offset in the call stack is jump
ed to
and the call stack is popped. This effectively returns to the next opcode after
the last call
, completing the subroutine.
If the call stack is empty, the virtual machine should put the string
<ret with empty stack>
in the output then immediately halt
.
- Arguments: an offset (2 bytes)
- Total length: 3 bytes
When this opcode is run, there is 50% chance of jumping to the given offset. If the jump does not happen, this is a no-op.
If the virtual machine finds an unrecognised opcode, it must halt
.
If the virtual machine tries to access an offset out of bounds of its memory,
it must halt
.