Diagnostics
Every finding the tool reports carries an identifier. It is NGA and four
digits, and it never changes meaning. This chapter lists all of them.
Read it when the tool said something you want to look up. Do not read it in order.
How to read a finding
error[NGA5205]: `level.map` is loaded from storage, and cannot live where the
stream reads through, at $4000
--> main.ngp:12:3
The identifier comes first. The message follows, with the names of the program written into it. The location points at the line that caused the finding, and a finding about the whole program has no location.
The number says which part of the tool raised it, so the number alone says where to look. The tables below are grouped that way.
A number is never reused. A diagnostic that is retired takes its number with it.
Severity
An error stops the build at the next gate. A warning does not stop anything. A note never stands alone and always explains the finding above it.
The severity in the tables is the default. A Project changes it in its
diagnostics block, and the command line
changes it with --deny, --allow and --off. The command line wins.
What the message shows here
The tables show the message as the tool holds it, with named arguments in
braces. A real finding has values there instead. So `{section}` is pinned at {address:hex} is printed as `hud` is pinned at $2000.
Below the tables, every finding has an entry: when the tool raises it, and what to do about it. Most entries show a small program that raises it, with what the tool printed for it. An example that shows no Project file is built with one that names its Modules and nothing else. An identifier in the tables links to its entry.
Index
The identifiers by the part of the tool that raises them.
Source lexing
| Code | Severity | Message |
|---|---|---|
NGA0001 |
error | unexpected character {character} |
NGA0002 |
error | unterminated string literal |
NGA0003 |
error | string literal is not closed before the end of the line |
NGA0004 |
error | unterminated character literal |
NGA0005 |
error | character literal is empty |
NGA0006 |
error | character literal holds more than one character |
NGA0007 |
error | unknown escape sequence \{escape} |
NGA0009 |
error | invalid UTF-8 encoding |
NGA0010 |
error | {prefix} is not followed by any digits |
NGA0011 |
error | {character} is not valid in a {base} literal |
NGA0012 |
error | _ in a numeric literal must stand between digits |
NGA0013 |
error | hexadecimal literals are written $1F, not 0x1F |
NGA0014 |
error | numeric local labels do not exist; use @, @+, @-, or a name |
NGA0015 |
error | control character {code:hex} in source |
NGA0016 |
error | this number is too large to be represented |
NGA0017 |
error | a leading zero does not make {literal} octal; write it in decimal, $ or % |
Source parsing
| Code | Severity | Message |
|---|---|---|
NGA0100 |
error | expected an expression |
NGA0101 |
error | expected ) to close this parenthesis |
NGA0102 |
error | << is a shift; the low byte of an operand is < |
NGA0103 |
error | {outer} and {inner} need parentheses to say which one binds first |
NGA0104 |
error | this expression nests more than {limit} deep |
NGA0110 |
error | {token} cannot begin a statement |
NGA0111 |
error | unexpected {token} after the end of the statement |
NGA0112 |
error | {name} at column one defines a label; indent it to write an instruction |
NGA0113 |
warning | {name} at column one defines a label named like an instruction |
NGA0114 |
error | a direction marks a reference, not a definition |
NGA0115 |
error | a local label has no scope outside a .proc |
NGA0116 |
error | .declare says what a byte of a proc is, and this stands outside one |
NGA0117 |
error | .declare says what the .ztemp or .temp below it is, and this is not one |
NGA0118 |
error | .declare says arg or ret, found {token} |
NGA0119 |
error | {name} is not a type or a place; a declared byte is u8, i8, u16, i16, bool or u8[N], or a place is a letter a byte from the low one: a, x or y, and m for memory beside one of them |
NGA0120 |
error | unknown directive .{name} |
NGA0121 |
error | .end does not say what it closes; write the block's own closer: .ends, .endp, .endm, .endif, .endmatch, .endns or .endch |
NGA0122 |
error | expected a name after {after} |
NGA0123 |
error | {name} is not a section attribute |
NGA0124 |
error | this .section is never closed |
NGA0125 |
error | this .proc is never closed |
NGA0126 |
error | {directive} without an open .section |
NGA0127 |
error | {directive} without an open .proc |
NGA0128 |
error | a .section cannot open inside another; close the first one |
NGA0129 |
error | a .proc cannot open inside another |
NGA0130 |
error | this .proc already declares its result, and a proc has one |
NGA0131 |
error | {name} gives a placement this {directive} already has |
NGA0132 |
error | {name} is already given for this placement |
NGA0133 |
error | {name} is already given for this {directive} |
NGA0134 |
error | a slot is pointer or vector, and this is {name} |
NGA0135 |
error | a slot's placement is zeropage or absolute, and this is {name} |
NGA0136 |
error | .ztemp and .temp declare a variable, and need at column one a plain name for it, not a local one |
NGA0137 |
error | a .proc is a section of its own and cannot open inside a .section |
NGA0138 |
error | {what} stands in no section; what has an address is written in a .section or a .proc |
NGA0139 |
error | this byte is already an argument, and a byte is one argument or none |
NGA0140 |
error | there is no (expression,{register}) addressing mode |
NGA0141 |
warning | these parentheses group rather than indirect; (expression,x) is the indirect form |
NGA0142 |
error | expected x or y after ,, found {token} |
NGA0143 |
error | {code} names no diagnostic |
NGA0144 |
warning | .off {code} silenced nothing: no such warning stood on the line below |
NGA0145 |
error | an export names a symbol of the scope it stands in; to export {name}, write .export {member} inside {scope} |
NGA0150 |
error | this .charset is never closed |
NGA0151 |
error | {directive} without an open .charset |
NGA0152 |
error | expected a character set entry, written "..." = value |
NGA0153 |
error | a character set entry maps at least one character |
NGA0154 |
error | the left side of an entry names no character set; the set is the one being declared |
NGA0155 |
error | .macro cannot open inside a .section, a .proc or another .macro |
NGA0156 |
error | this .macro is never closed |
NGA0157 |
error | {directive} without an open .macro |
NGA0158 |
error | {what} cannot stand in a macro body, which holds instructions and data |
NGA0160 |
error | .namespace cannot open inside a .section or a .macro |
NGA0161 |
error | this .namespace is never closed |
NGA0162 |
error | {directive} without an open .namespace |
NGA0163 |
error | {directive} closes a namespace while a .section, .proc or .macro is still open |
NGA0164 |
error | a .charset stands at the top level: a literal's prefix is one name |
NGA0165 |
error | expected : here, and the answer for a false condition after it |
NGA0166 |
error | this .if is never closed |
NGA0167 |
error | {directive} without an open .if |
NGA0168 |
error | .elsif cannot follow .else, which is the branch taken when none is |
NGA0169 |
error | {what} cannot stand in a conditional branch, which holds instructions and data |
NGA0170 |
error | a label in a conditional branch is written @name: a branch defines no symbol, and two branches want one name |
NGA0171 |
error | {name}... takes every argument left, so it stands last |
NGA0172 |
error | .match stands in a macro body, which is where a pack is |
NGA0173 |
error | .case without an open .match |
NGA0174 |
error | {directive} without an open .match |
NGA0175 |
error | this .match is never closed |
NGA0176 |
error | a .match holds .cases, and this stands before the first |
NGA0177 |
error | ... spreads a pack and follows its name, touching it |
NGA0178 |
error | this .match has no .case, so nothing could ever fit |
NGA0179 |
error | temporary does not go with {other} |
NGA0180 |
error | a .proc is code, and temporary is a reservation |
NGA0181 |
error | .source is followed by a quoted path, a comma and a line number, found {token} |
NGA0182 |
error | a source line is counted from 1, and this is {line} |
NGA0183 |
error | a .{encoding} payload is written as a quoted literal, found {token} |
NGA0184 |
error | {character} is not valid in a .{encoding} payload |
NGA0185 |
error | = pads the end of a .base64 payload and stands nowhere else |
NGA0186 |
error | a .{encoding} payload takes {group} characters to {bytes}, and this one has {count} |
NGA0187 |
error | a payload is bytes and not text, so it names no character set |
NGA0188 |
error | a .namespace in a .proc holds sections, temporaries and constants, and {what} is none of them |
NGA0189 |
error | this .declare reserves no byte, and a .ztemp or .temp stands below it |
NGA0190 |
error | {register} already carries an argument of this proc |
NGA0191 |
error | {place} names one register for two bytes |
NGA0192 |
error | readonly does not go with {other} |
NGA0193 |
warning | a .proc holds code, which nothing writes unless a statement says so, and readonly changes nothing |
NGA0194 |
error | foreign does not go with {other} |
NGA0195 |
error | foreign says another master reads the section, which reaches it by an address handed to the hardware, so the section is a root |
NGA0196 |
error | a .proc holds code the CPU runs, and foreign says the CPU does not reach the bytes |
NGA0197 |
error | {name} is not an attribute of a transition; fast is the one there is |
NGA0198 |
error | movable is gone: a section has one address in every phase it is in |
NGA0199 |
error | a label is a name at column one, and is written without : |
NGA0200 |
error | {name} is another proc's byte, and an argument is a byte of this one or a register |
Project file and run configuration
| Code | Severity | Message |
|---|---|---|
NGA1101 |
error | project refers to {module}, which names no module and no group |
NGA1102 |
error | {module} already names a module; each module is declared once, and as gives another one a name of its own |
NGA1103 |
error | {path} is not a project file, and a run is given nothing else |
NGA1104 |
note | a source file becomes a module where a project's modules block names it |
NGA1105 |
error | a constant is a name, = and a number, found {token} |
NGA1106 |
error | the value of {name} is set more than once |
NGA1107 |
note | {name} was already set here |
NGA1108 |
error | {name} names no container; the tool writes {known} |
NGA1109 |
error | the container is set more than once |
NGA1110 |
error | {name} is not a project block |
NGA1111 |
error | this {name} block is never closed |
NGA1112 |
error | expected a block or an include, found {token} |
NGA1113 |
error | expected { to open the body of {name} |
NGA1114 |
error | a module is a quoted path, optionally followed by as and a name |
NGA1115 |
error | expected a name after as |
NGA1116 |
error | a quoted string of a Project file is not translated, so it names no character set |
NGA1117 |
error | expected deny, allow or off, found {token} |
NGA1118 |
error | {code} names no diagnostic |
NGA1119 |
error | the severity of {code} is set more than once |
NGA1120 |
note | {code} was already set here |
NGA1121 |
error | this include reaches a file that is already being read |
NGA1122 |
error | cannot read {path} |
NGA1123 |
error | this project declares no modules |
NGA1125 |
error | phase is followed by the phase's name, found {token} |
NGA1126 |
error | expected needs, then, without, entry or final, found {token} |
NGA1127 |
error | expected a name after {after} |
NGA1128 |
error | a resident entry names a module or a group, found {token} |
NGA1129 |
error | expected , between {previous} and {next} |
NGA1130 |
error | project refers to phase {phase}, which is not declared |
NGA1131 |
error | the entry phase is set more than once |
NGA1132 |
note | the entry phase was already set here |
NGA1133 |
error | this project declares phases and no entry |
NGA1134 |
warning | module {module} is in no phase, so it is never in memory |
NGA1135 |
error | expected region, register, holder, units, window, containers or cpu, found {token} |
NGA1136 |
error | expected a value after {after} |
NGA1137 |
error | a value here is written out, and {name} names nothing |
NGA1138 |
error | this does not come to a number |
NGA1139 |
error | a range is written start .. end |
NGA1140 |
note | the container was already set here |
NGA1141 |
error | this machine does not take the container {name}; it takes {taken} |
NGA1142 |
note | the machine says what it takes here |
NGA1143 |
error | {name} is not what a program is optimised for; the words are {known} |
NGA1144 |
error | what the program is optimised for is set more than once |
NGA1145 |
note | it was already set here |
NGA1146 |
error | {name} names no processor; the words are {known} |
NGA1147 |
error | the entry of phase {phase} is set more than once |
NGA1148 |
note | it was set here |
NGA1149 |
error | the processor is set more than once |
NGA1150 |
error | transform is followed by the transform's name, found {token} |
NGA1151 |
error | a transform entry names a section as module.section, found {token} |
NGA1152 |
note | the processor was already set here |
NGA1155 |
error | a region's range is followed by ram, rom, register or reserved, not by {token} |
NGA1156 |
error | {word} is not a region property; write ram, rom, register or reserved |
NGA1157 |
error | a region runs from a lower address to a higher one inside the address space, and this one does not |
NGA1158 |
error | a region named {name} is already declared |
NGA1159 |
note | {name} was declared here |
NGA1160 |
error | a register lies inside the address space, and its last byte would be at {value:hex} |
NGA1161 |
error | a register is one or two bytes, and {width} is neither |
NGA1163 |
note | the {kind} {region} is declared here |
NGA1164 |
error | expected units or size, found {token} |
NGA1165 |
error | storage has units by count and no size, and a unit holds something |
NGA1166 |
error | the size of a unit is set more than once |
NGA1167 |
note | it was set here |
NGA1168 |
error | the units are declared more than once; units names a set of the target or counts them |
NGA1169 |
note | they were declared here |
NGA1170 |
error | {count} units, and a unit is named in two bytes |
NGA1171 |
error | a unit holds between one byte and the address space, and {value:hex} is neither |
NGA1172 |
error | {name} names a group and a module, and a name in a list has to mean one thing |
NGA1173 |
note | the module {name} is declared here |
NGA1174 |
error | group {group} reaches itself here, so listing it would never end |
NGA1175 |
warning | group {group} holds no module, so naming it adds nothing |
NGA1176 |
error | {name} is a group, and one module is expected here |
NGA1177 |
error | a group entry names a module or a group, found {token} |
NGA1178 |
error | group is followed by the group's name, found {token} |
NGA1179 |
error | a window lists what it shows after views, found {token} |
NGA1180 |
error | {name} already names a {kind} of the target |
NGA1181 |
note | it was declared here |
NGA1182 |
error | a window's range runs from a lower address to a higher one inside the address space, and this one does not |
NGA1183 |
error | {state} is listed more than once among what {window} shows |
NGA1185 |
error | {name} is not a unit set of the target |
NGA1186 |
error | no window shows {name}, so what one of its units holds is unknown |
NGA1187 |
error | windows {window} and {other} both show {name} and differ in size, so a unit has no one size |
NGA1188 |
error | storage names a unit set, and what a unit holds is its window's size |
NGA1189 |
error | a unit set holds at least one unit |
NGA1190 |
error | panes is followed by in and a window, found {token} |
NGA1191 |
error | {name} is not a window of the target |
NGA1192 |
error | {state} is not a named state of window {window} |
NGA1193 |
error | a family holds between 1 and 255 panes, and {count} is neither |
NGA1194 |
error | window {window} shows no unit set, so a pane in it is pinned to a named state: write = STATE |
NGA1195 |
error | a family takes consecutive banks, and {pane} is pinned to one state |
NGA1196 |
error | expected a pane's name, found {token} |
NGA1197 |
error | phase {phase} is final, and then leads out of it |
NGA1198 |
error | load describes how a .xex loads, and this project's container is {container} |
NGA1199 |
error | expected needs or init, found {token} |
NGA1203 |
error | {name} is no generator; the generators are binary and script |
NGA1204 |
error | {name} is no argument of this generator |
NGA1205 |
error | this argument is given more than once |
NGA1206 |
error | {name} takes {wanted}, and this is {given} |
NGA1207 |
error | {generator} is given the file it works from as a quoted path with no name before it |
NGA1208 |
error | what {generator} produced cannot be emitted: {where} |
NGA1209 |
error | a generator's arguments are closed by ), found {token} |
NGA1210 |
error | {path} failed: {message} |
NGA1211 |
error | {path} did not finish within the work a generator is given |
NGA1212 |
error | {module}: {message} |
NGA1213 |
warning | {module}: {message} |
NGA1214 |
note | the generator said so at {where} |
NGA1215 |
error | {name} names no set of facts; the sets are {sets} |
NGA1216 |
error | the container {name} takes no board; only car, lnx and lyx name one |
NGA1217 |
error | a .{name} is an image of one board and this says none; write container {name} "{example}", and the boards are {known} |
NGA1218 |
error | {name} names no cartridge board; the boards are {known} |
NGA1219 |
error | the board {name} is ROM at {range} and this machine has {found} |
NGA1220 |
error | the board {name} switches banks into {range} and this machine declares no window of that one range |
NGA1221 |
error | the board {name} has {units:n} banks of storage and window {window} shows a set of {found:n} |
NGA1229 |
error | the board {name} has no banks for storage to stand in, and this machine declares storage |
NGA1230 |
error | a cartridge's entry is a field and a value, and {token} is neither |
NGA1231 |
error | {field} is not something a cartridge's header holds; it holds name, manufacturer and rotation |
NGA1232 |
error | {field} takes a value of the kind its header field is: name and manufacturer a quoted string, rotation a word |
NGA1233 |
error | {field} holds {available:n} bytes and {given:n} were given; a reader writes a terminator over the last, so one more would be a name nobody chose |
NGA1234 |
error | {field} is given twice |
NGA1235 |
error | {name} is no rotation; a cartridge is held none, left or right |
NGA1236 |
error | a cartridge block says what a header shows, and the container {name} carries no header to show it in |
NGA1237 |
error | a {name} cartridge is 255 pages of {expected:n} bytes, page zero being the bootstrap's, and this machine's storage is {count:n} units of {size:n} |
NGA1238 |
error | a {name} is {tracks:n} tracks of at most {expected:n} bytes, the unit's number being the track's, and this machine's storage is {count:n} units of {size:n} |
NGA1239 |
error | {name} is not something to do with an edge's descriptors; held is the one word there is |
NGA1240 |
error | frames is said once, and was said already |
NGA1241 |
note | the earlier one is here |
NGA1242 |
error | base is gone: no window has one, and what a window shows outside a .with is undefined |
NGA1243 |
error | frames held asks an edge to hold its descriptors, and with no storage an edge has none |
NGA1244 |
error | {name} is {count:n} banks of {size:n} bytes from {begin:hex}, which reach past the end of its linear range at {last:hex} |
NGA1245 |
error | a unit set's linear range runs from a lower address to a higher one, and this one does not |
NGA1246 |
error | cannot read {file}, which --overlay gives for {path} |
NGA1247 |
error | -o is refused beside --overlay: a binary built from text on no disk answers to no saved source |
NGA1248 |
error | {after} is followed by {what} in quotes, found {token} |
NGA1249 |
error | the container {name} is not compressed while it loads; only a .xex's loader runs code between what it writes |
NGA1250 |
error | {name} is no format a .xex is compressed in; the formats are {known} |
NGA1251 |
error | an except entry names a module or a group, found {token} |
NGA1252 |
error | choose names {count:n} documents, and there is nothing to choose between fewer than two |
NGA1253 |
error | choose is written more than once |
NGA1254 |
note | the first choose is here |
NGA1255 |
error | {document} is a choice and declares {what}; a choice declares only registers in target and constants |
NGA1256 |
error | {name} is declared by {document} and not by {other}; every choice declares the same names |
NGA1257 |
error | choose changes a .xex without storage while it loads, and this program {what} |
NGA1258 |
error | {name} stands at {address:hex} under {document}, where the first choice lets a section stand |
Symbols, Merge, duplicates and Slots
| Code | Severity | Message |
|---|---|---|
NGA2202 |
note | previous definition of {symbol} is here |
NGA2203 |
error | {symbol} is already defined in this module |
NGA2204 |
error | {symbol} is exported but not defined in this module |
NGA2205 |
error | {symbol} is exported by more than one module |
NGA2206 |
error | {symbol} is not defined |
NGA2207 |
error | {symbol} is defined in terms of itself |
NGA2208 |
error | {mnemonic} on the accumulator is written {mnemonic}, without a |
NGA2210 |
error | no definition of @{name} matches this reference |
NGA2211 |
error | @{name} has more than one definition here; write @+{name} or @-{name} |
NGA2212 |
error | an anonymous local label is reached with @+ or @- |
NGA2213 |
error | {name} is already a label of this macro body |
NGA2214 |
error | {name} is a parameter of this macro, and a label cannot take its name |
NGA2215 |
error | no definition of @{name} outside this branch matches, and one in another branch may not be there at all |
NGA2220 |
error | expected an integer here, and this is {type} |
NGA2221 |
error | two addresses cannot be added; a - b is the distance between them |
NGA2222 |
error | an address cannot be subtracted from a number |
NGA2223 |
error | these addresses are not in one section, so this is a property of the layout rather than of the program |
NGA2224 |
error | only a label reaches the attributes of its section, and this is {type} |
NGA2225 |
error | .{directive} takes {allowed}, and this is {type} |
NGA2226 |
error | an operand is an address, a number or a pane, and this is {type} |
NGA2227 |
error | {name} is not an attribute of a section |
NGA2228 |
error | a conditional chooses between two of one type, and these are {type} and {other} |
NGA2229 |
error | a conditional between addresses of two sections has no section of its own, and subtraction and width need one |
NGA2230 |
error | {symbol} is not a character set |
NGA2231 |
error | {charset} does not map {character} |
NGA2232 |
error | character set {charset} is derived from itself |
NGA2233 |
error | {character} is already mapped earlier in this .charset block |
NGA2234 |
error | a character set maps to bytes, and this run covers {start} to {end} |
NGA2235 |
error | a character set is resolved before any size or address exists, so this needs a value written in the source |
NGA2236 |
error | {symbol} is a character set, and a character set has no value |
NGA2237 |
error | {character} is not ASCII and this literal names no character set |
NGA2240 |
error | {phase} is not a phase of this project |
NGA2241 |
error | this transition to {to} stands in code present in phase {from}, which has no then {to} |
NGA2242 |
error | the target numbers phases in a byte, and this project has {count:n} |
NGA2243 |
error | the transition from {from} to {to} loads {count:n} sections, and a frame counts them in a byte |
NGA2244 |
error | {transform} is not a format the tool can encode |
NGA2245 |
error | module {module} has no label named {section}, and a section is named by one |
NGA2246 |
warning | phase {from} declares then {to}, and no .transition {to} is present in it, so the edge is taken by nothing |
NGA2247 |
warning | {module}.{section} is never loaded by a transition, so nothing transforms it |
NGA2248 |
error | {section} names the section {previous} already lists, and a section is transformed once |
NGA2249 |
error | {module}.{section} is named in transform, and without storage only a .xex decodes anything, while it loads |
NGA2250 |
error | {symbol} is not a slot |
NGA2251 |
error | {symbol} is not a label or a section of this module |
NGA2252 |
error | {slot} has two implementations live in phase {phase}: {symbol} and {other} |
NGA2253 |
note | {symbol} implements it here |
NGA2254 |
error | a frame counts cell writes in a byte, so a program has at most 255 slots, and this one has {count:n} |
NGA2255 |
error | {symbol} fills slot {slot} from pane {pane}, and the cell holds an address but not the state that shows it |
NGA2260 |
error | {name} is not a proc of this module, and then names one |
NGA2261 |
error | {name} already follows {previous}, and can follow only one proc |
NGA2262 |
error | {name} follows {previous}, and cannot also be pinned or aligned |
NGA2264 |
error | {name} follows itself through then |
NGA2265 |
error | {name} follows {previous}, so both are in one pane or neither is |
NGA2266 |
error | {type} is a {want}-byte type, and this reserves {got} |
NGA2270 |
error | a proc holds code, and a reservation is not code; a variable is a .ztemp or lives in a .section |
NGA2271 |
error | a temporary section holds reservations only, and this is not one |
NGA2272 |
error | {symbol} names a {kind} the project declares, and a module cannot define it |
NGA2273 |
error | this section holds no label, and a section is named by one |
NGA2274 |
error | {label} is not defined in this module, and a decoder is one of its labels |
NGA2275 |
error | {label} is a {kind}, and a decoder is entered at a label |
NGA2276 |
error | {format} is not a format the tool can encode, so nothing produces what this decodes |
NGA2277 |
error | {format} already has a decoder, and a format has one |
NGA2278 |
note | the decoder of {format} is declared here |
NGA2279 |
error | no module declares a decoder for copy, and every Transition copies; the storage driver declares one with .transform copy |
NGA2280 |
error | no module declares a decoder for {transform} |
NGA2281 |
error | a .transition is taken and no module declares the storage driver; one module declares it with .driver, and a machine variant usually lists that module |
NGA2282 |
error | this module declares the storage driver, and {module} already does |
NGA2283 |
note | the driver is declared here |
NGA2284 |
error | {role} is not a role of the driver; the roles are open, read, unit, offset, init, finalize, stream, show, showAt, seek, span, rom, select, mask and unmask |
NGA2285 |
error | the driver declares no {role}, and the routine calls it |
NGA2286 |
error | {label} is not defined in this module, and a role names a macro or a label of the driver's own module |
NGA2287 |
error | as {name} {reason} |
NGA2288 |
error | {proc} is as {type}, so its arguments are {type}'s temporaries, and it declares {what} of its own |
NGA2289 |
error | the driver is present in some phases only, and every Transition calls it |
NGA2290 |
error | this decoder's module is present in some phases only, and any Transition may call it |
NGA2291 |
error | {role} is declared more than once |
NGA2292 |
error | {module}.{section} stands in {pane} and is named in transform, and what stands in a pane or a unit set is written as it is, with no decoder to run on it |
NGA2293 |
error | {role} takes {count} {names}, and is given {given} |
NGA2294 |
error | {window} is not a window of the target |
NGA2295 |
error | the driver declares no {role} for window {window}, and the target declares the window |
NGA2296 |
error | storage is the units of {name}, and the driver names no stream to read them through |
NGA2297 |
error | the stream reads through {window}, which does not show the units storage is |
NGA2298 |
error | nga.{role} names a window first, and this does not |
NGA2299 |
error | {symbol} names a window of the target, and a window is not a value |
NGA2300 |
error | {name} is an instruction, and a macro cannot take its name |
NGA2301 |
error | parameter {name} is given twice |
NGA2302 |
error | parameter {name} has the name of a symbol this module defines |
NGA2303 |
error | {name} is neither an instruction nor a macro in scope |
NGA2304 |
error | {name} is an instruction and takes one operand; an index register is x or y |
NGA2305 |
error | a macro's argument is an expression: no #, no ,x or ,y, and no parenthesis that indirects |
NGA2306 |
error | {name} takes {expected} {arguments} and was given {given} |
NGA2308 |
error | {symbol} is a macro and stands where a value is expected |
NGA2309 |
error | {label} is a {kind}, and a role is a macro the tool expands where it uses the role |
NGA2310 |
error | nga is the tool's namespace, and no module defines it |
NGA2311 |
error | {space} is not a namespace |
NGA2312 |
error | nga.{name} names nothing the tool defines |
NGA2313 |
error | nga.{name} is used, and the program has no driver: no module declares one, or the one declared was refused |
NGA2314 |
error | {symbol} is a name the tool defines, and a module may not define it |
NGA2315 |
note | the tool defines {symbol} here |
NGA2316 |
error | {name} is a namespace and stands where a value is expected |
NGA2317 |
error | {symbol} is also a namespace, and one name cannot be both |
NGA2319 |
error | {name} is an attribute of a section, and a name in a proc cannot take it |
NGA2321 |
error | a condition decides how many bytes there are, so it is a declared value: nothing naming a position or a size may stand in it |
NGA2322 |
error | this expansion is {depth} uses deep at {name} and shows no sign of ending |
NGA2323 |
note | the expansion began at this use |
NGA2324 |
error | {name} is a {kind}, and stands where an instruction or a macro is expected |
NGA2325 |
error | {name} is not a pack, and only a pack spreads |
NGA2326 |
error | {name} is not a pack, and .match counts a pack's elements |
NGA2327 |
error | {name} is already bound around this .case, and a case hides nothing |
NGA2328 |
error | {name} was given {count} elements, and no .case of .match {name} fits that |
NGA2329 |
note | the .match is here |
NGA2330 |
warning | a .case above this one fits everything this one does, so it is never taken |
NGA2331 |
error | {name} takes at least {expected} {arguments} and was given {given} |
NGA2332 |
error | this expansion has produced {count:n} statements, more than the target has bytes to put them in |
NGA2333 |
error | with its arguments in place this expression nests {depth} deep, more than {limit} |
NGA2334 |
error | {place} keeps {want} in memory, and the .ztemp or .temp below reserves {got} |
NGA2335 |
error | {word} is not something a medium does about an offset; forward is the one word there is |
NGA2412 |
error | {symbol} is in pane {pane}, and this code does not run with that pane shown: put the statement under a .with, or the code in a Proc declared under it |
NGA2414 |
error | reference to {symbol}, which is not in memory in phase {phase} while {section} is |
NGA2415 |
error | reference to {slot}, which has no implementation in phase {phase} while {section} is |
NGA2416 |
error | this reaches inside proc {proc} where only a read may: a proc is entered at its start, and written only in the operand of an instruction that does not jump, or in an opcode its .alt gives alternatives for |
NGA2417 |
error | a branch to {symbol} in {section}: a branch reaches its own proc or one chained to it by then; use jmp |
NGA2418 |
error | {name} is neither a pane, a region nor a unit set the Project declares |
NGA2420 |
error | {section} is in pane {pane}, and a window covers no zero page |
NGA2421 |
error | a pane's value is the state the solver chose, and this is arithmetic on it; a pane stands as an immediate, a data item or a role's argument |
NGA2422 |
error | {name} has {count} members, and {index} is not one of them |
NGA2423 |
error | a pane is a state of a window and not an address, and this operand is one |
NGA2424 |
error | a dispatch to {symbol}, which is not a position of {section}: a dispatch goes where it stands, and .own is how a table reaches other sections |
NGA2425 |
error | a dispatch of {count} targets, and an index reaches {most} |
NGA2426 |
error | {word} is not something an image does across a unit; none is the one word there is |
NGA2427 |
error | {label} is a {kind}, and {role} names the label of a reservation the stream stands in |
NGA2428 |
error | {role} names {got}, and the stream's {role} is {want} |
NGA2429 |
error | {place} is not where showAt takes a state: x is one byte in X, and xy two, the high one in Y |
NGA2430 |
error | window {window} has {count:n} states, and the driver's showAt for it takes one byte; with xy it takes two |
NGA2431 |
error | the driver's showAt for window {window} takes the state in {want}, and this gives it in {given} |
NGA2433 |
error | the driver declares {count:n} ROMs, and the set select is handed is a byte |
NGA2434 |
error | {module} is not a ROM the driver switches out, and a phase does without only what one is |
NGA2435 |
error | phase {phase} is without {module}, and {needed}, which it needs, shows it |
NGA2436 |
error | the entry phase of a .xex is loaded by a DOS with every ROM in, and it is without {module} |
NGA2437 |
error | .alt applies to the instruction on the line below, and this is not one |
NGA2438 |
error | {mnemonic} reaches memory through its operand, and only an instruction that reaches none has alternatives |
NGA2439 |
error | {alternative} has no form that takes the operand {mnemonic} is written with, at its length |
NGA2440 |
error | this writes {value:hex} into the opcode of {mnemonic}, which is neither it nor any alternative its .alt declares |
NGA2441 |
error | nga.{name} is used, and the driver switches ROMs and has no stream to {name} |
NGA2442 |
error | {name} is a region of registers or reserved memory, and a section stands only in one of RAM or ROM |
NGA2443 |
error | {name} is a pane, and a section in a pane names no other place with in |
NGA2444 |
error | {section} is in no pane, and only a section a pane holds has a linear address |
NGA2445 |
error | {section} is in pane {pane}, pinned to a named state, and only a bank of a unit set has a linear address |
NGA2446 |
error | {section} is in pane {pane}, and {units}, whose banks it stands in, declares no linear range |
NGA2447 |
error | {section} is in the family {pane}, whose every member holds it: its address in the first is linearFamilyAddress |
NGA2448 |
error | {section} is in {pane}, which is no family: its address is linearSectionAddress |
NGA2449 |
error | a linear address is the medium's and not the CPU's: take its bytes with <, > and >> |
NGA2450 |
error | {name} declares no linear range, and a section stands in a unit set only at a linear address |
NGA2451 |
error | {name} is a unit set, and a section in one names no other place with in |
NGA2452 |
error | {section} is {what}, and a unit set holds only what the medium reads |
NGA2453 |
error | {section} stands in {units}, where its address is linear, and it has no runtime one |
NGA2454 |
error | this divides by zero |
NGA2455 |
error | this comes to a number past what 64 bits hold |
NGA2456 |
error | {name} {what}; a result declared elsewhere names the reservation another proc returns in |
Context, Requirements and interrupt handlers
| Code | Severity | Message |
|---|---|---|
NGA3001 |
error | .with applies to the instruction or macro use on the line below, and this is not one |
NGA3002 |
error | {name} is a {kind}, and .with takes a pane, a family with , x, a window with , x or a window = STATE |
NGA3003 |
error | {state} is not a named state of window {window} |
NGA3005 |
warning | {window} shows this state already, so this .with changes nothing |
NGA3006 |
error | {window} is shown by a .with on this statement already, and a window shows one state at a time |
NGA3007 |
error | a statement under .with may not {mnemonic}: it would leave the window as shown |
NGA3008 |
error | what this statement reaches names {symbol}, in pane {pane}, which this .with does not show |
NGA3009 |
note | {symbol} is named here |
NGA3011 |
error | {symbol} is in state {state} of window {window}, and nothing shows that state here |
NGA3012 |
error | {directive} applies to the instruction or data on the line below, and this is not one |
NGA3013 |
error | .own and .root on one statement: an address is followed by this section or by the hardware, not both |
NGA3014 |
error | .root hands the address to the one holder that takes it, and this names {count} |
NGA3015 |
error | this section is in pane {pane} of window {window}, and code in a pane cannot switch its own window: the switch would take the code with it; a proc in fixed, .proc NAME, under {pane}, does it |
NGA3016 |
error | under {name} {reason} |
NGA3017 |
error | {symbol} runs under pane {pane}, which must be shown where it is called, and here it is not |
Prune and Trace
| Code | Severity | Message |
|---|---|---|
NGA4501 |
warning | phase {phase} is not reachable from the entry phase |
NGA4505 |
warning | {section} is pinned at {address:hex} and nothing reaches it, so it is dropped; mark it root if the hardware reads it |
NGA4601 |
error | the address of {section} is taken, and a temporary has none to give: its bytes are another's while it is not active |
NGA4602 |
error | {section} is temporary while {owner} runs, and {owner} can be entered again before it returns |
NGA4603 |
warning | nothing this statement names is code or a temporary, so .own changes nothing |
NGA4606 |
error | the address of {section} is taken and nothing says who follows it: .own if this section does, .own NAME if another does, .root HOLDER if the hardware does |
NGA4607 |
error | {section} jumps through a pointer and owns no address of code, so nothing says where the jump goes |
NGA4608 |
warning | nothing this statement names is a section, so .root marks nothing |
NGA4609 |
error | {name} is not a section, a proc or a label, and .own names who follows the address |
NGA4611 |
error | {section} is handed to {follower}, which is present in phase {phase} where {section} is not: a jump from there would land in nothing |
NGA4612 |
warning | control runs off the end of {section} into whatever is placed after it: end it with a jump or a return, or chain a proc to it with then |
NGA4613 |
error | phase {phase} is final, and {entry}, where it is entered, may return: nothing is kept there for a return to land on |
NGA4614 |
error | {name} is no holder: a target declares the hardware that holds a section with holder |
Size and Place
| Code | Severity | Message |
|---|---|---|
NGA5102 |
error | {mnemonic} has no {mode} form |
NGA5103 |
error | the placement class of this operand cannot be determined, so its width cannot be either |
NGA5104 |
error | this size depends on itself |
NGA5105 |
error | a reservation of {size:n} bytes is not a reservation |
NGA5106 |
error | {value:hex} is not an address |
NGA5107 |
error | {mnemonic} is a {needs} instruction, and this target is a {cpu} |
NGA5201 |
error | {section} overlaps {other} at {address:hex} |
NGA5202 |
error | there is no room for {section}, which needs {size:n} bytes |
NGA5203 |
error | a pin is a declared address, and {text} is {what} |
NGA5204 |
error | {section} is zero page and does not fit below $100 |
NGA5205 |
error | {section} is loaded from storage, and cannot live where the stream reads through, at {address:hex} |
NGA5206 |
error | no layout satisfies every constraint at once |
NGA5207 |
error | {section} and {other} cannot be kept apart: no layout holds both without one lying over the other |
NGA5208 |
note | {section} is declared here |
NGA5209 |
warning | the search stopped before it could show that fewer pairs would do; the ones named suffice |
NGA5210 |
error | this assertion does not hold |
NGA5211 |
error | this assertion cannot be decided |
NGA5212 |
error | an alignment is a declared power of two from 1 to 65,536, and {text} is {what} |
NGA5213 |
error | a boundary is a declared count of bytes from 1 to 65,536, and {text} is {what} |
NGA5214 |
error | {section} is {size:n} bytes, and cannot lie within a boundary of {boundary:n} |
NGA5215 |
error | {section} is pinned at {address:hex}, which is not aligned to {alignment:n} |
NGA5216 |
error | {section} is pinned at {address:hex}, and reaches {last:hex} across a boundary of {boundary:n} |
NGA5217 |
error | {section} is pinned at {address:hex}, in the register region {region}, where nothing can be placed |
NGA5218 |
warning | {section} is pinned at {address:hex}, in the reserved region {region} |
NGA5219 |
error | the search found no layout within its budget, and no sum shows that none exists |
NGA5220 |
note | phase {phase} has the least room left in {pool}: {free:n} of {available:n} bytes |
NGA5222 |
error | there is no storage for {section}, which needs {size:n} bytes |
NGA5224 |
warning | {section} is root and holds no bytes to restore, and is evicted in phase {gap} {between} |
NGA5225 |
error | pane {pane} takes {size:n} bytes in phase {phase}, and a bank of {set} holds {available:n} |
NGA5226 |
error | {section} is pinned at {address:hex}, outside the window of pane {pane} |
NGA5227 |
error | {section} has bytes and is in pane {pane}, which is pinned to a named state: only a .xex fills one, and only in the window its driver's stream reads through |
NGA5229 |
error | family {pane} needs {count} banks in a row, and {set} has {banks} |
NGA5230 |
error | {section} says readonly and this writes it |
NGA5231 |
note | readonly is declared here |
NGA5232 |
warning | {section} reserves space and emits no bytes, so readonly says nothing about it |
NGA5233 |
error | {section} is pinned at {address:hex} in {region}, which is ROM, and it is not read-only: it is written, holds no bytes, or has its address taken without readonly |
NGA5234 |
error | the sections nothing writes come to {required:n} bytes and this machine has {available:n} of ROM |
NGA5235 |
error | {section} is pinned at {address:hex}, inside window {window}, where only a pane or storage stands |
NGA5250 |
error | the layout gives {section} an address, and nothing reaches it |
NGA5251 |
error | the layout ends {section} at {address:hex} in phase {phase}, and {next}, which follows it, starts at {other:hex} |
NGA5253 |
error | {section} holds bytes and reaches {last:hex}, where {region} stands: what a foreign section holds is written by the CPU like every other byte, and the CPU does not reach there |
NGA5254 |
error | this reaches {address:hex} of {section}, where {region} stands, and the CPU does not reach there |
NGA5255 |
error | {section} comes to {size:n} bytes, and nothing in this storage may run from one unit into the next, the widest of which holds {available:n} |
NGA5256 |
error | the layout puts {section} at {address:hex}, inside window {window}, and it is in no pane |
NGA5258 |
warning | {section} is written as it is: as {format} it comes to {form:n} bytes, and it is {size:n} |
NGA5259 |
warning | {section} is written as it is: decoding it in place needs {margin:n} bytes past its end, and {address:hex} is not memory the loader may write |
NGA5260 |
error | there is no room while the program loads for {section}, which runs while it loads and needs {size:n} bytes |
NGA5261 |
error | {section} is named in transform, and the cold start runs it before anything is decoded |
NGA5262 |
error | there is no memory free while the program loads to put what hides under a ROM before it is moved there |
NGA5263 |
warning | {section} hides under a ROM and is moved there as it is: as {format} it comes to {form:n} bytes, and {room:n} are free while the program loads |
NGA5264 |
error | {section} is pinned at {address:hex}, outside the region its in names |
NGA5265 |
error | {section} runs while the file loads, and {module} is needed by phase {phase} too: what the load runs is done with before any phase |
NGA5266 |
warning | {section} is pinned at {address:hex}, which {holder} holds while the file loads, and its bytes are written then |
NGA5267 |
error | the layout puts {section} at {address:hex}, which {holder} holds while the file loads, and its bytes are written then |
NGA5268 |
error | init {name} names {what}: it names a label of a module the load needs |
NGA5269 |
error | {section} is pinned at {address:hex}, and the banks of {units} lie from {begin:hex} to {last:hex} |
NGA5270 |
error | in phase {phase} the sections in {units} come to {size:n} bytes, and its banks hold {holds:n} |
NGA5271 |
error | {section} has bytes in {units}, and no Container fills that set while the program loads, so it holds only sections that reserve |
NGA5272 |
error | {section} has bytes and is in pane {pane}, whose banks are units of {units}, and no Container fills that set while the program loads |
NGA5273 |
error | nothing the file leaves alone while it loads holds the {size:n} bytes that change it for a choice |
NGA5631 |
error | phase {phase} does not fit in view {view}: requires {required:n} bytes, {available:n} available |
NGA5632 |
error | phase {phase} needs {required:n} bytes of zero page, and {available:n} are available |
NGA5633 |
note | {section} accounts for {size:n} bytes |
NGA5634 |
note | {section} accounts for {size:n} bytes, kept here because phase {needer} needs it and with no storage nothing could bring it back |
Layout verification
| Code | Severity | Message |
|---|---|---|
NGA5240 |
error | the layout has {section} and {other} sharing {address:hex}, and phase {phase} holds both |
NGA5241 |
error | the layout puts {section} at {address:hex}, and it is pinned at {pinned:hex} |
NGA5242 |
error | the layout puts zero page {section} at {address:hex}, and it reaches {last:hex} |
NGA5243 |
error | the layout puts {section} at {address:hex}..{last:hex}, reaching into the window it waits behind |
NGA5244 |
error | the layout puts {section} at {address:hex}..{last:hex}, outside the pool it was allocated from |
NGA5245 |
error | the layout gives {section} no address |
NGA5246 |
error | the layout puts {section} at {address:hex}, and it reaches past the end of memory |
NGA5247 |
error | the layout puts {section} at {address:hex}, which is not aligned to {alignment:n} |
NGA5248 |
error | the layout puts {section} at {address:hex}..{last:hex}, across a boundary of {boundary:n} |
Patch, Emit, compression and the Container
| Code | Severity | Message |
|---|---|---|
NGA6101 |
error | {value} does not fit in {room} written here |
NGA6102 |
error | {mnemonic} reaches -128 to 127 and this is {distance:n} bytes away; write {jcc}, which is five bytes where two do not reach |
NGA6201 |
error | {section} and {other} share {address:hex}, and a raw image cannot hold both |
NGA6204 |
error | the .xex fills storage through the driver's showAt, and no module declares a driver |
NGA6205 |
error | the .xex fills a unit by writing into the window the stream reads through, and this driver names none |
NGA6207 |
error | the driver declares init, and the container {container} has nowhere to call it: the .xex is the one Container that reaches the driver before the entry |
NGA6208 |
error | the .xex calls the driver's init before it fills a unit, and ngaInit has no address to call |
NGA6211 |
error | phase {phase} has no entry: no label {name} is defined in the modules it needs |
NGA6212 |
error | {name} is defined in more than one module that phase {phase} needs, so it does not say where the phase starts |
NGA6213 |
error | {name} is a {kind}, and an entry is a label |
NGA6214 |
error | the .xex fills a unit through one range, and window {name} has {count} |
NGA6221 |
error | an .atr reads storage a sector at a time and shows no Window, and this storage is the unit set {name} |
NGA6222 |
error | a unit of storage on a diskette is the {size:n} bytes 256 sectors of {sector:n} hold, and {unit:n} is not that |
NGA6223 |
error | the boot record of an .atr shows no Window, and this driver streams through {name} |
NGA6224 |
error | a sector is numbered in two bytes, so an image holds {available:n} of them, and this program needs {required:n} |
NGA6225 |
error | {section} stands at {address:hex}, inside the boot record the .atr loads over {begin:hex} to {end:hex}, which is still loading the program when those bytes are written |
NGA6226 |
error | an .atr is booted by its first sectors, and none were made |
NGA6227 |
error | the boot record holds {available:n} bytes and its loader came to {required:n} |
NGA6231 |
error | storage comes to {required:n} bytes and a {name} cartridge holds {available:n} |
NGA6232 |
error | {section} holds bytes at {address:hex}, and the board {name} is ROM at {range} and nothing else, so nothing would ever put them there |
NGA6233 |
error | a cartridge is started through the six bytes at its top, and the tool could not complete them |
NGA6234 |
error | a bs93 image carries one address, which is both where it is loaded and where it is entered, so the entry has to be its lowest byte: the entry is {entry:hex} and the image begins at {begin:hex} |
NGA6235 |
error | {section} waits in storage, and a bs93 image is one block an emulator copies into memory: it has no loader, and nothing would ever put those bytes where they belong |
NGA6236 |
error | a Lynx cartridge is booted by fifty bytes its ROM decrypts and the loader they read in, and those were not made |
NGA6237 |
error | the boot ROM decrypts {available:n} bytes and the loader's first part came to {required:n} |
NGA6238 |
error | the rest of page zero holds {available:n} bytes and the loader came to {required:n}: the first part reads the second where the ROM left the counter, and the counter does not leave the page it is on |
NGA6239 |
error | a {name} cartridge holds {available:n} bytes and this comes to {required:n} |
NGA6240 |
error | a prg is loaded at BASIC's own start and the line that enters it stands there, so the program begins at {floor:hex}: this image begins at {begin:hex}, which the load would write over BASIC's pointers |
NGA6241 |
error | {section} waits in storage, and a prg is one block a PET is handed by hand: it has no loader, and nothing would ever put those bytes where they belong |
NGA6242 |
error | the program comes to {required:n} sectors and the Phases left {available:n}: a diskette holds both, and the Phases are placed first |
NGA6243 |
error | the program has no bytes, and a {container} of none would load nothing |
NGA6244 |
error | the tool wrote no {container} and found nothing wrong with the program: the fault is the tool's |
NGA6245 |
error | under {document}, {section} {what}, and a choice may differ from the first in bytes alone |
NGA6246 |
error | {document} changes the byte of {section} at offset {offset:n}, which runs while the file loads, before anything is chosen |
NGA6247 |
error | {document} changes the byte of {section} at offset {offset:n}, and the load never holds it as it is where it could change it |
NGA6248 |
warning | nothing the file runs while it loads names ngaChoice, so it always loads as {document} |
Lexing a .ngc Module
| Code | Severity | Message |
|---|---|---|
NGA7001 |
error | unexpected character {character} |
NGA7002 |
error | control character {code:hex} in source |
NGA7003 |
error | invalid UTF-8 encoding |
NGA7004 |
error | /* is not closed before the end of the file |
NGA7005 |
error | a backslash at the end of a line does not carry a // comment onto the next |
NGA7006 |
error | a leading zero does not make {constant} octal; write it in decimal, 0x or 0b |
NGA7007 |
error | {suffix}: an integer constant takes no suffix |
NGA7008 |
error | there are no floating-point constants |
NGA7009 |
error | {character} is not valid in a {base} constant |
NGA7010 |
error | {prefix} is not followed by any digits |
NGA7011 |
error | ' in an integer constant must stand between digits |
NGA7012 |
error | this constant is too large to be represented |
NGA7013 |
error | {name} is reserved: C keeps a name that begins with __, or with _ and a capital, for the compiler |
NGA7014 |
error | this {what} is not closed before the end of its line |
NGA7015 |
error | {escape} is no escape: the six are \\, \", \', \n, \t and \0 |
NGA7016 |
error | {character} is not ASCII, and this literal names no character set |
NGA7017 |
error | a character constant holds one character, and this holds {what} |
Parsing a .ngc Module
| Code | Severity | Message |
|---|---|---|
NGA7100 |
error | expected {expected}, found {found} |
NGA7101 |
error | {what} nest more than {limit} deep |
NGA7102 |
error | the subset spells {found} as {spelling} |
NGA7103 |
error | a literal of {second} is not joined to one of {first} |
Compiling a .ngc Module
| Code | Severity | Message |
|---|---|---|
NGA7200 |
error | the compiler does not compile {construct} yet |
NGA7201 |
error | {name} is not declared |
NGA7202 |
error | {name} is not a function, and only a function or a .proc can be called |
NGA7203 |
error | {name} is a function, and a function cannot be assigned |
NGA7204 |
error | {name} is already defined in this file |
NGA7205 |
note | the previous definition of {name} is here |
NGA7206 |
error | {value} is outside the range of {type} |
NGA7207 |
error | {left} and {right} differ in signedness, and only a cast mixes them |
NGA7208 |
error | a {from} does not fit in the {to} it is assigned to without a cast |
NGA7209 |
error | a bool holds true, false or a comparison, and is neither an operand nor an integer |
NGA7210 |
warning | {value} is outside the range of {type}, so this comparison is always {outcome} |
NGA7211 |
error | a value of {type} shifted by {count}: the count is from 0 to {largest} |
NGA7212 |
error | a condition is a bool, and this is {what} |
NGA7213 |
error | {keyword} stands in no {around} |
NGA7214 |
error | {name} is not a type |
NGA7216 |
error | {type} has no enumerator {name} |
NGA7217 |
error | {type} is an enumeration, whose values are compared and never computed |
NGA7218 |
error | {left} and {right} are different types |
NGA7219 |
error | a switch takes a value of an enum or an integer, and this is {what} |
NGA7220 |
error | {label} is not an enumerator of {type} |
NGA7221 |
error | {label} is a label of this switch already |
NGA7222 |
warning | no case names {names} of {type}, and the switch has no default |
NGA7223 |
error | {name} has {count} enumerators, and an enumeration holds 256 at most |
NGA7224 |
error | {name} takes as many arguments as it has parameters, {count}, and this call gives {given} |
NGA7225 |
error | {name} returns nothing, and this reads what it returns |
NGA7226 |
error | {name} returns {type}, and this return gives no value |
NGA7227 |
error | {name} returns nothing, and this return gives a value |
NGA7228 |
error | {name} returns {type}, and the end of its body is reached with no return |
NGA7229 |
error | this call closes a cycle of calls, {cycle}, and a function never reaches itself |
NGA7230 |
error | {what} is not cast to a {type} |
NGA7231 |
error | {what} is given a constant, and this is not one |
NGA7232 |
error | {name} is const, and is given no value where it is declared |
NGA7233 |
error | a constant is defined through itself, {cycle} |
NGA7234 |
error | {name} is const, and is not assigned |
NGA7235 |
error | {name} is read in its own {what}, before it has one |
NGA7236 |
error | {index} is outside {name}, whose elements are indexed from 0 to {last} |
NGA7237 |
error | an index is {allowed}, and this is {what} |
NGA7238 |
error | {name} is an array, and is not assigned but for its elements |
NGA7239 |
error | {name} is neither an array nor a pointer, and nothing else is indexed |
NGA7240 |
error | this divides by zero |
NGA7241 |
error | {name} is given {given} values, more than the {count} it holds |
NGA7242 |
error | {name} is {what}, and is given {given} |
NGA7243 |
error | the size of {name} is a constant from 1 to {largest} |
NGA7244 |
error | {name} is {what}, and a declaration declares pointers or none |
NGA7245 |
error | {name} is a parameter, whose address is not taken; copy it to a local |
NGA7246 |
error | {left} and {right} do not meet |
NGA7247 |
error | what is written here is const, reached through a pointer to const |
NGA7248 |
error | {what} is no pointer, and only a pointer is dereferenced |
NGA7249 |
error | {name} is a pointer, and C would ignore the size written for it |
NGA7250 |
error | {name} has no members, and C gives such a type no size |
NGA7251 |
error | a type holds itself by value and has no size, {cycle} |
NGA7252 |
error | {name} is a member, which is given no value and is not const |
NGA7253 |
error | {type} has no member {name} |
NGA7254 |
error | {name} is a member of {type} already |
NGA7255 |
error | {what} is no struct or union, and only one has members |
NGA7256 |
error | {what} is given {given} |
NGA7257 |
error | {what} is a struct or a union, which no operator takes |
NGA7258 |
error | {name} is no attribute of the subset |
NGA7259 |
error | [[{attribute}]] applies to {applies}, and {what} is none |
NGA7260 |
error | {name} is an array of {what}, which lies in no stripes |
NGA7261 |
error | {name} has {count} elements, and a striped array holds 256 at most |
NGA7262 |
error | {name} lies in stripes, and has no address of its own |
NGA7263 |
error | {name} is a Label of the assembler with no shape in C: {reason} |
NGA7264 |
error | {name} is {reason}, which C does not read |
NGA7265 |
error | {name} is a reserved Region, which C does not reach |
NGA7267 |
note | {name} is defined here |
NGA7268 |
error | {name} takes or returns u8[N], bytes that a call from C does not hand over |
NGA7269 |
error | {name} is defined in C, and extern declares only what the assembler exports |
NGA7270 |
error | {name} is declared extern, and nothing the assembler exports is named so |
NGA7271 |
error | {name} is declared extern already, and a name is declared once in the program |
NGA7272 |
error | {name} is declared extern, and {what} |
NGA7273 |
error | {name} {what} |
NGA7274 |
error | {name} reads past what the assembler wrote as data: {reason} |
NGA7275 |
error | {path}, at offset {offset}, splits an item the assembler wrote |
NGA7276 |
error | {what} holds {value}, which is no {type} |
NGA7277 |
error | {name} {what} |
NGA7278 |
error | {name} is no character set, and a literal's prefix names one |
NGA7279 |
error | {name} is {what}, and {form} takes {takes} |
NGA7280 |
error | {name} is in family {family}, whose member is known at run time alone: call it in a with({family}, i) block |
NGA7281 |
error | {name} is in pane {pane} of window {window}, which this block shows in another state: the call's .with would leave that pane shown, not the block's |
NGA7282 |
error | window {window} is shown by the block this one stands in, and a window shows one state at a time |
NGA7283 |
error | {keyword} leaves the with block, which would leave the window as the block shows it |
NGA7284 |
error | the address of {name}, in what this block shows, is kept only in a local of the block or handed to a call in it: here it {escapes} |
NGA7286 |
error | the index of with({name}, i) is {what}, and X takes a u8 or a constant |
NGA7287 |
error | [[{attribute}]] takes {takes} |
NGA7288 |
error | {name} is [[in]] a pane and [[under]] one, and code under a pane is in none |
NGA7289 |
error | this block shows another state of window {window} from code in pane {pane}, which cannot switch its own window: write [[with(...), trampoline]], and pay a Proc in fixed and a jsr |
NGA7290 |
error | trampoline on a block that needs none: {where}, and the block is a macro under .with |
NGA7291 |
error | this block shows {pane}, and the code is in {pane} already |
NGA7292 |
error | {name} is in pane {pane} of window {window}, and this code is in pane {own} of it, which cannot switch its own window: call it in a [[with({pane}), trampoline]] block or an [[under({own})]] function |
NGA7293 |
error | {name} runs under pane {pane}, called from code in the pane, from another function under it, or in a block that shows it, and this is none |
NGA7294 |
error | a transition enters a phase and never comes back, so it stands on a bare return in a void function, and {what} |
NGA7295 |
error | {name} is a slot, and its binding is its type's: a function binds a vector and a T* const a pointer, and {what} |
NGA7296 |
error | {name} fills slot {slot}, whose cell holds an address the program reads as {wanted}, and {what} |
NGA7297 |
error | {name} is no {type}: {what} |
NGA7298 |
error | {name} is taken as {type} here and as {other} elsewhere, and a function reads its arguments from one place |
NGA7299 |
error | {name} names a function type, which is a type only as a pointer: {name}* |
NGA7300 |
error | this call is of the function type its caller is a member of, which would write the temporaries the caller reads; a member dispatches through another type, or through a name |
NGA7301 |
error | {name} is written auto and given {what}, which takes its type from where it is used and so has none to give |
NGA7302 |
error | {name} is written inline and cannot be wrapped into its caller: it {what} |
NGA7303 |
error | inline is written on {what}, which has no body to wrap into a caller |
NGA7304 |
error | {name} is assigned by {operator} where it is used as a value, and reached again in the same expression, which is an order the subset does not fix |
NGA7305 |
error | {name} is a pointer, which (zp),y reads through, so it lies in the zero page whatever is asked |
NGA7306 |
error | {name} lies in stripes, whose place its layout settles, so [[placement]] is a second answer |
NGA7307 |
warning | {name} is {class} already, so this says nothing |
NGA7308 |
error | {name} is read here before anything writes it, and a static local holds what was there; give it a value where it is declared |
NGA7309 |
error | {name} is a name in a Namespace, and C defines none there; :: reads what the assembler exports |
NGA7310 |
error | a plain assignment is a statement and not a value: write two assignments; a compound one, such as +=, is a value |
NGA7311 |
error | {name} is const and given constants, so it is read-only data, which lies off the zero page whatever is asked |
NGA7312 |
warning | {name} is const and given a constant, so it takes no byte, and [[placement]] has nothing to place |
Every diagnostic
One entry per identifier, in the order of their numbers.
NGA0001
error · unexpected character {character}
Outside strings and comments, an .asm Module or a Project file holds ASCII
letters, digits and the punctuation of the language. Any other character there
raises this, such as a backslash or a non-ASCII letter. Typographic quotes
pasted from a word processor are a common case.
.section
title .byte “HELLO”
.ends
error[NGA0001]: unexpected character `“`
--> main.asm:2:15
|
2 | title .byte “HELLO”
| ^
error[NGA0001]: unexpected character `”`
--> main.asm:2:23
|
2 | title .byte “HELLO”
| ^
Type the ASCII character that was meant, here ".
NGA0002
error · unterminated string literal
A string literal is still open where the file ends: the last line lacks its
closing ", and no line ending follows it. The same mistake on any other line
is NGA0003. Close the string.
NGA0003
error · string literal is not closed before the end of the line
A string literal ends on the line it starts on, and this one reaches the end of
its line without a closing ". There is no line continuation. Everything after
the opening quote belongs to the string, a ; comment included.
.section
title .byte "PRESS START
.ends
error[NGA0003]: string literal is not closed before the end of the line
--> main.asm:2:15
|
2 | title .byte "PRESS START
| ^^^^^^^^^^^^
Close the string. A longer text is several strings, on one .byte line or on
several.
NGA0004
error · unterminated character literal
A character literal opens with ' and is not closed before the end of its line.
An apostrophe inside one is written \'.
.proc entry
lda #'A
rts
.endp
error[NGA0004]: unterminated character literal
--> main.asm:2:14
|
2 | lda #'A
| ^^
Close it: 'A'.
NGA0005
error · character literal is empty
A character literal stands for the value of one character, and '' holds none.
For a space write ' ', and for the zero byte '\0' or 0. An apostrophe is
'\'': ''' reads as an empty literal followed by an open one.
.section
blank .byte ''
.ends
error[NGA0005]: character literal is empty
--> main.asm:2:15
|
2 | blank .byte ''
| ^^
NGA0006
error · character literal holds more than one character
A character literal is the value of one character. An escape such as '\n'
counts as one. For several bytes, write a string: .byte "AB".
.section
keys .byte 'AB'
.ends
error[NGA0006]: character literal holds more than one character
--> main.asm:2:15
|
2 | keys .byte 'AB'
| ^^^^
NGA0007
error · unknown escape sequence \{escape}
A backslash in a string or a character literal starts an escape. The escapes are
\\, \", \', \n, \t and \0. There is no \xNN and no \r.
.section
prompt .byte "READY\x9B"
.ends
error[NGA0007]: unknown escape sequence `\x`
--> main.asm:2:21
|
2 | prompt .byte "READY\x9B"
| ^^
A byte no escape spells goes beside the string in the data directive:
.byte "READY", $9B.
NGA0009
error · invalid UTF-8 encoding
Raised inside a comment, a string or a character literal whose bytes are not
UTF-8. Outside them, such a byte is NGA0001. A comment or a
literal reports it once. The usual cause is a file saved in a legacy code page
with accented letters in its comments. Save the file as UTF-8.
NGA0010
error · {prefix} is not followed by any digits
$ begins a hexadecimal number and % a binary one, and here no digit follows.
The language has no remainder operator, so % written as one raises this.
COUNT = 20
.proc entry
lda #COUNT % 8
rts
.endp
error[NGA0010]: `%` is not followed by any digits
--> main.asm:4:20
|
4 | lda #COUNT % 8
| ^
For a power of two, COUNT & 7 is the remainder of division by 8.
NGA0011
error · {character} is not valid in a {base} literal
A number has one base: decimal with no prefix, hexadecimal after $, binary
after %. Raised for a digit the base does not have, such as 2 after %,
and for a letter that touches a number, which is read as one of its digits.
0FFh, the notation of other assemblers, is read as a decimal number, and F
is not a decimal digit.
.proc entry
lda #0FFh
rts
.endp
error[NGA0011]: `F` is not valid in a decimal literal
--> main.asm:2:15
|
2 | lda #0FFh
| ^
Write $FF. A number reports this once, however many of its digits are wrong.
NGA0012
error · _ in a numeric literal must stand between digits
A _ groups the digits of a number, as in %1010_0101 or 65_536. It needs a
digit on each side: it cannot follow the prefix, end the number, or stand next
to another _.
.section
mask .byte %_1010_0101
.ends
error[NGA0012]: `_` in a numeric literal must stand between digits
--> main.asm:2:16
|
2 | mask .byte %_1010_0101
| ^
A number reports this once, however many separators are misplaced in it.
NGA0013
error · hexadecimal literals are written $1F, not 0x1F
Hexadecimal is written with $. 0x is C's notation, and neither an .asm
Module nor a Project file takes it. A .ngc Module does.
.proc entry
lda #0x1F
rts
.endp
error[NGA0013]: hexadecimal literals are written `$1F`, not `0x1F`
--> main.asm:2:14
|
2 | lda #0x1F
| ^^^^
NGA0014
error · numeric local labels do not exist; use @, @+, @-, or a name
A local label is named, @loop, or anonymous, @. A digit after @, @+ or
@- is refused: @1 is not a name, and @-2 does not count two labels back.
.proc entry
ldx #8
@1 dex
bne @1
rts
.endp
error[NGA0014]: numeric local labels do not exist; use `@`, `@+`, `@-`, or a name
--> main.asm:3:1
|
3 | @1 dex
| ^^
error[NGA0014]: numeric local labels do not exist; use `@`, `@+`, `@-`, or a name
--> main.asm:4:13
|
4 | bne @1
| ^^
Name the label, or write @ and reach the nearest one with @- or @+. See
Local labels.
NGA0015
error · control character {code:hex} in source
A control character, a byte below $20 or the byte $7F, stands outside a
string, a character literal and a comment. Tab, line feed and carriage return
are allowed. The usual cause is a form feed or another byte left by an editor
or a file conversion. Delete it; the location shows where. The line quoted under
the message shows the byte as its symbol from Unicode's Control Pictures, ␀
for a NUL and ␌ for a form feed.
NGA0016
error · this number is too large to be represented
The tool computes with signed 64-bit integers, so the largest literal is
$7FFF_FFFF_FFFF_FFFF.
.section
big .word $1_0000_0000_0000_0000
.ends
error[NGA0016]: this number is too large to be represented
--> main.asm:2:15
|
2 | big .word $1_0000_0000_0000_0000
| ^^^^^^^^^^^^^^^^^^^^^^
A value that is representable but does not fit the byte or word it is written
to is NGA6101.
NGA0017
error · a leading zero does not make {literal} octal; write it in decimal, $ or %
A decimal literal of more than one digit starts with 0. C reads such a
literal as octal, so 017 is 15 there and 17 to anyone who never learned C.
The tool takes neither reading. 0 alone is zero, and a 0 after $ or %
is an ordinary digit.
.proc entry
ldx #017
rts
.endp
error[NGA0017]: a leading zero does not make `017` octal; write it in decimal, `$` or `%`
--> main.asm:2:14
|
2 | ldx #017
| ^^^
Drop the zero, ldx #17, or write the value in hexadecimal or binary,
ldx #$0F. The same rule in a .ngc Module is NGA7006.
NGA0100
error · expected an expression
The grammar needs a value here and finds none. Typical causes are an
operand left out, as in lda #, a comma at the end of a list of data, and *
written for the current address, which the language does not have. Put a Label
where an address is wanted.
.section
table .byte 1, 2, 3,
.ends
error[NGA0100]: expected an expression
--> main.asm:2:23
|
2 | table .byte 1, 2, 3,
| ^
NGA0101
error · expected ) to close this parenthesis
A ( in an expression or an operand has no ) before the end of the line. The
location is the ( left open.
WIDTH = 40
.proc entry
lda #(WIDTH * 2
rts
.endp
error[NGA0101]: expected `)` to close this parenthesis
--> main.asm:4:14
|
4 | lda #(WIDTH * 2
| ^
NGA0102
error · << is a shift; the low byte of an operand is <
< in front of an operand takes its low byte, and > its high byte. << is
the left shift and needs a value on each side. Written in front of an operand
it is read as <, so nothing else is reported.
.proc entry
lda #<<screen
rts
.endp
.section
screen .res 40
.ends
error[NGA0102]: `<<` is a shift; the low byte of an operand is `<`
--> main.asm:2:14
|
2 | lda #<<screen
| ^^
Remove one <.
NGA0103
error · {outer} and {inner} need parentheses to say which one binds first
Two pairs of operators are refused without parentheses: a shift with + or
-, and &, | or ^ with a comparison. C gives both an order that is often
not the one meant: it reads a & $FF == 0 as a & ($FF == 0). The tool names
the two operators and does not choose.
ROWS = 24
.proc entry
lda #ROWS + 1 << 2
rts
.endp
error[NGA0103]: `<<` and `+` need parentheses to say which one binds first
--> main.asm:4:14
|
4 | lda #ROWS + 1 << 2
| ^^^^^^^^^^^^^
Add the parentheses for the reading you mean, (ROWS + 1) << 2 or
ROWS + (1 << 2). See Precedence.
NGA0104
error · this expression nests more than {limit} deep
An expression nests at most 64 operators deep, and at most 64 parentheses
deep, the two counted apart. A chain such as 1+1+1 counts each operator, so a long sum
written term by term reaches the limit. Split it into Constants that each hold
a part: the limit applies to each expression on its own.
NGA0110
error · {token} cannot begin a statement
A statement begins with a mnemonic, a macro's name or a directive. At column one
a line may also begin with a Label or a Constant. Raised for a line that begins
with anything else. Two common cases come from other assemblers: *= $2000 to
set the address, and a comment written with //.
*= $2000
.proc entry
rts
.endp
error[NGA0110]: `*` cannot begin a statement
--> main.asm:1:1
|
1 | *= $2000
| ^
A comment starts with ;. A Section says where it goes with an attribute,
.section absolute at $2000, or names no address and the solver picks one. See
Placement.
NGA0111
error · unexpected {token} after the end of the statement
A statement ends where its grammar is complete, and the rest of its line is
empty or a ; comment. Raised for whatever follows: most often a comma missing
between two values, or a second statement on the same line, as in
lda #1 : sta $80. A line holds one statement. Not raised for a token the
lexer refused, such as % 8, which has a finding of its own.
.section
table .byte 1, 2 3
.ends
error[NGA0111]: unexpected `3` after the end of the statement
--> main.asm:2:20
|
2 | table .byte 1, 2 3
| ^
NGA0112
error · {name} at column one defines a label; indent it to write an instruction
A name at column one is a Label, and what follows it on the line must be a
statement. Raised where it cannot be one. Usually an instruction with an
operand has lost its indentation: lda #0 at column one is a Label lda
followed by #0, and also gets NGA0113. A Label written with a
colon, as other assemblers write one, is NGA0199 instead.
.proc entry
lda #0
sta $D01A
rts
.endp
warning[NGA0113]: `lda` at column one defines a label named like an instruction
--> main.asm:2:1
|
2 | lda #0
| ^^^
error[NGA0112]: `lda` at column one defines a label; indent it to write an instruction
--> main.asm:2:1
|
2 | lda #0
| ^^^
Indent the instruction.
NGA0113
warning · {name} at column one defines a label named like an instruction
A label in column one that is spelled like an instruction is almost always an instruction that lost its indentation. The tool cannot tell the two apart, because a label is marked by position and nothing else.
.proc entry
lda #0
sta $0600
rts
.endp
warning[NGA4612]: control runs off the end of `entry` into whatever is placed after it: end it with a jump or a return, or chain a proc to it with `then`
--> main.asm:3:9
|
3 | sta $0600
| ^^^^^^^^^
warning[NGA0113]: `rts` at column one defines a label named like an instruction
--> main.asm:4:1
|
4 | rts
| ^^^
Here the rts became a label, and the Proc now runs off its end. Indent the
line. Where a label is meant to be named like this, turn the
warning off on the line below with .off NGA0113. A Proc's name is not such a
label: .proc inc names it after a directive, which no lost indent writes, so
it draws nothing, and a C function called inc is written that way.
NGA0114
error · a direction marks a reference, not a definition
@- and @+ belong to a reference, where they choose the nearest definition
before or after it. A definition is @name or @ alone.
.proc entry
ldx #8
@-loop dex
bne @-loop
rts
.endp
error[NGA0114]: a direction marks a reference, not a definition
--> main.asm:3:1
|
3 | @-loop dex
| ^^^^^^
error[NGA2210]: no definition of `@loop` matches this reference
--> main.asm:4:13
|
4 | bne @-loop
| ^^^^^^
Write the definition without the sign. Since this one is refused, the reference
below it finds no @loop, which is NGA2210.
NGA0115
error · a local label has no scope outside a .proc
A local label, @name or @, takes its scope from the .proc or the macro
body it stands in. In a .section or at the top level of a Module there is
none, and the definition and every reference are refused.
.section
clear ldx #0
@loop sta $0600,x
inx
bne @loop
rts
.ends
error[NGA0115]: a local label has no scope outside a `.proc`
--> main.asm:3:1
|
3 | @loop sta $0600,x
| ^^^^^
error[NGA0115]: a local label has no scope outside a `.proc`
--> main.asm:5:13
|
5 | bne @loop
| ^^^^^
Write the code as a .proc, or give the label a plain name. See
Local labels.
NGA0116
error · .declare says what a byte of a proc is, and this stands outside one
.declare makes a Temporary of a Proc an argument or the result. It stands
inside the .proc, on the line above the .ztemp or .temp it names.
.declare arg u8
value .ztemp 1
.proc twice
lda value
asl
sta value
rts
.endp
error[NGA0116]: `.declare` says what a byte of a proc is, and this stands outside one
--> main.asm:1:9
|
1 | .declare arg u8
| ^^^^^^^^
Move both lines into the Proc. See .declare.
NGA0117
error · .declare says what the .ztemp or .temp below it is, and this is not one
.declare applies to the next statement, which must be a .ztemp or a .temp.
Only blank lines and comments may stand between. Raised where something else
comes first, or nothing does.
.proc twice
.declare arg u8
lda value
asl
sta value
rts
value .ztemp 1
.endp
error[NGA0117]: `.declare` says what the `.ztemp` or `.temp` below it is, and this is not one
--> main.asm:2:9
|
2 | .declare arg u8
| ^^^^^^^^
Move the .declare to the line above its reservation. A .declare that keeps
every byte in a register, as .declare arg a, takes no reservation and is not
held to this.
NGA0118
error · .declare says arg or ret, found {token}
The word after .declare is the role: arg for an argument, ret for the
result. A type or a place may follow it, as in .declare arg u8.
.proc twice
.declare u8
value .ztemp 1
lda value
asl
sta value
rts
.endp
error[NGA0118]: `.declare` says `arg` or `ret`, found `u8`
--> main.asm:2:18
|
2 | .declare u8
| ^^
NGA0119
error · {name} is not a type or a place; a declared byte is u8, i8, u16, i16, bool or u8[N], or a place is a letter a byte from the low one: a, x or y, and m for memory beside one of them
After arg or ret comes a type, a place, or nothing. The count of u8[N] is
a number written out, from 1 to 65535, and a Constant's name is refused there.
A place is one or two letters, one per byte from the low one, and at least one
of them names a register.
LENGTH = 4
.proc clear
.declare arg u8[LENGTH]
buffer .ztemp LENGTH
lda #0
sta buffer
rts
.endp
error[NGA0119]: `u8[LENGTH]` is not a type or a place; a declared byte is `u8`, `i8`, `u16`, `i16`, `bool` or `u8[N]`, or a place is a letter a byte from the low one: `a`, `x` or `y`, and `m` for memory beside one of them
--> main.asm:4:22
|
4 | .declare arg u8[LENGTH]
| ^^
Where the size is a Constant, write no type. The size of the reservation then
gives it, so .declare arg over buffer .ztemp LENGTH is a u8[4].
NGA0120
error · unknown directive .{name}
A directive is a . and one of the words listed in
The assembler. The usual cause is a directive of another
assembler. .org has no counterpart: a Section says where it goes with
.section absolute at $2000, or the solver places it. .db and .dw are
.byte and .word. A file that .include would read is a Module of its own,
named in the Project's modules block, and a binary file is a
binary( "file.bin" ) entry there.
.org $2000
.proc entry
rts
.endp
error[NGA0120]: unknown directive `.org`
--> main.asm:1:1
|
1 | .org $2000
| ^^^^
NGA0121
error · .end does not say what it closes; write the block's own closer: .ends, .endp, .endm, .endif, .endmatch, .endns or .endch
Each block has its own closer: .ends, .endp, .endm, .endif, .endns,
.endch and .endmatch, and .end is none of them. The block stays open, so
it is also reported as never closed.
.proc entry
rts
.end
error[NGA0125]: this `.proc` is never closed
--> main.asm:1:1
|
1 | .proc entry
| ^^^^^
error[NGA0121]: `.end` does not say what it closes; write the block's own closer: `.ends`, `.endp`, `.endm`, `.endif`, `.endmatch`, `.endns` or `.endch`
--> main.asm:3:1
|
3 | .end
| ^^^^
Where .end marks the end of the source, as in other assemblers, delete it: a
Module ends where its file does. See
Abbreviations.
NGA0122
error · expected a name after {after}
The grammar needs a name here and finds something else, or the end of the line.
Raised after a directive that declares or names something, such as .proc,
.macro, .namespace, .slot or .transition; after then at .endp; after
in, under or as among a Section's attributes; and after a . with no word
behind it. A number or a string is not a name.
.proc entry
rts
.endp then
error[NGA0122]: expected a name after `then`
--> main.asm:3:7
|
3 | .endp then
| ^^^^
NGA0123
error · {name} is not a section attribute
A Section's attributes are a placement, root, in NAME, temporary,
readonly and foreign, and a .proc adds under NAME and as NAME. at,
align and within are not attributes. They complete a placement, so they
stand right after zeropage or absolute, with no comma.
.section at $2000
table .byte 1, 2, 3
.ends
error[NGA0123]: `at` is not a section attribute
--> main.asm:1:10
|
1 | .section at $2000
| ^^
Write .section absolute at $2000. The word is dropped together with what
follows it up to the next comma, here $2000, and the Section opens with the
attributes that are left. What it holds and its .ends are read as usual. See
Placement.
NGA0124
error · this .section is never closed
A .section closes with .ends before the end of the file, and one opened
inside a .proc closes before its .endp. The finding stands at the
.section left open.
.proc entry
inc counter
rts
.section
counter .byte 0
.endp
error[NGA0124]: this `.section` is never closed
--> main.asm:4:1
|
4 | .section
| ^^^^^^^^
Add the .ends.
NGA0125
error · this .proc is never closed
A .proc closes with .endp before the end of the file. The finding stands
at the .proc left open. A .endp inside an .if branch is refused,
NGA0169, and leaves the Proc open.
.proc entry
rts
error[NGA0125]: this `.proc` is never closed
--> main.asm:1:1
|
1 | .proc entry
| ^^^^^
NGA0126
error · {directive} without an open .section
.ends and .endsection close a .section, and none is open here. The usual
cause is a .proc closed with .ends, which also leaves the Proc open.
.proc entry
rts
.ends
error[NGA0125]: this `.proc` is never closed
--> main.asm:1:1
|
1 | .proc entry
| ^^^^^
error[NGA0126]: `.ends` without an open `.section`
--> main.asm:3:1
|
3 | .ends
| ^^^^^
Close a Proc with .endp. The mirror mistake is NGA0127.
NGA0127
error · {directive} without an open .proc
.endp and .endproc close a .proc, and none is open here. The usual cause
is a .section closed with .endp, which also leaves the Section open. A
.proc line that was refused, for a missing name or a wrong attribute, leaves
its .endp with nothing to close as well.
.section
table .byte 1, 2, 3
.endp
error[NGA0124]: this `.section` is never closed
--> main.asm:1:1
|
1 | .section
| ^^^^^^^^
error[NGA0127]: `.endp` without an open `.proc`
--> main.asm:3:1
|
3 | .endp
| ^^^^^
Close a Section with .ends. The mirror mistake is NGA0126.
NGA0128
error · a .section cannot open inside another; close the first one
A .section ends at its .ends, and another cannot open before that. The usual
cause is a missing .ends. The refused line is dropped, so what follows it
lands in the first Section.
.section
table .byte 1, 2, 3
.section
other .byte 4
.ends
error[NGA0128]: a `.section` cannot open inside another; close the first one
--> main.asm:3:1
|
3 | .section
| ^^^^^^^^
Close the first Section before the second opens. Inside a .proc, one
.section at a time may stand beside the Proc's code.
NGA0129
error · a .proc cannot open inside another
A .proc ends at its .endp, and another cannot open before that. The usual
cause is a missing .endp on the Proc above.
.proc entry
jsr helper
rts
.proc helper
rts
.endp
error[NGA0129]: a `.proc` cannot open inside another
--> main.asm:5:1
|
5 | .proc helper
| ^^^^^
Close the first Proc before the second opens. A .proc inside a .section is
NGA0137.
NGA0130
error · this .proc already declares its result, and a proc has one
A Proc has one result, so it has one .declare ret. A result of two bytes is
one reservation of two bytes, .declare ret u16 over result .ztemp 2, or a
pair of registers, .declare ret ax.
.proc split
.declare ret u8
low .ztemp 1
.declare ret u8
high .ztemp 1
lda #0
sta low
sta high
rts
.endp
error[NGA0130]: this `.proc` already declares its result, and a proc has one
--> main.asm:4:9
|
4 | .declare ret u8
| ^^^^^^^^
NGA0131
error · {name} gives a placement this {directive} already has
A Section has one placement, zeropage or absolute, with its at, align
and within. The second one is reported and dropped, and the first stands.
.section zeropage, absolute
ptr .res 2
.ends
error[NGA0131]: `absolute` gives a placement this `.section` already has
--> main.asm:1:20
|
1 | .section zeropage, absolute
| ^^^^^^^^
Keep one. A qualifier given twice in one placement is
NGA0132, and another attribute given twice, such as root, is
NGA0133.
NGA0132
error · {name} is already given for this placement
at, align and within complete the placement of a .section or a .proc,
and each of them is given at most once.
.section absolute align 256 align 512
table .res 256
.ends
error[NGA0132]: `align` is already given for this placement
--> main.asm:1:29
|
1 | .section absolute align 256 align 512
| ^^^^^
Keep one of the two. A second placement class, as in absolute at $10, zeropage, is NGA0131, and any other attribute written twice is
NGA0133.
NGA0133
error · {name} is already given for this {directive}
Raised for root, temporary, readonly, foreign, as or under written a
second time on one .section or .proc. Remove the repeat.
.section readonly, root, readonly
table .byte 1, 2, 4, 8
.ends
error[NGA0133]: `readonly` is already given for this `.section`
--> main.asm:1:26
|
1 | .section readonly, root, readonly
| ^^^^^^^^
in is the one attribute that may repeat. Each in names another Region the
Section may stand in, and the solver picks one of them.
NGA0134
error · a slot is pointer or vector, and this is {name}
A .slot names its Binding after a comma: vector for a Slot that is called or
jumped to, pointer for one that is read through, as in lda (slot),y. The
tool does not guess, because the Binding decides the Cell: a jmp and an
address for vector, the address alone for pointer.
.slot update
error[NGA0134]: a slot is `pointer` or `vector`, and this is `line end`
--> main.asm:1:13
|
1 | .slot update
| ^
Here the Slot is called, so it is .slot update, vector. See
Slots.
NGA0135
error · a slot's placement is zeropage or absolute, and this is {name}
The third word of a .slot places its Cell, and is zeropage or absolute,
spelled out. Leave it off and the Cell is absolute.
.slot screen, pointer, zp
error[NGA0135]: a slot's placement is `zeropage` or `absolute`, and this is `zp`
--> main.asm:1:24
|
1 | .slot screen, pointer, zp
| ^^
NGA0136
error · .ztemp and .temp declare a variable, and need at column one a plain name for it, not a local one
NAME .ztemp SIZE and NAME .temp SIZE name the variable they reserve, and
the name is required: a plain identifier at column one. Raised where the name
is missing, and where it is local, as @ptr. A Temporary is a Section of its
own, and a local label is a position inside a Proc.
.proc entry
@ptr .ztemp 2
rts
.endp
error[NGA0136]: `.ztemp` and `.temp` declare a variable, and need at column one a plain name for it, not a local one
--> main.asm:2:1
|
2 | @ptr .ztemp 2
| ^^^^
Drop the @. A .ztemp written in a Proc takes the Proc's scope, so ptr here
is entry.ptr, and another Proc may have a ptr of its own.
NGA0137
error · a .proc is a section of its own and cannot open inside a .section
A Proc is placed on its own, as a Section is, so .proc stands at the top level
of a Module and not inside a .section.
.section
table .byte 1, 2, 4, 8
.proc entry
lda table
rts
.endp
.ends
error[NGA0137]: a `.proc` is a section of its own and cannot open inside a `.section`
--> main.asm:3:1
|
3 | .proc entry
| ^^^^^
error[NGA0127]: `.endp` without an open `.proc`
--> main.asm:6:1
|
6 | .endp
| ^^^^^
Close the .section with .ends before the .proc. The .endp of the refused
Proc is reported as well, NGA0127. The other way round is allowed:
a .section block inside a Proc opens a Section beside it.
NGA0138
error · {what} stands in no section; what has an address is written in a .section or a .proc
Raised for an instruction, data, a reservation, a label, a macro use or an
.if that stands outside every .section, .proc and macro body. What
produces bytes or names a position needs somewhere to put them, and .section
and .proc are the two places that have an address.
.proc entry
lda table
rts
.endp
table .byte 1, 2, 4, 8
error[NGA0138]: `table` stands in no section; what has an address is written in a `.section` or a `.proc`
--> main.asm:6:1
|
6 | table .byte 1, 2, 4, 8
| ^^^^^
Put table in a .section block. What has no address stays at the top level: a
Constant, a .ztemp or .temp, an .assert, an .export.
NGA0139
error · this byte is already an argument, and a byte is one argument or none
.declare arg makes the reservation below it an argument, and one byte carries
one argument. Two .declare arg lines above one .ztemp make the same byte two
arguments.
.proc add
.declare arg u8
.declare arg u8
left .ztemp 1
right .ztemp 1
clc
lda left
adc right
sta left
rts
.endp
error[NGA0139]: this byte is already an argument, and a byte is one argument or none
--> main.asm:3:9
|
3 | .declare arg u8
| ^^^^^^^^
Put each .declare on the line right above its own .ztemp, rather than all
of them at the top of the Proc. Two .declares over one reservation are allowed
when one is arg and the other ret: the byte then brings the argument in and
the result out. See .declare.
NGA0140
error · there is no (expression,{register}) addressing mode
The 6502 indexes an indirect address in two ways: (zp,x) adds x before the
pointer is read, and (zp),y adds y after. There is no (zp,y).
.section zeropage
ptr .res 2
.ends
.proc entry
ldy #0
lda (ptr,y)
rts
.endp
error[NGA0140]: there is no `(expression,y)` addressing mode
--> main.asm:7:13
|
7 | lda (ptr,y)
| ^
Write lda (ptr),y.
NGA0141
warning · these parentheses group rather than indirect; (expression,x) is the indirect form
The processor has (zp,x) and (zp),y and no other indirect mode. So
(table),x is not indirect, and the parentheses group an expression instead.
The operand that comes out is an ordinary address, and the instruction is three
bytes where the indirect form is two.
.section zeropage
table .res 2
.ends
.proc entry
ldx #0
lda (table),x
rts
.endp
warning[NGA0141]: these parentheses group rather than indirect; `(expression,x)` is the indirect form
--> main.asm:7:13
|
7 | lda (table),x
| ^^^^^^^
The warning is there because the two spellings are one character apart. Write
(table,x) for the indirect form, or drop the parentheses for the indexed one.
NGA0142
error · expected x or y after ,, found {token}
In an indirect operand the comma is followed by an index register, and the
registers are written x and y, in lowercase.
.section zeropage
ptr .res 2
.ends
.proc entry
ldx #0
lda (ptr,X)
rts
.endp
error[NGA0142]: expected `x` or `y` after `,`, found `X`
--> main.asm:7:18
|
7 | lda (ptr,X)
| ^
Write (ptr,x). Outside parentheses, lda table,X is
NGA2304 instead.
NGA0143
error · {code} names no diagnostic
.off takes an identifier as the tool prints it: NGA in capitals and four
digits. A code that names nothing is refused rather than ignored, because a
.off that silences nothing would look as if it worked.
.proc entry
.off nga0113
rts
.endp
error[NGA0143]: `nga0113` names no diagnostic
--> main.asm:2:6
|
2 | .off nga0113
| ^^^^^^^
The Project's diagnostics block refuses such a code the same way, as
NGA1118.
NGA0144
warning · .off {code} silenced nothing: no such warning stood on the line below
.off CODE silences that warning on the statement on the next line, and
nowhere else. Raised when no such warning was reported there: the code is the
wrong one, the warning points at another line, or the finding went away and the
.off stayed. Not raised while the build has errors, since the Step that would
raise the warning may not have run.
.proc entry
.off NGA0113
lda #0
rts
.endp
warning[NGA0144]: `.off NGA0113` silenced nothing: no such warning stood on the line below
--> main.asm:2:1
|
2 | .off NGA0113
| ^^^^^^^^^^^^
Remove the .off, or move it to the line above the one the warning points at.
NGA0145
error · an export names a symbol of the scope it stands in; to export {name}, write .export {member} inside {scope}
.export takes a plain name and looks for it in the block it stands in, so
worker.inner after .export is refused. To export a position inside a Proc,
or a name inside a .namespace block, write the .export inside that block.
.export worker, worker.inner
.proc worker
inner lda #$10
rts
.endp
error[NGA0145]: an export names a symbol of the scope it stands in; to export `worker.inner`, write `.export inner` inside `worker`
--> main.asm:1:17
|
1 | .export worker, worker.inner
| ^^^^^^^^^^^^
Write .export inner inside .proc worker. Another Module then reads
worker.inner and writes the operand of the instruction there, as A Proc has
one entry allows, and never jumps to
it.
NGA0150
error · this .charset is never closed
A .charset block ends at .endcharset or .endch. Without one, the block
ends at the next line that begins with a directive, and the tool reads on from
that line as usual. The finding points at the .charset.
.charset digits
"0123456789" = $10
.section
score .byte digits"0042"
.ends
error[NGA0150]: this `.charset` is never closed
--> main.asm:1:1
|
1 | .charset digits
| ^^^^^^^^
Add .endch after the last entry. A block is closed even when it holds no
entries.
NGA0151
error · {directive} without an open .charset
An .endch or .endcharset with no .charset open. Usually there is one too
many. It also follows a .charset that was refused, as one in a Namespace is,
NGA0164, and a block that ended early at a directive inside it,
NGA0150.
.charset digits
"0123456789" = $10
.endch
.endch
error[NGA0151]: `.endch` without an open `.charset`
--> main.asm:4:1
|
4 | .endch
| ^^^^^^
NGA0152
error · expected a character set entry, written "..." = value
Each line of a .charset block is one entry: a string, =, and the byte its
first character takes. Raised for a line that starts with anything but a
string, a character literal included, and for one with no =.
.charset font
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" = $00
'.' = $1A
.endch
error[NGA0152]: expected a character set entry, written `"..." = value`
--> main.asm:3:3
|
3 | '.' = $1A
| ^^^
Write one character as a run of one: "." = $1A.
NGA0153
error · a character set entry maps at least one character
An entry maps a run of characters, the first to the byte on the right and the rest to the bytes after it. An empty string maps nothing.
.charset font
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" = $00
"" = $1A
.endch
error[NGA0153]: a character set entry maps at least one character
--> main.asm:3:3
|
3 | "" = $1A
| ^^
Put the characters in the quotes, or remove the line.
NGA0154
error · the left side of an entry names no character set; the set is the one being declared
The left side of an entry lists code points of the set being declared, so it carries no prefix. That holds in a derived set too: an entry that adds to the base or overrides it is written plain.
.charset font
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" = $00
.endch
.charset bright : font ^ $80
font"." = $9A
.endch
error[NGA0154]: the left side of an entry names no character set; the set is the one being declared
--> main.asm:6:3
|
6 | font"." = $9A
| ^^^^
Write "." = $9A.
NGA0155
error · .macro cannot open inside a .section, a .proc or another .macro
A macro definition stands at the top level of a Module, or in a .namespace
block there. It does not stand inside a .section, a .proc or another
.macro.
.proc entry
.macro clear at
lda #0
sta at
.endm
rts
.endp
error[NGA0155]: `.macro` cannot open inside a `.section`, a `.proc` or another `.macro`
--> main.asm:2:1
|
2 | .macro clear at
| ^^^^^^
error[NGA0157]: `.endm` without an open `.macro`
--> main.asm:5:1
|
5 | .endm
| ^^^^^
Move the definition above the Proc. The .endm of the refused macro is reported
as well, NGA0157.
NGA0156
error · this .macro is never closed
A .macro without .endm or .endmacro takes every line after it, to the end
of the file, as its body. The finding points at the .macro.
.proc entry
clear $80
rts
.endp
.macro clear at
lda #0
sta at
error[NGA0156]: this `.macro` is never closed
--> main.asm:6:1
|
6 | .macro clear at
| ^^^^^^
Add .endm after the last line of the body. Where a .proc or a .section
follows the unclosed macro, it stands in the body and is reported as
NGA0158.
NGA0157
error · {directive} without an open .macro
An .endm or .endmacro with no .macro open. Usually there is one too many,
or the .macro it was meant to close was refused, NGA0155.
.macro clear at
lda #0
sta at
.endm
.endm
error[NGA0157]: `.endm` without an open `.macro`
--> main.asm:5:1
|
5 | .endm
| ^^^^^
NGA0158
error · {what} cannot stand in a macro body, which holds instructions and data
A macro body holds instructions and data. It does not hold declarations. A macro is instantiated where it is used, so a declaration inside one would declare the same name again at every use.
Besides instructions, labels and uses of other macros, a body takes .byte,
.word, a payload, .if, .match, .with and .source. Everything else is
refused: a Constant, a reservation, a Section, any other directive.
.macro wait frames
count .ztemp 1
lda #frames
sta count
@loop dec count
bne @loop
.endm
error[NGA0158]: `.ztemp` cannot stand in a macro body, which holds instructions and data
--> main.asm:2:9
|
2 | count .ztemp 1
| ^^^^^^
Declare the Temporary in the Proc that uses the macro and pass it in as an argument, as Macros does. Define a Constant outside the body.
NGA0160
error · .namespace cannot open inside a .section or a .macro
A .namespace block holds whole Sections, Procs and macros, so it opens outside
them: at the top level of a Module, or in a Proc, where it holds what stands
beside the Proc. It does not open inside a .section or a macro body.
.section
.namespace colors
red .byte $32
.endns
.ends
error[NGA0160]: `.namespace` cannot open inside a `.section` or a `.macro`
--> main.asm:2:1
|
2 | .namespace colors
| ^^^^^^^^^^
error[NGA0162]: `.endns` without an open `.namespace`
--> main.asm:4:1
|
4 | .endns
| ^^^^^^
Open the Namespace above the .section and close it after .ends. The .endns
of the refused block is reported as well, NGA0162.
NGA0161
error · this .namespace is never closed
A .namespace with no .endnamespace or .endns before the end of the file,
or, for one opened in a Proc, before the Proc's .endp. The finding points at
the .namespace.
.namespace sound
.proc play
rts
.endp
error[NGA0161]: this `.namespace` is never closed
--> main.asm:1:1
|
1 | .namespace sound
| ^^^^^^^^^^
Add .endns. .namespace one.two opens two levels, and one .endns closes
both.
NGA0162
error · {directive} without an open .namespace
An .endns or .endnamespace with no .namespace open. One .endns closes a
.namespace one.two whole, so a second one for the inner name is one too many.
It also follows a .namespace that was refused, NGA0160.
.namespace sound.music
.proc play
rts
.endp
.endns
.endns
error[NGA0162]: `.endns` without an open `.namespace`
--> main.asm:6:1
|
6 | .endns
| ^^^^^^
NGA0163
error · {directive} closes a namespace while a .section, .proc or .macro is still open
A Namespace holds whole blocks. An .endns while a .section, .proc or
.macro opened inside the Namespace is still open would leave that block in two
scopes. In a Proc, .endns closes only a Namespace that was opened in the same
Proc.
.namespace sound
.proc play
rts
.endns
.endp
error[NGA0161]: this `.namespace` is never closed
--> main.asm:1:1
|
1 | .namespace sound
| ^^^^^^^^^^
error[NGA0163]: `.endns` closes a namespace while a `.section`, `.proc` or `.macro` is still open
--> main.asm:4:1
|
4 | .endns
| ^^^^^^
Close the inner block first: here .endp goes above .endns. The refused
.endns leaves the Namespace open, which is reported too,
NGA0161.
NGA0164
error · a .charset stands at the top level: a literal's prefix is one name
A literal's prefix is one identifier, as in font"A", with no room for a
Namespace. A Charset declared in a Namespace could not be named from outside
it, so .charset stands at the top level of a Module.
.charset font
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" = $00
.endch
.namespace title
.charset bright : font ^ $80
.endch
.endns
error[NGA0164]: a `.charset` stands at the top level: a literal's prefix is one name
--> main.asm:6:1
|
6 | .charset bright : font ^ $80
| ^^^^^^^^
error[NGA0151]: `.endch` without an open `.charset`
--> main.asm:7:1
|
7 | .endch
| ^^^^^^
Move the block out of the Namespace. The .endch of the refused block is
reported as well, NGA0151.
NGA0165
error · expected : here, and the answer for a false condition after it
The conditional value, CONDITION ? TAKEN : OTHERWISE, needs both answers.
Raised where the : after the first answer is missing.
NTSC = 1
frames = NTSC ? 60
error[NGA0165]: expected `:` here, and the answer for a false condition after it
--> main.asm:2:19
|
2 | frames = NTSC ? 60
| ^
Write the second answer: frames = NTSC ? 60 : 50. See
The conditional value.
NGA0166
error · this .if is never closed
An .if without .endif or .endi. The finding points at the .if.
A block opens and closes within one branch. So in a Proc, the .endp below an
unclosed .if stands in its last branch and is refused,
NGA0169, and the Proc is then reported unclosed,
NGA0125.
FAST = 1
.proc entry
.if FAST
lda #1
.else
lda #2
rts
.endp
error[NGA0125]: this `.proc` is never closed
--> main.asm:3:1
|
3 | .proc entry
| ^^^^^
error[NGA0166]: this `.if` is never closed
--> main.asm:4:1
|
4 | .if FAST
| ^^^
error[NGA0169]: `.endp` cannot stand in a conditional branch, which holds instructions and data
--> main.asm:9:1
|
9 | .endp
| ^^^^^
An .endif above the .endp clears all three.
NGA0167
error · {directive} without an open .if
An .else, .elsif, .endif or .endi with no .if open. Usually there is
one too many, or a second .else in one .if. It is also raised where the
innermost open block is a .match, which closes with .endmatch first.
FAST = 1
.proc entry
.if FAST
lda #1
.endif
rts
.endif
.endp
error[NGA0167]: `.endif` without an open `.if`
--> main.asm:8:1
|
8 | .endif
| ^^^^^^
NGA0168
error · .elsif cannot follow .else, which is the branch taken when none is
.else is the branch taken when no condition above it holds, so it comes last.
Move the .elsif above the .else.
LEVEL = 1
.proc entry
.if LEVEL == 1
lda #1
.else
lda #3
.elsif LEVEL == 2
lda #2
.endif
rts
.endp
error[NGA0168]: `.elsif` cannot follow `.else`, which is the branch taken when none is
--> main.asm:8:1
|
8 | .elsif LEVEL == 2
| ^^^^^^
NGA0169
error · {what} cannot stand in a conditional branch, which holds instructions and data
A conditional branch holds instructions and data, for the same reason a macro body does.
A branch takes instructions, .byte, .word, a payload, .res, macro uses and
.with. What defines a Symbol is refused: a Constant, a Temporary, a Section, a
Proc, a macro, a Namespace, a Charset. So are .transition, .assert,
.export and .off. No Symbol is conditional, since two branches would want
one name and only one of them is there. A block also opens and closes within one
branch, so an .endp or .endm inside an open .if is refused too.
NTSC = 1
.proc entry
.if NTSC
frames = 60
.else
frames = 50
.endif
lda #frames
rts
.endp
error[NGA0169]: a constant definition cannot stand in a conditional branch, which holds instructions and data
--> main.asm:5:1
|
5 | frames = 60
| ^^^^^^
error[NGA0169]: a constant definition cannot stand in a conditional branch, which holds instructions and data
--> main.asm:7:1
|
7 | frames = 50
| ^^^^^^
A name with two values is one Constant with a conditional value, written at the
top level: frames = NTSC ? 60 : 50. See
Not the other way.
NGA0170
error · a label in a conditional branch is written @name: a branch defines no symbol, and two branches want one name
A plain label defines a Symbol, and no Symbol is conditional. In a branch a
label is local, written @name, and each branch may define its own. A
.section has no local labels, so a branch in one holds no label at all.
FAST = 1
.proc entry
ldx #8
.if FAST
loop dex
bne loop
.endif
rts
.endp
error[NGA0170]: a label in a conditional branch is written `@name`: a branch defines no symbol, and two branches want one name
--> main.asm:6:1
|
6 | loop dex
| ^^^^
Write @loop and bne @loop.
NGA0171
error · {name}... takes every argument left, so it stands last
A pack, name..., takes every argument the names before it do not, so it is the
last name of a .macro header or of a .case. Put the fixed parameters first.
.macro store values..., at
lda #0
sta at
.endm
error[NGA0171]: `values...` takes every argument left, so it stands last
--> main.asm:1:14
|
1 | .macro store values..., at
| ^^^^^^
Here it is .macro store at, values....
NGA0172
error · .match stands in a macro body, which is where a pack is
.match counts the elements of a pack, and a pack is a parameter of a macro.
Outside a macro body there is none to count. To choose statements by a
Constant, use .if.
.proc entry
.match args
.case
.endmatch
rts
.endp
error[NGA0172]: `.match` stands in a macro body, which is where a pack is
--> main.asm:2:1
|
2 | .match args
| ^^^^^^
error[NGA0173]: `.case` without an open `.match`
--> main.asm:3:1
|
3 | .case
| ^^^^^
error[NGA0174]: `.endmatch` without an open `.match`
--> main.asm:4:1
|
4 | .endmatch
| ^^^^^^^^^
The .case and .endmatch of the refused .match are reported too, as
NGA0173 and NGA0174. In a body, a .match on a
parameter that is not a pack is NGA2326.
NGA0173
error · .case without an open .match
A .case with no .match open. The .match is missing, was refused, or was
closed by an .endmatch above this .case.
.macro first values...
.case head, rest...
.byte head
.endm
error[NGA0173]: `.case` without an open `.match`
--> main.asm:2:1
|
2 | .case head, rest...
| ^^^^^
Open the block with .match and the pack's name above the first .case, and
close it with .endmatch after the last.
NGA0174
error · {directive} without an open .match
An .endmatch with no .match open. Usually there is one too many. It is also
raised where the innermost open block is an .if that has not reached its
.endif.
.macro pair values...
.match values
.case a, b
.byte a, b
.case
.endmatch
.endmatch
.endm
error[NGA0174]: `.endmatch` without an open `.match`
--> main.asm:7:1
|
7 | .endmatch
| ^^^^^^^^^
NGA0175
error · this .match is never closed
A .match without .endmatch. The finding points at the .match. As with an
.if, the block closes before the macro does, so the .endm below it is
refused, NGA0169, and the macro is reported unclosed,
NGA0156.
.macro push values...
.match values
.case first, rest...
lda #first
pha
push rest...
.case
.endm
error[NGA0156]: this `.macro` is never closed
--> main.asm:1:1
|
1 | .macro push values...
| ^^^^^^
error[NGA0175]: this `.match` is never closed
--> main.asm:2:1
|
2 | .match values
| ^^^^^^
error[NGA0169]: `.endm` cannot stand in a conditional branch, which holds instructions and data
--> main.asm:8:1
|
8 | .endm
| ^^^^^
Add .endmatch after the last .case.
NGA0176
error · a .match holds .cases, and this stands before the first
Every statement of a .match belongs to one of its .cases, and a statement
between .match and the first .case belongs to none.
.macro push values...
.match values
clc
.case first, rest...
lda #first
pha
push rest...
.case
.endmatch
.endm
error[NGA0176]: a `.match` holds `.case`s, and this stands before the first
--> main.asm:3:9
|
3 | clc
| ^^^
Move it above the .match where every case needs it, or into the cases that do.
NGA0177
error · ... spreads a pack and follows its name, touching it
A spread is the pack's name with ... touching it: values.... Dots after a
space, or after anything but a bare name, as in (values)..., are refused.
.macro table values...
.byte values ...
.endm
error[NGA0177]: `...` spreads a pack and follows its name, touching it
--> main.asm:2:22
|
2 | .byte values ...
| ^^^
Remove the space. Spreading a name that is not a pack is
NGA2325.
NGA0178
error · this .match has no .case, so nothing could ever fit
A .match with no .case has nothing that could fit, so every use of the macro
would be an error. Add the cases. A .case with no names fits the empty pack.
.macro push values...
.match values
.endmatch
.endm
error[NGA0178]: this `.match` has no `.case`, so nothing could ever fit
--> main.asm:2:1
|
2 | .match values
| ^^^^^^
When a .match has cases and none fits the arguments of a use, the error is
NGA2328, at that use.
NGA0179
error · temporary does not go with {other}
temporary lets a Section share its address with another Temporary that is
never active at the same time. A Root is read by the hardware at any time, so
its bytes would never be free to share. A Temporary holds reservations and no
bytes, so readonly would say nothing about it. in is refused as well,
whether it names a Pane or a Region.
.section temporary, root
buffer .res 64
.ends
error[NGA0179]: `temporary` does not go with `root`
--> main.asm:1:1
|
1 | .section temporary, root
| ^^^^^^^^
Drop one of the two. A reservation that must keep its address to itself is a
.res in a .section without temporary.
NGA0180
error · a .proc is code, and temporary is a reservation
Raised for temporary among the attributes of a .proc. A Temporary holds
reservations only, and its bytes belong to other Temporaries while it is not
active.
.proc entry, temporary
rts
.endp
error[NGA0180]: a `.proc` is code, and `temporary` is a reservation
--> main.asm:1:1
|
1 | .proc entry, temporary
| ^^^^^
For variables the Proc needs only while it runs, declare a .ztemp or a
.temp inside it; see .ztemp and .temp.
To reuse the memory of code that runs once, put that code in a Module that only
the Phases running it need.
NGA0181
error · .source is followed by a quoted path, a comma and a line number, found {token}
Raised for a .source line that is not .source "PATH", LINE: a path without
quotes, a path with a character set prefix, or no line number after it. The
path names a file, so it is a bare string that nothing translates.
.source tiles.txt, 3
.proc entry
rts
.endp
error[NGA0181]: `.source` is followed by a quoted path, a comma and a line number, found `tiles`
--> main.asm:1:9
|
1 | .source tiles.txt, 3
| ^^^^^
Quote the path: .source "tiles.txt", 3. See
.source.
NGA0182
error · a source line is counted from 1, and this is {line}
Raised for a .source whose line number is 0. Lines count from 1, as an editor
counts them. A program that writes .source lines and counts from zero has to
add one.
.source "tiles.txt", 0
.proc entry
rts
.endp
error[NGA0182]: a source line is counted from 1, and this is 0
--> main.asm:1:22
|
1 | .source "tiles.txt", 0
| ^
NGA0183
error · a .{encoding} payload is written as a quoted literal, found {token}
Raised where .hex, .binary or .base64 is followed by something other than
a string literal. The quotes mark where the payload ends, so a comment may
follow it on the line.
.section
sprite .hex ad12f4
.ends
error[NGA0183]: a `.hex` payload is written as a quoted literal, found `ad12f4`
--> main.asm:2:9
|
2 | sprite .hex ad12f4
| ^^^^
Write .hex "ad12f4". Space and tab inside the quotes are ignored, so the
bytes may be grouped: "ad 12 f4". See Data.
NGA0184
error · {character} is not valid in a .{encoding} payload
Raised once for each character of a payload that its directive's alphabet
lacks: 0-9 A-F a-f for .hex, 0 1 for .binary, and A-Z a-z 0-9 + / =
for .base64. Space and tab are the only other characters allowed, and they
are skipped. The usual causes are a $ in front of hex digits and commas
between bytes. A ; inside the quotes is such a character too, not a comment.
.section
sprite .hex "$ad12f4"
.ends
error[NGA0184]: `$` is not valid in a `.hex` payload
--> main.asm:2:15
|
2 | sprite .hex "$ad12f4"
| ^
NGA0185
error · = pads the end of a .base64 payload and stands nowhere else
Raised for a = anywhere in a .base64 payload except its last one or two
characters. = pads the last group of four characters. One in the middle
usually means that two encoded strings were joined into one literal.
.section
sprite .base64 "QUE=QUJD"
.ends
error[NGA0185]: `=` pads the end of a `.base64` payload and stands nowhere else
--> main.asm:2:21
|
2 | sprite .base64 "QUE=QUJD"
| ^
Encode the bytes again as one string, or give each string its own .base64
line. Two lines in one Section emit their bytes one after the other.
NGA0186
error · a .{encoding} payload takes {group} characters to {bytes}, and this one has {count}
Raised where the characters of a payload do not make whole bytes. .hex takes
two characters to a byte and .binary eight. .base64 takes groups of four,
each three bytes, with = filling out the last group. The count leaves out
spaces and tabs.
.section
sprite .binary "0001100 00111100"
.ends
error[NGA0186]: a `.binary` payload takes 8 characters to the byte, and this one has 15
--> main.asm:2:17
|
2 | sprite .binary "0001100 00111100"
| ^^^^^^^^^^^^^^^^^^
The first byte here has seven digits. A digit dropped or typed twice is the
usual cause. Not raised where a character was refused already, since that
character is why the count is short; see NGA0184.
NGA0187
error · a payload is bytes and not text, so it names no character set
Raised for a character set prefix on the literal of .hex, .binary or
.base64. A prefix asks for text to be translated into a Charset, and a
payload is bytes that were never characters.
.section
sprite .hex atascii"ad12f4"
.ends
error[NGA0187]: a payload is bytes and not text, so it names no character set
--> main.asm:2:14
|
2 | sprite .hex atascii"ad12f4"
| ^^^^^^^^^^^^^^^
Remove the prefix. To emit text in a Charset, write the prefixed literal after
.byte; see Character sets.
NGA0188
error · a .namespace in a .proc holds sections, temporaries and constants, and {what} is none of them
Raised inside a .namespace block that stands in a .proc, once for each line
that belongs to the Proc itself: an instruction, data, a label or a .declare.
Such a block holds what stands beside the Proc, which is .section blocks,
.ztemp and .temp reservations, and Constants.
.proc entry
.namespace state
count .ztemp 1
lda #0
.endns
sta state.count
rts
.endp
error[NGA0188]: a `.namespace` in a `.proc` holds sections, temporaries and constants, and `lda` is none of them
--> main.asm:4:9
|
4 | lda #0
| ^^^
Close the block with .endns before the code. The Proc's labels need no
Namespace, because the Proc is a scope of its own: a label loop inside
entry is entry.loop from outside.
NGA0189
error · this .declare reserves no byte, and a .ztemp or .temp stands below it
Raised where a .declare reserves no byte, and a .ztemp or .temp stands on
the line below it. One that keeps every byte in registers, such as .declare arg a, reserves none, and nor does one that names another Proc's result, such as
.declare ret low.result. A .declare names the reservation below it, and
these take none, so a reservation there is taken for a mistake.
.proc plot
.declare arg a
column .ztemp 1
sta column
rts
.endp
.proc entry
lda #3
jsr plot
rts
.endp
error[NGA0189]: this `.declare` reserves no byte, and a `.ztemp` or `.temp` stands below it
--> main.asm:2:9
|
2 | .declare arg a
| ^^^^^^^^
Where the .ztemp is the Proc's own scratch, move it above the .declare.
Where it was meant to carry the argument, leave out the place, and the argument
is passed in the reservation. See .declare.
NGA0190
error · {register} already carries an argument of this proc
Raised where two .declare arg lines of one Proc put a byte in the same
register. A register carries one argument into the call. The result may use a
register an argument came in.
.proc print
.declare arg ax
.declare arg x
rts
.endp
.proc entry
jsr print
rts
.endp
error[NGA0190]: `x` already carries an argument of this proc
--> main.asm:3:9
|
3 | .declare arg x
| ^^^^^^^^
Move one of the arguments to a register that is still free, or to a reservation.
NGA0191
error · {place} names one register for two bytes
Raised for a place that names one register for both bytes: aa, xx or yy.
A place is a letter per byte, low byte first, and a register holds one byte.
.proc plot
.declare arg xx
rts
.endp
.proc entry
jsr plot
rts
.endp
error[NGA0191]: `xx` names one register for two bytes
--> main.asm:2:22
|
2 | .declare arg xx
| ^^
Use two registers, such as ax, or a register and the reservation, such as
am.
NGA0192
error · readonly does not go with {other}
Raised for readonly on a zeropage Section. readonly lets the solver put
the Section in a rom Region. The zero page is the scarcest memory the machine
has, and the tool does not spend it on bytes nothing writes.
.section zeropage, readonly
mask .byte $0F
.ends
error[NGA0192]: `readonly` does not go with `zeropage`
--> main.asm:1:1
|
1 | .section zeropage, readonly
| ^^^^^^^^
Drop zeropage to let the bytes go to ROM where the Target has some, or drop
readonly to keep them on the zero page. See Cartridges
for what readonly is for.
NGA0193
warning · a .proc holds code, which nothing writes unless a statement says so, and readonly changes nothing
Raised for readonly on a .proc. A Proc that no statement writes into is
read-only without the word, and can go in a rom Region where the Target has
one. A Proc that some statement writes into, such as one whose operand another
routine patches, stays in RAM. The word changes neither, so the tool drops it.
.proc entry, readonly
rts
.endp
warning[NGA0193]: a `.proc` holds code, which nothing writes unless a statement says so, and `readonly` changes nothing
--> main.asm:1:1
|
1 | .proc entry, readonly
| ^^^^^
Remove the word.
NGA0194
error · foreign does not go with {other}
Raised for foreign beside temporary or readonly. foreign marks bytes
that another master of the address space reads while the program runs, such as
a display buffer. A Temporary's bytes belong to other Sections between its
uses, and readonly asks for ROM, where nothing writes.
.section absolute align 4, root, foreign, readonly
screen .res 8160
.ends
error[NGA0194]: `foreign` does not go with `readonly`
--> main.asm:1:1
|
1 | .section absolute align 4, root, foreign, readonly
| ^^^^^^^^
Drop the other word.
NGA0195
error · foreign says another master reads the section, which reaches it by an address handed to the hardware, so the section is a root
Raised for foreign on a .section that is not root. The other master
reaches the Section through an address the program hands to the hardware, and
no Reference follows that. Without root, Prune finds nothing that reaches the
Section and drops it.
.section absolute align 4, foreign
screen .res 8160
.ends
error[NGA0195]: `foreign` says another master reads the section, which reaches it by an address handed to the hardware, so the section is a `root`
--> main.asm:1:1
|
1 | .section absolute align 4, foreign
| ^^^^^^^^
NGA0196
error · a .proc holds code the CPU runs, and foreign says the CPU does not reach the bytes
Raised for foreign on a .proc. foreign says the CPU does not read the
bytes, and the CPU is what runs a Proc.
.proc entry
jsr draw
rts
.endp
.proc draw, foreign
rts
.endp
error[NGA0196]: a `.proc` holds code the CPU runs, and `foreign` says the CPU does not reach the bytes
--> main.asm:6:1
|
6 | .proc draw, foreign
| ^^^^^
Remove the word. Bytes that another processor runs are data to the CPU, and
belong in a .section.
NGA0197
error · {name} is not an attribute of a transition; fast is the one there is
Raised for a word other than fast after the comma of
.transition NAME, .... fast asks storage to start everything the edge loads
at the beginning of a unit, so that a driver which reaches an offset by reading
up to it never has to. It has an effect only where the driver works that way.
Under optimize speed every edge is treated as fast.
main.ngp
modules { "main.asm" "game.asm" }
phase title { needs main then game }
phase game { needs game entry play }
entry title
main.asm
.proc entry
.transition game, quick
.endp
game.asm
.proc play
jmp play
.endp
error[NGA0197]: `quick` is not an attribute of a transition; `fast` is the one there is
--> main.asm:2:27
|
2 | .transition game, quick
| ^^^^^
warning[NGA2246]: phase `title` declares `then game`, and no `.transition game` is present in it, so the edge is taken by nothing
Write fast, or nothing. The statement is dropped with the finding, which is
why the edge is then also reported as one nothing takes.
NGA0198
error · movable is gone: a section has one address in every phase it is in
Raised for movable among the attributes of a .section or a .proc. The
word once let a Section stand at a different address in each Phase. A Section
now has one address in every Phase it is present in.
.section absolute, movable
sprites .res 64
.ends
error[NGA0198]: `movable` is gone: a section has one address in every phase it is in
--> main.asm:1:20
|
1 | .section absolute, movable
| ^^^^^^^
Delete the word. Where two Phases cannot hold the bytes at one address, give each Phase a Section of its own, in a Module that only that Phase needs.
NGA0199
error · a label is a name at column one, and is written without :
A Label is a name at column one and nothing more, and the colon other assemblers write after one is refused. The Label is defined all the same, and what follows the colon is read as the statement, so the colon costs this one finding.
.proc entry
ldx #8
loop: dex
bne loop
rts
.endp
error[NGA0199]: a label is a name at column one, and is written without `:`
--> main.asm:3:5
|
3 | loop: dex
| ^
Drop the colon.
NGA0200
error · {name} is another proc's byte, and an argument is a byte of this one or a register
Raised where .declare arg names a byte of another Proc, such as .declare arg low.result. An argument is a byte the caller writes for this Proc, in a
reservation of its own or in a register. Only a result may be another Proc's,
since the caller reads it after the call wherever it was left.
.proc low
.declare ret u16
result .ztemp 2
rts
.endp
.proc show
.declare arg low.result
rts
.endp
.proc entry
jsr low
jsr show
rts
.endp
error[NGA0200]: `low.result` is another proc's byte, and an argument is a byte of this one or a register
--> main.asm:8:22
|
8 | .declare arg low.result
| ^^^^^^^^^^
Declare the argument over a .ztemp of the Proc, and have the caller copy the
value there. See .declare.
NGA1101
error · project refers to {module}, which names no module and no group
Raised where a list of Modules in the Project names something that is neither a
Module nor a group: needs, without, resident, load, a group, or the
Module part of a transform entry. A Module answers to the stem of its file,
or to the name after as, and to nothing else. Once as renames a Module, its
stem names nothing.
main.ngp
modules { "main.asm" as game }
resident { main }
main.asm
.proc entry
rts
.endp
error[NGA1101]: project refers to `main`, which names no module and no group
--> main.ngp:3:12
|
3 | resident { main }
| ^^^^
Use the name the modules block gives; see
modules.
NGA1102
error · {module} already names a module; each module is declared once, and as gives another one a name of its own
Raised where two entries of modules come to one Module name: two files with
one stem in different directories, or a file and a generator call whose file
has that stem. The note, NGA1173, points at the first entry. A
Project file that two include lines reach is read once, so its modules
block does not raise this.
main.ngp
modules {
"main.asm"
"levels/main.asm"
}
main.asm
.proc entry
rts
.endp
error[NGA1102]: `main` already names a module; each module is declared once, and `as` gives another one a name of its own
--> main.ngp:3:3
|
3 | "levels/main.asm"
| ^^^^^^^^^^^^^^^^^
note: the module `main` is declared here
--> main.ngp:2:3
|
2 | "main.asm"
| ^^^^^^^^^^
Give one of them another name with as: "levels/main.asm" as level.
NGA1103
error · {path} is not a project file, and a run is given nothing else
Raised when the file given to the run does not end in .ngp. A run takes a
Project and nothing else, because what a Module is called, which Phases need it
and what the Target is are written in the Project and in no source file.
Write a Project that names the source file, which can be one line,
modules { "main.asm" }, and run nga main.ngp. See
The Project and Modules.
NGA1104
note · a source file becomes a module where a project's modules block names it
Follows NGA1103 and says how a source file takes part in a build:
a Project names it in its modules block.
NGA1105
error · a constant is a name, = and a number, found {token}
Raised inside constants where an entry is not a name, = and one number
literal, such as 8, $F0 or %1010, with an optional - before it as its
sign, as in -1. An expression is refused, and so is the name of another
constant: nothing in the block marks where an expression would end, so a value
is one literal. A - before a name is refused as well. An entry that breaks is
reported once, and what is left of it is read past.
main.ngp
constants {
LEVELS = 8
LIVES = LEVELS
}
modules { "main.asm" }
main.asm
.proc entry
lda #LIVES
rts
.endp
error[NGA1105]: a constant is a name, `=` and a number, found `LEVELS`
--> main.ngp:3:12
|
3 | LIVES = LEVELS
| ^^^^^^
Write the number, or do the arithmetic in the source that reads the constant.
See constants.
NGA1106
error · the value of {name} is set more than once
A constant of the constants block is set once in the whole Project, counting
every file an include reaches. A second value would depend on which file is
read first.
main.ngp
constants {
LEVELS = 8
LEVELS = 9
}
modules { "main.asm" }
main.asm
.proc entry
lda #LEVELS
rts
.endp
error[NGA1106]: the value of `LEVELS` is set more than once
--> main.ngp:3:3
|
3 | LEVELS = 9
| ^^^^^^
note: `LEVELS` was already set here
--> main.ngp:2:3
|
2 | LEVELS = 8
| ^^^^^^
To give a variant a value that a Project can change, keep the constant out of the variant and set it in the Project.
NGA1107
note · {name} was already set here
Follows NGA1106 and points at the first place the constant is
set.
NGA1108
error · {name} names no container; the tool writes {known}
Raised for a word after container in the Project, or after containers in a
target block, that names no Container the tool writes. The message lists the
words there are.
main.ngp
container cart
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1108]: `cart` names no container; the tool writes `raw`, `xex`, `atr`, `car`, `bs93`, `lnx`, `lyx`, `prg`, `d64`, `d80` and `d82`
--> main.ngp:1:11
|
1 | container cart
| ^^^^
A cartridge image is car, followed by the board's name in quotes, as in
container car "xegs128"; see Cartridges.
NGA1109
error · the container is set more than once
Raised for a second container line in the Project, counting every file an
include reaches, even where both name the same Container. What the build
writes cannot depend on which file is read first. The note
NGA1140 points at the first one.
main.ngp
include "machine.ngp"
container xex
modules { "main.asm" }
machine.ngp
include "atari/800xl.ngp"
container xex
main.asm
.proc entry
rts
.endp
error[NGA1109]: the container is set more than once
--> main.ngp:2:11
|
2 | container xex
| ^^^
note: the container was already set here
--> machine.ngp:2:11
|
2 | container xex
| ^^^
Keep one, in the Project rather than in a file it includes.
NGA1110
error · {name} is not a project block
Raised for a word at the top level of a Project file that starts no block the tool knows. It is usually a misspelling. The blocks are listed in the Project file.
main.ngp
module { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1110]: `module` is not a project block
--> main.ngp:1:1
|
1 | module { "main.asm" }
| ^^^^^^
The block here is modules. A word with no { after it is reported once, here,
and the tool reads on from the word after it.
NGA1111
error · this {name} block is never closed
Raised when the file ends inside a block. The finding points at the block's
first line, and the } is missing somewhere after it.
main.ngp
modules { "main.asm" }
target {
region $0080 .. $00FF ram
region $2000 .. $BFFF ram
main.asm
.proc entry
rts
.endp
error[NGA1111]: this `target` block is never closed
--> main.ngp:3:1
|
3 | target {
| ^^^^^^
A block left open before another block is reported differently. The } of the
next block closes the open one, and the next block's name is refused as an
entry of it.
NGA1112
error · expected a block or an include, found {token}
Raised at the top level of a Project file for something that starts no block: a
quoted path outside modules, a stray }, or punctuation such as : after a
word. An include whose path is not quoted is NGA1248.
main.ngp
"main.asm"
main.asm
.proc entry
rts
.endp
error[NGA1112]: expected a block or an `include`, found `"main.asm"`
--> main.ngp:1:1
|
1 | "main.asm"
| ^^^^^^^^^^
A path stands inside a modules block: modules { "main.asm" }.
NGA1113
error · expected { to open the body of {name}
Raised where the name of a block is not followed by {. A block has its body in
braces even when it holds one entry: resident { hud }. include, entry,
container and optimize are lines of their own and take none.
main.ngp
modules "main.asm"
main.asm
.proc entry
rts
.endp
error[NGA1113]: expected `{` to open the body of `modules`
--> main.ngp:1:1
|
1 | modules "main.asm"
| ^^^^^^^
error[NGA1112]: expected a block or an `include`, found `"main.asm"`
--> main.ngp:1:9
|
1 | modules "main.asm"
| ^^^^^^^^^^
What stood where the brace should be is then read at the top level, which adds
NGA1112.
NGA1114
error · a module is a quoted path, optionally followed by as and a name
Raised inside modules for an entry that is neither a quoted path nor a
generator call such as binary( "font.bin" ). The usual causes are a path
without quotes and a comma between entries: unlike needs and resident,
modules takes no commas.
main.ngp
modules { main.asm }
main.asm
.proc entry
rts
.endp
error[NGA1114]: a module is a quoted path, optionally followed by `as` and a name
--> main.ngp:1:11
|
1 | modules { main.asm }
| ^^^^
NGA1115
error · expected a name after as
Raised for as in a modules entry with no name after it. The name is a bare
identifier, not a quoted string. A quoted one is read as the path of the next
entry instead, which adds NGA1122.
main.ngp
modules { "main.asm" as "game" }
main.asm
.proc entry
rts
.endp
error[NGA1115]: expected a name after `as`
--> main.ngp:1:22
|
1 | modules { "main.asm" as "game" }
| ^^
error[NGA1122]: cannot read `game`
--> main.ngp:1:25
|
1 | modules { "main.asm" as "game" }
| ^^^^^^
Write "main.asm" as game.
NGA1116
error · a quoted string of a Project file is not translated, so it names no character set
Raised for a character set prefix on a quoted string of the Project file: a
Module path, an include, a generator's argument, the name after cpu.
Nothing in a Project file is translated for the target. A path may hold
non-ASCII characters as they are.
main.ngp
modules { atascii"main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1116]: a quoted string of a Project file is not translated, so it names no character set
--> main.ngp:1:11
|
1 | modules { atascii"main.asm" }
| ^^^^^^^^^^^^^^^^^
Remove the prefix.
NGA1117
error · expected deny, allow or off, found {token}
Raised inside diagnostics where an entry does not start with deny, allow
or off. deny makes a finding an error, allow makes it a warning, and off
silences it.
main.ngp
modules { "main.asm" }
diagnostics {
error NGA4501
}
main.asm
.proc entry
rts
.endp
error[NGA1117]: expected `deny`, `allow` or `off`, found `error`
--> main.ngp:4:3
|
4 | error NGA4501
| ^^^^^
See diagnostics.
NGA1118
error · {code} names no diagnostic
Raised where the diagnostics block, --deny, --allow or --off names an
identifier the tool does not have. It is refused rather than skipped, since a
line that silenced nothing would look as if it worked. In source, .off with
such an identifier is NGA0143.
main.ngp
modules { "main.asm" }
diagnostics {
off NGA113
}
main.asm
.proc entry
rts
.endp
error[NGA1118]: `NGA113` names no diagnostic
--> main.ngp:4:7
|
4 | off NGA113
| ^^^^^^
An identifier is NGA and four digits, as the tables above list them.
NGA1119
error · the severity of {code} is set more than once
Raised where one identifier is given a severity twice in the Project, counting
every file an include reaches, even where both say the same. Which one won
would depend on the order the files are read. The note NGA1120
points at the first. Given twice on the command line, by --deny, --allow
or --off, it is raised with no position, for the same reason.
main.ngp
modules { "main.asm" }
diagnostics {
deny NGA4501
allow NGA4501
}
main.asm
.proc entry
rts
.endp
error[NGA1119]: the severity of `NGA4501` is set more than once
--> main.ngp:5:9
|
5 | allow NGA4501
| ^^^^^^^
note: `NGA4501` was already set here
--> main.ngp:4:9
|
4 | deny NGA4501
| ^^^^^^^
Keep one. To change a severity that an included file sets, use --deny,
--allow or --off on the command line, which win over the Project.
NGA1120
note · {code} was already set here
Follows NGA1119 and points at the first place the identifier's
severity is set.
NGA1121
error · this include reaches a file that is already being read
Raised for an include that reaches a file still being read, directly or
through other files. The tool reads each file once, but a file that is still
being read has not been read yet, so the cycle would not end.
main.ngp
include "machine.ngp"
modules { "main.asm" }
machine.ngp
include "main.ngp"
target { region $2000 .. $BFFF ram }
main.asm
.proc entry
rts
.endp
error[NGA1121]: this include reaches a file that is already being read
--> machine.ngp:1:9
|
1 | include "main.ngp"
| ^^^^^^^^^^
Remove the include that leads back.
NGA1122
error · cannot read {path}
Raised for a file the tool cannot read: a Module in modules, a file an
include names, the file a generator works from, or the Project file given to
the run. A path is relative to the file that holds it, not to the directory the
tool runs in. Where no file is there, the tool looks in
the library. The message names the place
beside the file.
main.ngp
modules { "main.asm" "sprite.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1122]: cannot read `sprite.asm`
--> main.ngp:1:22
|
1 | modules { "main.asm" "sprite.asm" }
| ^^^^^^^^^^^^
NGA1123
error · this project declares no modules
Raised when the Project, with every file it includes, names no Module. The
modules block is missing or empty. The Modules the tool adds for what the
Project declares, such as its constants, its named Regions or the loader of a
.xex, do not count.
target {
region $0080 .. $00FF ram
region $2000 .. $BFFF ram
}
error[NGA1123]: this project declares no modules
Name the source files in a modules block; see
modules.
NGA1125
error · phase is followed by the phase's name, found {token}
A Phase is named before its brace, with a bare word: phase game { ... }, not
phase "game". The name is what then and the document's entry refer to.
A body without a name is skipped whole, so nothing inside it is checked until
the name is there.
main.ngp
modules { "main.asm" }
phase { needs main }
main.asm
.proc entry
rts
.endp
error[NGA1125]: `phase` is followed by the phase's name, found `{`
--> main.ngp:3:1
|
3 | phase { needs main }
| ^^^^^
NGA1126
error · expected needs, then, without, entry or final, found {token}
A phase block holds needs, then, without, entry and final, and
nothing else. The tool reports the first word it does not know and skips to the
next one it does, so what stood between is not read.
main.ngp
modules { "main.asm" }
phase game { needs main init start }
entry game
main.asm
.proc entry
rts
.endp
error[NGA1126]: expected `needs`, `then`, `without`, `entry` or `final`, found `init`
--> main.ngp:3:26
|
3 | phase game { needs main init start }
| ^^^^
init is a word of the load block. A Phase names the Label it starts at with
entry. A missing comma ends here too: in needs main music, the name music
is read as the next entry of the block.
NGA1127
error · expected a name after {after}
Raised where a word that takes a name is followed by something else: a list
that ends in a comma, an entry or a then with nothing after it, or a quoted
name. needs and then name Modules and Phases as bare words, main and not
"main.asm". In a target block, register, holder, units and window
take the name of what they declare first.
main.ngp
modules { "main.asm" }
phase game { needs main, }
entry game
main.asm
.proc entry
rts
.endp
error[NGA1127]: expected a name after `,`
--> main.ngp:3:24
|
3 | phase game { needs main, }
| ^
cpu takes the processor's name in quotes, and cpu 6502 without them is
NGA1248.
NGA1128
error · a resident entry names a module or a group, found {token}
resident names Modules and groups, and a Module's name is the stem of its
file, or the name after as in modules. A quoted path is not a name.
main.ngp
modules { "main.asm" }
resident { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1128]: a resident entry names a module or a group, found `"main.asm"`
--> main.ngp:2:12
|
2 | resident { "main.asm" }
| ^^^^^^^^^^
Write resident { main }.
NGA1129
error · expected , between {previous} and {next}
Names in resident, group and panes are separated by commas. The tool takes
both names anyway, so nothing else is reported.
main.ngp
modules { "main.asm" "music.asm" }
resident { main music }
main.asm
.proc entry
rts
.endp
music.asm
.proc play
rts
.endp
error[NGA1129]: expected `,` between `main` and `music`
--> main.ngp:2:17
|
2 | resident { main music }
| ^^^^^
In the needs of a phase block, the second name is read as the next entry of
the block instead, and the finding is NGA1126.
NGA1130
error · project refers to phase {phase}, which is not declared
A then, or the entry of the document, names a Phase that no phase block
declares. The name may be misspelt, or the Phase renamed. Declare the Phase or
correct the name.
main.ngp
modules { "main.asm" }
phase title { needs main then game }
entry title
main.asm
.proc entry
rts
.endp
error[NGA1130]: project refers to phase `game`, which is not declared
--> main.ngp:3:32
|
3 | phase title { needs main then game }
| ^^^^
A name in needs or resident that names no Module and no group is
NGA1101 instead.
NGA1131
error · the entry phase is set more than once
The Phase the program starts in is named once in the whole Project, counting
every file an include reaches. A second entry is refused even when it names
the same Phase, because otherwise the start would depend on which file is read
first.
main.ngp
modules { "main.asm" }
phase game { needs main }
entry game
entry game
main.asm
.proc entry
rts
.endp
error[NGA1131]: the entry phase is set more than once
--> main.ngp:5:7
|
5 | entry game
| ^^^^
note: the entry phase was already set here
--> main.ngp:4:7
|
4 | entry game
| ^^^^
Keep the entry in the Project file and out of the files it includes.
NGA1132
note · the entry phase was already set here
Follows NGA1131 and points at the first entry.
NGA1133
error · this project declares phases and no entry
A Project with phase blocks says which Phase the program starts in, with
entry NAME at the top level of the document. An entry inside a phase
block does not count: it names the Label that Phase starts at.
main.ngp
modules { "main.asm" }
phase game { needs main }
main.asm
.proc entry
rts
.endp
error[NGA1133]: this project declares phases and no `entry`
Add entry game. A Project with no phase block has one Phase and needs no
entry; see the Project file.
NGA1134
warning · module {module} is in no phase, so it is never in memory
In a Project with phase blocks, a Module is in memory in the Phases whose
needs name it, directly or through a group, and in every Phase if resident
names it. Nothing names this one. The build goes on without it.
main.ngp
modules { "main.asm" "tools.asm" }
phase game { needs main }
entry game
main.asm
.proc entry
rts
.endp
tools.asm
.proc dump
rts
.endp
warning[NGA1134]: module `tools` is in no phase, so it is never in memory
--> main.ngp:1:23
|
1 | modules { "main.asm" "tools.asm" }
| ^^^^^^^^^^^
Name the Module in the needs of the Phases that use it, or in resident, or
take it out of modules. A Module that only the load block needs is not
reported.
NGA1135
error · expected region, register, holder, units, window, containers or cpu, found {token}
A target block holds region, register, holder, units, window,
containers and cpu. The tool reports the first word it does not know and
skips to the next one it does.
main.ngp
modules { "main.asm" }
target { container xex }
main.asm
.proc entry
rts
.endp
error[NGA1135]: expected `region`, `register`, `holder`, `units`, `window`, `containers` or `cpu`, found `container`
--> main.ngp:3:10
|
3 | target { container xex }
| ^^^^^^^^^
container stands at the top level of the Project and names what the tool
builds. containers, in a target block, says what the machine takes. This
finding also follows an entry that broke in the middle, whose remaining words
are read as entries of their own, as in NGA1139.
NGA1136
error · expected a value after {after}
A word that takes a value has none after it: a register without its address,
units NAME without its count, a size with nothing after it, or a .. that
ends before the second address. Write the number.
main.ngp
modules { "main.asm" }
target { register COLBK }
main.asm
.proc entry
rts
.endp
error[NGA1136]: expected a value after `COLBK`
--> main.ngp:3:19
|
3 | target { register COLBK }
| ^^^^^
NGA1137
error · a value here is written out, and {name} names nothing
The Project has no Symbols, so a name means nothing in a value of the Project
file. That includes a Constant of its own constants block and a register
declared beside it. Constants are for the Modules, which read them in source.
Write the number out.
main.ngp
constants { GTIA = $D000 }
modules { "main.asm" }
target { register COLBK GTIA + $1A }
main.asm
.proc entry
rts
.endp
error[NGA1137]: a value here is written out, and `GTIA` names nothing
--> main.ngp:5:25
|
5 | target { register COLBK GTIA + $1A }
| ^^^^
NGA1138
error · this does not come to a number
The value holds no name and still does not come to a number. Usually it is
quoted. The Project file quotes paths and the name of a processor, but a number
is written bare: $D01A, not "$D01A". A division by zero ends here too.
main.ngp
modules { "main.asm" }
target { register COLBK "$D01A" }
main.asm
.proc entry
rts
.endp
error[NGA1138]: this does not come to a number
--> main.ngp:3:25
|
3 | target { register COLBK "$D01A" }
| ^^^^^^^
NGA1139
error · a range is written start .. end
A region, a window and a unit set's linear take a range: two values with
.. between them, both ends inclusive. A - between the two makes one value
of them, their difference, and the .. is then missing.
main.ngp
modules { "main.asm" }
target { region $2000-$9FFF ram }
main.asm
.proc entry
rts
.endp
error[NGA1139]: a range is written `start .. end`
--> main.ngp:3:10
|
3 | target { region $2000-$9FFF ram }
| ^^^^^^
error[NGA1135]: expected `region`, `register`, `holder`, `units`, `window`, `containers` or `cpu`, found `ram`
--> main.ngp:3:29
|
3 | target { region $2000-$9FFF ram }
| ^^^
The words after the broken range are read as entries of the block, which is the
NGA1135 after it. Write region $2000 .. $9FFF ram.
NGA1140
note · the container was already set here
Follows NGA1109 and points at the first container.
NGA1141
error · this machine does not take the container {name}; it takes {taken}
The Project's container names a Container that the Target's containers
entry leaves out. A machine variant says there what its machine can load: the
library's atari/130xe.ngp takes xex alone, and atari/800xl.ngp takes xex
or atr.
main.ngp
target { containers xex }
container atr
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1141]: this machine does not take the container `atr`; it takes `xex`
--> main.ngp:3:11
|
3 | container atr
| ^^^
note: the machine says what it takes here
--> main.ngp:1:10
|
1 | target { containers xex }
| ^^^^^^^^^^
Name a Container the machine takes, or include the variant of another machine.
Not raised where the Project names no container, nor where no Target says
what it takes.
NGA1142
note · the machine says what it takes here
Follows NGA1141 and points at the containers entry of the
Target, usually in the machine variant the Project includes.
NGA1143
error · {name} is not what a program is optimised for; the words are {known}
fast and small are not among the words. A Project without optimize gets
fit. What each word prefers is in
the Project file.
main.ngp
modules { "main.asm" }
optimize fast
main.asm
.proc entry
rts
.endp
error[NGA1143]: `fast` is not what a program is optimised for; the words are `speed`, `size` and `fit`
--> main.ngp:3:10
|
3 | optimize fast
| ^^^^
NGA1144
error · what the program is optimised for is set more than once
optimize is said once in the whole Project, counting every file an include
reaches. A second one is refused even when it says the same word.
main.ngp
modules { "main.asm" }
optimize speed
optimize size
main.asm
.proc entry
rts
.endp
error[NGA1144]: what the program is optimised for is set more than once
--> main.ngp:4:10
|
4 | optimize size
| ^^^^
note: it was already set here
--> main.ngp:3:10
|
3 | optimize speed
| ^^^^^
Keep it in the Project file and out of the files it includes.
NGA1145
note · it was already set here
Follows NGA1144 and points at the first optimize.
NGA1146
error · {name} names no processor; the words are {known}
The words are lowercase, so "65SC02" is refused as well. A 65C02 has every
instruction of the 65SC02, so a machine with one is written "65sc02".
Neither word allows the Rockwell bit instructions, wai or stp; see
cpu.
main.ngp
modules { "main.asm" }
target { cpu "65c02" }
main.asm
.proc entry
rts
.endp
error[NGA1146]: `65c02` names no processor; the words are `6502` and `65sc02`
--> main.ngp:3:14
|
3 | target { cpu "65c02" }
| ^^^^^^^
NGA1147
error · the entry of phase {phase} is set more than once
entry inside a phase block names the Label the Phase starts at, and a Phase
has one. Two phase blocks of one name sum, so a second entry is refused even
in another block, or in another file.
main.ngp
modules { "main.asm" }
phase game { needs main entry start }
phase game { entry restart }
entry game
main.asm
.proc entry
rts
.endp
error[NGA1147]: the entry of phase `game` is set more than once
--> main.ngp:4:20
|
4 | phase game { entry restart }
| ^^^^^^^
note: it was set here
--> main.ngp:3:32
|
3 | phase game { needs main entry start }
| ^^^^^
Keep one of them.
NGA1148
note · it was set here
Follows NGA1147 and points at the first entry of that Phase.
NGA1149
error · the processor is set more than once
cpu is said once in the whole Project, and a machine variant says it: every
variant in the library does. A Project that includes a variant cannot change
its processor.
machine.ngp
target { cpu "6502" }
main.ngp
include "machine.ngp"
target { cpu "65sc02" }
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1149]: the processor is set more than once
--> main.ngp:3:14
|
3 | target { cpu "65sc02" }
| ^^^^^^^^
note: the processor was already set here
--> machine.ngp:1:10
|
1 | target { cpu "6502" }
| ^^^
For another processor, write a variant of your own and include that one.
NGA1150
error · transform is followed by the transform's name, found {token}
The word after transform is the format the listed Sections are encoded in,
such as zx0 or rle. It is also the name of the decoder a Module declares
with .transform. Write it before the brace: transform zx0 { main.tiles }. A
body without a name is skipped whole.
main.ngp
modules { "main.asm" }
transform { main.tiles }
main.asm
.proc entry
rts
.endp
error[NGA1150]: `transform` is followed by the transform's name, found `{`
--> main.ngp:3:1
|
3 | transform { main.tiles }
| ^^^^^^^^^
NGA1151
error · a transform entry names a section as module.section, found {token}
A transform applies to Sections, not to Modules. A Section has no name of its
own, so an entry names it by one of its Labels, after the Module's name and a
dot: main.tiles, or main.space.tiles for a Label in a Namespace. Any Label
of the Section will do, exported or not.
main.ngp
modules { "main.asm" }
transform zx0 { main }
main.asm
.proc entry
rts
.endp
error[NGA1151]: a transform entry names a section as `module.section`, found `}`
--> main.ngp:3:17
|
3 | transform zx0 { main }
| ^^^^
The found part of the message is what stood after the Module's name, here the
closing brace.
NGA1152
note · the processor was already set here
Follows NGA1149 and points at the first cpu, usually in the
machine variant the Project includes.
NGA1155
error · a region's range is followed by ram, rom, register or reserved, not by {token}
A region ends with its property, and here the range is followed by something
else, usually the closing brace. The property is ram, rom, register or
reserved; see region. The finding points at
region, since what follows the range is often on the next line.
main.ngp
modules { "main.asm" }
target { region $2000 .. $9FFF }
main.asm
.proc entry
rts
.endp
error[NGA1155]: a region's range is followed by `ram`, `rom`, `register` or `reserved`, not by `}`
--> main.ngp:3:10
|
3 | target { region $2000 .. $9FFF }
| ^^^^^^
NGA1156
error · {word} is not a region property; write ram, rom, register or reserved
readonly is an attribute of a .section. The Region where such Sections go on
a cartridge is rom. A Region's name goes before its range, as in region io $D000 .. $D7FF register, so a name written after the range is read as the
property and is reported here as well.
main.ngp
modules { "main.asm" }
target { region cart $A000 .. $BFFF readonly }
main.asm
.proc entry
rts
.endp
error[NGA1156]: `readonly` is not a region property; write `ram`, `rom`, `register` or `reserved`
--> main.ngp:3:37
|
3 | target { region cart $A000 .. $BFFF readonly }
| ^^^^^^^^
NGA1157
error · a region runs from a lower address to a higher one inside the address space, and this one does not
Both ends of a Region are inclusive: the end is the last address in it. A Region
that reaches the top of memory ends at $FFFF, not at $10000. The start must
not be above the end either.
main.ngp
modules { "main.asm" }
target { region $E000 .. $10000 ram }
main.asm
.proc entry
rts
.endp
error[NGA1157]: a region runs from a lower address to a higher one inside the address space, and this one does not
--> main.ngp:3:10
|
3 | target { region $E000 .. $10000 ram }
| ^^^^^^
NGA1158
error · a region named {name} is already declared
A named Region gives every Module a Symbol, so one name stands for one Region.
This includes the Regions that register declares and those of an included
variant. A second declaration is refused even when it is the same.
main.ngp
modules { "main.asm" }
target {
region ram $0080 .. $00FF ram
region ram $2000 .. $9FFF ram
}
main.asm
.proc entry
rts
.endp
error[NGA1158]: a region named `ram` is already declared
--> main.ngp:5:10
|
5 | region ram $2000 .. $9FFF ram
| ^^^
note: `ram` was declared here
--> main.ngp:4:10
|
4 | region ram $0080 .. $00FF ram
| ^^^
Give the two Regions two names, or none. A Project that narrows a Region of its
variant leaves its own unnamed: atari/130xe.ngp names dos, so a Project
that includes it and reserves more for its DOS writes
region $0700 .. $2FFF reserved. A name a unit set or a Window already has is
NGA1180.
NGA1159
note · {name} was declared here
Follows NGA1158 and points at the first declaration of the name,
which may be in an included variant.
NGA1160
error · a register lies inside the address space, and its last byte would be at {value:hex}
Every byte of a register lies in the 64 KB address space. The address is
above $FFFF or below zero, or it is $FFFF with a width of two, whose second
byte would be past the end.
main.ngp
modules { "main.asm" }
target { register COLBK $D01A0 }
main.asm
.proc entry
rts
.endp
error[NGA1160]: a register lies inside the address space, and its last byte would be at $0D01A0
--> main.ngp:3:25
|
3 | target { register COLBK $D01A0 }
| ^^^^^^
NGA1161
error · a register is one or two bytes, and {width} is neither
A register entry declares one byte, or two with , 2 after the address. A
wider block of hardware is a Region with the property register:
region io $D000 .. $D7FF register.
main.ngp
modules { "main.asm" }
target { register AUDF1 $D200, 4 }
main.asm
.proc entry
rts
.endp
error[NGA1161]: a register is one or two bytes, and 4 is neither
--> main.ngp:3:32
|
3 | target { register AUDF1 $D200, 4 }
| ^
NGA1163
note · the {kind} {region} is declared here
Follows a finding about a Region and points at the line of the target block
that declares it: a pin into a register Region (NGA5217), a
reserved one (NGA5218) or a rom one (NGA5233),
a foreign Section with bytes over one (NGA5253), a Module that
defines a name the Project declares (NGA2272), or a cartridge
whose ROM does not match the machine's rom Region (NGA1219).
It names what it points at: a Region, a register, a unit set, a Window or a
Pane.
NGA1164
error · expected units or size, found {token}
A storage block holds units and size, and nothing else:
storage { units 720 size 128 } for units known by their numbers, and
storage { units extension } for the Banks of a unit set. The tool reports the
first word it does not know and skips to the next one it does.
main.ngp
modules { "main.asm" }
storage { count 720 size 128 }
main.asm
.proc entry
rts
.endp
error[NGA1164]: expected `units` or `size`, found `count`
--> main.ngp:3:11
|
3 | storage { count 720 size 128 }
| ^^^^^
NGA1165
error · storage has units by count and no size, and a unit holds something
units with a number declares units known by their numbers, such as the
sectors of a diskette, and nothing else says how many bytes each one holds. Add
size, in this block or in another storage block of the Project:
storage { units 720 size 128 }.
main.ngp
modules { "main.asm" }
storage { units 720 }
main.asm
.proc entry
rts
.endp
error[NGA1165]: storage has units by count and no `size`, and a unit holds something
--> main.ngp:3:11
|
3 | storage { units 720 }
| ^^^^^
Units that are the Banks of a unit set, units extension, take their size from
the Window that shows the set and need no size.
NGA1166
error · the size of a unit is set more than once
size is said once in the whole Project, counting every storage block and
every file an include reaches. A second one is refused even when it gives the
same number.
main.ngp
modules { "main.asm" }
storage { units 720 size 128 }
storage { size 256 }
main.asm
.proc entry
rts
.endp
error[NGA1166]: the size of a unit is set more than once
--> main.ngp:4:11
|
4 | storage { size 256 }
| ^^^^
note: it was set here
--> main.ngp:3:22
|
3 | storage { units 720 size 128 }
| ^^^^
A Project that includes a storage file of the library, such as
atari/disk.ngp, and has a storage block of its own meets this. Use one or
the other.
NGA1167
note · it was set here
Follows NGA1166 and points at the first size.
NGA1168
error · the units are declared more than once; units names a set of the target or counts them
Storage has one kind of unit: the Banks of a unit set, units extension, or
units known by their numbers, units 720. units is said once in the whole
Project, in either form, and a second one is refused even when it says the same.
main.ngp
modules { "main.asm" }
storage { units 720 size 128 }
storage { units 1040 }
main.asm
.proc entry
rts
.endp
error[NGA1168]: the units are declared more than once; `units` names a set of the target or counts them
--> main.ngp:4:11
|
4 | storage { units 1040 }
| ^^^^^
note: they were declared here
--> main.ngp:3:11
|
3 | storage { units 720 size 128 }
| ^^^^^
As with NGA1166, a storage file of the library included beside a
storage block of the Project's own meets this. Use one or the other.
NGA1169
note · they were declared here
Follows NGA1168 and points at the first units.
NGA1170
error · {count} units, and a unit is named in two bytes
Raised for units in a target block, which declares a unit set, and in a
storage block, which counts units by number. The count is at most 65536,
because a unit's number is written in no more than two bytes: in a Frame, in
the table of a .transition and in the driver's cell.
main.ngp
storage { units 131072 size 512 }
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1170]: 131072 units, and a unit is named in two bytes
--> main.ngp:1:17
|
1 | storage { units 131072 size 512 }
| ^^^^^^
Declare the units the program can use rather than every unit the medium has. For storage the count is a ceiling, not a reservation: the image holds only what its Payloads come to.
NGA1171
error · a unit holds between one byte and the address space, and {value:hex} is neither
size in a storage block is what one unit holds, such as one sector. It is
between 1 and 65536 bytes. The storage is units × size bytes, so size is
not the size of the whole medium.
main.ngp
storage { units 720 size 720 * 128 }
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1171]: a unit holds between one byte and the address space, and $016800 is neither
--> main.ngp:1:27
|
1 | storage { units 720 size 720 * 128 }
| ^^^^^^^^^
A diskette of 720 sectors of 128 bytes is units 720 size 128.
NGA1172
error · {name} names a group and a module, and a name in a list has to mean one thing
A named modules block is a group, and a group's name stands in the same
lists as a Module's: needs, resident and load. One name for both would
mean two things there. It usually happens when a named block holds a file of
the same stem.
main.ngp
modules { "main.asm" }
modules sfx { "sfx.asm" }
main.asm
.proc entry
rts
.endp
sfx.asm
.section
beep .byte 1, 2, 3
.ends
error[NGA1172]: `sfx` names a group and a module, and a name in a list has to mean one thing
--> main.ngp:2:9
|
2 | modules sfx { "sfx.asm" }
| ^^^
note: the module `sfx` is declared here
--> main.ngp:2:15
|
2 | modules sfx { "sfx.asm" }
| ^^^^^^^^^
Rename the group, or give the Module another name with as.
NGA1173
note · the module {name} is declared here
Follows NGA1172 or NGA1102 and points at the entry
that gives the Module its name.
NGA1174
error · group {group} reaches itself here, so listing it would never end
A group may name other groups to any depth, but it may not reach itself through
them. The tool expands a group where a needs, resident or load list names
it, and reports the cycle at the name that closes it.
main.ngp
modules { "main.asm" }
group game { main, hud }
group hud { game }
phase play { needs game }
entry play
main.asm
.proc entry
rts
.endp
error[NGA1174]: group `game` reaches itself here, so listing it would never end
--> main.ngp:3:14
|
3 | group hud { game }
| ^^^^
Take out one of the names that close the cycle, here game in hud.
NGA1175
warning · group {group} holds no module, so naming it adds nothing
A needs, resident or load list names a group that holds no Module: a
named modules block with nothing in it, or a group whose members are all
empty groups. A group that no list names is not reported.
main.ngp
modules { "main.asm" }
modules sfx {
; "sfx/beep.asm"
}
phase play { needs main, sfx }
entry play
main.asm
.proc entry
rts
.endp
warning[NGA1175]: group `sfx` holds no module, so naming it adds nothing
--> main.ngp:2:9
|
2 | modules sfx {
| ^^^
Fill the group, or take its name out of the list.
NGA1176
error · {name} is a group, and one module is expected here
A transform entry names a Section as module.label, and without names one
ROM Module. Neither takes a group.
main.ngp
modules { "main.asm" }
modules art { "tiles.asm" }
transform rle { art.tiles }
main.asm
.proc entry
rts
.endp
tiles.asm
.section
tiles .byte 1, 2, 3
.ends
error[NGA1176]: `art` is a group, and one module is expected here
--> main.ngp:4:17
|
4 | transform rle { art.tiles }
| ^^^
Name the Module that holds the Section. It is named after the file's stem, so
here the entry is tiles.tiles.
NGA1177
error · a group entry names a module or a group, found {token}
A group block lists the names of Modules and of other groups, separated by
commas. It takes no path. A file joins a group through a named modules block,
which declares the Module and the group at once.
main.ngp
modules { "main.asm" }
group sfx { "beep.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1177]: a group entry names a module or a group, found `"beep.asm"`
--> main.ngp:2:13
|
2 | group sfx { "beep.asm" }
| ^^^^^^^^^^
Here that is modules sfx { "beep.asm" }.
NGA1178
error · group is followed by the group's name, found {token}
The tool skips the body of a group with no name, so nothing in it is
grouped.
main.ngp
modules { "main.asm" }
group { main }
main.asm
.proc entry
rts
.endp
error[NGA1178]: `group` is followed by the group's name, found `{`
--> main.ngp:2:1
|
2 | group { main }
| ^^^^^
Name it, as in group play { main }.
NGA1179
error · a window lists what it shows after views, found {token}
A window in a target block gives its name, its address ranges separated by
commas, and then views and the states it can show: unit sets, or named
states of the hardware. Here views and the states are missing.
main.ngp
target {
units extension 4
window ext $4000 .. $7FFF
}
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1179]: a window lists what it shows after `views`, found `}`
--> main.ngp:3:3
|
3 | window ext $4000 .. $7FFF
| ^^^^^^
Write window ext $4000 .. $7FFF views extension.
NGA1180
error · {name} already names a {kind} of the target
Regions, unit sets, Windows and Panes share one name space, because each name
is a Symbol every Module sees. Two Regions of one name are
NGA1158 instead.
main.ngp
include "atari/130xe.ngp"
target { region screen $3C00 .. $3FFF reserved }
modules { "main.asm" }
panes in ext { screen }
main.asm
.proc entry
rts
.endp
error[NGA1180]: `screen` already names a region of the target
--> main.ngp:7:16
|
7 | panes in ext { screen }
| ^^^^^^
note: it was declared here
--> main.ngp:3:17
|
3 | target { region screen $3C00 .. $3FFF reserved }
| ^^^^^^
Rename one of the two. Where the first is declared in a machine variant, rename the one in the Project.
NGA1181
note · it was declared here
Follows NGA1180 and points at the first declaration of the name,
which may be in a machine variant the Project includes.
NGA1182
error · a window's range runs from a lower address to a higher one inside the address space, and this one does not
Each range of a window runs from a lower address to a higher one, both ends
inclusive and both inside $0000-$FFFF. The finding stands at window,
whichever of its ranges is wrong.
main.ngp
target {
units extension 4
window ext $C000 .. $10000 views extension
}
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1182]: a window's range runs from a lower address to a higher one inside the address space, and this one does not
--> main.ngp:3:3
|
3 | window ext $C000 .. $10000 views extension
| ^^^^^^
The usual cause is an end written as the start plus the size. The end is the
last address of the range: $C000 .. $FFFF.
NGA1183
error · {state} is listed more than once among what {window} shows
Each name after views is a state the Window can show, and each is listed
once. The tool numbers the states in the order they are written, and the driver
receives a state by that number.
main.ngp
target {
window blit $4000 .. $7FFF views sprites, palette, sprites
}
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1183]: `sprites` is listed more than once among what `blit` shows
--> main.ngp:2:55
|
2 | window blit $4000 .. $7FFF views sprites, palette, sprites
| ^^^^^^^
Remove the second sprites.
NGA1185
error · {name} is not a unit set of the target
storage { units NAME } takes the Banks of a unit set the Target declares with
units. A usual mistake is the name of the Window that shows the set, as here.
Another is atari/extension.ngp included beside a machine that has no
extension set, such as atari/800xl.ngp: it is the 130XE's storage.
main.ngp
include "atari/130xe.ngp"
storage { units ext }
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1185]: `ext` is not a unit set of the target
--> main.ngp:3:17
|
3 | storage { units ext }
| ^^^
Name the set: storage { units extension }.
NGA1186
error · no window shows {name}, so what one of its units holds is unknown
A unit set used as storage takes the size of its unit from the Window that
shows the set. No window of the Target lists this set after views, so
there is no size.
main.ngp
target { units extension 4 }
storage { units extension }
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1186]: no window shows `extension`, so what one of its units holds is unknown
--> main.ngp:3:17
|
3 | storage { units extension }
| ^^^^^^^^^
Declare the Window that shows the set, as in
window ext $4000 .. $7FFF views extension. Storage that the CPU never sees
through a Window, such as a diskette, is counted instead:
storage { units 720 size 128 }.
NGA1187
error · windows {window} and {other} both show {name} and differ in size, so a unit has no one size
A unit of a set is as large as the Window that shows it. Raised where storage
names a set that two Windows of different sizes show, so that a unit would have
two sizes.
main.ngp
target {
units extension 4
window ext $4000 .. $7FFF views extension
window high $8000 .. $9FFF views extension
}
storage { units extension }
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1187]: windows `high` and `ext` both show `extension` and differ in size, so a unit has no one size
--> main.ngp:4:3
|
4 | window high $8000 .. $9FFF views extension
| ^^^^^^
Make the two Windows the same size, or take the set out of one Window's
views.
NGA1188
error · storage names a unit set, and what a unit holds is its window's size
With units NAME, a unit is a Bank, and its size is the size of the Window
that shows the set. size goes only with units N, the units known by
number.
main.ngp
include "atari/130xe.ngp"
storage { units extension size $4000 }
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1188]: storage names a unit set, and what a unit holds is its window's size
--> main.ngp:3:28
|
3 | storage { units extension size $4000 }
| ^^^^
Delete size.
NGA1189
error · a unit set holds at least one unit
units NAME N in a target block declares the N Banks of a unit set.
main.ngp
target { units extension 0 }
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1189]: a unit set holds at least one unit
--> main.ngp:1:26
|
1 | target { units extension 0 }
| ^
Where the machine has no such memory, leave out the units line and every
window that shows the set.
NGA1190
error · panes is followed by in and a window, found {token}
A panes block opens with in and the Window its Panes are in, then
= STATE where they are pinned, then the body: panes in ext { level }. The
tool skips the body of a block whose header it cannot read.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes ext { level }
main.asm
.proc entry
rts
.endp
error[NGA1190]: `panes` is followed by `in` and a window, found `ext`
--> main.ngp:5:1
|
5 | panes ext { level }
| ^^^^^
Here in is missing.
NGA1191
error · {name} is not a window of the target
The name after panes in is a Window the Target declares with window. The
usual mistake is the name of the unit set the Window shows: on the 130XE the
Window is ext and the set is extension.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in extension { level }
main.asm
.proc entry
rts
.endp
error[NGA1191]: `extension` is not a window of the target
--> main.ngp:5:10
|
5 | panes in extension { level }
| ^^^^^^^^^
Write panes in ext { level }.
NGA1192
error · {state} is not a named state of window {window}
= STATE pins the block's Panes to a named state of the Window: a name in its
views that is not a unit set. A unit set is a run of Banks, and the solver
picks the Bank.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in ext = extension { level }
main.asm
.proc entry
rts
.endp
error[NGA1192]: `extension` is not a named state of window `ext`
--> main.ngp:5:16
|
5 | panes in ext = extension { level }
| ^^^^^^^^^
To put a Pane in a Bank, leave out = STATE: panes in ext { level }. See
Panes.
NGA1193
error · a family holds between 1 and 255 panes, and {count} is neither
NAME[N] declares a family of N Panes on consecutive Banks, and N is between 1
and 255, because a member is chosen by an index in a byte.
main.ngp
include "atari/mariacel.ngp"
modules { "main.asm" }
panes in cel8000 { frames[300] }
main.asm
.proc entry
rts
.endp
error[NGA1193]: a family holds between 1 and 255 panes, and 300 is neither
--> main.ngp:5:27
|
5 | panes in cel8000 { frames[300] }
| ^^^
Declare two families instead, such as framesA[150], framesB[150].
NGA1194
error · window {window} shows no unit set, so a pane in it is pinned to a named state: write = STATE
A Window that shows no unit set has only named states, so the solver has no Bank to give a Pane there.
main.ngp
include "atari/mariacel.ngp"
modules { "main.asm" }
panes in cel4000 { strips }
main.asm
.proc entry
rts
.endp
error[NGA1194]: window `cel4000` shows no unit set, so a pane in it is pinned to a named state: write `= STATE`
--> main.ngp:5:1
|
5 | panes in cel4000 { strips }
| ^^^^^
On MariaCEL, cel4000 shows the blitter's blocks, so this is
panes in cel4000 = strip { strips }.
NGA1195
error · a family takes consecutive banks, and {pane} is pinned to one state
A family is N Panes on consecutive Banks. A header with = STATE gives each of
its Panes one named state, which is a single state and not a run of Banks.
main.ngp
include "atari/mariacel.ngp"
modules { "main.asm" }
panes in cel4000 = strip { strips[2] }
main.asm
.proc entry
rts
.endp
error[NGA1195]: a family takes consecutive banks, and `strips` is pinned to one state
--> main.ngp:5:28
|
5 | panes in cel4000 = strip { strips[2] }
| ^^^^^^
Drop the [2], or declare the family in a Window that shows a unit set, where
the solver gives it its Banks.
NGA1196
error · expected a pane's name, found {token}
The body of a panes block is a list of names separated by commas, each
followed by [N] where it declares a family. Raised for anything else there,
such as a comma before the closing brace, a quoted name, or a count that ]
does not close. Two names with no comma between them are
NGA1129.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in ext { level, title, }
main.asm
.proc entry
rts
.endp
error[NGA1196]: expected a pane's name, found `}`
--> main.ngp:5:30
|
5 | panes in ext { level, title, }
| ^
Delete the last comma.
NGA1197
error · phase {phase} is final, and then leads out of it
final marks a Phase the program never leaves. The tool then keeps out of it
what only leaving or returning needs. A then in the same Phase says the
program does leave it. See phase.
main.ngp
modules { "title.asm" "game.asm" }
phase title { needs title entry titleStart then game }
phase game { needs game entry gameStart then title final }
entry title
title.asm
.proc titleStart
.transition game
.endp
game.asm
.proc gameStart
@loop jmp @loop
.endp
error[NGA1197]: phase `game` is final, and `then` leads out of it
--> main.ngp:4:58
|
4 | phase game { needs game entry gameStart then title final }
| ^^^^^
Drop then title if the game never goes back to the title, or drop final if
it does. The entry of a final Phase must not return either, which is
NGA4613.
NGA1198
error · load describes how a .xex loads, and this project's container is {container}
A load block says what the machine holds while a DOS loads a .xex, and
which code of the program runs during the load through INITAD. No other
Container is loaded by a DOS that calls INITAD.
main.ngp
include "atari/800xl.ngp"
modules { "main.asm" "fade.asm" }
load { needs fade init fadeStart }
phase main { needs main }
entry main
container atr
main.asm
.proc entry
rts
.endp
fade.asm
.proc fadeStart
rts
.endp
error[NGA1198]: `load` describes how a `.xex` loads, and this project's container is `atr`
--> main.ngp:5:1
|
5 | load { needs fade init fadeStart }
| ^^^^
Remove the load block, or build a .xex with container xex. See
load.
NGA1199
error · expected needs or init, found {token}
A load block holds two kinds of entry: needs and a list of Modules, and
init and a Label to call. Where the program starts is the entry Phase's
entry, not a word of load.
main.ngp
include "atari/800xl.ngp"
modules { "main.asm" "fade.asm" }
load { needs fade run fadeStart }
phase main { needs main }
entry main
container xex
main.asm
.proc entry
rts
.endp
fade.asm
.proc fadeStart
rts
.endp
error[NGA1199]: expected `needs` or `init`, found `run`
--> main.ngp:5:21
|
5 | load { needs fade run fadeStart }
| ^^^
To call fadeStart while the file loads, write init fadeStart.
NGA1203
error · {name} is no generator; the generators are binary and script
The modules block knows two generators: binary, which takes a file's bytes
as they are, and script, which runs JavaScript. Any other name before ( is
refused.
main.ngp
modules {
"main.asm"
png( "gfx/title.png" ) as title
}
main.asm
.proc entry
rts
.endp
error[NGA1203]: `png` is no generator; the generators are `binary` and `script`
--> main.ngp:3:3
|
3 | png( "gfx/title.png" ) as title
| ^^^
For a file in another format, convert it to raw bytes with a tool of your own
and read it with binary, or write a script that decodes the bytes
nga.read returns. See Generators.
NGA1204
error · {name} is no argument of this generator
binary takes the file and the attributes a .section takes: section,
namespace, placement, at, align, within, in, root, temporary
and readonly. A script hands every argument to the script, so a script
call does not raise this.
main.ngp
modules {
"main.asm"
binary( "gfx/font.bin", label = font )
}
main.asm
.proc entry
rts
.endp
error[NGA1204]: `label` is no argument of this generator
--> main.ngp:3:27
|
3 | binary( "gfx/font.bin", label = font )
| ^^^^^^^^^^^^
The Label at the start of the Section is section = font.
NGA1205
error · this argument is given more than once
A generator takes each argument once. The one exception is in of binary,
which may name several Regions. A second quoted path is the file given twice: a
call works from one file. A script is held to the same rule, since it would
see only the last value under a name and only the first path.
main.ngp
modules {
"main.asm"
binary( "gfx/font.bin", "gfx/font2.bin" ) as font
}
main.asm
.proc entry
rts
.endp
error[NGA1205]: this argument is given more than once
--> main.ngp:3:27
|
3 | binary( "gfx/font.bin", "gfx/font2.bin" ) as font
| ^^^^^^^^^^^^^^^
Write one call per file, and each becomes a Module with a Section of its own.
To keep the bytes of both files in one Section, read them with nga.read in a
script.
NGA1206
error · {name} takes {wanted}, and this is {given}
Each argument of binary takes one kind of value. section, namespace and
in take a name, written bare. at, align and within take a number.
placement takes absolute or zeropage. root, temporary and readonly
take no value: the name alone sets them.
main.ngp
modules {
"main.asm"
binary( "maps/level1.map", in = "level" ) as maps
}
main.asm
.proc entry
rts
.endp
error[NGA1206]: `in` takes a name, and this is a quoted literal
--> main.ngp:3:30
|
3 | binary( "maps/level1.map", in = "level" ) as maps
| ^^^^^^^^^^^^
Only the path is quoted. Write in = level.
NGA1207
error · {generator} is given the file it works from as a quoted path with no name before it
The file a generator works from is its one argument without a name, a quoted
path: the data for binary, the script for script.
main.ngp
modules {
"main.asm"
script( file = "tools/rows.js", width = 37 ) as rows
}
main.asm
.proc entry
rts
.endp
error[NGA1207]: `script` is given the file it works from as a quoted path with no name before it
--> main.ngp:3:3
|
3 | script( file = "tools/rows.js", width = 37 ) as rows
| ^^^^^^
Write the path alone: script( "tools/rows.js", width = 37 ). A bare word, as
in binary( font ), is a flag and not a path.
NGA1208
error · what {generator} produced cannot be emitted: {where}
What a generator returns is checked before it becomes the text of a Module. The text after the colon says where the fault is, as a path into what the script returned, and what is wrong there. See What a script returns.
main.ngp
modules {
"main.asm"
script( "tools/squares.js" ) as squares
}
main.asm
.proc entry
rts
.endp
tools/squares.js
export default () =>
{
const squares = [];
for ( let i = 0; i < 32; i++ )
{
squares.push( i * i );
}
return { sections: [ { name: "squares", items: [ squares ] } ] };
};
error[NGA1208]: what `script` produced cannot be emitted: sections[0].items[0][16]: not a byte
--> main.ngp:3:3
|
3 | script( "tools/squares.js" ) as squares
| ^^^^^^
An array of numbers is bytes, and 16 * 16 is not a byte. { words: squares }
writes two bytes for each. binary raises this too where its Module's name is
no name, since it names the Section after the Module: binary( "font-8x8.bin" )
needs as font or section = font.
NGA1209
error · a generator's arguments are closed by ), found {token}
The arguments of a generator call are separated by commas and closed by ).
The message names the first token after an argument that is neither.
main.ngp
modules {
"main.asm"
binary( "gfx/font.bin" align = 1024 ) as font
}
main.asm
.proc entry
rts
.endp
error[NGA1209]: a generator's arguments are closed by `)`, found `align`
--> main.ngp:3:3
|
3 | binary( "gfx/font.bin" align = 1024 ) as font
| ^^^^^^
Here the comma before align is missing. An unquoted path stops the call too,
at its first . or /: quote the path.
NGA1210
error · {path} failed: {message}
The script did not run to its end. It threw, it is not valid JavaScript, it has
no default export, or it used something the engine does not have. The text
after the colon is the engine's, with the line of the script. There is no
Date, no Math.random, no module to import, and no file access but
nga.read, which throws where the file is not there.
main.ngp
modules {
"main.asm"
script( "tools/noise.js" ) as noise
}
main.asm
.proc entry
rts
.endp
tools/noise.js
export default () =>
{
const noise = [];
for ( let i = 0; i < 16; i++ )
{
noise.push( Math.floor( Math.random() * 256 ) );
}
return { sections: [ { name: "noise", items: [ noise ] } ] };
};
error[NGA1210]: `tools/noise.js` failed: TypeError: not a function, at default (tools/noise.js:6:34)
--> main.ngp:3:3
|
3 | script( "tools/noise.js" ) as noise
| ^^^^^^
Math.random is undefined here, so calling it is not a function. There is no
random because a build must give the same bytes every time it runs. For a table
that looks random, write a seeded generator in the script. To refuse an input,
call nga.error rather than throw; that is NGA1212.
NGA1211
error · {path} did not finish within the work a generator is given
A script is stopped after a fixed amount of work, counted by the engine and not in seconds, so a slow machine stops it where a fast one does. The allowance is generous, and a script that reaches it almost always loops forever.
main.ngp
modules {
"main.asm"
script( "tools/pairs.js", count = 37 ) as pairs
}
main.asm
.proc entry
rts
.endp
tools/pairs.js
export default ( args ) =>
{
let pairs = 0;
for ( let left = args.count; left !== 0; left -= 2 )
{
pairs++;
}
return { sections: [ { name: "pairs", items: [ [ pairs ] ] } ] };
};
error[NGA1211]: `tools/pairs.js` did not finish within the work a generator is given
--> main.ngp:3:3
|
3 | script( "tools/pairs.js", count = 37 ) as pairs
| ^^^^^^
Here left steps over zero, because the count is odd. --verbose reports how
much of the allowance each script used.
NGA1212
error · {module}: {message}
The text after the colon comes from the generator, not from the tool. A script
that is given something it cannot use says so itself with nga.error, and
this is how it reaches the reader. The finding stands at the call in the
Project, and the note, NGA1214, points at the line of the script.
main.ngp
modules {
"main.asm"
script( "tools/rows.js", width = 48 ) as rows
}
main.asm
.proc entry
rts
.endp
tools/rows.js
export default ( args, nga ) =>
{
if ( args.width > 40 )
{
nga.error( `a row of ${ args.width } is wider than the screen` );
}
return { sections: [ { name: "row", items: [ { reserve: args.width } ] } ] };
};
error[NGA1212]: rows: a row of 48 is wider than the screen
--> main.ngp:3:3
|
3 | script( "tools/rows.js", width = 48 ) as rows
| ^^^^^^
note: the generator said so at tools/rows.js:5:29
Fix what the message names, usually an argument of the call or the file the
script reads. A script that throws raises NGA1210 instead.
NGA1213
warning · {module}: {message}
A script called nga.warn. The text after the colon is the script's own, the
note, NGA1214, points at its line, and the build goes on.
main.ngp
modules {
"main.asm"
script( "tools/tiles.js", count = 33 ) as tiles
}
main.asm
.proc entry
rts
.endp
tools/tiles.js
export default ( args, nga ) =>
{
if ( args.count > 32 )
{
nga.warn( `${ args.count } tiles, and a screen shows 32 at once` );
}
return { sections: [ { name: "tiles", items: [ { reserve: args.count * 8 } ] } ] };
};
warning[NGA1213]: tiles: 33 tiles, and a screen shows 32 at once
--> main.ngp:3:3
|
3 | script( "tools/tiles.js", count = 33 ) as tiles
| ^^^^^^
note: the generator said so at tools/tiles.js:5:19
Every script's warnings share this identifier, so --deny NGA1213 on the
command line makes all of them errors. The Project's diagnostics block does
not reach it, wherever the block stands: a script runs while the Project is
read, and the block takes effect after.
NGA1214
note · the generator said so at {where}
Follows NGA1212 or NGA1213 and points at the line
and column of the script where nga.error or nga.warn was called. The
finding itself stands at the call in the Project.
NGA1215
error · {name} names no set of facts; the sets are {sets}
--fact names the sets of facts --facts writes: diagnostics, project,
map, sources, tokens, symbols and bytes, or all, several of them
separated by commas. A name that is none of these is an error, and no empty set
is written for it. Without --fact, --facts writes diagnostics and
project.
NGA1216
error · the container {name} takes no board; only car, lnx and lyx name one
Only a cartridge Container takes a quoted board after its name: car on the
Atari, and lnx and lyx on the Lynx. Raised where a board follows any other
Container, such as one left behind when a Project moved from a .car to a
.xex.
main.ngp
container xex "8k"
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1216]: the container `xex` takes no board; only `car`, `lnx` and `lyx` name one
--> main.ngp:1:15
|
1 | container xex "8k"
| ^^^^
Delete the quoted word, or name the Container the board is for.
NGA1217
error · a .{name} is an image of one board and this says none; write container {name} "{example}", and the boards are {known}
A cartridge image is the image of one board. On the Atari the board decides how large the image is, where each bank stands in it, and which mapper number its header carries. On the Lynx it decides the size of a page. A Container of either kind without a board is refused rather than guessed at.
main.ngp
container car
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1217]: a `.car` is an image of one board and this says none; write `container car "8k"`, and the boards are `8k`, `16k`, `xegs32`, `xegs64`, `xegs128`, `xegs256`, `xegs512`, `xegs1024`
--> main.ngp:1:11
|
1 | container car
| ^^^
Write the board after the Container, in quotes: container car "xegs128".
The message lists the boards there are. On the Lynx they are "64k",
"128k", "256k" and "512k". See Cartridges.
NGA1218
error · {name} names no cartridge board; the boards are {known}
The quoted board names none the tool writes. The Atari's are "8k" and
"16k", which have no banks, and the XEGS boards from "xegs32" to
"xegs1024". The Lynx's are "64k", "128k", "256k" and "512k".
main.ngp
container car "128k"
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1218]: `128k` names no cartridge board; the boards are `8k`, `16k`, `xegs32`, `xegs64`, `xegs128`, `xegs256`, `xegs512`, `xegs1024`
--> main.ngp:1:15
|
1 | container car "128k"
| ^^^^^^
"128k" is a Lynx board. The 128 KB XEGS board is "xegs128". A mapper the
tool does not write, such as a MegaCart, has no name here;
Cartridges says why.
NGA1219
error · the board {name} is ROM at {range} and this machine has {found}
The board in container car and the memory the Target declares are checked
against each other. The board's fixed part, the ROM no switch takes away, must
be the Target's rom Region, at the same range. "8k" and the XEGS boards
are ROM at $A000-$BFFF, and "16k" at $8000-$BFFF. Also raised where the
Target has no rom Region at all.
main.ngp
target {
containers car
region $0080 .. $00FF ram
region $2000 .. $7FFF ram
region $A000 .. $BFFF rom
}
container car "16k"
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1219]: the board `16k` is ROM at $8000..$BFFF and this machine has $A000..$BFFF
--> main.ngp:8:15
|
8 | container car "16k"
| ^^^^^
note: the region `$A000..$BFFF` is declared here
--> main.ngp:5:3
|
5 | region $A000 .. $BFFF rom
| ^^^^^^
The tool derives neither from the other, so fix the one that is wrong: the
board's name, or the rom Region of the variant. The library's
atari/xegs128.ngp is the variant for "xegs128".
NGA1220
error · the board {name} switches banks into {range} and this machine declares no window of that one range
An XEGS board switches one bank at a time into $8000-$9FFF. The Target must
declare a Window of exactly that one range, which shows the board's banks as a
unit set. Raised where no window has that range.
main.ngp
target {
containers car
region $0080 .. $00FF ram
region $2000 .. $7FFF ram
region $A000 .. $BFFF rom
}
container car "xegs32"
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1220]: the board `xegs32` switches banks into $8000..$9FFF and this machine declares no window of that one range
--> main.ngp:8:15
|
8 | container car "xegs32"
| ^^^^^^^^
Declare the unit set and the Window in the variant, as atari/xegs128.ngp
does with units banks 15 and window switched $8000 .. $9FFF views banks.
NGA1221
error · the board {name} has {units:n} banks of storage and window {window} shows a set of {found:n}
The unit set the board's Window shows holds one Bank fewer than the board has banks. The last bank is the fixed part, which the CPU always sees, so it is not storage. A 128 KB XEGS board has sixteen banks and a set of fifteen; a 64 KB board has eight and a set of seven.
main.ngp
include "atari/xegs128.ngp"
container car "xegs64"
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1221]: the board `xegs64` has 7 banks of storage and window `switched` shows a set of 15
--> main.ngp:3:15
|
3 | container car "xegs64"
| ^^^^^^^^
Name the board the variant describes, or change the count in its units
line.
NGA1229
error · the board {name} has no banks for storage to stand in, and this machine declares storage
An 8 KB and a 16 KB cartridge have no banks. The image is the fixed part and nothing else, so there is nowhere for storage to be, and a unit written into the image would stand over the program. Raised where a Project names such a board and its machine declares storage.
main.ngp
container car "8k"
modules { "main.asm" }
target {
containers car
region zp $0080 .. $00FF ram
region ram $2000 .. $20FF ram
region cart $A000 .. $BFFF rom
holder cartinit
}
storage { units 4 size 8192 }
main.asm
.proc entry
rts
.endp
error[NGA1229]: the board `8k` has no banks for storage to stand in, and this machine declares storage
--> main.ngp:1:15
|
1 | container car "8k"
| ^^^^
Remove the storage block, or name a XEGS board, whose switched banks are
storage.
NGA1230
error · a cartridge's entry is a field and a value, and {token} is neither
The cartridge block fills the header of a .lnx. Each entry is a field and
its value, with nothing between them: name "Asteroids", rotation left.
Raised at a token that is neither, such as a number, or the = in
name = "Asteroids". What is left of the entry, the "Asteroids", is read
past, so the entry costs one finding.
main.ngp
include "lynx/lynx.ngp"
container lnx "64k"
cartridge {
rotation 1
}
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1230]: a cartridge's entry is a field and a value, and `1` is neither
--> main.ngp:6:12
|
6 | rotation 1
| ^
The header holds the rotation as a number, but the block takes the word for
it: none, left or right.
NGA1231
error · {field} is not something a cartridge's header holds; it holds name, manufacturer and rotation
The cartridge block sets three fields of the .lnx header: name,
manufacturer and rotation. The page size comes from the board in
container lnx, and the tool writes every other field itself, with a fixed
value.
main.ngp
include "lynx/lynx.ngp"
container lnx "64k"
cartridge {
name "Asteroids"
year "1990"
}
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1231]: `year` is not something a cartridge's header holds; it holds `name`, `manufacturer` and `rotation`
--> main.ngp:7:3
|
7 | year "1990"
| ^^^^
Delete the entry.
NGA1232
error · {field} takes a value of the kind its header field is: name and manufacturer a quoted string, rotation a word
name and manufacturer take a quoted string, and rotation takes a word.
Raised where the value is of the other kind: a name without quotes, or
rotation "left".
main.ngp
include "lynx/lynx.ngp"
container lnx "64k"
cartridge {
name Asteroids
}
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1232]: `name` takes a value of the kind its header field is: `name` and `manufacturer` a quoted string, `rotation` a word
--> main.ngp:6:8
|
6 | name Asteroids
| ^^^^^^^^^
Quote the name, or take the quotes off the rotation.
NGA1233
error · {field} holds {available:n} bytes and {given:n} were given; a reader writes a terminator over the last, so one more would be a name nobody chose
The header has 32 bytes for name and 16 for manufacturer. A reader writes
a terminator over the last byte, so the text may be 31 and 15 bytes long. The
tool refuses a longer one instead of cutting it. The count is of bytes, not
characters.
main.ngp
include "lynx/lynx.ngp"
container lnx "64k"
cartridge {
manufacturer "Atari Corporation, Sunnyvale"
}
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1233]: `manufacturer` holds 15 bytes and 28 were given; a reader writes a terminator over the last, so one more would be a name nobody chose
--> main.ngp:6:16
|
6 | manufacturer "Atari Corporation, Sunnyvale"
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Shorten the text.
NGA1234
error · {field} is given twice
name, manufacturer and rotation are each set once in the Project, and an
empty name counts as a name given. cartridge blocks sum, so this holds across
several blocks and every file an include reaches. A second value would depend
on which file is read first.
main.ngp
include "lynx/lynx.ngp"
container lnx "64k"
cartridge {
name "Asteroids"
name "Asteroids II"
}
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1234]: `name` is given twice
--> main.ngp:7:3
|
7 | name "Asteroids II"
| ^^^^
Keep one of them.
NGA1235
error · {name} is no rotation; a cartridge is held none, left or right
The rotation says how the Lynx is held for this program, so that a reader can
turn the picture: none, left or right. Raised for any other word.
main.ngp
include "lynx/lynx.ngp"
container lnx "64k"
cartridge {
rotation upright
}
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1235]: `upright` is no rotation; a cartridge is held `none`, `left` or `right`
--> main.ngp:6:12
|
6 | rotation upright
| ^^^^^^^
none is the usual way up, and is what a block without rotation writes.
NGA1236
error · a cartridge block says what a header shows, and the container {name} carries no header to show it in
The cartridge block fills the header of a .lnx, and is raised with any
other Container. A .lyx is the same image without the header, so a name
written for it would never be read.
main.ngp
include "lynx/lynx.ngp"
container lyx "64k"
cartridge {
name "Asteroids"
}
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1236]: a `cartridge` block says what a header shows, and the container `lyx` carries no header to show it in
--> main.ngp:5:1
|
5 | cartridge {
| ^^^^^^^^^
Write container lnx to get the header, or delete the block.
NGA1237
error · a {name} cartridge is 255 pages of {expected:n} bytes, page zero being the bootstrap's, and this machine's storage is {count:n} units of {size:n}
A Lynx cartridge has 256 pages, and the board in container lnx or
container lyx says how wide a page is: 256, 512, 1024 or 2048 bytes. Page
zero is the bootstrap's, so storage is 255 units of that width. Raised where
the storage the Project includes is something else. A driver handed a unit of
the wrong width would read the wrong bytes.
main.ngp
include "lynx/lynx.ngp"
include "lynx/cart256k.ngp"
container lnx "64k"
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1237]: a `64k` cartridge is 255 pages of 256 bytes, page zero being the bootstrap's, and this machine's storage is 255 units of 1,024
--> main.ngp:4:15
|
4 | container lnx "64k"
| ^^^^^
Include the storage file of the board: lynx/cart64k.ngp for "64k", and so
on up to lynx/cart512k.ngp for "512k".
NGA1238
error · a {name} is {tracks:n} tracks of at most {expected:n} bytes, the unit's number being the track's, and this machine's storage is {count:n} units of {size:n}
A d64, d80 or d82 is the surface of one Commodore drive, and its tracks
are the units of storage. A unit's number is its track's, so there is one unit
more than there are tracks, unit zero being no track. A unit is as wide as the
widest track. Raised where the storage the Project includes does not match the
Container.
main.ngp
include "pet/3032.ngp"
include "pet/d80.ngp"
container d64
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1238]: a `d64` is 35 tracks of at most 5,376 bytes, the unit's number being the track's, and this machine's storage is 78 units of 7,424
--> main.ngp:4:11
|
4 | container d64
| ^^^
Include the storage file named after the Container: pet/d64.ngp,
pet/d80.ngp or pet/d82.ngp.
NGA1239
error · {name} is not something to do with an edge's descriptors; held is the one word there is
frames held makes a Transition read the list of blocks in its Frame once,
instead of going back to the Frame in storage between one block and the next.
It costs code in every Phase, and pays where opening the stream is slow, as on
a Lynx cartridge or a diskette. held is the only word frames takes.
Leaving the line out is the other choice.
main.ngp
frames buffered
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1239]: `buffered` is not something to do with an edge's descriptors; `held` is the one word there is
--> main.ngp:1:8
|
1 | frames buffered
| ^^^^^^^^
NGA1240
error · frames is said once, and was said already
frames stands once in the Project, counting every file an include
reaches.
main.ngp
frames held
frames held
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1240]: `frames` is said once, and was said already
--> main.ngp:2:8
|
2 | frames held
| ^^^^
note: the earlier one is here
--> main.ngp:1:8
|
1 | frames held
| ^^^^
Delete one of them. NGA1241 points at the first.
NGA1241
note · the earlier one is here
Follows NGA1240 and points at the first frames.
NGA1242
error · base is gone: no window has one, and what a window shows outside a .with is undefined
base named the state a Window showed outside a .with, in a window line,
a group or a phase. It is gone: no Window has a base, and what a Window
shows outside a .with is undefined. The tool still reads the word, to say
so, and skips what follows it.
main.ngp
target {
units extension 4
window ext $4000 .. $7FFF views extension, main base main
}
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1242]: `base` is gone: no window has one, and what a window shows outside a `.with` is undefined
--> main.ngp:3:53
|
3 | window ext $4000 .. $7FFF views extension, main base main
| ^^^^
Delete base and its name. Code that reads through the Window shows the state
first with .with, and a Section that lived in the base belongs in a Pane. See
window and Panes.
NGA1243
error · frames held asks an edge to hold its descriptors, and with no storage an edge has none
frames held applies to Frames, and only a Project with storage has them.
Without storage a Transition loads nothing: every Section with bytes is
already in memory, and taking an edge is a jump into the Phase it enters.
Raised in a Project that has a then and no storage.
main.ngp
frames held
modules { "main.asm" }
phase intro { needs main then game entry introStart }
phase game { needs main entry gameStart }
entry intro
main.asm
.proc introStart
.transition game
.endp
.proc gameStart
rts
.endp
error[NGA1243]: `frames held` asks an edge to hold its descriptors, and with no storage an edge has none
--> main.ngp:1:8
|
1 | frames held
| ^^^^
Delete frames held, or include the storage of the machine, such as
atari/disk.ngp.
NGA1244
error · {name} is {count:n} banks of {size:n} bytes from {begin:hex}, which reach past the end of its linear range at {last:hex}
A unit set with linear lies in the medium's own memory, as a blitter or a
video chip reads it: Bank 0 at the start of the range, and each next Bank
right after the one before. A Bank is as large as the Window that shows the
set. Raised where the Banks, end to end, run past the end of the range.
linear is what gives a Section there a linearSectionAddress; see
Attribute access.
main.ngp
target {
units vram 4 linear $0 .. $7FFF
window w $4000 .. $7FFF views vram
}
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1244]: `vram` is 4 banks of 16,384 bytes from $00, which reach past the end of its linear range at $7FFF
--> main.ngp:2:10
|
2 | units vram 4 linear $0 .. $7FFF
| ^^^^
Four Banks of 16 KB need 64 KB, and the range is 32 KB. Correct the count, the range or the Window.
NGA1245
error · a unit set's linear range runs from a lower address to a higher one, and this one does not
The linear range of a unit set runs from a lower address to a higher one,
both ends inclusive. Raised where the end is below the start, where the start
is negative, or where the end is $FFFFFFFF or more.
main.ngp
target {
units vram 2 linear $7FFF .. $0
window w $4000 .. $7FFF views vram
}
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1245]: a unit set's linear range runs from a lower address to a higher one, and this one does not
--> main.ngp:2:25
|
2 | units vram 2 linear $7FFF .. $0
| ^^^^^
Write the lower address first.
NGA1246
error · cannot read {file}, which --overlay gives for {path}
--overlay PATH FILE makes the build read FILE wherever it would read PATH.
An editor uses it to build the text it holds and has not saved. Raised where
FILE cannot be read. The run stops there rather than read PATH from the disk,
which is not the text being looked at. Check the path of FILE.
NGA1247
error · -o is refused beside --overlay: a binary built from text on no disk answers to no saved source
A run given --overlay reads text that is on no disk, so a binary written
from it would match no saved source. Raised where -o stands beside
--overlay. Use --overlay for findings and --facts, and save the files
before building the binary.
NGA1248
error · {after} is followed by {what} in quotes, found {token}
Raised where a Project file wants quotes and finds none: the path after
include, the processor's name after cpu, and a cartridge's board after
container car, lnx or lyx. A processor's name and a board begin with a
digit, which no name of the Project file may, and a path holds / and .. A
path without its quotes is read past whole, so the finding is one.
main.ngp
target { cpu 6502 }
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1248]: `cpu` is followed by the processor's name in quotes, found `6502`
--> main.ngp:1:10
|
1 | target { cpu 6502 }
| ^^^
Quote it: cpu "6502", include "atari/800xl.ngp". In include atari/800xl.ngp
the lexer also refuses the digits of 800xl, as NGA0011, before
the Project is read.
NGA1249
error · the container {name} is not compressed while it loads; only a .xex's loader runs code between what it writes
Only a .xex can be compressed. Its loader calls code between the segments it
writes, and a compressed segment needs that call to be decoded. No other
Container's loader does this, so compress after any other one is refused.
main.ngp
container atr compress zx0
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1249]: the container `atr` is not compressed while it loads; only a `.xex`'s loader runs code between what it writes
--> main.ngp:1:15
|
1 | container atr compress zx0
| ^^^^^^^^
Delete compress zx0, or write the program as a .xex.
NGA1250
error · {name} is no format a .xex is compressed in; the formats are {known}
compress names the format the segments are carried in, and the tool has to
be able to encode it. The finding lists the formats it encodes. copy is a
format but saves nothing, so it is refused too.
main.ngp
container xex compress copy
modules { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1250]: `copy` is no format a `.xex` is compressed in; the formats are `rle` and `zx0`
--> main.ngp:1:24
|
1 | container xex compress copy
| ^^^^
Name one of the formats the finding lists. zx0 compresses best.
NGA1251
error · an except entry names a module or a group, found {token}
except lists Modules and groups by name, as resident does. A Module's name
is the stem of its file, or the name after as in modules. A quoted path is
not a name.
main.ngp
modules { "main.asm" }
container xex compress zx0 except { "main.asm" }
main.asm
.proc entry
rts
.endp
error[NGA1251]: an `except` entry names a module or a group, found `"main.asm"`
--> main.ngp:3:37
|
3 | container xex compress zx0 except { "main.asm" }
| ^^^^^^^^^^
Write the name without quotes: except { main }.
NGA1252
error · choose names {count:n} documents, and there is nothing to choose between fewer than two
choose names the documents a .xex may be changed into while it loads. With
one document there is nothing to choose between.
main.ngp
include "atari/800xl.ngp"
choose { "low.ngp" }
modules { "main.asm" }
container xex
low.ngp
target { register PORT $D640 }
main.asm
.proc entry
sta PORT
rts
.endp
error[NGA1252]: `choose` names 1 documents, and there is nothing to choose between fewer than two
--> main.ngp:3:1
|
3 | choose { "low.ngp" }
| ^^^^^^
Name the second document, or include the one there is.
NGA1253
error · choose is written more than once
A Project has one choose block. Two of them would be two sets of documents
for one byte to choose between.
main.ngp
include "atari/800xl.ngp"
choose { "low.ngp" "high.ngp" }
choose { "low.ngp" "high.ngp" }
modules { "main.asm" }
container xex
low.ngp
target { register PORT $D640 }
high.ngp
target { register PORT $D740 }
main.asm
.proc entry
sta PORT
rts
.endp
error[NGA1253]: `choose` is written more than once
--> main.ngp:4:1
|
4 | choose { "low.ngp" "high.ngp" }
| ^^^^^^
note: the first `choose` is here
--> main.ngp:3:1
|
3 | choose { "low.ngp" "high.ngp" }
| ^^^^^^
Put every document in one block.
NGA1254
note · the first choose is here
Follows NGA1253 and points at the first choose block.
NGA1255
error · {document} is a choice and declares {what}; a choice declares only registers in target and constants
A document that choose names may declare register lines in a target
block and constants entries, and nothing else. Every document is built over
the first one's layout, so nothing in one may change what is placed or where.
An include is refused too, since the included file could declare anything.
main.ngp
include "atari/800xl.ngp"
choose { "low.ngp" "high.ngp" }
modules { "main.asm" }
container xex
low.ngp
target { register PORT $D640 }
modules { "extra.asm" }
high.ngp
target { register PORT $D740 }
main.asm
.proc entry
sta PORT
rts
.endp
error[NGA1255]: `low.ngp` is a choice and declares a module; a choice declares only registers in `target` and `constants`
--> low.ngp:2:11
|
2 | modules { "extra.asm" }
| ^^^^^^^^^^^
Declare what is not a value in the Project, outside the documents.
NGA1256
error · {name} is declared by {document} and not by {other}; every choice declares the same names
Every document that choose names declares the same names. A name that one
declares and another does not would leave a build of the other without it.
main.ngp
include "atari/800xl.ngp"
choose { "low.ngp" "high.ngp" }
modules { "main.asm" }
container xex
low.ngp
target { register PORT $D640 }
constants { LEVEL = 1 }
high.ngp
target { register PORT $D740 }
main.asm
.proc entry
lda #LEVEL
sta PORT
rts
.endp
error[NGA1256]: `LEVEL` is declared by `low.ngp` and not by `high.ngp`; every choice declares the same names
--> low.ngp:2:13
|
2 | constants { LEVEL = 1 }
| ^^^^^
Give the name a value in every document, even where the value is the same.
NGA1257
error · choose changes a .xex without storage while it loads, and this program {what}
Only a .xex without storage runs code of the program's while it loads and is
written into memory as it is, so only such a file can be changed into another
document while it loads. The message says what this program is instead.
main.ngp
include "atari/800xl.ngp"
choose { "low.ngp" "high.ngp" }
modules { "main.asm" }
container atr
low.ngp
target { register PORT $D640 }
high.ngp
target { register PORT $D740 }
main.asm
.proc entry
sta PORT
rts
.endp
error[NGA1257]: `choose` changes a `.xex` without storage while it loads, and this program is written as `atr`
--> main.ngp:3:1
|
3 | choose { "low.ngp" "high.ngp" }
| ^^^^^^
Build one file for each document instead: one small Project for each that includes its document and the common one.
NGA1258
error · {name} stands at {address:hex} under {document}, where the first choice lets a section stand
The program is placed as the first document builds it, so a section may stand anywhere the first document's registers leave free. A register that a later document puts in that memory could have a section on top of it.
main.ngp
include "atari/800xl.ngp"
choose { "low.ngp" "high.ngp" }
modules { "main.asm" }
container xex
low.ngp
target { register PORT $D640 }
high.ngp
target { register PORT $3000 }
main.asm
.proc entry
sta PORT
rts
.endp
error[NGA1258]: `PORT` stands at $3000 under `high.ngp`, where the first choice lets a section stand
--> high.ngp:1:19
|
1 | target { register PORT $3000 }
| ^^^^
Put the register where the machine has registers, in a register region.
NGA2202
note · previous definition of {symbol} is here
Follows a finding about a name defined twice, NGA2203,
NGA2205 or NGA2213, and points at the first
definition. After NGA2211 it points at the first of the local
labels the reference could mean.
NGA2203
error · {symbol} is already defined in this module
A Module has one set of names for its Symbols, whatever their kind, so a
Constant and a Label cannot share a name. A Section opens no scope: a Label in
one Section collides with the same Label in another. A Proc does open one. A
plain label inside .proc clear is clear.fill, and two Procs may each have
a fill.
.section
buffer .res 16
.ends
.section
buffer .res 16
.ends
.proc entry
lda buffer
rts
.endp
error[NGA2203]: `buffer` is already defined in this module
--> main.asm:6:1
|
6 | buffer .res 16
| ^^^^^^
note: previous definition of `buffer` is here
--> main.asm:2:1
|
2 | buffer .res 16
| ^^^^^^
Rename one, or move it into a Proc or a Namespace.
Inside a Proc, @ labels may repeat; see
Local labels.
NGA2204
error · {symbol} is exported but not defined in this module
.export names a Symbol of its own Module. The tool resolves it at the end of
the Module, so the definition may come after it. It looks in the block the
.export stands in, and a qualified name is NGA0145. Raised
where no Symbol of that name is found there: a misspelling, or a name defined
inside a .namespace block while the .export stands outside it.
.export draw
.namespace gfx
.proc draw
rts
.endp
.endns
.proc entry
jsr gfx.draw
rts
.endp
error[NGA2204]: `draw` is exported but not defined in this module
--> main.asm:1:9
|
1 | .export draw
| ^^^^
Move the .export into the .namespace block. Another Module then reaches the
Proc as gfx.draw.
NGA2205
error · {symbol} is exported by more than one module
Exported names share one table across the Project, whatever Phases their
Modules are in, so two Modules that export one name collide. In C every
function not declared static is exported. The finding stands on the second
definition and the note on the first.
main.asm
.export draw
.proc draw
rts
.endp
.proc entry
jsr draw
rts
.endp
other.asm
.export draw
.proc draw
rts
.endp
error[NGA2205]: `draw` is exported by more than one module
--> other.asm:3:7
|
3 | .proc draw
| ^^^^
note: previous definition of `draw` is here
--> main.asm:3:7
|
3 | .proc draw
| ^^^^
Rename one, or keep one private: drop its .export, or declare the C function
static. Where the two are one routine written for different Phases, the
answer is a Slot.
NGA2206
error · {symbol} is not defined
Nothing defines the name where the use can see it. The search runs from the enclosing Namespace outwards, and at each step takes the Module's own Symbols first and the exported ones of other Modules second. A Symbol of another Module is visible only once that Module exports it.
main.asm
.proc entry
jsr clearScreen
rts
.endp
other.asm
.proc clearScreen
rts
.endp
error[NGA2206]: `clearScreen` is not defined
--> main.asm:2:13
|
2 | jsr clearScreen
| ^^^^^^^^^^^
Add .export clearScreen to other.asm. The same finding names an unknown
Charset in a string's prefix, as in atasci"OOPS", and an unknown Slot after
.implements. An undefined a after asl or another instruction with an
accumulator form is NGA2208.
NGA2207
error · {symbol} is defined in terms of itself
A Constant whose expression reaches itself, directly or through other Constants, has no value. The finding stands once, at the reference that closes the loop.
WIDTH = HEIGHT * 2
HEIGHT = WIDTH / 2
.proc entry
lda #WIDTH
rts
.endp
error[NGA2207]: `WIDTH` is defined in terms of itself
--> main.asm:2:10
|
2 | HEIGHT = WIDTH / 2
| ^^^^^
Give one of them a literal value.
NGA2208
error · {mnemonic} on the accumulator is written {mnemonic}, without a
The accumulator form of asl, lsr, rol, ror, and of inc and dec on a
65SC02, is written without an operand. Other assemblers write asl a. Here a
would be an operand naming a Symbol, and this is raised where the program
defines no a.
.proc entry
lda #1
asl a
rts
.endp
error[NGA2208]: `asl` on the accumulator is written `asl`, without `a`
--> main.asm:3:13
|
3 | asl a
| ^
Write asl. A program that defines a Label or a Constant a gets no finding:
asl a shifts the byte at that address.
NGA2210
error · no definition of @{name} matches this reference
A local label is reached only inside the Proc or macro body that defines it.
@-name takes the nearest definition before the reference in the source,
@+name the nearest after, and @name the only one. Raised where none
matches: the label is on the other side, in another Proc, or of the other
kind, since @- passes over every @name and @-name over every @.
.proc entry
lda $F0
beq @-done
sta $F1
@done rts
.endp
error[NGA2210]: no definition of `@done` matches this reference
--> main.asm:3:13
|
3 | beq @-done
| ^^^^^^
@done comes after the branch, so the reference is @+done.
NGA2211
error · @{name} has more than one definition here; write @+{name} or @-{name}
A bare @name stands for the one definition of name in its Proc or macro
body. Where there are several, the reference does not choose. A bare @wait
that worked stops working once a second @wait appears anywhere in the Proc,
before it or after it.
.proc entry
ldx #8
@wait dex
bne @wait
ldy #8
@wait dey
bne @-wait
rts
.endp
error[NGA2211]: `@wait` has more than one definition here; write `@+wait` or `@-wait`
--> main.asm:4:13
|
4 | bne @wait
| ^^^^^
note: previous definition of `wait` is here
--> main.asm:3:1
|
3 | @wait dex
| ^
Write @-wait for the nearest definition before the reference, or @+wait
for the nearest after.
NGA2212
error · an anonymous local label is reached with @+ or @-
@ alone defines an anonymous local label. A reference to one says which way
to look: @- for the nearest before, @+ for the nearest after.
.proc entry
ldx #8
@ dex
bne @
rts
.endp
error[NGA2212]: an anonymous local label is reached with `@+` or `@-`
--> main.asm:4:13
|
4 | bne @
| ^
The loop is behind the branch, so the reference is bne @-.
NGA2213
error · {name} is already a label of this macro body
A plain label of a macro body belongs to the body and is made again at each
use. It is unique in the body. @ labels may repeat, and are another kind of
name: wait never reaches @wait, so the two may share a spelling.
.macro delay
ldx #0
wait dex
bne wait
ldx #0
wait dex
bne wait
.endm
.proc entry
delay
rts
.endp
error[NGA2213]: `wait` is already a label of this macro body
--> main.asm:6:1
|
6 | wait dex
| ^^^^
note: previous definition of `wait` is here
--> main.asm:3:1
|
3 | wait dex
| ^
Rename one, or write both as @wait and reach each with @-wait.
NGA2214
error · {name} is a parameter of this macro, and a label cannot take its name
A macro parameter stands for what the use wrote. A label of the body with the
parameter's name would mean one thing where it is defined and another where it
is read. The same holds for a name a .case binds.
.macro delay count
ldx #count
count dex
bne count
.endm
.proc entry
delay 8
rts
.endp
error[NGA2214]: `count` is a parameter of this macro, and a label cannot take its name
--> main.asm:3:1
|
3 | count dex
| ^^^^^
Rename the label or the parameter.
NGA2215
error · no definition of @{name} outside this branch matches, and one in another branch may not be there at all
A local label defined in a branch of an .if is visible in that branch and the
branches inside it, and nowhere else. The branch may not be assembled, so a
reference outside it cannot count on the label being there. Raised where the
only definitions of the name stand in other branches.
FAST = 1
.proc entry
ldx #8
.if FAST
@loop dex
.else
@loop nop
dex
.endif
bne @-loop
rts
.endp
error[NGA2215]: no definition of `@loop` outside this branch matches, and one in another branch may not be there at all
--> main.asm:11:13
|
11 | bne @-loop
| ^^^^^^
Define the label once, on a line of its own before the .if, so that both
branches start at it. See
Conditional assembly.
NGA2220
error · expected an integer here, and this is {type}
An operator or a directive wants an Integer and was given an Address, a String
or a Pane. *, /, <<, >>, -x, ~x and !x take Integers only;
Operators has the rest. The usual case is the high
byte of an address written as a division.
.section
buffer .res 256
.ends
.proc entry
lda #buffer / 256
sta $F1
rts
.endp
error[NGA2220]: expected an integer here, and this is an address
--> main.asm:6:14
|
6 | lda #buffer / 256
| ^^^^^^^^^^^^
Take the byte with >buffer, or <buffer for the low one. Both are
Integers.
NGA2221
error · two addresses cannot be added; a - b is the distance between them
An Address plus an Integer is an Address, and one Address minus another is the Integer distance between them. The sum of two Addresses has no meaning, so it is refused. A midpoint is the usual case.
.section
table .byte 1, 2, 3, 4, 5, 6
tableEnd
.ends
.proc entry
lda (table + tableEnd) / 2
rts
.endp
error[NGA2221]: two addresses cannot be added; `a - b` is the distance between them
--> main.asm:7:13
|
7 | lda (table + tableEnd) / 2
| ^^^^^^^^^^^^^^^^^^
Write the midpoint as a position plus half the distance:
table + (tableEnd - table) / 2.
NGA2222
error · an address cannot be subtracted from a number
An Integer minus an Address is refused, as -buffer is. Where an Address
stands in a subtraction it stands on the left: buffer - 1 is an Address, and
tableEnd - table is an Integer.
.section
buffer .res 16
.ends
.proc entry
ldx #$100 - buffer
rts
.endp
error[NGA2222]: an address cannot be subtracted from a number
--> main.asm:6:14
|
6 | ldx #$100 - buffer
| ^^^^^^^^^^^^^
Where the arithmetic needs a byte of the address, take it first: <buffer
and >buffer are Integers.
NGA2223
error · these addresses are not in one section, so this is a property of the layout rather than of the program
Each Section is placed on its own. The distance between Labels of two
Sections, and which of them comes first, is what the solver chose, and another
build may choose differently. A difference of two Addresses, and a <, <=,
> or >= between them, needs both in one Section and one space. == and
!= do not.
.section
header .byte 1, 2
.ends
.section
body .byte 3, 4, 5
.ends
.proc entry
ldx #body - header
rts
.endp
error[NGA2223]: these addresses are not in one section, so this is a property of the layout rather than of the program
--> main.asm:10:14
|
10 | ldx #body - header
| ^^^^^^^^^^^^^
Put both Labels in one Section where the distance is meant to be fixed. The
size of a whole Section is runtimeSectionSize, and needs no second Label. See
Subtracting addresses.
NGA2224
error · only a label reaches the attributes of its section, and this is {type}
The attributes after a dot, such as runtimeSectionAddress,
runtimeSectionSize and resident, belong to a Section, and only a Label
reaches them. A Constant is a number even where it holds an address, and has
no Section. The same holds for a register, a Region's name and any expression.
buffer = $0600
.proc entry
ldx #buffer.runtimeSectionSize
rts
.endp
error[NGA2224]: only a label reaches the attributes of its section, and this is an integer
--> main.asm:4:14
|
4 | ldx #buffer.runtimeSectionSize
| ^^^^^^^^^^^^^^^^^^^^^^^^^
Declare the memory as a Section with a Label and .res, and the Section has
the attributes. Where the address must be fixed, pin it with absolute at.
See Attribute access.
NGA2225
error · .{directive} takes {allowed}, and this is {type}
A Label is an Address, and .byte has room for one byte of it.
.section
pointers
.byte message
.ends
.section
message
.byte "HELLO"
.ends
error[NGA2225]: `.byte` takes an integer, a string or a pane, and this is an address
--> main.asm:3:15
|
3 | .byte message
| ^^^^^^^
Write <message or >message for one byte of the address, or .word message
for both. A String in .word is refused the same way, and so is a number in
.dispatch, which takes Labels of its own Section.
NGA2226
error · an operand is an address, a number or a pane, and this is {type}
A string literal is a String even when it holds one character, and no
instruction takes one. The character literal 'A' is an Integer.
.proc entry
lda #"A"
rts
.endp
error[NGA2226]: an operand is an address, a number or a pane, and this is a string
--> main.asm:2:14
|
2 | lda #"A"
| ^^^
Write lda #'A'. With a Charset prefix, as in lda #screen'A', the value is
the byte that Charset maps the character to.
NGA2227
error · {name} is not an attribute of a section
A Label reaches five attributes of its Section: runtimeSectionAddress,
runtimeSectionSize, resident, linearSectionAddress and
linearFamilyAddress. Any other name after the dot is refused, and so are
storagePayloadAddress and storagePayloadSize, which are reserved and not
built.
.section
buffer .res 64
.ends
.proc entry
ldx #buffer.size
rts
.endp
error[NGA2227]: `size` is not an attribute of a section
--> main.asm:6:21
|
6 | ldx #buffer.size
| ^^^^
The size is buffer.runtimeSectionSize. After the name of a Proc, a name the
Proc does not define is read as an attribute, so a misspelt worker.count gets
this finding too. See Attribute access.
NGA2228
error · a conditional chooses between two of one type, and these are {type} and {other}
The conditional value c ? a : b has the type of its answers. A Constant that
holds a register's address is an Integer, and a Label is an Address.
SHADOW = 1
COLBK = $D01A
.section
colorShadow
.res 1
.ends
.proc entry
lda #$34
sta SHADOW ? colorShadow : COLBK
rts
.endp
error[NGA2228]: a conditional chooses between two of one type, and these are an address and an integer
--> main.asm:11:22
|
11 | sta SHADOW ? colorShadow : COLBK
| ^^^^^^^^^^^^^^^^^^^
Choose the statement instead of the value: put sta colorShadow and
sta COLBK in the two branches of an .if SHADOW. See
The conditional value.
NGA2229
error · a conditional between addresses of two sections has no section of its own, and subtraction and width need one
An Address carries its Section, and both subtracting it from another Address and deciding the width of an instruction need that Section. A choice between Labels of two Sections has none to carry.
PAL = 1
.section
palSpeeds
.byte 5, 6, 7
.ends
.section
ntscSpeeds
.byte 6, 7, 8
.ends
.proc entry
lda PAL ? palSpeeds : ntscSpeeds
rts
.endp
error[NGA2229]: a conditional between addresses of two sections has no section of its own, and subtraction and width need one
--> main.asm:14:19
|
14 | lda PAL ? palSpeeds : ntscSpeeds
| ^^^^^^^^^^^^^^^^^^^^^^
Put both tables in one Section, with a Label at each, and the conditional is
accepted. Or keep one Label and choose its bytes with .if PAL inside the
Section.
NGA2230
error · {symbol} is not a character set
The prefix of a literal, and the base after : in a derived .charset, must
name a Charset. Here font is the Label of the font's bytes, which is not the
mapping of characters to them.
.section
font .res 1024
.ends
.section
title
.byte font"HELLO"
.ends
error[NGA2230]: `font` is not a character set
--> main.asm:7:15
|
7 | .byte font"HELLO"
| ^^^^
Declare the mapping with .charset under a name of its own, and use that name
as the prefix. A prefix that names nothing at all is
NGA2206.
NGA2231
error · {charset} does not map {character}
Every character of a prefixed literal must be one its Charset maps. An escape
is asked of the Charset like any other character, so \n needs an entry too.
The finding names the first character that is missing, once per literal.
.charset font
" " = $00
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" = $01
.endch
.section
title
.byte font"Game Over"
.ends
error[NGA2231]: `font` does not map `a`
--> main.asm:8:15
|
8 | .byte font"Game Over"
| ^^^^^^^^^^^^^^^
This font has no lower case. Add a run to the .charset for the missing
characters, or write the text in characters it maps.
NGA2232
error · character set {charset} is derived from itself
A derived Charset is built from the table of its base, so the base must be built first. Here each is the other's base, and neither can be built. The finding stands at the first declaration of the cycle.
.charset bright : dim ^ $80
.endch
.charset dim : bright ^ $80
.endch
error[NGA2232]: character set `bright` is derived from itself
--> main.asm:1:10
|
1 | .charset bright : dim ^ $80
| ^^^^^^
Give one of them entries of its own and no base, and derive the other from it.
NGA2233
error · {character} is already mapped earlier in this .charset block
Inside one .charset block a character is mapped once, since a literal holding
it would otherwise have two bytes to choose from. Two characters may share one
byte, which is what a font with only upper case wants.
.charset font
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" = $01
"0123456789" = $1B
" .,:!?O" = $25
.endch
error[NGA2233]: `O` is already mapped earlier in this `.charset` block
--> main.asm:4:3
|
4 | " .,:!?O" = $25
| ^^^^^^^^^
O is in the first run and again in the last. Remove one of the two. An entry
of a derived Charset overrides its base, and that is not a duplicate, but two
entries of one derived block for one character are.
NGA2234
error · a character set maps to bytes, and this run covers {start} to {end}
A run takes consecutive bytes from the value on its right, one per character,
and every one of them must be between $00 and $FF. The finding gives the
first and last byte the run would cover, in decimal. A mask after ^ wider
than a byte is refused the same way.
.charset font
"0123456789" = $00
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" = $F0
.endch
error[NGA2234]: a character set maps to bytes, and this run covers 240 to 265
--> main.asm:3:3
|
3 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" = $F0
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Start the run lower, or split it into runs that fit.
NGA2235
error · a character set is resolved before any size or address exists, so this needs a value written in the source
The value on the right of a .charset entry, and the mask after ^, must be
declared values: literals, and Constants
made of literals. A Label, a size, or the distance between two Labels is known
only later.
.section
glyphs
.res 8
letters .res 208
.ends
.charset font
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" = letters - glyphs
.endch
error[NGA2235]: a character set is resolved before any size or address exists, so this needs a value written in the source
--> main.asm:8:34
|
8 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" = letters - glyphs
| ^^^^^^^^^^^^^^^^
Write the number, or a Constant that holds it.
NGA2236
error · {symbol} is a character set, and a character set has no value
A Charset is named only as the prefix of a literal, as in font"HELLO" or
font'A'. Its name alone has no value.
.charset font
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" = $01
.endch
.proc entry
lda #font
rts
.endp
error[NGA2236]: `font` is a character set, and a character set has no value
--> main.asm:6:14
|
6 | lda #font
| ^^^^
For the byte of one character, write lda #font'A'.
NGA2237
error · {character} is not ASCII and this literal names no character set
A literal without a prefix is the source's own bytes, so it must be ASCII. Nothing says which byte a character above 127 would be, because the machine's own character set is neither Unicode nor ASCII.
.section
credits
.byte "© 1984 NGA"
.ends
error[NGA2237]: `©` is not ASCII and this literal names no character set
--> main.asm:3:15
|
3 | .byte "© 1984 NGA"
| ^^^^^^^^^^^^
Put the name of a Charset that maps the character in front of the literal, as
in atascii"...". The runs inside a .charset are not checked, since they
list the characters a font draws. See Character sets.
NGA2240
error · {phase} is not a phase of this project
.transition NAME names a Phase that a phase block declares. Here the name
is misspelt.
main.ngp
modules { "intro.asm" "game.asm" }
phase intro { needs intro then game entry introStart }
phase game { needs game entry gameStart }
entry intro
intro.asm
.proc introStart
.transition gmae
.endp
game.asm
.proc gameStart
@loop jmp @loop
.endp
error[NGA2240]: `gmae` is not a phase of this project
--> intro.asm:2:21
|
2 | .transition gmae
| ^^^^
The statement may have meant the edge then game, so that edge is not also
reported as taken by nothing, which would be NGA2246. A Project
that declares no then at all is checked the same way.
NGA2241
error · this transition to {to} stands in code present in phase {from}, which has no then {to}
The code of a .transition does not know at run time which Phase it runs in.
So every Phase that needs its Module must declare then to the Phase it
names, and the finding names each Phase that does not.
main.ngp
modules { "intro.asm" "game.asm" }
phase intro { needs intro then game entry introStart }
phase game { needs game entry gameStart }
entry intro
intro.asm
.proc introStart
.transition game
.endp
game.asm
.proc gameStart
.transition intro
.endp
error[NGA2241]: this transition to `intro` stands in code present in phase `game`, which has no `then intro`
--> game.asm:2:21
|
2 | .transition intro
| ^^^^^
Add then intro to the game Phase. A .transition in a Module that
resident names needs the edge from every Phase. In a Project where no Phase
declares then, every .transition that names a Phase is refused this way.
NGA2242
error · the target numbers phases in a byte, and this project has {count:n}
Raised where a Project with Transitions declares more than 254 Phases. A
Phase's number is one byte in every Frame and in every .transition, and $FF
ends a table. Reduce the number of Phases: where several Phases run the same
code over different data, one Phase can run it.
NGA2243
error · the transition from {from} to {to} loads {count:n} sections, and a frame counts them in a byte
Raised with storage, for an edge that would load more than 255 Sections. The
Frame of an edge lists each Section it loads as one block and counts the blocks
in a byte. An edge loads every Section with bytes of a Module the entered Phase
needs and the Phase it leaves does not, whether or not a .transition takes
it. A Section in a Pane or in a unit set is not counted: the Container writes
it into its Bank once, and no edge loads it.
Use fewer, larger Sections in the Modules that Phase brings. A Module both Phases need is kept and not loaded.
NGA2244
error · {transform} is not a format the tool can encode
The transform block names a format the tool encodes, since the tool writes
the Payload in that form when it builds the program. The formats are copy,
rle and zx0.
main.ngp
modules { "main.asm" }
transform lz4 { main.title }
main.asm
.section
title .byte "TITLE SCREEN"
.ends
.proc entry
lda title
rts
.endp
error[NGA2244]: `lz4` is not a format the tool can encode
--> main.ngp:3:11
|
3 | transform lz4 { main.title }
| ^^^
A .transform in a Module that names an unknown format is
NGA2276.
NGA2245
error · module {module} has no label named {section}, and a section is named by one
A Section has no name of its own, so the transform block names it by one of
its Labels, as module.label, or module.space.label for a Label in a
Namespace. Raised where the Module has no Label of that name. Whether the Label
is exported does not matter.
main.ngp
include "atari/800xl.ngp"
include "atari/disk.ngp"
modules { "main.asm" }
transform zx0 { main.titel }
container atr
main.asm
.section
title .byte "TITLE SCREEN"
.ends
.proc entry
lda title
rts
.endp
error[NGA2245]: module `main` has no label named `titel`, and a section is named by one
--> main.ngp:6:22
|
6 | transform zx0 { main.titel }
| ^^^^^
NGA2246
warning · phase {from} declares then {to}, and no .transition {to} is present in it, so the edge is taken by nothing
then in a phase block declares an edge, and a .transition in a Module of
that Phase takes it. Raised where no Module the Phase needs holds a
.transition to the Phase named.
main.ngp
modules { "intro.asm" "game.asm" }
phase intro { needs intro then game entry introStart }
phase game { needs game entry gameStart }
entry intro
intro.asm
.proc introStart
rts
.endp
game.asm
.proc gameStart
rts
.endp
warning[NGA2246]: phase `intro` declares `then game`, and no `.transition game` is present in it, so the edge is taken by nothing
Nothing enters game, and what only game needs is left out of the build.
Write the .transition game where intro ends, or remove then game.
NGA2247
warning · {module}.{section} is never loaded by a transition, so nothing transforms it
Raised with storage, where transform names a Section that no Transition
loads, so there is no Payload to decode. On an .atr such Sections are those
of a resident Module, which every edge keeps, and those of the entry Phase
when no edge leads back to it. A Section in a Pane is one too, wherever there
is storage, since the Container writes it into its Bank. The Container writes
them as they are.
main.ngp
include "atari/800xl.ngp"
include "atari/disk.ngp"
modules { "main.asm" }
transform zx0 { main.title }
container atr
main.asm
.section
title .byte "TITLE SCREEN"
.ends
.proc entry
lda title
rts
.endp
warning[NGA2247]: `main.title` is never loaded by a transition, so nothing transforms it
--> main.ngp:6:22
|
6 | transform zx0 { main.title }
| ^^^^^
Take the Section out of the transform block, or move it to a Module of a
Phase that a Transition enters.
NGA2248
error · {section} names the section {previous} already lists, and a section is transformed once
A Section is transformed once. Any Label of a Section names the whole Section,
so two Labels of one Section in transform blocks name it twice.
main.ngp
include "atari/800xl.ngp"
include "atari/disk.ngp"
modules { "intro.asm" "level.asm" }
phase intro { needs intro then level entry introStart }
phase level { needs level entry levelStart }
entry intro
transform zx0 { level.map, level.mapEnd }
container atr
intro.asm
.proc introStart
.transition level
.endp
level.asm
.section
map .byte "##########"
mapEnd
.ends
.proc levelStart
lda map
@stop jmp @stop
.endp
error[NGA2248]: `mapEnd` names the section `map` already lists, and a section is transformed once
--> main.ngp:10:34
|
10 | transform zx0 { level.map, level.mapEnd }
| ^^^^^^
mapEnd stands at the end of the Section that map starts. List one Label
per Section.
NGA2249
error · {module}.{section} is named in transform, and without storage only a .xex decodes anything, while it loads
Without storage no edge loads anything: every Section is written once, when the
program loads. A .xex can run the decoder while the DOS loads it. No other
Container runs code while it is loaded, so nothing would decode the Section.
copy is accepted in any Container.
main.ngp
modules { "main.asm" }
transform zx0 { main.title }
main.asm
.section
title .byte "TITLE SCREEN"
.ends
.proc entry
lda title
rts
.endp
error[NGA2249]: `main.title` is named in `transform`, and without storage only a `.xex` decodes anything, while it loads
--> main.ngp:3:22
|
3 | transform zx0 { main.title }
| ^^^^^
Include the storage document beside the variant, such as atari/disk.ngp for
an .atr, build a .xex, or take the Section out of the block.
NGA2250
error · {symbol} is not a slot
.implements SLOT, SYMBOL names the Slot first. Raised where the first name is
defined and is not a Slot, as here, where the two names are the wrong way
round.
.slot draw, vector
.implements levelDraw, draw
.proc levelDraw
rts
.endp
error[NGA2250]: `levelDraw` is not a slot
--> main.asm:3:13
|
3 | .implements levelDraw, draw
| ^^^^^^^^^
Write .implements draw, levelDraw. A first name that is not defined at all is
NGA2206.
NGA2251
error · {symbol} is not a label or a section of this module
The second name of .implements is a Label or a Section of the Module the
directive stands in. Raised where that Module defines no Label of that name. A
Label exported by another Module does not count.
main.asm
.slot draw, vector
.export draw
.implements draw, levelDraw
level.asm
.export levelDraw
.proc levelDraw
rts
.endp
error[NGA2251]: `levelDraw` is not a label or a section of this module
--> main.asm:4:1
|
4 | .implements draw, levelDraw
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
Move the .implements line into level.asm, beside the Proc.
NGA2252
error · {slot} has two implementations live in phase {phase}: {symbol} and {other}
A Slot has one live Implementation in each Phase. Two Modules that implement it in the same Phase leave the tool no single address to write into the Cell.
main.ngp
modules { "main.asm" "level.asm" }
resident { main }
phase level { needs level entry levelStart }
entry level
main.asm
.slot draw, vector
.export draw
.implements draw, drawNothing
.proc drawNothing
rts
.endp
level.asm
.implements draw, drawMap
.proc drawMap
rts
.endp
.proc levelStart
jsr draw
rts
.endp
error[NGA2252]: `draw` has two implementations live in phase `level`: `drawMap` and `drawNothing`
--> level.asm:1:1
|
1 | .implements draw, drawMap
| ^^^^^^^^^^^^^^^^^^^^^^^^^
note: `drawNothing` implements it here
--> main.asm:4:1
|
4 | .implements draw, drawNothing
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
A resident Module is live in every Phase, so a default there collides with
every Phase that fills the Slot. There is no order of precedence. Remove one
.implements, or fill the Slot in the Module of each Phase. The note
NGA2253 points at the other Implementation.
NGA2253
note · {symbol} implements it here
Follows NGA2252 and points at the .implements of the other
Implementation live in that Phase.
NGA2254
error · a frame counts cell writes in a byte, so a program has at most 255 slots, and this one has {count:n}
Raised where the program declares more than 255 Slots, counting every .slot
in every Module. Every Slot has a Cell, and a Frame counts the Cells it writes
in a byte. Use fewer Slots: a Phase can fill one pointer Slot with the
address of a table of its own, and the code reads the other addresses from that
table.
NGA2255
error · {symbol} fills slot {slot} from pane {pane}, and the cell holds an address but not the state that shows it
An Implementation stands in no Pane. A call through the Cell does not show the Pane, and would run whatever the Window shows at that moment.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in ext { level }
main.asm
.slot draw, vector
.implements draw, levelDraw
.proc levelDraw, in level
rts
.endp
error[NGA2255]: `levelDraw` fills slot `draw` from pane `level`, and the cell holds an address but not the state that shows it
--> main.asm:3:1
|
3 | .implements draw, levelDraw
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
Fill the Slot with a Proc outside the Pane that puts .with level over its
jsr, as levelDraw does in Slots.
NGA2260
error · {name} is not a proc of this module, and then names one
.endp then NAME names a Proc of the same Module, by the Label at its start. A
Label in a .section, a Label inside a Proc, or a Proc of another Module is
refused.
.proc entry
ldx #0
.endp then clear
.section
clear
sta $0600,x
rts
.ends
error[NGA2260]: `clear` is not a proc of this module, and `then` names one
--> main.asm:3:12
|
3 | .endp then clear
| ^^^^^
Make clear a .proc, or drop the then and end entry with jmp clear.
See .endp then NAME.
NGA2261
error · {name} already follows {previous}, and can follow only one proc
The Proc that then names is placed right after the Proc that names it, and
only one Proc can stand right before it.
.proc entry
jsr fillScreen
ldx #0
.endp then clear
.proc fillScreen
ldx #$FF
.endp then clear
.proc clear
rts
.endp
error[NGA2261]: `clear` already follows `entry`, and can follow only one proc
--> main.asm:8:12
|
8 | .endp then clear
| ^^^^^
Keep one then, and end the other Proc with jmp clear.
NGA2262
error · {name} follows {previous}, and cannot also be pinned or aligned
The Proc after then starts where the one before it ends, so its address
comes from the chain. An at or an align of its own would conflict with
that.
.proc entry
ldx #0
.endp then clear
.proc clear, absolute align 256
rts
.endp
error[NGA2262]: `clear` follows `entry`, and cannot also be pinned or aligned
--> main.asm:3:12
|
3 | .endp then clear
| ^^^^^
Pin or align the first Proc of the chain instead.
NGA2264
error · {name} follows itself through then
A chain of then that comes back to where it started has no first Proc to
place. It is reported once, at the then of the Proc of the cycle declared
first.
.proc entry
jmp first
.endp
.proc first
inx
.endp then second
.proc second
iny
.endp then first
error[NGA2264]: `second` follows itself through `then`
--> main.asm:7:12
|
7 | .endp then second
| ^^^^^^
Drop one then and end that Proc with a jmp to the next.
NGA2265
error · {name} follows {previous}, so both are in one pane or neither is
The Proc that then names stands in the bytes right after the first one. A
Pane's bytes are there only while the Pane is shown, so a chain cannot run from
a Pane into memory outside it, or the other way.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in ext { level }
main.asm
.proc drawLevel, in level
ldx #0
.endp then finish
.proc finish
rts
.endp
error[NGA2265]: `finish` follows `drawLevel`, so both are in one pane or neither is
--> main.asm:3:12
|
3 | .endp then finish
| ^^^^^^
Put both in the Pane, or drop the then and end drawLevel with
jmp finish.
NGA2266
error · {type} is a {want}-byte type, and this reserves {got}
Where .declare arg or .declare ret writes a type, the .ztemp or .temp
under it reserves exactly that type's bytes: one for u8, i8 and bool, two
for u16 and i16, N for u8[N].
.proc double
.declare arg u16
value .ztemp 1
asl value
rts
.endp
error[NGA2266]: `u16` is a 2-byte type, and this reserves 1
--> main.asm:2:22
|
2 | .declare arg u16
| ^^^
Reserve two bytes, or drop the type and let the reservation answer: one byte is
a u8. A place such as ax is held to its bytes by
NGA2334.
NGA2270
error · a proc holds code, and a reservation is not code; a variable is a .ztemp or lives in a .section
A Proc holds code, and a table the code reads may stand in it with .byte. A
variable may not.
.proc entry
inc counter
rts
counter .res 1
.endp
error[NGA2270]: a proc holds code, and a reservation is not code; a variable is a `.ztemp` or lives in a `.section`
--> main.asm:4:9
|
4 | counter .res 1
| ^^^^^^
Declare it as counter .ztemp 1 or .temp, which takes the Proc's scope, or
put it in a .section, which may be opened inside the Proc.
NGA2271
error · a temporary section holds reservations only, and this is not one
A Temporary shares its addresses with other Temporaries while it is not active,
so a byte written into it when the program loads would not be there when it
runs. A .section temporary holds .res and nothing else: no data and no
instructions.
.section temporary
scratch
.byte 0, 0
.ends
error[NGA2271]: a temporary section holds reservations only, and this is not one
--> main.asm:3:9
|
3 | .byte 0, 0
| ^^^^^^^^^^
Set the values in code when the Section is entered, or put initialised data in
an ordinary .section.
NGA2272
error · {symbol} names a {kind} the project declares, and a module cannot define it
The names of the Target's Regions, registers, unit sets and Windows, and of the Project's Panes, are visible in every Module, and no Module may define one again, exported or not. This catches a local copy of a register's address, which could drift from the Target's.
main.ngp
target {
region $0080 .. $00FF ram
region $2000 .. $BFFF ram
register PORTB $D301
}
modules { "main.asm" }
main.asm
PORTB = $D301
.proc entry
lda #$FE
sta PORTB
rts
.endp
error[NGA2272]: `PORTB` names a register the project declares, and a module cannot define it
--> main.asm:1:1
|
1 | PORTB = $D301
| ^^^^^
note: the register `PORTB` is declared here
--> main.ngp:4:12
|
4 | register PORTB $D301
| ^^^^^
Delete the definition and use the Target's name. The note
NGA1163 points at its declaration.
NGA2273
error · this section holds no label, and a section is named by one
A Section has no name of its own. Its Labels name it, in source, in the Project
and in the memory map, so a .section with no Label anywhere in it cannot be
named at all.
.section
.byte 1, 2, 4, 8, 16, 32, 64, 128
.ends
error[NGA2273]: this section holds no label, and a section is named by one
--> main.asm:1:1
|
1 | .section
| ^^^^^^^^
Put a Label at its start.
NGA2274
error · {label} is not defined in this module, and a decoder is one of its labels
.transform FORMAT LABEL stands in the decoder's own Module. The declaration
exports the Label, so it needs no .export of its own.
.transform rle unpackRle
.proc unpack
rts
.endp
error[NGA2274]: `unpackRle` is not defined in this module, and a decoder is one of its labels
--> main.asm:1:16
|
1 | .transform rle unpackRle
| ^^^^^^^^^
Correct the name, or move the .transform into the decoder's Module.
NGA2275
error · {label} is a {kind}, and a decoder is entered at a label
The Transition routine jumps to a decoder, so .transform names the Label it
starts at. A Constant, a macro or any other kind of Symbol is refused, and the
message says which kind it is.
.transform rle unpack
.macro unpack
rts
.endm
error[NGA2275]: `unpack` is a macro, and a decoder is entered at a label
--> main.asm:1:16
|
1 | .transform rle unpack
| ^^^^^^
Write the decoder as a .proc and name that.
NGA2276
error · {format} is not a format the tool can encode, so nothing produces what this decodes
.transform declares a decoder for a format the tool encodes: copy, rle
or zx0. The tool would never write a Payload in any other format, so a
decoder for one would have nothing to decode.
.transform lz4 unpack
.proc unpack
rts
.endp
error[NGA2276]: `lz4` is not a format the tool can encode, so nothing produces what this decodes
--> main.asm:1:12
|
1 | .transform lz4 unpack
| ^^^
The library's decoders are stream/rle.asm and stream/zx0.asm. The same name
in the Project's transform block is NGA2244.
NGA2277
error · {format} already has a decoder, and a format has one
Raised at a second .transform for one format, in the same Module or in
another. A Frame names a block's decoder by a number, one per format, so a
format has one decoder. The usual cause is a decoder of the program's own beside the one a
storage document lists, as atari/disk.ngp lists stream/zx0.asm.
.transform rle unpack
.transform rle unpackFast
.proc unpack
rts
.endp
.proc unpackFast
rts
.endp
error[NGA2277]: `rle` already has a decoder, and a format has one
--> main.asm:2:12
|
2 | .transform rle unpackFast
| ^^^
note: the decoder of `rle` is declared here
--> main.asm:1:1
|
1 | .transform rle unpack
| ^^^^^^^^^^^^^^^^^^^^^
Keep one of the two. The note, NGA2278, points at the one the
tool kept.
NGA2278
note · the decoder of {format} is declared here
Follows NGA2277 and points at the first .transform for the
format, which is the decoder the tool keeps.
NGA2279
error · no module declares a decoder for copy, and every Transition copies; the storage driver declares one with .transform copy
Raised where the program has storage, takes a Transition, and no Module
declares .transform copy. A Payload that no transform block names is moved
into place by the copy decoder. The driver declares it, because the driver
knows how its medium is best copied.
main.ngp
storage { units 1 size 4096 }
modules { "main.asm" "drive.asm" }
resident { drive }
phase level { needs main then level entry start }
entry level
main.asm
.proc start
.transition level
.endp
drive.asm
.driver open driveOpen
.driver read driveRead
.driver unit driveUnit
.driver offset driveAt
.macro driveOpen
nop
.endm
.macro driveRead
lda #0
.endm
.section zeropage
driveAt .res 2
driveUnit .res 1
.ends
error[NGA2279]: no module declares a decoder for `copy`, and every Transition copies; the storage driver declares one with `.transform copy`
--> drive.asm:1:1
|
1 | .driver open driveOpen
| ^^^^^^^^^^^^^^^^^^^^^^^^
Add .transform copy to the driver, with a Label of its own that does the
copying, as every driver in the library does.
NGA2280
error · no module declares a decoder for {transform}
Raised for a transform block of the Project whose format no Module decodes.
The tool encodes the format, and a Module of the program decodes it: a
.transform line binds the format to a Label of that Module. The library
holds stream/rle.asm and stream/zx0.asm.
main.ngp
storage { units 1 size 4096 }
modules { "main.asm" }
transform rle { main.tiles }
main.asm
.section
tiles .byte 0, 0, 0, 0, 1, 1, 1, 1
.ends
error[NGA2280]: no module declares a decoder for `rle`
--> main.ngp:5:22
|
5 | transform rle { main.tiles }
| ^^^^^
List the decoder in modules and in resident, as "stream/rle.asm" and
rle. A storage document of the library lists stream/zx0.asm already. A
.xex without storage needs neither, because the tool adds the library's
decoder to the code that runs while the file loads.
NGA2281
error · a .transition is taken and no module declares the storage driver; one module declares it with .driver, and a machine variant usually lists that module
Raised when a .transition is taken in a program with storage and no Module
declares .driver. A Transition reads its Frame and its Payloads from storage,
and only the driver knows how to read it. Without a storage block a
Transition loads nothing and needs no driver.
main.ngp
storage { units 1 size 4096 }
modules { "main.asm" }
phase level { needs main then level entry start }
entry level
main.asm
.proc start
.transition level
.endp
error[NGA2281]: a `.transition` is taken and no module declares the storage driver; one module declares it with `.driver`, and a machine variant usually lists that module
Include the machine's storage document, which lists its driver:
atari/disk.ngp beside atari/800xl.ngp, for one. A Project that declares its
own storage lists a driver Module of its own too, in modules and in
resident.
NGA2282
error · this module declares the storage driver, and {module} already does
Raised at the second Module that declares .driver. A program has one driver,
which the Transition routine, the decoders and every .with use. Usually two
documents each list one, such as atari/roms.ngp beside atari/disk.ngp.
main.asm
.driver init setup
.macro setup
cld
.endm
roms.asm
.driver init begin
.macro begin
sei
.endm
error[NGA2282]: this module declares the storage driver, and `main` already does
--> roms.asm:1:1
|
1 | .driver init begin
| ^^^^^^^^^^^^^^^^^^
note: the driver is declared here
--> main.asm:1:1
|
1 | .driver init setup
| ^^^^^^^^^^^^^^^^^^
Keep one driver, and give it every role the program needs.
NGA2283 points at the one the tool kept.
NGA2283
note · the driver is declared here
Follows NGA2282 and points at the first .driver line of the
driver the tool kept.
NGA2284
error · {role} is not a role of the driver; the roles are open, read, unit, offset, init, finalize, stream, show, showAt, seek, span, rom, select, mask and unmask
Raised at a .driver line whose first word is not a role. The roles are the
fixed set the tool calls, so any other word would declare something nothing
uses. They are case-sensitive: showat is not showAt.
.driver write driveWrite
.macro driveWrite
sta $D301
.endm
error[NGA2284]: `write` is not a role of the driver; the roles are `open`, `read`, `unit`, `offset`, `init`, `finalize`, `stream`, `show`, `showAt`, `seek`, `span`, `rom`, `select`, `mask` and `unmask`
--> main.asm:1:9
|
1 | .driver write driveWrite
| ^^^^^
NGA2285
error · the driver declares no {role}, and the routine calls it
Raised where the driver lacks a role the tool calls. A driver of storage needs
open, read, unit and offset: the routine writes a position into the
two cells, then opens the stream and reads it. A driver that declares a rom
needs select, which switches the ROMs on every edge. init, finalize,
mask and unmask are optional.
main.ngp
storage { units 1 size 4096 }
modules { "main.asm" }
main.asm
.driver open driveOpen
.driver unit driveUnit
.driver offset driveAt
.macro driveOpen
nop
.endm
.section zeropage
driveAt .res 2
driveUnit .res 1
.ends
error[NGA2285]: the driver declares no `read`, and the routine calls it
--> main.asm:1:1
|
1 | .driver open driveOpen
| ^^^^^^^^^^^^^^^^^^^^^^^^
Declare the missing role. A driver that only switches ROMs, in a program without storage, declares none of the stream's roles.
NGA2286
error · {label} is not defined in this module, and a role names a macro or a label of the driver's own module
Raised where a .driver line names something its own Module does not define.
A role belongs to the driver: the macro, or the Label of a cell, stands in the
Module that says .driver. One that another Module exports does not count.
main.asm
.driver init driveInit
setup.asm
.export driveInit
.macro driveInit
cld
.endm
error[NGA2286]: `driveInit` is not defined in this module, and a role names a macro or a label of the driver's own module
--> main.asm:1:14
|
1 | .driver init driveInit
| ^^^^^^^^^
Move the definition into the driver's Module.
NGA2287
error · as {name} {reason}
as names the Proc whose Temporaries hold the arguments of every Proc that
joins it. Raised where the name is something else, such as the table that
holds the handlers' addresses, and where as stands on a .section, which
takes no arguments.
.section
handlers .word 0
.ends
.proc onFire, as handlers
rts
.endp
error[NGA2287]: `as handlers` names what is no proc, and a function type is the proc whose temporaries hold the arguments
--> main.asm:5:18
|
5 | .proc onFire, as handlers
| ^^^^^^^^
Name the Proc that is the type. A type declared in C as
typedef u8 chooser(u8 x); is joined with as chooser; see
Function types.
NGA2288
error · {proc} is as {type}, so its arguments are {type}'s temporaries, and it declares {what} of its own
Raised where a Proc that says as also declares an argument or a result with
.declare. A member reads its arguments from the type's Temporaries, so that
a direct call and a call through a pointer write the same bytes.
.proc handler
ptr .ztemp 2
key .ztemp 1
jmp (ptr)
.endp
.proc onKey, as handler
.declare arg u8
pressed .ztemp 1
lda pressed
rts
.endp
error[NGA2288]: `onKey` is `as handler`, so its arguments are `handler`'s temporaries, and it declares arguments of its own
--> main.asm:7:17
|
7 | .proc onKey, as handler
| ^^^^^^^
Drop the .declare and the .ztemp under it, and read handler.key.
NGA2289
error · the driver is present in some phases only, and every Transition calls it
Raised where the driver's Module is not in memory in every Phase. Every Transition calls the driver, whichever Phase it leaves.
main.ngp
modules { "main.asm" "game.asm" "drive.asm" }
phase intro { needs main, drive then game entry start }
phase game { needs game entry play }
entry intro
main.asm
.proc start
.transition game
.endp
game.asm
.proc play
rts
.endp
drive.asm
.driver init driveInit
.macro driveInit
cld
.endm
error[NGA2289]: the driver is present in some phases only, and every Transition calls it
--> drive.asm:1:1
|
1 | .driver init driveInit
| ^^^^^^^^^^^^^^^^^^^^^^
List the Module in resident, as the library's variants and storage documents
list their drivers.
NGA2290
error · this decoder's module is present in some phases only, and any Transition may call it
Raised where a Module that declares .transform is not in memory in every
Phase. Any Transition may load a Payload in that format, so its decoder has to
be there whichever Phase the Transition leaves.
main.ngp
modules { "main.asm" "game.asm" "unpack.asm" }
phase intro { needs main, unpack then game entry start }
phase game { needs game entry play }
entry intro
main.asm
.proc start
.transition game
.endp
game.asm
.proc play
rts
.endp
unpack.asm
.transform rle unpack
.proc unpack
rts
.endp
error[NGA2290]: this decoder's module is present in some phases only, and any Transition may call it
--> unpack.asm:1:1
|
1 | .transform rle unpack
| ^^^^^^^^^^^^^^^^^^^^^
List the Module in resident.
NGA2291
error · {role} is declared more than once
Raised at the second .driver line for one role. A role is declared once:
show and showAt once per Window, and rom once per Module it names.
.driver init driveInit
.driver init driveReset
.macro driveInit
cld
.endm
.macro driveReset
sei
.endm
error[NGA2291]: `init` is declared more than once
--> main.asm:2:9
|
2 | .driver init driveReset
| ^^^^
Delete one. Where both bodies are needed, put them in one macro.
NGA2292
error · {module}.{section} stands in {pane} and is named in transform, and what stands in a pane or a unit set is written as it is, with no decoder to run on it
Raised for a .xex without storage, where a Section named in transform
stands in a Pane or in a unit set. Such a Section is written into its Bank
while the file loads, and no decoder runs on it there.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in ext { level }
transform zx0 { main.levelData }
container xex
main.asm
.section in level
levelData
.byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.ends
.proc entry
.with level
lda levelData
rts
.endp
error[NGA2292]: `main.levelData` stands in `level` and is named in `transform`, and what stands in a pane or a unit set is written as it is, with no decoder to run on it
--> main.asm:1:1
|
1 | .section in level
| ^^^^^^^^
Take the Section out of the transform block.
NGA2293
error · {role} takes {count} {names}, and is given {given}
Raised where a .driver line has the wrong number of names after the role.
show and showAt take a Window and a macro, and showAt may add x or
xy, the registers it takes the state in. rom takes a Module and may add a
second whose ranges it shows too. Every other role takes one name.
.driver show ext
.macro driveShow state
ldx #state
stx $D301
.endm
error[NGA2293]: `show` takes 2 names, and is given 1
--> main.asm:1:9
|
1 | .driver show ext
| ^^^^
NGA2294
error · {window} is not a window of the target
Raised where a .driver line names a Window the Target does not declare. A
driver is written for one machine and names that machine's Windows, so this
usually means a driver of another machine, or a misspelled name.
.driver show ext driveShow
.macro driveShow state
ldx #state
stx $D301
.endm
error[NGA2294]: `ext` is not a window of the target
--> main.asm:1:14
|
1 | .driver show ext driveShow
| ^^^
Name a Window that a window line of the Target declares; see
window.
NGA2295
error · the driver declares no {role} for window {window}, and the target declares the window
Raised where the Target declares a Window and the driver has no show or no
showAt for it. A driver shows every Window the Target declares: a .with
expands show where the state is known when the program is built, and
showAt where it is in X.
main.ngp
target {
units extra 4
window ext $4000 .. $7FFF views extra
}
modules { "main.asm" }
main.asm
.driver show ext driveShow
.macro driveShow state
ldx #state
stx $D301
.endm
error[NGA2295]: the driver declares no `showAt` for window `ext`, and the target declares the window
--> main.asm:1:1
|
1 | .driver show ext driveShow
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
Declare the missing role for that Window.
NGA2296
error · storage is the units of {name}, and the driver names no stream to read them through
Raised where storage is the Banks of a unit set, storage { units NAME }, and
the driver declares no stream. Those Banks are read through a Window that
shows them, and .driver stream WINDOW says which.
main.ngp
target {
units extra 4
window ext $4000 .. $7FFF views extra
}
storage { units extra }
modules { "main.asm" }
main.asm
.driver open driveOpen
.driver read driveRead
.driver unit driveUnit
.driver offset driveAt
.driver show ext driveShow
.driver showAt ext driveShowAt
.macro driveOpen
nop
.endm
.macro driveRead
lda #0
.endm
.macro driveShow state
ldx #state
stx $D301
.endm
.macro driveShowAt
stx $D301
.endm
.section zeropage
driveAt .res 2
driveUnit .res 1
.ends
error[NGA2296]: storage is the units of `extra`, and the driver names no `stream` to read them through
--> main.asm:1:1
|
1 | .driver open driveOpen
| ^^^^^^^^^^^^^^^^^^^^^^^^
Add .driver stream with the Window whose views lists the unit set, here
.driver stream ext. See storage.
NGA2297
error · the stream reads through {window}, which does not show the units storage is
Raised where .driver stream names a Window that does not show storage.
Storage that is a unit set is read through a Window whose views lists that
set. Storage declared by count, units N size S, is read without a Window,
and its driver declares no stream, as atari/disk.asm does.
main.ngp
target {
units extra 4
window ext $4000 .. $7FFF views extra
}
storage { units 16 size 4096 }
modules { "main.asm" }
main.asm
.driver open driveOpen
.driver read driveRead
.driver unit driveUnit
.driver offset driveAt
.driver stream ext
.driver show ext driveShow
.driver showAt ext driveShowAt
.macro driveOpen
nop
.endm
.macro driveRead
lda #0
.endm
.macro driveShow state
ldx #state
stx $D301
.endm
.macro driveShowAt
stx $D301
.endm
.section zeropage
driveAt .res 2
driveUnit .res 1
.ends
error[NGA2297]: the stream reads through `ext`, which does not show the units storage is
--> main.asm:5:16
|
5 | .driver stream ext
| ^^^
Name the Window that shows storage's unit set. For storage by count, delete
the stream line.
NGA2298
error · nga.{role} names a window first, and this does not
Raised where nga.show or nga.showAt does not begin with a Window. The
driver declares these two roles once per Window, so the Window picks the macro,
and the arguments after it are the macro's.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
container xex
main.asm
.proc entry
nga.show 2
rts
.endp
error[NGA2298]: `nga.show` names a window first, and this does not
--> main.asm:2:18
|
2 | nga.show 2
| ^
Write the Window first: nga.show ext, 2. In a program, a
.with is usually what is wanted, since it also
checks what the statement under it reaches.
NGA2299
error · {symbol} names a window of the target, and a window is not a value
Raised where a Window's name stands as a value. The name is for .with and
for the driver's roles, and stands for neither the Window's address nor a
state of it.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
container xex
main.asm
.proc entry
lda #<ext
rts
.endp
error[NGA2299]: `ext` names a window of the target, and a window is not a value
--> main.asm:2:15
|
2 | lda #<ext
| ^^^
For the address, declare a Constant, extWindow = $4000. For a state, write a
Pane's name. For the number of Banks, write the unit set's name.
NGA2300
error · {name} is an instruction, and a macro cannot take its name
Raised at a .macro whose name is a mnemonic. A use would be read as the
instruction, so the macro could never be reached. Every mnemonic the tool
knows counts, so a 65SC02 instruction such as phx cannot be a macro on a
6502 Target either.
.macro phx
txa
pha
.endm
error[NGA2300]: `phx` is an instruction, and a macro cannot take its name
--> main.asm:1:8
|
1 | .macro phx
| ^^^
Give the macro another name, such as pushX.
NGA2301
error · parameter {name} is given twice
Raised where the header of a macro, or the pattern of a .case, lists one name
twice. The body could not tell which argument the name means.
.macro copy from, from
lda from
sta to
.endm
error[NGA2301]: parameter `from` is given twice
--> main.asm:1:19
|
1 | .macro copy from, from
| ^^^^
NGA2302
error · parameter {name} has the name of a symbol this module defines
Raised where a macro parameter has the name of a Symbol its Module defines.
Inside the body the name would mean the argument and outside it the Symbol,
and a reader of the body could not tell which was meant. A name a .case
binds is held to the same rule.
count = 8
.macro clear at, count
lda #0
ldx #count - 1
@loop sta at,x
dex
bpl @loop
.endm
error[NGA2302]: parameter `count` has the name of a symbol this module defines
--> main.asm:3:18
|
3 | .macro clear at, count
| ^^^^^
Rename the parameter.
NGA2303
error · {name} is neither an instruction nor a macro in scope
Raised where the first word of a statement is no instruction and no macro the
Module can see. Mnemonics are lowercase, so LDA is a name like any other. A
macro of another Module is seen only where that Module exports it with
.export. For a qualified name, the Namespace exists and holds no such macro.
.proc entry
lad #0
rts
.endp
error[NGA2303]: `lad` is neither an instruction nor a macro in scope
--> main.asm:2:9
|
2 | lad #0
| ^^^
NGA2304
error · {name} is an instruction and takes one operand; an index register is x or y
Raised where an instruction's operand has a comma followed by something other
than x or y. That makes a list, and only a macro takes one. Index registers
are lowercase, so table,X is a list of two values.
.section
table .byte 1, 2, 3, 4
.ends
.proc entry
ldx #0
lda table,X
rts
.endp
error[NGA2304]: `lda` is an instruction and takes one operand; an index register is `x` or `y`
--> main.asm:7:9
|
7 | lda table,X
| ^^^
NGA2305
error · a macro's argument is an expression: no #, no ,x or ,y, and no parenthesis that indirects
Raised where a macro is used with an argument shaped like an operand: #value,
at,x, or (ptr),y. An argument is an expression, and the body decides how it
is used.
.macro background color
lda #color
sta $D01A
.endm
.proc entry
background #$94
rts
.endp
error[NGA2305]: a macro's argument is an expression: no `#`, no `,x` or `,y`, and no parenthesis that indirects
--> main.asm:7:9
|
7 | background #$94
| ^^^^^^^^^^^^^^^
Drop the #, since the body writes lda #color already. For an indexed
address, pass the address and write the index in the body.
NGA2306
error · {name} takes {expected} {arguments} and was given {given}
Raised where a macro use gives more or fewer arguments than the macro has
parameters. A macro whose last parameter is a pack takes at least the names
before it, and is NGA2331 instead.
.macro poke at, value
lda #value
sta at
.endm
.proc entry
poke $D01A
rts
.endp
error[NGA2306]: `poke` takes 2 arguments and was given 1
--> main.asm:7:9
|
7 | poke $D01A
| ^^^^
NGA2308
error · {symbol} is a macro and stands where a value is expected
Raised where a macro's name stands as an operand, usually after jsr or
jmp. A macro has no address, because its body is copied into each use. The
driver's roles, such as nga.read, are macros too.
.macro clear at
lda #0
sta at
.endm
.proc entry
jsr clear
rts
.endp
error[NGA2308]: `clear` is a macro and stands where a value is expected
--> main.asm:7:13
|
7 | jsr clear
| ^^^^^
Write the name where an instruction stands, clear $D01A, or make it a
.proc where a call is wanted.
NGA2309
error · {label} is a {kind}, and a role is a macro the tool expands where it uses the role
Raised where a .driver role names a Label or a Constant instead of a macro.
The tool expands a role at each place it uses it, so a role is a macro even
when its body is one jsr. The cells unit and offset are the exception:
they name Labels.
.driver init driveInit
.proc driveInit
cld
rts
.endp
error[NGA2309]: `driveInit` is a label, and a role is a macro the tool expands where it uses the role
--> main.asm:1:14
|
1 | .driver init driveInit
| ^^^^^^^^^
Keep the Proc, and name in .driver a macro whose body is a jsr to it, as
the library's drivers do.
NGA2310
error · nga is the tool's namespace, and no module defines it
Raised where a Module defines nga, as a Symbol or by opening
.namespace nga. The name is the tool's: the driver's roles are reached
through it, as nga.read and nga.show.
.namespace nga
width = 40
.endns
error[NGA2310]: `nga` is the tool's namespace, and no module defines it
--> main.asm:1:12
|
1 | .namespace nga
| ^^^
NGA2311
error · {space} is not a namespace
Raised where a macro use is qualified by a name that is no Namespace. A
Module's name is not a Namespace: a macro that print.asm exports is used as
line, not print.line. A Namespace is opened with .namespace.
main.asm
.proc entry
print.line 3
rts
.endp
print.asm
.export line
.macro line n
ldx #n
stx $0600
.endm
error[NGA2311]: `print` is not a namespace
--> main.asm:2:9
|
2 | print.line 3
| ^^^^^
NGA2312
error · nga.{name} names nothing the tool defines
Raised for nga.NAME where the tool defines no such name. The tool's
Namespace holds the driver's roles, nga.open, nga.read, nga.init,
nga.select, nga.mask, nga.unmask, nga.finalize, nga.show and
nga.showAt, and the two cells of its stream, nga.unit and nga.offset.
.proc entry
nga.close
rts
.endp
error[NGA2312]: `nga.close` names nothing the tool defines
--> main.asm:2:13
|
2 | nga.close
| ^^^^^
NGA2313
error · nga.{name} is used, and the program has no driver: no module declares one, or the one declared was refused
Raised where code uses a role or a cell of the driver, such as nga.read or
nga.unit, or a .with, and the program has no driver. For the roles it is
reported once, at the first use. It also follows a driver the tool refused,
such as one missing a role, NGA2285. nga.select, nga.mask,
nga.unmask and nga.finalize are never reported: without a driver they
expand to nothing.
.proc entry
nga.read
sta $0600
rts
.endp
error[NGA2313]: `nga.read` is used, and the program has no driver: no module declares one, or the one declared was refused
--> main.asm:2:13
|
2 | nga.read
| ^^^^
Include the machine's storage document, which lists its driver, or list a driver Module of your own.
NGA2314
error · {symbol} is a name the tool defines, and a module may not define it
Raised where a Module defines a name the tool already gives every Module, such
as a Constant of the Project's constants block. In that Module its own
definition would win, and every other Module would see the Project's value.
main.ngp
constants { LEVELS = 8 }
modules { "main.asm" }
main.asm
LEVELS = 3
.proc entry
lda #LEVELS
rts
.endp
error[NGA2314]: `LEVELS` is a name the tool defines, and a module may not define it
--> main.asm:1:1
|
1 | LEVELS = 3
| ^^^^^^
note: the tool defines `LEVELS` here
--> main.ngp:1:13
|
1 | constants { LEVELS = 8 }
| ^^^^^^
Delete one of the two definitions, or rename one. NGA2315 points
at the Project's.
NGA2315
note · the tool defines {symbol} here
Follows NGA2314 and points at the line of the Project file that
defines the name.
NGA2316
error · {name} is a namespace and stands where a value is expected
Raised where the name of a Namespace stands as a value. A Namespace is a prefix on the names inside it and has no value of its own.
.namespace sound
volume = 8
.endns
.proc entry
lda #sound
rts
.endp
error[NGA2316]: `sound` is a namespace and stands where a value is expected
--> main.asm:6:14
|
6 | lda #sound
| ^^^^^
Name the member: lda #sound.volume.
NGA2317
error · {symbol} is also a namespace, and one name cannot be both
Raised at a Symbol whose name is also a Namespace. A dotted name after a Label
reads an attribute of its Section, so player.x would mean two things. The
Label of a .proc is the exception, since a Proc is a scope of that name
itself.
.section
player .res 4
.ends
.namespace player
x = 0
y = 1
.endns
error[NGA2317]: `player` is also a namespace, and one name cannot be both
--> main.asm:2:1
|
2 | player .res 4
| ^^^^^^
Rename one of the two.
NGA2319
error · {name} is an attribute of a section, and a name in a proc cannot take it
Raised where a name inside a Proc is one of a Section's attributes:
runtimeSectionAddress, runtimeSectionSize, resident,
linearSectionAddress, linearFamilyAddress, storagePayloadAddress or
storagePayloadSize. From outside, loader.resident is the Proc's attribute,
and a name inside it would take the same spelling.
.proc loader
resident .ztemp 1
lda resident
rts
.endp
error[NGA2319]: `resident` is an attribute of a section, and a name in a proc cannot take it
--> main.asm:2:1
|
2 | resident .ztemp 1
| ^^^^^^^^
Rename it. See Attribute access.
NGA2321
error · a condition decides how many bytes there are, so it is a declared value: nothing naming a position or a size may stand in it
Raised where an .if condition names a position or a size: a Label, or an
attribute such as runtimeSectionSize. In a macro body this includes a
parameter whose argument is one. The condition must be a
declared value, made of literals and of
Constants made of literals.
.section
table .byte 1, 2, 3
.ends
.proc entry
.if table.runtimeSectionSize > 2
ldx #2
.endif
rts
.endp
error[NGA2321]: a condition decides how many bytes there are, so it is a declared value: nothing naming a position or a size may stand in it
--> main.asm:6:5
|
6 | .if table.runtimeSectionSize > 2
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
To check a size or an address, write .assert, which is evaluated after Place.
NGA2322
error · this expansion is {depth} uses deep at {name} and shows no sign of ending
Raised in the Expand Step when a macro uses itself, directly or through other
macros, more than 1024 uses deep. The tool takes that as a recursion whose
condition never turns false. Usually the argument that should bring it to an
end is passed on unchanged: here zeros n was meant to be zeros n - 1.
.macro zeros n
.if n > 0
.byte 0
zeros n
.endif
.endm
.section
table zeros 4
.ends
error[NGA2322]: this expansion is 1025 uses deep at `zeros` and shows no sign of ending
--> main.asm:4:9
|
4 | zeros n
| ^^^^^
note: the expansion began at this use
--> main.asm:9:9
|
9 | table zeros 4
| ^^^^^
The finding stands at the use inside the body, and the note
NGA2323 at the use where the expansion began. Nothing more of
that use is expanded. A recursion that ends but produces too much is
NGA2332.
NGA2323
note · the expansion began at this use
Follows NGA2322, NGA2332 and
NGA2333, and a finding about a .with written in a macro body,
such as NGA3008. The finding stands in the body, which may be used
in many places. The note points at the use in a Section or a Proc where this
expansion began.
NGA2324
error · {name} is a {kind}, and stands where an instruction or a macro is expected
A name where a mnemonic stands is a macro use, and the name is looked up as any
name is, this Module's own Symbols first. Raised when what it finds is a
Label, a Constant or any other Symbol that is not a macro. The usual cause is a
call written without its jsr.
.proc clear
lda #0
sta $0600
rts
.endp
.proc entry
clear
rts
.endp
error[NGA2324]: `clear` is a label, and stands where an instruction or a macro is expected
--> main.asm:8:9
|
8 | clear
| ^^^^^
A Symbol of another kind is not skipped in favour of a macro of the same name
further out, so lda fill and fill 1, 2 in one Module never mean two
different fills. Rename one of them. A name that is nothing at all is
NGA2303.
NGA2325
error · {name} is not a pack, and only a pack spreads
NAME... as an item of a list spreads a pack: its elements stand in its place.
Raised where NAME is not a pack: a fixed parameter of the macro, a fixed name
of a .case, or any name outside a macro body. Usually the parameter was
declared without its dots.
.macro table values
.byte values, values...
.endm
error[NGA2325]: `values` is not a pack, and only a pack spreads
--> main.asm:2:23
|
2 | .byte values, values...
| ^^^^^^
Write the last parameter as values... on the .macro line. Only the last
parameter may be a pack. See Packs.
NGA2326
error · {name} is not a pack, and .match counts a pack's elements
.match NAME chooses a .case by how many elements the pack NAME has.
Raised where NAME is not a pack the body binds: a fixed parameter, a fixed
name of an enclosing .case, or a name the body does not bind at all.
.macro poke at, values
.match values
.case first, rest...
lda #first
sta at
poke at + 1, rest...
.case
.endmatch
.endm
error[NGA2326]: `values` is not a pack, and `.match` counts a pack's elements
--> main.asm:2:8
|
2 | .match values
| ^^^^^^
Declare the parameter as a pack, values.... To choose by a value rather than
by a count, use .if.
NGA2327
error · {name} is already bound around this .case, and a case hides nothing
The names of a .case are new names for the pack's elements. Raised where one
of them is already bound around the .case: a parameter of the macro, or a
name of the .case of an enclosing .match. Inside the case the name would
mean one thing and just outside it another. Another .case of the same
.match is not around it, and may bind the same names.
.macro store at, value, rest...
lda #value
sta at
.match rest
.case value, more...
store at + 1, value, more...
.case
.endmatch
.endm
error[NGA2327]: `value` is already bound around this `.case`, and a case hides nothing
--> main.asm:5:7
|
5 | .case value, more...
| ^^^^^
Give the case a name of its own, such as next.
NGA2328
error · {name} was given {count} elements, and no .case of .match {name} fits that
Raised at a use where the pack has a number of elements that no .case of a
.match fits. It is reported once per use, and the note
NGA2329 points at the .match. In a recursion that takes an
element off each turn, the usual cause is a missing .case with no names,
which fits the empty pack and is where the recursion stops.
.macro words values...
.match values
.case first, rest...
.word first
words rest...
.endmatch
.endm
.section
limits words 100, 2000
.ends
error[NGA2328]: `values` was given 0 elements, and no `.case` of `.match values` fits that
--> main.asm:5:9
|
5 | words rest...
| ^^^^^
note: the `.match` is here
--> main.asm:2:8
|
2 | .match values
| ^^^^^^
Here the third use gets an empty pack. Add an empty .case, or a case for the
count the use gives. How a case fits is in Packs.
NGA2329
note · the .match is here
Follows NGA2328 and points at the .match whose cases the pack
did not fit.
NGA2330
warning · a .case above this one fits everything this one does, so it is never taken
.match keeps the first .case that fits. Raised at a .case that an earlier
case always fits first, so it is never taken: after .case first, rest...,
which fits one element or more, .case last cannot be reached. Raised where the
macro is defined, whether it is used or not.
.macro words values...
.match values
.case first, rest...
.word first
words rest...
.case last
.word last
.case
.endmatch
.endm
warning[NGA2330]: a `.case` above this one fits everything this one does, so it is never taken
--> main.asm:6:1
|
6 | .case last
| ^^^^^^^^^^
Put the narrower case first, or remove it.
NGA2331
error · {name} takes at least {expected} {arguments} and was given {given}
A macro whose last parameter is a pack takes at least as many arguments as it has names before the pack. The pack takes the rest, none included. Raised at a use that gives fewer.
.macro poke at, first, rest...
lda #first
sta at
.match rest
.case next, more...
poke at + 1, next, more...
.case
.endmatch
.endm
.proc entry
poke $0600
rts
.endp
error[NGA2331]: `poke` takes at least 2 arguments and was given 1
--> main.asm:12:9
|
12 | poke $0600
| ^^^^
A macro without a pack takes exactly its parameters, and a use that gives
another count is NGA2306.
NGA2332
error · this expansion has produced {count:n} statements, more than the target has bytes to put them in
Raised when one use expands to more than 65536 statements, the number of bytes
in the address space: an expansion that size could not be placed if each
statement emitted a single byte. The depth limit of NGA2322 does
not catch it. A macro that uses itself twice per level ends at a small depth,
after a number of uses that doubles with each level.
.macro tree n
.if n > 0
.byte n
tree n - 1
tree n - 1
.endif
.endm
.section
nodes tree 20
.ends
error[NGA2332]: this expansion has produced 65,538 statements, more than the target has bytes to put them in
--> main.asm:5:9
|
5 | tree n - 1
| ^^^^
note: the expansion began at this use
--> main.asm:10:9
|
10 | nodes tree 20
| ^^^^
The note NGA2323 points at the use where the expansion began.
Write the recursion with one use per level.
NGA2333
error · with its arguments in place this expression nests {depth} deep, more than {limit}
An argument with a declared value is put in as that value, and one that adds or
subtracts a declared value is carried as one sum. Any other argument is carried
as its expression, so a recursion that passes on at + step, where step is
not a declared value, nests one level deeper at every use. Raised when the
expression passes the 64 levels it may nest.
.section
screen .res 4000
.ends
.section
line .res 40
.ends
.macro clear n, at
.if n > 0
sta at
clear n - 1, at + line.runtimeSectionSize
.endif
.endm
.proc entry
lda #0
clear 100, screen
rts
.endp
error[NGA2333]: with its arguments in place this expression nests 65 deep, more than 64
--> main.asm:12:22
|
12 | clear n - 1, at + line.runtimeSectionSize
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: the expansion began at this use
--> main.asm:18:9
|
18 | clear 100, screen
| ^^^^^
Make the step a declared value, such as LINE = 40, and at + LINE stays one
sum however deep the recursion goes. See
Declared values.
NGA2334
error · {place} keeps {want} in memory, and the .ztemp or .temp below reserves {got}
A place on .declare puts some bytes of an argument or a result in registers,
and the bytes written m in the reservation below it. Raised where the
reservation does not hold exactly the m bytes. am is one byte in A and one
in memory, so its .ztemp is one byte.
.proc plot
.declare arg am
column .ztemp 2
lda column
rts
.endp
error[NGA2334]: `am` keeps 1 byte in memory, and the `.ztemp` or `.temp` below reserves 2 bytes
--> main.asm:2:9
|
2 | .declare arg am
| ^^^^^^^^
Reserve only what the place keeps in memory. The same rule for a type, such as
u16 over a reservation of one byte, is NGA2266. See
.declare.
NGA2335
error · {word} is not something a medium does about an offset; forward is the one word there is
.driver seek is a word about the medium and not a role. forward is the only
one: it says the driver reaches an offset only by reading up to it, as the
Lynx's cartridge does. Raised for any other word.
.driver seek random
error[NGA2335]: `random` is not something a medium does about an offset; `forward` is the one word there is
--> main.asm:1:14
|
1 | .driver seek random
| ^^^^^^
A driver that reaches any offset at no cost, such as a sector in a buffer or a
Bank in a Window, declares no seek. With forward, the images a
.transition NAME, fast opens begin where a unit does. The other word of this
kind is span, NGA2426.
NGA2412
error · {symbol} is in pane {pane}, and this code does not run with that pane shown: put the statement under a .with, or the code in a Proc declared under it
Raised where code names a Label of a Pane's Section and does not run with that
Pane shown: it is outside the Pane, has no .with over the statement, and is
not in a Proc declared under the Pane. Outside a .with, what a Window shows
is undefined. The address is refused as well as the access, so #<levelMap is
refused as lda levelMap is.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in ext { level }
main.asm
.section in level
levelMap
.byte 1, 2, 3
.ends
.proc entry
lda levelMap
sta $0600
rts
.endp
error[NGA2412]: `levelMap` is in pane `level`, and this code does not run with that pane shown: put the statement under a `.with`, or the code in a Proc declared `under` it
--> main.asm:7:13
|
7 | lda levelMap
| ^^^^^^^^
Put .with level on the line above the statement, or put the code in a Proc
declared .proc NAME, under level. In C, write [[with(level)]] over the
block or [[under(level)]] on the function. Under a .with that shows
another Pane the finding is NGA3008, and for a Pane pinned to a
named state it is NGA3011. See
Panes.
NGA2414
error · reference to {symbol}, which is not in memory in phase {phase} while {section} is
A Section is in memory only in the Phases that need its Module. Raised where code present in a Phase names a Section that is not in memory in that Phase: there the address holds whatever that Phase put in it. It is reported for the first such Phase only.
main.ngp
modules { "title.asm" "game.asm" }
phase title { needs title then game }
phase game { needs game entry play }
entry title
title.asm
.proc entry
lda #0
sta score
.transition game
.endp
game.asm
.export score
.section
score .res 1
.ends
.proc play
inc score
rts
.endp
error[NGA2414]: reference to `score`, which is not in memory in phase `title` while `entry` is
--> title.asm:3:13
|
3 | sta score
| ^^^^^
Put what both Phases use in a Module both need, or in resident. Where each
Phase has its own version of a routine, the answer is a Slot.
In a program without storage the bytes a Section emits stay where they are, and
may be read and written in every Phase from which one that needs them can be
reached. A reservation has no bytes, and a call or a jump is always held to the
Phases that need its Module.
NGA2415
error · reference to {slot}, which has no implementation in phase {phase} while {section} is
A Slot is reached through a Cell that each Transition writes. Raised at a use of a Slot by code that is present in a Phase where no Module implements it. The Cell there holds what the last edge wrote, which points at memory this Phase does not hold. It is reported for the first such Phase, once per use.
main.ngp
modules { "hud.asm" "title.asm" "game.asm" }
resident { hud }
phase title { needs title then game }
phase game { needs game entry play }
entry title
hud.asm
.export draw, frame
.slot draw, vector
.proc frame
jsr draw
rts
.endp
title.asm
.proc entry
jsr frame
.transition game
.endp
game.asm
.implements draw, gameDraw
.proc gameDraw
rts
.endp
.proc play
jsr frame
rts
.endp
error[NGA2415]: reference to `draw`, which has no implementation in phase `title` while `frame` is
--> hud.asm:6:13
|
6 | jsr draw
| ^^^^
Implement the Slot in that Phase too, with a Proc that only returns where there is nothing to do, or keep the use out of the Phase. A Phase that neither uses nor implements a Slot needs nothing.
NGA2416
error · this reaches inside proc {proc} where only a read may: a proc is entered at its start, and written only in the operand of an instruction that does not jump, or in an opcode its .alt gives alternatives for
From outside, a Proc is entered at its start, so the tool knows every place
control comes in. Raised where a Reference from another Section goes further in
than that allows: a call or a jump past the start, a write anywhere but into
the operand of an instruction that does not jump or into an opcode with .alt,
or the address of any other byte taken. A read may go anywhere.
.proc clear
lda #0
fill sta $0600,x
dex
bne fill
rts
.endp
.proc entry
lda #$20
ldx #40
jsr clear.fill
rts
.endp
error[NGA2416]: this reaches inside proc `clear` where only a read may: a proc is entered at its start, and written only in the operand of an instruction that does not jump, or in an opcode its `.alt` gives alternatives for
--> main.asm:12:13
|
12 | jsr clear.fill
| ^^^^^^^^^^
Make the second way in a Proc of its own and chain the first to it with
.endp then fill, so that clear falls through into it. Code that is jumped
into the middle of belongs in a .section. See
A Proc has one entry.
NGA2417
error · a branch to {symbol} in {section}: a branch reaches its own proc or one chained to it by then; use jmp
A branch reaches 128 bytes back and 127 forward, so its target must be at a
distance the program fixes. Raised for a Bcc or a Jcc to a Label in another
Section, which the solver may place anywhere, unless the target is the start of
a Proc chained to this one by then.
.proc entry
lda $0600
beq idle
sta $0601
rts
.endp
.proc idle
rts
.endp
error[NGA2417]: a branch to `idle` in `idle`: a branch reaches its own proc or one chained to it by `then`; use `jmp`
--> main.asm:3:13
|
3 | beq idle
| ^^^^
Use jmp, under a branch of the opposite sense where the jump is conditional,
or chain the two Procs with .endp then idle so that the solver places them
together. See Branch reach.
NGA2418
error · {name} is neither a pane, a region nor a unit set the Project declares
in NAME on a .section or a .proc names a Pane of the Project's panes
block, a Region of RAM or ROM, or a unit set. under NAME on a Proc names a
Pane. Raised where NAME is none of those, usually because the Pane is not
declared in the Project yet, or is spelt differently there.
.section in level
levelMap
.byte 1, 2, 3
.ends
error[NGA2418]: `level` is neither a pane, a region nor a unit set the Project declares
--> main.asm:1:13
|
1 | .section in level
| ^^^^^
Declare the Pane in the Project, as in panes in ext { level }. A Region of
registers or reserved memory is NGA2442. See
panes.
NGA2420
error · {section} is in pane {pane}, and a window covers no zero page
A Section in a Pane stands in its Window, and no Window covers the zero page.
Raised for a Section declared both in a Pane and zeropage.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in ext { level }
main.asm
.section in level, zeropage
levelPtr
.res 2
.ends
error[NGA2420]: `levelPtr` is in pane `level`, and a window covers no zero page
--> main.asm:1:13
|
1 | .section in level, zeropage
| ^^^^^
Keep the zero-page variable out of the Pane: a .ztemp of the code that uses
it, or a zeropage Section of its own. A Section in a Pane is absolute
without saying so.
NGA2421
error · a pane's value is the state the solver chose, and this is arithmetic on it; a pane stands as an immediate, a data item or a role's argument
A Pane's value is the index of the state the solver gave it, known only after
Place. It may stand as an immediate operand, an item of .byte or .word, or
the argument of a driver's role, and < and > may take it apart. The one
arithmetic allowed on it is FAMILY + n. Raised for any other operator, a
comparison in an .assert included. A common case is computing the hardware's
value for a state, which is the driver's work.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in ext { level }
main.asm
.proc entry
lda #level << 2 | $E3
sta PORTB
rts
.endp
error[NGA2421]: a pane's value is the state the solver chose, and this is arithmetic on it; a pane stands as an immediate, a data item or a role's argument
--> main.asm:2:14
|
2 | lda #level << 2 | $E3
| ^^^^^^^^^^
Show the Pane with .with level, or load its state with ldx #level and hand
it to the driver with .with ext, x. See
Where a state number comes from.
NGA2422
error · {name} has {count} members, and {index} is not one of them
FAMILY + n names member n of a family declared NAME[N], and n is a
declared value from zero to N. N itself is allowed as the end of a range,
one past the last member. Raised for anything beyond that, or for an n that
is not a declared value. A single Pane counts as a family of one. Under
.with, which shows a member, N is refused too, since no Bank holds it.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in ext { rooms[2] }
main.asm
.section
roomStates
.byte rooms, rooms + 1, rooms + 2, rooms + 3
.ends
error[NGA2422]: `rooms` has 2 members, and 3 is not one of them
--> main.asm:3:44
|
3 | .byte rooms, rooms + 1, rooms + 2, rooms + 3
| ^^^^^^^^^
Here rooms + 2 is the end of the range and passes, and rooms + 3 is
refused. Other arithmetic on a Pane is NGA2421.
NGA2423
error · a pane is a state of a window and not an address, and this operand is one
A Pane's name is a number, the state of its Window, and not the address of
anything. Raised where it stands as an operand that reaches memory, usually
lda level where lda #level was meant.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in ext { level }
main.asm
.section
shown .res 1
.ends
.proc entry
lda level
sta shown
rts
.endp
error[NGA2423]: a pane is a state of a window and not an address, and this operand is one
--> main.asm:6:13
|
6 | lda level
| ^^^^^
Write the operand as an immediate. To read what the Pane holds, name one of its
Labels under .with level.
NGA2424
error · a dispatch to {symbol}, which is not a position of {section}: a dispatch goes where it stands, and .own is how a table reaches other sections
.dispatch goes to positions of the Section it stands in, which is what keeps
that Section's flow known to the tool. Raised for a target that is not one: a
Label of another Section or Proc, or a Slot.
.proc entry
lda $0600
.dispatch @walk, idle
@walk inc $0601
rts
.endp
.proc idle
rts
.endp
error[NGA2424]: a dispatch to `idle`, which is not a position of `entry`: a dispatch goes where it stands, and `.own` is how a table reaches other sections
--> main.asm:3:26
|
3 | .dispatch @walk, idle
| ^^^^
Name a position of this Proc instead, one that jumps on: @idle jmp idle. A
table that reaches other Sections is a table of addresses under .own, and the
Section that jumps through it then has no known flow. See
One of its own positions.
NGA2425
error · a dispatch of {count} targets, and an index reaches {most}
A .dispatch chooses by the value in A, which is one byte, so no value
reaches a target past the 256th. Raised for a statement of more than 256
targets, counting every row of it. The tool writes jmp (abs,x) where the
processor has it and the targets are 128 or fewer, and the rts trick, which
reaches 256, otherwise. Where the choice is wider than a byte, choose on the
high byte with one .dispatch, and on the low byte with another at each of its
targets.
NGA2426
error · {word} is not something an image does across a unit; none is the one word there is
.driver span is a word about the medium and not a role. none is the only
one: it promises the driver that no image and no Frame runs from one unit of
storage into the next, so the driver need not know which unit follows which.
pet/disk.asm says it, since a diskette's tracks hold different numbers of
sectors. Raised for any other word.
.driver span sectors
error[NGA2426]: `sectors` is not something an image does across a unit; `none` is the one word there is
--> main.asm:1:14
|
1 | .driver span sectors
| ^^^^^^^
A driver that carries an offset into the next unit, as the others the tool
ships do, declares no span. With none, every image has to fit in one unit,
or the placement refuses it with NGA5255. The other word of this
kind is seek, NGA2335.
NGA2427
error · {label} is a {kind}, and {role} names the label of a reservation the stream stands in
.driver unit and .driver offset name the two cells the Transition routine
writes a position into before it expands open. Each is a Label of the
driver's Module over a reservation, usually in the zero page. Raised where the
name is a Constant, a macro or any other kind of Symbol.
.driver open myOpen
.driver read myRead
.driver unit myUnit
.driver offset myAt
myUnit = $80
.macro myOpen
nop
.endm
.macro myRead
lda #0
.endm
.section zeropage
myAt .res 2
.ends
error[NGA2427]: `myUnit` is a constant, and `unit` names the label of a reservation the stream stands in
--> main.asm:3:17
|
3 | .driver unit myUnit
| ^^^^^^
Reserve the cell in a .section zeropage of the driver, as myAt is. How big
each must be is NGA2428.
NGA2428
error · {role} names {got}, and the stream's {role} is {want}
The routine writes a unit's number into the unit cell, and an offset of two
bytes, the low one first, into the offset cell. Raised where the reservation
under either Label is another size, or the Label stands over no reservation. A
unit's number is one byte for up to 256 units of storage and two above that.
Without storage nothing writes the unit cell, and its size is not checked.
.driver open myOpen
.driver read myRead
.driver unit myUnit
.driver offset myAt
.macro myOpen
nop
.endm
.macro myRead
lda #0
.endm
.section zeropage
myUnit .res 1
myAt .res 1
.ends
error[NGA2428]: `offset` names a reservation of 1 byte, and the stream's offset is 2 bytes
--> main.asm:4:17
|
4 | .driver offset myAt
| ^^^^
Reserve two bytes for the offset. A driver for machines with different counts
sizes the unit's cell from the unit set, as atari/mcel.asm does with
celUnitBytes = 1 + ( sdram > 256 ).
NGA2429
error · {place} is not where showAt takes a state: x is one byte in X, and xy two, the high one in Y
.driver showAt WINDOW NAME may end with a word saying where the macro takes
the state: x, which is what saying nothing means, for one byte in X, or
xy for two bytes, the high one in Y. Raised for any other word.
main.ngp
target {
window extra $4000 .. $7FFF views off, on
}
modules { "main.asm" }
main.asm
.driver show extra extraShow
.driver showAt extra extraShowAt a
.macro extraShow state
lda #state
sta $D500
.endm
.macro extraShowAt
sta $D500
.endm
error[NGA2429]: `a` is not where `showAt` takes a state: `x` is one byte in `X`, and `xy` two, the high one in `Y`
--> main.asm:2:35
|
2 | .driver showAt extra extraShowAt a
| ^
The tool hands the state over in X, or in X and Y, and nowhere else. Write
the macro to read X, and drop the word or write x.
NGA2430
error · window {window} has {count:n} states, and the driver's showAt for it takes one byte; with xy it takes two
A Window has a state for each of its named states and one for each Bank of the
unit sets it shows. Raised where a Window has more than 256 states and the
driver's showAt for it takes one byte, which cannot hold every state.
main.ngp
target {
units sdram 512
window extra $4000 .. $7FFF views sdram
}
modules { "main.asm" }
main.asm
.driver show extra extraShow
.driver showAt extra extraShowAt
.macro extraShow state
ldx #<state
ldy #>state
extraShowAt
.endm
.macro extraShowAt
stx $D500
sty $D501
.endm
error[NGA2430]: window `extra` has 512 states, and the driver's `showAt` for it takes one byte; with `xy` it takes two
--> main.asm:2:23
|
2 | .driver showAt extra extraShowAt
| ^^^^^^^^^^^
End the declaration with xy, and the macro takes the high byte in Y. A
.with that hands the state in registers then writes , xy,
NGA2431. A driver may say xy for a smaller Window too, and is
then handed a zero in Y.
NGA2431
error · the driver's showAt for window {window} takes the state in {want}, and this gives it in {given}
.with WINDOW, x and .with FAMILY, x hand the state to the driver in X, and
, xy hands it in X and Y, the high byte in Y. The form must be the one
the driver's showAt for that Window declares. Raised where they differ. On
MariaCEL, cel8000 shows 2047 Banks, so its driver takes xy.
main.ngp
include "atari/mariacel.ngp"
modules { "main.asm" }
main.asm
.proc entry
ldx #3
.with cel8000, x
lda $8000
rts
.endp
error[NGA2431]: the driver's `showAt` for window `cel8000` takes the state in `xy`, and this gives it in `x`
--> main.asm:3:9
|
3 | .with cel8000, x
| ^^^^^^^^^^^^^^^^
Load the high byte as well, ldy #0, and write .with cel8000, xy. Where the
driver takes x, write , x.
NGA2433
error · the driver declares {count:n} ROMs, and the set select is handed is a byte
.driver rom names a Module the driver can switch out. Each is one bit of the
set that select is handed in A, in the order the lines are written. Raised
where a driver declares more than eight.
.driver rom osrom
.driver rom basic
.driver rom cart1
.driver rom cart2
.driver rom cart3
.driver rom cart4
.driver rom cart5
.driver rom cart6
.driver rom cart7
.driver select romsSelect
.macro romsSelect
sta $D500
.endm
error[NGA2433]: the driver declares 9 ROMs, and the set `select` is handed is a byte
--> main.asm:1:1
|
1 | .driver rom osrom
| ^^^^^^^^^^^^^^^^^^^^^
NGA2434
error · {module} is not a ROM the driver switches out, and a phase does without only what one is
without NAME in a phase block takes out of that Phase a Module that
resident put in. It works only for a ROM the driver switches out, one it
names with .driver rom. Raised for any other Module, and for every without
where no driver switches anything. atari/800xl.ngp alone has no such driver.
main.ngp
include "atari/800xl.ngp"
modules { "title.asm" "game.asm" }
phase title { needs title then game }
phase game { needs game without osrom }
entry title
title.asm
.proc entry
.transition game
.endp
game.asm
.proc entry
rts
.endp
error[NGA2434]: `osrom` is not a ROM the driver switches out, and a phase does without only what one is
--> main.ngp:6:36
|
6 | phase game { needs game without osrom }
| ^^^^^
On an 800XL, include atari/roms.ngp beside the machine. The 130XE's own
driver switches the ROMs. A program on a diskette keeps the OS in every Phase,
because the diskette's driver reads through it. See
phase.
NGA2435
error · phase {phase} is without {module}, and {needed}, which it needs, shows it
A .driver rom line may name a second Module, whose ranges showing the first
shows too. On an XL one bit of PORTB switches the OS ROM and the floating-point
pack together, and the driver says so with .driver rom mathpack osrom. Raised
where a Phase is without the second Module and needs the first. mathpack is
resident in the variant, so a Phase that leaves out only osrom still needs
it.
main.ngp
include "atari/800xl.ngp"
include "atari/roms.ngp"
modules { "title.asm" "game.asm" }
phase title { needs title then game }
phase game { needs game without osrom }
entry title
title.asm
.proc entry
.transition game
.endp
game.asm
.proc entry
rts
.endp
error[NGA2435]: phase `game` is without `osrom`, and `mathpack`, which it needs, shows it
--> main.ngp:7:36
|
7 | phase game { needs game without osrom }
| ^^^^^
Leave both out: without osrom, mathpack.
NGA2436
error · the entry phase of a .xex is loaded by a DOS with every ROM in, and it is without {module}
Raised for a without in the entry Phase of a Project whose Container is
xex, once for each Module it names.
main.ngp
include "atari/800xl.ngp"
include "atari/roms.ngp"
modules { "game.asm" "ending.asm" }
phase game { needs game then ending without osrom, mathpack }
phase ending { needs ending }
entry game
container xex
game.asm
.proc entry
.transition ending
.endp
ending.asm
.proc entry
rts
.endp
error[NGA2436]: the entry phase of a .xex is loaded by a DOS with every ROM in, and it is without `osrom`
--> main.ngp:6:51
|
6 | phase game { needs game then ending without osrom, mathpack }
| ^^^^^
error[NGA2436]: the entry phase of a .xex is loaded by a DOS with every ROM in, and it is without `mathpack`
--> main.ngp:6:58
|
6 | phase game { needs game then ending without osrom, mathpack }
| ^^^^^^^^
Start in a Phase that keeps the ROMs, and take a Transition to the one that does without them.
NGA2437
error · .alt applies to the instruction on the line below, and this is not one
.alt lists the opcodes the instruction on the next line may be given. Raised
where that line is not an instruction: data, a Constant, a macro use, the end
of the Section, or a Label on a line of its own. The last is the usual case,
because the Label that names the opcode stands above the .alt and not
between it and the instruction.
.proc walk
.alt iny, dey
direction
nop
rts
.endp
error[NGA2437]: `.alt` applies to the instruction on the line below, and this is not one
--> main.asm:2:1
|
2 | .alt iny, dey
| ^^^^
Move the Label above the .alt, or onto the instruction's own line. See
.alt.
NGA2438
error · {mnemonic} reaches memory through its operand, and only an instruction that reaches none has alternatives
The tool knows an instruction by its length, where control goes after it and
what memory it touches. An Alternative may change none of these, except that
it may return. So the instruction under .alt reaches no memory: it has no
operand or an immediate one. Raised where its operand is an address, as when
inc and dec of a variable are to be swapped.
.section
position .res 1
.ends
.proc walk
.alt dec
inc position
rts
.endp
error[NGA2438]: `inc` reaches memory through its operand, and only an instruction that reaches none has alternatives
--> main.asm:7:9
|
7 | inc position
| ^^^^^^^^^^^^
Keep the value in a register and swap instructions that take no operand, such
as .alt dey over iny.
NGA2439
error · {alternative} has no form that takes the operand {mnemonic} is written with, at its length
Each Alternative takes the operand the instruction is written with, at the
instruction's length. Raised where the processor has no such form of it: nop
has no immediate form, so it cannot replace lda #$80, and jmp has no form
without an operand.
.proc fade
.alt nop
lda #$80
sta $D01A
rts
.endp
error[NGA2439]: `nop` has no form that takes the operand `lda` is written with, at its length
--> main.asm:2:6
|
2 | .alt nop
| ^^^
Over an immediate, list only instructions that have an immediate form. To turn
code off, put the .alt over a one-byte instruction, such as .alt rts over a
nop at the start.
NGA2440
error · this writes {value:hex} into the opcode of {mnemonic}, which is neither it nor any alternative its .alt declares
A write into an instruction's opcode from outside its Proc is allowed at the
Label of an instruction that has .alt. Where the store writes an immediate
loaded just before it, the value must be the instruction's own opcode or one
its .alt lists. Raised when it is neither. A value read from a table is taken
on trust.
.proc walk
direction
.alt iny, dey
nop
rts
.endp
.proc entry
lda #$E8
sta walk.direction
jsr walk
rts
.endp
error[NGA2440]: this writes $E8 into the opcode of `nop`, which is neither it nor any alternative its `.alt` declares
--> main.asm:10:13
|
10 | sta walk.direction
| ^^^^^^^^^^^^^^
$E8 is inx, and the declaration lists iny and dey. Write one of the
declared opcodes, or add the mnemonic to the .alt. A write into an opcode
with no .alt is NGA2416.
NGA2441
error · nga.{name} is used, and the driver switches ROMs and has no stream to {name}
A driver that only switches ROMs, such as atari/roms.asm, has no stream: no
open, no read and no cells. It can be the driver only of a program without
storage. Raised for nga.open or nga.read where such a driver is the
program's.
main.ngp
include "atari/800xl.ngp"
include "atari/roms.ngp"
modules { "main.asm" }
main.asm
.proc entry
nga.read
sta $0600
rts
.endp
error[NGA2441]: `nga.read` is used, and the driver switches ROMs and has no stream to read
--> main.asm:2:13
|
2 | nga.read
| ^^^^
A program that reads storage needs the driver of that storage, which streams.
Where no driver is declared at all, the finding is NGA2313.
NGA2442
error · {name} is a region of registers or reserved memory, and a section stands only in one of RAM or ROM
in NAME with a Region's name puts the Section inside that Region, as
in underOsLow does on the XL. The solver places Sections only in ram and
rom Regions, so a register or reserved one has no room to give.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
container xex
main.asm
.section in dos
buffer .res 64
.ends
.proc entry
lda buffer
rts
.endp
error[NGA2442]: `dos` is a region of registers or reserved memory, and a section stands only in one of RAM or ROM
--> main.asm:1:13
|
1 | .section in dos
| ^^^
Name a ram Region instead. Where the Section has to stand at an address
inside a reserved Region, pin it there with at, which is a warning,
NGA5218.
NGA2443
error · {name} is a pane, and a section in a pane names no other place with in
in may be repeated to give the solver a choice of Regions:
.section in underOsLow, in underOsHigh. A Pane is no such choice. Its
Sections stand in the Bank the Pane is given and nowhere else, so a Pane is
named alone.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in ext { level }
container xex
main.asm
.section in level, in underOsLow
map .byte 1
.ends
.proc entry
rts
.endp
error[NGA2443]: `level` is a pane, and a section in a pane names no other place with `in`
--> main.asm:1:13
|
1 | .section in level, in underOsLow
| ^^^^^
Keep the Pane or the Regions, not both. A unit set is named alone too,
NGA2451.
NGA2444
error · {section} is in no pane, and only a section a pane holds has a linear address
linearSectionAddress and linearFamilyAddress are where a Section stands in
the medium's own memory, which a blitter or a video chip reads as one. Only a
Section in a Bank has one: a Section in a Pane of a Window that shows a
linear unit set, or a Section in such a unit set itself. This Section is in
neither.
main.ngp
include "atari/mariacel.ngp"
modules { "main.asm" }
container xex
main.asm
.section
ship .byte 1, 2, 3, 4
.ends
.proc entry
lda #<ship.linearSectionAddress
rts
.endp
error[NGA2444]: `ship` is in no pane, and only a section a pane holds has a linear address
--> main.asm:6:20
|
6 | lda #<ship.linearSectionAddress
| ^^^^^^^^^^^^^^^^^^^^
Put the Section in a Pane of the Window that shows the unit set, here
panes in cel8000 { textures }, or in the unit set, .section in sdram.
NGA2445
error · {section} is in pane {pane}, pinned to a named state, and only a bank of a unit set has a linear address
A Pane pinned to a named state, panes in WINDOW = STATE { ... }, stands in a
state of the hardware and not in a Bank of a unit set, so it has no linear
address. On MariaCEL the blitter's tables are such Panes, and cel.draw is
one of their Sections.
main.ngp
include "atari/mariacel.ngp"
modules { "main.asm" }
container xex
main.asm
.proc entry
lda #<cel.draw.linearSectionAddress
rts
.endp
error[NGA2445]: `cel.draw` is in pane `sprlist`, pinned to a named state, and only a bank of a unit set has a linear address
--> main.asm:2:24
|
2 | lda #<cel.draw.linearSectionAddress
| ^^^^^^^^^^^^^^^^^^^^
Ask for linearSectionAddress only of a Section in a Pane the solver gives a
Bank.
NGA2446
error · {section} is in pane {pane}, and {units}, whose banks it stands in, declares no linear range
A unit set has linear addresses when its units line in the variant ends in
linear FROM .. TO, which says where its Banks lie in the medium's memory.
atari/mariacel.ngp declares one for sdram. atari/130xe.ngp declares none
for extension.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in ext { level }
container xex
main.asm
.section in level
map .byte 1
.ends
.proc entry
lda #<map.linearSectionAddress
rts
.endp
error[NGA2446]: `map` is in pane `level`, and `extension`, whose banks it stands in, declares no linear range
--> main.asm:6:19
|
6 | lda #<map.linearSectionAddress
| ^^^^^^^^^^^^^^^^^^^^
Where only the CPU reads the Banks, there is no linear address to ask for:
read the Section through the Window, under a .with. Where other hardware
reads them as one memory, the variant's units line is where that is
declared.
NGA2447
error · {section} is in the family {pane}, whose every member holds it: its address in the first is linearFamilyAddress
Every member of a family holds the Section at the same address in its own
Bank, so the Section has one linear address per member. Ask for the first
member's with linearFamilyAddress. Member n is n Banks further on, each
Bank as long as the Window.
main.ngp
include "atari/mariacel.ngp"
modules { "main.asm" }
panes in cel8000 { frames[2] }
container xex
main.asm
.section in frames
pixels .res 256
.ends
.proc entry
lda #<pixels.linearSectionAddress
rts
.endp
error[NGA2447]: `pixels` is in the family `frames`, whose every member holds it: its address in the first is `linearFamilyAddress`
--> main.asm:6:22
|
6 | lda #<pixels.linearSectionAddress
| ^^^^^^^^^^^^^^^^^^^^
The reverse, linearFamilyAddress of a Section in a single Pane, is
NGA2448.
NGA2448
error · {section} is in {pane}, which is no family: its address is linearSectionAddress
linearFamilyAddress is for a Section in a family, whose members each hold
it. Raised for a Section in a single Pane, and for one that stands in a unit
set itself, whose name the message gives in place of a Pane's.
main.ngp
include "atari/mariacel.ngp"
modules { "main.asm" }
panes in cel8000 { textures }
container xex
main.asm
.section in textures
ship .byte 1, 2, 3, 4
.ends
.proc entry
lda #<ship.linearFamilyAddress
rts
.endp
error[NGA2448]: `ship` is in `textures`, which is no family: its address is `linearSectionAddress`
--> main.asm:6:20
|
6 | lda #<ship.linearFamilyAddress
| ^^^^^^^^^^^^^^^^^^^
Write linearSectionAddress. The reverse is NGA2447.
NGA2449
error · a linear address is the medium's and not the CPU's: take its bytes with <, > and >>
A linear address may be wider than 16 bits, and the CPU cannot reach memory
through it in any case. So it is refused as an instruction's operand and as an
item of .word. The Labels of a Section in a unit set are linear addresses
themselves, and the same holds for them.
main.ngp
include "atari/mariacel.ngp"
modules { "main.asm" }
panes in cel8000 { textures }
container xex
main.asm
.section in textures
ship .byte 1, 2, 3, 4
.ends
.section
list .word ship.linearSectionAddress
.ends
.proc entry
lda list
rts
.endp
error[NGA2449]: a linear address is the medium's and not the CPU's: take its bytes with `<`, `>` and `>>`
--> main.asm:6:15
|
6 | list .word ship.linearSectionAddress
| ^^^^^^^^^^^^^^^^^^^^^^^^^
Take its bytes and hand them to the hardware that reads the medium:
<ship.linearSectionAddress, >ship.linearSectionAddress and
<(ship.linearSectionAddress >> 16), as immediates or items of .byte.
NGA2450
error · {name} declares no linear range, and a section stands in a unit set only at a linear address
A Section in a unit set stands in the medium's memory at a linear address,
and has no other. A set whose units line declares no linear range gives it
none.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
container xex
main.asm
.section in extension
map .byte 1
.ends
.proc entry
rts
.endp
error[NGA2450]: `extension` declares no linear range, and a section stands in a unit set only at a linear address
--> main.asm:1:13
|
1 | .section in extension
| ^^^^^^^^^
For memory the CPU reads through a Window, declare a Pane in that Window,
panes in ext { level }, and write .section in level.
NGA2451
error · {name} is a unit set, and a section in one names no other place with in
in repeated gives the solver a choice of Regions. A unit set is not one of
them: a Section in it has a linear address and no address the CPU uses, so the
set is named alone.
main.ngp
include "atari/mariacel.ngp"
modules { "main.asm" }
container xex
main.asm
.section in sdram, in ram
ship .byte 1, 2, 3, 4
.ends
.proc entry
rts
.endp
error[NGA2451]: `sdram` is a unit set, and a section in one names no other place with `in`
--> main.asm:1:13
|
1 | .section in sdram, in ram
| ^^^^^
Keep the unit set or the Regions, not both. A Pane is named alone too,
NGA2443.
NGA2452
error · {section} is {what}, and a unit set holds only what the medium reads
A unit set holds data the medium reads, such as a blitter's textures. The CPU
has no address in it, so it runs no code there, and zero page is the CPU's own
memory. Raised for a Proc and for a zeropage Section.
main.ngp
include "atari/mariacel.ngp"
modules { "main.asm" }
container xex
main.asm
.proc draw, in sdram
rts
.endp
.proc entry
rts
.endp
error[NGA2452]: `draw` is a proc, and a unit set holds only what the medium reads
--> main.asm:1:16
|
1 | .proc draw, in sdram
| ^^^^^
Code that runs in the Window that shows the set stands in a Pane of that
Window: panes in cel8000 { code }, and .proc draw, in code.
NGA2453
error · {section} stands in {units}, where its address is linear, and it has no runtime one
Raised for runtimeSectionAddress of a Section that stands in a unit set.
main.ngp
include "atari/mariacel.ngp"
modules { "main.asm" }
container xex
main.asm
.section in sdram
ship .byte 1, 2, 3, 4
.ends
.proc entry
lda #<ship.runtimeSectionAddress
rts
.endp
error[NGA2453]: `ship` stands in `sdram`, where its address is linear, and it has no runtime one
--> main.asm:6:20
|
6 | lda #<ship.runtimeSectionAddress
| ^^^^^^^^^^^^^^^^^^^^^
Its Labels are its linear address: take their bytes, <ship, >ship and
<(ship >> 16). For memory the CPU reads, put the Section in a Pane instead.
NGA2454
error · this divides by zero
An expression divides by something that comes to zero. The division has no
value, so it is refused where it is written, whatever the expression is for: an
operand, a .byte item, the size of a .res, a pin, an alignment or an
assertion. The divisor is usually a constant that one configuration sets to
zero.
columns = 0
.section
row .res 40 / columns
.ends
.proc entry
rts
.endp
error[NGA2454]: this divides by zero
--> main.asm:4:19
|
4 | row .res 40 / columns
| ^^^^^^^
Give the divisor a value that is not zero, or write the expression so that it
does not divide where that value is zero, as columns ? 40 / columns : 0.
NGA2455
error · this comes to a number past what 64 bits hold
An expression comes to a number that 64 signed bits do not hold, past -9,223,372,036,854,775,808 or 9,223,372,036,854,775,807. Arithmetic is done in those bits and the answer has no value, so it is refused where it is written. In practice the operands are themselves near the limit, often a constant negated or multiplied once too often.
least = 0 - $7FFFFFFFFFFFFFFF - 1
.proc entry
ldx #-least
rts
.endp
error[NGA2455]: this comes to a number past what 64 bits hold
--> main.asm:4:14
|
4 | ldx #-least
| ^^^^^^
Keep the arithmetic within 64 bits. A value meant for a byte or a word is
usually wanted reduced first, as least & $FF.
NGA2456
error · {name} {what}; a result declared elsewhere names the reservation another proc returns in
Raised where .declare ret names another Proc's result and the name is not
one. It has to be the reservation another Proc declares its result over, with
every byte in memory, as this Module sees it. A name that resolves to nothing
raises this, and so do an argument's reservation and a result a register
carries part of.
.proc low
.declare arg u8
value .ztemp 1
.declare ret u16
result .ztemp 2
rts
.endp
.proc either
jsr low
rts
.declare ret low.value
.endp
.proc entry
jsr either
rts
.endp
error[NGA2456]: `low.value` is no reservation a proc declares its result in; a result declared elsewhere names the reservation another proc returns in
--> main.asm:12:22
|
12 | .declare ret low.value
| ^^^^^^^^^
Name the reservation under the other Proc's .declare ret, here
low.result. If that result is partly in a register, declare this result over
a reservation of its own and copy the value into it.
NGA3001
error · .with applies to the instruction or macro use on the line below, and this is not one
.with covers the one statement on the next line, and that statement has to be
an instruction or a macro use. A .byte, a directive, or a Label on a line of
its own is refused, and so is a .with with nothing after it. An .off,
.own, .root, .alt or another .with may stand between.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in ext { level }
container xex
main.asm
.section in level
map .byte 1
.ends
.proc entry
.with level
@first
lda map
rts
.endp
error[NGA3001]: `.with` applies to the instruction or macro use on the line below, and this is not one
--> main.asm:6:9
|
6 | .with level
| ^^^^^
Write the Label on the line of the instruction, @first lda map, or above the
.with.
NGA3002
error · {name} is a {kind}, and .with takes a pane, a family with , x, a window with , x or a window = STATE
Each form of .with takes one kind of name. .with PANE takes a Pane or a
member of a family, FAMILY + n. The , x form takes a family or a Window,
and = STATE a Window. Raised for any other pairing, such as a Window alone or
a family alone.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in ext { slots[3] }
container xex
main.asm
.section in slots
row .res 40
.ends
.proc entry
.with slots
lda row
rts
.endp
error[NGA3002]: `slots` is a family, and `.with` takes a pane, a family with `, x`, a window with `, x` or a window `= STATE`
--> main.asm:6:15
|
6 | .with slots
| ^^^^^
Name a member, .with slots + 0, or show the member whose state is in X
with .with slots, x.
NGA3003
error · {state} is not a named state of window {window}
WINDOW = STATE names one of the states the variant lists after views. A
name the Window does not list names nothing. Neither does the name of a unit
set it lists, which gives one state per Bank and has no name of its own.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
container xex
main.asm
.proc entry
.with ext = extension
nop
rts
.endp
error[NGA3003]: `extension` is not a named state of window `ext`
--> main.asm:2:21
|
2 | .with ext = extension
| ^^^^^^^^^
Show a Bank through the Pane that stands in it, .with PANE, or by number
with .with ext, x.
NGA3005
warning · {window} shows this state already, so this .with changes nothing
The .with shows what is shown already. That is the case in a Proc declared
under a Pane, for a .with of that Pane, and in a Pane's own code, for a
.with of the same Pane. The switch is still written, and costs bytes and
time.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in ext { level }
container xex
main.asm
.section in level
map .byte 1
.ends
.proc readMap, under level
.with level
lda map
rts
.endp
.proc entry
.with level
jsr readMap
rts
.endp
warning[NGA3005]: `ext` shows this state already, so this `.with` changes nothing
--> main.asm:6:9
|
6 | .with level
| ^^^^^^^^^^^
Remove the .with.
NGA3006
error · {window} is shown by a .with on this statement already, and a window shows one state at a time
Several .with lines over one statement show one state each, on different
Windows. Two on the same Window would need it to show two states at once.
Raised also where a .with in a macro body names the Window that the .with
over the use shows already.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in ext { level, tables }
container xex
main.asm
.section in level
map .byte 1
.ends
.section in tables
table .byte 2
.ends
.proc copy
lda table
sta map
rts
.endp
.proc entry
.with level
.with tables
jsr copy
rts
.endp
error[NGA3006]: `ext` is shown by a `.with` on this statement already, and a window shows one state at a time
--> main.asm:17:9
|
17 | .with tables
| ^^^^^^^^^^^^
Split the work into two statements, each under its own .with, and carry the
data between them in memory outside the Window.
NGA3007
error · a statement under .with may not {mnemonic}: it would leave the window as shown
In a Proc declared under a Pane, a .with on that Pane's Window is followed
by code the tool adds, which shows the Pane again, since the Proc returns to
code that expects it shown. An rts or rti as the statement, or in a macro
used there, returns before that code runs. A jsr is allowed, because it
returns to where the added code stands.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in ext { level, tables }
container xex
main.asm
.section in level
map .byte 1
.ends
.section in tables
table .byte 2
.ends
.macro fetch
lda table
rts
.endm
.proc readTable, under level
.with tables
fetch
.endp
.proc entry
.with level
jsr readTable
rts
.endp
error[NGA3007]: a statement under `.with` may not `rts`: it would leave the window as shown
--> main.asm:16:9
|
16 | fetch
| ^^^^^
Return on a line of its own, after the statement. Outside such a Proc nothing
is shown again, and a return under .with is allowed.
NGA3008
error · what this statement reaches names {symbol}, in pane {pane}, which this .with does not show
A .with shows one state of its Window. A statement under it that reaches a
Section of another Pane is reaching memory that is not there. The tool follows
every jsr and jmp out of the statement, so a routine two calls away that
names such a Section is caught too, and NGA3009 points at the
name.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in ext { level, tables }
container xex
main.asm
.section in level
drawLevel
rts
.ends
.proc entry
.with tables
jsr drawLevel
rts
.endp
error[NGA3008]: what this statement reaches names `drawLevel`, in pane `level`, which this `.with` does not show
--> main.asm:7:9
|
7 | .with tables
| ^^^^^^^^^^^^
note: `drawLevel` is named here
--> main.asm:8:13
|
8 | jsr drawLevel
| ^^^^^^^^^
Show the Pane the statement reaches. The rule holds over Symbols: memory reached through a pointer is not checked.
NGA3009
note · {symbol} is named here
Follows NGA3008, and NGA3017 where that is raised
at a .with. It points at the place the Symbol is named, which may be in a
routine the statement calls rather than in the statement itself.
NGA3011
error · {symbol} is in state {state} of window {window}, and nothing shows that state here
A Pane pinned to a named state, as atari/mariacel.ngp pins sprlist with
panes in cel4000 = sprlist { sprlist }, is shown by that state and no other.
Its Sections are named only where the state is shown: under a .with that
shows it, in a Proc declared under the Pane, or in the Pane's own code.
main.ngp
include "atari/mariacel.ngp"
modules { "main.asm" }
container xex
main.asm
.proc entry
lda #0
sta cel.draw
rts
.endp
error[NGA3011]: `cel.draw` is in state `sprlist` of window `cel4000`, and nothing shows that state here
--> main.asm:3:13
|
3 | sta cel.draw
| ^^^^^^^^
Put .with cel4000 = sprlist, or .with sprlist, over the statement. For a
Pane the solver gives a Bank, the same rule is NGA2412.
NGA3012
error · {directive} applies to the instruction or data on the line below, and this is not one
.own and .root cover the statement on the next line, which takes an
address: an instruction, a .byte or a .word. Raised where that line is
anything else: a .res, a .dispatch, a Label on a line of its own, or
nothing at the end of the file.
.section
.own entry
table
.word handler
.ends
.proc handler
rts
.endp
.proc entry
jmp (table)
.endp
error[NGA3012]: `.own` applies to the instruction or data on the line below, and this is not one
--> main.asm:2:9
|
2 | .own entry
| ^^^^
Put the directive directly above the statement. A Label goes on the
statement's own line, table .word handler, or above the directive.
NGA3013
error · .own and .root on one statement: an address is followed by this section or by the hardware, not both
An address under .root goes to the hardware: what it names becomes a Root,
and no jump of the program's reaches it through this statement. An address
under .own is followed by the program. One statement says one or the other.
.proc entry
.own
.root vbd
ldx #>handler
rts
.endp
.proc handler
rts
.endp
error[NGA3013]: `.own` and `.root` on one statement: an address is followed by this section or by the hardware, not both
--> main.asm:3:9
|
3 | .root vbd
| ^^^^^
Keep the one that is true of the address.
NGA3014
error · .root hands the address to the one holder that takes it, and this names {count}
.root names the Holder that takes the address, one of the holder names the
Target declares, such as vbd or dlist. A statement hands one address to
one Holder, so a .root with no name or with two is refused.
.proc entry
.root
ldx #>handler
rts
.endp
.proc handler
rts
.endp
error[NGA3014]: `.root` hands the address to the one holder that takes it, and this names none
--> main.asm:2:9
|
2 | .root
| ^^^^^
Memory that something outside the program uses for as long as its Module is
present has no statement that hands it over. Mark that Section root instead.
NGA3015
error · this section is in pane {pane} of window {window}, and code in a pane cannot switch its own window: the switch would take the code with it; a proc in fixed, .proc NAME, under {pane}, does it
Code in a Pane stands in the Window's memory, so a .with on the same Window
would switch away the code that is running. Raised for code in a Pane and in a
family of the Window. A .with of the code's own Pane is the warning
NGA3005 instead.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in ext { level, tables }
container xex
main.asm
.section in tables
table .byte 2
.ends
.section in level
drawLevel
.with tables
lda table
rts
.ends
.proc entry
.with level
jsr drawLevel
rts
.endp
error[NGA3015]: this section is in pane `level` of window `ext`, and code in a pane cannot switch its own window: the switch would take the code with it; a proc in fixed, `.proc NAME, under level`, does it
--> main.asm:7:9
|
7 | .with tables
| ^^^^^^^^^^^^
Do the switch in a Trampoline: a Proc outside the Window, declared
.proc NAME, under level, which holds the .with and is called from the
Pane's code. See Panes.
NGA3016
error · under {name} {reason}
under declares the Pane a Proc runs with shown. It is refused on a family,
whose member is known only at run time; on a .section, since data does not
run; and beside in, since a Proc under a Pane stands outside the Window and
not in a Pane of it.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in ext { slots[3] }
container xex
main.asm
.section in slots
row .res 40
.ends
.proc clearRow, under slots
lda #0
sta row
rts
.endp
.proc entry
rts
.endp
error[NGA3016]: `under slots` names a family, whose member is known at run time alone
--> main.asm:5:23
|
5 | .proc clearRow, under slots
| ^^^^^
Code that works on a family's members stands in the family and is called
under .with slots, x, as in
Panes.
NGA3017
error · {symbol} runs under pane {pane}, which must be shown where it is called, and here it is not
A Proc declared under a Pane names that Pane's Sections on the promise that
the Pane is shown whenever it runs. Every call is held to it. The caller is
the Pane's own code, another Proc under the same Pane, or a statement under a
.with that shows the Pane.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in ext { level }
container xex
main.asm
.section in level
map .byte 1
.ends
.proc readMap, under level
lda map
rts
.endp
.proc entry
jsr readMap
rts
.endp
error[NGA3017]: `readMap` runs under pane `level`, which must be shown where it is called, and here it is not
--> main.asm:11:13
|
11 | jsr readMap
| ^^^^^^^
Put .with level over the call.
NGA4501
warning · phase {phase} is not reachable from the entry phase
A Phase that no chain of then from the entry Phase reaches. Nothing enters
it, yet it is built, placed and carried in the Container. It is usually a
then that was renamed or removed.
main.ngp
modules { "main.asm" }
phase game { needs main }
phase scores { needs main entry showScores }
entry game
main.asm
.proc entry
@stop jmp @stop
.endp
.proc showScores
@stop jmp @stop
.endp
warning[NGA4501]: phase `scores` is not reachable from the entry phase
--> main.ngp:4:7
|
4 | phase scores { needs main entry showScores }
| ^^^^^^
Add the then that leads to the Phase, or remove the Phase. Raise the warning
to an error with deny NGA4501 in the
diagnostics block of a Project where this
must not happen.
NGA4505
warning · {section} is pinned at {address:hex} and nothing reaches it, so it is dropped; mark it root if the hardware reads it
Prune drops a Section that nothing reaches from a Root, pinned or not. A pin usually means something expects the memory at that address, often the hardware or an OS that no instruction of the program names. Once the Section is dropped, the solver may give that memory to another Section.
.section absolute at $9F00
mailbox .res 16
.ends
.proc entry
rts
.endp
warning[NGA4505]: `mailbox` is pinned at $9F00 and nothing reaches it, so it is dropped; mark it `root` if the hardware reads it
--> main.asm:1:1
|
1 | .section absolute at $9F00
| ^^^^^^^^
Mark the Section root if something outside the program reads or writes it.
Otherwise remove the pin, or the Section. See
Roots.
NGA4601
error · the address of {section} is taken, and a temporary has none to give: its bytes are another's while it is not active
A Temporary shares its bytes with Temporaries that are never active at the
same time. An address of it, once taken, could be used while another
Temporary holds those bytes. Raised at the statement that takes the address,
where no .own stands over it.
.proc entry
buffer .temp 8
lda #<buffer
rts
.endp
error[NGA4601]: the address of `entry.buffer` is taken, and a temporary has none to give: its bytes are another's while it is not active
--> main.asm:3:9
|
3 | lda #<buffer
| ^^^^^^^^^^^^
Where a routine reads or writes through the pointer, name it with .own NAME
on each taking. It then becomes an Owner of the Temporary, as a routine that
names it is. Otherwise reserve the memory with .res, which never shares.
NGA4602
error · {section} is temporary while {owner} runs, and {owner} can be entered again before it returns
A call from an Owner of the Temporary can come back into that Owner, through another Section, before the Owner returns. The second Activation uses the same bytes and destroys the value of the first.
.proc walk
depth .ztemp 1
sta depth
jsr step
lda depth
rts
.endp
.proc step
jsr walk
rts
.endp
.proc entry
jsr walk
rts
.endp
error[NGA4602]: `walk.depth` is temporary while `walk` runs, and `walk` can be entered again before it returns
--> main.asm:2:1
|
2 | depth .ztemp 1
| ^^^^^^^^^^^^^^^^
Keep such a value in a plain .res, and save it on the stack around the call
where it has to survive the call, or break the cycle. A path that comes back
through a .transition is not such a cycle.
NGA4603
warning · nothing this statement names is code or a temporary, so .own changes nothing
.own says who follows an address of code, or who owns a Temporary whose
address is taken, and the statement under it takes neither. An address of data
needs no .own. Over the jmp (ptr) itself it does nothing either, since the
edge belongs to the statement that took the address.
.section
colors .byte $28, $CA, $94
.ends
.proc entry
.own
lda #<colors
rts
.endp
warning[NGA4603]: nothing this statement names is code or a temporary, so `.own` changes nothing
--> main.asm:7:9
|
7 | lda #<colors
| ^^^^^^^^^^^^
Remove the .own, or move it to the statement that takes the address of the
code.
NGA4606
error · the address of {section} is taken and nothing says who follows it: .own if this section does, .own NAME if another does, .root HOLDER if the hardware does
Taking the address of code tells the tool nothing about who will jump to it,
so the statement has to say: .own for this Section, .own NAME for another,
.root HOLDER for the hardware, naming which. An address of data needs none
of this.
.section
actions .word fire
.ends
.proc fire
rts
.endp
.proc entry
lda actions
rts
.endp
error[NGA4606]: the address of `fire` is taken and nothing says who follows it: `.own` if this section does, `.own NAME` if another does, `.root HOLDER` if the hardware does
--> main.asm:2:9
|
2 | actions .word fire
| ^^^^^^^^^^
Trace needs the jump the address stands for to know which Sections can be active at once. See Roots.
NGA4607
error · {section} jumps through a pointer and owns no address of code, so nothing says where the jump goes
A jump through a pointer goes wherever the pointer holds. The tool follows the addresses of code the program owns, so a Section that jumps that way has to own the code it can reach.
.section zeropage
vector .res 2
.ends
.proc entry
jmp (vector)
.endp
error[NGA4607]: `entry` jumps through a pointer and owns no address of code, so nothing says where the jump goes
--> main.asm:6:9
|
6 | jmp (vector)
| ^^^^^^^^^^^^
Put .own on the statements that take the addresses the pointer is loaded
with, or .own NAME naming this Section where another Section takes them. A
table of positions of the jumping Section itself is a .dispatch. This often
comes together with NGA4606, at the other end of the same
pointer.
NGA4608
warning · nothing this statement names is a section, so .root marks nothing
.root hands what the statement names to the hardware, and the statement
names no Section: only a number or a Constant. The .root usually stands one
line off the statement that takes the address.
main.ngp
target { holder vbd }
modules { "main.asm" }
main.asm
.proc entry
.root vbd
lda #7
rts
.endp
warning[NGA4608]: nothing this statement names is a section, so `.root` marks nothing
--> main.asm:3:9
|
3 | lda #7
| ^^^^^^
Move it down to the statements that take the address. Before a call of
SETVBV on the XL, that is .root vbd over ldx #>handler and again over
ldy #<handler.
NGA4609
error · {name} is not a section, a proc or a label, and .own names who follows the address
.own NAME names the Section that follows the address, by any of its Labels;
a Proc's name is one. A name that is something else, such as a Constant, or
that is not defined, is refused.
VDSLST = $0200
.proc entry
.own VDSLST
lda #<handler
sta VDSLST
rts
.endp
.proc handler
rti
.endp
error[NGA4609]: `VDSLST` is not a section, a proc or a label, and `.own` names who follows the address
--> main.asm:4:14
|
4 | .own VDSLST
| ^^^^^^
Name the code that jumps through the pointer, not the pointer. Where the
hardware does the jumping, write .root HOLDER instead, here .root dli on
the XL.
NGA4611
error · {section} is handed to {follower}, which is present in phase {phase} where {section} is not: a jump from there would land in nothing
.own NAME hands an address of code to another Section, which jumps to it
later. Residency is per Module, so this is raised where the follower's Module
is present in a Phase and the code's Module is not: here a resident dispatcher
and a routine of game. Reported once per taking and follower, for the first
such Phase.
main.ngp
modules { "main.asm" "game.asm" }
resident { main }
phase game { needs game then over entry gameStart }
phase over { entry gameOver }
entry game
main.asm
.export dispatch, ptr
.section zeropage
ptr .res 2
.ends
.proc dispatch
jmp (ptr)
.endp
.proc gameOver
@stop jmp @stop
.endp
game.asm
.proc gameStart
lda handler
sta ptr
lda handler + 1
sta ptr + 1
jsr dispatch
.transition over
.own dispatch
handler .word step
.endp
.proc step
rts
.endp
error[NGA4611]: `step` is handed to `dispatch`, which is present in phase `over` where `step` is not: a jump from there would land in nothing
--> game.asm:9:9
|
9 | handler .word step
| ^^^^^^^^^^
Hand the address to a follower in the code's own Module, which is present
exactly where the code is, or make the code's Module present wherever the
follower is. Under a bare .own the follower is the Section that takes the
address, and the same mistake is NGA2414.
NGA4612
warning · control runs off the end of {section} into whatever is placed after it: end it with a jump or a return, or chain a proc to it with then
Sections are placed independently, so control that runs past the last statement of one goes into whatever the solver put after it. Raised at the statement some run leaves from: an instruction that goes on, a call of a routine that may return, a branch to the end of the Section, or code that runs into data.
.proc entry
jsr init
.endp
.proc init
rts
.endp
warning[NGA4612]: control runs off the end of `entry` into whatever is placed after it: end it with a jump or a return, or chain a proc to it with `then`
--> main.asm:2:9
|
2 | jsr init
| ^^^^^^^^
A brk ends a Section as a return or a jump does. To fall into the next Proc
on purpose, chain it with
.endp then NAME, which the solver places
right after. Where a branch at the end is always taken, .off NGA4612 on it
says so.
NGA4613
error · phase {phase} is final, and {entry}, where it is entered, may return: nothing is kept there for a return to land on
A final Phase is one the program never leaves. The tool keeps out of it the
code that runs only when the program ends or returns. A return from the
Phase's entry would land in that code, which is not there.
main.ngp
modules { "main.asm" }
phase game { needs main final }
entry game
main.asm
CONSOL = $D01F
.proc entry
@frame lda CONSOL
cmp #6
bne @frame
rts
.endp
error[NGA4613]: phase `game` is final, and `entry`, where it is entered, may return: nothing is kept there for a return to land on
--> main.ngp:3:26
|
3 | phase game { needs main final }
| ^^^^^
End every path of the entry in a loop that does not return, or drop final.
NGA4614
error · {name} is no holder: a target declares the hardware that holds a section with holder
.root and .release name a Holder: hardware that holds one Section at a
time, which the Target declares with holder. atari/800xl.ngp and
atari/130xe.ngp declare nine, from dlist to dosini. The stand-in Target
declares none.
.proc entry
.root dlist
lda #<list
rts
.endp
.section
list .byte $70
.ends
error[NGA4614]: `dlist` is no holder: a `target` declares the hardware that holds a section with `holder`
--> main.asm:2:15
|
2 | .root dlist
| ^^^^^
Include the variant of the machine, or declare the Holder in a target block
of the Project, target { holder dlist }. See
Roots.
NGA5102
error · {mnemonic} has no {mode} form
The processor has no instruction for this mnemonic and this operand. Either
the form does not exist at all, as sta #1, or it exists for one
PlacementClass only: stx takes ,y and sty takes ,x only with a
zero-page operand. The message names the form that is missing: absolute,y
where only the zero-page form exists, as here, and direct,y where neither
width has one.
.section
buffer .res 16
.ends
.proc entry
ldy #0
stx buffer,y
rts
.endp
error[NGA5102]: `stx` has no absolute,y form
--> main.asm:7:9
|
7 | stx buffer,y
| ^^^^^^^^^^^^
buffer is absolute. Put it in a .section zeropage, or go through A
with txa and sta buffer,y.
NGA5103
error · the placement class of this operand cannot be determined, so its width cannot be either
An operand without # that is an Integer has no PlacementClass, so its
value decides whether the instruction is zero page or absolute. That value has
to be a declared value, known before any
Section has an address. tableEnd - table is an Integer with Labels at its
leaves, and has a value only after Size.
.section
table .byte 1, 2, 3
tableEnd
.ends
.proc entry
ldx #0
@loop lda table,x
inx
cpx tableEnd - table
bne @loop
rts
.endp
error[NGA5103]: the placement class of this operand cannot be determined, so its width cannot be either
--> main.asm:10:13
|
10 | cpx tableEnd - table
| ^^^^^^^^^^^^^^^^
Here the # is missing: cpx #tableEnd - table compares with the count.
Where an address is meant, write an Address, such as a Label plus an offset,
which takes its Section's PlacementClass.
NGA5104
error · this size depends on itself
The count of a .res may be written in terms of other sizes, such as
work.runtimeSectionSize or the distance between two Labels. Raised where
following those sizes leads back to the reservation itself.
.section
buffer .res buffer.runtimeSectionSize
.ends
error[NGA5104]: this size depends on itself
--> main.asm:2:9
|
2 | buffer .res buffer.runtimeSectionSize
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
A cycle through several Sections is reported once, at one of its reservations. Break it by writing one of the sizes as a Constant.
NGA5105
error · a reservation of {size:n} bytes is not a reservation
.res takes a count from 0 to 65,536. A negative count usually comes from a
subtraction of two Constants in the wrong order, or after one of them changed.
ROWS = 24
VISIBLE = 25
.section
spare .res ROWS - VISIBLE
.ends
error[NGA5105]: a reservation of -1 bytes is not a reservation
--> main.asm:5:9
|
5 | spare .res ROWS - VISIBLE
| ^^^^^^^^^^^^^^^^^^^
A Section that stands in a unit set declaring linear may reserve up to the
size of the set's Banks end to end, which can exceed 64 KB.
NGA5106
error · {value:hex} is not an address
An Integer operand without # is an address given by its value, so the
value must lie between $0000 and $FFFF. It is usually a Constant with an
offset added past the end of memory, or subtracted below zero.
SCREEN = $F000
.proc entry
lda SCREEN + $1000
rts
.endp
error[NGA5106]: $010000 is not an address
--> main.asm:4:13
|
4 | lda SCREEN + $1000
| ^^^^^^^^^^^^^^
Check the Constant and the arithmetic on it.
NGA5107
error · {mnemonic} is a {needs} instruction, and this target is a {cpu}
The Target says which processor the program is for, and a Target that names
none is a 6502. The 65SC02's additions, such as stz, bra, phx and the
(zp) modes, are refused on a 6502. So is an opcode of the 65SC02 that an
.alt names.
.section
counter .res 1
.ends
.proc entry
stz counter
rts
.endp
error[NGA5107]: `stz` is a `65sc02` instruction, and this target is a `6502`
--> main.asm:6:9
|
6 | stz counter
| ^^^^^^^^^^^
Where the machine has a 65SC02, write cpu "65sc02" in its target block;
see the Project file. Otherwise write the 6502 form,
here lda #0 and sta counter. See
Instructions.
NGA5201
error · {section} overlaps {other} at {address:hex}
Two pinned Sections claim the same bytes in a Phase both are present in. A pin is never moved, so the tool has no way to resolve it. The message names the Section reported and the pinned one it lands on.
.section absolute at $3000
screen .res 960
.ends
.section absolute at $3300
font .res 1024
.ends
error[NGA5201]: `font` overlaps `screen` at $3300
--> main.asm:5:1
|
5 | .section absolute at $3300
| ^^^^^^^^
screen reaches $33BF. Move one of the pins, or drop one and let the solver
place that Section. Sections that are never in memory at the same time, such
as reservations in Modules no Phase needs together, may be pinned at the same
address.
NGA5202
error · there is no room for {section}, which needs {size:n} bytes
Raised in two cases. A pinned Section runs past $FFFF. Or a Section that is
not pinned is larger than every range of free memory it could start in, once
its in, align and within are counted.
.section
buffer .res 40000
.ends
error[NGA5202]: there is no room for `buffer`, which needs 40,000 bytes
--> main.asm:1:1
|
1 | .section
| ^^^^^^^^
error[NGA5206]: no layout satisfies every constraint at once
error[NGA5631]: phase `(implicit)` does not fit in view `fixed`: requires 40,000 bytes, 32,768 available
note: `buffer` accounts for 40,000 bytes
--> main.asm:1:1
|
1 | .section
| ^^^^^^^^
The findings after it say the same thing for the whole program: no layout
exists (NGA5206), and the Phase needs more memory than it has
(NGA5631). With no region declared, the stand-in Target has
32 KB, at $2000-$9FFF. Make the Section smaller or split it. A zero-page
Section that does not fit is NGA5204 instead.
NGA5203
error · a pin is a declared address, and {text} is {what}
A pin is a declared value from $0000 to
$FFFF, so no Label and no size may appear in it: a pin is part of the layout,
and a Label's address is what the layout decides. In a Section that stands in a
unit set declaring linear, the pin is a linear address and may be larger.
.section absolute at $10000
table .byte 1
.ends
error[NGA5203]: a pin is a declared address, and `$10000` is past $FFFF
--> main.asm:1:22
|
1 | .section absolute at $10000
| ^^^^^^
NGA5204
error · {section} is zero page and does not fit below $100
A zeropage Section lies wholly below $100. Raised for a pin that makes it
run past $FF, and for a Section that is not pinned and is larger than every
free range of zero page the Target has.
.section zeropage at $F0
ptrs .res 32
.ends
error[NGA5204]: `ptrs` is zero page and does not fit below $100
--> main.asm:1:1
|
1 | .section zeropage at $F0
| ^^^^^^^^
Pin it lower, split it, or move what does not need zero-page addressing into
an absolute Section. With no region declared, the stand-in Target has 16
bytes of zero page, $80-$8F.
NGA5205
error · {section} is loaded from storage, and cannot live where the stream reads through, at {address:hex}
The Window the driver's stream reads through is where storage arrives. A Section that waits in storage cannot also live at the address it arrives through, because the arrival would overwrite it while it is being read.
main.ngp
include "atari/130xe.ngp"
include "atari/extension.ngp"
modules { "main.asm" "level.asm" }
phase intro { needs main then level }
phase level { needs level entry run }
entry intro
main.asm
.proc entry
.transition level
.endp
level.asm
.section absolute at $4000
map .byte 1, 2, 3
.ends
.proc run
lda map
@ jmp @-
.endp
error[NGA5205]: `map` is loaded from storage, and cannot live where the stream reads through, at $4000
--> level.asm:1:1
|
1 | .section absolute at $4000
| ^^^^^^^^
Only a pin reaches this, since the solver keeps such a Section out of the
Window by itself. Drop the pin, or put the Section in a Pane,
which has no Payload and is read where it stands. A Section with no Payload
pinned in a Window is NGA5235. See
Banks and Windows.
NGA5206
error · no layout satisfies every constraint at once
The solver showed that no layout exists. Usually a finding beside it says why:
a Phase over capacity (NGA5631, NGA5632), a Pane
over its Bank (NGA5225), too little ROM
(NGA5234), or a Section with no room at all
(NGA5202). Alone, it means that every Section fits on its own and
every sum holds, and the constraints together still cannot be met.
.section absolute align $4000
font .res $3000
.ends
.section absolute align $4000
screen .res $3000
.ends
error[NGA5206]: no layout satisfies every constraint at once
Both can start only at $4000, since $8000 plus their size runs past the
stand-in's memory. Run the build with --explain to have the tool name the
pairs no layout keeps apart (NGA5207).
NGA5207
error · {section} and {other} cannot be kept apart: no layout holds both without one lying over the other
Raised only when the build is run with --explain, after
NGA5206, and only where no sum already said why. The tool then
looks for the layout that lets the fewest pairs of Sections overlap, and names
each pair it had to let overlap. Where several choices are equally small, it
names one of them. Each Section of a pair gets an NGA5208 note.
Change one Section of each pair: its size, its align, within or pin, or
the Phases its Module is needed in.
NGA5208
note · {section} is declared here
Follows NGA5207, once for each Section of the pair, and points at
its declaration.
NGA5209
warning · the search stopped before it could show that fewer pairs would do; the ones named suffice
Follows the NGA5207 findings under --explain when the search
for the fewest overlapping pairs ran out of its budget. A layout exists if the
pairs named may overlap, but fewer pairs might be enough. Start from them all
the same.
NGA5210
error · this assertion does not hold
.assert states a condition checked after Place, when every address and size
is known. Raised where the condition is zero.
.section
colors .byte $00, $0E, $34, $86, $C8
.ends
.proc entry
lda colors
rts
.endp
.assert colors.runtimeSectionSize == 4
error[NGA5210]: this assertion does not hold
--> main.asm:10:1
|
10 | .assert colors.runtimeSectionSize == 4
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
An assertion guards something the code relies on and the solver does not know. Either the program changed under it, or the assertion is out of date.
NGA5211
error · this assertion cannot be decided
Raised where an .assert has no value even after Place. The usual cause is a
Section that Prune dropped, which has no address: an .assert is not a
Reference, so it does not keep the Section it names. A division whose divisor
comes out zero is the other cause.
.section
table .byte 1, 2, 3
.ends
.proc entry
rts
.endp
.assert table >= $2000
error[NGA5211]: this assertion cannot be decided
--> main.asm:9:1
|
9 | .assert table >= $2000
| ^^^^^^^^^^^^^^^^^^^^^^
Nothing reaches table. Name it from code that is kept, mark it root, or
remove the assertion.
NGA5212
error · an alignment is a declared power of two from 1 to 65,536, and {text} is {what}
align N takes a declared value that is a
power of two from 1 to 65,536: the start of the Section is a multiple of it.
Raised for zero, for a larger value, for one that is not a power of two, such as
align 3, and for one that is not declared.
.section absolute align 0
font .res 1024
.ends
error[NGA5212]: an alignment is a declared power of two from 1 to 65,536, and `0` is out of that range
--> main.asm:1:25
|
1 | .section absolute align 0
| ^
NGA5213
error · a boundary is a declared count of bytes from 1 to 65,536, and {text} is {what}
within N takes a declared value from 1 to 65,536, as align does
(NGA5212), but need not be a power of two: the Section does not
cross a multiple of it. within 256 keeps a Section in one page.
.section absolute within 0
list .res 32
.ends
error[NGA5213]: a boundary is a declared count of bytes from 1 to 65,536, and `0` is out of that range
--> main.asm:1:26
|
1 | .section absolute within 0
| ^
NGA5214
error · {section} is {size:n} bytes, and cannot lie within a boundary of {boundary:n}
within N keeps a Section from crossing a multiple of N, so the Section can
be at most N bytes. Raised before the solver is asked, since no start would
do.
.section absolute within 256
sines .res 320
.ends
error[NGA5214]: `sines` is 320 bytes, and cannot lie within a boundary of 256
--> main.asm:1:1
|
1 | .section absolute within 256
| ^^^^^^^^
Split the Section into parts that each fit, each with its own within, or
widen the boundary.
NGA5215
error · {section} is pinned at {address:hex}, which is not aligned to {alignment:n}
A pin has to satisfy the rest of the Section's placement. Here the address
after at is not a multiple of the align.
.section absolute at $3200 align 1024
font .res 1024
.ends
error[NGA5215]: `font` is pinned at $3200, which is not aligned to 1,024
--> main.asm:1:1
|
1 | .section absolute at $3200 align 1024
| ^^^^^^^^
Move the pin to a multiple, or drop the at and let the solver choose an
aligned address.
NGA5216
error · {section} is pinned at {address:hex}, and reaches {last:hex} across a boundary of {boundary:n}
A pinned Section with within N must not cross a multiple of N. This pin
starts close enough to one that the Section's last byte lies past it.
.section absolute at $33F0 within 1024
dlist .res 32
.ends
error[NGA5216]: `dlist` is pinned at $33F0, and reaches $340F across a boundary of 1,024
--> main.asm:1:1
|
1 | .section absolute at $33F0 within 1024
| ^^^^^^^^
Move the pin, or drop the at and let the solver find a start that keeps the
Section inside the boundary.
NGA5217
error · {section} is pinned at {address:hex}, in the register region {region}, where nothing can be placed
A register Region is hardware, and nothing the program places can stand
there. A pin into one is an error, where a pin into a reserved Region is a
warning (NGA5218).
main.ngp
target {
region $0080 .. $00FF ram
region $2000 .. $BFFF ram
region gtia $D000 .. $D01F register
}
modules { "main.asm" }
main.asm
.section absolute at $D000
hposp0 .res 1
hposp1 .res 1
.ends
error[NGA5217]: `hposp0` is pinned at $D000, in the register region `gtia`, where nothing can be placed
--> main.asm:1:1
|
1 | .section absolute at $D000
| ^^^^^^^^
note: the region `gtia` is declared here
--> main.ngp:4:3
|
4 | region gtia $D000 .. $D01F register
| ^^^^^^
Name a register in the target block instead, as register HPOSP0 $D000,
and every Module sees the name; see
the Project file. Memory that another chip
reads, such as a Lynx display buffer over Mikey's registers, is declared
foreign and root, and may lie there.
NGA5218
warning · {section} is pinned at {address:hex}, in the reserved region {region}
A reserved Region belongs to something else, usually the machine or its DOS.
A pin puts a Section there anyway, which the tool allows and reports. Read it
as a question: is this Region really reserved, or is this pin really wanted.
main.ngp
target {
region $0080 .. $00FF ram
region dos $0700 .. $1FFF reserved
region $2000 .. $BFFF ram
}
modules { "main.asm" }
main.asm
.section absolute at $0700
buffer .res 16
.ends
.proc entry
lda buffer
rts
.endp
warning[NGA5218]: `buffer` is pinned at $0700, in the reserved region `dos`
--> main.asm:1:1
|
1 | .section absolute at $0700
| ^^^^^^^^
note: the region `dos` is declared here
--> main.ngp:3:3
|
3 | region dos $0700 .. $1FFF reserved
| ^^^^^^
Not raised for a foreign Section, nor for a Module the Container's load
needs, whose memory the variant reserves for it. A pin into a register Region
is an error instead, NGA5217, and so is a pin into a rom Region
of a Section that is not read-only, NGA5233.
NGA5219
error · the search found no layout within its budget, and no sum shows that none exists
The solver's search has a budget. Raised where it ran out before finding a
layout or showing that none exists, and no sum over a Phase refused the
program first. It does not mean that no layout exists. The
NGA5220 note names the pool with the least room left, which is
where to look first.
Many pins that cut memory into small holes, with many Sections about the size
of those holes, make the search hard. Free some room in the pool the note
names, or drop pins and alignments the program does not need. --explain
does not run here, since nothing was shown to explain.
NGA5220
note · phase {phase} has the least room left in {pool}: {free:n} of {available:n} bytes
Follows NGA5219. It names the Phase and the pool, view fixed
or the zero page, whose sum came closest to refusing the program, and how many
of its bytes are free.
NGA5222
error · there is no storage for {section}, which needs {size:n} bytes
A Section with a Payload waits in storage until a Transition loads it, and so
does every Frame. Raised where storage has no free run long enough for this
one after what was placed before it. The size is that of the stored form, so a
transform changes it. A Frame is named by its edge, as
frame intro -> level.
main.ngp
target {
region $0080 .. $00FF ram
region $2000 .. $BFFF ram
register PORTB $D301
units extension 1
window ext $4000 .. $5FFF views extension
}
storage { units extension }
modules { "atari/portb.asm" "main.asm" "level.asm" }
resident { portb }
phase intro { needs main then level }
phase level { needs level entry run }
entry intro
main.asm
.proc entry
.transition level
.endp
level.asm
.section
map .byte 1
.res $2000
.byte 1
.ends
.proc run
lda map
@ jmp @-
.endp
error[NGA5222]: there is no storage for `map`, which needs 8,196 bytes
--> level.asm:1:1
|
1 | .section
| ^^^^^^^^
Storage here is one Bank of 8 KB. Reserved space between two emitted bytes
travels with them, so the .res costs storage; at the end of the Section it
would cost nothing. Otherwise compress the Section with a transform in the
Project, or use a Target with more storage. See
the Project file.
NGA5224
warning · {section} is root and holds no bytes to restore, and is evicted in phase {gap} {between}
A root Section is read by the hardware with no Reference in the code. One
that only reserves space has no bytes to carry, so where a Phase that does not
need its Module comes between two that do, nothing puts its contents back. The
later Phase finds what the Phase in between left there.
main.ngp
modules { "main.asm" "game.asm" }
phase intro { needs main then game }
phase game { needs game then outro entry play }
phase outro { needs main then game entry finish }
entry intro
main.asm
.section root
screen .res 960
.ends
.proc entry
.transition game
.endp
.proc finish
@ jmp @-
.endp
game.asm
.proc play
.transition outro
.endp
warning[NGA5224]: `screen` is `root` and holds no bytes to restore, and is evicted in phase `game` between `intro` and `outro`, which both need it
--> main.asm:1:1
|
1 | .section root
| ^^^^^^^^
List the Module in game too, or in resident, so that it stays. Where the
program sets the memory up again on every entry, .off NGA5224 above the
Section says so. A root Section that holds bytes is not reported: its bytes
are brought back, or kept in place where there is no storage.
NGA5225
error · pane {pane} takes {size:n} bytes in phase {phase}, and a bank of {set} holds {available:n}
A Pane is one Bank, so its Sections present in one Phase have to fit in it
together. The sum is checked before the solver is asked, and the finding
points at the Pane. A Project with no phase block has one unnamed Phase,
which the message calls (implicit).
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in ext { level }
main.asm
.section in level, root
map .res $3000
.ends
.section in level, root
tiles .res $1800
.ends
error[NGA5225]: pane `level` takes 18,432 bytes in phase `(implicit)`, and a bank of `extension` holds 16,384
--> main.ngp:5:1
|
5 | panes in ext { level }
| ^^^^^
error[NGA5206]: no layout satisfies every constraint at once
Declare a second Pane, panes in ext { level, tiles }, and move one Section
to it, or put the two in Modules no Phase needs together.
NGA5206 follows, as it follows every sum that refuses.
NGA5226
error · {section} is pinned at {address:hex}, outside the window of pane {pane}
A Pane's Section is reached through its Pane's Window, which is the only place its Bank appears. A pin must put the whole Section inside the Window's ranges.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in ext { level }
main.asm
.section in level, absolute at $8000, root
map .res 1024
.ends
error[NGA5226]: `map` is pinned at $8000, outside the window of pane `level`
--> main.asm:1:1
|
1 | .section in level, absolute at $8000, root
| ^^^^^^^^
ext is $4000-$7FFF on the 130XE. Pin inside it, or drop the pin and let
the solver choose where in the Window the Section stands.
NGA5227
error · {section} has bytes and is in pane {pane}, which is pinned to a named state: only a .xex fills one, and only in the window its driver's stream reads through
A named state is not a Bank: storage holds nothing for it, and outside the case the message names, no Container writes bytes into it. A Pane pinned to one holds reservations, which the program fills itself.
main.ngp
include "atari/mariacel.ngp"
modules { "main.asm" }
panes in cel4000 = derived { shapes }
container xex
main.asm
.section in shapes, root
shape .byte $0F, $3C, $F0
.ends
.proc entry
rts
.endp
error[NGA5227]: `shape` has bytes and is in pane `shapes`, which is pinned to a named state: only a `.xex` fills one, and only in the window its driver's stream reads through
--> main.asm:1:1
|
1 | .section in shapes, root
| ^^^^^^^^
On MariaCEL the driver's stream reads through cel8000, and cel4000 shows the
blitter's memory. Reserve the space with .res and fill it from code under a
.with, as atari/mceltables.asm does.
NGA5229
error · family {pane} needs {count} banks in a row, and {set} has {banks}
A family NAME[N] is N Panes on N consecutive Banks of the unit set its
Window shows. Raised where N is larger than the number of Banks in the set.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
panes in ext { rooms[8] }
main.asm
.section in rooms, root
room .res 4096
.ends
error[NGA5229]: family `rooms` needs 8 banks in a row, and `extension` has 5
--> main.ngp:5:1
|
5 | panes in ext { rooms[8] }
| ^^^^^
error[NGA5206]: no layout satisfies every constraint at once
The 130XE has five Banks. Declare fewer members. NGA5206
follows. See Panes.
NGA5230
error · {section} says readonly and this writes it
A Section nothing writes is read-only without being told. readonly is for one
whose address the program takes, where the tool cannot see what is done
through the pointer, and it says the pointer is only read through. A write the
tool can see contradicts the word and is refused: a store, an increment or a
shift on it.
.section readonly
lives .byte 3
.ends
.proc entry
dec lives
rts
.endp
error[NGA5230]: `lives` says `readonly` and this writes it
--> main.asm:6:9
|
6 | dec lives
| ^^^^^^^^^
note: `readonly` is declared here
--> main.asm:1:1
|
1 | .section readonly
| ^^^^^^^^
Drop readonly if the Section is meant to change, or the write if it is not.
NGA5231 points at the declaration.
NGA5231
note · readonly is declared here
Follows NGA5230 and points at the .section readonly that the
write contradicts.
NGA5232
warning · {section} reserves space and emits no bytes, so readonly says nothing about it
readonly is about bytes that could stand in ROM. A Section of reservations
alone emits none, so the word has nothing to say about it.
.section readonly
buffer .res 64
.ends
.proc entry
lda buffer
rts
.endp
warning[NGA5232]: `buffer` reserves space and emits no bytes, so `readonly` says nothing about it
--> main.asm:1:1
|
1 | .section readonly
| ^^^^^^^^
Remove readonly. A Section meant to hold constant data needs .byte or
.word rather than .res.
NGA5233
error · {section} is pinned at {address:hex} in {region}, which is ROM, and it is not read-only: it is written, holds no bytes, or has its address taken without readonly
A rom Region holds what nothing writes. A pin is the author's word, so a
Section pinned there stands there. Raised where that Section is not read-only:
the program writes it, it emits no bytes, or its address is taken and it does
not say readonly.
main.ngp
target {
region $0080 .. $00FF ram
region $2000 .. $7FFF ram
region cart $8000 .. $9FFF rom
}
modules { "main.asm" }
main.asm
.section absolute at $8000
score .byte 0
.ends
.proc entry
inc score
rts
.endp
error[NGA5233]: `score` is pinned at $8000 in `cart`, which is ROM, and it is not read-only: it is written, holds no bytes, or has its address taken without `readonly`
--> main.asm:1:1
|
1 | .section absolute at $8000
| ^^^^^^^^
note: the region `cart` is declared here
--> main.ngp:4:3
|
4 | region cart $8000 .. $9FFF rom
| ^^^^^^
A write to ROM changes nothing, and the next read returns what the ROM holds.
Pin a variable into RAM, or drop the pin: the solver puts what nothing writes
into ROM by itself. A table read through a pointer needs readonly.
NGA5234
error · the sections nothing writes come to {required:n} bytes and this machine has {available:n} of ROM
Where the Target has a rom Region, every Section nothing writes stands
there, code included. ROM is summed once for the whole run and not per Phase,
because nothing loads it and no Phase gives its addresses to another. The
notes name the largest Sections.
main.ngp
target {
region $0080 .. $00FF ram
region $2000 .. $2FFF ram
region $8000 .. $800F rom
}
modules { "main.asm" }
main.asm
.section
message .byte "HELLO, WORLD!"
.ends
.proc entry
lda message
rts
.endp
error[NGA5206]: no layout satisfies every constraint at once
error[NGA5234]: the sections nothing writes come to 17 bytes and this machine has 16 of ROM
note: `message` accounts for 13 bytes
--> main.asm:1:1
|
1 | .section
| ^^^^^^^^
note: `entry` accounts for 4 bytes
--> main.asm:5:1
|
5 | .proc entry
| ^^^^^^^^^^^
On a cartridge, move what one Phase needs into a Pane, which stands in a Bank
of the board rather than in its fixed part; see
Cartridges. NGA5206 follows.
NGA5235
error · {section} is pinned at {address:hex}, inside window {window}, where only a pane or storage stands
No Window has a base: what it shows outside a .with is whatever was shown
last. So the solver gives a Window's addresses only to Panes and to storage,
and a pin of any other Section there is refused.
main.ngp
include "atari/130xe.ngp"
modules { "main.asm" }
main.asm
.section absolute at $4000
buffer .res 256
.ends
.proc entry
lda buffer
rts
.endp
error[NGA5235]: `buffer` is pinned at $4000, inside window `ext`, where only a pane or storage stands
--> main.asm:1:1
|
1 | .section absolute at $4000
| ^^^^^^^^
Pin it outside $4000-$7FFF, or put it in a Pane with in NAME and read it
under a .with. A Section with a Payload pinned there is
NGA5205 instead. See
Panes.
NGA5240
error · the layout has {section} and {other} sharing {address:hex}, and phase {phase} holds both
Raised only when the tool runs with --verify-layout. The option reads the
Layout again after Place and checks every Constraint against it, with code that
shares nothing with the solver. A finding of it means the tool placed something
wrong. The program is not at fault, and there is nothing in it to change.
Report the finding with the Project that raised it. The option changes nothing
in the build, so a build without it writes the same Layout with the same
fault.
This one finds two Sections on a common address in a Phase that holds both. Two Temporaries that are never live at once may share an address, and so may two Sections in different states of one Window. This pair is neither.
NGA5241
error · the layout puts {section} at {address:hex}, and it is pinned at {pinned:hex}
A finding of --verify-layout, and a fault of the tool, not of the program;
see NGA5240. The Section is pinned with at, and the Layout put
it somewhere else.
NGA5242
error · the layout puts zero page {section} at {address:hex}, and it reaches {last:hex}
A finding of --verify-layout, and a fault of the tool, not of the program;
see NGA5240. A zeropage Section ends below $0100, and the
Layout let this one run past it.
NGA5243
error · the layout puts {section} at {address:hex}..{last:hex}, reaching into the window it waits behind
A finding of --verify-layout, and a fault of the tool, not of the program;
see NGA5240. A Section that waits in storage may not stand in the
Window the driver's stream reads through, because the Window shows a Bank there
while a Transition reads. The Layout put this one there. The same rule for a
pin is NGA5205.
NGA5244
error · the layout puts {section} at {address:hex}..{last:hex}, outside the pool it was allocated from
A finding of --verify-layout, and a fault of the tool, not of the program;
see NGA5240. The solver placed the Section outside the memory it
may stand in: the ram Regions of its placement class, the rom Regions for a
Section nothing writes, its Pane's Window, or the Regions its in names. For a
Section in a unit set, that memory is the set's Banks. A pinned Section is not
held to this.
NGA5245
error · the layout gives {section} no address
A finding of --verify-layout, and a fault of the tool, not of the program;
see NGA5240. Prune kept the Section, so it needs an address, and
the Layout has none for it.
NGA5246
error · the layout puts {section} at {address:hex}, and it reaches past the end of memory
A finding of --verify-layout, and a fault of the tool, not of the program;
see NGA5240. The Layout put the Section where it runs past
$FFFF.
NGA5247
error · the layout puts {section} at {address:hex}, which is not aligned to {alignment:n}
A finding of --verify-layout, and a fault of the tool, not of the program;
see NGA5240. The Section says align N, and the Layout put it at
an address that is not a multiple of N.
NGA5248
error · the layout puts {section} at {address:hex}..{last:hex}, across a boundary of {boundary:n}
A finding of --verify-layout, and a fault of the tool, not of the program;
see NGA5240. The Section says within N, and the Layout put it
across a multiple of N.
NGA5250
error · the layout gives {section} an address, and nothing reaches it
A finding of --verify-layout, and a fault of the tool, not of the program;
see NGA5240. Prune dropped the Section because nothing reaches
it, and the Layout gave it an address anyway.
NGA5251
error · the layout ends {section} at {address:hex} in phase {phase}, and {next}, which follows it, starts at {other:hex}
A finding of --verify-layout, and a fault of the tool, not of the program;
see NGA5240. The Proc ends with .endp then NAME, so NAME must
start at the byte after it in every Phase that holds both. The Layout put NAME
somewhere else.
NGA5253
error · {section} holds bytes and reaches {last:hex}, where {region} stands: what a foreign section holds is written by the CPU like every other byte, and the CPU does not reach there
foreign says that another master of the address space reads the Section and
the CPU does not, as a Lynx's display reads its buffer. It lets the Section lie
over a register or reserved Region. Raised when such a Section holds bytes
and reaches one of those Regions. The bytes would be written by the CPU, through
a loader or a Transition's copy, and at those addresses the CPU sees a chip's
registers or a ROM, not the memory.
main.ngp
target {
region $0080 .. $00FF ram
region $0200 .. $FBFF ram
region io $FC00 .. $FFFF register
}
modules { "main.asm" }
main.asm
.section absolute at $E000, root, foreign
screen .byte $11
.res 8159
.ends
.proc entry
rts
.endp
error[NGA5253]: `screen` holds bytes and reaches $FFDF, where `io` stands: what a `foreign` section holds is written by the CPU like every other byte, and the CPU does not reach there
--> main.asm:1:1
|
1 | .section absolute at $E000, root, foreign
| ^^^^^^^^
note: the region `io` is declared here
--> main.ngp:4:3
|
4 | region io $FC00 .. $FFFF register
| ^^^^^^
Make the Section a reservation, with .res only, and let the program or the
hardware fill it at run time. A foreign Section with bytes is allowed where
all of it lies in ram.
NGA5254
error · this reaches {address:hex} of {section}, where {region} stands, and the CPU does not reach there
An instruction reads or writes a foreign Section at an address where a
register or reserved Region stands. The access goes to what the CPU sees
there, such as a chip's registers, and not to the Section's memory. The check is made on the address
the operand names, once the Section has its address. What an index register
adds at run time is not checked, nor is an access through a pointer, and taking
the address with #< is not an access.
main.ngp
target {
region $0080 .. $00FF ram
region $0200 .. $FBFF ram
region io $FC00 .. $FFFF register
}
modules { "main.asm" }
main.asm
.section absolute at $E000, root, foreign
screen .res 8160
.ends
.proc entry
lda #0
sta screen + 8000
rts
.endp
error[NGA5254]: this reaches $FF40 of `screen`, where `io` stands, and the CPU does not reach there
--> main.asm:7:9
|
7 | sta screen + 8000
| ^^^^^^^^^^^^^^^^^
screen + 8000 is $FF40, inside io. The CPU may use the part of the
Section below $FC00, and the rest is the other master's. The same rule for
the Section's own bytes is NGA5253.
NGA5255
error · {section} comes to {size:n} bytes, and nothing in this storage may run from one unit into the next, the widest of which holds {available:n}
Raised on a Commodore diskette, a d64, d80 or d82, for a Section that
waits in storage and whose stored form is larger than the widest track. A unit
there is a track, tracks hold different numbers of sectors, and nothing may run
from one track into the next.
A driver that declares .driver span none has such a form cut into pieces that
each fit in a track. The shipped pet/disk.asm declares it. A driver of your
own for a diskette that does not declare it gets the form whole, and no track
holds it. Add .driver span none to the driver.
NGA5256
error · the layout puts {section} at {address:hex}, inside window {window}, and it is in no pane
A finding of --verify-layout, and a fault of the tool, not of the program;
see NGA5240. The Layout put a Section that is in no Pane inside a
Window, where only a Pane's Sections and storage stand. A pin there is refused
as NGA5235.
NGA5258
warning · {section} is written as it is: as {format} it comes to {form:n} bytes, and it is {size:n}
A .xex with no storage carries a Section named in a transform in its
encoded form, and decodes it in place while the file loads. Raised when the
encoded form is no shorter than the Section's bytes. The .xex then carries
the bytes as they are. The program is the same; only the compression is lost.
Also raised for a Section the .xex moves under a ROM.
main.ngp
include "atari/800xl.ngp"
modules { "main.asm" }
transform zx0 { main.table }
container xex
main.asm
.proc entry
lda table
rts
.endp
.section
table .byte 1, 2, 3, 4
.ends
warning[NGA5258]: `table` is written as it is: as `zx0` it comes to 9 bytes, and it is 4
--> main.asm:6:1
|
6 | .section
| ^^^^^^^^
Short data, and data with nothing repeated, rarely shrink. Take the Section out
of the transform block.
NGA5259
warning · {section} is written as it is: decoding it in place needs {margin:n} bytes past its end, and {address:hex} is not memory the loader may write
The setting of NGA5258. To decode in place, the loader writes the
encoded form so that it ends a few bytes past the end of the Section, and the
decoder writes the Section from its start without overtaking what it has still
to read. Those bytes past the end must be memory the loader may write while the
file loads: in a ram Region, and not held by a root reservation of the entry
Phase, such as the OS ROM, or by a Module of the load block. Raised when they
are not. The .xex then carries the Section's bytes as they are.
main.ngp
include "atari/800xl.ngp"
modules { "main.asm" }
transform zx0 { main.table }
container xex
main.asm
.proc entry
lda table
rts
.endp
.section absolute at $BFE0
table .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.ends
warning[NGA5259]: `table` is written as it is: decoding it in place needs 2 bytes past its end, and $C000 is not memory the loader may write
--> main.asm:6:1
|
6 | .section absolute at $BFE0
| ^^^^^^^^
The table ends at $BFFF, and the OS ROM starts at $C000. Pin the Section
lower, or drop the at and let the solver place it.
NGA5260
error · there is no room while the program loads for {section}, which runs while it loads and needs {size:n} bytes
A .xex with no storage runs code while it loads: the decoder of each format a
transform names, the move of bytes kept under a ROM, and the code of the
load block's Modules. The tool places that code in memory that is free while
the file loads: clear of every Section being decoded, of every root
reservation of the entry Phase, and of what the load block says the machine
holds. The rest of the program is no obstacle, since it is written after this
code has run. Raised when no free stretch holds what the message names.
main.ngp
target {
region $0080 .. $00FF ram
region $2000 .. $2FFF ram
}
modules { "main.asm" }
transform zx0 { main.table }
container xex
main.asm
.proc entry
lda table
rts
.endp
.section
table .byte 1
.res 4000
.byte 2
.ends
error[NGA5260]: there is no room while the program loads for `ngaLoad.zx0Copy`, which runs while it loads and needs 31 bytes
error[NGA5260]: there is no room while the program loads for `ngaLoad.zx0Decode`, which runs while it loads and needs 154 bytes
The table takes 4002 of the 4096 bytes of RAM, and the zx0 decoder does not fit in the rest. Leave memory free while the program loads: decode less, or reserve less in the entry Phase.
NGA5261
error · {section} is named in transform, and the cold start runs it before anything is decoded
A .xex with storage brings the Sections of its entry Phase that a transform
names by a cold start: an edge into the entry Phase from nowhere, which reads
them from storage and decodes them before the entry Label runs. The driver and
the decoders run during the cold start, so they are in memory before the first
block is read, and nothing could decode one of their own Sections. Raised for a
Section of the driver's Module, or of a Module that declares a decoder, named
in a transform.
main.ngp
include "atari/130xe.ngp"
include "atari/extension.ngp"
modules { "main.asm" "unpack.asm" }
transform rle { main.table, unpack.unpack }
container xex
main.asm
.proc entry
lda table
rts
.endp
.section
table .byte 0, 0, 0, 0, 0, 0, 0, 0
.ends
unpack.asm
.transform rle unpack
.proc unpack
rts
.endp
error[NGA5261]: `unpack` is named in `transform`, and the cold start runs it before anything is decoded
--> unpack.asm:3:1
|
3 | .proc unpack
| ^^^^^^^^^^^^
Take the Section out of the transform block, and the .xex writes it as it
is. A cartridge's cold start is described in
Cartridges.
NGA5262
error · there is no memory free while the program loads to put what hides under a ROM before it is moved there
A .xex with no storage can keep bytes for a later Phase in the RAM under a
ROM, while the entry Phase has that ROM switched in. The file loads with every
ROM in, so the .xex first writes those bytes into memory that is free while
it loads, and then moves them under the ROM with every ROM switched out. Raised
when no free stretch is large enough to hold any of them. Free means clear of
every root reservation of the entry Phase, of what the load block says the
machine holds, and of the driver and the tool's own load code. Reserve less in
the entry Phase, so that some memory is free while the program loads.
NGA5263
warning · {section} hides under a ROM and is moved there as it is: as {format} it comes to {form:n} bytes, and {room:n} are free while the program loads
The setting of NGA5262, for a Section a transform names. Its
encoded form is written whole into one free stretch and decoded from there
under the ROM. Raised when the form is larger than the largest free stretch.
The Section is then moved as it is, in pieces, and the .xex is larger by what
the encoding would have saved. Reserve less in the entry Phase, or take the
Section out of the transform block.
NGA5264
error · {section} is pinned at {address:hex}, outside the region its in names
in NAME with a Region puts the Section inside that Region, and at pins it.
Raised where a Section has both and its pinned bytes do not lie wholly inside
any Region its in names. The tool does not choose between the two.
main.ngp
include "atari/800xl.ngp"
modules { "main.asm" }
main.asm
.section absolute at $B000, in underOsLow
table .byte 1, 2, 3, 4
.ends
.proc entry
lda table
rts
.endp
error[NGA5264]: `table` is pinned at $B000, outside the region its `in` names
--> main.asm:1:1
|
1 | .section absolute at $B000, in underOsLow
| ^^^^^^^^
underOsLow is $C000-$CFFF. Drop the at and the solver places the Section
in the Region, or pin it inside the Region. See
in NAME.
NGA5265
error · {section} runs while the file loads, and {module} is needed by phase {phase} too: what the load runs is done with before any phase
A Module the load block needs that holds anything but pinned reservations
is code of the program's own, which runs while the .xex loads. The tool
places it in memory that is free during the load and writes the rest of the
file over it afterwards, so it belongs to no Phase. Raised when a Phase also needs the
Module, or resident names it.
main.ngp
modules { "main.asm" "early.asm" }
load { needs early init early }
phase main { needs main, early }
entry main
container xex
main.asm
.proc entry
rts
.endp
early.asm
.proc early
rts
.endp
error[NGA5265]: `early` runs while the file loads, and `early` is needed by phase `main` too: what the load runs is done with before any phase
--> early.asm:1:1
|
1 | .proc early
| ^^^^^^^^^^^
Take the Module out of the Phase's needs. See
load.
NGA5266
warning · {section} is pinned at {address:hex}, which {holder} holds while the file loads, and its bytes are written then
A Module the load block needs that holds only pinned reservations says what
memory the machine uses while the .xex loads, such as the DOS's. Place keeps
every Section with bytes off it. Raised for a Section pinned there whose bytes
the .xex writes during the load, onto memory the DOS may still be using. It
is a warning because a pin is the author's word: writing INITAD, in the OS's
memory, is how a program talks to the DOS.
main.ngp
modules { "main.asm" "dos.asm" }
load { needs dos }
phase main { needs main }
entry main
container xex
main.asm
.section absolute at $2400
flag .byte 1
.ends
.proc entry
lda flag
rts
.endp
dos.asm
.section absolute at $2000
dos .res $1000
.ends
warning[NGA5266]: `flag` is pinned at $2400, which `dos` holds while the file loads, and its bytes are written then
--> main.asm:1:1
|
1 | .section absolute at $2400
| ^^^^^^^^
Where the pin is not meant, move it or drop it. A Section with no bytes may stand there without a warning, since the DOS is done with the memory by the time the program writes it.
NGA5267
error · the layout puts {section} at {address:hex}, which {holder} holds while the file loads, and its bytes are written then
A finding of --verify-layout, and a fault of the tool, not of the program;
see NGA5240. The .xex writes this Section's bytes while it
loads, and the Layout put it on memory that a Module of the load block says
the machine holds then. A pinned Section there is a warning instead,
NGA5266.
NGA5268
error · init {name} names {what}: it names a label of a module the load needs
init NAME in the load block names a Label that the .xex calls through
INITAD while it loads. The name is looked up among the Modules the same block
needs, as entry is among a Phase's. Raised when none of them defines it,
when more than one does, or when it is not a Label; the message says which.
main.ngp
modules { "main.asm" "early.asm" }
load { needs early init fadeIn }
phase main { needs main }
entry main
container xex
main.asm
.proc entry
rts
.endp
early.asm
.proc fade
rts
.endp
error[NGA5268]: `init fadeIn` names nothing: it names a label of a module the load needs
--> main.ngp:3:26
|
3 | load { needs early init fadeIn }
| ^^^^^^
Correct the name, or add the Module that defines it to the block's needs.
NGA5269
error · {section} is pinned at {address:hex}, and the banks of {units} lie from {begin:hex} to {last:hex}
A Section in a unit set that declares linear stands in the medium's own
memory, at a linear address, and not at an address the CPU uses. Its at is a
linear address too, and is held to the set's Banks: from the start of the
linear range to the end of the last Bank. Raised when the pinned bytes fall
outside. An at written as a CPU address, such as the Window's, is the usual
cause.
main.ngp
target {
region $0080 .. $00FF ram
region $2000 .. $3FFF ram
units vram 4 linear $10000 .. $1FFFF
window vwin $4000 .. $7FFF views vram
}
modules { "main.asm" }
main.asm
.section absolute at $4000, in vram
sprites .res 256
.ends
.proc entry
lda #<sprites
rts
.endp
error[NGA5269]: `sprites` is pinned at $4000, and the banks of `vram` lie from $010000 to $01FFFF
--> main.asm:1:1
|
1 | .section absolute at $4000, in vram
| ^^^^^^^^
Pin the Section at a linear address in the range, such as $10000, or drop
the at.
NGA5270
error · in phase {phase} the sections in {units} come to {size:n} bytes, and its banks hold {holds:n}
Before the solver runs, the tool adds up, for each Phase, the Sections that
stand in a unit set and the Sections of Panes in that set's Banks, a family's
once per member. Raised when the sum is more than the set's Banks hold end to
end. The solver is asked all the same, so NGA5206 comes with it.
main.ngp
target {
region $0080 .. $00FF ram
region $2000 .. $3FFF ram
units vram 4 linear $10000 .. $1FFFF
window vwin $4000 .. $7FFF views vram
}
modules { "main.asm" }
main.asm
.section in vram
screen .res $C000
.ends
.section in vram
copy .res $5000
.ends
.proc entry
lda #<screen
lda #<copy
rts
.endp
error[NGA5206]: no layout satisfies every constraint at once
error[NGA5270]: in phase `(implicit)` the sections in `vram` come to 69,632 bytes, and its banks hold 65,536
Four Banks of $4000 hold $10000 bytes. Make the Sections smaller, or put
them in Modules of different Phases, since the sum is taken per Phase.
NGA5271
error · {section} has bytes in {units}, and no Container fills that set while the program loads, so it holds only sections that reserve
A Section in a unit set that holds bytes is written into the set by the
Container while the program loads. A Container fills one set: the one storage
is made of, or, with no storage, the one the driver's stream reads through. Any
other set holds only reservations. Raised for a Section with bytes in such a
set.
main.ngp
target {
region $0080 .. $00FF ram
region $2000 .. $3FFF ram
units vram 4 linear $10000 .. $1FFFF
window vwin $4000 .. $7FFF views vram
}
modules { "main.asm" }
main.asm
.section in vram
palette .byte $00, $0F, $F0, $FF
.ends
.proc entry
lda #<palette
rts
.endp
error[NGA5271]: `palette` has bytes in `vram`, and no Container fills that set while the program loads, so it holds only sections that reserve
--> main.asm:1:1
|
1 | .section in vram
| ^^^^^^^^
Make the Section a reservation, with .res, and have the program fill it at
run time.
NGA5272
error · {section} has bytes and is in pane {pane}, whose banks are units of {units}, and no Container fills that set while the program loads
A Pane's Section with bytes is written into the Pane's Bank by the Container while the program loads. The Container fills one set of units: the one storage is made of, or, with no storage, the one the driver's stream reads through. Raised for a Section with bytes in a Pane of any other set. With no storage and no driver, no set is filled at all.
main.ngp
target {
units extension 4
window ext $4000 .. $7FFF views extension
}
modules { "main.asm" }
panes in ext { level }
container xex
main.asm
.section in level, root
map .byte 1, 2, 3
.ends
.proc entry
rts
.endp
error[NGA5272]: `map` has bytes and is in pane `level`, whose banks are units of `extension`, and no Container fills that set while the program loads
--> main.asm:1:1
|
1 | .section in level, root
| ^^^^^^^^
A target written by hand needs a Module that declares a driver, with .driver stream ext, as atari/130xe.ngp lists atari/portb.asm. Or make the Section a
reservation and have the program fill it at run time.
NGA5273
error · nothing the file leaves alone while it loads holds the {size:n} bytes that change it for a choice
A .xex built from choose writes, before each call that changes the bytes,
the list of what to change: an address and a byte for each later document. The
list goes into memory the program's own bytes will fill later, into memory
nothing writes, or into the program's bytes where nothing changes and which
are written again after the call. Here every byte of the table changes and
little else of memory is there.
main.ngp
include "small.ngp"
choose { "low.ngp" "high.ngp" }
modules { "detect.asm" "main.asm" }
load { needs detect init detect }
phase main { needs main }
entry main
container xex
small.ngp
target {
region $0080 .. $00FF ram
region $2000 .. $27FF ram
region $D000 .. $D7FF register
}
low.ngp
constants { LEVEL = 1 }
high.ngp
constants { LEVEL = 2 }
detect.asm
.proc detect
lda #1
sta ngaChoice
rts
.endp
main.asm
.macro sites n
.if n > 0
.byte LEVEL, LEVEL, LEVEL, LEVEL, LEVEL, LEVEL, LEVEL, LEVEL
sites n - 1
.endif
.endm
.proc entry
rts
.endp
.section root
table
sites 80
.ends
error[NGA5273]: nothing the file leaves alone while it loads holds the 588 bytes that change it for a choice
Make the bytes that differ fewer, for example by keeping the value in one place and reading it from there.
NGA5631
error · phase {phase} does not fit in view {view}: requires {required:n} bytes, {available:n} available
Before the solver runs, the tool adds up, for each Phase, the absolute
Sections the Phase holds, and compares the sum with the memory outside every
Window, which is the View fixed. Raised for a Phase whose sum is larger. The
notes name the three Sections that weigh most. The solver is asked all the
same, so NGA5206 comes with it.
.section
level .res 30000
.ends
.section
tiles .res 20000
.ends
.proc entry
lda level
lda tiles
rts
.endp
error[NGA5206]: no layout satisfies every constraint at once
error[NGA5631]: phase `(implicit)` does not fit in view `fixed`: requires 50,007 bytes, 32,768 available
note: `level` accounts for 30,000 bytes
--> main.asm:1:1
|
1 | .section
| ^^^^^^^^
note: `tiles` accounts for 20,000 bytes
--> main.asm:5:1
|
5 | .section
| ^^^^^^^^
note: `entry` accounts for 7 bytes
--> main.asm:9:1
|
9 | .proc entry
| ^^^^^^^^^^^
Make the Phase hold less: split the program into Phases whose Modules arrive
from storage by a Transition (Phases), or put data in a Pane
behind a Window (Panes). With no storage, a Section stays in memory from the
load until the last Phase that needs it, and counts in every Phase on the way;
its note is then NGA5634.
NGA5632
error · phase {phase} needs {required:n} bytes of zero page, and {available:n} are available
The same sum as NGA5631, for the zeropage Sections of a Phase,
against the zero page the Target's ram Regions leave. The stand-in Target has
16 bytes of it, $0080-$008F. A machine variant declares its own.
.section zeropage
pointers .res 12
.ends
.section zeropage
counters .res 8
.ends
.proc entry
lda pointers
lda counters
rts
.endp
error[NGA5206]: no layout satisfies every constraint at once
error[NGA5632]: phase `(implicit)` needs 20 bytes of zero page, and 16 are available
note: `pointers` accounts for 12 bytes
--> main.asm:1:1
|
1 | .section zeropage
| ^^^^^^^^
note: `counters` accounts for 8 bytes
--> main.asm:5:1
|
5 | .section zeropage
| ^^^^^^^^
Take zeropage off Sections that do not need it. Scratch bytes can be
Temporaries, declared with .ztemp, which share an address with others that
are never live at the same time (Temporaries).
NGA5633
note · {section} accounts for {size:n} bytes
Follows NGA5631, NGA5632 or
NGA5234, once for each of the three Sections that weigh most in
the sum, largest first, and points at the Section.
NGA5634
note · {section} accounts for {size:n} bytes, kept here because phase {needer} needs it and with no storage nothing could bring it back
Follows NGA5631 or NGA5632 in place of
NGA5633, for a Section the Phase does not need. With no storage,
bytes are written when the program loads and stay in memory while a Phase still
to come needs them, so this Phase holds them for the Phase the note names. With
a storage block they would wait there and
arrive by a Transition.
NGA6101
error · {value} does not fit in {room} written here
Raised when the tool writes the bytes: an operand of an instruction, or an item
of .byte or .word, has a value the place does not hold. A byte holds -128 to
255 and a word -32768 to 65535. A negative value is written as its two's
complement, so .byte -1 is $FF.
Here it is an address where a byte is meant: table is at $2000, and
#table asks for all of it in one byte.
.section
table .byte 1, 2, 3
.ends
.proc entry
lda #table
rts
.endp
error[NGA6101]: 8192 does not fit in the byte written here
--> main.asm:6:14
|
6 | lda #table
| ^^^^^
Write #<table or #>table for one half of it. See
the operators.
NGA6102
error · {mnemonic} reaches -128 to 127 and this is {distance:n} bytes away; write {jcc}, which is five bytes where two do not reach
A branch reaches 128 bytes back and 127 forward. The tool says how far the target actually is, and names the conditional jump that reaches anywhere. It is five bytes where a branch is two.
.macro zeros n
.if n > 0
.byte 0
zeros n - 1
.endif
.endm
.proc entry
bne far
zeros 200
far rts
.endp
error[NGA6102]: `bne` reaches -128 to 127 and this is 200 bytes away; write `jne`, which is five bytes where two do not reach
--> main.asm:9:9
|
9 | bne far
| ^^^^^^^
jne is two bytes where the target is close enough and five where it is not,
and the tool picks; see Instructions.
NGA6201
error · {section} and {other} share {address:hex}, and a raw image cannot hold both
Raised when the Container is the raw image, the default where a Project names none, and two Sections with bytes stand at one address. Place allows that where no Phase needs both, since the two are never in memory together. A raw image is the memory at one instant, and it has room for one of them. Here the solver put the two entries at one address by itself.
main.ngp
include "atari/130xe.ngp"
include "atari/extension.ngp"
modules { "intro.asm" "game.asm" }
phase intro { needs intro then game entry introStart }
phase game { needs game entry gameStart }
entry intro
intro.asm
.proc introStart
.transition game
.endp
game.asm
.proc gameStart
@stop jmp @stop
.endp
error[NGA6201]: `gameStart` and `introStart` share $20DF, and a raw image cannot hold both
--> game.asm:1:1
|
1 | .proc gameStart
| ^^^^^^^^^^^^^^^
Name the Container the machine loads, here container xex. The .xex keeps
gameStart in storage and the Transition brings it in. See
container.
NGA6204
error · the .xex fills storage through the driver's showAt, and no module declares a driver
Raised when a .xex has bytes to put into Banks, a Pane's Sections or what waits
in storage, and no Module declares a driver with .driver. The .xex fills a
Bank while it loads: it calls the driver's showAt to show the Bank in the
Window and writes the bytes through it. See
Banks and Windows.
main.ngp
target {
units extension 4
window ext $4000 .. $7FFF views extension
}
storage { units extension }
modules { "main.asm" }
panes in ext { level }
container xex
main.asm
.section in level, root
map .byte 1, 2, 3
.ends
.proc entry
rts
.endp
error[NGA6204]: the .xex fills storage through the driver's `showAt`, and no module declares a driver
The Pane's Section is kept by root, and no code reads it. A program that takes
a .transition or writes a .with is told earlier, by NGA2281 or
NGA2313. This one is seen where no code uses the driver yet.
Without storage, the same Pane is NGA5272: with no driver there
is no stream, so no set of units is filled at all. The
library's variants list their driver, as atari/130xe.ngp lists
atari/portb.asm. A target written by hand needs a Module that declares one.
NGA6205
error · the .xex fills a unit by writing into the window the stream reads through, and this driver names none
Raised when a .xex has bytes to put into Banks or storage and the driver
declares no .driver stream WINDOW. The .xex fills a unit by showing it in
that Window and writing into it. A driver that reads its medium some other way
leaves it nothing to write into. atari/disk.asm is one: it reads sectors
through the OS.
main.ngp
include "atari/800xl.ngp"
include "atari/disk.ngp"
modules { "intro.asm" "level.asm" }
phase intro { needs intro then level }
phase level { needs level }
entry intro
container xex
intro.asm
.proc entry
.transition level
.endp
level.asm
.section
map .byte 1, 2, 3
.ends
.proc entry
lda map
@stop jmp @stop
.endp
error[NGA6205]: the .xex fills a unit by writing into the window the stream reads through, and this driver names none
Storage on a diskette goes with container atr, as in
Phases. A .xex takes
storage in Banks, such as atari/extension.ngp beside atari/130xe.ngp.
NGA6207
error · the driver declares init, and the container {container} has nowhere to call it: the .xex is the one Container that reaches the driver before the entry
Raised when the driver declares .driver init and the Container is neither a
.xex nor a raw image, which nothing of the tool starts.
init is what the hardware needs before the driver can use it, such as a board
on the parallel bus that answers at none of its addresses until it is selected.
The .xex calls it through INITAD before it fills a unit and before the
entry. The other Containers have no place that calls it, and the driver's writes
would then go to hardware that does not answer.
main.ngp
include "atari/800xl.ngp"
modules { "main.asm" }
container atr
main.asm
; A board that answers on the bus only once it is selected.
.driver init wake
.macro wake
lda #1
sta $D1FF
.endm
.proc entry
@stop jmp @stop
.endp
error[NGA6207]: the driver declares `init`, and the container `atr` has nowhere to call it: the `.xex` is the one Container that reaches the driver before the entry
--> main.asm:2:9
|
2 | .driver init wake
| ^^^^
Build a .xex where the machine takes one.
NGA6208
error · the .xex calls the driver's init before it fills a unit, and ngaInit has no address to call
The .xex calls the driver's init at ngaInit, a Proc the tool writes for
that call, as a Root. Raised when that Proc has no address once the program is
placed. It is a check of the tool's own work, and nothing a Project declares is
meant to reach it.
NGA6211
error · phase {phase} has no entry: no label {name} is defined in the modules it needs
Raised when the Container has to say where the program starts and the entry
Phase has no Label of that name in the Modules it needs. The name is the one
entry NAME gives in the Phase's phase block, and entry where the block
gives none. A Project with no phase block has one Phase, shown as
(implicit), and its entry is a Label named entry.
main.ngp
modules { "main.asm" }
container xex
main.asm
.proc start
rts
.endp
error[NGA6211]: phase `(implicit)` has no entry: no label `entry` is defined in the modules it needs
Name the Label entry, or add a phase block that names it,
phase main { needs main entry start }, with entry main beside it. The Label
may be private to its Module. The raw image is not entered by anything, so it
does not ask. See phase.
NGA6212
error · {name} is defined in more than one module that phase {phase} needs, so it does not say where the phase starts
Raised when more than one Module the entry Phase needs defines a Label of the
entry's name. Each Module may have a private entry of its own, and then
nothing says which one the Phase starts at. The finding points at the first.
main.ngp
modules { "main.asm" "other.asm" }
container xex
main.asm
.proc entry
rts
.endp
other.asm
.proc entry
rts
.endp
error[NGA6212]: `entry` is defined in more than one module that phase `(implicit)` needs, so it does not say where the phase starts
--> main.asm:1:7
|
1 | .proc entry
| ^^^^^
Rename all but one, or give the Phase an entry NAME that one Module alone
defines.
NGA6213
error · {name} is a {kind}, and an entry is a label
Raised when the name the entry Phase starts at is defined once, and as something other than a Label, such as a Constant. An entry is a place in the program, and a Label is what names one. A Constant does not, even when its value is an address, as here.
main.ngp
modules { "main.asm" }
container xex
main.asm
entry = $2000
error[NGA6213]: `entry` is a constant, and an entry is a label
--> main.asm:1:1
|
1 | entry = $2000
| ^^^^^
Define the entry as a Label, or rename the other definition and say which Label
the Phase starts at with entry NAME.
NGA6214
error · the .xex fills a unit through one range, and window {name} has {count}
Raised when the driver's stream reads through a Window of more than one range
and a .xex has to fill a unit through it. The .xex writes a unit as one run
of memory, and a Window of two ranges is not one.
main.ngp
target {
units pages 4
window split $4000 .. $4FFF, $6000 .. $6FFF views pages
}
modules { "main.asm" }
panes in split { level }
container xex
main.asm
.driver open boardOpen
.driver read boardRead
.driver unit boardUnit
.driver offset boardAt
.driver stream split
.driver show split boardShow
.driver showAt split boardShowAt
.macro boardOpen
.endm
.macro boardRead
.endm
.macro boardShow state
.endm
.macro boardShowAt
.endm
.section zeropage
boardAt .res 2
boardUnit .res 1
.ends
.section in level
map .byte 1, 2, 3
.ends
.proc entry
.with level
lda map
rts
.endp
error[NGA6214]: the .xex fills a unit through one range, and window `split` has 2
The driver's macros are empty here because only the Window matters. Stream through a Window of one range.
NGA6221
error · an .atr reads storage a sector at a time and shows no Window, and this storage is the unit set {name}
Raised when the Container is atr and the storage block names a unit set,
units NAME. Storage on a diskette is its sectors, which the driver reads one
at a time through the OS. A unit set is Banks shown through a Window, and the
boot record that loads the program shows no Window to fill them through.
main.ngp
include "atari/800xl.ngp"
target {
units extension 4
window ext $4000 .. $7FFF views extension
}
storage { units extension }
modules { "main.asm" }
container atr
main.asm
.proc entry
@stop jmp @stop
.endp
error[NGA6221]: an .atr reads storage a sector at a time and shows no Window, and this storage is the unit set `extension`
Storage on a diskette is declared by count: include atari/disk.ngp, which
declares it and lists the driver that reads it. Banks go with container xex.
A driver that streams through the Window is refused as well,
NGA6223.
NGA6222
error · a unit of storage on a diskette is the {size:n} bytes 256 sectors of {sector:n} hold, and {unit:n} is not that
Raised when the Container is atr and a unit of storage is not 65536 bytes. A
unit is 256 sectors of 256 bytes. The unit's number is then the high byte of the
sector number and the offset is the rest, so the driver does no arithmetic.
main.ngp
include "atari/800xl.ngp"
storage { units 720 size 256 }
modules { "main.asm" }
container atr
main.asm
.proc entry
@stop jmp @stop
.endp
error[NGA6222]: a unit of storage on a diskette is the 65,536 bytes 256 sectors of 256 hold, and 256 is not that
Include atari/disk.ngp rather than writing the block. It declares three units
of 65536 bytes from sector 4 on, the first sector after the boot record.
NGA6223
error · the boot record of an .atr shows no Window, and this driver streams through {name}
Raised when the Container is atr and the driver declares
.driver stream WINDOW. A driver that streams through a Window is one for
memory the CPU sees, such as Banks. The boot record of an .atr reads sectors
and shows no Window.
main.ngp
include "atari/800xl.ngp"
target {
units pages 4
window ext $4000 .. $7FFF views pages
}
modules { "main.asm" }
container atr
main.asm
.driver open boardOpen
.driver read boardRead
.driver unit boardUnit
.driver offset boardAt
.driver stream ext
.driver show ext boardShow
.driver showAt ext boardShowAt
.macro boardOpen
.endm
.macro boardRead
.endm
.macro boardShow state
.endm
.macro boardShowAt
.endm
.section zeropage
boardAt .res 2
boardUnit .res 1
.ends
.proc entry
@stop jmp @stop
.endp
error[NGA6223]: the boot record of an .atr shows no Window, and this driver streams through `ext`
A diskette's driver is atari/disk.asm, which atari/disk.ngp lists. A driver
that streams through a Window goes with container xex. Storage in Banks on an
.atr is NGA6221, raised beside this one when the driver streams
through those Banks.
NGA6224
error · a sector is numbered in two bytes, so an image holds {available:n} of them, and this program needs {required:n}
Raised when an .atr would need more than 65535 sectors: the boot record, the
storage the program uses, and the load image after it. The OS's disk call takes
a sector number in two bytes, so no image holds more. The tool makes an image of
720 sectors, a diskette, and grows it past that as far as this limit.
Make the Payloads smaller with a transform, such as zx0, or keep less of the
program in storage.
NGA6225
error · {section} stands at {address:hex}, inside the boot record the .atr loads over {begin:hex} to {end:hex}, which is still loading the program when those bytes are written
Raised for a Section the .atr would load into $0700-$087F. The OS reads
the boot record there, and the loader in it then reads the rest of the program.
A byte loaded there would overwrite the loader while it runs.
main.ngp
include "atari/800xl.ngp"
modules { "main.asm" }
container atr
main.asm
.section absolute at $0800
table .byte 1, 2, 3
.ends
.proc entry
lda table
@stop jmp @stop
.endp
error[NGA6225]: `table` stands at $0800, inside the boot record the .atr loads over $0700 to $087F, which is still loading the program when those bytes are written
--> main.asm:1:1
|
1 | .section absolute at $0800
| ^^^^^^^^
atari/800xl.ngp leaves those addresses out of every Region, so the solver
never puts a Section there, and the cause is a pin. Move it above $087F, or
drop it. A target written by hand for an .atr has to leave the range out of
its ram Regions too, or the solver itself puts Sections there.
NGA6226
error · an .atr is booted by its first sectors, and none were made
The tool writes the boot record of an .atr itself, as a Module of its own, and
fills in the sector the load image starts at. Raised when that Module, or the
place in it the sector goes, is missing or outside the record. It is a check of
the tool's own work, and nothing a Project declares is meant to reach it.
NGA6227
error · the boot record holds {available:n} bytes and its loader came to {required:n}
The boot record is the first three sectors of the diskette, 384 bytes the OS
reads to $0700. Raised when the loader the tool writes there comes to more.
The loader is the tool's own and fits with room to spare, so this is a check of
the tool's work rather than of the program's.
NGA6231
error · storage comes to {required:n} bytes and a {name} cartridge holds {available:n}
Raised when what waits in storage reaches past the end of the cartridge image.
On a board with Banks, storage is the Banks the board switches, and the
container car line holds the Target's unit set to the board's count
(NGA1221). The library's variants therefore never get here. A
storage block written by hand can declare more than the board holds; declare
the storage the board has.
NGA6232
error · {section} holds bytes at {address:hex}, and the board {name} is ROM at {range} and nothing else, so nothing would ever put them there
Raised for a Section with bytes that stands outside the cartridge's ROM and that
nothing copies there. Nothing loads a cartridge: the CPU reads it where it
lies. On a board with Banks, the bytes of a Section in RAM wait in a Bank and the
cold start copies them, as in
Cartridges. A board without Banks, 8k or
16k, has nowhere for them to wait.
main.ngp
target {
containers car
region $0080 .. $00FF ram
region $2000 .. $2FFF ram
region $A000 .. $BFFF rom
holder cartinit
}
modules { "main.asm" }
container car "8k"
main.asm
.section
lives .byte 3
.ends
.proc entry
dec lives
@stop jmp @stop
.endp
error[NGA6232]: `lives` holds bytes at $2000, and the board `8k` is ROM at $A000..$BFFF and nothing else, so nothing would ever put them there
--> main.asm:1:1
|
1 | .section
| ^^^^^^^^
Reserve the byte with .res 1 and set it from code, or use a board with Banks.
A Section that nothing writes goes into ROM by itself. A Proc whose bytes the
program writes is kept out of ROM, and is refused here the same way.
NGA6233
error · a cartridge is started through the six bytes at its top, and the tool could not complete them
Raised when the tool cannot complete the six bytes at the top of a cartridge,
$BFFA-$BFFF, which the OS reads to start it. The first two hold where the
program starts. Where the entry Phase has no entry Label, the tool has nothing
to write there, and this comes with NGA6211,
NGA6212 or NGA6213.
main.ngp
target {
containers car
region $0080 .. $00FF ram
region $2000 .. $7FFF ram
region $A000 .. $BFFF rom
holder cartinit
}
modules { "main.asm" }
container car "8k"
main.asm
.proc start
rts
.endp
error[NGA6233]: a cartridge is started through the six bytes at its top, and the tool could not complete them
error[NGA6211]: phase `(implicit)` has no entry: no label `entry` is defined in the modules it needs
Fix the entry and both findings go.
NGA6234
error · a bs93 image carries one address, which is both where it is loaded and where it is entered, so the entry has to be its lowest byte: the entry is {entry:hex} and the image begins at {begin:hex}
Raised when the Container is bs93 and the entry Label is not the image's
lowest byte. The header of a bs93 holds one address, where the block is loaded
and where it is entered, so the program has to start at its first byte. The tool
puts no jmp in front, because that would move the address the header holds.
main.ngp
include "lynx/lynx.ngp"
modules { "main.asm" }
container bs93
main.asm
.section
colors .byte 1, 2, 3
.ends
.proc entry
lda colors
@stop bra @stop
.endp
error[NGA6234]: a `bs93` image carries one address, which is both where it is loaded and where it is entered, so the entry has to be its lowest byte: the entry is $0203 and the image begins at $0200
The solver put colors first. Pin the entry below everything else, as
.proc entry, absolute at $0200.
NGA6235
error · {section} waits in storage, and a bs93 image is one block an emulator copies into memory: it has no loader, and nothing would ever put those bytes where they belong
Raised when the Container is bs93 and a Section has a Payload, which waits in
storage for a Transition to load it. An emulator copies a bs93 block into
memory and enters it, and nothing ever reads storage.
main.ngp
include "lynx/lynx.ngp"
include "lynx/cart64k.ngp"
modules { "intro.asm" "level.asm" }
phase intro { needs intro then level entry introStart }
phase level { needs level entry levelStart }
entry intro
container bs93
intro.asm
.proc introStart
.transition level
.endp
level.asm
.section
map .byte 1, 2, 3
.ends
.proc levelStart
lda map
@stop bra @stop
.endp
error[NGA6235]: `map` waits in storage, and a `bs93` image is one block an emulator copies into memory: it has no loader, and nothing would ever put those bytes where they belong
--> level.asm:1:1
|
1 | .section
| ^^^^^^^^
error[NGA6235]: `levelStart` waits in storage, and a `bs93` image is one block an emulator copies into memory: it has no loader, and nothing would ever put those bytes where they belong
--> level.asm:5:1
|
5 | .proc levelStart
| ^^^^^^^^^^^^^^^^
Leave out the storage document, here lynx/cart64k.ngp. Without storage every
Section with bytes is in the block, and a Transition loads nothing. Or build a
cartridge, container lnx "64k", which has a loader.
NGA6236
error · a Lynx cartridge is booted by fifty bytes its ROM decrypts and the loader they read in, and those were not made
A Lynx cartridge boots in two parts. The boot ROM decrypts fifty bytes from the start of the cartridge and runs them, and they read the rest of the loader, which reads the program. The tool writes both parts itself, as a Module of its own, and fills in two operands of the second part. Raised when that Module or those operands are missing. It is a check of the tool's own work, and nothing a Project declares is meant to reach it.
NGA6237
error · the boot ROM decrypts {available:n} bytes and the loader's first part came to {required:n}
The first part of a Lynx cartridge's loader is the one block the boot ROM
decrypts, fifty bytes run at $0200. Raised when the tool's own first part
comes to more. It is a check of the tool's work rather than of the program's.
NGA6238
error · the rest of page zero holds {available:n} bytes and the loader came to {required:n}: the first part reads the second where the ROM left the counter, and the counter does not leave the page it is on
The second part of a Lynx cartridge's loader stands in the rest of page zero,
after the first part. The first part reads it from where the boot ROM's counter
stopped, and the counter does not run on into the next page, so the loader has
to fit in that page: 204 bytes on a 64k board. Raised when it does not. The
loader is the tool's own and is written to fit the smallest board, so this is a
check of the tool's work.
NGA6239
error · a {name} cartridge holds {available:n} bytes and this comes to {required:n}
Raised when a Lynx cartridge would need more bytes than the board holds. Page zero holds the loader, storage follows from page one, and the load image, which is everything the entry Phase needs, begins on the page after the storage the program uses. The message counts all three. Here the entry Phase carries 40000 bytes and the other Phase's 30000 wait in storage.
main.ngp
include "lynx/lynx.ngp"
include "lynx/cart64k.ngp"
modules { "intro.asm" "level.asm"
script( "fill.js", name = "title", size = 40000 ) as titleArt
script( "fill.js", name = "map", size = 30000 ) as levelArt
}
phase intro { needs intro, titleArt then level entry introStart }
phase level { needs level, levelArt entry levelStart }
entry intro
container lnx "64k"
fill.js
export default ( args ) => ( {
sections: [ { name: args.name, items: [ new Uint8Array( args.size ) ] } ]
} );
intro.asm
.proc introStart
lda title
.transition level
.endp
level.asm
.proc levelStart
lda map
@stop bra @stop
.endp
error[NGA6239]: a `64k` cartridge holds 65,536 bytes and this comes to 70,895
Name a larger board, "128k", "256k" or "512k", and include its storage
document in place of lynx/cart64k.ngp. Or make the Payloads smaller with a
transform.
NGA6240
error · a prg is loaded at BASIC's own start and the line that enters it stands there, so the program begins at {floor:hex}: this image begins at {begin:hex}, which the load would write over BASIC's pointers
Raised when the Container is prg and the image begins below $040E. LOAD
puts a .prg at BASIC's start, $0401, and the tool puts a line of BASIC there
that enters the program with SYS. The program's own bytes begin behind that
line. A Section with bytes further down would have to be loaded over BASIC's
pointers by the load itself.
main.ngp
include "pet/3032.ngp"
modules { "main.asm" }
container prg
main.asm
.section zeropage
speed .byte 4
.ends
.proc entry
lda speed
rts
.endp
error[NGA6240]: a `prg` is loaded at BASIC's own start and the line that enters it stands there, so the program begins at $040E: this image begins at $00, which the load would write over BASIC's pointers
pet/3032.ngp leaves $0200-$040D out of every Region, so the solver keeps
out of it. The cause is a pin or, as here, a zeropage Section with bytes.
Reserve the byte with .res 1 and set it from code.
NGA6241
error · {section} waits in storage, and a prg is one block a PET is handed by hand: it has no loader, and nothing would ever put those bytes where they belong
Raised when the Container is prg and a Section has a Payload, which waits in
storage for a Transition to load it. A .prg is one block a PET is given with
LOAD, and it has no loader to read storage.
main.ngp
include "pet/3032.ngp"
include "pet/d64.ngp"
modules { "intro.asm" "level.asm" }
phase intro { needs intro then level entry introStart }
phase level { needs level entry levelStart }
entry intro
container prg
intro.asm
.proc introStart
.transition level
.endp
level.asm
.section
map .byte 1, 2, 3
.ends
.proc levelStart
lda map
@stop jmp @stop
.endp
error[NGA6241]: `map` waits in storage, and a `prg` is one block a PET is handed by hand: it has no loader, and nothing would ever put those bytes where they belong
--> level.asm:1:1
|
1 | .section
| ^^^^^^^^
error[NGA6241]: `levelStart` waits in storage, and a `prg` is one block a PET is handed by hand: it has no loader, and nothing would ever put those bytes where they belong
--> level.asm:5:1
|
5 | .proc levelStart
| ^^^^^^^^^^^^^^^^
Build the same program as container d64, the diskette whose other sectors a
Transition reads. Or leave out the storage document, here pet/d64.ngp: every
Section then stays in memory, and a Transition loads nothing.
NGA6242
error · the program comes to {required:n} sectors and the Phases left {available:n}: a diskette holds both, and the Phases are placed first
Raised when a Commodore diskette, d64, d80 or d82, has too few free
sectors left for the program's own file. The Phases' storage is written first.
The program, the file LOAD reads, then goes into what is left as a chain of
sectors, 254 bytes of it in each. The message counts the sectors the program
needs and those left.
Make the Payloads smaller with a transform, or use a larger surface, d80 or
d82, with the storage document of that surface.
NGA6243
error · the program has no bytes, and a {container} of none would load nothing
Raised when the Container is prg, d64 or bs93 and the entry Phase has no
Section that writes a byte. Each of them is one block that a machine loads and
then enters, and a block of nothing has nothing to enter.
main.ngp
modules { "main.asm" }
container prg
main.asm
.proc entry
.endp
error[NGA6243]: the program has no bytes, and a `prg` of none would load nothing
Give the entry Phase the code it runs. A raw image of the same program is an empty file, which is all such a program is, so a raw image is not refused.
NGA6244
error · the tool wrote no {container} and found nothing wrong with the program: the fault is the tool's
Raised when a Container came out with no bytes and nothing the tool checked said why. Every other refusal of a Container names its reason. This one stands for the places where writing stops on something an earlier Step should have ruled out, such as a Label the tool declared itself and then cannot find. It is a check of the tool's own work, and nothing a Project declares is meant to reach it. Report it with the Project that raised it. Without this check the tool would write an empty file and report success.
NGA6245
error · under {document}, {section} {what}, and a choice may differ from the first in bytes alone
A document that choose names may change bytes and nothing else, because the
program is placed once for all of them. Here a .if takes a branch of another
length under the second document, so entry would be one byte longer.
main.ngp
include "atari/800xl.ngp"
choose { "low.ngp" "high.ngp" }
modules { "detect.asm" "main.asm" }
load { needs detect init detect }
phase main { needs main }
entry main
container xex
low.ngp
constants { LEVEL = 1 }
high.ngp
constants { LEVEL = 2 }
detect.asm
.proc detect
lda #1
sta ngaChoice
rts
.endp
main.asm
.proc entry
.if LEVEL == 1
lda #1
.else
lda #1
ora #2
.endif
sta level
rts
.endp
.section
level .res 1
.ends
error[NGA6245]: under `high.ngp`, `entry` is 8 bytes rather than 6, and a choice may differ from the first in bytes alone
--> main.asm:1:1
|
1 | .proc entry
| ^^^^^^^^^^^
Make both branches the same length, or decide at run time what the .if
decided.
NGA6246
error · {document} changes the byte of {section} at offset {offset:n}, which runs while the file loads, before anything is chosen
Nothing is chosen until the first init of the load block returns, so the
code it runs still holds the first document's bytes. Code that finds the
hardware names the places it looks at by numbers or by registers no document
declares.
main.ngp
include "atari/800xl.ngp"
choose { "low.ngp" "high.ngp" }
modules { "detect.asm" "main.asm" }
load { needs detect init detect }
phase main { needs main }
entry main
container xex
low.ngp
target { register PORT $D640 }
high.ngp
target { register PORT $D740 }
detect.asm
.proc detect
lda PORT
and #1
sta ngaChoice
rts
.endp
main.asm
.proc entry
sta PORT
rts
.endp
error[NGA6246]: `high.ngp` changes the byte of `detect` at offset 2, which runs while the file loads, before anything is chosen
--> detect.asm:1:1
|
1 | .proc detect
| ^^^^^^^^^^^^
Read $D640 and $D740 by their numbers in the code that chooses. Code that
uses the chosen registers while the file loads can be a second init, which
runs after the bytes are changed.
NGA6247
error · {document} changes the byte of {section} at offset {offset:n}, and the load never holds it as it is where it could change it
The bytes a document changes are changed where the load has them in memory as they are. A section carried encoded and decoded under a ROM is never there, so its bytes cannot be changed.
main.ngp
include "atari/800xl.ngp"
include "atari/roms.ngp"
choose { "low.ngp" "high.ngp" }
modules { "detect.asm" "intro.asm" "game.asm" "art.asm" }
load { needs detect init detect }
phase intro { needs intro then game entry introStart }
phase game { needs game, art without osrom, mathpack entry gameStart }
entry intro
transform zx0 { art.art }
container xex
low.ngp
constants { LEVEL = 1 }
high.ngp
constants { LEVEL = 2 }
detect.asm
.proc detect
lda #1
sta ngaChoice
rts
.endp
intro.asm
.proc introStart
.transition game
.endp
game.asm
.proc gameStart
lda art
sta seen
rts
.endp
.section
seen .res 1
.ends
art.asm
.export art
.macro rows n
.if n > 0
.byte 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4
rows n - 1
.endif
.endm
.section in underOsLow
art .byte LEVEL
rows 16
.ends
error[NGA6247]: `high.ngp` changes the byte of `art` at offset 0, and the load never holds it as it is where it could change it
--> art.asm:10:1
|
10 | .section in underOsLow
| ^^^^^^^^
Take the section out of the transform, or keep the bytes that differ in a
section of their own outside it.
NGA6248
warning · nothing the file runs while it loads names ngaChoice, so it always loads as {document}
Nothing that runs while the file loads names ngaChoice, so the byte stays
zero and the file always loads as the first document. The program is built,
and the other documents are carried for nothing.
main.ngp
include "atari/800xl.ngp"
choose { "low.ngp" "high.ngp" }
modules { "main.asm" }
container xex
low.ngp
constants { LEVEL = 1 }
high.ngp
constants { LEVEL = 2 }
main.asm
.proc entry
lda #LEVEL
sta level
rts
.endp
.section
level .res 1
.ends
warning[NGA6248]: nothing the file runs while it loads names `ngaChoice`, so it always loads as `low.ngp`
--> main.ngp:3:1
|
3 | choose { "low.ngp" "high.ngp" }
| ^^^^^^
Give the load block an init that finds out which document the machine needs
and writes its index into ngaChoice.
NGA7001
error · unexpected character {character}
The lexer found a character, outside a comment or a literal, that no token of
C begins with: $, @, a backtick, a \, or a letter beyond ASCII in a name.
A name is ASCII letters, digits and _.
static u8 total;
static void entry()
{
total = $10;
}
error[NGA7001]: unexpected character `$`
--> main.ngc:5:11
|
5 | total = $10;
| ^
$ is the assembler's prefix for hexadecimal. C writes 0x10. A character
beyond ASCII belongs in a literal that names a Charset, see
NGA7016. A byte that is not valid UTF-8 is reported here too when
it stands outside a comment or a literal; inside one it is
NGA7003.
NGA7002
error · control character {code:hex} in source
The lexer found a byte below $20 other than tab, line feed and carriage
return, or the byte $7F, between tokens or inside a string literal or a
character constant. A form feed or a vertical tab is not whitespace here.
Refusing these bytes means that a file that is not text, such as a binary named
as a .ngc or a source saved as UTF-16, stops here and is not read as tokens.
Inside a literal, a raw tab is allowed, as it is in an assembler string.
Delete the character, or save the file as UTF-8. A byte that should be in a
string is written as an escape, such as \n, or as a number in a u8 array.
A comment may hold a control character. The line quoted under the message shows
the byte as its symbol from Unicode's Control Pictures, ␀ for a NUL.
NGA7003
error · invalid UTF-8 encoding
A comment or a literal holds bytes that are not UTF-8. Source is UTF-8. A file
saved in an 8-bit code page, such as Windows-1250, or text exported from an
Atari editor, has bytes above $7F that are not valid UTF-8. A comment reports
this once, a literal at each bad byte.
Convert the file to UTF-8. Outside a comment or a literal, such a byte is
NGA7001.
NGA7004
error · /* is not closed before the end of the file
A block comment runs to the first */, and there is none before the end of the
file. Usually the */ was deleted, or a comment opened to disable some code
was never closed.
static u8 total;
/* Clears the total.
static void clear()
{
total = 0;
}
error[NGA7004]: `/*` is not closed before the end of the file
--> main.ngc:3:1
|
3 | /* Clears the total.
| ^^
Close the comment, or write it as // lines.
NGA7005
error · a backslash at the end of a line does not carry a // comment onto the next
C joins a line that ends in a backslash to the next one before it looks for
comments. In C, a // comment that ends in \ therefore also comments out the
line below it. The subset joins no lines, and refuses the comment rather than
compile a program that a C compiler reads differently.
// Converted from C:\ART\
static u8 const tiles[] = { 0, 1, 2 };
error[NGA7005]: a backslash at the end of a line does not carry a `//` comment onto the next
--> main.ngc:1:25
|
1 | // Converted from C:\ART\
| ^
End the comment with a character other than the backslash.
NGA7006
error · a leading zero does not make {constant} octal; write it in decimal, 0x or 0b
C reads a constant with a leading zero as octal, so 040 is 32 in C. The
subset has no octal. Reading 040 as 40 would differ from C, so the spelling
is refused. Padding a column of numbers with zeros is the usual cause.
static u8 const widths[] = { 100, 040 };
error[NGA7006]: a leading zero does not make `040` octal; write it in decimal, `0x` or `0b`
--> main.ngc:1:35
|
1 | static u8 const widths[] = { 100, 040 };
| ^^^
Drop the leading zeros. 0 alone is zero.
NGA7007
error · {suffix}: an integer constant takes no suffix
C23's suffixes are recognised and refused: u, l, ll and wb, in either
case, and u beside one of the others. A constant of the subset has no type of
its own. It takes the type of the operand beside it or of the object it is
assigned to, so a suffix has nothing to say.
static u16 delay;
static void entry()
{
delay = 1000u;
}
error[NGA7007]: `u`: an integer constant takes no suffix
--> main.ngc:5:15
|
5 | delay = 1000u;
| ^
Drop the suffix. Where the type matters, a cast gives it: (u16)1000. Any
other letter after the digits is NGA7009.
NGA7008
error · there are no floating-point constants
There is no floating-point type, so a constant with a fraction or an exponent
has nothing to be. Raised for 1.5, .5, 1e5 and the hexadecimal 0x1p3.
static u8 half;
static void entry()
{
half = 0.5;
}
error[NGA7008]: there are no floating-point constants
--> main.ngc:5:10
|
5 | half = 0.5;
| ^^^
Write the value scaled to an integer, such as 0.5 as 128 in the low byte of
an 8.8 fixed-point u16.
NGA7009
error · {character} is not valid in a {base} constant
A constant holds a digit its base does not have, or a letter after the digits
that is no suffix: a 2 in a binary constant, a G in a hexadecimal one. A
_ is one too: the assembler groups digits with _, and C groups them with
'. The character may stand straight after the prefix, as in 0xG0 or
0b_1010.
static u8 const mask = 0b1010_0101;
error[NGA7009]: `_` is not valid in a binary constant
--> main.ngc:1:30
|
1 | static u8 const mask = 0b1010_0101;
| ^
Write 0b1010'0101. A suffix C would take is NGA7007 instead.
NGA7010
error · {prefix} is not followed by any digits
0x or 0b has nothing after it, or only a suffix such as u. A prefix
followed by a character that is no digit of its base, as in 0xG0 or 0b_1010,
is NGA7009 at that character.
static u8 const mask = 0x;
error[NGA7010]: `0x` is not followed by any digits
--> main.ngc:1:24
|
1 | static u8 const mask = 0x;
| ^^
Write the digits after the prefix.
NGA7011
error · ' in an integer constant must stand between digits
' groups the digits of a constant, as in 0xFF'FF or 1'000. It needs a
digit on each side: it cannot follow the prefix, end the constant, or stand
next to another '. The assembler has the same rule for _,
NGA0012.
static u8 const mask = 0b'1010'0101;
error[NGA7011]: `'` in an integer constant must stand between digits
--> main.ngc:1:26
|
1 | static u8 const mask = 0b'1010'0101;
| ^
Only the first misplaced separator of a constant is reported.
NGA7012
error · this constant is too large to be represented
The lexer holds a constant in a signed 64-bit number, and this one is above
0x7FFF'FFFF'FFFF'FFFF. No type of the subset is wider than 16 bits, so no
program needs a constant this large.
static u16 const mask = 0xFFFF'FFFF'FFFF'FFFF;
error[NGA7012]: this constant is too large to be represented
--> main.ngc:1:25
|
1 | static u16 const mask = 0xFFFF'FFFF'FFFF'FFFF;
| ^^^^^^^^^^^^^^^^^^^^^
A constant the lexer can hold and the type where it is used cannot is
NGA7206.
NGA7013
error · {name} is reserved: C keeps a name that begins with __, or with _ and a capital, for the compiler
C reserves the names that begin with __, or with _ and a capital letter, for
the compiler. This compiler uses them: the scratch bytes it adds to a Proc are
named __t0, __t1 and on, in the Proc's scope. Refusing them in a program
keeps the two sets of names apart.
static u8 __tmp;
error[NGA7013]: `__tmp` is reserved: C keeps a name that begins with `__`, or with `_` and a capital, for the compiler
--> main.ngc:1:11
|
1 | static u8 __tmp;
| ^^^^^
Rename it. _tmp, with a lower-case letter after one _, is allowed, and so
is a __ anywhere but at the start.
NGA7014
error · this {what} is not closed before the end of its line
A string literal or a character constant ends on the line it starts on. Raised where the closing quote is missing, or where a text was continued onto the next line.
static u8 const title[] = "SCORE;
error[NGA7014]: this string literal is not closed before the end of its line
--> main.ngc:1:27
|
1 | static u8 const title[] = "SCORE;
| ^^^^^^^
Close the quote. For a text longer than a line, write a literal on each line.
Adjacent literals join where they carry the same prefix, see
NGA7103.
NGA7015
error · {escape} is no escape: the six are \\, \", \', \n, \t and \0
A literal has the assembler's six escapes and no others, so there is no \x,
no octal and no \r. Each escape is one ASCII character that the literal's
Charset translates, and a byte that no character stands for has no escape.
static u8 const title[] = "SCORE\x9B";
error[NGA7015]: `\x` is no escape: the six are `\\`, `\"`, `\'`, `\n`, `\t` and `\0`
--> main.ngc:1:33
|
1 | static u8 const title[] = "SCORE\x9B";
| ^^
Name a Charset that maps a character to the byte: atascii maps \n to
$9B. Otherwise write the bytes as an array of constants. See
Character sets.
NGA7016
error · {character} is not ASCII, and this literal names no character set
A literal without a prefix is ASCII, copied to the bytes as it is. A character beyond ASCII has no byte until a Charset says which one, so it is refused, once per character.
static u8 const lives[] = "LIVES ♥";
error[NGA7016]: `♥` is not ASCII, and this literal names no character set
--> main.ngc:1:34
|
1 | static u8 const lives[] = "LIVES ♥";
| ^
Glue the Charset's name to the opening quote, in a Project that includes
atari/800xl.ngp. An array given a literal also gets its terminating \0,
which atascii does not map, so give the array its size to leave it out:
lives[7] = atascii"LIVES ♥". A prefix that no Module exports is
NGA7201. See Character sets.
NGA7017
error · a character constant holds one character, and this holds {what}
A character constant is one character, or one escape, between single quotes.
Raised for '', and for more than one character, which C accepts with a value
each compiler chooses. A string written in single quotes is the usual cause.
static u8 const title[] = 'SCORE';
error[NGA7017]: a character constant holds one character, and this holds more than one
--> main.ngc:1:27
|
1 | static u8 const title[] = 'SCORE';
| ^^^^^^^
Write a string in double quotes.
NGA7100
error · expected {expected}, found {found}
The parser found a token that the grammar does not allow where it stands. It
reports what it expected and what it found, skips to the ; that ends the
statement or past the } of the block, and carries on. Several things C has
and the subset does not arrive here: a prototype, unsigned, long, short
and signed, goto, a value on an enumerator, and a statement before the
first label of a switch.
static void draw();
static void entry()
{
draw();
}
static void draw()
{
}
error[NGA7100]: expected `{`, found `;`
--> main.ngc:1:19
|
1 | static void draw();
| ^
Delete the prototype. A function can be called from anywhere in its file, before its definition as well as after it. See What is not there.
NGA7101
error · {what} nest more than {limit} deep
The parser limits how deep a program nests: operators 64 deep in one
expression, parentheses 64 deep, and blocks together with if, while, do
and for 127 deep. A call, a prefix operator and = each count as one level
of operators. The compiler walks the tree recursively in every pass, and the
limits keep that within a thread's stack. The parser reports once and skips
what it refused.
Split the expression with locals, or move the inner part of a deep nest into a
function. See Limits. The assembler's limit is
NGA0104.
NGA7102
error · the subset spells {found} as {spelling}
The subset spells each type one way, and int and char are not the spelling
of any. The message names the one to use. Raised wherever a type is written: at
file scope, for a local, a parameter, a member or a cast.
static int score;
error[NGA7102]: the subset spells `int` as `i16`
--> main.ngc:1:8
|
1 | static int score;
| ^^^
Write i16 for int and u8 for char. A value that fits a byte is cheaper
as a u8 or an i8 on the 6502. unsigned, long, short and signed are
parse errors, NGA7100.
NGA7103
error · a literal of {second} is not joined to one of {first}
Adjacent string literals join into one, as in C, only where they carry the same prefix. No prefix counts as a prefix of its own: ASCII, untranslated. C would give the joined literal the one prefix written; the subset refuses the join.
main.ngp
include "atari/800xl.ngp"
modules { "main.ngc" }
main.ngc
static u8 const title[] = "SCORE " screen"000";
error[NGA7103]: a literal of `screen` is not joined to one of no prefix
--> main.ngc:1:36
|
1 | static u8 const title[] = "SCORE " screen"000";
| ^^^^^^^^^^^
Give every piece the same prefix: screen"SCORE " screen"000".
NGA7200
error · the compiler does not compile {construct} yet
The grammar reads more of C than the compiler compiles. A construct that parses
and has no code behind it is refused where it stands, and the message names it.
Among them are a call of anything but a name, an assignment to anything but a
name, an expression statement that neither assigns nor calls, a constant
shifted by a value, and any operator on a pointer but +, -, == and !=.
static u8 x;
static u8 y;
static void entry()
{
x = 1 << y;
}
error[NGA7200]: the compiler does not compile a constant shifted by a value yet
--> main.ngc:6:7
|
6 | x = 1 << y;
| ^^^^^^
Rewrite it with what compiles, here as x = 1; followed by x <<= y;. See
Statements and expressions.
NGA7201
error · {name} is not declared
A name needs no declaration before its use, and most names are visible to the
whole program. A static name is seen only in its own file, a name of an
assembler Module only where that Module .exports it, and a local only in its
block or in the statement that declares it. The Charset before a literal is a
name too.
main.ngc
static u8 shown;
static void entry()
{
reset();
shown = lives;
}
other.ngc
static u8 lives;
void reset()
{
lives = 3;
}
error[NGA7201]: `lives` is not declared
--> main.ngc:6:11
|
6 | shown = lives;
| ^^^^^
lives is static in other.ngc. Drop the static, or give other.ngc a
function that returns it. A name that is visible but cannot be called is
NGA7202.
NGA7202
error · {name} is not a function, and only a function or a .proc can be called
Only a C function or an assembler .proc can be called. Raised for a call of an
object, a type, or a name the assembler exports that is not a Proc, such as a
Label over code in a .section. A Proc says what it takes and returns through
its .declare lines. A Label says nothing about either.
main.ngc
static void entry()
{
clear();
}
clear.asm
.export clear
.section
clear lda #0
sta $0600
rts
.ends
error[NGA7202]: `clear` is not a function, and only a function or a `.proc` can be called
--> main.ngc:3:3
|
3 | clear();
| ^^^^^
Write the routine as .proc clear and .endp, and keep the .export. See
Reading the assembler.
NGA7203
error · {name} is a function, and a function cannot be assigned
A function's name stands for its code, and code is not assigned. Raised for an
assignment to a C function or to an assembler .proc. The usual intent is a
handler that changes while the program runs, which is a pointer of a function
type.
static void idle()
{
}
static void update()
{
}
static void entry()
{
update = idle;
}
error[NGA7203]: `update` is a function, and a function cannot be assigned
--> main.ngc:11:3
|
11 | update = idle;
| ^^^^^^
Declare the handler as a pointer, typedef void step(); and
static step* update;, and assign the function to it. See
Function types.
NGA7204
error · {name} is already defined in this file
A file defines each name once. Raised for a second object, function, type or
enumerator of a name the file defines already, and for a local or a parameter
declared twice in one scope. C takes two u8 x; at file scope as one object,
and the subset refuses them as well. An enumerator of a plain enum is a name
of the file, so it meets the file's other names.
static u8 score;
static u16 score;
error[NGA7204]: `score` is already defined in this file
--> main.ngc:2:12
|
2 | static u16 score;
| ^^^^^
note: the previous definition of `score` is here
--> main.ngc:1:11
|
1 | static u8 score;
| ^^^^^
Rename one, or delete the second. While a file has a name defined twice at file
scope its bodies are not checked, so more findings may follow the fix. The same
name exported by two files is NGA2205.
NGA7205
note · the previous definition of {name} is here
Follows NGA7204, and NGA7271 for a second extern,
and points at the first definition of the name.
NGA7206
error · {value} is outside the range of {type}
An integer constant takes its type from where it is used: the object it is
assigned to, the parameter it is given to, or the operand beside it. Raised
where that type cannot hold it. An expression of constants is folded exactly,
and only the answer is held to the type, so 256 - 1 stands where a u8 is
wanted and 200 + 100 does not. A - directly before a constant is its sign,
so -128 is an i8.
static u8 timer;
static void entry()
{
timer = 300;
}
error[NGA7206]: 300 is outside the range of `u8`
--> main.ngc:5:11
|
5 | timer = 300;
| ^^^
Use a wider type, or a cast where the wrap is meant: (u8)300 is 44. A
constant beside a u8 operand is held to u8 even where the result goes into a
u16, so widen the operand: (u16)x + 300. In a comparison the same constant
is a warning, NGA7210.
NGA7207
error · {left} and {right} differ in signedness, and only a cast mixes them
The operands of one operator have one signedness, and so do an object and the value assigned to it. C converts one to the other by its promotion rules, which are easy to misread, so the subset asks for a cast that says which is meant.
static u8 x;
static i8 dx;
static void entry()
{
x += dx;
}
error[NGA7207]: `u8` and `i8` differ in signedness, and only a cast mixes them
--> main.ngc:6:5
|
6 | x += dx;
| ^^
Cast one side. x += (u8)dx; adds the same byte, so a negative dx still
moves x down. A wider value assigned to a narrower object is
NGA7208.
NGA7208
error · a {from} does not fit in the {to} it is assigned to without a cast
A wider value is not assigned to a narrower object without a cast. C drops the
high byte silently; here the cast says that it is meant. Raised for an
assignment, an argument and a return. A narrower value is widened where it is
assigned, a u8 with zeros and an i8 with its sign, so that direction needs
nothing.
static u16 score;
static u8 low;
static void entry()
{
low = score;
}
error[NGA7208]: a `u16` does not fit in the `u8` it is assigned to without a cast
--> main.ngc:6:9
|
6 | low = score;
| ^^^^^
Cast to keep the low byte, low = (u8)score;, or write (u8)(score >> 8) for
the high one.
NGA7209
error · a bool holds true, false or a comparison, and is neither an operand nor an integer
A bool holds true, false or the result of a comparison. An integer is not
assigned to one, a bool is not assigned to an integer, and a bool is no
operand of arithmetic or of a comparison. C converts any integer to 0 or 1 on
the way into a bool, and the subset has no such conversion. !, && and
|| take a bool.
static bool paused;
static void entry()
{
paused = 0;
}
error[NGA7209]: a `bool` holds `true`, `false` or a comparison, and is neither an operand nor an integer
--> main.ngc:5:12
|
5 | paused = 0;
| ^
Write false or true. Make a bool of a number with a comparison,
paused = x != 0;, and read one as a number with a cast, (u8)paused. An
integer where a condition is expected is NGA7212.
NGA7210
warning · {value} is outside the range of {type}, so this comparison is always {outcome}
A comparison with a constant outside the range of the other operand has one
answer for every value, and the message says which. A u8 widened by a cast
still holds 0 to 255, and the message names u8 rather than the type of the
cast.
static u8 table[256];
static void entry()
{
for (u8 i = 0; i < 256; ++i)
table[i] = i;
}
warning[NGA7210]: 256 is outside the range of `u8`, so this comparison is always true
--> main.ngc:5:22
|
5 | for (u8 i = 0; i < 256; ++i)
| ^^^
This loop never ends, because i goes from 255 back to 0. Count with a wider
type, or write the loop as do ... while (i != 0);, which stops when i wraps.
A constant out of range anywhere but a comparison is an error,
NGA7206.
NGA7211
error · a value of {type} shifted by {count}: the count is from 0 to {largest}
An operator works in the width of its operands. C promotes a u8 to int
before a shift, and the subset does not, so the count runs from 0 to 7 for an
8-bit value and from 0 to 15 for a 16-bit one. Raised for a constant count
outside that.
static u8 high;
static u8 low;
static u16 address;
static void entry()
{
address = high << 8 | low;
}
error[NGA7211]: a value of `u8` shifted by 8: the count is from 0 to 7
--> main.ngc:7:21
|
7 | address = high << 8 | low;
| ^
Widen the value before the shift: (u16)high << 8 | low.
NGA7212
error · a condition is a bool, and this is {what}
The condition of if, while, do, for and ?:, and each operand of !,
&& and ||, is a bool. C takes any integer or pointer there and tests it
against zero. The subset wants the comparison written.
static u8 frames;
static void entry()
{
while (1)
frames += 1;
}
error[NGA7212]: a condition is a `bool`, and this is an integer constant
--> main.ngc:5:10
|
5 | while (1)
| ^
Write while (true) or for (;;) for a loop without end, if (lives != 0)
for a count, and p != nullptr for a pointer.
NGA7213
error · {keyword} stands in no {around}
continue stands in a loop, and break in a loop or a switch. Raised for one
in neither, usually a break meant to leave the function.
static u8 lives;
static u8 shown;
static void entry()
{
if (lives == 0)
break;
shown = lives;
}
error[NGA7213]: `break` stands in no loop or `switch`
--> main.ngc:7:5
|
7 | break;
| ^^^^^^
Write return to leave the function. In a block under [[with(...)]], a
break or a continue that would leave the block is NGA7283.
NGA7214
error · {name} is not a type
A declaration starts with a type, and this name is not one. The types are u8,
i8, u16, i16 and bool, and the names of the program's enum,
enum struct, struct and union types and of its function types. A name from
<stdint.h> is the usual cause, since there is no preprocessor and no header.
static uint8_t lives;
error[NGA7214]: `uint8_t` is not a type
--> main.ngc:1:8
|
1 | static uint8_t lives;
| ^^^^^^^
uint8_t is u8, int8_t is i8, uint16_t is u16 and int16_t is
i16. int and char are NGA7102.
NGA7216
error · {type} has no enumerator {name}
An enumerator is reached through its type, as in Light::RED, and the type has
no enumerator of this name. Usually it is misspelled, or it belongs to another
enumeration.
enum struct Light { RED, AMBER, GREEN };
static Light light;
static void entry()
{
light = Light::YELLOW;
}
error[NGA7216]: `Light` has no enumerator `YELLOW`
--> main.ngc:7:18
|
7 | light = Light::YELLOW;
| ^^^^^^
Use a name the type declares. An enumerator of another type used as a case
label is NGA7220.
NGA7217
error · {type} is an enumeration, whose values are compared and never computed
The values of an enumeration are assigned and compared, by the order of their
enumerators, and are never computed. There is no arithmetic on them, no ++
and no bitwise operator. A plain enum is held to this as an enum struct is.
enum struct Light { RED, AMBER, GREEN };
static Light light;
static void entry()
{
light = light + 1;
}
error[NGA7217]: `Light` is an enumeration, whose values are compared and never computed
--> main.ngc:7:11
|
7 | light = light + 1;
| ^^^^^^^^^
Assign the next enumerator by name, in a switch over the current one. Where
the program needs the number, (u8)light reads it, and a u8 is the type for
a value that is computed. A value of another type meeting the enumeration is
NGA7218.
NGA7218
error · {left} and {right} are different types
An enumeration meets only its own type: it is assigned a value of that type and
compared with one. An integer, a constant and a value of another enumeration
are different types. The two ways of a ?: must be of one type as well, and so
must two struct objects in an assignment.
enum struct Light { RED, AMBER, GREEN };
static Light light;
static void entry()
{
light = 0;
}
error[NGA7218]: a `Light` and an integer constant are different types
--> main.ngc:7:11
|
7 | light = 0;
| ^
Assign the enumerator, light = Light::RED;. No cast turns a number into an
enumerator. Arithmetic on a value of the type is NGA7217.
NGA7219
error · a switch takes a value of an enum or an integer, and this is {what}
Raised for a switch over a bool, a pointer, a struct or a union.
static bool paused;
static u8 colour;
static void entry()
{
switch (paused)
{
case true:
colour = 2;
break;
}
}
error[NGA7219]: a `switch` takes a value of an `enum` or an integer, and this is a `bool`
--> main.ngc:6:11
|
6 | switch (paused)
| ^^^^^^
Test a bool with if and else.
NGA7220
error · {label} is not an enumerator of {type}
A switch over an enumeration takes the type's own enumerators as its labels.
Raised for a number, or an enumerator of another type. A switch over a plain
enum takes a label written either way, EASY or Level::EASY.
enum struct Light { RED, AMBER, GREEN };
static Light light;
static u8 stops;
static void entry()
{
switch (light)
{
case 0:
stops += 1;
break;
default:
break;
}
}
error[NGA7220]: `0` is not an enumerator of `Light`
--> main.ngc:10:8
|
10 | case 0:
| ^
Write the enumerator, case Light::RED:. A name the type does not declare is
NGA7216.
NGA7221
error · {label} is a label of this switch already
A label stands once in a switch, and so does default. The labels of a
switch over an integer are compared by value, after folding, so 0x41
repeats 'A'. Over a plain enum, EASY and Level::EASY are one label.
static u8 key;
static u8 dx;
static void entry()
{
switch (key)
{
case 'A':
dx = 255;
break;
case 0x41:
dx = 1;
break;
}
}
error[NGA7221]: `0x41` is a label of this `switch` already
--> main.ngc:11:3
|
11 | case 0x41:
| ^^^^^^^^^^
Delete one of the two, or join their statements under one label.
NGA7222
warning · no case names {names} of {type}, and the switch has no default
A switch over an enum or an enum struct names every enumerator in a
case, or has a default. Raised where some enumerators are named by no case and nothing
takes the rest, so a value of one of them runs none of the switch.
enum struct Light { RED, AMBER, GREEN };
static Light light;
static u8 stops;
static void entry()
{
switch ( light )
{
case Light::RED:
stops += 1;
break;
}
}
warning[NGA7222]: no case names `AMBER`, `GREEN` of `Light`, and the `switch` has no `default`
--> main.ngc:8:3
|
8 | switch ( light )
| ^^^^^^^^^^^^^^^^
Add the missing cases, or a default: with an empty break where doing
nothing is meant. A switch over an integer is not checked.
NGA7223
error · {name} has {count} enumerators, and an enumeration holds 256 at most
A value of an enumeration is one byte, and its enumerators are numbered from 0, so a type names 256 of them at most. Raised at the name of a type that declares more. Split it into two types.
NGA7224
error · {name} takes as many arguments as it has parameters, {count}, and this call gives {given}
The subset has no default arguments and no variadic functions. The count is
the function's own for a function of C, the function type's for a call through
a pointer, and the number of .declare arg lines for a .proc of the
assembler.
static u8 total;
static u8 add( u8 x, u8 y )
{
return x + y;
}
static void entry()
{
total = add( 1 );
}
error[NGA7224]: `add` takes as many arguments as it has parameters, 2, and this call gives 1
--> main.ngc:10:11
|
10 | total = add( 1 );
| ^^^^^^^^
Where the callee is a .proc, check that every byte the caller is meant to
write has a .declare arg over it. A .ztemp without one is the Proc's own
scratch.
NGA7225
error · {name} returns nothing, and this reads what it returns
Raised where a call is read as a value, in an assignment, an expression or a
condition, and the callee returns nothing: a void function, or a .proc with
no .declare ret. A call that stands as a statement is not refused.
main.ngc
static u8 level;
static void entry()
{
level = roll();
}
dice.asm
.export roll
.proc roll
result .ztemp 1
lda #4
sta result
rts
.endp
error[NGA7225]: `roll` returns nothing, and this reads what it returns
--> main.ngc:5:11
|
5 | level = roll();
| ^^^^^^
Here the Proc leaves a value in result, but nothing says the byte is its
result. Put .declare ret on the line above result. A result left in A is
declared as well, .declare ret a; see .declare.
NGA7226
error · {name} returns {type}, and this return gives no value
Raised at a bare return; in a function declared with a result.
static u8 lives;
static u8 loseLife()
{
if ( lives == 0 )
return;
lives -= 1;
return lives;
}
error[NGA7226]: `loseLife` returns a `u8`, and this `return` gives no value
--> main.ngc:6:5
|
6 | return;
| ^^^^^^^
Give the return the value the caller should see, or declare the function
void where no caller reads its result.
NGA7227
error · {name} returns nothing, and this return gives a value
Raised at return with a value in a void function.
static u8 lives;
static void loseLife()
{
lives -= 1;
return lives;
}
error[NGA7227]: `loseLife` returns nothing, and this `return` gives a value
--> main.ngc:6:3
|
6 | return lives;
| ^^^^^^^^^^^^^
Declare the function's result type where the value is meant to reach the caller, and drop the value otherwise.
NGA7228
error · {name} returns {type}, and the end of its body is reached with no return
Raised at the closing brace of a function with a result, where some path through
the body reaches it without a return. A loop that nothing leaves reaches no
end, and an if whose two arms both return is complete.
enum struct Light { RED, GREEN };
static u8 delay( Light light )
{
switch ( light )
{
case Light::RED:
return 50;
case Light::GREEN:
return 10;
}
}
error[NGA7228]: `delay` returns a `u8`, and the end of its body is reached with no `return`
--> main.ngc:12:1
|
12 | }
| ^
A switch over an enumeration is not complete even where every enumerator has
a case that returns, because a byte that holds no enumerator's value runs none
of them. Make one of the cases default:, or end the function with a return.
NGA7229
error · this call closes a cycle of calls, {cycle}, and a function never reaches itself
Raised at a call that closes a cycle of calls: a function that calls itself, or functions that call one another, in one file or across several. Each cycle is reported once, at the call written last.
A function's parameters, locals and result are Temporaries, each at one address, and not a frame on a stack. A second activation of a function would write over the bytes of the first.
static u8 depth;
static void descend( u8 level )
{
depth = level;
if ( level < 4 )
descend( level + 1 );
}
error[NGA7229]: this call closes a cycle of calls, `descend` -> `descend`, and a function never reaches itself
--> main.ngc:7:5
|
7 | descend( level + 1 );
| ^^^^^^^^^^^^^^^^^^^^
Write the recursion as a loop. Where it needs to remember a path, keep the path in an array of your own and index it as a stack.
NGA7230
error · {what} is not cast to a {type}
Raised at a cast the subset does not have. Only a bool casts to a bool: a
bool holds true, false or a comparison, and a cast is none of them. A
pointer casts to another pointer or to a u16, and only a pointer, a u16 or a
constant casts to a pointer. A function's address casts to nothing: it goes to a
pointer of a function type.
static u8 lives;
static bool alive;
static void entry()
{
alive = (bool)lives;
}
error[NGA7230]: a `u8` is not cast to a `bool`
--> main.ngc:6:11
|
6 | alive = (bool)lives;
| ^^^^^^^^^^^
Write the comparison that is meant, lives != 0. To get a pointer into a
narrower integer, cast it to u16 first.
NGA7231
error · {what} is given a constant, and this is not one
An object at file scope or a static local that is given a value has that
value in the program's bytes when it is loaded. No code runs to compute it, so
the value must be a constant: a literal, a const with a constant value, an
enumerator, sizeof, an address the assembler knows, or nullptr. Also raised
at a case label of a switch over an integer that is not a constant; an
enumerator there is a constant of another type, which is
NGA7218.
static u8 width = 40;
static u8 middle = width / 2;
error[NGA7231]: `middle` is given a constant, and this is not one
--> main.ngc:2:20
|
2 | static u8 middle = width / 2;
| ^^^^^^^^^
Here width is a variable. Declare it const, and width / 2 is a constant.
Where the value really is computed, assign it at the start of entry.
NGA7232
error · {name} is const, and is given no value where it is declared
Raised at a const object declared without a value, at file scope or in a
function. Nothing may assign it later, so it would hold whatever the byte held.
static const u8 LIMIT;
error[NGA7232]: `LIMIT` is `const`, and is given no value where it is declared
--> main.ngc:1:17
|
1 | static const u8 LIMIT;
| ^^^^^
Give it its value where it is declared. To read a value the assembler or the
Project defines, declare it extern const u8 LIMIT; instead; see Reading the
assembler.
NGA7233
error · a constant is defined through itself, {cycle}
Raised where constants are defined through one another in a circle, so that none of them has a value to start from. The circle may pass through the size of an array, and through other files. It is reported once, at the name that closes it.
static const u8 FIRST = SECOND + 1;
static const u8 SECOND = FIRST;
error[NGA7233]: a constant is defined through itself, `FIRST` -> `SECOND` -> `FIRST`
--> main.ngc:2:26
|
2 | static const u8 SECOND = FIRST;
| ^^^^^
A constant that names itself directly is NGA7235.
NGA7234
error · {name} is const, and is not assigned
Raised at an assignment, a compound assignment, ++ or -- whose target is
const: a const object, an element or a member of one, or a name of the
assembler that C reads as a constant or that an extern const declares.
static const u8 LIVES = 3;
static void entry()
{
LIVES -= 1;
}
error[NGA7234]: `LIVES` is `const`, and is not assigned
--> main.ngc:5:3
|
5 | LIVES -= 1;
| ^^^^^
Drop the const where the object is meant to change. A write through a pointer
to const is NGA7247.
NGA7235
error · {name} is read in its own {what}, before it has one
Raised where the value a declaration gives reads the name being declared. As in
C, the name is in scope from its own declarator on, and there it holds nothing
yet. An array whose size is sizeof of itself is the same mistake.
static u8 count = 0;
static void entry()
{
u8 count = count + 1;
}
error[NGA7235]: `count` is read in its own value, before it has one
--> main.ngc:5:14
|
5 | u8 count = count + 1;
| ^^^^^
The usual cause is a local named like a global: the local hides the global already in its own value. Rename the local.
NGA7236
error · {index} is outside {name}, whose elements are indexed from 0 to {last}
Raised where a constant index is outside an array of known size: below 0, or at
or past its count. sizeof t[9] is held to it too.
static u8 scores[4];
static u8 last;
static void entry()
{
last = scores[4];
}
error[NGA7236]: 4 is outside `scores`, whose elements are indexed from 0 to 3
--> main.ngc:6:17
|
6 | last = scores[4];
| ^
Only a constant index of an array is checked. A pointer is not, an array of the assembler whose count a string leaves unknown is not, and neither is an index computed at run time; see What a program may not count on.
NGA7237
error · an index is {allowed}, and this is {what}
The index of an array is a u8, a u16, or a constant inside the array. A
signed index is refused, since an array starts at index 0, and so is a bool or
a value of an enumeration. A pointer takes any integer, signed included, since
it may point into the middle of something. A [[striped]] array takes only a
u8 or a constant, because its index goes into X.
static u8 heights[8];
static i8 column;
static u8 height;
static void entry()
{
height = heights[column];
}
error[NGA7237]: an index is a `u8`, a `u16` or a constant inside the array, and this is an `i8`
--> main.ngc:7:20
|
7 | height = heights[column];
| ^^^^^^
Cast the index to the unsigned type that is meant, heights[(u8)column], or
declare it unsigned.
NGA7238
error · {name} is an array, and is not assigned but for its elements
Raised at an assignment, or a compound one, to a whole array: an array of C, an
array member of a struct, or an array the assembler exports. C has no array
assignment either.
static u8 shown[4];
static u8 saved[4];
static void entry()
{
saved = shown;
}
error[NGA7238]: `saved` is an array, and is not assigned but for its elements
--> main.ngc:6:3
|
6 | saved = shown;
| ^^^^^
Copy the elements in a loop. Or keep the array in a struct, which is assigned
whole: with struct Row { u8 cells[4]; };, two Rows copy with saved = shown;.
NGA7239
error · {name} is neither an array nor a pointer, and nothing else is indexed
Raised at x[i] where x is neither an array nor a pointer, and at sizeof x[0] of such a name.
static u16 score;
static u8 low;
static void entry()
{
low = score[0];
}
error[NGA7239]: `score` is neither an array nor a pointer, and nothing else is indexed
--> main.ngc:6:9
|
6 | low = score[0];
| ^^^^^
A byte of a u16 is a cast: (u8)score is the low byte and (u8)(score >> 8)
the high one. An address held in a u16 is indexed through a cast to a
pointer, ((u8*)address)[2].
NGA7240
error · this divides by zero
Raised where the divisor of / or % is a constant that folds to zero. A
divisor computed at run time is not checked.
static const u8 ROWS = 0;
static u8 perRow;
static void entry()
{
perRow = 200 / ROWS;
}
error[NGA7240]: this divides by zero
--> main.ngc:6:18
|
6 | perRow = 200 / ROWS;
| ^^^^
NGA7241
error · {name} is given {given} values, more than the {count} it holds
Raised where a list gives an array more values than its size. A string literal
gives its characters and a \0; where the array holds the characters exactly,
the \0 is dropped, so u8 name[3] = "ABC"; is accepted and u8 name[2] = "ABC"; is not.
static const u8 steps[3] = { 1, 2, 4, 8 };
error[NGA7241]: `steps` is given 4 values, more than the 3 it holds
--> main.ngc:1:28
|
1 | static const u8 steps[3] = { 1, 2, 4, 8 };
| ^^^^^^^^^^^^^^
Leave the size out, steps[], and the list gives it.
NGA7242
error · {name} is {what}, and is given {given}
Raised where an array is given a single value, or a scalar is given a braced list.
static u8 counts[4] = 0;
error[NGA7242]: `counts` is an array, and is given a single value
--> main.ngc:1:11
|
1 | static u8 counts[4] = 0;
| ^^^^^^
An array takes a list, { 0, 0, 0, 0 }, and a scalar a bare value.
NGA7243
error · the size of {name} is a constant from 1 to {largest}
Raised where the size of an array is missing, zero, not a constant, or so large that the array would pass 64 KB. The largest count is 65536 divided by the size of an element, and the message gives it. The size may be left out only where a list or a string literal gives the count.
static u8 buffer[];
error[NGA7243]: the size of `buffer` is a constant from 1 to 65536
--> main.ngc:1:11
|
1 | static u8 buffer[];
| ^^^^^^
Write the size, buffer[40]. A size from a variable is not in the subset; use
a const.
NGA7244
error · {name} is {what}, and a declaration declares pointers or none
A declaration of several names declares them all pointers, or none. In C,
u8* from, to; makes from a pointer and to a byte, which reads as two
pointers.
static u8* from, to;
error[NGA7244]: `to` is no pointer, and a declaration declares pointers or none
--> main.ngc:1:18
|
1 | static u8* from, to;
| ^^
Write one declaration per name, or put the * on each, u8 *from, *to;.
NGA7245
error · {name} is a parameter, whose address is not taken; copy it to a local
Raised at & of a parameter. A parameter is a byte of the callee that the
caller writes before the jsr, and the compiler may keep it in a register or
share its byte with another Temporary, so it has no address to give.
static void clear( u8* at )
{
*at = 0;
}
static void reset( u8 count )
{
clear( &count );
}
error[NGA7245]: `count` is a parameter, whose address is not taken; copy it to a local
--> main.ngc:8:11
|
8 | clear( &count );
| ^^^^^
A local whose address is taken is given a byte of its own, so u8 copy = count; and clear( © ); work.
NGA7246
error · {left} and {right} do not meet
Raised where a pointer meets a value it does not agree with, in an assignment,
an argument, a return, ==, != or -. A pointer takes nullptr, or a
pointer to the same type, which may add const or volatile but not drop
them. An integer is not a pointer, and an array's name is a pointer to its first
element, so n = table is refused here too.
static u8* cursor;
static void entry()
{
cursor = 0;
}
error[NGA7246]: a `u8*` and an integer constant do not meet
--> main.ngc:5:12
|
5 | cursor = 0;
| ^
Write nullptr for no address. An address held in a u16 goes in through a
cast, cursor = (u8*)address;.
NGA7247
error · what is written here is const, reached through a pointer to const
Raised at a write through a pointer to const, by *p, p[i] or p->m. The
pointer may change; what it points at may not be written through it.
static const u8* source;
static void entry()
{
source[0] = 1;
}
error[NGA7247]: what is written here is `const`, reached through a pointer to `const`
--> main.ngc:5:3
|
5 | source[0] = 1;
| ^^^^^^^^^
Declare the pointer without const where it is meant to write. It can then no
longer be given the address of a const object, which is
NGA7246.
NGA7248
error · {what} is no pointer, and only a pointer is dereferenced
Raised at *x where x is not a pointer.
static u16 address;
static u8 value;
static void entry()
{
value = *address;
}
error[NGA7248]: a `u16` is no pointer, and only a pointer is dereferenced
--> main.ngc:6:12
|
6 | value = *address;
| ^^^^^^^
A u16 that holds an address is not a pointer. Cast it, *(u8*)address, or
keep the address in a pointer. x->m on what is no pointer is
NGA7255.
NGA7249
error · {name} is a pointer, and C would ignore the size written for it
Raised at a size written in a parameter's brackets. In C the parameter is a pointer whatever the size says, and the function takes an array of any length, so here the size is refused rather than ignored.
static void clearRow( u8 row[40] )
{
row[0] = 0;
}
error[NGA7249]: `row` is a pointer, and C would ignore the size written for it
--> main.ngc:1:29
|
1 | static void clearRow( u8 row[40] )
| ^^^
Write u8 row[] or u8* row, and pass the length where the function needs it.
NGA7250
error · {name} has no members, and C gives such a type no size
Raised at a struct or a union declared with no members.
struct Empty { };
error[NGA7250]: `Empty` has no members, and C gives such a type no size
--> main.ngc:1:8
|
1 | struct Empty { };
| ^^^^^
Give it the members it is meant to hold, or remove it.
NGA7251
error · a type holds itself by value and has no size, {cycle}
Raised where a struct or a union holds itself by value, directly or through
other types. It is reported once per cycle, at the member that closes it.
struct Node { u8 value; Node next; };
error[NGA7251]: a type holds itself by value and has no size, `Node` -> `Node`
--> main.ngc:1:25
|
1 | struct Node { u8 value; Node next; };
| ^^^^
Hold a pointer instead, Node* next;.
NGA7252
error · {name} is a member, which is given no value and is not const
Raised at a member that is const, a const pointer, or given a value in the
type.
struct Ship { const u8 speed; u8 x; };
error[NGA7252]: `speed` is a member, which is given no value and is not `const`
--> main.ngc:1:24
|
1 | struct Ship { const u8 speed; u8 x; };
| ^^^^^
Put const on the object, static const Ship SCOUT = { 3, 0 };, and give the
values in its list. A member may still be a pointer to const.
NGA7253
error · {type} has no member {name}
Raised at s.m or p->m where the type has no member of that name. Through a
pointer, the member is looked up in the type the pointer points at.
struct Point { u8 x; u8 y; };
static Point cursor;
static void entry()
{
cursor.z = 0;
}
error[NGA7253]: `Point` has no member `z`
--> main.ngc:7:10
|
7 | cursor.z = 0;
| ^
NGA7254
error · {name} is a member of {type} already
Raised at the second member of one name in a struct or a union.
struct Point { u8 x; u8 x; };
error[NGA7254]: `x` is a member of `Point` already
--> main.ngc:1:25
|
1 | struct Point { u8 x; u8 x; };
| ^
NGA7255
error · {what} is no struct or union, and only one has members
Raised at s.m where s is not a struct or a union, and at p->m where
p does not point at one. . on a pointer lands here too.
struct Point { u8 x; u8 y; };
static Point* cursor;
static void entry()
{
cursor.x = 0;
}
error[NGA7255]: a `Point*` is no `struct` or `union`, and only one has members
--> main.ngc:7:3
|
7 | cursor.x = 0;
| ^^^^^^
Write cursor->x through a pointer, and s.x on an object.
NGA7256
error · {what} is given {given}
Raised where a braced list does not fit what it fills: more values than a
struct has members, more than one for a union, whose list gives its first
member alone, an array member given a single value or more values than it
holds, or a list where a scalar stands.
struct Point { u8 x; u8 y; };
static Point start = { 1, 2, 3 };
error[NGA7256]: `Point` is given 3 values for 2 members
--> main.ngc:3:22
|
3 | static Point start = { 1, 2, 3 };
| ^^^^^^^^^^^
Give one value per member, in order. An array member takes a list of its own,
in braces, as a nested struct does: C's elided braces are not read, so a
struct Row { u8 cells[2]; }; is given { { 1, 2 } }.
NGA7257
error · {what} is a struct or a union, which no operator takes
Raised where a struct or a union is the operand of an operator: a
comparison, arithmetic, a unary operator or a cast. A struct is assigned
whole, passed to a function, or read member by member.
struct Point { u8 x; u8 y; };
static Point here;
static Point there;
static bool same;
static void entry()
{
same = here == there;
}
error[NGA7257]: this is a `struct` or a `union`, which no operator takes
--> main.ngc:9:10
|
9 | same = here == there;
| ^^^^^^^^^^^^^
Compare the members, here.x == there.x && here.y == there.y.
NGA7258
error · {name} is no attribute of the subset
The dialect's attributes are the nine listed in
Attributes, written without a prefix. Raised at
any other, at one with a prefix such as [[gnu::packed]] or
[[nga::striped]], at C23's own such as [[deprecated]], and at striped,
trampoline or slot given arguments.
[[maybe_unused]] static u8 spare;
error[NGA7258]: `maybe_unused` is no attribute of the subset
--> main.ngc:1:3
|
1 | [[maybe_unused]] static u8 spare;
| ^^^^^^^^^^^^
NGA7259
error · [[{attribute}]] applies to {applies}, and {what} is none
Raised where one of the dialect's attributes stands on something it does not
apply to. The message names what it applies to. Two cases are not obvious from
the table in Attributes: [[in(PANE)]] is refused
on a pointer, which lies in the zero page that no Window covers, and an
extern that is a [[slot]] takes no other attribute.
[[striped]] static u16 score;
error[NGA7259]: `[[striped]]` applies to an array, and `score` is none
--> main.ngc:1:24
|
1 | [[striped]] static u16 score;
| ^^^^^
NGA7260
error · {name} is an array of {what}, which lies in no stripes
[[striped]] splits each element into one array per byte, so it applies to an
array of u16, of i16, or of a struct whose members are scalars, pointers
or structs of the same kind. An array of one-byte elements is a single stripe
already. A union, and a struct with an array member, are refused.
[[striped]] static u8 heights[8];
error[NGA7260]: `heights` is an array of a `u8`, which lies in no stripes
--> main.ngc:1:23
|
1 | [[striped]] static u8 heights[8];
| ^^^^^^^
Drop the attribute from an array of bytes. For a struct with an array member,
write the array's elements as members of their own.
NGA7261
error · {name} has {count} elements, and a striped array holds 256 at most
A striped array is indexed through X, so it holds 256 elements at most.
[[striped]] static u16 scores[300];
error[NGA7261]: `scores` has 300 elements, and a striped array holds 256 at most
--> main.ngc:1:24
|
1 | [[striped]] static u16 scores[300];
| ^^^^^^
Split it into two striped arrays, or drop the attribute.
NGA7262
error · {name} lies in stripes, and has no address of its own
Raised at & of an element of a [[striped]] array, at & of a member of more
than one byte in one, and at the array's name used as a value. The bytes of an
element lie in different stripes, so neither the element nor the array has one
address.
struct Point { u8 x; u8 y; };
[[striped]] static Point points[8];
static Point* chosen;
static void entry()
{
chosen = &points[2];
}
error[NGA7262]: `points` lies in stripes, and has no address of its own
--> main.ngc:8:12
|
8 | chosen = &points[2];
| ^^^^^^^^^^
A member of one byte has an address, so &points[2].x is allowed. Pass the
index where the code would pass a pointer.
NGA7263
error · {name} is a Label of the assembler with no shape in C: {reason}
Raised where C reads a name an .asm Module exports, and the Label has no
shape C can give a type. A Label's shape is the run of one kind of directive at
it: .byte lines, .word lines, or reservations. The message gives the reason:
it holds both .byte and .word, or code, or nothing, or a reservation whose
size the compiler cannot fold, or a .if chooses what stands at it. The note
points at the Label.
main.ngc
static u8 first;
static void entry()
{
first = enemies[0];
}
enemies.asm
.export enemies
.section
enemies .byte 1
.word 300
.ends
error[NGA7263]: `enemies` is a Label of the assembler with no shape in C: it holds both `.byte` and `.word`
--> main.ngc:5:11
|
5 | first = enemies[0];
| ^^^^^^^
note: `enemies` is defined here
--> enemies.asm:4:1
|
4 | enemies .byte 1
| ^^^^^^^
For data of mixed widths, say how C reads it with an extern declaration,
usually of a struct: struct Enemy { u8 kind; u16 speed; }; and extern const Enemy enemies[];. See Reading the
assembler.
NGA7264
error · {name} is {reason}, which C does not read
C names something an .asm Module exports that C has no reading for: a
Charset used as a value, a Slot or a macro of the assembler, a Pane or a Window
anywhere but in an attribute, or a Constant that is a string or names one of
those. Raised where an expression names it and where an extern declares it.
C reads a Label as memory and a Constant as a number, and a string is neither.
Put text under a Label in a .byte line, which C reads as u8[]. A Charset is
named as a literal's prefix, letters"AB", and a Pane in [[in(...)]] and
[[with(...)]].
main.ngc
static u8 x;
static void entry()
{
x = GREETING[0];
}
text.asm
.export GREETING
GREETING = "HELLO"
error[NGA7264]: `GREETING` is a string, which C does not read
--> main.ngc:5:7
|
5 | x = GREETING[0];
| ^^^^^^^^
note: `GREETING` is defined here
--> text.asm:3:1
|
3 | GREETING = "HELLO"
| ^^^^^^^^
NGA7265
error · {name} is a reserved Region, which C does not reach
C names a Region the Target declares reserved, in an expression or in an
extern. A named ram Region or a register is memory at its address in C;
a reserved one belongs to something else, usually the machine's OS or a DOS,
and C does not reach it.
Write what touches those bytes in an .asm Module, and call that Proc from C.
main.ngp
target {
region $0080 .. $00FF ram
region dos $0700 .. $1FFF reserved
region $2000 .. $BFFF ram
}
modules { "main.ngc" }
main.ngc
static u8 x;
static void entry()
{
x = dos[0];
}
error[NGA7265]: `dos` is a `reserved` Region, which C does not reach
--> main.ngc:5:7
|
5 | x = dos[0];
| ^^^
note: `dos` is defined here
--> main.ngp:3:10
|
3 | region dos $0700 .. $1FFF reserved
| ^^^
NGA7267
note · {name} is defined here
Follows NGA7263, NGA7264 or
NGA7265, and points at the definition of the name C was refused:
the Label, Constant or Charset in its .asm Module, or the Region in the
Project file.
NGA7268
error · {name} takes or returns u8[N], bytes that a call from C does not hand over
C calls a .proc of the assembler, with no extern for it, and one of the
Proc's .declare arg or .declare ret lines is u8[N]: written so, or over a
reservation of three bytes or more with no type written. Such bytes are not a
value, and a call from C hands over values only.
Declare the Proc with an extern whose parameter is a struct of those N
bytes, extern void draw(Spot spot); for the example below, and the call
copies the struct into the Proc's bytes. Or split the bytes into
.declare arg lines of u8 and u16.
main.ngc
static void entry()
{
draw( 0 );
}
draw.asm
.export draw
.proc draw
.declare arg
spot .ztemp 3
rts
.endp
error[NGA7268]: `draw` takes or returns `u8[N]`, bytes that a call from C does not hand over
--> main.ngc:3:3
|
3 | draw( 0 );
| ^^^^^^^^^
NGA7269
error · {name} is defined in C, and extern declares only what the assembler exports
An extern names a variable or a function that a .ngc file defines. In this
dialect extern says how C reads a name the assembler exports. A name defined
in C is visible to every file without a declaration, so delete the extern.
main.ngc
extern u8 lives;
static void entry()
{
lives -= 1;
}
other.ngc
u8 lives = 3;
error[NGA7269]: `lives` is defined in C, and `extern` declares only what the assembler exports
--> main.ngc:1:11
|
1 | extern u8 lives;
| ^^^^^
NGA7270
error · {name} is declared extern, and nothing the assembler exports is named so
An extern names something no .asm Module exports. The Module may define
the Label without an .export, the Module may be missing from the Project's
modules block, or the two spellings may differ.
main.ngc
extern u16 score;
static void entry()
{
score += 10;
}
score.asm
.section
score .res 2
.ends
error[NGA7270]: `score` is declared `extern`, and nothing the assembler exports is named so
--> main.ngc:1:12
|
1 | extern u16 score;
| ^^^^^
Add .export score to the Module.
NGA7271
error · {name} is declared extern already, and a name is declared once in the program
A second extern of one name, in another .ngc file. One extern is visible
to every file of the program, so the second could only repeat it or contradict
it. Keep one, in any file. Two in one file are
NGA7204 instead.
main.ngc
extern u16 score;
static void entry()
{
score += 10;
}
other.ngc
extern u16 score;
score.asm
.export score
.section
score .res 2
.ends
error[NGA7271]: `score` is declared `extern` already, and a name is declared once in the program
--> other.ngc:1:12
|
1 | extern u16 score;
| ^^^^^
note: the previous definition of `score` is here
--> main.ngc:1:12
|
1 | extern u16 score;
| ^^^^^
NGA7272
error · {name} is declared extern, and {what}
An extern the dialect refuses as it is written. The message gives the
reason. An extern is given no value and carries no attribute, because the
bytes and where they stand are the assembler's. A .proc is declared as a
function and not as an object. A Constant is declared const, as a scalar, an
enum struct or a pointer.
Here a Constant of the Project is declared without const:
main.ngp
constants {
LEVELS = 8
}
modules { "main.ngc" }
main.ngc
extern u8 LEVELS;
static u8 level;
static void entry()
{
level = LEVELS;
}
error[NGA7272]: `LEVELS` is declared `extern`, and names a Constant, which is declared `const`, as a scalar, an `enum struct` or a pointer
--> main.ngc:1:11
|
1 | extern u8 LEVELS;
| ^^^^^^
A Constant is a number and not memory, so C cannot write it. Write
extern const u8 LEVELS;.
NGA7273
error · {name} {what}
An extern whose type does not fit the bytes it reads. The bytes start at the
Label and run past other Labels to the end of the Label's Section, and no
further. The message says what does not fit: the type needs more bytes than
the assembler wrote before the Section ends; NAME[] reads elements that do
not divide those bytes evenly; or a named Region is longer or shorter than the
type.
main.ngc
extern const u8 steps[4];
static u8 step;
static void entry()
{
step = steps[1];
}
steps.asm
.export steps
.section
steps .byte 1, 2, 4
.ends
error[NGA7273]: `steps` reads 4 bytes, and the assembler wrote 3 to the end of its Section
--> main.ngc:1:17
|
1 | extern const u8 steps[4];
| ^^^^^
Give the array the size of the data, or write steps[] and let the bytes give
the count. Where something other than data ends the bytes first, the finding is
NGA7274.
NGA7274
error · {name} reads past what the assembler wrote as data: {reason}
The bytes an extern reads run into something that is not data before the
type is covered: code, lines a .if chooses between, or a .res whose size
the compiler cannot fold. The message names which. An extern is checked item
by item, and none of these has items to check.
main.ngc
extern const u8 table[4];
static u8 value;
static void entry()
{
value = table[3];
}
table.asm
.export table
.section
table .byte 1, 2
rts
.ends
error[NGA7274]: `table` reads past what the assembler wrote as data: it holds code
--> main.ngc:1:17
|
1 | extern const u8 table[4];
| ^^^^^
Make the type as long as the data in front of the code, or put the data in a Section of its own.
NGA7275
error · {path}, at offset {offset}, splits an item the assembler wrote
An extern's type puts the start or the end of a value of C inside an item the
assembler wrote. The usual cases are a .word read as two u8s, and a
struct whose u16 member starts on the second byte of a .word. The message
names the element or member and its offset.
A .word holds one value, so C may not read it as two bytes. Two .byte
items read as one u16 are accepted, and a .res may be read as any type.
main.ngc
extern const u8 speeds[4];
static u8 low;
static void entry()
{
low = speeds[0];
}
speeds.asm
.export speeds
.section
speeds .word 300, 500
.ends
error[NGA7275]: `speeds[0]`, at offset 0, splits an item the assembler wrote
--> main.ngc:1:17
|
1 | extern const u8 speeds[4];
| ^^^^^^
Declare speeds as u16, or write the data as .byte if it is bytes.
NGA7276
error · {what} holds {value}, which is no {type}
An extern of a bool or an enum struct over a byte whose value is outside
the type: not 0 or 1 for a bool, not below the number of enumerators for an
enum struct. A Constant declared as one of them is checked the same way. Only
items whose value the compiler can fold are checked, so an address is not.
main.ngc
enum struct Mode { OFF, ON, BLINK };
extern const Mode modes[];
static Mode mode;
static void entry()
{
mode = modes[2];
}
modes.asm
.export modes
.section
modes .byte 0, 1, 3
.ends
error[NGA7276]: `modes[2]` holds 3, which is no `Mode`
--> main.ngc:3:19
|
3 | extern const Mode modes[];
| ^^^^^
Correct the table, or add the enumerator it was written for.
NGA7277
error · {name} {what}
extern RESULT NAME(PARAMETERS); does not match the .proc it declares. The
message says where: the name is no .proc; there are more or fewer parameters
than .declare arg lines; a result is declared where the Proc has no
.declare ret, or the reverse; a parameter's type does not fit its bytes; or a
parameter's name is not the name of the byte its .declare stands over.
main.ngc
extern void plot(u8 x, u8 y);
static void entry()
{
plot( 3, 4 );
}
plot.asm
.export plot
.proc plot
.declare arg
column .ztemp 1
.declare arg
row .ztemp 1
rts
.endp
error[NGA7277]: `plot` names its parameter `x` where the `.proc` declares `column`
--> main.ngc:1:21
|
1 | extern void plot(u8 x, u8 y);
| ^
A parameter's name, where one is written, is held to the Proc's byte. Name them
column and row, or leave the names out: extern void plot(u8, u8);. See
Reading the assembler.
NGA7278
error · {name} is no character set, and a literal's prefix names one
A string or character literal's prefix names something an .asm Module
exports, and it is not a Charset. Here a Label has the name the program meant
for a Charset. A prefix that names nothing at all is
NGA7201.
main.ngc
static const u8 title[] = screen"READY";
static u8 first;
static void entry()
{
first = title[0];
}
screen.asm
.export screen
.section
screen .res 40
.ends
error[NGA7278]: `screen` is no character set, and a literal's prefix names one
--> main.ngc:1:27
|
1 | static const u8 title[] = screen"READY";
| ^^^^^^
Rename the Label, or write the Charset's own name in front of the quote. See Character sets.
NGA7279
error · {name} is {what}, and {form} takes {takes}
[[in(...)]], [[under(...)]] or [[with(...)]] names something that is not
what the form takes. in takes a Pane or a family. under takes a Pane, not a
family, since which member is shown is known only at run time. with(NAME)
takes a Pane, with(NAME, i) a family or a Window, and with(NAME = STATE) a
Window. The message says what the name is instead, or that the program does
not know it.
main.ngp
include "atari/130xe.ngp"
modules { "main.ngc" }
panes in ext { rows[3] }
main.ngc
[[in(rows)]] static u8 row[40];
static void entry()
{
[[with(rows)]]
{
row[0] = 0;
}
}
error[NGA7279]: `rows` is a family, and `with(NAME)` takes a pane
--> main.ngc:5:10
|
5 | [[with(rows)]]
| ^^^^
rows is a family, so the block names a member: [[with(rows, i)]]. See
Panes.
NGA7280
error · {name} is in family {family}, whose member is known at run time alone: call it in a with({family}, i) block
A direct call of a function [[in(FAMILY)]] from code that is not in a block
showing a member of the family. The compiler wraps a call into another Pane in
a .with of that Pane, and a family has several members; the call does not
say which one.
main.ngp
include "atari/130xe.ngp"
modules { "main.ngc" }
panes in ext { rows[3] }
main.ngc
[[in(rows)]] static u8 row[40];
[[in(rows)]] static void clear()
{
row[0] = 0;
}
static void entry()
{
clear();
}
error[NGA7280]: `clear` is in family `rows`, whose member is known at run time alone: call it in a `with(rows, i)` block
--> main.ngc:10:3
|
10 | clear();
| ^^^^^^^
Make the call inside [[with(rows, i)]], where i names the member.
NGA7281
error · {name} is in pane {pane} of window {window}, which this block shows in another state: the call's .with would leave that pane shown, not the block's
Inside a [[with]] block, a call into a function in another Pane of the
Window the block shows. The compiler would wrap the call in a .with of that
other Pane, and after the call the Window would still show it. The rest of the
block would read map with other shown.
main.ngp
include "atari/130xe.ngp"
modules { "main.ngc" }
panes in ext { level, other }
main.ngc
[[in(level)]] static u8 map[40];
[[in(other)]] static u8 tiles[8];
[[in(other)]] static void loadTiles()
{
tiles[0] = 1;
}
static void entry()
{
[[with(level)]]
{
map[0] = 1;
loadTiles();
}
}
error[NGA7281]: `loadTiles` is in pane `other` of window `ext`, which this block shows in another state: the call's `.with` would leave that pane shown, not the block's
--> main.ngc:14:5
|
14 | loadTiles();
| ^^^^^^^^^^^
Make the call before or after the block. A call into a Pane of another Window is wrapped as usual.
NGA7282
error · window {window} is shown by the block this one stands in, and a window shows one state at a time
A [[with]] block stands inside another one on the same Window. A Window
shows one state at a time, so the inner block would take away what the outer
one shows for the rest of it.
main.ngp
include "atari/130xe.ngp"
modules { "main.ngc" }
panes in ext { level, other }
main.ngc
[[in(level)]] static u8 map[40];
[[in(other)]] static u8 tiles[8];
static void entry()
{
[[with(level)]]
{
[[with(other)]]
{
map[0] = tiles[0];
}
}
}
error[NGA7282]: window `ext` is shown by the block this one stands in, and a window shows one state at a time
--> main.ngc:8:7
|
8 | [[with(other)]]
| ^^^^^^^^^^^
Write the two blocks one after the other, and carry the value between them in a local. A block on another Window may stand inside.
NGA7283
error · {keyword} leaves the with block, which would leave the window as the block shows it
return inside a [[with]] block, or a break or continue of a loop outside
the block. A [[transition(...)]] return there is refused the same way.
The block is compiled into a macro used once under .with, and a statement
under .with runs to its end, as the assembler holds with
NGA3007. Where the code is in a Pane, the end of the .with is
what shows that Pane again.
main.ngp
include "atari/130xe.ngp"
modules { "main.ngc" }
panes in ext { level }
main.ngc
[[in(level)]] static u8 map[40];
static void entry()
{
[[with(level)]]
{
if ( map[0] == 0 )
{
return;
}
map[0] = 1;
}
}
error[NGA7283]: `return` leaves the `with` block, which would leave the window as the block shows it
--> main.ngc:9:7
|
9 | return;
| ^^^^^^^
Test inside the block, keep the answer in a local, and leave after the block.
A loop inside the block may break and continue as usual.
NGA7284
error · the address of {name}, in what this block shows, is kept only in a local of the block or handed to a call in it: here it {escapes}
Inside a [[with]] block, the address of data the block shows, such as map
or &map[i], is stored anywhere but in a local declared in the block, or is
returned. The address means that data only while the block shows its Pane.
After the block the same address may show another Bank.
main.ngp
include "atari/130xe.ngp"
modules { "main.ngc" }
panes in ext { level }
main.ngc
[[in(level)]] static u8 map[40];
static u8* cursor;
static void entry()
{
[[with(level)]]
{
cursor = &map[1];
}
}
error[NGA7284]: the address of `map`, in what this block shows, is kept only in a local of the block or handed to a call in it: here it is stored in `cursor`, declared outside the block
--> main.ngc:8:14
|
8 | cursor = &map[1];
| ^^^^^^^
Keep the pointer in a local of the block, or hand it to a call made inside the block. To remember a position past the block, keep the index rather than the address.
NGA7286
error · the index of with({name}, i) is {what}, and X takes a u8 or a constant
The index of [[with(FAMILY, i)]] or [[with(WINDOW, i)]] is not a u8
variable or a constant from 0 to 255. The message says what it is. The index is
loaded into X before the block, as .with NAME, x takes it in the
assembler.
main.ngp
include "atari/130xe.ngp"
modules { "main.ngc" }
panes in ext { rows[3] }
main.ngc
[[in(rows)]] static u8 row[40];
static u16 which;
static void entry()
{
[[with(rows, which)]]
{
row[0] = 0;
}
}
error[NGA7286]: the index of `with(rows, i)` is a `u16`, and `X` takes a `u8` or a constant
--> main.ngc:6:16
|
6 | [[with(rows, which)]]
| ^^^^^
Compute the index into a u8 local before the block, u8 member = (u8)which;,
and name that local.
NGA7287
error · [[{attribute}]] takes {takes}
An attribute of the dialect is given arguments it does not take. The message
says what it takes. [[placement(...)]] takes zeropage or absolute;
[[in(...)]] and [[under(...)]] take one name; [[transition(...)]] takes
one Phase; [[with(...)]] takes one of its four forms; and trampoline stands
only beside a with.
[[placement(zp)]] static u8 counter;
static void entry()
{
counter = 0;
}
error[NGA7287]: `[[placement]]` takes `zeropage` or `absolute`
--> main.ngc:1:3
|
1 | [[placement(zp)]] static u8 counter;
| ^^^^^^^^^^^^^
An attribute given arguments where it takes none is not one of the dialect's,
NGA7258. See Attributes.
NGA7288
error · {name} is [[in]] a pane and [[under]] one, and code under a pane is in none
A function carries both [[in(PANE)]] and [[under(PANE)]]. in puts the
function's code in the Pane. under keeps the code outside the Window and has
it run while the Pane is shown, which is what lets it show another state of
the Window. A function is one or the other.
main.ngp
include "atari/130xe.ngp"
modules { "main.ngc" }
panes in ext { level }
main.ngc
[[in(level)]] static u8 map[40];
[[in(level), under(level)]] static void draw()
{
map[0] = 1;
}
static void entry()
{
[[with(level)]]
{
draw();
}
}
error[NGA7288]: `draw` is `[[in]]` a pane and `[[under]]` one, and code under a pane is in none
--> main.ngc:3:41
|
3 | [[in(level), under(level)]] static void draw()
| ^^^^
Keep in where the code may live in the Bank beside its data. Keep under
where it must stay outside the Window.
NGA7289
error · this block shows another state of window {window} from code in pane {pane}, which cannot switch its own window: write [[with(...), trampoline]], and pay a Proc in fixed and a jsr
Code [[in(PANE)]] holds a [[with]] block that shows another state of the
Pane's own Window. Switching the Window would take away the code doing the
switching. The block has to be a Trampoline: a Proc outside the Window that
the code calls with jsr, which shows the other state, runs the block and
shows the code's Pane again. That costs a Proc and a jsr, so the compiler
asks for it to be written.
main.ngp
include "atari/130xe.ngp"
modules { "main.ngc" }
panes in ext { level, other }
main.ngc
[[in(level)]] static u8 map[40];
[[in(other)]] static u8 tiles[8];
[[in(level)]] static void draw()
{
u8 tile = 0;
[[with(other)]]
{
tile = tiles[0];
}
map[0] = tile;
}
static void entry()
{
draw();
}
error[NGA7289]: this block shows another state of window `ext` from code in pane `level`, which cannot switch its own window: write `[[with(...), trampoline]]`, and pay a Proc in fixed and a `jsr`
--> main.ngc:7:5
|
7 | [[with(other)]]
| ^^^^^^^^^^^
Write [[with(other), trampoline]]. A function [[under(level)]] stands
outside the Window and needs no Trampoline for the same block. See
Panes.
NGA7290
error · trampoline on a block that needs none: {where}, and the block is a macro under .with
trampoline on a [[with]] block that does not need one. The message says
why: the code stands outside every Window, it is in a Pane of another Window
than the block's, or it runs [[under]] a Pane and shows that Pane again
itself. There the block is a macro under .with that costs no jsr, and
trampoline would state a cost the code does not pay.
main.ngp
include "atari/130xe.ngp"
modules { "main.ngc" }
panes in ext { level }
main.ngc
[[in(level)]] static u8 map[40];
static void entry()
{
[[with(level), trampoline]]
{
map[0] = 1;
}
}
error[NGA7290]: `trampoline` on a block that needs none: the code is in fixed, and the block is a macro under `.with`
--> main.ngc:5:5
|
5 | [[with(level), trampoline]]
| ^^^^^^^^^^^
Remove trampoline. The opposite case, a block that needs one and does not
say so, is NGA7289.
NGA7291
error · this block shows {pane}, and the code is in {pane} already
A [[with]] block shows the Pane the code is in already. Code in a Pane runs
only while that Pane is shown, so the block switches nothing. Code in a family
is refused any block on the family, since it already runs in the member that
is shown.
main.ngp
include "atari/130xe.ngp"
modules { "main.ngc" }
panes in ext { level }
main.ngc
[[in(level)]] static u8 map[40];
[[in(level)]] static void draw()
{
[[with(level)]]
{
map[0] = 1;
}
}
static void entry()
{
draw();
}
error[NGA7291]: this block shows `level`, and the code is in `level` already
--> main.ngc:5:5
|
5 | [[with(level)]]
| ^^^^^^^^^^^
Remove the block and keep its statements.
NGA7292
error · {name} is in pane {pane} of window {window}, and this code is in pane {own} of it, which cannot switch its own window: call it in a [[with({pane}), trampoline]] block or an [[under({own})]] function
Code [[in(P)]] calls a function in another Pane of the same Window. The call
would have to switch the Window, and the switch would take the calling code
away before the call returned to it.
main.ngp
include "atari/130xe.ngp"
modules { "main.ngc" }
panes in ext { level, other }
main.ngc
[[in(level)]] static u8 map[40];
[[in(other)]] static u8 tiles[8];
[[in(other)]] static void loadTiles()
{
tiles[0] = 1;
}
[[in(level)]] static void draw()
{
loadTiles();
map[0] = 1;
}
static void entry()
{
draw();
}
error[NGA7292]: `loadTiles` is in pane `other` of window `ext`, and this code is in pane `level` of it, which cannot switch its own window: call it in a `[[with(other), trampoline]]` block or an `[[under(level)]]` function
--> main.ngc:11:3
|
11 | loadTiles();
| ^^^^^^^^^^^
The message names the two answers. Make the call in a
[[with(other), trampoline]] block, or write the calling code as an
[[under(level)]] function, which stands outside the Window and may switch
it. See Panes.
NGA7293
error · {name} runs under pane {pane}, called from code in the pane, from another function under it, or in a block that shows it, and this is none
A call of a function [[under(P)]] from code that does not run with P
shown: not code in P, not another function under P, and not inside a
block that shows P. The function names what P holds and does not show P
itself, so whoever calls it shows it.
main.ngp
include "atari/130xe.ngp"
modules { "main.ngc" }
panes in ext { level }
main.ngc
[[in(level)]] static u8 map[40];
[[under(level)]] static void draw()
{
map[0] = 1;
}
static void entry()
{
draw();
}
error[NGA7293]: `draw` runs under pane `level`, called from code in the pane, from another function under it, or in a block that shows it, and this is none
--> main.ngc:10:3
|
10 | draw();
| ^^^^^^
Make the call inside [[with(level)]].
NGA7294
error · a transition enters a phase and never comes back, so it stands on a bare return in a void function, and {what}
[[transition(PHASE)]] return in a function that returns a value, or on a
return that carries one. A Transition enters the next Phase and never comes
back, so there is no caller to take a value.
main.ngp
modules { "main.ngc" "game.ngc" }
phase title { needs main then game entry titleStart }
phase game { needs game entry gameStart }
entry title
main.ngc
static u8 lives;
u8 titleStart()
{
lives = 3;
[[transition(game)]] return lives;
}
game.ngc
void gameStart()
{
for ( ;; )
{
}
}
error[NGA7294]: a transition enters a phase and never comes back, so it stands on a bare `return` in a `void` function, and this one returns a value
--> main.ngc:6:5
|
6 | [[transition(game)]] return lives;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning[NGA2246]: phase `title` declares `then game`, and no `.transition game` is present in it, so the edge is taken by nothing
Make the function void and the return bare. The warning after the error
follows from it: with the Transition refused, nothing takes the edge to game.
NGA7295
error · {name} is a slot, and its binding is its type's: a function binds a vector and a T* const a pointer, and {what}
[[slot]] extern on an object whose type gives no Binding. A Slot's Binding
comes from its type: a function binds a vector, and a pointer that is
const binds a pointer. Anything else is refused, and the message says
what the type is. The pointer must be const because the Transition routine
writes the Cell, not the program.
[[slot]] extern u8* title;
static u8 first;
static void entry()
{
first = title[0];
}
error[NGA7295]: `title` is a slot, and its binding is its type's: a function binds a vector and a `T* const` a pointer, and this pointer is not `const`, and the cell is the transition routine's to write
--> main.ngc:1:21
|
1 | [[slot]] extern u8* title;
| ^^^^^
Write [[slot]] extern u8* const title;. See Slots.
NGA7296
error · {name} fills slot {slot}, whose cell holds an address the program reads as {wanted}, and {what}
[[implements(SLOT)]] stands on a definition that is not what the Slot's Cell
is read as: an object where the Slot is a function, a function where it is a
pointer, a function of another signature, or data of another type than the
pointer's.
[[slot]] extern void draw();
static u8 drawn;
[[implements(draw)]] static void drawRow(u8 row)
{
drawn = row;
}
static void entry()
{
draw();
}
error[NGA7296]: `drawRow` fills slot `draw`, whose cell holds an address the program reads as a `void(void)`, and this one takes or returns something
--> main.ngc:5:34
|
5 | [[implements(draw)]] static void drawRow(u8 row)
| ^^^^^^^
Make the Implementation match the Slot. A Slot to a function may take and
return, so where the parameter is meant, give it to the Slot too:
[[slot]] extern void draw(u8 row);.
NGA7297
error · {name} is no {type}: {what}
The address of a function goes to a pointer of a function type, and the
function's signature is not the type's. The message says where they differ.
Raised also where the address goes to anything but a pointer of a function
type, and for a .proc of the assembler that does not say
.proc NAME, as TYPE.
typedef u8 chooser(u8 x);
static chooser* pick;
static u8 wide(u16 x)
{
return (u8)x;
}
static void entry()
{
pick = &wide;
}
error[NGA7297]: `wide` is no `chooser`: its parameter 1 is a `u16` and the type's a `u8`
--> main.ngc:12:10
|
12 | pick = &wide;
| ^^^^^
Give the function the type's signature. See Function types.
NGA7298
error · {name} is taken as {type} here and as {other} elsewhere, and a function reads its arguments from one place
One function's address is taken as two function types. A member of a type reads its arguments from the type's Temporaries and has none of its own, so it belongs to one type.
typedef u8 chooser(u8 x);
typedef u8 scorer(u8 x);
static chooser* pick;
static scorer* score;
static u8 twice(u8 x)
{
return x + x;
}
static void entry()
{
pick = &twice;
score = &twice;
}
error[NGA7298]: `twice` is taken as `scorer` here and as `chooser` elsewhere, and a function reads its arguments from one place
--> main.ngc:15:11
|
15 | score = &twice;
| ^^^^^^
Use one type for both pointers, or write a second function for the second type that calls the first by name.
NGA7299
error · {name} names a function type, which is a type only as a pointer: {name}*
An object, a member or a local is declared of a function type, without *. A
function type has no bytes, so nothing is of it; it is a type only as a
pointer.
typedef u8 chooser(u8 x);
static chooser pick;
static void entry()
{
}
error[NGA7299]: `chooser` names a function type, which is a type only as a pointer: `chooser*`
--> main.ngc:3:16
|
3 | static chooser pick;
| ^^^^
Write static chooser* pick;.
NGA7300
error · this call is of the function type its caller is a member of, which would write the temporaries the caller reads; a member dispatches through another type, or through a name
A member of a function type calls its own type: through a pointer of the type, or by naming another member. The call would write the type's Temporaries, from which the member is still reading its own arguments.
typedef u8 chooser(u8 x);
static chooser* pick;
static u8 again(u8 x)
{
return pick( x - 1 );
}
static void entry()
{
pick = &again;
pick( 3 );
}
error[NGA7300]: this call is of the function type its caller is a member of, which would write the temporaries the caller reads; a member dispatches through another type, or through a name
--> main.ngc:7:10
|
7 | return pick( x - 1 );
| ^^^^^^^^^^^^^
A member that dispatches makes the second call through another function type, or calls a function that is no member of its own type by name.
NGA7301
error · {name} is written auto and given {what}, which takes its type from where it is used and so has none to give
A local written auto is given a value with no type of its own: an integer
constant, nullptr, or the address of a function. Such a value takes its type
from where it is used, so it has none for auto to take. A later use of the
local is then reported as not declared.
static void entry()
{
auto step = 5;
}
error[NGA7301]: `step` is written `auto` and given an integer constant, which takes its type from where it is used and so has none to give
--> main.ngc:3:8
|
3 | auto step = 5;
| ^^^^
Write the type, u8 step = 5;, or cast the value, auto step = (u8)5;.
NGA7302
error · {name} is written inline and cannot be wrapped into its caller: it {what}
A function written inline cannot be wrapped into its caller, for the reason
the message gives. The reasons are in the shape of the function: it holds a
static local or a local array, or a [[with]] block; it is in a Pane or runs under one; it is a member of a
function type or fills a Slot. A call made under a .with or inside a
[[with]] block is refused at the call. Without inline the compiler leaves
such a call as it is and says nothing.
static u8 out;
inline static u8 counted()
{
static u8 seen = 0;
seen += 1;
return seen;
}
static void entry()
{
out = counted();
}
error[NGA7302]: `counted` is written `inline` and cannot be wrapped into its caller: it holds a `static` local or a local array, which is one object however many callers there are
--> main.ngc:3:1
|
3 | inline static u8 counted()
| ^^^^^^
Remove inline, or move what stops the wrap out of the function. Here seen
can become an object at file scope.
NGA7303
error · inline is written on {what}, which has no body to wrap into a caller
inline is written on something that has no body: a .proc of the assembler
declared by extern, a function type, an object, a struct or an enum. The
compiler wraps only bodies written in C.
main.ngc
inline extern void clear();
static void entry()
{
clear();
}
clear.asm
.export clear
.proc clear
rts
.endp
error[NGA7303]: `inline` is written on a `.proc` of the assembler, which has no body to wrap into a caller
--> main.ngc:1:1
|
1 | inline extern void clear();
| ^^^^^^
Remove inline.
NGA7304
error · {name} is assigned by {operator} where it is used as a value, and reached again in the same expression, which is an order the subset does not fix
An expression uses ++, -- or a compound assignment as a value, and reads or
writes the same variable again elsewhere in it. C does not fix the order of
the two, and the subset does not choose one. The variable is the whole object,
so stepping one element of an array and reading another in the same
expression is refused too.
static u8 queue[] = { 0, 0, 0, 0 };
static u8 head;
static void entry()
{
queue[head] = head++;
}
error[NGA7304]: `head` is assigned by `++` where it is used as a value, and reached again in the same expression, which is an order the subset does not fix
--> main.ngc:6:17
|
6 | queue[head] = head++;
| ^^^^^^
Split it into two statements: queue[head] = head; and then head += 1;.
NGA7305
error · {name} is a pointer, which (zp),y reads through, so it lies in the zero page whatever is asked
[[placement(absolute)]] on the declaration of a pointer. The compiler reads
through a pointer with (zp),y, which has no absolute form, so a pointer lies
in the zero page whatever is asked.
static u8 screen[] = { 1, 2, 3 };
static void entry()
{
[[placement(absolute)]] u8* at = &screen[0];
*at = 0;
}
error[NGA7305]: `at` is a pointer, which `(zp),y` reads through, so it lies in the zero page whatever is asked
--> main.ngc:5:31
|
5 | [[placement(absolute)]] u8* at = &screen[0];
| ^^
Remove the attribute from the pointer. Over a function or a block, absolute
leaves a pointer declared inside in the zero page and says nothing.
NGA7306
error · {name} lies in stripes, whose place its layout settles, so [[placement]] is a second answer
[[placement(...)]] and [[striped]] on one array. A striped array is a
Section per stripe, laid out so that an element is reached with abs,x, and
that layout already settles where it stands.
struct Point { u8 x; u8 y; };
[[placement(zeropage), striped]] static Point points[4];
static void entry()
{
points[0].x = 1;
}
error[NGA7306]: `points` lies in stripes, whose place its layout settles, so `[[placement]]` is a second answer
--> main.ngc:3:47
|
3 | [[placement(zeropage), striped]] static Point points[4];
| ^^^^^^
Remove [[placement]]. See [[striped]].
NGA7307
warning · {name} is {class} already, so this says nothing
[[placement(...)]] asks for the class the declaration has anyway: absolute
on an object at file scope, the class of the function or the block around a
local, or zeropage on a pointer anywhere, since a pointer lies in the zero page
whatever is asked. A static local, a volatile one, one whose address is
taken and any local array are absolute with no [[placement]] over them, as an
object at file scope is, and take the class of a [[placement]] on a block or on
the function around them. A struct or a union of more than four bytes, and a
local array or struct that is const and given constants, are absolute
whatever is asked, so absolute on one of them is this warning too.
[[placement(absolute)]] static u8 lives;
static void entry()
{
lives = 3;
}
warning[NGA7307]: `lives` is `absolute` already, so this says nothing
--> main.ngc:1:35
|
1 | [[placement(absolute)]] static u8 lives;
| ^^^^^
Remove the attribute.
NGA7308
error · {name} is read here before anything writes it, and a static local holds what was there; give it a value where it is declared
A static local is read on some path from the function's entry before any
statement writes it. This dialect does not zero static storage, so the first
call reads whatever was in that byte. Arrays, objects whose address is taken,
and objects given a value are not checked.
static u8 frames;
static void tick()
{
static u8 count;
count += 1;
frames = count;
}
static void entry()
{
tick();
}
error[NGA7308]: `count` is read here before anything writes it, and a `static` local holds what was there; give it a value where it is declared
--> main.ngc:6:3
|
6 | count += 1;
| ^
Give it a value where it is declared: static u8 count = 0;. See
What static, inline and volatile mean here.
NGA7309
error · {name} is a name in a Namespace, and C defines none there; :: reads what the assembler exports
A definition in C is named with ::: a variable, a function, a parameter, a
member or an enumerator. In C, gfx::count reads gfx.count, a name the
assembler exports from .namespace gfx, and C defines no name of its own in a
Namespace.
static void gfx::clear()
{
}
static void entry()
{
}
error[NGA7309]: `gfx::clear` is a name in a Namespace, and C defines none there; `::` reads what the assembler exports
--> main.ngc:1:13
|
1 | static void gfx::clear()
| ^^^^^^^^^^
Give the definition a plain name, or define it in the assembler inside the
.namespace and read it from C with ::.
NGA7310
error · a plain assignment is a statement and not a value: write two assignments; a compound one, such as +=, is a value
A plain assignment stands where a value is read: on the right of another
assignment, in a condition, as an argument or as an operand. In this dialect
= makes a statement and gives no value, so a = b = 0 and
if ((c = next()) != 0) are errors. A compound assignment such as +=, and
++ and --, are values.
static u8 x;
static u8 y;
static void entry()
{
x = y = 0;
}
error[NGA7310]: a plain assignment is a statement and not a value: write two assignments; a compound one, such as `+=`, is a value
--> main.ngc:6:7
|
6 | x = y = 0;
| ^^^^^
Write two assignments, y = 0; and then x = y;. See
Statements and expressions.
NGA7311
error · {name} is const and given constants, so it is read-only data, which lies off the zero page whatever is asked
[[placement(zeropage)]] stands on a local array or struct that is const and
given constants. The compiler keeps such a local as read-only data, filled once
and kept between calls as a static one is, and that data lies off the zero
page whatever is asked: it may go to ROM, and the zero page is RAM. The same
local given a value that is not a constant, such as { seed }, is written each
time its declaration runs and takes [[placement]] as any local array does.
static u8 seed;
static u8 sink;
static void entry()
{
[[placement(zeropage)]] const u8 steps[] = { 1, 2, 4, 8 };
sink = steps[seed];
}
error[NGA7311]: `steps` is `const` and given constants, so it is read-only data, which lies off the zero page whatever is asked
--> main.ngc:6:36
|
6 | [[placement(zeropage)]] const u8 steps[] = { 1, 2, 4, 8 };
| ^^^^^
Remove the attribute, or drop const if the bytes must be in the zero page. See
[[placement(...)]].
NGA7312
warning · {name} is const and given a constant, so it takes no byte, and [[placement]] has nothing to place
[[placement(...)]] stands on a local scalar that is const and given a
constant, static or not. The compiler makes such a local a constant of the
assembler, which takes no byte at all, so there is nothing for the attribute to
place: the value goes into each instruction that reads it, which costs less
than a byte on the zero page would. This is a warning and not an error, since
the program is no worse for it.
static u8 sink;
static void entry()
{
[[placement(zeropage)]] const u8 step = 4;
sink = sink + step;
}
warning[NGA7312]: `step` is `const` and given a constant, so it takes no byte, and `[[placement]]` has nothing to place
--> main.ngc:5:36
|
5 | [[placement(zeropage)]] const u8 step = 4;
| ^^^^
Remove the attribute. Drop const if the value must be a byte the program can
take the address of or change.