3418 lines
113 KiB
JSON
3418 lines
113 KiB
JSON
{
|
|
"chunk": "game_mainProgram0800_515D",
|
|
"unit": "game/mainProgram0800",
|
|
"unitLabels": {
|
|
"game/mainProgram0800": {
|
|
"538B": "cmdDroneShotDown"
|
|
}
|
|
},
|
|
"notes": {
|
|
"515D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "read the single argument byte into cmdParam0 and step mergedCmdReadIndex past this 2-byte command",
|
|
"routine": [
|
|
"cmdClearTarget - Handler of command $86 CLEAR TARGET (2 bytes: BOOMER unit). getBoomerTarget turns the unit",
|
|
"index into that unit's ordinal among all BOOMERs and the matching entry of boomerTargetTable is zeroed, so",
|
|
"the BOOMER stops holding fire for a particular enemy. The carry that getBoomerTarget returns is not tested,",
|
|
"so a non-BOOMER argument would clear a slot chosen by a leftover Y; only the unit menu of a BOOMER offers",
|
|
"the item, so that never happens in practice.",
|
|
"In: mergedCmdBuffer $908F / mergedCmdReadIndex $90B7 (the queued command), cmdParam0 after readCmdArg1",
|
|
"Out: boomerTargetTable $91DC[ordinal] = 0; mergedCmdReadIndex += 2; X = unit, Y = ordinal",
|
|
"Called from: commandHandlerTable slot for $86 ($4D36), dispatched by executeTurnCommands at $4EEE"
|
|
]
|
|
},
|
|
"5160": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X = the BOOMER's unit index"
|
|
},
|
|
"5162": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$3C74: for a BOOMER (unitTypeTable & 7 == 2) returns Y = its ordinal among all BOOMERs"
|
|
},
|
|
"5165": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "0 = no target and no lock"
|
|
},
|
|
"5167": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear this BOOMER's slot of the 20-entry boomerTargetTable at $91DC"
|
|
},
|
|
"516A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done - CLEAR TARGET touches nothing but the target table"
|
|
},
|
|
"516B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "read the two arguments: cmdParam1 = the BOOMER, cmdParam2 = the target unit; read index += 3",
|
|
"routine": [
|
|
"cmdSetTarget - Handler of command $87 SET TARGET (3 bytes: BOOMER unit, target unit). It only rearranges",
|
|
"the parameter bytes so that setBoomerTargetCmd ($3C50) finds the BOOMER in cmdParam0 and the target in",
|
|
"cmdParam2, then jumps there; the result is boomerTargetTable[BOOMER ordinal] = target | $80. The command is",
|
|
"sent by sub_3C20 when the player puts the cursor on an enemy unit with a BOOMER selected. The EOR #$80 on",
|
|
"cmdFromOpponent at $5171 is undone again at $517C without anything reading it in between, and the store at",
|
|
"$5177 is immediately overwritten at $5180 - both are leftovers from an earlier version.",
|
|
"In: the queued command in mergedCmdBuffer; cmdParam1 = BOOMER, cmdParam2 = target after readCmdArgs2",
|
|
"Out: boomerTargetTable $91DC[ordinal] = target | $80 via $3C50; cmdParam0 = BOOMER; read index += 3",
|
|
"Called from: commandHandlerTable slot for $87 ($4D38)"
|
|
]
|
|
},
|
|
"516E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "take a copy of the own/remote flag of the command being executed"
|
|
},
|
|
"5170": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "push it"
|
|
},
|
|
"5171": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "flip bit 7 = 'this command came from the opponent' ..."
|
|
},
|
|
"5173": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "... and store the flipped value back; nothing between here and $517C looks at it, so the flip does nothing (leftover)"
|
|
},
|
|
"5175": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "A = the target unit index"
|
|
},
|
|
"5177": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "cmdParam0 = target - overwritten again at $5180, so this store is dead"
|
|
},
|
|
"5179": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "write cmdParam2 back over itself - a no-op"
|
|
},
|
|
"517B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "pull the untouched own/remote flag"
|
|
},
|
|
"517C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "undo the EOR of $5171"
|
|
},
|
|
"517E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "A = the BOOMER's unit index"
|
|
},
|
|
"5180": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "setBoomerTargetCmd wants the BOOMER in cmdParam0 and the target in cmdParam2"
|
|
},
|
|
"5182": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$3C50: boomerTargetTable[BOOMER ordinal] = cmdParam2 | $80 (target unit plus the 'locked' bit)"
|
|
},
|
|
"5185": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "read the two arguments: cmdParam1 = unit index, cmdParam2 = group byte (id in bits 2-4, side in bit 5)",
|
|
"routine": [
|
|
"cmdJoinGroup - Handler of command $88 JOIN GROUP (3 bytes: unit, group byte). It jumps to joinUnitToGroup",
|
|
"($4AD4), which makes the unit follow the group's movement and sets unitFlagsTable = (old & 3) | group | $40.",
|
|
"The eight instructions at $5188-$5197 are a shuffle whose only lasting effect is cmdParam0 = group byte, and",
|
|
"nothing downstream reads cmdParam0 - the whole block is dead code.",
|
|
"In: the queued command; cmdParam1 = unit, cmdParam2 = group byte (id bits 2-4, side bit 5)",
|
|
"Out: unitFlagsTable $F708[unit] and unitDisplayFlagsTable $FB54[unit] via $4AD4; read index += 3",
|
|
"Called from: commandHandlerTable slot for $88 ($4D3A)"
|
|
]
|
|
},
|
|
"5188": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "A = the unit index",
|
|
"block": [
|
|
"Eight instructions of register shuffling whose only lasting effect is cmdParam0 = the group byte, and",
|
|
"nothing reads cmdParam0 afterwards. Dead code left over from an earlier calling convention."
|
|
]
|
|
},
|
|
"518A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "cmdParam0 = unit - overwritten again at $5192"
|
|
},
|
|
"518C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "read the same byte straight back"
|
|
},
|
|
"518E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store the unit index back into cmdParam1 - a no-op"
|
|
},
|
|
"5190": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "A = the group byte"
|
|
},
|
|
"5192": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "cmdParam0 = group byte; nothing downstream ever reads cmdParam0, so even this is pointless"
|
|
},
|
|
"5194": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "read it back again"
|
|
},
|
|
"5196": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store the group byte back into cmdParam2 - another no-op"
|
|
},
|
|
"5198": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$4AD4: make unit cmdParam1 follow group cmdParam2 and set unitFlagsTable = (old & 3) | group | $40"
|
|
},
|
|
"519B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "cmdParam0 = the unit index; read index += 2",
|
|
"routine": [
|
|
"cmdLeaveGroup - Handler of command $89 (2 bytes: unit): clears bit 6 ('in a group') of the unit's",
|
|
"unitFlagsTable entry and tail-jumps to syncLocalGroupFlags ($4C6B), which mirrors bits 2-6 into",
|
|
"unitDisplayFlagsTable so the overview map stops drawing the unit's group marker. Sent by",
|
|
"removeSelectedUnitFromGroup ($4AF2), the GROUP menu item REMOVED.",
|
|
"In: the queued command; cmdParam0 = unit index",
|
|
"Out: unitFlagsTable $F708[unit] &= $BF, unitDisplayFlagsTable $FB54[unit] refreshed; read index += 2",
|
|
"Called from: commandHandlerTable slot for $89 ($4D3C)"
|
|
]
|
|
},
|
|
"519E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X = the unit"
|
|
},
|
|
"51A0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F708 flags: facing bits 0-1, group id bits 2-4, side bit 5, 'in a group' bit 6"
|
|
},
|
|
"51A3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear bit 6 - the unit no longer belongs to a group"
|
|
},
|
|
"51A5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "write the flags back"
|
|
},
|
|
"51A8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$4C6B: copy bits 2-6 into unitDisplayFlagsTable so the map stops drawing the group marker"
|
|
},
|
|
"51AB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "read three arguments: cmdParam0 = unit, cmdParam1 = column, cmdParam2 = row; read index += 4",
|
|
"routine": [
|
|
"cmdPlaceUnit - Handler of command $8A (4 bytes: unit, column, row): teleports a unit during the deployment",
|
|
"phase. The unit's cloak bits (unitPathColTable & $C0) and blitz bits (unitPathRowTable & $C0) are first",
|
|
"saved into the ORA operands at $51C8 and $51E4, then the new column is written to unitColTable, to",
|
|
"unitPathColTable (keeping the cloak state) and to unitDestColTable with the 'arrived' bit 7, bit 7 of",
|
|
"unitDisplayFlagsTable is set, and the new row goes to unitRowTable, unitDestRowTable and unitPathRowTable",
|
|
"(keeping the blitz state). The $F000 map itself is not touched here.",
|
|
"In: the queued command; cmdParam0 = unit, cmdParam1/cmdParam2 = column/row (mirrored when remote)",
|
|
"Out: $F640, $F6A4, $F7D0, $F834, $F898, $F8FC and $FB54 of the unit; self-modifies $51C9 and $51E5",
|
|
"Called from: commandHandlerTable slot for $8A ($4D3E)"
|
|
]
|
|
},
|
|
"51AE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "a remote player sends his own coordinates: convert them with 39-v so both machines agree"
|
|
},
|
|
"51B1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y = the unit index into every one of the $64-spaced unit arrays"
|
|
},
|
|
"51B3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F898 waypoint column: bits 0-5 column, bits 6-7 = cloak ordered / cloak active",
|
|
"block": [
|
|
"Save the two flag pairs that live in the top bits of the waypoint bytes, so the rewrite below can put them",
|
|
"back: cloak in unitPathColTable bits 6-7, blitz in unitPathRowTable bits 6-7."
|
|
]
|
|
},
|
|
"51B6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "keep only the two cloak bits"
|
|
},
|
|
"51B8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patch them into the ORA immediate at $51C8 so the rewrite below preserves them"
|
|
},
|
|
"51BB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F8FC waypoint row: bits 0-5 row, bits 6-7 = blitz ordered / blitz active"
|
|
},
|
|
"51BE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "keep only the two blitz bits"
|
|
},
|
|
"51C0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patch them into the ORA immediate at $51E4"
|
|
},
|
|
"51C3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "A = the new map column",
|
|
"block": [
|
|
"Column: current position, waypoint (cloak preserved) and destination (marked as already reached)."
|
|
]
|
|
},
|
|
"51C5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F640 = the unit's current column"
|
|
},
|
|
"51C8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "immediate operand patched at $51B8 with the saved cloak bits"
|
|
},
|
|
"51CA": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "waypoint column = the new column with the cloak state untouched"
|
|
},
|
|
"51CD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "strip the cloak bits off again"
|
|
},
|
|
"51CF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 7 of unitDestColTable means 'already standing on its destination'"
|
|
},
|
|
"51D1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F7D0 destination column = the new column, marked as reached"
|
|
},
|
|
"51D4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$FB54 draw flags of the unit"
|
|
},
|
|
"51D7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 7 = idle / at destination, the copy the drawing code looks at"
|
|
},
|
|
"51D9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "write the draw flags back"
|
|
},
|
|
"51DC": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "A = the new map row",
|
|
"block": [
|
|
"Row: current position, destination and waypoint (blitz preserved)."
|
|
]
|
|
},
|
|
"51DE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F6A4 = the unit's current row"
|
|
},
|
|
"51E1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F834 destination row = the same row (rows carry no flag bit)"
|
|
},
|
|
"51E4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "immediate operand patched at $51C0 with the saved blitz bits"
|
|
},
|
|
"51E6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "waypoint row = the new row with the blitz state untouched"
|
|
},
|
|
"51E9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "note that the $F000 map cell is never updated here - the setup screen redraws the board itself"
|
|
},
|
|
"51EA": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "command $A6: the sender chose the flipped map variant",
|
|
"routine": [
|
|
"cmdSetCustomMapSeed - Handler of command $A6 (4 bytes: three seed bytes): sets mapFlipFlag ($0B9D) = 1 and",
|
|
"falls into cmdSetMapSeed. Overlay A sends $A6 instead of $8B at $79BD when the player picked the flipped",
|
|
"(180-degree rotated) view of the map, so both machines build the battlefield the same way round.",
|
|
"In: the queued command",
|
|
"Out: mapFlipFlag = 1, then everything cmdSetMapSeed does",
|
|
"Called from: the last entry of commandHandlerTable ($4D76, command $A6)"
|
|
]
|
|
},
|
|
"51EC": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "always taken - join the shared body"
|
|
},
|
|
"51EE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "command $8B: the map in its generated orientation",
|
|
"routine": [
|
|
"cmdSetMapSeed - Handler of command $8B (4 bytes: three seed bytes): mapFlipFlag = 0, the three arguments are",
|
|
"copied into the 24-bit map seed $0B95-$0B97, and bit 7 of gamePhase is cleared. The player who owns the map",
|
|
"sends this at the start of a session; the other machine's waitForMapSeedCommand ($7C1C) spins on gamePhase",
|
|
"bit 7 until this handler runs, after which both generate the identical 40x40 battlefield.",
|
|
"In: the queued command; cmdParam0/1/2 = the seed bytes after readCmdArgs3",
|
|
"Out: mapFlipFlag $0B9D, mapSeed $0B95-$0B97, gamePhase zp_B1 &= $7F; read index += 4",
|
|
"Called from: commandHandlerTable slot for $8B ($4D40), and by fall-through from cmdSetCustomMapSeed"
|
|
]
|
|
},
|
|
"51F0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0B9D: 0 = map as generated, 1 = rotated 180 degrees (the F1 TO FLIP option on the map screen)"
|
|
},
|
|
"51F3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "read the three seed bytes into cmdParam0/1/2; read index += 4"
|
|
},
|
|
"51F6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "seed byte 0"
|
|
},
|
|
"51F8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0B95: byte 0 of the 24-bit battlefield seed, which is the 5-letter map name packed 5 bits per letter"
|
|
},
|
|
"51FB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "seed byte 1"
|
|
},
|
|
"51FD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0B96"
|
|
},
|
|
"5200": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "seed byte 2"
|
|
},
|
|
"5202": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0B97"
|
|
},
|
|
"5205": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "zp_B1 game phase"
|
|
},
|
|
"5207": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear bit 7 = 'still waiting for the map seed'"
|
|
},
|
|
"5209": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "this releases waitForMapSeedCommand ($7C1C) on the receiving machine"
|
|
},
|
|
"520B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "both machines now hold the same seed and will generate the identical battlefield"
|
|
},
|
|
"520C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "a 1-byte command: just step the read index over it",
|
|
"routine": [
|
|
"cmdComcenRepairedOrSetupReady - Handler of the 1-byte command $9E, which means two different things. While",
|
|
"the battle runs (gamePhase = 0) it is the result of a successful COMCEN repair from the REPAIR console tab",
|
|
"($1812): the stun counter in the low nibble of the sending side's COMCEN unitStunTable entry is cleared.",
|
|
"In every other phase it is the READY / phase-sync acknowledgement of sendPhaseSyncAndWait ($7BF9): the",
|
|
"sender's bit of gamePhase is cleared with getPauseClearMask, input is locked out for 32 frames, a fake",
|
|
"SPACE key event is injected so any 'press space' loop falls through, and the chat state is reset.",
|
|
"In: gamePhase zp_B1, cmdFromOpponent zp_76, playerSide $0B9F, perSideValueTable $0C8A",
|
|
"Out: battle: unitStunTable $F960[comcen] &= $F0. Setup: zp_B1 masked, $0B7D = $20, $90EA = $20, $929C = 0.",
|
|
" mergedCmdReadIndex += 1 in both cases",
|
|
"Called from: commandHandlerTable slot for $9E ($4D66)"
|
|
]
|
|
},
|
|
"520F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "zp_B1 is zero only while the battle itself is running"
|
|
},
|
|
"5211": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "battle: this is a successful COMCEN repair"
|
|
},
|
|
"5213": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "setup: A = the AND mask that clears the sending side's 'not ready' bit"
|
|
},
|
|
"5216": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "apply it to the phase byte"
|
|
},
|
|
"5218": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "once both bits are gone sendPhaseSyncAndWait ($7BF9) stops waiting"
|
|
},
|
|
"521A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$20 = 32"
|
|
},
|
|
"521C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0B7D: ignore keyboard and joystick for the next 32 frames"
|
|
},
|
|
"521F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "inject key code $20 (SPACE) so any 'press space' wait loop falls through at once"
|
|
},
|
|
"5222": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "0"
|
|
},
|
|
"5224": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$929C: abandon any chat line that was being typed"
|
|
},
|
|
"5227": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "phase sync done"
|
|
},
|
|
"5228": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0B9F = the side this machine plays, 0 or 1",
|
|
"block": [
|
|
"Battle phase: command $9E means the sending side's COMCEN has finished repairing itself, so clear its",
|
|
"stun counter."
|
|
]
|
|
},
|
|
"522B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "who sent the repair?"
|
|
},
|
|
"522D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "our own command: our own COMCEN was repaired"
|
|
},
|
|
"522F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "remote command: the other side's COMCEN"
|
|
},
|
|
"5231": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X = the sender's absolute side"
|
|
},
|
|
"5232": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0C8A = {$31,$63}: unit 49 is side 0's COMCEN, unit 99 is side 1's"
|
|
},
|
|
"5235": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F960: low nibble = stun/knock-out counter, bit 4 spare, bits 5-7 = dig state"
|
|
},
|
|
"5238": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear the stun counter - the COMCEN is back on line"
|
|
},
|
|
"523A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "write it back, leaving the dig bits alone"
|
|
},
|
|
"523D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"523E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "this handler runs inside the packet merge loop, so stash its X and Y into the operands at $532B/$532D",
|
|
"routine": [
|
|
"cmdSessionControl - Handler of command $8C (2 bytes: reason). It is never dispatched out of the merged",
|
|
"buffer: both packet mergers call it directly ($4F36 and $4F9C) with A = the reason byte while the packets",
|
|
"are being merged, so the effect is immediate and the bytes are not copied into the film. Reason 0 = the game",
|
|
"is being abandoned: gameOverFlags = $C0, the message queue is cleared, 'GAME ABORTED.' is shown for a remote",
|
|
"abort, the end-of-game countdown is armed, and the dispatcher is abandoned by pulling two return addresses",
|
|
"off the stack. Reasons 1 and 2 return at once ($8C,$02 is the menu READY packet handled elsewhere). Reason 3",
|
|
"= link timeout, reason 5 = deliberate hang-up, anything else (4) = resume. Everything except reason 0 is",
|
|
"skipped during film playback.",
|
|
"In: A = reason byte, X/Y = the merge loop's registers, cmdFromOpponent zp_76, $0B9B, $0BA8",
|
|
"Out: pauseState zp_BE, $92A1, $0B7D, $929C, $92C9, $923F, zp_72, the message queue; returns through $532A",
|
|
" with X/Y restored, or never returns at all for reason 0",
|
|
"Called from: mergeIncomingPacket $4F36 and mergeOutgoingPacket $4F9C"
|
|
]
|
|
},
|
|
"5241": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "A holds the reason byte the merger fetched out of the packet"
|
|
},
|
|
"5243": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "reasons 3 and up are the pause / hang-up / resume group"
|
|
},
|
|
"5245": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "branch to the pause group"
|
|
},
|
|
"5247": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "reason 0 = the game is being abandoned"
|
|
},
|
|
"5249": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "handle the abort"
|
|
},
|
|
"524B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "reason 1 is unused; reason 2 is the menu-level READY packet handled by readyForNewGameHandshake"
|
|
},
|
|
"524C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$C0 = game finished, no result computed",
|
|
"block": [
|
|
"Reason 0 - the game is being abandoned, by us or by the opponent."
|
|
]
|
|
},
|
|
"524E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$923F game-over flags"
|
|
},
|
|
"5251": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "98 ticks of end-of-game countdown when no battle was running"
|
|
},
|
|
"5253": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0BA8 is non-zero whenever no battle is in progress"
|
|
},
|
|
"5256": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "no battle: keep the $62 countdown and say nothing"
|
|
},
|
|
"5258": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "a battle was running: throw away everything queued for the status line"
|
|
},
|
|
"525B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "who aborted?"
|
|
},
|
|
"525D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "our own abort - the local menu code has already set the countdown"
|
|
},
|
|
"525F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "message $03"
|
|
},
|
|
"5261": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "'GAME ABORTED.' - the opponent quit on us"
|
|
},
|
|
"5264": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "113 ticks so the message can be read before the menu returns"
|
|
},
|
|
"5266": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92C9 counts down to the return to the main menu"
|
|
},
|
|
"5269": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "discard the return address of this handler ...",
|
|
"block": [
|
|
"Abandon the whole dispatcher. This handler was entered as JSR cmdSessionControl from inside",
|
|
"mergeIncomingPacket/mergeOutgoingPacket, which themselves were entered as JSR from serviceCommandExchange,",
|
|
"so four PLAs drop both return addresses and the JMP below returns straight to serviceCommandExchange's",
|
|
"own caller."
|
|
]
|
|
},
|
|
"526A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "(second byte)"
|
|
},
|
|
"526B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "... and that of mergeIncomingPacket / mergeOutgoingPacket ..."
|
|
},
|
|
"526C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "... so the RTS below lands in the caller of serviceCommandExchange instead"
|
|
},
|
|
"526D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "comm function 2 = acknowledge and consume the finished exchange"
|
|
},
|
|
"526F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$E000; its RTS unwinds two levels because of the four PLAs above"
|
|
},
|
|
"5272": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0B9B bit 7 = a game film is being replayed",
|
|
"block": [
|
|
"Reasons 3 and up - the pause, hang-up and resume group. All of them are ignored during film playback."
|
|
]
|
|
},
|
|
"5275": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "during playback the pause / resume traffic is ignored"
|
|
},
|
|
"5277": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "0"
|
|
},
|
|
"5279": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "cancel any chat line being typed"
|
|
},
|
|
"527C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$3C = 60 frames, about one second"
|
|
},
|
|
"527E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "hold the player's input off while the pause state changes"
|
|
},
|
|
"5281": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "reason 3 = link timeout"
|
|
},
|
|
"5283": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "not the timeout reason"
|
|
},
|
|
"5285": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "zp_BE = 3: both sides counted as paused"
|
|
},
|
|
"5287": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "message $19"
|
|
},
|
|
"5289": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "'TIMEOUT. RUN/STOP TO RESUME.' stays on the line until someone resumes"
|
|
},
|
|
"528C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "always taken - go and queue the message"
|
|
},
|
|
"528E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "reason 5 = the link was hung up on purpose"
|
|
},
|
|
"5290": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "not the hang-up reason"
|
|
},
|
|
"5292": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 7 of pauseState = link dropped (DISCONNECT / SET VOICE)"
|
|
},
|
|
"5294": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "always taken"
|
|
},
|
|
"5296": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "any other reason (4 = RESUME) clears only the sender's own bit"
|
|
},
|
|
"5298": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "A = $FD for our resume, $FE for his, $FC in a solo game"
|
|
},
|
|
"529B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear that bit of the pause state"
|
|
},
|
|
"529D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store the new pause state"
|
|
},
|
|
"529F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "someone is still paused - leave the message up"
|
|
},
|
|
"52A1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "A = 0: no persistent message any more"
|
|
},
|
|
"52A4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "zp_72 = 0 so the next message appears immediately"
|
|
},
|
|
"52A6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "message $1B 'RESUMED'"
|
|
},
|
|
"52A8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "put it on the status line"
|
|
},
|
|
"52AB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "leave through the shared tail that restores the merge loop's X and Y"
|
|
},
|
|
"52AE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "mask that clears both pause bits at once",
|
|
"routine": [
|
|
"getPauseClearMask - Returns the AND mask that clears the resuming side's bit of a two-bit ready/pause byte.",
|
|
"cmdSessionControl applies it to pauseState (zp_BE) and cmdComcenRepairedOrSetupReady applies it to gamePhase",
|
|
"(zp_B1). In a solo-trainer game there is no independent opponent, so both bits are cleared at once ($FC);",
|
|
"otherwise an own command clears bit 0 ($FD) and a remote command clears bit 1 ($FE), and in the remote case",
|
|
"the message 'OPPONENT READY.' is queued if his bit was still set.",
|
|
"In: X = the pause/phase byte before this command, isSoloTrainer $0BA5, cmdFromOpponent zp_76",
|
|
"Out: A = $FC, $FD or $FE; may queue message $04; Y clobbered",
|
|
"Called from: cmdSessionControl $5298 and cmdComcenRepairedOrSetupReady $5213"
|
|
]
|
|
},
|
|
"52B0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0BA5 bit 7 = PRACTICE WITH SOLO TRAINER"
|
|
},
|
|
"52B3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "solo: there is no independent opponent, so clear both bits together"
|
|
},
|
|
"52B5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "mask that clears bit 0 = this machine's bit"
|
|
},
|
|
"52B7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "who sent the command?"
|
|
},
|
|
"52B9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "our own command: bit 0 is the one to clear"
|
|
},
|
|
"52BB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "A = the pause/phase byte as it was before this command (passed in X)"
|
|
},
|
|
"52BC": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 1 = the opponent was still flagged as not ready"
|
|
},
|
|
"52BE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "he was already ready - nothing to announce"
|
|
},
|
|
"52C0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "message $04"
|
|
},
|
|
"52C2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "'OPPONENT READY.'"
|
|
},
|
|
"52C5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "mask that clears bit 1 = the opponent's bit"
|
|
},
|
|
"52C7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "A = the AND mask"
|
|
},
|
|
"52C8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "read straight out of the received packet at $E020; Y points at the heading byte",
|
|
"routine": [
|
|
"cmdDroneMove - Handler of command $8D (4 bytes: heading, column, row), the opponent's live drone telemetry.",
|
|
"Only mergeIncomingPacket calls it, with Y pointing at the heading byte inside the received packet $E020;",
|
|
"mergeOutgoingPacket deals with our own $8D by re-centring the tactical view instead, which is why the",
|
|
"commandHandlerTable slot for $8D is a dummy - the byte never reaches the merged buffer. The handler mirrors",
|
|
"the 2x2 drone origin into our coordinate frame and, while the COMCEN radar screen is showing and the drone",
|
|
"has not already finished, parks sprite 0 on the drone's cell with the shape for the reversed heading.",
|
|
"In: Y = index of the heading byte in $E020, cmdFromOpponent zp_76, droneArrivalFlags $92F9, $90FB",
|
|
"Out: cmdParam0/1/2, droneControlFlags $920D bit 0, $9022, $92F6/$92F7, $9010/$9018, $91CC, $9008 and",
|
|
" sprite 0's shape; X/Y restored from the operands patched by saveRegsForCmdReturn",
|
|
"Called from: mergeIncomingPacket $4F28"
|
|
]
|
|
},
|
|
"52CB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "heading 0-7 of the opponent's drone"
|
|
},
|
|
"52CD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "next packet byte"
|
|
},
|
|
"52CE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "fetch it"
|
|
},
|
|
"52D1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "drone map column in the sender's coordinate frame"
|
|
},
|
|
"52D3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "next packet byte"
|
|
},
|
|
"52D4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "fetch it"
|
|
},
|
|
"52D7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "drone map row in the sender's coordinate frame"
|
|
},
|
|
"52D9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "remember the merge loop's X and Y for the common exit at $532A"
|
|
},
|
|
"52DC": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "mirror into our frame and step back one cell, because the drone occupies a 2x2 block"
|
|
},
|
|
"52DF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92F9 tracks the life of the drone"
|
|
},
|
|
"52E2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 4 = it reached its target, bit 5 = its kill burst has already been played"
|
|
},
|
|
"52E4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the drone is finished - ignore stale telemetry"
|
|
},
|
|
"52E6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$920D drone state flags"
|
|
},
|
|
"52E9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 0 = an enemy drone is currently being tracked on our display"
|
|
},
|
|
"52EB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store the flags back"
|
|
},
|
|
"52EE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$90FB: 0 = battlefield, 1 = COMCEN radar screen, 2 = drone screen, 3 = menus"
|
|
},
|
|
"52F1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "is the radar screen showing?"
|
|
},
|
|
"52F3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the enemy drone blip only exists on the radar screen"
|
|
},
|
|
"52F5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9022 shadow of VIC_SPR_ENA",
|
|
"block": [
|
|
"Move sprite 0, the enemy drone blip, to the drone's cell on the 21x17 radar grid. The sprite is switched",
|
|
"off first so that a drone which has flown off the grid simply disappears."
|
|
]
|
|
},
|
|
"52F8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear bit 0 - hide sprite 0 until we know the drone is inside the grid"
|
|
},
|
|
"52FA": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store the sprite enable shadow back"
|
|
},
|
|
"52FD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X = drone column"
|
|
},
|
|
"52FF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92F6 = the tracked drone's map column"
|
|
},
|
|
"5302": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y = drone row"
|
|
},
|
|
"5304": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92F7 = its map row"
|
|
},
|
|
"5307": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$340B: converts map cell X,Y into the sprite X/Y of that cell's centre on the 21x17 radar grid; C=1 when off-grid"
|
|
},
|
|
"530A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "off the visible grid - leave sprite 0 switched off"
|
|
},
|
|
"530C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9018 = sprite 0 Y position shadow"
|
|
},
|
|
"530F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9010 = sprite 0 X position shadow"
|
|
},
|
|
"5312": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "0"
|
|
},
|
|
"5314": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$91CC = 0 so loadDirectionShapeSprite fills sprite 0's shape at $8A00"
|
|
},
|
|
"5317": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the heading as the sender sees it"
|
|
},
|
|
"5319": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry for the add"
|
|
},
|
|
"531A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "+4 of the 8 compass points = the opposite direction ..."
|
|
},
|
|
"531C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "past the eighth point?"
|
|
},
|
|
"531E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "no wrap needed"
|
|
},
|
|
"5320": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "... modulo 8; reversing the heading is exactly what the 180-degree map mirror demands"
|
|
},
|
|
"5322": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$3340: copy shape A out of the decompressed set at $0200 into sprite 0 and enable it"
|
|
},
|
|
"5325": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "VIC colour 1 = white"
|
|
},
|
|
"5327": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9008 = sprite 0 colour shadow"
|
|
},
|
|
"532A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "immediate operand patched by saveRegsForCmdReturn: restore the merge loop's X"
|
|
},
|
|
"532C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "immediate operand patched by saveRegsForCmdReturn: restore the merge loop's Y"
|
|
},
|
|
"532E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "back into the middle of the packet merge loop"
|
|
},
|
|
"532F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "write X into the LDX # operand of the shared exit at $532A",
|
|
"routine": [
|
|
"saveRegsForCmdReturn - Two-instruction helper for the handlers that are called from the middle of the packet",
|
|
"merge loop instead of from the table dispatcher: it copies X and Y into the LDX/LDY immediate operands at",
|
|
"$532B and $532D, so the shared exit at $532A hands the merger back exactly the loop registers it had.",
|
|
"In: X, Y",
|
|
"Out: self-modifies $532B and $532D",
|
|
"Called from: cmdSessionControl $523E and cmdDroneMove $52D9"
|
|
]
|
|
},
|
|
"5332": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "write Y into the LDY # operand at $532C"
|
|
},
|
|
"5335": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done - the exit will now hand the caller back its own registers"
|
|
},
|
|
"5336": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "cmdParam1 = target column, cmdParam2 = target row; read index += 3",
|
|
"routine": [
|
|
"cmdDroneDetonate - Handler of command $8E (3 bytes: column, row). For our own command it clears the",
|
|
"'strike pending' bit 5 of droneControlFlags. If droneArrivalFlags bit 7 is already set the drone died or",
|
|
"arrived before the order was exchanged, so the detonation is cancelled by overwriting the $8E byte in the",
|
|
"merged buffer with $0E in place - bit 7 clear makes executeTurnCommands skip it while $0E & $3F still gives",
|
|
"length 3, so the film keeps a correctly sized no-op. Otherwise the drone is marked detonated, the",
|
|
"coordinates are mirrored, sound $11 plays, applyDroneBlast damages the 2x2 blast area and the blast-ring",
|
|
"sprite is drawn; a remote detonation finally clears our copy of his drone state through the tail at $537E.",
|
|
"In: the queued command, cmdFromOpponent zp_76, droneArrivalFlags $92F9, filmPlaybackMode $0B9B",
|
|
"Out: $92F9, $920D, the command byte in mergedCmdBuffer, sound, blast damage and the marker sprite",
|
|
"Called from: commandHandlerTable slot for $8E ($4D46)"
|
|
]
|
|
},
|
|
"5339": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "whose drone is detonating?"
|
|
},
|
|
"533B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the opponent's - nothing local to clean up"
|
|
},
|
|
"533D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$920D drone state flags"
|
|
},
|
|
"5340": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear bit 5 = 'a strike of ours is pending' (strikeWithDrone set it at $8187)"
|
|
},
|
|
"5342": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store the flags back"
|
|
},
|
|
"5345": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92F9 bit 7 = the drone has already finished its flight"
|
|
},
|
|
"5348": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "still airborne, so the strike counts"
|
|
},
|
|
"534A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "readCmdArgs2 left the read index 3 past the command byte ...",
|
|
"block": [
|
|
"The drone had already finished when the detonate order came round, so cancel the command in place instead",
|
|
"of executing it."
|
|
]
|
|
},
|
|
"534D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0E has bit 7 clear so executeTurnCommands skips it, and $0E & $3F still yields length 3"
|
|
},
|
|
"534F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$908C+readIndex is mergedCmdBuffer[command byte]: neuter the $8E in place, so the film records a correctly sized no-op"
|
|
},
|
|
"5352": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "always taken (A = $0E)"
|
|
},
|
|
"5354": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$40 = the drone has detonated",
|
|
"block": [
|
|
"A real detonation: mark the drone as burst, damage the 2x2 blast area and draw the ring."
|
|
]
|
|
},
|
|
"5356": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92F9 drone life flags"
|
|
},
|
|
"5359": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "mirror the 2x2 blast origin into our frame for a remote strike"
|
|
},
|
|
"535C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0B9B bit 7 = film playback"
|
|
},
|
|
"535F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "during playback everything is audible"
|
|
},
|
|
"5361": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "whose strike is it?"
|
|
},
|
|
"5363": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "our own strike is silent here - the drone screen already made its noise"
|
|
},
|
|
"5365": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "sound $11 = the drone explosion"
|
|
},
|
|
"5367": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "hand it to the sound driver"
|
|
},
|
|
"536A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$19 = 25 points of blast damage"
|
|
},
|
|
"536C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "overlay $72A1: damage whatever stands in the four cells of the 2x2 blast"
|
|
},
|
|
"536F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "blast column"
|
|
},
|
|
"5371": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "blast row"
|
|
},
|
|
"5373": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "marker style 1 = the drone burst ring (offsets 8,9 and colour 4 from the table at $33C2)"
|
|
},
|
|
"5375": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$33C8: put the blast-ring sprite on that cell and start its 90-frame timer"
|
|
},
|
|
"5378": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "join the shared tail"
|
|
},
|
|
"537B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "1-byte command $8F: step the read index over it",
|
|
"routine": [
|
|
"cmdDroneRelease - Handler of the 1-byte command $8F, queued by releaseDroneControl ($8230) when the player",
|
|
"lets go of the drone. It only steps the read index and falls into the tail shared with cmdDroneDetonate,",
|
|
"which for a remote command clears bits 0-5 of droneControlFlags - our copy of the opponent's drone state -",
|
|
"while bits 6-7, which describe our own drone flight, are preserved.",
|
|
"In: cmdFromOpponent zp_76, droneControlFlags $920D",
|
|
"Out: mergedCmdReadIndex += 1; $920D &= $C0 for a remote command",
|
|
"Called from: commandHandlerTable slot for $8F ($4D48); the tail at $537E also from cmdDroneDetonate"
|
|
]
|
|
},
|
|
"537E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "shared tail of $8E and $8F: whose drone was it?"
|
|
},
|
|
"5380": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "our own drone state belongs to the drone screen, not here"
|
|
},
|
|
"5382": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$920D drone state flags"
|
|
},
|
|
"5385": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "keep bits 6-7 (our own flight) and clear bits 0-5, our copy of his drone state"
|
|
},
|
|
"5387": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store the flags back"
|
|
},
|
|
"538A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"538B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "1-byte command $92: step the read index over it",
|
|
"routine": [
|
|
"cmdDroneShotDown - Handler of the 1-byte command $92. The only place that ever queues it is",
|
|
"checkStrikeHitsDrone ($79CC), which runs right after a COMCEN missile is fired and asks whether the aim",
|
|
"point falls on one of the 2x2 cells the tracked drone occupies: $92 therefore means 'a missile has shot the",
|
|
"drone down', not 'the drone arrived'. It clears bits 6-7 of droneControlFlags (no drone flight in progress",
|
|
"any more) and, for our own command, sets bit 4 of droneArrivalFlags so showDroneKillBurst ($79DD) plays the",
|
|
"kill effect on the next frame. Both packet mergers additionally set droneArrivalFlags = $80 the moment a $92",
|
|
"is seen in either packet, and sendOutgoingPacket drops a queued $92 when the drone detonated first.",
|
|
"In: cmdFromOpponent zp_76, droneControlFlags $920D, droneArrivalFlags $92F9",
|
|
"Out: $920D &= $3F; $92F9 |= $10 for an own command; mergedCmdReadIndex += 1",
|
|
"Called from: commandHandlerTable slot for $92 ($4D4E)",
|
|
"(the survey called this cmdDroneArrived; renamed because $92 is the shot-down report, and the drone",
|
|
"reaching its target is reported with $8E/$8F instead)"
|
|
]
|
|
},
|
|
"538E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$920D drone state flags"
|
|
},
|
|
"5391": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear bits 6-7: no drone flight is in progress any more"
|
|
},
|
|
"5393": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store the flags back"
|
|
},
|
|
"5396": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "who fired the missile that killed the drone?"
|
|
},
|
|
"5398": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the opponent scored the kill - nothing else to record here"
|
|
},
|
|
"539A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92F9 drone life flags"
|
|
},
|
|
"539D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 4 = we shot a drone down; showDroneKillBurst ($79DD) picks this up next frame and plays the effect"
|
|
},
|
|
"539F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store the flags back"
|
|
},
|
|
"53A2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"53A3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "1-byte command $97: step the read index over it",
|
|
"routine": [
|
|
"cmdDroneLaunch - Handler of the 1-byte command $97: droneArrivalFlags = 0 for a fresh drone in the air. The",
|
|
"opponent's launch also raises the 'DRONE ALERT!' message with sound through overlay B's showDroneAlert.",
|
|
"Either way, if that side still has drones one is spent and markComcenRevealed exposes the launching COMCEN",
|
|
"for six rounds - the price of flying a drone.",
|
|
"In: cmdFromOpponent zp_76, dronesLeft $92AE",
|
|
"Out: $92F9 = 0, $92AE[side] decremented, COMCEN reveal timer and visibility bits via $403B",
|
|
"Called from: commandHandlerTable slot for $97 ($4D58)"
|
|
]
|
|
},
|
|
"53A6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "index 0 = this machine's allowances"
|
|
},
|
|
"53A8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92F9 = 0: a fresh drone is in the air"
|
|
},
|
|
"53AB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "who launched?"
|
|
},
|
|
"53AD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "our own launch - the drone screen has already told the player"
|
|
},
|
|
"53AF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "overlay $820F: sound 7 plus message $20 'DRONE ALERT!'"
|
|
},
|
|
"53B2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "index 1 = the opponent's allowances"
|
|
},
|
|
"53B4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92AE[side] = drones that side still has"
|
|
},
|
|
"53B7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "already out of drones - nothing to charge"
|
|
},
|
|
"53B9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "spend one drone"
|
|
},
|
|
"53BC": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$403B: launching exposes that side's COMCEN for 6 rounds (X selects the side)"
|
|
},
|
|
"53BF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"53C0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "read the two payload bytes into cmdParam1/cmdParam2; read index += 3",
|
|
"routine": [
|
|
"cmdMissileStrike - Handler of command $90 (3 bytes), which carries two different payloads. During a setup",
|
|
"phase (gamePhase non-zero) the two bytes are the sender's drone and missile allowances and are stored in",
|
|
"dronesLeft/missilesLeft for that side - this is what overlay A's editDronesAndMissiles sends. During the",
|
|
"battle they are the target cell of a COMCEN missile: if the firing side still has missiles and the game has",
|
|
"not ended, one missile is spent, markComcenRevealed exposes the firing COMCEN, the coordinates are mirrored",
|
|
"for a remote shot and the unit standing on the cell takes 14 points of damage, halved to 7 for a COMCEN.",
|
|
"The blast-ring sprite is drawn in either case and sound $0C plays unless it is our own live shot.",
|
|
"In: the queued command, gamePhase zp_B1, cmdFromOpponent zp_76, gameEndReason $0BA8, the $F000 map",
|
|
"Out: $92AE/$92B0[side], unit energy and score via $3B22, the blast-ring sprite, sound",
|
|
"Called from: commandHandlerTable slot for $90 ($4D4A)"
|
|
]
|
|
},
|
|
"53C3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "zp_B1 is zero only while the battle runs"
|
|
},
|
|
"53C5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "battle: the payload is a target cell"
|
|
},
|
|
"53C7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "setup phase: the payload is the sender's drone/missile allowance; index 0 = us",
|
|
"block": [
|
|
"Setup phase: the two bytes are the sender's drone and missile allowances, not a target cell."
|
|
]
|
|
},
|
|
"53C9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "who sent it?"
|
|
},
|
|
"53CB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "our own settings"
|
|
},
|
|
"53CD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "index 1 = the opponent"
|
|
},
|
|
"53CE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "first byte = number of drones"
|
|
},
|
|
"53D0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92AE[side]"
|
|
},
|
|
"53D3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "second byte = number of missiles"
|
|
},
|
|
"53D5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92B0[side]"
|
|
},
|
|
"53D8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "allowances stored"
|
|
},
|
|
"53D9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "battle: index 0 = our own missile stock",
|
|
"block": [
|
|
"Battle phase: the two bytes are the target cell of a COMCEN missile."
|
|
]
|
|
},
|
|
"53DB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "who fired?"
|
|
},
|
|
"53DD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "our own shot needs no mirroring"
|
|
},
|
|
"53DF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "turn his aim point into our coordinates (39-v)"
|
|
},
|
|
"53E2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "index 1 = the opponent's missile stock"
|
|
},
|
|
"53E4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92B0[side]"
|
|
},
|
|
"53E7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the firing side has no missiles left - ignore the shot"
|
|
},
|
|
"53E9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0BA8 is non-zero once the game has ended"
|
|
},
|
|
"53EC": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "no shots after the final whistle"
|
|
},
|
|
"53EE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "spend one missile"
|
|
},
|
|
"53F1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "firing gives the firing COMCEN away for 6 rounds"
|
|
},
|
|
"53F4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "target column"
|
|
},
|
|
"53F6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$28 = 40, the width of the battlefield"
|
|
},
|
|
"53F8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "off the map: draw the ring but hit nothing"
|
|
},
|
|
"53FA": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "target row"
|
|
},
|
|
"53FC": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$28 = 40, the height of the battlefield"
|
|
},
|
|
"53FE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "off the map"
|
|
},
|
|
"5400": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$25FA: A = the $F000 map byte of column X, row Y"
|
|
},
|
|
"5403": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 7 clear = plain terrain, nobody is standing there"
|
|
},
|
|
"5405": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bits 0-6 = the index of the unit occupying the cell"
|
|
},
|
|
"5407": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y = the victim"
|
|
},
|
|
"5408": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0E = 14 points of missile damage"
|
|
},
|
|
"540A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "unit 49 = side 0's COMCEN"
|
|
},
|
|
"540C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "halve it"
|
|
},
|
|
"540E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "unit 99 = side 1's COMCEN"
|
|
},
|
|
"5410": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "an ordinary unit takes the full 14"
|
|
},
|
|
"5412": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "a COMCEN only takes half, 7 points"
|
|
},
|
|
"5413": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$3B22: subtract the energy, score it, explode the unit or knock the COMCEN out"
|
|
},
|
|
"5416": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "blast column"
|
|
},
|
|
"5418": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "blast row"
|
|
},
|
|
"541A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "marker style 0 = the missile blast ring (offsets 10,8 and colour 2 from the table at $33C2)"
|
|
},
|
|
"541C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$33C8: draw the ring sprite on the target cell"
|
|
},
|
|
"541F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "whose shot?"
|
|
},
|
|
"5421": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the opponent's shot is always audible"
|
|
},
|
|
"5423": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0B9B bit 7 = film playback"
|
|
},
|
|
"5426": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "our own shot is silent in live play - the radar screen made its own noise"
|
|
},
|
|
"5428": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "sound $0C = missile impact"
|
|
},
|
|
"542A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "hand it to the sound driver"
|
|
},
|
|
"542D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"542E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "cmdParam0 = the unit index; bit 7 set means 'the whole group this unit belongs to'",
|
|
"routine": [
|
|
"cmdSelfDestruct - Handler of command $91 (2 bytes: unit; bit 7 of the argument means 'the whole group this",
|
|
"unit belongs to'). A plain unit index falls straight into destroyUnit. For a group the match value",
|
|
"(unitFlagsTable & $3C) | $40 is patched into the CMP operand at $544D and units 99..0 are scanned, calling",
|
|
"destroyUnit on every member; because the $3C mask keeps the side bit 5, a group can never span both armies.",
|
|
"In: the queued command; cmdParam0 = unit index, bit 7 = group mode; unitFlagsTable $F708",
|
|
"Out: unitTypeTable $F76C entries set to $FF; self-modifies $544E; cmdParam0 reused as the loop counter",
|
|
"Called from: commandHandlerTable slot for $91 ($4D4C)"
|
|
]
|
|
},
|
|
"5431": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "look at the argument"
|
|
},
|
|
"5433": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "a plain unit index: destroy just that one and return through destroyUnit"
|
|
},
|
|
"5435": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "strip the 'whole group' flag to get the unit index"
|
|
},
|
|
"5437": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y = the named unit"
|
|
},
|
|
"5438": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "its $F708 flags"
|
|
},
|
|
"543B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "group id in bits 2-4 plus the side bit 5, so a group can never span both armies"
|
|
},
|
|
"543D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 6 = 'in a group', which every member carries"
|
|
},
|
|
"543F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patch the CMP immediate of the scan loop with the group signature to look for"
|
|
},
|
|
"5442": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$63 = 99, the highest unit index",
|
|
"block": [
|
|
"Scan units 99..0 and destroy every living member whose group signature matches the one patched into the",
|
|
"CMP at $544D. cmdParam0 doubles as the loop counter because destroyUnit reads its victim from there."
|
|
]
|
|
},
|
|
"5444": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "reuse cmdParam0 as the loop counter, because destroyUnit reads its victim from there"
|
|
},
|
|
"5446": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y = the unit currently being tested"
|
|
},
|
|
"5448": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "its $F708 flags"
|
|
},
|
|
"544B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "group id, side and in-group bit"
|
|
},
|
|
"544D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "immediate operand patched at $543F with the group signature"
|
|
},
|
|
"544F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "not a member of the group"
|
|
},
|
|
"5451": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "blow this member up"
|
|
},
|
|
"5454": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "step down one unit"
|
|
},
|
|
"5456": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "keep going until unit 0 has been tested"
|
|
},
|
|
"5458": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the whole group is gone"
|
|
},
|
|
"5459": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y = the unit to destroy (also the loop counter of cmdSelfDestruct)",
|
|
"routine": [
|
|
"destroyUnit - Removes unit cmdParam0 from play. A COMCEN (unit 49 or 99) is never allowed to self-destruct",
|
|
"and returns unchanged. Everything else takes 52 points of damage through sub_3B52 - more than the 50-point",
|
|
"maximum energy, so the kill is certain and runs through the normal explosion, sound, score and redraw path -",
|
|
"and then has its slot freed outright by writing $FF into unitTypeTable.",
|
|
"In: cmdParam0 zp_73 = unit index",
|
|
"Out: unitTypeTable $F76C[unit] = $FF plus all the side effects of sub_3B52; Y = unit index",
|
|
"Called from: cmdSelfDestruct (branch at $5433 and JSR at $5451)"
|
|
]
|
|
},
|
|
"545B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "unit 49 = side 0's COMCEN"
|
|
},
|
|
"545D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "a COMCEN may never self-destruct"
|
|
},
|
|
"545F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "unit 99 = side 1's COMCEN"
|
|
},
|
|
"5461": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "likewise protected"
|
|
},
|
|
"5463": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$34 = 52 points, more than the 50-point maximum energy, so the kill is certain"
|
|
},
|
|
"5465": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the damage path of applyHitToUnit without its attacker/SPY preamble: explosion, sound, score, redraw"
|
|
},
|
|
"5468": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "reload the unit index (sub_3B52 clobbers Y)"
|
|
},
|
|
"546A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$FF = free slot, bit 7 set = dead"
|
|
},
|
|
"546C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F76C: release the record so nothing draws or scans it again"
|
|
},
|
|
"546F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"5470": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "cmdParam0 = unit, cmdParam1/cmdParam2 = goal column/row; read index += 4",
|
|
"routine": [
|
|
"cmdMoveKeepGroup - Handler of command $98 MOVE TO GOAL (4 bytes: unit, column, row), the order issued to",
|
|
"each member of a group in turn by $4C0B. It reads and mirrors the arguments and jumps to",
|
|
"setGroupMemberDestination ($4C59), which counts the order off pendingGroupOrderCount when the unit belongs",
|
|
"to the group being ordered and then sets the destination through $34D5 without disturbing the group bits -",
|
|
"unlike command $80, which drops the unit out of its group.",
|
|
"In: the queued command; cmdParam0 = unit, cmdParam1/cmdParam2 = goal column/row",
|
|
"Out: destination tables of the unit, pendingGroupOrderCount $929E; read index += 4",
|
|
"Called from: commandHandlerTable slot for $98 ($4D5A)"
|
|
]
|
|
},
|
|
"5473": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "mirror a remote player's goal into our coordinates"
|
|
},
|
|
"5476": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$4C59: count the order off pendingGroupOrderCount and set the destination without touching the group bits"
|
|
},
|
|
"5479": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "cmdParam1 = the unit, cmdParam2 = the energy to add; read index += 3",
|
|
"routine": [
|
|
"cmdAddEnergy - Handler of command $9A (3 bytes: unit, amount), sent by the COMCEN energy repair on the",
|
|
"REPAIR tab. Unless the game has already ended by a COMCEN knock-out ($0BA8 bit 7) the amount is added to",
|
|
"bits 0-5 of the unit's unitEnergyTable entry and saturated at 50; the two visibility bits 6-7 are saved into",
|
|
"the ORA operand at $5498 and put back afterwards.",
|
|
"In: the queued command; cmdParam1 = unit, cmdParam2 = energy to add; gameEndReason $0BA8",
|
|
"Out: unitEnergyTable $F9C4[unit]; self-modifies $5499; read index += 3",
|
|
"Called from: commandHandlerTable slot for $9A ($4D5E)"
|
|
]
|
|
},
|
|
"547C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y = the unit being repaired"
|
|
},
|
|
"547E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0BA8 bit 7 set = a COMCEN has been knocked out"
|
|
},
|
|
"5481": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "no repairs once the game has been decided"
|
|
},
|
|
"5483": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F9C4: bits 0-5 energy 0-50, bits 6-7 = spotted / visible flags"
|
|
},
|
|
"5486": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "keep the whole byte in X"
|
|
},
|
|
"5487": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "isolate the two visibility bits"
|
|
},
|
|
"5489": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patch them into the ORA immediate at $5498 so they survive the rewrite"
|
|
},
|
|
"548C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "get the byte back"
|
|
},
|
|
"548D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the current energy on its own"
|
|
},
|
|
"548F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry for the add"
|
|
},
|
|
"5490": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "add the repair amount"
|
|
},
|
|
"5492": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$32 = 50 = full energy"
|
|
},
|
|
"5494": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "still below the cap"
|
|
},
|
|
"5496": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "saturate at 50"
|
|
},
|
|
"5498": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "immediate operand patched at $5489 with the saved visibility bits"
|
|
},
|
|
"549A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store the repaired energy"
|
|
},
|
|
"549D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"549E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "cmdParam0 = the group byte (id in bits 2-4, side in bit 5); read index += 2",
|
|
"routine": [
|
|
"cmdHaltGroup - Handler of command $9B (2 bytes: group byte), the group HALT order. Units 99..0 are scanned",
|
|
"and for every living member (unitFlagsTable & $7C equal to the group byte | $40) the current position is",
|
|
"copied into the destination and waypoint, the two 'arrived' bits (unitDestColTable bit 7 and",
|
|
"unitDisplayFlagsTable bit 7) are set, the cloak bits of the waypoint column are preserved through the ORA",
|
|
"operand patched at $54CF, and the blitz bits of the waypoint row are dropped because a plain row value is",
|
|
"written over them.",
|
|
"In: the queued command; cmdParam0 = group byte; unitTypeTable $F76C, unitFlagsTable $F708",
|
|
"Out: $F7D0, $F834, $F898, $F8FC and $FB54 of every member; self-modifies $54D0; read index += 2",
|
|
"Called from: commandHandlerTable slot for $9B ($4D60)"
|
|
]
|
|
},
|
|
"54A1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the group byte"
|
|
},
|
|
"54A3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 6 = 'in a group', so the byte can be compared with unitFlagsTable & $7C directly"
|
|
},
|
|
"54A5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "keep it as the match value"
|
|
},
|
|
"54A7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "start at unit 99 and walk down to 0",
|
|
"block": [
|
|
"Walk units 99..0 and stop every living member of the group where it stands."
|
|
]
|
|
},
|
|
"54A9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F76C, bit 7 set = dead or free slot"
|
|
},
|
|
"54AC": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "skip dead units"
|
|
},
|
|
"54AE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the unit's $F708 flags"
|
|
},
|
|
"54B1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "group id, side and in-group bit"
|
|
},
|
|
"54B3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "does it belong to the group being halted?"
|
|
},
|
|
"54B5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "no - next unit"
|
|
},
|
|
"54B7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the member's current column"
|
|
},
|
|
"54BA": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patch it into the ORA immediate at $54CF"
|
|
},
|
|
"54BD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 7 = standing on its destination"
|
|
},
|
|
"54BF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F7D0 destination column = where the unit already is"
|
|
},
|
|
"54C2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$FB54 draw flags"
|
|
},
|
|
"54C5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 7 = idle / at destination"
|
|
},
|
|
"54C7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store the draw flags back"
|
|
},
|
|
"54CA": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F898 waypoint column"
|
|
},
|
|
"54CD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "keep only the cloak bits 6-7"
|
|
},
|
|
"54CF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "immediate operand patched at $54BA with the member's current column"
|
|
},
|
|
"54D1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "waypoint = current position, cloak state untouched"
|
|
},
|
|
"54D4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the member's current row"
|
|
},
|
|
"54D7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F834 destination row = where the unit already is"
|
|
},
|
|
"54DA": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F8FC waypoint row likewise; a row is below 64, so this also clears the blitz bits 6-7"
|
|
},
|
|
"54DD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "step down one unit"
|
|
},
|
|
"54DE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "continue until unit 0 has been tested"
|
|
},
|
|
"54E0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the whole group has stopped"
|
|
},
|
|
"54E1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "cmdParam0 = mode, cmdParam1/cmdParam2 = column/row; read index += 4",
|
|
"routine": [
|
|
"cmdSetRecycler - Handler of command $9C (4 bytes: mode, column, row), sent by overlay A's chooseRecycler",
|
|
"($8436) during the setup of the game types that have a recycler. recyclerMode[side] takes the mode, with",
|
|
"side = the sender's absolute side (playerSide, EOR 1 when the command is remote); for modes 0 and 1 the",
|
|
"coordinates are mirrored for a remote sender and stored in recyclerCol/recyclerRow[side]. Our own recycler",
|
|
"is additionally painted onto the overview map, the enemy one is not - it has to be spotted first.",
|
|
"In: the queued command; cmdParam0 = mode, cmdParam1/2 = column/row; playerSide $0B9F, cmdFromOpponent",
|
|
"Out: $92A6/$92A8/$92AA indexed by side, map redraw via $3F27; self-modifies $550C; read index += 4",
|
|
"Called from: commandHandlerTable slot for $9C ($4D62)"
|
|
]
|
|
},
|
|
"54E4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0B9F = the side this machine plays"
|
|
},
|
|
"54E7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "who sent the command?"
|
|
},
|
|
"54E9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "our own choice"
|
|
},
|
|
"54EB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "remote: the sender is the other side"
|
|
},
|
|
"54ED": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y = the sender's absolute side, the index of the per-side recycler tables"
|
|
},
|
|
"54EE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "also stash it in the LDY immediate at $550B, because Y is reused before the draw call"
|
|
},
|
|
"54F1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the chosen recycler mode"
|
|
},
|
|
"54F3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92A6[side]"
|
|
},
|
|
"54F6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "modes 2 and up carry no coordinates"
|
|
},
|
|
"54F8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "skip the mirror for those"
|
|
},
|
|
"54FA": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "mirror a remote placement into our coordinate frame"
|
|
},
|
|
"54FD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "recycler column"
|
|
},
|
|
"54FF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92A8[side]"
|
|
},
|
|
"5502": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "recycler row"
|
|
},
|
|
"5504": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92AA[side]"
|
|
},
|
|
"5507": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "whose recycler is it?"
|
|
},
|
|
"5509": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the enemy recycler stays hidden until it is spotted"
|
|
},
|
|
"550B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "immediate operand patched at $54EE with our own side index"
|
|
},
|
|
"550D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$3F27: write the recycler glyph $67 into the map cell (or under whichever unit stands there)"
|
|
},
|
|
"5510": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"5511": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "cmdParam0 = the sender's side-preference token (0 or $FF from the setup screen, or a random tie-break byte)",
|
|
"routine": [
|
|
"cmdChooseSide - Handler of command $9D (2 bytes: the sender's side-preference token), the side-selection",
|
|
"handshake. In a solo game playerSide is simply forced to 0. In a modem game only the opponent's copy of the",
|
|
"command matters: our own token was parked in $90F8 by sendChooseSide, and the player with the higher token",
|
|
"becomes side 1 (the carry of the CPY is rotated into A). gamePhase is then set to $DF, whose clear bit 5",
|
|
"releases the wait loop at $797C. If both tokens are identical nobody wins: a fresh random token with bit 7",
|
|
"set is drawn and the code falls into sendChooseSide to send command $9D again, leaving gamePhase untouched",
|
|
"so the loop keeps waiting. That only terminates because the two machines' game RNGs have drifted apart",
|
|
"before a game starts (they are forced into step only once the map seed is exchanged).",
|
|
"In: the queued command; cmdParam0 = his token, selectedUnit $90F8 = ours, isSoloTrainer $0BA5, zp_76",
|
|
"Out: playerSide $0B9F = 0 or 1 and gamePhase zp_B1 = $DF, or a retry through sendChooseSide",
|
|
"Called from: commandHandlerTable slot for $9D ($4D64)"
|
|
]
|
|
},
|
|
"5514": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0BA5 bit 7 = PRACTICE WITH SOLO TRAINER"
|
|
},
|
|
"5517": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "modem game: settle it against the opponent"
|
|
},
|
|
"5519": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "solo: the human always plays side 0"
|
|
},
|
|
"551B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "always taken"
|
|
},
|
|
"551D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "which copy of the command is this?"
|
|
},
|
|
"551F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "our own copy tells us nothing we did not already know"
|
|
},
|
|
"5521": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "build the resulting side number in A"
|
|
},
|
|
"5523": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$90F8 holds our own token, parked there by sendChooseSide"
|
|
},
|
|
"5526": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "compare it with his; carry set means our token is the higher one"
|
|
},
|
|
"5528": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "identical tokens - nobody wins, so re-pick"
|
|
},
|
|
"552A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "A = the carry: 1 when our token was higher, so we take side 1"
|
|
},
|
|
"552B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0B9F is 0 or 1 from now on"
|
|
},
|
|
"552E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$DF clears bit 5 of the phase byte ..."
|
|
},
|
|
"5530": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "... which is the bit the side-selection loop at $797C spins on"
|
|
},
|
|
"5532": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the side handshake is finished"
|
|
},
|
|
"5533": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$FD5D: draw a fresh token; the two RNG states have drifted apart before a game starts, so the values probably differ"
|
|
},
|
|
"5536": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 7 marks it as a tie-break retry token"
|
|
},
|
|
"5538": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "park it in playerSide, from where sendChooseSide picks it up below (fall-through)"
|
|
},
|
|
"553B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "our own preference token (0 or $FF from the setup screen, or a tie-break byte)",
|
|
"routine": [
|
|
"sendChooseSide - The sending half of the $9D exchange: copies playerSide into cmdParam0 and into",
|
|
"selectedUnit $90F8 (where cmdChooseSide later finds our own token) and queues the 2-byte command $9D. At",
|
|
"this point playerSide still holds a preference token - 0 or $FF chosen by the setup screen, or a random",
|
|
"byte with bit 7 set after a tie - not yet a side number.",
|
|
"In: playerSide $0B9F",
|
|
"Out: cmdParam0 zp_73, selectedUnit $90F8, two bytes appended to the outgoing command ring",
|
|
"Called from: overlay A's side-selection screen ($7976), and by fall-through from cmdChooseSide's tie path"
|
|
]
|
|
},
|
|
"553E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the argument byte of command $9D"
|
|
},
|
|
"5540": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$90F8 doubles as the 'our own pick' scratch that cmdChooseSide compares against"
|
|
},
|
|
"5543": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "command $9D CHOOSE SIDE"
|
|
},
|
|
"5545": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "append the 2-byte command to the outgoing ring"
|
|
},
|
|
"5548": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$20 = unitStunTable bits 5-7 set to 001, 'digging in'",
|
|
"routine": [
|
|
"cmdDigIn - Handler of command $9F DIG IN (2 bytes: unit): calls setUnitDigBits with $20, i.e.",
|
|
"unitStunTable bits 5-7 = 001. The per-unit step code then advances those bits by $20 for every round the",
|
|
"unit stays still until it counts as fortified.",
|
|
"In: the queued command; cmdParam0 = unit after setUnitDigBits",
|
|
"Out: unitStunTable $F960[unit] = (old & $1F) | $20",
|
|
"Called from: commandHandlerTable slot for $9F ($4D68)"
|
|
]
|
|
},
|
|
"554A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "always taken"
|
|
},
|
|
"554C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "0 = unitStunTable bits 5-7 cleared, neither digging nor dug in",
|
|
"routine": [
|
|
"cmdDigOut - Handler of command $A0 DIG OUT (2 bytes: unit): setUnitDigBits with 0 clears the dig-progress",
|
|
"bits 5-7 of unitStunTable, and bit 6 of unitTypeTable - the 'fortified' flag the combat code consults - is",
|
|
"cleared as well.",
|
|
"In: the queued command; cmdParam0 = unit",
|
|
"Out: unitStunTable $F960[unit] &= $1F, unitTypeTable $F76C[unit] &= $BF",
|
|
"Called from: commandHandlerTable slot for $A0 ($4D6A)"
|
|
]
|
|
},
|
|
"554E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear the dig bits and leave Y = the unit"
|
|
},
|
|
"5551": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F76C of that unit"
|
|
},
|
|
"5554": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear bit 6 = 'fortified', the flag the combat code consults"
|
|
},
|
|
"5556": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store the type byte back"
|
|
},
|
|
"5559": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"555A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patch the new dig bits into the ORA immediate at $5567",
|
|
"routine": [
|
|
"setUnitDigBits - Shared prologue of cmdDigIn and cmdDigOut: patches the new dig bits into the ORA operand",
|
|
"at $5567, reads the unit argument, leaves it in Y and falls into applyDigBitsToUnit.",
|
|
"In: A = the new bits 5-7 ($20 or $00); the queued command",
|
|
"Out: self-modifies $5568; cmdParam0 and Y = the unit; unitStunTable[unit] rewritten",
|
|
"Called from: cmdDigIn (branch at $554A) and cmdDigOut ($554E)"
|
|
]
|
|
},
|
|
"555D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "cmdParam0 = the unit index; read index += 2"
|
|
},
|
|
"5560": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y = the unit, and it stays there for cmdDigOut"
|
|
},
|
|
"5562": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F960: low nibble = stun counter, bit 4 spare, bits 5-7 = dig state",
|
|
"routine": [
|
|
"applyDigBitsToUnit - The two-line worker shared by the single-unit and the group dig handlers:",
|
|
"unitStunTable[Y] = (old & $1F) | patchedBits, so the low-nibble stun counter and bit 4 survive while the",
|
|
"dig-state bits 5-7 are replaced wholesale.",
|
|
"In: Y = unit index; the ORA operand at $5568 patched by setUnitDigBits or by the group entry at $5573",
|
|
"Out: unitStunTable $F960[Y]",
|
|
"Called from: the group loop at $558F, and by fall-through from setUnitDigBits"
|
|
]
|
|
},
|
|
"5565": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "keep the stun counter and bit 4"
|
|
},
|
|
"5567": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "immediate operand patched at $555A or $5573 with the new dig bits"
|
|
},
|
|
"5569": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store the new dig state"
|
|
},
|
|
"556C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"556D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$20 = dig bits 001 for every member",
|
|
"routine": [
|
|
"cmdGroupDigIn - Handler of command $A1 (2 bytes: group byte): patches the dig bits to $20 and runs the",
|
|
"shared group loop that follows.",
|
|
"In: the queued command; cmdParam0 = group byte",
|
|
"Out: unitStunTable $F960 of every living member = (old & $1F) | $20",
|
|
"Called from: commandHandlerTable slot for $A1 ($4D6C)"
|
|
]
|
|
},
|
|
"556F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "always taken"
|
|
},
|
|
"5571": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "0 = clear the dig bits of every member",
|
|
"routine": [
|
|
"cmdGroupDigOut - Handler of command $A2 (2 bytes: group byte) and the entry of the shared group dig loop:",
|
|
"patches the dig bits to 0, reads the group byte, ORs $40 into it so it can be compared with",
|
|
"unitFlagsTable & $7C, and walks units 99..0 calling applyDigBitsToUnit for every living member. Unlike",
|
|
"cmdDigOut it never clears bit 6 of unitTypeTable, so a group dug in as a group can only be un-fortified one",
|
|
"unit at a time.",
|
|
"In: the queued command; cmdParam0 = group byte; unitTypeTable $F76C, unitFlagsTable $F708",
|
|
"Out: unitStunTable $F960 of every member; self-modifies $5568; read index += 2",
|
|
"Called from: commandHandlerTable slot for $A2 ($4D6E), and by branch from cmdGroupDigIn"
|
|
]
|
|
},
|
|
"5573": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patch the ORA immediate shared with applyDigBitsToUnit"
|
|
},
|
|
"5576": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "cmdParam0 = the group byte; read index += 2"
|
|
},
|
|
"5579": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the group byte"
|
|
},
|
|
"557B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 6 = 'in a group', so it matches unitFlagsTable & $7C directly"
|
|
},
|
|
"557D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "keep it as the match value"
|
|
},
|
|
"557F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "walk units 99 down to 0"
|
|
},
|
|
"5581": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F76C, bit 7 set = dead or free slot"
|
|
},
|
|
"5584": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "skip dead units"
|
|
},
|
|
"5586": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the unit's $F708 flags"
|
|
},
|
|
"5589": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "group id, side and in-group bit"
|
|
},
|
|
"558B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "is it a member of this group?"
|
|
},
|
|
"558D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "no - next unit"
|
|
},
|
|
"558F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "rewrite this member's dig bits"
|
|
},
|
|
"5592": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "step down one unit"
|
|
},
|
|
"5593": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "continue until unit 0 has been tested"
|
|
},
|
|
"5595": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "note that, unlike cmdDigOut, this never clears bit 6 of unitTypeTable"
|
|
},
|
|
"5596": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "cmdParam1 = the group leader's unit index, cmdParam2 = rotation mode 0-2; read index += 3",
|
|
"routine": [
|
|
"cmdSetFormation - Handler of command $A3 (3 bytes: group leader unit, rotation mode 0-2): reads the two",
|
|
"arguments and jumps to rotateGroupFormation ($4C84), which transforms every member's offset from the",
|
|
"leader's destination with the rule pair at $4C7E/$4C81 and re-issues the destinations.",
|
|
"In: the queued command; cmdParam1 = leader unit index, cmdParam2 = rotation mode",
|
|
"Out: the destinations of all the leader's group members; read index += 3",
|
|
"Called from: commandHandlerTable slot for $A3 ($4D70)"
|
|
]
|
|
},
|
|
"5599": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$4C84: rotate every member's offset from the leader using the rules at $4C7E"
|
|
},
|
|
"559C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "cmdParam0 = the options byte; read index += 2",
|
|
"routine": [
|
|
"cmdSetGameType - Handler of command $A4 (2 bytes): stores the argument into gameTypeOptions ($0BA3), which",
|
|
"carries the game type in bits 0-2, the UNIT MENUS and DAMAGE switches in bits 3-4, CUSTOM rules in bit 6 and",
|
|
"the custom-map flag in bit 7. Sent by overlay A's runMapTypeMenu ($833E) so both machines agree on the",
|
|
"scenario before the map is generated.",
|
|
"In: the queued command; cmdParam0 = the options byte",
|
|
"Out: gameTypeOptions $0BA3; read index += 2",
|
|
"Called from: commandHandlerTable slot for $A4 ($4D72)"
|
|
]
|
|
},
|
|
"559F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the options byte"
|
|
},
|
|
"55A1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0BA3: bits 0-2 game type, bit 3 UNIT MENUS, bit 4 DAMAGE, bit 6 CUSTOM rules, bit 7 custom map"
|
|
},
|
|
"55A4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "both machines now agree on the scenario"
|
|
},
|
|
"55A5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "cmdParam1 = option kind, cmdParam2 = value; read index += 3",
|
|
"routine": [
|
|
"cmdSetupOption - Handler of command $A5 (3 bytes: kind, value), the generic carrier of overlay A's",
|
|
"custom-rules editors. Kind 0 (HANDICAP) adds value*10 to the 16-bit counter $92A2/$92A4 indexed by the",
|
|
"sender's absolute side; because that counter holds the points scored against a side, this is a head start",
|
|
"credited to the sender's opponent, and the index has to be restored from the operand at $55C1 because",
|
|
"multiply8x8 returns with X = 0. Kind 1 (TERRAIN PTS) stores the value in $92AC for the sender's opponent.",
|
|
"Kind 2 and above - only kind 3, COMCEN SPEED, is ever sent - stores it in $92B4 indexed 0 = us, 1 = him.",
|
|
"In: the queued command; cmdParam1 = kind, cmdParam2 = value; playerSide $0B9F, cmdFromOpponent zp_76",
|
|
"Out: $92A2/$92A4, $92AC or $92B4; self-modifies $55C2; read index += 3",
|
|
"Called from: commandHandlerTable slot for $A5 ($4D74)"
|
|
]
|
|
},
|
|
"55A8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0B9F = the side this machine plays"
|
|
},
|
|
"55AB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "who sent the option?"
|
|
},
|
|
"55AD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "our own setting"
|
|
},
|
|
"55AF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "remote: the other side"
|
|
},
|
|
"55B1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X = the sender's absolute side"
|
|
},
|
|
"55B2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "stash it in the LDX immediate at $55C1, because multiply8x8 returns with X = 0"
|
|
},
|
|
"55B5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the option kind"
|
|
},
|
|
"55B7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "kinds 1 and up"
|
|
},
|
|
"55B9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "kind 0 = HANDICAP: the value counts in units of ten points",
|
|
"block": [
|
|
"Kind 0 - HANDICAP: add value*10 to the 16-bit score already credited against the sender's side."
|
|
]
|
|
},
|
|
"55BB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "multiplier 10"
|
|
},
|
|
"55BD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$FCCD: A = low byte and Y = high byte of value*10"
|
|
},
|
|
"55C0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry for the 16-bit add"
|
|
},
|
|
"55C1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "immediate operand patched at $55B2: restore the sender's side index"
|
|
},
|
|
"55C3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92A2/$92A3 = the 16-bit points scored against that side, so this is a head start for his opponent"
|
|
},
|
|
"55C6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store the new low byte"
|
|
},
|
|
"55C9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "product high byte"
|
|
},
|
|
"55CA": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92A4/$92A5 = the high halves of the two side scores"
|
|
},
|
|
"55CD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store the new high byte"
|
|
},
|
|
"55D0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"55D1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "kind 2 and up?",
|
|
"block": [
|
|
"Kind 1 - TERRAIN PTS: the per-cell bonus for holding enemy ground, stored against the sender's opponent."
|
|
]
|
|
},
|
|
"55D3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "yes - COMCEN SPEED and friends"
|
|
},
|
|
"55D5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "kind 1 = TERRAIN PTS"
|
|
},
|
|
"55D6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the bonus is credited against the sender's opponent"
|
|
},
|
|
"55D8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X = that side"
|
|
},
|
|
"55D9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the value"
|
|
},
|
|
"55DB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92AC[side]: points per cell of enemy ground held, read at $47A9"
|
|
},
|
|
"55DE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"55DF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "kind 2 and up (only kind 3, COMCEN SPEED, is ever sent): index 0 = us",
|
|
"block": [
|
|
"Kind 2 and up - in practice only kind 3, COMCEN SPEED, indexed 0 = us / 1 = the opponent."
|
|
]
|
|
},
|
|
"55E1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "who sent it?"
|
|
},
|
|
"55E3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "our own setting"
|
|
},
|
|
"55E5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "index 1 = the opponent"
|
|
},
|
|
"55E6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the value"
|
|
},
|
|
"55E8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92B4/$92B5; the value 4 is what makes $34E1 refuse to move a COMCEN at all"
|
|
},
|
|
"55EB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"55EC": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$929F counts commands queued but not yet executed; this entry is used by the 1-byte commands",
|
|
"routine": [
|
|
"queueCmdBytePending - Entry used by the 1-byte commands ($8F, $92, $97, $9E): counts one command in",
|
|
"pendingOwnCmdCount and falls into queueCmdByte to append the single byte.",
|
|
"In: A = the command byte",
|
|
"Out: pendingOwnCmdCount $929F incremented, one byte appended to the outgoing ring",
|
|
"Called from: $1814 in this file, and $79CC/$809A/$823C in both $6F00 overlays"
|
|
]
|
|
},
|
|
"55EF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0B9B bit 7 = a film is being replayed",
|
|
"routine": [
|
|
"queueCmdByte - Appends A to the 40-byte outgoing command ring at $9065, wrapping the write index $908D at",
|
|
"40, and always leaves an $FF end marker one byte past the new tail. It does nothing at all while a game",
|
|
"film is being replayed, since the player issues no commands then.",
|
|
"In: A = byte, outgoingCmdWriteIndex $908D, filmPlaybackMode $0B9B",
|
|
"Out: outgoingCmdRing $9065[], $908D advanced; Y clobbered",
|
|
"Called from: queueCmd4/queueCmd3/queueCmd2 ($560A, $5612, $5617, $561C, $5622, $5627)"
|
|
]
|
|
},
|
|
"55F2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "during playback the player issues no commands, so drop the byte"
|
|
},
|
|
"55F4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$908D = the write cursor of the 40-byte ring at $9065"
|
|
},
|
|
"55F7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store the byte in the ring"
|
|
},
|
|
"55FA": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "advance the cursor"
|
|
},
|
|
"55FB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$28 = 40 bytes in the ring"
|
|
},
|
|
"55FD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "no wrap needed"
|
|
},
|
|
"55FF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "wrap back to the start"
|
|
},
|
|
"5601": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "save the new write cursor"
|
|
},
|
|
"5604": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$FF = end-of-queue marker"
|
|
},
|
|
"5606": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "always keep a terminator one byte past the last command byte"
|
|
},
|
|
"5609": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"560A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "4-byte command: queue the command code held in A ...",
|
|
"routine": [
|
|
"queueCmd4 - Queues a 4-byte command: the code in A followed by cmdParam0, cmdParam1 and cmdParam2 (used for",
|
|
"$80 MOVE, $81, $8A, $8B, $8D, $98, $9C, $A6). It queues the code and cmdParam0 itself and then falls into",
|
|
"queueCmd3, which counts the command once and queues the remaining two arguments.",
|
|
"In: A = command code, cmdParam0/1/2 zp_73-zp_75",
|
|
"Out: four bytes in the outgoing ring, pendingOwnCmdCount $929F incremented once",
|
|
"Called from: $183D, $349C, $4A4A, $4C0D, $5646 and overlay A ($79BF, $8438)"
|
|
]
|
|
},
|
|
"560D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "... then cmdParam0, and fall into queueCmd3 for the rest"
|
|
},
|
|
"560F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "count the command once (queueCmd4 arrives here having already queued its code)",
|
|
"routine": [
|
|
"queueCmd3 - Queues a 3-byte command: the code in A followed by cmdParam1 and cmdParam2 (the commands of",
|
|
"length 3 are $87, $88, $8E, $90, $9A, $A3 and $A5). It is also the tail of queueCmd4, which arrives here",
|
|
"with A = cmdParam0 and its command code already in the ring, which is why the count is incremented here.",
|
|
"In: A = command code (or cmdParam0 when entered from queueCmd4), cmdParam1/cmdParam2",
|
|
"Out: three bytes in the outgoing ring, pendingOwnCmdCount $929F incremented once",
|
|
"Called from: $1939, $3C48, $4ACD, $6630 and both $6F00 overlays ($7667, $81A4, $84E9, $850E, $8544, $85D8)"
|
|
]
|
|
},
|
|
"5612": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "queue the command code, or cmdParam0 when entered from queueCmd4"
|
|
},
|
|
"5615": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "second argument"
|
|
},
|
|
"5617": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "queue it"
|
|
},
|
|
"561A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "third argument"
|
|
},
|
|
"561C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "queue it and return to the caller"
|
|
},
|
|
"561F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "count the command in pendingOwnCmdCount",
|
|
"routine": [
|
|
"queueCmd2 - Queues a 2-byte command: the code in A followed by cmdParam0 (the commands of length 2 are the",
|
|
"unit, group and reason commands $82-$86, $89, $8C, $91, $93-$96, $9B, $9D, $9F-$A2 and $A4).",
|
|
"In: A = command code, cmdParam0 zp_73",
|
|
"Out: two bytes in the outgoing ring, pendingOwnCmdCount $929F incremented once",
|
|
"Called from: $1AA9, $1C22, $20B8, $4B01, $5545, $5FA3, $62DE, $64E1, $65CD, $8340 and $C7A7"
|
|
]
|
|
},
|
|
"5622": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "queue the command code held in A"
|
|
},
|
|
"5625": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "its single argument"
|
|
},
|
|
"5627": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "queue it and return to the caller"
|
|
},
|
|
"562A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "number of bytes already placed in the outgoing packet by sendOutgoingPacket"
|
|
},
|
|
"562B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$920D bit 6 = our own drone is under joystick control",
|
|
"routine": [
|
|
"sendOutgoingPacket - Builds the packet for the next lock-step exchange and hands it to the comm module.",
|
|
"If our drone is under joystick control, is not paused and has not finished, it is first stepped one cell and",
|
|
"an $8D heading/column/row report is queued. Whole commands are then copied out of the outgoing ring into the",
|
|
"comm module's transmit buffer at $E027 as long as the packet stays below 5 bytes; a $92 is dropped while",
|
|
"droneArrivalFlags bit 6 says the drone detonated instead of arriving, and an $8E found while no drone flight",
|
|
"is in progress flushes the entire ring and sends an empty packet. Finally $E01F is set to the packet length",
|
|
"and the comm module is asked to transmit.",
|
|
"In: outgoingCmdRing $9065 with $908D/$908E, droneControlFlags $920D, droneArrivalFlags $92F9, pauseState",
|
|
"Out: $E027.., $E01F, outgoingCmdReadIndex $908E, outPacketFill $562A; self-modifies $566B",
|
|
"Called from: executeTurnCommands $4F02, disconnectFromOpponent $1C25 and overlay A $7979"
|
|
]
|
|
},
|
|
"562E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "no drone of ours to steer"
|
|
},
|
|
"5630": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "zp_BE is non-zero while either side is paused"
|
|
},
|
|
"5632": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "do not step the drone while the game is paused"
|
|
},
|
|
"5634": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92F9 bit 7 = the drone has already finished its flight"
|
|
},
|
|
"5637": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "nothing left to report"
|
|
},
|
|
"5639": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "overlay $731E: turn droneHeading toward the joystick and move the drone one cell"
|
|
},
|
|
"563C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "overlay $81FE: cmdParam1/cmdParam2 = droneViewOrigin + (6,5) = the drone's own map cell"
|
|
},
|
|
"563F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$920B = the current 0-7 compass heading"
|
|
},
|
|
"5642": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "first argument of the report"
|
|
},
|
|
"5644": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "command $8D DRONE POSITION"
|
|
},
|
|
"5646": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "queue heading, column and row"
|
|
},
|
|
"5649": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$908E = the read cursor of the outgoing ring",
|
|
"block": [
|
|
"Fill the outgoing packet from the command ring. Only whole commands are copied and the packet holds at",
|
|
"most 4 command bytes, so a long burst of orders is spread over several exchanges."
|
|
]
|
|
},
|
|
"564C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "0"
|
|
},
|
|
"564E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the packet starts out empty"
|
|
},
|
|
"5651": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "has the read cursor caught the write cursor?"
|
|
},
|
|
"5654": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the ring is empty - send what we have"
|
|
},
|
|
"5656": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the next command byte in the ring"
|
|
},
|
|
"5659": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patch it into the LDA # at $566A so the special-case tests below can look at it"
|
|
},
|
|
"565C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$4D9F: total length of the command from commandLengthTable, also left in $92EE"
|
|
},
|
|
"565F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry for the add"
|
|
},
|
|
"5660": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "how long the packet would be with this command in it"
|
|
},
|
|
"5663": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "a packet carries at most 4 command bytes"
|
|
},
|
|
"5665": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "it would not fit - leave it in the ring until next exchange"
|
|
},
|
|
"5667": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X = the write offset inside the packet buffer"
|
|
},
|
|
"566A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "immediate operand patched at $5659 with the command byte"
|
|
},
|
|
"566C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92 = 'the drone reached its target'",
|
|
"block": [
|
|
"Two special cases are filtered out here rather than at queue time, because whether they are still valid",
|
|
"only becomes clear when the packet is built."
|
|
]
|
|
},
|
|
"566E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "not a $92"
|
|
},
|
|
"5670": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92F9 bit 6 = the drone detonated instead of being shot down"
|
|
},
|
|
"5673": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 6 clear: the shot-down report is still valid, so copy it"
|
|
},
|
|
"5675": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "drop the stale $92: back the packet cursor up so the INX at $5696 cancels out"
|
|
},
|
|
"5676": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "step over it in the ring without copying anything"
|
|
},
|
|
"5679": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$8E = 'detonate the drone'"
|
|
},
|
|
"567B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "not an $8E"
|
|
},
|
|
"567D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$920D bit 7 = a drone flight of ours really is in progress"
|
|
},
|
|
"5680": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "it is - copy the detonate command normally"
|
|
},
|
|
"5682": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "stale detonate: throw the whole ring away by moving the read cursor to the write cursor ..."
|
|
},
|
|
"5685": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "... and send an empty packet this exchange"
|
|
},
|
|
"5687": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "always taken"
|
|
},
|
|
"5689": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "copy one byte of the command",
|
|
"block": [
|
|
"Copy the remaining bytes of this command from the ring into the packet, wrapping the ring index at 40."
|
|
]
|
|
},
|
|
"568C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$E027 is the comm module's 7-byte transmit buffer"
|
|
},
|
|
"568F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "advance the ring cursor"
|
|
},
|
|
"5690": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$28 = 40 bytes in the ring"
|
|
},
|
|
"5692": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "no wrap needed"
|
|
},
|
|
"5694": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "wrap back to the start"
|
|
},
|
|
"5696": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "advance the packet cursor"
|
|
},
|
|
"5697": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92EE counts the bytes of this command down"
|
|
},
|
|
"569A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "copy the rest of the command"
|
|
},
|
|
"569C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "remember how full the packet is"
|
|
},
|
|
"569F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "is there room for at least one more byte?"
|
|
},
|
|
"56A1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "yes - look at the next command in the ring"
|
|
},
|
|
"56A3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X = the finished packet length"
|
|
},
|
|
"56A6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the ring is consumed up to here"
|
|
},
|
|
"56A9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$E01F = the number of bytes the comm module should transmit"
|
|
},
|
|
"56AC": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "comm function 1 = request a send"
|
|
},
|
|
"56AE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$E000; the modem driver queues the packet, the solo trainer throws it away"
|
|
},
|
|
"56B1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the comm module's carrier state byte",
|
|
"routine": [
|
|
"pollMenuSession - Reached while a link is up but no game is running (commSessionState $0B9C bit 7): if the",
|
|
"carrier is gone the session is torn down, otherwise the menu-level packet handler runs. Note that the",
|
|
"commandHandlerTable slot for command $99 also points here, but nothing in the game ever queues a $99, so",
|
|
"that entry is unreachable filler.",
|
|
"In: the comm module's carrier byte $E03C",
|
|
"Out: falls into handleMenuSessionPacket, or jumps to disconnectFromOpponent",
|
|
"Called from: processCommandExchange $4DCE and $4E3E"
|
|
]
|
|
},
|
|
"56B4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 6 = carrier present"
|
|
},
|
|
"56B6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "still connected: service the menu-level traffic"
|
|
},
|
|
"56B8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$1C17: carrier lost - tear the session down and hang up"
|
|
},
|
|
"56BB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "10 frames",
|
|
"routine": [
|
|
"handleMenuSessionPacket - Menu-level receive path: re-arms the 10-frame link poll delay and returns unless a",
|
|
"packet has arrived. A 2-byte [$8C,$05] means the opponent hung up, so we hang up too; [$8C,$02] means he is",
|
|
"ready for a new game and puts 'OPPONENT READY FOR NEW GAME.' on the status line, rate limited by the middle",
|
|
"byte of the frame counter so the message cannot repeat every exchange. Every other packet just falls into",
|
|
"completeExchange to be consumed.",
|
|
"In: $E01D, $E01E, $E020/$E021, frameCounterMid zp_46",
|
|
"Out: linkPollDelay $9163 = 10, message $1F, zp_46 reset; falls into completeExchange",
|
|
"Called from: pollMenuSession (branch at $56B6) and the text engine's pause handler $C737"
|
|
]
|
|
},
|
|
"56BD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9163: do not poll the link again for 10 frames"
|
|
},
|
|
"56C0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$E01D exchange flags"
|
|
},
|
|
"56C3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 7 = a packet from the opponent has arrived"
|
|
},
|
|
"56C5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "nothing received - come back next poll"
|
|
},
|
|
"56C6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$E01E = length of the received packet"
|
|
},
|
|
"56C9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "only 2-byte menu packets mean anything here"
|
|
},
|
|
"56CB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "wrong length - just finish the exchange"
|
|
},
|
|
"56CD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "first byte of the received packet"
|
|
},
|
|
"56D0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$8C = session control"
|
|
},
|
|
"56D2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "not a session-control packet"
|
|
},
|
|
"56D4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the reason byte"
|
|
},
|
|
"56D7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "reason 5 = the opponent hung up"
|
|
},
|
|
"56D9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "not a hang-up"
|
|
},
|
|
"56DB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$1B33: drop our end of the line too"
|
|
},
|
|
"56DE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "reason 2 = READY FOR A NEW GAME"
|
|
},
|
|
"56E0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "some other reason - ignore it"
|
|
},
|
|
"56E2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "zp_46, the middle byte of the free-running frame counter, is abused as a crude rate limit"
|
|
},
|
|
"56E4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "about 3*256 frames since the last announcement"
|
|
},
|
|
"56E6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "too soon - say nothing this time"
|
|
},
|
|
"56E8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "message $1F"
|
|
},
|
|
"56EA": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "'OPPONENT READY FOR NEW GAME.'"
|
|
},
|
|
"56ED": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "0"
|
|
},
|
|
"56EF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "restart the rate limit (and, as a side effect, the frame counter's middle byte)"
|
|
},
|
|
"56F1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$E01D exchange flags",
|
|
"routine": [
|
|
"completeExchange - Makes sure the packet exchange currently in flight finishes. Nothing pending returns at",
|
|
"once; an already completed exchange is consumed; if our own packet is out or a send is already requested it",
|
|
"only waits; otherwise an empty packet is sent to give the opponent something to answer. It then spins for up",
|
|
"to $4B ticks of linkWaitTimer, servicing the status line, until the exchange completes, and consumes it. A",
|
|
"timeout hangs the modem up.",
|
|
"In: $E01D exchange flags, linkSessionState $0B9C",
|
|
"Out: $E01F, linkWaitTimer zp_7F, the comm module's exchange state; or jumps to hangUpModem",
|
|
"Called from: $1B2A, readyForNewGameHandshake $572B, handleMenuSessionPacket (four branches) and $EE06"
|
|
]
|
|
},
|
|
"56F4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "nothing in flight - nothing to finish"
|
|
},
|
|
"56F6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "look at the flags"
|
|
},
|
|
"56F7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 6 = the exchange has completed"
|
|
},
|
|
"56F9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "just consume it"
|
|
},
|
|
"56FB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "look at the flags again"
|
|
},
|
|
"56FC": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 5 = our packet has already gone out"
|
|
},
|
|
"56FE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "only his answer is missing - wait for it"
|
|
},
|
|
"5700": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "look at the flags again"
|
|
},
|
|
"5701": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 0 = a send has already been requested"
|
|
},
|
|
"5703": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "wait for it"
|
|
},
|
|
"5705": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "0"
|
|
},
|
|
"5707": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$E01F = 0: nothing to say, so send a zero-length packet"
|
|
},
|
|
"570A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "A carries the session state down to the comm module"
|
|
},
|
|
"570D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "comm function 1 = request a send"
|
|
},
|
|
"570F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "hand it over"
|
|
},
|
|
"5712": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$4B = 75 ticks; zp_7F is decremented every 8th frame, so roughly ten seconds"
|
|
},
|
|
"5714": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "arm the timeout"
|
|
},
|
|
"5716": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$C4EF keeps the status line, chat and clock alive while we spin"
|
|
},
|
|
"5719": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$E01D exchange flags"
|
|
},
|
|
"571C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 6: the exchange completed"
|
|
},
|
|
"571E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the timeout counts down in the raster IRQ"
|
|
},
|
|
"5720": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "keep waiting"
|
|
},
|
|
"5722": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the opponent never answered - hang up the modem"
|
|
},
|
|
"5725": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "comm function 2 = acknowledge and clear the finished exchange"
|
|
},
|
|
"5727": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$E000, then return to our caller"
|
|
},
|
|
"572A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "nothing to do"
|
|
},
|
|
"572B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "make sure no half-finished exchange is left over from the previous game",
|
|
"routine": [
|
|
"readyForNewGameHandshake - Run before a new game over an existing link: finishes any pending exchange, puts",
|
|
"'WAITING FOR OPPONENT...' up as a persistent message and then repeatedly sends [$8C,$02] and waits for the",
|
|
"exchange to complete. When the opponent's packet is also [$8C,$02] the session state becomes 2 (game",
|
|
"session), the message is cleared and the status line is wiped; [$8C,$05] means he hung up; anything else is",
|
|
"consumed and the READY packet is sent again.",
|
|
"In: $E01D/$E01E/$E020/$E021",
|
|
"Out: linkSessionState $0B9C = 2, persistentMessageId $92A1 cleared; or jumps to hangUpModem",
|
|
"Called from: overlay A $795A"
|
|
]
|
|
},
|
|
"572E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "message $0B"
|
|
},
|
|
"5730": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "'WAITING FOR OPPONENT...' stays on the status line for the whole handshake"
|
|
},
|
|
"5733": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "show it now"
|
|
},
|
|
"5736": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "put $8C,$02 = READY FOR A NEW GAME in the transmit buffer"
|
|
},
|
|
"5739": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "comm function 1 = request a send"
|
|
},
|
|
"573B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "hand it over"
|
|
},
|
|
"573E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "service the status line while waiting"
|
|
},
|
|
"5741": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$E01D exchange flags"
|
|
},
|
|
"5744": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "spin until bit 6 says the exchange completed"
|
|
},
|
|
"5746": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "length of the packet that came back"
|
|
},
|
|
"5749": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "a menu packet is exactly 2 bytes"
|
|
},
|
|
"574B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "anything else: consume it and try again"
|
|
},
|
|
"574D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "first byte of his packet"
|
|
},
|
|
"5750": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$8C = session control"
|
|
},
|
|
"5752": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "not session control - try again"
|
|
},
|
|
"5754": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "his reason byte"
|
|
},
|
|
"5757": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "2 = he is ready for a new game as well"
|
|
},
|
|
"5759": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "not a READY - check for a hang-up"
|
|
},
|
|
"575B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "2 = a game session has been agreed"
|
|
},
|
|
"575D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0B9C session state"
|
|
},
|
|
"5760": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "0"
|
|
},
|
|
"5762": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "take the WAITING message off the line"
|
|
},
|
|
"5765": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "comm function 2 = consume the finished exchange"
|
|
},
|
|
"5767": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "hand it over"
|
|
},
|
|
"576A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$C39F wipes the status line and returns to overlay A's caller"
|
|
},
|
|
"576D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "reason 5 = he hung up instead"
|
|
},
|
|
"576F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "some other reason - consume it and resend"
|
|
},
|
|
"5771": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$1B33: drop our end of the line too"
|
|
},
|
|
"5774": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "comm function 2 = consume whatever it was"
|
|
},
|
|
"5776": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "hand it over"
|
|
},
|
|
"5779": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "and send our READY packet again"
|
|
},
|
|
"577C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "command $8C session control",
|
|
"routine": [
|
|
"buildReadyPacket - Fills the comm module's transmit buffer with the 2-byte packet $8C,$02 (session control,",
|
|
"reason 2 = READY FOR A NEW GAME) and sets the transmit length $E01F to 2.",
|
|
"In: none",
|
|
"Out: $E027 = $8C, $E028 = $02, $E01F = 2",
|
|
"Called from: readyForNewGameHandshake $5736"
|
|
]
|
|
},
|
|
"577E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "first byte of the comm module's transmit buffer"
|
|
},
|
|
"5781": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "reason 2 = READY FOR A NEW GAME"
|
|
},
|
|
"5783": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "second byte of the transmit buffer"
|
|
},
|
|
"5786": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$E01F = 2 bytes to transmit (the same value as the reason byte only by coincidence)"
|
|
},
|
|
"5789": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the packet is ready to be sent"
|
|
},
|
|
"578A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92EB = number of command bytes merged for this exchange",
|
|
"routine": [
|
|
"recordExchangeToFilm - Appends one lock-step exchange to the game film held in the RAM under the I/O area.",
|
|
"Nothing is written when the exchange carried no commands, when the battle is not running, or when the film",
|
|
"buffer is full. A record is [ (splitIndex << 4) | length ] [ time stamp, 1 or 2 bytes ] [ length command",
|
|
"bytes ]; the split index says how many of the bytes belong to the first player, so playback can restore the",
|
|
"own/remote flag exactly. Every byte goes through writeFilmByte, which banks the I/O area out around the",
|
|
"store, and filmPtr is advanced by the length of the record at the end.",
|
|
"In: mergedCmdLength $92EB, mergedCmdSplitIndex $92EC, mergedCmdBuffer $908F, filmPtr zp_BC/zp_BD,",
|
|
" filmEndPtr $92F1/$92F2, gamePhase zp_B1",
|
|
"Out: film bytes written, filmPtr advanced; X = length, Y = record size",
|
|
"Called from: executeTurnCommands $4EFA"
|
|
]
|
|
},
|
|
"578D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "nothing happened - do not waste a film record"
|
|
},
|
|
"578F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "zp_B1 is zero only during the battle"
|
|
},
|
|
"5791": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the setup screens and menus are not filmed"
|
|
},
|
|
"5793": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$591E: C = 1 once filmPtr has reached filmEndPtr"
|
|
},
|
|
"5796": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the film buffer in the RAM under the I/O area is full"
|
|
},
|
|
"5798": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X = index into mergedCmdBuffer"
|
|
},
|
|
"579A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y = offset within the film record being written"
|
|
},
|
|
"579C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92EC = how many of the merged bytes belong to the first player"
|
|
},
|
|
"579F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "shift it ..."
|
|
},
|
|
"57A0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "... into ..."
|
|
},
|
|
"57A1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "... the high ..."
|
|
},
|
|
"57A2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "... nibble of the header byte"
|
|
},
|
|
"57A3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "low nibble = the total length; both always fit in four bits"
|
|
},
|
|
"57A6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$5893 stores at (filmPtr),Y with $01 = $34 so the RAM under $D000 is visible"
|
|
},
|
|
"57A9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "next byte of the record"
|
|
},
|
|
"57AA": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$57BE: one or two bytes of clock delta plus the sub-tick index; it advances Y itself"
|
|
},
|
|
"57AD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "copy the merged command bytes verbatim - this is what playback re-executes",
|
|
"block": [
|
|
"Copy the exchange's command bytes verbatim; playback feeds exactly these bytes back through",
|
|
"executeTurnCommands, which is why a film replays identically whether the opponent was a person or the",
|
|
"solo trainer."
|
|
]
|
|
},
|
|
"57B0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "write it to the film"
|
|
},
|
|
"57B3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "next film byte"
|
|
},
|
|
"57B4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "next command byte"
|
|
},
|
|
"57B5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "all of them written?"
|
|
},
|
|
"57B8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "no - keep copying"
|
|
},
|
|
"57BA": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$57E7: filmPtr += Y, the length of the record just written"
|
|
},
|
|
"57BD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
}
|
|
},
|
|
"dataTypes": {
|
|
"562A": [
|
|
"byte",
|
|
1
|
|
]
|
|
},
|
|
"zpComments": {
|
|
"73": "first argument byte of the command being queued or executed: unit index, group byte, session-control reason, recycler mode or map-seed byte 0",
|
|
"74": "second argument byte of the command: usually the map column, but also the unit index of the 3-byte group commands ($87, $88, $9A, $A3) and map-seed byte 1",
|
|
"75": "third argument byte of the command: usually the map row, but also the target unit, group byte, option value or map-seed byte 2",
|
|
"76": "bit 7 set while the command being merged or executed came from the opponent: its coordinates are mirrored with 39-v, its side is playerSide EOR 1, and most sound/message side effects are suppressed for our own copy",
|
|
"7F": "countdown decremented every 8th frame; completeExchange and the link waits load it with $4B (about ten seconds) and hang the modem up if the exchange has not completed by then",
|
|
"B1": "game phase: 0 only while the battle runs. Bit 7 = still waiting for the map seed (cleared by command $8B/$A6), bit 5 = side selection still open (cleared to $DF by command $9D), bits 0-1 = the two sides' 'not ready' bits cleared one at a time by command $9E through getPauseClearMask",
|
|
"BE": "pause state: bit 0 = this machine paused, bit 1 = the opponent paused, the whole byte is 3 after a link timeout and $80 after a deliberate hang-up. Bits are cleared one side at a time by command $8C reason 4 through getPauseClearMask; while it is non-zero the drone is not stepped",
|
|
"BC": "pointer (lo) into the game film buffer in the RAM under the I/O area; recordExchangeToFilm writes each exchange at (filmPtr),Y and then adds the record length",
|
|
"BD": "high byte of filmPtr; compareFilmPtrToEnd stops recording when the pair reaches filmEndPtr $92F1/$92F2"
|
|
}
|
|
}
|