INSET
Besides simple values like IO::BACKGROUND_COLOR, IO memory can also store compound objects. For example, each video tilemap is controlled by 16 bytes, consisting of 8 variables. We could define each variable individually using LOCATED AT, like this:
# SIMPLISTIC REPRESENTATION OF TILEMAPS
MODULE IO
VAR TILEMAP_A_X: PAIR LOCATED AT $D0_0310
VAR TILEMAP_A_Y: PAIR LOCATED AT $D0_0312
VAR TILEMAP_A_COL_COUNT: PAIR LOCATED AT $D0_0314
VAR TILEMAP_A_ROW_COUNT: PAIR LOCATED AT $D0_0316
VAR TILEMAP_A_TILE_CODES_ADDRESS: INT LOCATED AT $D0_0318
VAR TILEMAP_A_EDGE_MODE: BYTE LOCATED AT $D0_031C
VAR TILEMAP_A_JUMBO: BYTE LOCATED AT $D0_031D
VAR TILEMAP_A_TILE_COUNT: PAIR LOCATED AT $D0_031E
VAR TILEMAP_B_X: PAIR LOCATED AT $D0_0320
VAR TILEMAP_B_Y: PAIR LOCATED AT $D0_0322
VAR TILEMAP_B_COL_COUNT: PAIR LOCATED AT $D0_0324
VAR TILEMAP_B_ROW_COUNT: PAIR LOCATED AT $D0_0326
VAR TILEMAP_B_TILE_CODES_ADDRESS: INT LOCATED AT $D0_0328
VAR TILEMAP_B_EDGE_MODE: BYTE LOCATED AT $D0_032C
VAR TILEMAP_B_JUMBO: BYTE LOCATED AT $D0_032D
VAR TILEMAP_B_TILE_COUNT: PAIR LOCATED AT $D0_032E
. . .
END MODULE
However, this would be difficult to work with—for example, how would we make a function whose parameter could be tilemap A or B or C? It's better to represent these structures using a CLASS definition:
CLASS IO_TILEMAP # SIZE 16
VAR X: PAIR, Y: PAIR
VAR COL_COUNT: PAIR, ROW_COUNT: PAIR
VAR TILE_CODES_ADDRESS: INT
VAR EDGE_MODE: BYTE
VAR JUMBO: BYTE
VAR TILE_COUNT: PAIR
END CLASS
Inset module members
In order to map the above structure to IO memory, we need to define a module variable with this type. It would seem that we could do this:
MODULE IO
# ⚠️ WRONG
VAR TILEMAP_A: IO_TILEMAP LOCATED AT $D0_0310
# ⚠️ WRONG
VAR TILEMAP_B: IO_TILEMAP LOCATED AT $D0_0320
END MODULE
...however the above syntax would locate a 4-byte pointer at $D0_0310, whereas we intended to specify that the entire IO_TILEMAP object (and its X member) should start at $D0_0310.
The INSET storage directive solves this problem:
MODULE IO
# CORRECT
INSET TILEMAP_A: IO_TILEMAP LOCATED AT $D0_0310
INSET TILEMAP_B: IO_TILEMAP LOCATED AT $D0_0320
END MODULE
It specifies that the IO_TILEMAP instance itself starts in memory at $D0_0310, eliminating the pointer. If your program puts IO::TILEMAP_A into a regular variable, the pointer value will be $D0_0310 rather than being read from address $D0_0310.
Inset class members
INSET can also be used with CLASS member variables. There, it eliminates the pointer by directly embedding one class instance inside another. For example, Jamdac specifies controllable sound dynamics using this 5 byte structure:
CLASS IO_DYNAMIC # 5 BYTES
VAR CONTROL: BYTE
VAR LOW: PAIR
VAR HIGH: PAIR
END CLASS
A channel effect contains six of these 5-byte structures, arranged sequentially in memory, for a total of 30 bytes. We use INSET to embed them directly in IO_CHANNEL_EFFECT:
CLASS IO_CHANNEL_EFFECT # SIZE 30
INSET DISTORTION_GAIN: IO_DYNAMIC
INSET DELAY_SAMPLES: IO_DYNAMIC
INSET DELAY_FEEDBACK: IO_DYNAMIC
INSET DRY_LEVEL: IO_DYNAMIC
INSET PREDELAY_LEVEL: IO_DYNAMIC
INSET POSTDELAY_LEVEL: IO_DYNAMIC
END CLASS
Without INSET, the above class would instead contain six pointers to separately allocated IO_DYNAMIC objects.
Inset array elements
For fixed-size arrays whose element is a pointer type, the pointer can be eliminated by replacing the SIZE keyword with INSET. For example:
MODULE IO
# ⚠️ WRONG - THE AUDIO_QUEUES[0] POINTER IS AT $D0_4000
INSET AUDIO_QUEUES: IO_AUDIO_QUEUE[SIZE 6] LOCATED AT $D0_4000
END MODULE
MODULE IO
# CORRECT - THE AUDIO_QUEUES[0] OBJECT ITSELF STARTS AT $D0_4000
INSET AUDIO_QUEUES: IO_AUDIO_QUEUE[INSET 6] LOCATED AT $D0_4000
END MODULE
Since the size of IO_AUDIO_QUEUE is 512 bytes ($200 hexadecimal), the AUDIO_QUEUES[1] object will be located at $D0_4200, and AUDIO_QUEUES[2] will be located at $D0_4400, and so forth.
Rules for INSET
Rules that the compiler enforces for INSET:
INSETmodule members must haveLOCATED AT.INSETarrays must be fixed-size, and their elements must beINSET(not using theSIZEkeyword).INSETmembers cannot form a circular reference, as this would imply an infinitely large object.- A class with a vtable cannot be
INSET.