from-a-file
A program of Generators.
main.ngp
include "atari/130xe.ngp"
modules { "print.asm" "run.asm" "shared.asm" "intro.asm" "level.asm"
; tag generator
binary( "maps/level1.map", section = levelMap, in = level ) as maps
; end generator
}
panes in ext { level }
resident { print, run, shared }
phase intro { needs intro then level entry introStart }
phase level { needs level, maps entry levelStart }
entry intro
container xex
130xe.ngp project
; An Atari 130XE: four extended Banks as a unit set, the Window PORTB brings
; one of them into, the Window over the OS ROM, every Region of the address
; space, and the Modules a program on this machine needs. What PORTB takes to
; show a state is the driver's and not here, and the OS is a Module rather than
; a Region because it occupies memory for a while rather than being a truth
; about addresses.
target {
cpu "6502"
; DOS loads a `.xex`, and a Project naming any other Container is refused
; here rather than at the writer.
containers xex
units extension 4
window ext $4000 .. $7FFF views main, extension base main
window os $C000 .. $CFFF, $D800 .. $FFFF views rom, ram base rom
}
storage { units extension }
target {
region ram $0000 .. $CFFF ram
region $D800 .. $FFFF ram
region stack $0100 .. $01FF reserved
region io $D000 .. $D7FF register
; This machine takes a `.xex` and nothing else, and a `.xex` is loaded by a
; DOS, which stays where a DOS of the 2.x family stays. A Project whose DOS
; takes more says so with a `reserved` Region of its own, which narrows this
; one further.
region dos $0700 .. $1FFF reserved
; What the driver writes. A Project that wants more of the hardware by name
; declares it, as it declares the memory its DOS holds.
register PORTB $D301
}
; The OS, the driver for this storage and the decoders the tool ships, listed
; as a file of the Project's own would be. Every Transition calls the driver
; and the decoders, so they are resident; a decoder nothing uses is dropped.
modules { "atari/os.asm" "atari/charsets.asm" "atari/portb.asm" "stream/zx0.asm" }
resident { os, charsets, portb, zx0 }
os.asm os
; The Atari OS as a Module: what it occupies while it is in memory, and the
; names a program reaches it by. Sections that hold no bytes, pinned where
; the OS lives, so the solver sees memory that is taken rather than a Region
; it may never allocate from — which is what lets a Phase that switches the
; ROM out have those addresses back, once there is a way to say so. See
; 0038 for why what occupies memory for a while is a Module, and 0051 for
; what this first cut settles and what it leaves.
;
; Every Section here is `root`: the OS and the hardware reach them with no
; Reference in any Chunk, so nothing else would keep them. None holds bytes,
; so none has a Payload and no Transition loads one.
;
; This is the OS as an XL or XE ships it. A machine whose OS lives elsewhere
; declares a Module of its own; the variant is what chooses.
.export RTCLOK, SDMCTL, SDLSTL, SDLSTH, CH, SETVBV, XITVBV
; The OS's half of the zero page. The program's own variables live above it,
; in the half the variant leaves to the solver.
.section zeropage at $0000, root
osZero
.res $12
RTCLOK .res 3 ; $0012: the frame counter, three bytes
.res $6B
.ends
; The OS's variables and buffers. The shadow registers are among them and
; are Labels here rather than registers of the variant: they are the OS's
; memory, which the OS copies to the hardware on every vertical blank, and
; a `register` Region inside this Section would be an address the Section
; may not cover.
.section absolute at $0200, root
osRam
.res $2F
SDMCTL .res 1 ; $022F: shadows DMACTL
SDLSTL .res 1 ; $0230: the display list address, low
SDLSTH .res 1 ; $0231: and high
.res $CA
CH .res 1 ; $02FC: the last key pressed, $FF for none
.res $403
.ends
; The ROM, in the two ranges the hardware registers leave between them, and
; the entry points a program calls in the second. The RAM underneath is what
; a Phase without the OS would be given.
.section absolute at $C000, root
osRomLow
.res $1000
.ends
.section absolute at $D800, root
osRomHigh
.res $C5C
SETVBV .res 3 ; $E45C: A = the stage, X/Y = the routine
.res 3
XITVBV .res 3 ; $E462: the end of a deferred routine
.res $1B9B
.ends
charsets.asm charsets
; The Atari's two codes for the same letters, as Charsets.
;
; `atascii` is what the character I/O takes: the machine's own code, with the
; graphics characters where an ASCII machine keeps its control codes, and the
; letters where ASCII has them — which is why an unprefixed literal of plain
; letters has always worked and why nothing else has. `\n` is `$9B`, the end of
; line, and not `$0A`.
;
; `screen` is what the display reads out of screen memory, which is the same
; letters at other numbers. A program that writes where the display looks
; rather than through the OS wants this one.
;
; The graphics characters are written here as the Unicode the box-drawing and
; block characters have, so a picture drawn in the source is the picture the
; machine draws. A letter in inverse video is one of those too — Unicode squares
; them off in a negative, and `atascii"PRESS 🆂"` is seven bytes with the last
; one inverse. A whole line of inverse text is better asked of a Charset
; derived from this one, `.charset bright : atascii ^ $80`, which is what a
; derivation is for. Two of them have no exact Unicode: `$02` and `$0D` are a
; quarter of a cell where the nearest character is an eighth, and are written
; as `▕` and `▔`. Everything else, the inverse entries included, was read off
; the machine's own font and matches it.
;
; This Module emits nothing: it is two names and two tables.
.export atascii, screen
; tag atascii
.charset atascii
"♥├▕┘┤┐╱╲◢▗◣▝▘▔▂▖♣┌─┼●▄▎┬┴▌└" = $00
"↑↓←→" = $1C
" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" = $20
"♦" = $60
"abcdefghijklmnopqrstuvwxyz" = $61
"♠" = $7B
"│" = $7C
"\n" = $9B
; Inverse video is the same glyph with the bits the other way round, which
; for the blocks and the triangles is another character Unicode draws. Every
; one of these was read off the machine's own font and is exact; the rest of
; the inverse half has no glyph to be written as, and is reached by adding
; $80 or by a Charset derived from this one.
"▊" = $82 ; ▕
"◤" = $88 ; ◢
"▛" = $89 ; ▗
"◥" = $8A ; ◣
"▙" = $8B ; ▝
"▟" = $8C ; ▘
"▆" = $8D ; ▔
"▜" = $8F ; ▖
"▀" = $95 ; ▄
"▐" = $99 ; ▌
"█" = $A0 ; the space
; And the letters, which Unicode squares off in a negative.
"🅰🅱🅲🅳🅴🅵🅶🅷🅸🅹🅺🅻🅼🅽🅾🅿🆀🆁🆂🆃🆄🆅🆆🆇🆈🆉" = $C1
.endch
; end atascii
.charset screen
" !\"#$%&'()*+,-./0123456789:;<=>?" = $00
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" = $20
"♥├▕┘┤┐╱╲◢▗◣▝▘▔▂▖♣┌─┼●▄▎┬┴▌└" = $40
"♦" = $60
"abcdefghijklmnopqrstuvwxyz" = $61
"♠" = $7B
"│" = $7C
; The same inverses, at the display's numbers.
"▊" = $C2
"◤" = $C8
"▛" = $C9
"◥" = $CA
"▙" = $CB
"▟" = $CC
"▆" = $CD
"▜" = $CF
"▀" = $D5
"▐" = $D9
"█" = $80
"🅰🅱🅲🅳🅴🅵🅶🅷🅸🅹🅺🅻🅼🅽🅾🅿🆀🆁🆂🆃🆄🆅🆆🆇🆈🆉" = $A1
.endch
portb.asm portb
; The storage driver for extended memory behind PORTB: the units are the
; Banks of the variant's `extension`, which a value written to PORTB brings
; into the $4000-$7FFF window — `ext` in the variant — and the stream is a
; pointer into that window that walks on to the next unit at its end. Each
; role is a macro declared with `.driver`, which the routine, the loader's
; glue, the decoders and the tool's own Procs expand where they use it as
; `nga.open`, `nga.read`, `nga.show` and `nga.showAt`. What the hardware
; calls each state of a Window is this Module's alone: `portbValues` holds
; a PORTB value per state of `ext` — base RAM first, then one per Bank, as
; many as the variant's `extension` counts — and the OS Window is bit 0.
; `PORTB` is the variant's register.
;
; Resident, and outside the window — the variant lists this Module in
; `resident`, and the tool holds it outside the window the stream reads
; through.
portbWindow = $4000
portbWindowEnd = portbWindow + $4000 ; one past the window: the high byte of the first address outside it
portbUnitPages = $40 ; a unit, in pages: what an offset carries by
portbBase = $FF ; base RAM in, the OS ROM in, BASIC and the self-test out
.driver open portbOpen
.driver read portbRead
.driver stream ext
.driver show ext portbShow
.driver showAt ext portbShowAt
.driver show os portbShowOs
.driver showAt os portbShowOsAt
.transform copy portbCopy
.macro portbOpen
jsr portbOpenStream
.endm
.macro portbRead
jsr portbReadByte
.endm
; The state to show, as the tool numbers ext's states: 0 is base RAM, and
; Bank n is n + 1.
.macro portbShow state
ldx #state
jsr portbSelect
.endm
; X = the state to show.
.macro portbShowAt
jsr portbSelect
.endm
; The OS Window is bit 0 of PORTB: set for the ROM, state 0, and clear for
; the RAM beneath it, state 1. The bank bits are left as they are.
.macro portbShowOs state
lda PORTB
and #$FE
ora #1 - state
sta PORTB
.endm
; X = the state to show, 0 or 1.
.macro portbShowOsAt
lda PORTB
ora #1
cpx #0
beq @store
and #$FE
@store
sta PORTB
.endm
; PORTB per state of ext: base RAM, then one value per Bank. The list runs
; to the 130XE's four and the variant's count trims it, so that a variant
; with fewer Banks takes a prefix; one with more lists its values here.
; Every value has bit 0 set — the OS ROM in — which is what lets
; portbSelect keep the OS Window's bit with one `and` and no scratch byte.
.macro portbBankValues n, values...
.if n > 0
.match values
.case first, rest...
.byte first
portbBankValues n - 1, rest...
.endmatch
.endif
.endm
; The table portbSelect indexes, in a Section of its own: what has an
; address stands in one, and a Proc holds code alone.
.section
portbValues
.byte portbBase
portbBankValues extension, $E3, $E7, $EB, $EF
.ends
; The stream: where the next byte is, and which unit is in. A plain zero-page
; Section rather than Temporaries, because the value has to survive between
; one call and the next while nothing here is running.
.section zeropage
portbPtr .res 2
portbUnit .res 1
.ends
; X = the state of ext to show: its PORTB value, with the OS bit left as it
; is, since the OS Window is the same byte. Writes no memory, so that a
; loader running it leaves nothing behind but the register.
.proc portbSelect
lda PORTB
ora #$FE
and portbValues,x
sta PORTB
rts
.endp
; A = the unit, X/Y = the offset in it: the stream stands there. An offset
; past the unit's end carries into the units after, since the routine
; counts on in a Frame without knowing where a unit ends: a unit is $4000
; bytes, so the offset's top two bits are units.
.proc portbOpenStream
sta portbUnit
stx portbPtr
tya
@carry
cmp #portbUnitPages
bcc @within
sbc #portbUnitPages
inc portbUnit
jmp @carry
@within
clc
adc #>portbWindow
sta portbPtr+1
ldx portbUnit
inx ; Bank n is state n + 1
jsr portbSelect
rts
.endp
; A = the next byte of the stream. X and Y are not preserved.
.proc portbReadByte
ldy #0
lda (portbPtr),y
inc portbPtr
bne @done
inc portbPtr+1
ldy portbPtr+1
cpy #>portbWindowEnd
bne @done
pha
jsr portbNextUnit
pla
@done
rts
.endp
; The window's end: the next unit in, and the pointer back at its start.
.proc portbNextUnit
inc portbUnit
ldx portbUnit
inx
jsr portbSelect
lda #0
sta portbPtr
lda #>portbWindow
sta portbPtr+1
rts
.endp
; The decoder of `copy`: X/Y = the destination, the stream at the stored
; size and then the bytes. Reads the window through the pointer rather than
; through portbReadByte, which is what a driver's own decoder is for: a run at a
; time, where a run ends at the source's page end or at the size, so that
; the inner loop is `(zp),y` down to zero — the window's end is a page end,
; so a unit is never crossed inside a run.
portbDst .ztemp 2
portbSize .ztemp 2
portbRun .ztemp 1 ; bytes in the run, zero for 256
.proc portbCopy
stx portbDst
sty portbDst+1
jsr portbReadByte
sta portbSize
jsr portbReadByte
sta portbSize+1
@run
lda portbSize
ora portbSize+1
beq @done
lda portbPtr ; to the end of the source's page
eor #$FF
clc
adc #1
sta portbRun
lda portbSize+1
bne @copy ; at least a page left: the run stands
lda portbRun
beq @cap ; a whole page, and less than one left
cmp portbSize
bcc @copy
@cap
lda portbSize
sta portbRun
@copy
ldy portbRun
@byte
dey
lda (portbPtr),y
sta (portbDst),y
tya
bne @byte
ldx portbRun ; the run, as 256 where it is zero
bne @counted
inc portbPtr+1
inc portbDst+1
dec portbSize+1
jmp @crossed
@counted
txa
clc
adc portbPtr
sta portbPtr
bcc @source
inc portbPtr+1
@source
txa
clc
adc portbDst
sta portbDst
bcc @destination
inc portbDst+1
@destination
sec
lda portbSize
stx portbRun
sbc portbRun
sta portbSize
bcs @crossed
dec portbSize+1
@crossed
lda portbPtr+1
cmp #>portbWindowEnd
bne @run
jsr portbNextUnit ; the window's end: the next unit in
jmp @run
@done
rts
.endp
zx0.asm zx0
; The decoder of `zx0` over any driver's stream: Einar Saukas's ZX0, version
; 2's standard forward stream, decoded as the reference dzx0.c does, driven
; by the stream's own end marker. Written here from the format, not ported:
; nothing of the reference's text is in it, and it is licensed as everything
; under lib/ is, see lib/LICENSE. Entered with X/Y = the destination and the
; stream at the stored size, which it reads past. A match is copied a byte
; at a time, forward, from what was written, which is what makes an offset
; shorter than its length — the run — come out right. Resident, and outside
; the driver's window.
;
; zx0Bits the bit buffer, a sentinel one above the bits still unread
; zx0Offset the last offset
; zx0Length the length in hand, or an offset's MSB while one is read
; zx0Invert one while an offset's MSB is read, whose data bits the
; stream carries complemented; zero otherwise
.transform zx0 zx0Decode
zx0Dst .ztemp 2
zx0Src .ztemp 2
zx0Bits .ztemp 1
zx0Offset .ztemp 2
zx0Length .ztemp 2
zx0Invert .ztemp 1
; The next bit of the stream, in A as zero or one and in the Z flag. The
; buffer holds a sentinel above the unread bits, so shifting it to nothing is
; the signal to fetch the next byte and put the sentinel back below it.
.proc zx0Bit
asl zx0Bits
bne @have
nga.read
rol ; the carry the asl left is the sentinel
sta zx0Bits
@have
lda #0
rol
rts
.endp
; An interlaced Elias gamma value into zx0Length: a control bit says whether
; a data bit follows, and the value begins at one. Three Procs chained by
; `then` because the value after an offset is entered with its first control
; bit already read, at zx0EliasData: the first falls through into the
; second, and the second branches into the third, which the chain is what
; allows.
.proc zx0Elias
lda #1
sta zx0Length
lda #0
sta zx0Length+1
.endp then zx0EliasMore
.proc zx0EliasMore
jsr zx0Bit
beq zx0EliasData ; zero: a data bit follows
rts
.endp then zx0EliasData
.proc zx0EliasData
jsr zx0Bit
eor zx0Invert
lsr
rol zx0Length
rol zx0Length+1
jmp zx0EliasMore
.endp
; One byte written: the destination moves on and the length in hand comes
; down, leaving Z set when it reaches zero.
.proc zx0Step
inc zx0Dst
bne @moved
inc zx0Dst+1
@moved
lda zx0Length
bne @low
dec zx0Length+1
@low
dec zx0Length
lda zx0Length
ora zx0Length+1
rts
.endp
; The length in hand copied from zx0Dst less the last offset to zx0Dst.
.proc zx0Copy
sec
lda zx0Dst
sbc zx0Offset
sta zx0Src
lda zx0Dst+1
sbc zx0Offset+1
sta zx0Src+1
@byte
ldy #0
lda (zx0Src),y
sta (zx0Dst),y
inc zx0Src
bne @from
inc zx0Src+1
@from
jsr zx0Step
bne @byte
rts
.endp
.proc zx0Decode
stx zx0Dst
sty zx0Dst+1
nga.read ; the stored size, which the end marker makes unnecessary
nga.read
lda #$80
sta zx0Bits ; an empty buffer: the sentinel alone
lda #1
sta zx0Offset
lda #0
sta zx0Offset+1 ; the last offset begins at one
sta zx0Invert
@literals
jsr zx0Elias
@literal
nga.read
ldy #0
sta (zx0Dst),y
jsr zx0Step
bne @literal
jsr zx0Bit
bne @offset
jsr zx0Elias ; a match at the last offset
jsr zx0Copy
jsr zx0Bit
beq @literals
@offset
lda #1
sta zx0Invert
jsr zx0Elias ; the new offset's MSB, complemented in the stream
lda #0
sta zx0Invert
lda zx0Length
beq @done ; 256 is the end marker, and the one value with a low byte of zero
lsr ; offset = MSB * 128 - LSB / 2
sta zx0Offset+1
lda #0
ror
sta zx0Offset
nga.read
lsr ; the LSB's low bit is the length's first control bit
php
eor #$FF
sec
adc zx0Offset
sta zx0Offset
bcs @subtracted
dec zx0Offset+1
@subtracted
plp
lda #1
sta zx0Length
lda #0
sta zx0Length+1
bcs @counted ; a control bit of one: the value is one
jsr zx0EliasData
@counted
inc zx0Length ; a match at a new offset is one longer than written
bne @copy
inc zx0Length+1
@copy
jsr zx0Copy
jsr zx0Bit
bne @offset
jmp @literals
@done
rts
.endp
print.asm
; The one thing both Phases need: a line on the screen, through the character
; I/O the OS opens on channel 0 before a program starts. `PUTREC` writes a
; record, so it ends the line itself.
CIOV = $E456
ICCOM = $0342
ICBAL = $0344
ICBLL = $0348
PUTREC = 9
; Both Phases call it, so both have to see the name.
.export printLine
; Where the line stands, and how long it is. Declaring where the two arguments
; are is what lets a Module of C call this one as a function.
.proc printLine
.declare arg xy
.declare arg a
stx ICBAL
sty ICBAL+1
sta ICBLL
lda #0
sta ICBLL+1
lda #PUTREC
sta ICCOM
ldx #0
jsr CIOV
rts
.endp
run.asm
; The shape every screen has: a title, and then whatever the Phase draws under
; it. Neither is here — this Module knows only that there are two of them, and
; which Phase is running it never learns.
; tag slot
.export title, draw, showScreen
.slot title, pointer, zeropage
.slot draw, vector
; end slot
; tag screen
.proc showScreen
ldy #0
@count lda (title),y ; the Phase's title, as long as it turns out
beq @print
iny
bne @count
@print
tya
ldx title
ldy title+1
jsr printLine
jsr draw
rts
.endp
; end screen
shared.asm
; Nothing of the program uses this. It is pinned into the Window's range to
; show what the rule permits: a Section in no Pane is in the Window's base
; state, and the Pane's Sections are in another, so the two never collide
; however their Phases overlap. `root`, because nothing names it.
.section absolute at $4000, root
.res 64
.ends
intro.asm
; tag fills
.implements title, introTitle
.implements draw, introDraw
.section
introTitle
.byte "INTRO", 0
.ends
; end fills
.section
introText
.byte "THE FIRST SCREEN"
introTextEnd
.ends
.proc introDraw
ldx #<introText
ldy #>introText
lda #introTextEnd - introText
jsr printLine
rts
.endp
.proc introStart
jsr showScreen
.transition level
.endp
level.asm
; The map is not here any more. What is here is what draws it, and the row
; width it walks by.
levelWidth = 37
; tag fills
.implements title, levelTitle
.implements draw, levelDraw
.section
levelTitle
.byte "LEVEL ONE", 0
.ends
; end fills
; A Trampoline: it stands in base RAM, out of the Window, but runs with `level`
; shown, which is what lets it name what the Pane holds.
.proc drawMap, under level
at .ztemp 2
left .ztemp 1
lda #<levelMap
sta at
lda #>levelMap
sta at+1
lda #levelMap.runtimeSectionSize / levelWidth
sta left
@row
ldx at
ldy at+1
lda #levelWidth
jsr printLine
clc
lda at
adc #levelWidth
sta at
bcc @counted
inc at+1
@counted
dec left
bne @row
rts
.endp
.proc levelDraw
.with level
jsr drawMap
rts
.endp
.proc levelStart
jsr showScreen
@stop jmp @stop
.endp
maps.asm maps
.source "maps/level1.map", 1
.section absolute, in level
levelMap
.export levelMap
.base64 "IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMuLi4uLi4uLi4u"
.base64 "Li4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLiMjLi4uLi4uLi4uLi4uLi4uLi4uLi4u"
.base64 "Li4uLi4uLi4uLi4uLi4jIy4uLi4uLiMjIyMjIyMjLi4uLi4uLi4uLi4uLi4uLi4u"
.base64 "Li4uIyMuLi4uLi4jLi4uLi4uIy4uLi4uLi4uLi4uLi4uLi4uLi4uLiMjLi4uLi4u"
.base64 "Iy4uLi4uLiMuLi4uLi4uLi4uLi4uLi4uLi4uLi4jIy4uLi4uLiMjIyMjIyMjLi4u"
.base64 "Li4uLi4uLi4uLi4uLi4uLi4uIyMuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u"
.base64 "Li4uLi4uLiMjLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4jIyMj"
.base64 "IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw=="
.ends
transition.asm nga.transition
; The Transition routine. Called by `jsr` from a `.transition`, with the
; statement's list right behind the call: the Phase to enter, and per Phase
; the code may be in, the unit and offset where the edge's Frame waits.
; nga.open and nga.read are the driver's roles, macros of the driver's
; Module expanded here; ngaShowBases is the Proc the tool generates beside
; the dispatcher, which reads from the Frame the base the entered Phase gives
; every Window and shows it, the stream's last; and ngaCurrentPhase is the
; Cell the tool generates. Everything else the edge has to say waits in the
; Frame, in storage. See docs/spec/transition.md.
;
; Its zero page is Temporaries: nothing of it is needed once the routine has
; jumped to the entered Phase's entry, and a `.transition` is a jump into the
; routine, so whatever the statement's Section had on the zero page is dead by
; then too. Two Temporaries never live at once share an address — see
; docs/decisions/0034-trace.md.
.export ngaTransition
ngaPtr .ztemp 2
ngaEntry .ztemp 2
ngaDst .ztemp 2
ngaValue .ztemp 2
ngaOffset .ztemp 2
ngaFramePos .ztemp 2
ngaWanted .ztemp 1
ngaCount .ztemp 1
ngaFrameUnit .ztemp 1
ngaUnit .ztemp 1
.proc ngaTransition
pla
sta ngaPtr
pla
sta ngaPtr+1 ; the return address: one below the statement's list
ldy #1
lda (ngaPtr),y
sta ngaWanted ; the Phase to enter
iny
lda (ngaPtr),y
sta ngaCount ; entries that follow
lda ngaPtr
clc
adc #3
sta ngaPtr
bcc @scan
inc ngaPtr+1
@scan
lda ngaCount
bne @check
brk ; no entry for the current Phase: unreachable while the static rule holds
@check
ldy #0
lda (ngaPtr),y
cmp ngaCurrentPhase
beq @found
lda ngaPtr ; the next entry: four bytes on
clc
adc #4
sta ngaPtr
bcc @skipped
inc ngaPtr+1
@skipped
dec ngaCount
jmp @scan
@found
iny
lda (ngaPtr),y
sta ngaFrameUnit ; the unit the Frame waits in
iny
lda (ngaPtr),y
sta ngaFramePos
iny
lda (ngaPtr),y
sta ngaFramePos+1 ; and where in it
.endp then ngaEnter
; The rest of it, and the way in for a Container that has no current Phase to
; look one up by: ngaWanted holds the Phase to enter and ngaFrameUnit and
; ngaFramePos where its Frame waits. The cold start comes here — see
; docs/decisions/0216-a-car-names-its-format-and-the-cold-start-is-an-edge.md.
.export ngaEnter
.proc ngaEnter
jsr ngaFrameOpen
nga.read
sta ngaEntry
nga.read
sta ngaEntry+1
nga.read
sta ngaCount ; blocks that follow
lda #3
jsr ngaFrameSkip
@block
lda ngaCount
beq @cells
jsr ngaFrameOpen ; back to the Frame: a block's stream replaced it
nga.read
sta ngaUnit
nga.read
sta ngaOffset
nga.read
sta ngaOffset+1
nga.read
sta ngaDst
nga.read
sta ngaDst+1
nga.read
pha ; the decoder's number
lda #6
jsr ngaFrameSkip
lda ngaUnit
ldx ngaOffset
ldy ngaOffset+1
nga.open ; the block's stream: its stored size, then its bytes
pla
ldx ngaDst
ldy ngaDst+1
jsr ngaTransform
dec ngaCount
jmp @block
@cells
jsr ngaFrameOpen
nga.read
sta ngaCount ; Cell writes that follow, read in one stream
@cell
lda ngaCount
beq @enter
nga.read
sta ngaDst
nga.read
sta ngaDst+1
nga.read
sta ngaValue
nga.read
sta ngaValue+1
ldy #0
lda ngaValue
sta (ngaDst),y ; a Cell stands outside the driver's window
iny
lda ngaValue+1
sta (ngaDst),y
dec ngaCount
jmp @cell
@enter
jsr ngaShowBases ; the entered Phase's base in every Window, read from the Frame
lda ngaWanted
sta ngaCurrentPhase ; the Phase the program is in from here on
jmp (ngaEntry)
.endp
; The Frame's stream, from where the routine last left it.
.proc ngaFrameOpen
lda ngaFrameUnit
ldx ngaFramePos
ldy ngaFramePos+1
nga.open
rts
.endp
; A bytes on in the Frame, which is where its stream is opened next.
.proc ngaFrameSkip
clc
adc ngaFramePos
sta ngaFramePos
bcc @done
inc ngaFramePos+1
@done
rts
.endp
cell nga.cell
ngaCurrentPhasetransforms.asm nga.transforms
; The dispatcher over the decoders the program declared, in the order the
; tool numbered them. See docs/spec/transition.md.
.export ngaShowBases
.proc ngaShowBases
nga.read
tax
nga.showAt os
nga.read
tax
nga.showAt ext
rts
.endp
.export ngaRestore
.proc ngaRestore, root
nga.show os, 0
nga.show ext, 0
rts
.endp
.export ngaLoadUnit, ngaLoadMap
.section root
ngaLoadUnit
.res 1
.ends
.proc ngaLoadMap, root
ldx ngaLoadUnit
nga.showAt ext
rts
.endp
.export ngaTransform
.proc ngaTransform
cmp #0
bne @not0
jmp portbCopy
@not0
brk
.endp
Memory map
- intro145 zero page, 16268 bytes
- level145 zero page, 16661 bytes
| Address | Bytes | Section | Module | Kind | Phases | Waits |
|---|---|---|---|---|---|---|
| $0000–$007F | 128 | osZero | os | section | 0..1 | |
| $0080–$0082 | 3 | portbPtr | portb | section | 0..1 | |
| $0083–$0084 | 2 | ngaDst | nga.transition | temporary | 0..1 | |
| $0083–$0084 | 2 | ngaPtr | nga.transition | temporary | 0..1 | |
| $0083–$0084 | 2 | portbDst | portb | temporary | 0..1 | |
| $0085–$0086 | 2 | ngaOffset | nga.transition | temporary | 0..1 | |
| $0085–$0086 | 2 | ngaValue | nga.transition | temporary | 0..1 | |
| $0085–$0086 | 2 | portbSize | portb | temporary | 0..1 | |
| $0087–$0087 | 1 | ngaUnit | nga.transition | temporary | 0..1 | |
| $0087–$0087 | 1 | portbRun | portb | temporary | 0..1 | |
| $0088–$0089 | 2 | ngaEntry | nga.transition | temporary | 0..1 | |
| $008A–$008B | 2 | ngaFramePos | nga.transition | temporary | 0..1 | |
| $008C–$008C | 1 | ngaWanted | nga.transition | temporary | 0..1 | |
| $008D–$008D | 1 | ngaCount | nga.transition | temporary | 0..1 | |
| $008E–$008E | 1 | ngaFrameUnit | nga.transition | temporary | 0..1 | |
| $008F–$0090 | 2 | title | nga.slots | section | 0..1 | |
| $0200–$06FF | 1280 | osRam | os | section | 0..1 | |
| $2000–$2004 | 5 | portbValues | portb | section | 0..1 | |
| $2005–$2010 | 12 | portbSelect | portb | proc | 0..1 | |
| $2011–$202C | 28 | portbOpenStream | portb | proc | 0..1 | |
| $202D–$2042 | 22 | portbReadByte | portb | proc | 0..1 | |
| $2043–$2053 | 17 | portbNextUnit | portb | proc | 0..1 | |
| $2054–$20C5 | 114 | portbCopy | portb | proc | 0..1 | |
| $20C6–$20DE | 25 | printLine | proc | 0..1 | ||
| $20DF–$20F3 | 21 | showScreen | run | proc | 0..1 | |
| $20F4–$20F9 | 6 | introTitle | intro | section | 0 | |
| $20FA–$2109 | 16 | introText | intro | section | 0 | |
| $210A–$2113 | 10 | introDraw | intro | proc | 0 | |
| $2114–$211F | 12 | introStart | intro | proc | 0 | |
| $2137–$217F | 73 | ngaTransition | nga.transition | proc | 0..1 | |
| $2180–$2210 | 145 | ngaEnter | nga.transition | proc | 0..1 | |
| $2211–$221A | 10 | ngaFrameOpen | nga.transition | proc | 0..1 | |
| $221B–$2224 | 10 | ngaFrameSkip | nga.transition | proc | 0..1 | |
| $2225–$2225 | 1 | ngaCurrentPhase | nga.cell | section | 0..1 | |
| $2226–$2228 | 3 | draw | nga.slots | section | 0..1 | |
| $2229–$2242 | 26 | ngaShowBases | nga.transforms | proc | 0..1 | |
| $2243–$2252 | 16 | ngaRestore | nga.transforms | proc | 0..1 | |
| $2253–$2253 | 1 | ngaLoadUnit | nga.transforms | section | 0..1 | |
| $2254–$225A | 7 | ngaLoadMap | nga.transforms | proc | 0..1 | |
| $225B–$2262 | 8 | ngaTransform | nga.transforms | proc | 0..1 | |
| $4000–$403F | 64 | spare | shared | section | 0..1 | |
| $C000–$CFFF | 4096 | osRomLow | os | section | 0..1 | |
| $D800–$FFFF | 10240 | osRomHigh | os | section | 0..1 | |
| $0083–$0084 | 2 | drawMap.at | level | temporary | 1 | |
| $0085–$0085 | 1 | drawMap.left | level | temporary | 1 | |
| $20F4–$20FD | 10 | levelTitle | level | section | 1 | bank 0 +$0026 (copy, 12 B) |
| $20FE–$2122 | 37 | drawMap | level | proc | 1 | bank 0 +$0032 (copy, 39 B) |
| $2123–$2130 | 14 | levelDraw | level | proc | 1 | bank 0 +$0059 (copy, 16 B) |
| $2131–$2136 | 6 | levelStart | level | proc | 1 | bank 0 +$0069 (copy, 8 B) |
| $4000–$4171 | 370 | levelMap | maps | section | 1 |
The xex
1136 bytes, 13 segments, 0 unaccounted.
| 0 | 2 | container header |
$2000–$211F 288 bytes at 2
| $2000 | 1 | portb.portbValues | portb.asm |
| $2001 | 4 | portb.portbValues | portb.asm |
| $2005 | 3 | portb.portbSelect | portb.asm |
| $2008 | 2 | portb.portbSelect | portb.asm |
| $200A | 3 | portb.portbSelect | portb.asm |
| $200D | 3 | portb.portbSelect | portb.asm |
| $2010 | 1 | portb.portbSelect | portb.asm |
| $2011 | 2 | portb.portbOpenStream | portb.asm |
| $2013 | 2 | portb.portbOpenStream | portb.asm |
| $2015 | 1 | portb.portbOpenStream | portb.asm |
| $2016 | 2 | portb.portbOpenStream | portb.asm |
| $2018 | 2 | portb.portbOpenStream | portb.asm |
| $201A | 2 | portb.portbOpenStream | portb.asm |
| $201C | 2 | portb.portbOpenStream | portb.asm |
| $201E | 3 | portb.portbOpenStream | portb.asm |
| $2021 | 1 | portb.portbOpenStream | portb.asm |
| $2022 | 2 | portb.portbOpenStream | portb.asm |
| $2024 | 2 | portb.portbOpenStream | portb.asm |
| $2026 | 2 | portb.portbOpenStream | portb.asm |
| $2028 | 1 | portb.portbOpenStream | portb.asm |
| $2029 | 3 | portb.portbOpenStream | portb.asm |
| $202C | 1 | portb.portbOpenStream | portb.asm |
| $202D | 2 | portb.portbReadByte | portb.asm |
| $202F | 2 | portb.portbReadByte | portb.asm |
| $2031 | 2 | portb.portbReadByte | portb.asm |
| $2033 | 2 | portb.portbReadByte | portb.asm |
| $2035 | 2 | portb.portbReadByte | portb.asm |
| $2037 | 2 | portb.portbReadByte | portb.asm |
| $2039 | 2 | portb.portbReadByte | portb.asm |
| $203B | 2 | portb.portbReadByte | portb.asm |
| $203D | 1 | portb.portbReadByte | portb.asm |
| $203E | 3 | portb.portbReadByte | portb.asm |
| $2041 | 1 | portb.portbReadByte | portb.asm |
| $2042 | 1 | portb.portbReadByte | portb.asm |
| $2043 | 2 | portb.portbNextUnit | portb.asm |
| $2045 | 2 | portb.portbNextUnit | portb.asm |
| $2047 | 1 | portb.portbNextUnit | portb.asm |
| $2048 | 3 | portb.portbNextUnit | portb.asm |
| $204B | 2 | portb.portbNextUnit | portb.asm |
| $204D | 2 | portb.portbNextUnit | portb.asm |
| $204F | 2 | portb.portbNextUnit | portb.asm |
| $2051 | 2 | portb.portbNextUnit | portb.asm |
| $2053 | 1 | portb.portbNextUnit | portb.asm |
| $2054 | 2 | portb.portbCopy | portb.asm |
| $2056 | 2 | portb.portbCopy | portb.asm |
| $2058 | 3 | portb.portbCopy | portb.asm |
| $205B | 2 | portb.portbCopy | portb.asm |
| $205D | 3 | portb.portbCopy | portb.asm |
| $2060 | 2 | portb.portbCopy | portb.asm |
| $2062 | 2 | portb.portbCopy | portb.asm |
| $2064 | 2 | portb.portbCopy | portb.asm |
| $2066 | 2 | portb.portbCopy | portb.asm |
| $2068 | 2 | portb.portbCopy | portb.asm |
| $206A | 2 | portb.portbCopy | portb.asm |
| $206C | 1 | portb.portbCopy | portb.asm |
| $206D | 2 | portb.portbCopy | portb.asm |
| $206F | 2 | portb.portbCopy | portb.asm |
| $2071 | 2 | portb.portbCopy | portb.asm |
| $2073 | 2 | portb.portbCopy | portb.asm |
| $2075 | 2 | portb.portbCopy | portb.asm |
| $2077 | 2 | portb.portbCopy | portb.asm |
| $2079 | 2 | portb.portbCopy | portb.asm |
| $207B | 2 | portb.portbCopy | portb.asm |
| $207D | 2 | portb.portbCopy | portb.asm |
| $207F | 2 | portb.portbCopy | portb.asm |
| $2081 | 2 | portb.portbCopy | portb.asm |
| $2083 | 1 | portb.portbCopy | portb.asm |
| $2084 | 2 | portb.portbCopy | portb.asm |
| $2086 | 2 | portb.portbCopy | portb.asm |
| $2088 | 1 | portb.portbCopy | portb.asm |
| $2089 | 2 | portb.portbCopy | portb.asm |
| $208B | 2 | portb.portbCopy | portb.asm |
| $208D | 2 | portb.portbCopy | portb.asm |
| $208F | 2 | portb.portbCopy | portb.asm |
| $2091 | 2 | portb.portbCopy | portb.asm |
| $2093 | 2 | portb.portbCopy | portb.asm |
| $2095 | 3 | portb.portbCopy | portb.asm |
| $2098 | 1 | portb.portbCopy | portb.asm |
| $2099 | 1 | portb.portbCopy | portb.asm |
| $209A | 2 | portb.portbCopy | portb.asm |
| $209C | 2 | portb.portbCopy | portb.asm |
| $209E | 2 | portb.portbCopy | portb.asm |
| $20A0 | 2 | portb.portbCopy | portb.asm |
| $20A2 | 1 | portb.portbCopy | portb.asm |
| $20A3 | 1 | portb.portbCopy | portb.asm |
| $20A4 | 2 | portb.portbCopy | portb.asm |
| $20A6 | 2 | portb.portbCopy | portb.asm |
| $20A8 | 2 | portb.portbCopy | portb.asm |
| $20AA | 2 | portb.portbCopy | portb.asm |
| $20AC | 1 | portb.portbCopy | portb.asm |
| $20AD | 2 | portb.portbCopy | portb.asm |
| $20AF | 2 | portb.portbCopy | portb.asm |
| $20B1 | 2 | portb.portbCopy | portb.asm |
| $20B3 | 2 | portb.portbCopy | portb.asm |
| $20B5 | 2 | portb.portbCopy | portb.asm |
| $20B7 | 2 | portb.portbCopy | portb.asm |
| $20B9 | 2 | portb.portbCopy | portb.asm |
| $20BB | 2 | portb.portbCopy | portb.asm |
| $20BD | 2 | portb.portbCopy | portb.asm |
| $20BF | 3 | portb.portbCopy | portb.asm |
| $20C2 | 3 | portb.portbCopy | portb.asm |
| $20C5 | 1 | portb.portbCopy | portb.asm |
| $20C6 | 3 | print.printLine | print.asm |
| $20C9 | 3 | print.printLine | print.asm |
| $20CC | 3 | print.printLine | print.asm |
| $20CF | 2 | print.printLine | print.asm |
| $20D1 | 3 | print.printLine | print.asm |
| $20D4 | 2 | print.printLine | print.asm |
| $20D6 | 3 | print.printLine | print.asm |
| $20D9 | 2 | print.printLine | print.asm |
| $20DB | 3 | print.printLine | print.asm |
| $20DE | 1 | print.printLine | print.asm |
| $20DF | 2 | run.showScreen | run.asm |
| $20E1 | 2 | run.showScreen | run.asm |
| $20E3 | 2 | run.showScreen | run.asm |
| $20E5 | 1 | run.showScreen | run.asm |
| $20E6 | 2 | run.showScreen | run.asm |
| $20E8 | 1 | run.showScreen | run.asm |
| $20E9 | 2 | run.showScreen | run.asm |
| $20EB | 2 | run.showScreen | run.asm |
| $20ED | 3 | run.showScreen | run.asm |
| $20F0 | 3 | run.showScreen | run.asm |
| $20F3 | 1 | run.showScreen | run.asm |
| $20F4 | 6 | intro.introTitle | intro.asm |
| $20FA | 16 | intro.introText | intro.asm |
| $210A | 2 | intro.introDraw | intro.asm |
| $210C | 2 | intro.introDraw | intro.asm |
| $210E | 2 | intro.introDraw | intro.asm |
| $2110 | 3 | intro.introDraw | intro.asm |
| $2113 | 1 | intro.introDraw | intro.asm |
| $2114 | 3 | intro.introStart | intro.asm |
| $2117 | 9 | intro.introStart | intro.asm |
$2137–$2225 239 bytes at 294
| $2137 | 1 | nga.transition.ngaTransition | transition.asm |
| $2138 | 2 | nga.transition.ngaTransition | transition.asm |
| $213A | 1 | nga.transition.ngaTransition | transition.asm |
| $213B | 2 | nga.transition.ngaTransition | transition.asm |
| $213D | 2 | nga.transition.ngaTransition | transition.asm |
| $213F | 2 | nga.transition.ngaTransition | transition.asm |
| $2141 | 2 | nga.transition.ngaTransition | transition.asm |
| $2143 | 1 | nga.transition.ngaTransition | transition.asm |
| $2144 | 2 | nga.transition.ngaTransition | transition.asm |
| $2146 | 2 | nga.transition.ngaTransition | transition.asm |
| $2148 | 2 | nga.transition.ngaTransition | transition.asm |
| $214A | 1 | nga.transition.ngaTransition | transition.asm |
| $214B | 2 | nga.transition.ngaTransition | transition.asm |
| $214D | 2 | nga.transition.ngaTransition | transition.asm |
| $214F | 2 | nga.transition.ngaTransition | transition.asm |
| $2151 | 2 | nga.transition.ngaTransition | transition.asm |
| $2153 | 2 | nga.transition.ngaTransition | transition.asm |
| $2155 | 2 | nga.transition.ngaTransition | transition.asm |
| $2157 | 1 | nga.transition.ngaTransition | transition.asm |
| $2158 | 2 | nga.transition.ngaTransition | transition.asm |
| $215A | 2 | nga.transition.ngaTransition | transition.asm |
| $215C | 3 | nga.transition.ngaTransition | transition.asm |
| $215F | 2 | nga.transition.ngaTransition | transition.asm |
| $2161 | 2 | nga.transition.ngaTransition | transition.asm |
| $2163 | 1 | nga.transition.ngaTransition | transition.asm |
| $2164 | 2 | nga.transition.ngaTransition | transition.asm |
| $2166 | 2 | nga.transition.ngaTransition | transition.asm |
| $2168 | 2 | nga.transition.ngaTransition | transition.asm |
| $216A | 2 | nga.transition.ngaTransition | transition.asm |
| $216C | 2 | nga.transition.ngaTransition | transition.asm |
| $216E | 3 | nga.transition.ngaTransition | transition.asm |
| $2171 | 1 | nga.transition.ngaTransition | transition.asm |
| $2172 | 2 | nga.transition.ngaTransition | transition.asm |
| $2174 | 2 | nga.transition.ngaTransition | transition.asm |
| $2176 | 1 | nga.transition.ngaTransition | transition.asm |
| $2177 | 2 | nga.transition.ngaTransition | transition.asm |
| $2179 | 2 | nga.transition.ngaTransition | transition.asm |
| $217B | 1 | nga.transition.ngaTransition | transition.asm |
| $217C | 2 | nga.transition.ngaTransition | transition.asm |
| $217E | 2 | nga.transition.ngaTransition | transition.asm |
| $2180 | 3 | nga.transition.ngaEnter | transition.asm |
| $2183 | 3 | nga.transition.ngaEnter | transition.asm |
| $2186 | 2 | nga.transition.ngaEnter | transition.asm |
| $2188 | 3 | nga.transition.ngaEnter | transition.asm |
| $218B | 2 | nga.transition.ngaEnter | transition.asm |
| $218D | 3 | nga.transition.ngaEnter | transition.asm |
| $2190 | 2 | nga.transition.ngaEnter | transition.asm |
| $2192 | 2 | nga.transition.ngaEnter | transition.asm |
| $2194 | 3 | nga.transition.ngaEnter | transition.asm |
| $2197 | 2 | nga.transition.ngaEnter | transition.asm |
| $2199 | 2 | nga.transition.ngaEnter | transition.asm |
| $219B | 3 | nga.transition.ngaEnter | transition.asm |
| $219E | 3 | nga.transition.ngaEnter | transition.asm |
| $21A1 | 2 | nga.transition.ngaEnter | transition.asm |
| $21A3 | 3 | nga.transition.ngaEnter | transition.asm |
| $21A6 | 2 | nga.transition.ngaEnter | transition.asm |
| $21A8 | 3 | nga.transition.ngaEnter | transition.asm |
| $21AB | 2 | nga.transition.ngaEnter | transition.asm |
| $21AD | 3 | nga.transition.ngaEnter | transition.asm |
| $21B0 | 2 | nga.transition.ngaEnter | transition.asm |
| $21B2 | 3 | nga.transition.ngaEnter | transition.asm |
| $21B5 | 2 | nga.transition.ngaEnter | transition.asm |
| $21B7 | 3 | nga.transition.ngaEnter | transition.asm |
| $21BA | 1 | nga.transition.ngaEnter | transition.asm |
| $21BB | 2 | nga.transition.ngaEnter | transition.asm |
| $21BD | 3 | nga.transition.ngaEnter | transition.asm |
| $21C0 | 2 | nga.transition.ngaEnter | transition.asm |
| $21C2 | 2 | nga.transition.ngaEnter | transition.asm |
| $21C4 | 2 | nga.transition.ngaEnter | transition.asm |
| $21C6 | 3 | nga.transition.ngaEnter | transition.asm |
| $21C9 | 1 | nga.transition.ngaEnter | transition.asm |
| $21CA | 2 | nga.transition.ngaEnter | transition.asm |
| $21CC | 2 | nga.transition.ngaEnter | transition.asm |
| $21CE | 3 | nga.transition.ngaEnter | transition.asm |
| $21D1 | 2 | nga.transition.ngaEnter | transition.asm |
| $21D3 | 3 | nga.transition.ngaEnter | transition.asm |
| $21D6 | 3 | nga.transition.ngaEnter | transition.asm |
| $21D9 | 3 | nga.transition.ngaEnter | transition.asm |
| $21DC | 2 | nga.transition.ngaEnter | transition.asm |
| $21DE | 2 | nga.transition.ngaEnter | transition.asm |
| $21E0 | 2 | nga.transition.ngaEnter | transition.asm |
| $21E2 | 3 | nga.transition.ngaEnter | transition.asm |
| $21E5 | 2 | nga.transition.ngaEnter | transition.asm |
| $21E7 | 3 | nga.transition.ngaEnter | transition.asm |
| $21EA | 2 | nga.transition.ngaEnter | transition.asm |
| $21EC | 3 | nga.transition.ngaEnter | transition.asm |
| $21EF | 2 | nga.transition.ngaEnter | transition.asm |
| $21F1 | 3 | nga.transition.ngaEnter | transition.asm |
| $21F4 | 2 | nga.transition.ngaEnter | transition.asm |
| $21F6 | 2 | nga.transition.ngaEnter | transition.asm |
| $21F8 | 2 | nga.transition.ngaEnter | transition.asm |
| $21FA | 2 | nga.transition.ngaEnter | transition.asm |
| $21FC | 1 | nga.transition.ngaEnter | transition.asm |
| $21FD | 2 | nga.transition.ngaEnter | transition.asm |
| $21FF | 2 | nga.transition.ngaEnter | transition.asm |
| $2201 | 2 | nga.transition.ngaEnter | transition.asm |
| $2203 | 3 | nga.transition.ngaEnter | transition.asm |
| $2206 | 3 | nga.transition.ngaEnter | transition.asm |
| $2209 | 2 | nga.transition.ngaEnter | transition.asm |
| $220B | 3 | nga.transition.ngaEnter | transition.asm |
| $220E | 3 | nga.transition.ngaEnter | transition.asm |
| $2211 | 2 | nga.transition.ngaFrameOpen | transition.asm |
| $2213 | 2 | nga.transition.ngaFrameOpen | transition.asm |
| $2215 | 2 | nga.transition.ngaFrameOpen | transition.asm |
| $2217 | 3 | nga.transition.ngaFrameOpen | transition.asm |
| $221A | 1 | nga.transition.ngaFrameOpen | transition.asm |
| $221B | 1 | nga.transition.ngaFrameSkip | transition.asm |
| $221C | 2 | nga.transition.ngaFrameSkip | transition.asm |
| $221E | 2 | nga.transition.ngaFrameSkip | transition.asm |
| $2220 | 2 | nga.transition.ngaFrameSkip | transition.asm |
| $2222 | 2 | nga.transition.ngaFrameSkip | transition.asm |
| $2224 | 1 | nga.transition.ngaFrameSkip | transition.asm |
| $2225 | 1 | nga.cell.ngaCurrentPhase |
$008F–$0090 2 bytes at 537
| $008F | 2 | nga.slots.title | run.asm |
$2226–$2252 45 bytes at 543
| $2226 | 3 | nga.slots.draw | run.asm |
| $2229 | 3 | nga.transforms.ngaShowBases | transforms.asm |
| $222C | 1 | nga.transforms.ngaShowBases | transforms.asm |
| $222D | 14 | nga.transforms.ngaShowBases | transforms.asm |
| $223B | 3 | nga.transforms.ngaShowBases | transforms.asm |
| $223E | 1 | nga.transforms.ngaShowBases | transforms.asm |
| $223F | 3 | nga.transforms.ngaShowBases | transforms.asm |
| $2242 | 1 | nga.transforms.ngaShowBases | transforms.asm |
| $2243 | 10 | nga.transforms.ngaRestore | transforms.asm |
| $224D | 5 | nga.transforms.ngaRestore | transforms.asm |
| $2252 | 1 | nga.transforms.ngaRestore | transforms.asm |
$2254–$2262 15 bytes at 592
| $2254 | 3 | nga.transforms.ngaLoadMap | transforms.asm |
| $2257 | 3 | nga.transforms.ngaLoadMap | transforms.asm |
| $225A | 1 | nga.transforms.ngaLoadMap | transforms.asm |
| $225B | 2 | nga.transforms.ngaTransform | transforms.asm |
| $225D | 2 | nga.transforms.ngaTransform | transforms.asm |
| $225F | 3 | nga.transforms.ngaTransform | transforms.asm |
| $2262 | 1 | nga.transforms.ngaTransform | transforms.asm |
$2253–$2253 1 bytes at 611
| $2253 | 1 | nga.transforms.ngaLoadUnit | transforms.asm |
$02E2–$02E3 2 bytes at 616
| $02E2 | 2 | initad |
$4000–$4070 113 bytes at 622
| $4000 | 64 | shared.spare | shared.asm |
| $4040 | 49 | storage image |
$2253–$2253 1 bytes at 739
| $2253 | 1 | nga.transforms.ngaLoadUnit | transforms.asm |
$02E2–$02E3 2 bytes at 744
| $02E2 | 2 | initad |
$4000–$4171 370 bytes at 750
| $4000 | 64 | shared.spare | shared.asm |
| $4040 | 306 | storage image |
$02E2–$02E3 2 bytes at 1124
| $02E2 | 2 | initad |
$02E0–$02E1 2 bytes at 1130
| $02E0 | 2 | runad |