{
 "chunk": "game_mainProgram0800_5E03",
 "unit": "game/mainProgram0800",
 "unitLabels": {
  "game/mainProgram0800": {
   "5E99": "buildUnitOptionsMenu",
   "5FF3": "menuLoopFrame",
   "602A": "menuIdleSnapshot",
   "607E": "menuLoopExitLast",
   "60BA": "menuSlowRowTest",
   "60BE": "menuMoveDirection",
   "60D6": "menuLoopReturnSelection",
   "6142": "drawJoinGroupList",
   "620B": "waitForGroupClick",
   "623F": "buildGroupOptionsMenu",
   "62D7": "queueGroupCommand",
   "6336": "groupMenuDone",
   "63C8": "groupEditorLoop",
   "63E2": "groupEditorOwnSideBranch",
   "6408": "groupEditorScroll",
   "643B": "groupEditorActOnUnit"
  }
 },
 "notes": {
  "5E03": {
   "unit": "game/mainProgram0800",
   "line": "text window left edge = screen character column 1",
   "routine": [
    "clearOverviewWindow - Points the text window at the 20x20 overview panel (left column 1, top row 1,",
    "width 20, bottom row limit 21) and blanks it with the text engine's window clear.",
    "In:  -",
    "Out: zp_39-zp_3C = 1/21/1/20, the overview area cleared",
    "Called from: mainStart ($0A98), clearCurrentScreenWindows ($2DF1) and overlay A ($76FC, $8235)"
   ]
  },
  "5E05": {
   "unit": "game/mainProgram0800",
   "line": "textWindowLeft = 1"
  },
  "5E07": {
   "unit": "game/mainProgram0800",
   "line": "and textWindowTop = 1: the overview frame starts at character (1,1)"
  },
  "5E09": {
   "unit": "game/mainProgram0800",
   "line": "20 characters wide"
  },
  "5E0B": {
   "unit": "game/mainProgram0800",
   "line": "textWindowWidth = 20 (the 40x40 map is drawn 4x4 pixels per cell inside this frame)"
  },
  "5E0D": {
   "unit": "game/mainProgram0800",
   "line": "row limit 21 (exclusive), i.e. rows 1-20"
  },
  "5E0F": {
   "unit": "game/mainProgram0800",
   "line": "textWindowBottom = 21"
  },
  "5E11": {
   "unit": "game/mainProgram0800",
   "line": "tail-call the text engine's window clear ($C06A) and return to the caller"
  },
  "5E14": {
   "unit": "game/mainProgram0800",
   "line": "3 bytes indexed by uiLevel ($9209): 0 browsing = colour 9, 1 unit selected = colour 5, 2 group = colour 4"
  },
  "5E17": {
   "unit": "game/mainProgram0800",
   "line": "index (0-99) of the own, unstunned unit the player just clicked on",
   "routine": [
    "handleOwnUnitClick - Entry taken by the battlefield main loop when the player clicks on one of his",
    "own, unstunned units (index already in selectedUnit $90F8). A unit that is a member of a group is",
    "handed to runGroupOptionsMenu; a lone unit falls through into runUnitOptionsMenu.",
    "In:  selectedUnit $90F8, unitDisplayFlagsTable $FB54 bit 6",
    "Out: control passes to one of the two option-menu routines, both of which end in exitUnitMenu",
    "Called from: the battlefield fire-button handler ($20CC)"
   ]
  },
  "5E1A": {
   "unit": "game/mainProgram0800",
   "line": "its local flag copy $FB54: bit 7 idle, bit 6 in a group, bits 2-5 group key, bits 0-1 facing"
  },
  "5E1D": {
   "unit": "game/mainProgram0800",
   "line": "test bit 6 = 'this unit belongs to a group'"
  },
  "5E1F": {
   "unit": "game/mainProgram0800",
   "line": "lone unit: fall through into the single-unit branch"
  },
  "5E21": {
   "unit": "game/mainProgram0800",
   "line": "group member: the whole group is commanded instead"
  },
  "5E24": {
   "unit": "game/mainProgram0800",
   "line": "0 into the three text-engine mode bytes below",
   "routine": [
    "runUnitOptionsMenu - Single-unit branch of handleOwnUnitClick, also entered by JMP from the group",
    "menu item DIRECT UNIT ($62F6). It highlights the unit and shows its info panel (which waits there",
    "until the stick moves or the button is pressed again); a deflected stick then starts SETTING",
    "DESTINATION, while a second click builds and runs the UNIT OPTIONS menu - but only when the UNIT",
    "MENUS option (gameTypeOptions $0BA3 bit 3) is on. The chosen item queues its command byte with the",
    "unit index as the argument.",
    "In:  selectedUnit $90F8, unit arrays $F76C/$F898/$F8FC/$F960/$FB54, joyDirection zp_5D, gamePhase",
    "     zp_B1, gameTypeOptions $0BA3 bit 3, comcenUnit $9236",
    "Out: highlightedUnit/highlightedGroupKey/uiLevel/menuLoopMode and the menu state set, viewport and",
    "     info panel redrawn, menuIdleSnapshot+1 patched, one of the commands $82/$84/$86/$93/$95/$9F/$A0",
    "     queued (or $87 through the target cursor, $88 through the join-group menu); falls into",
    "     exitUnitMenu",
    "Called from: handleOwnUnitClick ($5E1F) and the group menu item DIRECT UNIT ($62F6)"
   ]
  },
  "5E26": {
   "unit": "game/mainProgram0800",
   "line": "rawGlyphMode off: printChar translates ASCII again"
  },
  "5E28": {
   "unit": "game/mainProgram0800",
   "line": "textCentreWidth 0 = print left-aligned at the cursor"
  },
  "5E2B": {
   "unit": "game/mainProgram0800",
   "line": "fill/pad with glyph 0 (space)"
  },
  "5E2D": {
   "unit": "game/mainProgram0800",
   "line": "$FF = no group highlighted"
  },
  "5E2F": {
   "unit": "game/mainProgram0800",
   "line": "clear the viewport group highlight"
  },
  "5E32": {
   "unit": "game/mainProgram0800",
   "line": "the clicked unit..."
  },
  "5E35": {
   "unit": "game/mainProgram0800",
   "line": "...is the one the viewport highlights"
  },
  "5E38": {
   "unit": "game/mainProgram0800",
   "line": "repaint the 7x5-cell tactical view with the new highlight"
  },
  "5E3B": {
   "unit": "game/mainProgram0800",
   "line": "UI level 1"
  },
  "5E3D": {
   "unit": "game/mainProgram0800",
   "line": "uiLevel 1 = a single unit is selected (info-panel colour 5)"
  },
  "5E40": {
   "unit": "game/mainProgram0800",
   "line": "sprite 0 becomes the hollow-square cell cursor"
  },
  "5E43": {
   "unit": "game/mainProgram0800",
   "line": "colour 5 = the unit-level text colour (uiLevelTextColourTable[1])"
  },
  "5E45": {
   "unit": "game/mainProgram0800",
   "line": "ink colour for the info panel"
  },
  "5E47": {
   "unit": "game/mainProgram0800",
   "line": "and the same colour for the blanks that pad centred lines"
  },
  "5E49": {
   "unit": "game/mainProgram0800",
   "line": "clear the info-panel window (columns 25-38, rows 12-21)"
  },
  "5E4C": {
   "unit": "game/mainProgram0800",
   "line": "draw the unit's status there; that routine loops until the player deflects the stick, clicks again or the display is interrupted"
  },
  "5E4F": {
   "unit": "game/mainProgram0800",
   "line": "re-read the unit: the battle kept running under the panel",
   "block": [
    "Work out what ended the info panel: the unit died, the stick was deflected (start a move",
    "order) or the fire button was pressed (open the options menu)."
   ]
  },
  "5E52": {
   "unit": "game/mainProgram0800",
   "line": "unit type byte $F76C, bit 7 = destroyed"
  },
  "5E55": {
   "unit": "game/mainProgram0800",
   "line": "the unit was killed while its panel was up: just leave"
  },
  "5E57": {
   "unit": "game/mainProgram0800",
   "line": "joystick nibble latched by the IRQ, active low ($0F = centred)"
  },
  "5E59": {
   "unit": "game/mainProgram0800",
   "line": "still centred?"
  },
  "5E5B": {
   "unit": "game/mainProgram0800",
   "line": "centred: then it was the fire button that ended the panel"
  },
  "5E5D": {
   "unit": "game/mainProgram0800",
   "line": "clear the input lockout..."
  },
  "5E5F": {
   "unit": "game/mainProgram0800",
   "line": "...so the destination cursor reacts to the stick immediately"
  },
  "5E62": {
   "unit": "game/mainProgram0800",
   "line": "stick deflected: run SETTING / DESTINATION for this unit (ends in command $80)"
  },
  "5E65": {
   "unit": "game/mainProgram0800",
   "line": "back to the battlefield loop with uiLevel 0"
  },
  "5E68": {
   "unit": "game/mainProgram0800",
   "line": "was there a fresh fire-button press? (Z = 1 when yes)"
  },
  "5E6B": {
   "unit": "game/mainProgram0800",
   "line": "no press - the panel simply timed out: leave"
  },
  "5E6D": {
   "unit": "game/mainProgram0800",
   "line": "game type and option bits $0BA3"
  },
  "5E70": {
   "unit": "game/mainProgram0800",
   "line": "bit 3 = the UNIT MENUS option (set by the FULL WAR/$1D and DEFENDER/$1E presets, or by hand in a custom game)"
  },
  "5E72": {
   "unit": "game/mainProgram0800",
   "line": "this scenario has no unit option menus: leave"
  },
  "5E74": {
   "unit": "game/mainProgram0800",
   "line": "$FF = no group highlight",
   "block": [
    "Second click with the UNIT MENUS option on: re-establish the highlight and the cursor",
    "sprite (showUnitInfoPanel used sprites 1-4 for the unit picture) and set up the menu",
    "state."
   ]
  },
  "5E76": {
   "unit": "game/mainProgram0800",
   "line": "clear the group highlight again"
  },
  "5E79": {
   "unit": "game/mainProgram0800",
   "line": "the clicked unit..."
  },
  "5E7C": {
   "unit": "game/mainProgram0800",
   "line": "...stays highlighted"
  },
  "5E7F": {
   "unit": "game/mainProgram0800",
   "line": "repaint the view: showUnitInfoPanel moved the picture sprites and the path marker"
  },
  "5E82": {
   "unit": "game/mainProgram0800",
   "line": "UI level 1"
  },
  "5E84": {
   "unit": "game/mainProgram0800",
   "line": "uiLevel = 1 (unit)"
  },
  "5E87": {
   "unit": "game/mainProgram0800",
   "line": "restore the square cursor sprite (the info panel may have used sprites 1-4)"
  },
  "5E8A": {
   "unit": "game/mainProgram0800",
   "line": "$FF"
  },
  "5E8C": {
   "unit": "game/mainProgram0800",
   "line": "menuLoopMode $FF: the menu loop animates this unit's path marker (no group preview)"
  },
  "5E8F": {
   "unit": "game/mainProgram0800",
   "line": "1"
  },
  "5E91": {
   "unit": "game/mainProgram0800",
   "line": "redundant - uiLevel was already set to 1 at $5E84"
  },
  "5E94": {
   "unit": "game/mainProgram0800",
   "line": "0"
  },
  "5E96": {
   "unit": "game/mainProgram0800",
   "line": "start the selection on the first menu row"
  },
  "5E99": {
   "unit": "game/mainProgram0800",
   "line": "unit-level colour 5",
   "block": [
    "Build the UNIT OPTIONS list. Re-entered from $5F22 when the menu loop reports that the",
    "unit's idle flag changed, because that swaps the DIG items for the BLITZ items. Every",
    "item is appended with addMenuItem, which also prints its name on the next row."
   ]
  },
  "5E9B": {
   "unit": "game/mainProgram0800",
   "line": "ink colour"
  },
  "5E9D": {
   "unit": "game/mainProgram0800",
   "line": "pad colour"
  },
  "5E9F": {
   "unit": "game/mainProgram0800",
   "line": "clear the info panel before printing the menu"
  },
  "5EA2": {
   "unit": "game/mainProgram0800",
   "line": "$CB0A = '    UNIT' + CR"
  },
  "5EA4": {
   "unit": "game/mainProgram0800",
   "line": "high byte of the heading string"
  },
  "5EA6": {
   "unit": "game/mainProgram0800",
   "line": "print the first heading line"
  },
  "5EA9": {
   "unit": "game/mainProgram0800",
   "line": "print the string that follows it, $CB13 '   OPTIONS' + CR + CR"
  },
  "5EAC": {
   "unit": "game/mainProgram0800",
   "line": "unit index for the flag look-ups below"
  },
  "5EAF": {
   "unit": "game/mainProgram0800",
   "line": "0"
  },
  "5EB1": {
   "unit": "game/mainProgram0800",
   "line": "start with an empty item list"
  },
  "5EB4": {
   "unit": "game/mainProgram0800",
   "line": "item id 2 = CLOAKING ON"
  },
  "5EB6": {
   "unit": "game/mainProgram0800",
   "line": "$F898 (waypoint column), bit 6 = 'cloaking ordered'"
  },
  "5EB9": {
   "unit": "game/mainProgram0800",
   "line": "test the cloak-order bit"
  },
  "5EBB": {
   "unit": "game/mainProgram0800",
   "line": "not cloaked: offer CLOAKING ON"
  },
  "5EBD": {
   "unit": "game/mainProgram0800",
   "line": "already cloaked: item id 3 = NO CLOAKING"
  },
  "5EBF": {
   "unit": "game/mainProgram0800",
   "line": "append the item and print its name"
  },
  "5EC2": {
   "unit": "game/mainProgram0800",
   "line": "unit index",
   "block": [
    "The second item depends on what the unit is doing: a unit that stands still can DIG IN or",
    "DIG OUT, a unit that is moving can be given or denied a BLITZ order. The same flag byte",
    "is snapshotted into the menu loop so that the list is rebuilt when that state changes."
   ]
  },
  "5EC5": {
   "unit": "game/mainProgram0800",
   "line": "$FB54 flags, bit 7 = the unit is standing still"
  },
  "5EC8": {
   "unit": "game/mainProgram0800",
   "line": "force the byte nonzero: 0 is the 'do not watch the unit' sentinel of the menu loop"
  },
  "5ECA": {
   "unit": "game/mainProgram0800",
   "line": "self-modify the LDA #imm at menuIdleSnapshot ($602A): the loop returns $80 when this bit 7 changes"
  },
  "5ECD": {
   "unit": "game/mainProgram0800",
   "line": "bit 7 clear = the unit is moving: offer the blitz items"
  },
  "5ECF": {
   "unit": "game/mainProgram0800",
   "line": "item id 17 = DIG OUT"
  },
  "5ED1": {
   "unit": "game/mainProgram0800",
   "line": "$F960, bits 5-7 = dug-in / digging state"
  },
  "5ED4": {
   "unit": "game/mainProgram0800",
   "line": "isolate the dig bits"
  },
  "5ED6": {
   "unit": "game/mainProgram0800",
   "line": "already dug in or digging: DIG OUT"
  },
  "5ED8": {
   "unit": "game/mainProgram0800",
   "line": "otherwise item id 18 = DIG IN"
  },
  "5ED9": {
   "unit": "game/mainProgram0800",
   "line": "always taken (X = $12)"
  },
  "5EDB": {
   "unit": "game/mainProgram0800",
   "line": "item id 10 = SET BLITZ"
  },
  "5EDD": {
   "unit": "game/mainProgram0800",
   "line": "unit index"
  },
  "5EE0": {
   "unit": "game/mainProgram0800",
   "line": "$F8FC (waypoint row), bit 6 = 'blitz ordered'"
  },
  "5EE3": {
   "unit": "game/mainProgram0800",
   "line": "test the blitz-order bit"
  },
  "5EE5": {
   "unit": "game/mainProgram0800",
   "line": "blitz off: offer SET BLITZ"
  },
  "5EE7": {
   "unit": "game/mainProgram0800",
   "line": "blitz on: item id 11 = BLITZ OFF"
  },
  "5EE8": {
   "unit": "game/mainProgram0800",
   "line": "append the dig/blitz item"
  },
  "5EEB": {
   "unit": "game/mainProgram0800",
   "line": "unit index",
   "block": [
    "JOIN GROUP is offered to every unit except the command centre; a BOOMER additionally gets",
    "SET TARGET or CLEAR TARGET while a battle is in progress."
   ]
  },
  "5EEE": {
   "unit": "game/mainProgram0800",
   "line": "is this the player's own command centre (unit 49 or 99)?"
  },
  "5EF1": {
   "unit": "game/mainProgram0800",
   "line": "the comcen cannot join a group and has no weapon target"
  },
  "5EF3": {
   "unit": "game/mainProgram0800",
   "line": "item id 7 = JOIN GROUP"
  },
  "5EF5": {
   "unit": "game/mainProgram0800",
   "line": "append it"
  },
  "5EF8": {
   "unit": "game/mainProgram0800",
   "line": "gamePhase zp_B1 is 0 only while the battle runs"
  },
  "5EFA": {
   "unit": "game/mainProgram0800",
   "line": "setup or film phase: no target item"
  },
  "5EFC": {
   "unit": "game/mainProgram0800",
   "line": "unit index"
  },
  "5EFF": {
   "unit": "game/mainProgram0800",
   "line": "C = 1 and A = the boomer's target byte if unit X is a BOOMER (type 2)"
  },
  "5F02": {
   "unit": "game/mainProgram0800",
   "line": "not a boomer: no target item"
  },
  "5F04": {
   "unit": "game/mainProgram0800",
   "line": "item id 4 = CLEAR TARGET"
  },
  "5F06": {
   "unit": "game/mainProgram0800",
   "line": "test the target byte's bit 7"
  },
  "5F07": {
   "unit": "game/mainProgram0800",
   "line": "bit 7 set = a target is locked: offer CLEAR TARGET"
  },
  "5F09": {
   "unit": "game/mainProgram0800",
   "line": "no target yet: item id 5 = SET TARGET"
  },
  "5F0B": {
   "unit": "game/mainProgram0800",
   "line": "append the target item"
  },
  "5F0E": {
   "unit": "game/mainProgram0800",
   "line": "item id 12 = (EXIT), always the last row"
  },
  "5F10": {
   "unit": "game/mainProgram0800",
   "line": "append it"
  },
  "5F13": {
   "unit": "game/mainProgram0800",
   "line": "screen row 15"
  },
  "5F15": {
   "unit": "game/mainProgram0800",
   "line": "the item list starts on row 15 of the info panel"
  },
  "5F18": {
   "unit": "game/mainProgram0800",
   "line": "put the mini-map path marker back on the unit"
  },
  "5F1B": {
   "unit": "game/mainProgram0800",
   "line": "run the selector: A = chosen item id, Y = chosen row (or $80)"
  },
  "5F1E": {
   "unit": "game/mainProgram0800",
   "line": "$80 = the unit's idle flag changed while the menu was open"
  },
  "5F20": {
   "unit": "game/mainProgram0800",
   "line": "no: act on the chosen item"
  },
  "5F22": {
   "unit": "game/mainProgram0800",
   "line": "yes: DIG vs BLITZ is wrong now, rebuild the whole menu"
  },
  "5F25": {
   "unit": "game/mainProgram0800",
   "line": "keep the chosen item id (from here on $91D5 holds an id, not a row)",
   "block": [
    "Dispatch on the chosen item id. Every branch either queues a command byte through the",
    "common tail at $5F9E (argument = the unit index) or runs a sub-dialogue of its own."
   ]
  },
  "5F28": {
   "unit": "game/mainProgram0800",
   "line": "leftover load - every path below reloads X or Y (dead)"
  },
  "5F2B": {
   "unit": "game/mainProgram0800",
   "line": "the chosen item id"
  },
  "5F2E": {
   "unit": "game/mainProgram0800",
   "line": "CLOAKING ON?"
  },
  "5F30": {
   "unit": "game/mainProgram0800",
   "line": "no"
  },
  "5F32": {
   "unit": "game/mainProgram0800",
   "line": "command $82 = cloak on (2 bytes: unit)"
  },
  "5F34": {
   "unit": "game/mainProgram0800",
   "line": "always taken"
  },
  "5F36": {
   "unit": "game/mainProgram0800",
   "line": "NO CLOAKING?"
  },
  "5F38": {
   "unit": "game/mainProgram0800",
   "line": "no"
  },
  "5F3A": {
   "unit": "game/mainProgram0800",
   "line": "command $84 = cloak off (2 bytes: unit)"
  },
  "5F3C": {
   "unit": "game/mainProgram0800",
   "line": "unit index"
  },
  "5F3F": {
   "unit": "game/mainProgram0800",
   "line": "flip the local copy of the cloak bit at once..."
  },
  "5F42": {
   "unit": "game/mainProgram0800",
   "line": "...bit 6 of $F898..."
  },
  "5F44": {
   "unit": "game/mainProgram0800",
   "line": "...so the display shows the new state before the command is executed"
  },
  "5F47": {
   "unit": "game/mainProgram0800",
   "line": "command byte back into A"
  },
  "5F48": {
   "unit": "game/mainProgram0800",
   "line": "always taken: queue it"
  },
  "5F4A": {
   "unit": "game/mainProgram0800",
   "line": "CLEAR TARGET?"
  },
  "5F4C": {
   "unit": "game/mainProgram0800",
   "line": "no"
  },
  "5F4E": {
   "unit": "game/mainProgram0800",
   "line": "command $86 = clear the boomer's target (2 bytes: unit)"
  },
  "5F50": {
   "unit": "game/mainProgram0800",
   "line": "always taken"
  },
  "5F52": {
   "unit": "game/mainProgram0800",
   "line": "SET TARGET?"
  },
  "5F54": {
   "unit": "game/mainProgram0800",
   "line": "no"
  },
  "5F56": {
   "unit": "game/mainProgram0800",
   "line": "print 'SETTING' centred in the uiLevel colour"
  },
  "5F59": {
   "unit": "game/mainProgram0800",
   "line": "$CB61 = 'TARGET'"
  },
  "5F5B": {
   "unit": "game/mainProgram0800",
   "line": "high byte"
  },
  "5F5D": {
   "unit": "game/mainProgram0800",
   "line": "print it centred under SETTING"
  },
  "5F60": {
   "unit": "game/mainProgram0800",
   "line": "cursor mode 5"
  },
  "5F62": {
   "unit": "game/mainProgram0800",
   "line": "zp_BB > 0 = range-limited attack cursor"
  },
  "5F64": {
   "unit": "game/mainProgram0800",
   "line": "let the player pick the target; the cursor loop queues command $87 itself"
  },
  "5F67": {
   "unit": "game/mainProgram0800",
   "line": "done"
  },
  "5F6A": {
   "unit": "game/mainProgram0800",
   "line": "JOIN GROUP?"
  },
  "5F6C": {
   "unit": "game/mainProgram0800",
   "line": "no"
  },
  "5F6E": {
   "unit": "game/mainProgram0800",
   "line": "run the group picker; it queues command $88 itself"
  },
  "5F71": {
   "unit": "game/mainProgram0800",
   "line": "done"
  },
  "5F74": {
   "unit": "game/mainProgram0800",
   "line": "SET BLITZ?"
  },
  "5F76": {
   "unit": "game/mainProgram0800",
   "line": "no"
  },
  "5F78": {
   "unit": "game/mainProgram0800",
   "line": "command $93 = blitz on (2 bytes: unit)"
  },
  "5F7A": {
   "unit": "game/mainProgram0800",
   "line": "always taken"
  },
  "5F7C": {
   "unit": "game/mainProgram0800",
   "line": "BLITZ OFF?"
  },
  "5F7E": {
   "unit": "game/mainProgram0800",
   "line": "no"
  },
  "5F80": {
   "unit": "game/mainProgram0800",
   "line": "command $95 = blitz off (2 bytes: unit)"
  },
  "5F82": {
   "unit": "game/mainProgram0800",
   "line": "unit index"
  },
  "5F85": {
   "unit": "game/mainProgram0800",
   "line": "flip the local blitz bit immediately..."
  },
  "5F88": {
   "unit": "game/mainProgram0800",
   "line": "...bit 6 of $F8FC..."
  },
  "5F8A": {
   "unit": "game/mainProgram0800",
   "line": "...for instant menu feedback"
  },
  "5F8D": {
   "unit": "game/mainProgram0800",
   "line": "command byte back into A"
  },
  "5F8E": {
   "unit": "game/mainProgram0800",
   "line": "always taken"
  },
  "5F90": {
   "unit": "game/mainProgram0800",
   "line": "DIG OUT?"
  },
  "5F92": {
   "unit": "game/mainProgram0800",
   "line": "no"
  },
  "5F94": {
   "unit": "game/mainProgram0800",
   "line": "command $A0 = dig out (2 bytes: unit)"
  },
  "5F96": {
   "unit": "game/mainProgram0800",
   "line": "always taken"
  },
  "5F98": {
   "unit": "game/mainProgram0800",
   "line": "DIG IN?"
  },
  "5F9A": {
   "unit": "game/mainProgram0800",
   "line": "anything else (item 12 = (EXIT)) just closes the menu"
  },
  "5F9C": {
   "unit": "game/mainProgram0800",
   "line": "command $9F = dig in (2 bytes: unit)"
  },
  "5F9E": {
   "unit": "game/mainProgram0800",
   "line": "the unit index..."
  },
  "5FA1": {
   "unit": "game/mainProgram0800",
   "line": "...is the single argument of all of these commands"
  },
  "5FA3": {
   "unit": "game/mainProgram0800",
   "line": "queue 'command byte, unit' in the outgoing ring, then fall into exitUnitMenu"
  },
  "5FA6": {
   "unit": "game/mainProgram0800",
   "line": "0",
   "routine": [
    "exitUnitMenu - Shared tail of every unit/group menu path: drops back to UI level 0 and releases the",
    "info panel, then returns to the battlefield main loop.",
    "In:  -",
    "Out: uiLevel $9209 = 0, infoPanelUnit $91D7 = $FF",
    "Called from: $5E65, $5F67, $5F71, $5F9A and the fall-through at $5FA3, $6339 and $64D7"
   ]
  },
  "5FA8": {
   "unit": "game/mainProgram0800",
   "line": "uiLevel 0 = back to browsing the map"
  },
  "5FAB": {
   "unit": "game/mainProgram0800",
   "line": "$FF"
  },
  "5FAD": {
   "unit": "game/mainProgram0800",
   "line": "no unit owns the info panel any more"
  },
  "5FB0": {
   "unit": "game/mainProgram0800",
   "line": "return to the battlefield main loop"
  },
  "5FB1": {
   "unit": "game/mainProgram0800",
   "line": "item id into A",
   "routine": [
    "addMenuItem - Appends item id X to menuItemIdList[menuItemCount++] and prints the item's name on the",
    "current text line. Ids 0-11 come from the strings at $C9D2, ids 12-18 from those at $CAB2; both are",
    "printed with printTableEntry, which strides 8 bytes, so the first group is indexed with 2*id (its",
    "strings are padded with leading blanks onto a 16-byte grid). Every string ends with a CR, so the",
    "cursor drops to the next row by itself. Ids 1 (MOVE TO GOAL) and 9 (SELF DESTRCT) exist in the",
    "string table but are never passed to this routine in this build.",
    "In:  X = item id (0 FORMATION, 1 MOVE TO GOAL, 2 CLOAKING ON, 3 NO CLOAKING, 4 CLEAR TARGET,",
    "     5 SET TARGET, 6 MEMBERSHIP, 7 JOIN GROUP, 8 DIRECT UNIT, 9 SELF DESTRCT, 10 SET BLITZ,",
    "     11 BLITZ OFF, 12 (EXIT), 13 ENERGY, 14 BATTLE, 15 RADAR, 16 DRONE, 17 DIG OUT, 18 DIG IN);",
    "     menuItemCount $91D4 and the text cursor",
    "Out: menuItemIdList[n] = id, menuItemCount incremented, one line printed; A/X/Y clobbered",
    "Called from: runUnitOptionsMenu ($5EBF, $5EE8, $5EF5, $5F0B, $5F10), runGroupOptionsMenu ($6268,",
    "     $628E, $6293, $6298, $629D, $62A2) and runRepairWhichMenu ($6568, $6575)"
   ]
  },
  "5FB2": {
   "unit": "game/mainProgram0800",
   "line": "next free slot of the item list"
  },
  "5FB5": {
   "unit": "game/mainProgram0800",
   "line": "remember which id sits on which row"
  },
  "5FB8": {
   "unit": "game/mainProgram0800",
   "line": "one more item"
  },
  "5FBB": {
   "unit": "game/mainProgram0800",
   "line": "prepare an exact subtraction"
  },
  "5FBC": {
   "unit": "game/mainProgram0800",
   "line": "ids 12-18 come from the second string table"
  },
  "5FBE": {
   "unit": "game/mainProgram0800",
   "line": "ids 0-11: the 16-byte-strided UNIT/GROUP OPTIONS strings"
  },
  "5FC0": {
   "unit": "game/mainProgram0800",
   "line": "X = id - 12"
  },
  "5FC1": {
   "unit": "game/mainProgram0800",
   "line": "$CAB2 = ' (EXIT)', base of the 8-byte console strings"
  },
  "5FC3": {
   "unit": "game/mainProgram0800",
   "line": "high byte"
  },
  "5FC5": {
   "unit": "game/mainProgram0800",
   "line": "always taken"
  },
  "5FC7": {
   "unit": "game/mainProgram0800",
   "line": "id 0-11 back into A"
  },
  "5FC8": {
   "unit": "game/mainProgram0800",
   "line": "double it: printTableEntry strides 8 bytes but these strings sit on a 16-byte grid"
  },
  "5FC9": {
   "unit": "game/mainProgram0800",
   "line": "index for printTableEntry"
  },
  "5FCA": {
   "unit": "game/mainProgram0800",
   "line": "$C9D2 = 'FORMATION', base of the option strings"
  },
  "5FCC": {
   "unit": "game/mainProgram0800",
   "line": "high byte"
  },
  "5FCE": {
   "unit": "game/mainProgram0800",
   "line": "print the entry at base + 8*X; each string ends with CR so the cursor drops to the next row"
  },
  "5FD1": {
   "unit": "game/mainProgram0800",
   "line": "C = 1: behave exactly like runMenuLoop",
   "routine": [
    "runMenuLoopWithFlag - Alternative entry for the console and setup menus: with C = 1 it behaves",
    "exactly like runMenuLoop; with C = 0 it puts $FF into the slow-down row operand menuSlowRowTest+1 so",
    "there is no extra pause before the last item, and leaves the unit-idle watch operand untouched.",
    "In:  C flag, menu state menuItemCount/menuSelectedItem/menuFirstRow",
    "Out: as runMenuLoopWatchUnit",
    "Called from: runMainMenu ($1C59) and overlay A ($7F40, $835D, $83CE)"
   ]
  },
  "5FD3": {
   "unit": "game/mainProgram0800",
   "line": "C = 0: $FF disables the extra pause before the last row"
  },
  "5FD5": {
   "unit": "game/mainProgram0800",
   "line": "always taken; this path skips the store at $5FD9, so menuIdleSnapshot+1 keeps whatever the previous menu left there (harmless: these callers use the pseudo-units $F0/$FE/$FF, for which the watch is skipped anyway)"
  },
  "5FD7": {
   "unit": "game/mainProgram0800",
   "line": "0",
   "routine": [
    "runMenuLoop - Menu selector without the unit-idle watch: patches menuIdleSnapshot+1 ($602A) to 0 and",
    "falls into runMenuLoopWatchUnit, which then sets the slow-down row to itemCount-2.",
    "In:  menu state menuItemCount/menuSelectedItem/menuFirstRow, selectedUnit $90F8, menuLoopMode $612E",
    "Out: A = the selected item id, Y = the selected row",
    "Called from: runJoinGroupMenu ($61BC), runRepairWhichMenu ($6581), runInGameOptionsMenu ($65A9),",
    "     runFormationOptionsMenu ($661D) and runMenuLoopWithFlag ($5FD1)"
   ]
  },
  "5FD9": {
   "unit": "game/mainProgram0800",
   "line": "patch menuIdleSnapshot+1 ($602A): 0 turns the unit-idle watch off"
  },
  "5FDC": {
   "unit": "game/mainProgram0800",
   "line": "number of rows",
   "routine": [
    "runMenuLoopWatchUnit - The generic vertical menu selector used by every in-game option menu. It arms",
    "a 20-frame input lockout, highlights the current row, and then loops once per frame: it stirs the",
    "RNG, runs the update that suits the phase (updateGameFrame during a battle, the '*' / F1 hot keys",
    "plus serviceCommandExchange in the setup and film phases), keeps the info panel on the selected",
    "unit, blinks the selected row every 20 frames, updates the map feedback chosen by menuLoopMode (path",
    "marker, or a live preview of the group the current row stands for) and reads the joystick: up/down",
    "step through the rows without wrap-around, fire confirms. It returns early with A = Y = $80 when the",
    "watched unit's idle flag ($FB54 bit 7) no longer matches the snapshot in menuIdleSnapshot+1, and it",
    "forces the last item ((EXIT)) when the unit dies, the game-over countdown starts or checkUiContinue",
    "asks for an abort.",
    "In:  menuItemCount $91D4, menuSelectedItem $91D5, menuFirstRow $91D6, menuLoopMode $612E,",
    "     selectedUnit $90F8, joyDirection zp_5D, joyRepeatTimer zp_6C, menuBlinkTimer zp_6E, gamePhase",
    "     zp_B1, gameEndCountdown $92C9, gameEndReason $0BA8 and the patched operands",
    "     menuIdleSnapshot+1 / menuSlowRowTest+1",
    "Out: A = menuItemIdList[menuSelectedItem], Y = menuSelectedItem (or A = Y = $80 meaning 'rebuild the",
    "     menu'), menuSelectedItem updated, selectedGroupKey/highlightedGroupKey updated in group-preview",
    "     mode, menuBlinkState, inputLockoutTimer $0B7D, joyRepeatTimer, menuMoveDirection+1 patched; the",
    "     selected row is left highlighted",
    "Called from: runUnitOptionsMenu ($5F1B), runGroupOptionsMenu ($62AA) and through runMenuLoop"
   ]
  },
  "5FDF": {
   "unit": "game/mainProgram0800",
   "line": "..."
  },
  "5FE0": {
   "unit": "game/mainProgram0800",
   "line": "count - 2 = the row just before the last one"
  },
  "5FE1": {
   "unit": "game/mainProgram0800",
   "line": "patch the CMP #imm at menuSlowRowTest ($60BA): landing on this row adds a pause"
  },
  "5FE4": {
   "unit": "game/mainProgram0800",
   "line": "20 frames"
  },
  "5FE6": {
   "unit": "game/mainProgram0800",
   "line": "ignore held-over input for 20 frames..."
  },
  "5FE9": {
   "unit": "game/mainProgram0800",
   "line": "...and do not step the selection for 20 frames"
  },
  "5FEB": {
   "unit": "game/mainProgram0800",
   "line": "1"
  },
  "5FED": {
   "unit": "game/mainProgram0800",
   "line": "menuBlinkState 1 = the selected row is currently shown normally"
  },
  "5FF0": {
   "unit": "game/mainProgram0800",
   "line": "highlight the selected row and restart the 20-frame blink timer"
  },
  "5FF3": {
   "unit": "game/mainProgram0800",
   "line": "stir the 24-bit game RNG once per pass",
   "block": [
    "One pass per frame while the menu is open: keep the world running, watch the unit, update",
    "the map feedback, blink the selected row and read the joystick."
   ]
  },
  "5FF6": {
   "unit": "game/mainProgram0800",
   "line": "gamePhase zp_B1"
  },
  "5FF8": {
   "unit": "game/mainProgram0800",
   "line": "$FF = the pre-battle setup phase (overlay A resident)"
  },
  "5FFA": {
   "unit": "game/mainProgram0800",
   "line": "yes: poll overlay A's hot keys"
  },
  "5FFC": {
   "unit": "game/mainProgram0800",
   "line": "bits 6/7 flag the non-battle phases"
  },
  "5FFE": {
   "unit": "game/mainProgram0800",
   "line": "both clear: a battle is running - do the full per-frame update"
  },
  "6000": {
   "unit": "game/mainProgram0800",
   "line": "otherwise only service the opponent link"
  },
  "6002": {
   "unit": "game/mainProgram0800",
   "line": "setup phase: overlay A's '*' hot key (DESTROY-mode toggle)"
  },
  "6005": {
   "unit": "game/mainProgram0800",
   "line": "$0BA5 bit 7 = solo trainer game"
  },
  "6008": {
   "unit": "game/mainProgram0800",
   "line": "modem game: no F1 handler"
  },
  "600A": {
   "unit": "game/mainProgram0800",
   "line": "trainer only: F1 switches the BEGINNER/STANDARD display"
  },
  "600D": {
   "unit": "game/mainProgram0800",
   "line": "run one step of the lock-step command exchange"
  },
  "6010": {
   "unit": "game/mainProgram0800",
   "line": "skip the battle-only bookkeeping"
  },
  "6013": {
   "unit": "game/mainProgram0800",
   "line": "the selected unit...",
   "block": [
    "Battle phase: run one game frame, then check that the watched unit is still alive and",
    "still in the same movement state."
   ]
  },
  "6016": {
   "unit": "game/mainProgram0800",
   "line": "...keeps owning the info panel while the menu is open"
  },
  "6019": {
   "unit": "game/mainProgram0800",
   "line": "one frame of the battle simulation and its display"
  },
  "601C": {
   "unit": "game/mainProgram0800",
   "line": "gamePhase bit 6 = paused / waiting for the opponent"
  },
  "601E": {
   "unit": "game/mainProgram0800",
   "line": "paused: do not touch the unit or the map highlight"
  },
  "6020": {
   "unit": "game/mainProgram0800",
   "line": "selected unit"
  },
  "6023": {
   "unit": "game/mainProgram0800",
   "line": "$F0/$FE/$FF are console pseudo-units, not real units"
  },
  "6025": {
   "unit": "game/mainProgram0800",
   "line": "type byte, bit 7 = destroyed"
  },
  "6028": {
   "unit": "game/mainProgram0800",
   "line": "the unit died under the menu: close it on the last item"
  },
  "602A": {
   "unit": "game/mainProgram0800",
   "line": "operand patched at $5ECA/$6273 with the unit's $FB54 flags (or with 0 by runMenuLoop = watch disabled)"
  },
  "602C": {
   "unit": "game/mainProgram0800",
   "line": "0: the caller does not want the unit watched"
  },
  "602E": {
   "unit": "game/mainProgram0800",
   "line": "compare the snapshot with the live flags"
  },
  "6031": {
   "unit": "game/mainProgram0800",
   "line": "only the 'standing still' bit matters"
  },
  "6033": {
   "unit": "game/mainProgram0800",
   "line": "unchanged: carry on"
  },
  "6035": {
   "unit": "game/mainProgram0800",
   "line": "A = Y = $80 tells the caller to rebuild the menu"
  },
  "6036": {
   "unit": "game/mainProgram0800",
   "line": "early return with the rebuild code"
  },
  "6037": {
   "unit": "game/mainProgram0800",
   "line": "$FF unit menu, $01 group menu, $00/$20 join-group picker (side bit)",
   "block": [
    "Map feedback while the menu is open: either animate the selected unit's path marker or,",
    "in the join-group picker, highlight the group that the current row stands for."
   ]
  },
  "603A": {
   "unit": "game/mainProgram0800",
   "line": "unit menu: just animate the path marker"
  },
  "603C": {
   "unit": "game/mainProgram0800",
   "line": "re-read the mode"
  },
  "603F": {
   "unit": "game/mainProgram0800",
   "line": "odd = group menu"
  },
  "6041": {
   "unit": "game/mainProgram0800",
   "line": "group menu: also just animate the path marker"
  },
  "6043": {
   "unit": "game/mainProgram0800",
   "line": "join-group picker: the selected row is the group number"
  },
  "6046": {
   "unit": "game/mainProgram0800",
   "line": "never true - the list has 8 rows (0-7); probably an off-by-one, the (EXIT) row looks like it was meant to clear the highlight"
  },
  "6048": {
   "unit": "game/mainProgram0800",
   "line": "always taken"
  },
  "604A": {
   "unit": "game/mainProgram0800",
   "line": "would mean 'no group highlighted'"
  },
  "604C": {
   "unit": "game/mainProgram0800",
   "line": "unreachable in this build"
  },
  "604F": {
   "unit": "game/mainProgram0800",
   "line": "group number..."
  },
  "6050": {
   "unit": "game/mainProgram0800",
   "line": "...times 4 = the group-id field of $FB54"
  },
  "6051": {
   "unit": "game/mainProgram0800",
   "line": "add the player's side bit ($20 for units 50-99)"
  },
  "6054": {
   "unit": "game/mainProgram0800",
   "line": "the group the highlight is previewing"
  },
  "6057": {
   "unit": "game/mainProgram0800",
   "line": "is the viewport already showing that group?"
  },
  "605A": {
   "unit": "game/mainProgram0800",
   "line": "yes: nothing to redraw"
  },
  "605C": {
   "unit": "game/mainProgram0800",
   "line": "remember the highlighted group"
  },
  "605F": {
   "unit": "game/mainProgram0800",
   "line": "repaint the viewport with the new group highlighted"
  },
  "6062": {
   "unit": "game/mainProgram0800",
   "line": "on to the blink handling"
  },
  "6065": {
   "unit": "game/mainProgram0800",
   "line": "walk the mini-map path marker one step along the unit's route"
  },
  "6068": {
   "unit": "game/mainProgram0800",
   "line": "zp_6E, counted down by the IRQ",
   "block": [
    "Blink the selected row, then decide whether the menu has to close (game over, or an abort",
    "request from checkUiContinue)."
   ]
  },
  "606A": {
   "unit": "game/mainProgram0800",
   "line": "not expired yet"
  },
  "606C": {
   "unit": "game/mainProgram0800",
   "line": "every 20 frames: flip the highlight of the selected row"
  },
  "606F": {
   "unit": "game/mainProgram0800",
   "line": "$92C9 counts down while the game-over sequence runs"
  },
  "6072": {
   "unit": "game/mainProgram0800",
   "line": "game over: close the menu on the last item"
  },
  "6074": {
   "unit": "game/mainProgram0800",
   "line": "$0BA8 is nonzero once the game has ended"
  },
  "6077": {
   "unit": "game/mainProgram0800",
   "line": "after the game the abort test is skipped so the console menus stay usable"
  },
  "6079": {
   "unit": "game/mainProgram0800",
   "line": "returns 0 when SPACE, a screen change or a pause wants this menu closed"
  },
  "607C": {
   "unit": "game/mainProgram0800",
   "line": "keep going"
  },
  "607E": {
   "unit": "game/mainProgram0800",
   "line": "number of items"
  },
  "6081": {
   "unit": "game/mainProgram0800",
   "line": "index of the last one"
  },
  "6082": {
   "unit": "game/mainProgram0800",
   "line": "force the selection onto the last item, normally (EXIT)"
  },
  "6085": {
   "unit": "game/mainProgram0800",
   "line": "return that selection"
  },
  "6088": {
   "unit": "game/mainProgram0800",
   "line": "joystick nibble, active low",
   "block": [
    "Joystick handling: fire confirms the selection; up/down step through the rows without",
    "wrap-around, with the usual 16/6-frame auto-repeat plus an extra pause before the last",
    "row."
   ]
  },
  "608A": {
   "unit": "game/mainProgram0800",
   "line": "centred?"
  },
  "608C": {
   "unit": "game/mainProgram0800",
   "line": "deflected: try to move the selection"
  },
  "608E": {
   "unit": "game/mainProgram0800",
   "line": "Z = 1 on a fresh fire-button press"
  },
  "6091": {
   "unit": "game/mainProgram0800",
   "line": "fire: confirm the current selection"
  },
  "6093": {
   "unit": "game/mainProgram0800",
   "line": "auto-repeat delay still running?"
  },
  "6095": {
   "unit": "game/mainProgram0800",
   "line": "yes: nothing to do this frame"
  },
  "6097": {
   "unit": "game/mainProgram0800",
   "line": "joystick nibble"
  },
  "6099": {
   "unit": "game/mainProgram0800",
   "line": "force the left/right bits high: only up and down move the selection"
  },
  "609B": {
   "unit": "game/mainProgram0800",
   "line": "-1 = one row up"
  },
  "609D": {
   "unit": "game/mainProgram0800",
   "line": "$0E = bit 0 low = up"
  },
  "609F": {
   "unit": "game/mainProgram0800",
   "line": "up"
  },
  "60A1": {
   "unit": "game/mainProgram0800",
   "line": "+1 = one row down"
  },
  "60A3": {
   "unit": "game/mainProgram0800",
   "line": "$0D = bit 1 low = down"
  },
  "60A5": {
   "unit": "game/mainProgram0800",
   "line": "left/right only: ignore"
  },
  "60A7": {
   "unit": "game/mainProgram0800",
   "line": "the step (-1 or +1)"
  },
  "60A8": {
   "unit": "game/mainProgram0800",
   "line": "patch the LDY #imm at menuMoveDirection ($60BE) with the direction"
  },
  "60AB": {
   "unit": "game/mainProgram0800",
   "line": "clear carry for the add"
  },
  "60AC": {
   "unit": "game/mainProgram0800",
   "line": "candidate row = current + step"
  },
  "60AF": {
   "unit": "game/mainProgram0800",
   "line": "16 frames before the first repeat, 6 between repeats (A is preserved)"
  },
  "60B2": {
   "unit": "game/mainProgram0800",
   "line": "past the last row (or $FF above the first)?"
  },
  "60B5": {
   "unit": "game/mainProgram0800",
   "line": "in range"
  },
  "60B7": {
   "unit": "game/mainProgram0800",
   "line": "out of range - the selection does not wrap: just keep looping"
  },
  "60BA": {
   "unit": "game/mainProgram0800",
   "line": "operand = itemCount-2, or $FF when runMenuLoopWithFlag turned the pause off"
  },
  "60BC": {
   "unit": "game/mainProgram0800",
   "line": "not the slow-down row"
  },
  "60BE": {
   "unit": "game/mainProgram0800",
   "line": "operand = the move direction stored at $60A8"
  },
  "60C0": {
   "unit": "game/mainProgram0800",
   "line": "moving up: no extra delay"
  },
  "60C2": {
   "unit": "game/mainProgram0800",
   "line": "30 frames"
  },
  "60C4": {
   "unit": "game/mainProgram0800",
   "line": "moving down onto the second-to-last row: pause so the stick cannot run straight into (EXIT)"
  },
  "60C6": {
   "unit": "game/mainProgram0800",
   "line": "keep the new row"
  },
  "60C7": {
   "unit": "game/mainProgram0800",
   "line": "restore the colours of the row being left"
  },
  "60CA": {
   "unit": "game/mainProgram0800",
   "line": "new row back"
  },
  "60CB": {
   "unit": "game/mainProgram0800",
   "line": "it is the selection now"
  },
  "60CE": {
   "unit": "game/mainProgram0800",
   "line": "sound 2 = menu-move click"
  },
  "60D0": {
   "unit": "game/mainProgram0800",
   "line": "play it"
  },
  "60D3": {
   "unit": "game/mainProgram0800",
   "line": "highlight the new row and loop"
  },
  "60D6": {
   "unit": "game/mainProgram0800",
   "line": "0 = the row is already highlighted"
  },
  "60D9": {
   "unit": "game/mainProgram0800",
   "line": "nothing to do"
  },
  "60DB": {
   "unit": "game/mainProgram0800",
   "line": "leave the chosen row highlighted"
  },
  "60DE": {
   "unit": "game/mainProgram0800",
   "line": "the chosen row"
  },
  "60E1": {
   "unit": "game/mainProgram0800",
   "line": "A = its item id; Y still holds the row index"
  },
  "60E4": {
   "unit": "game/mainProgram0800",
   "line": "return to the menu's dispatcher"
  },
  "60E5": {
   "unit": "game/mainProgram0800",
   "line": "0 = the row is currently EORed (highlighted)",
   "routine": [
    "unhighlightMenuRow - Removes the highlight from the selected menu row, but only if it is currently",
    "applied (menuBlinkState = 0); otherwise it returns at once. Falls into toggleMenuRowHighlight.",
    "In:  menuBlinkState $92C5, menuSelectedItem, menuFirstRow, textWindowWidth zp_3C, textColour zp_3D",
    "Out: the row's colour bytes restored, menuBlinkState = 1",
    "Called from: the menu loop ($60C7), runRepairWhichMenu ($6593), runInGameOptionsMenu ($65DD, $65E3)",
    "     and overlay A ($845C)"
   ]
  },
  "60E8": {
   "unit": "game/mainProgram0800",
   "line": "already normal: nothing to undo"
  },
  "60EA": {
   "unit": "game/mainProgram0800",
   "line": "20 frames",
   "routine": [
    "toggleMenuRowHighlight - Flips the highlight of menu row menuFirstRow + menuSelectedItem by EORing",
    "the colour byte of every cell of that row with textColour, flips menuBlinkState and restarts the",
    "20-frame blink timer. Special case for the REPAIR WHICH menu (selectedUnit = $FF, row < 4): if the",
    "comcen is stunned it throws its return address away and jumps into the menu loop's exit path so the",
    "menu closes on (EXIT); otherwise it also blinks that comcen system's marker on the schematic.",
    "In:  menuSelectedItem, menuFirstRow, textWindowWidth zp_3C, textColour zp_3D, selectedUnit $90F8,",
    "     comcenStunStatus $922A, menuBlinkState $92C5",
    "Out: menuBlinkTimer zp_6E = 20, the row's colour bytes EORed, menuBlinkState flipped, screenPtr",
    "     zp_B6/zp_B7 and the text cursor moved",
    "Called from: the menu loop ($5FF0, $606C, $60DB), unhighlightMenuRow and overlay A ($8066, $847B)"
   ]
  },
  "60EC": {
   "unit": "game/mainProgram0800",
   "line": "restart the blink countdown"
  },
  "60EE": {
   "unit": "game/mainProgram0800",
   "line": "selected unit, or a console pseudo-unit"
  },
  "60F1": {
   "unit": "game/mainProgram0800",
   "line": "a real unit: no schematic marker to blink"
  },
  "60F3": {
   "unit": "game/mainProgram0800",
   "line": "$FF marks the REPAIR WHICH menu ($F0 = main menu, $FE = in-game options)"
  },
  "60F5": {
   "unit": "game/mainProgram0800",
   "line": "some other menu"
  },
  "60F7": {
   "unit": "game/mainProgram0800",
   "line": "selected row"
  },
  "60FA": {
   "unit": "game/mainProgram0800",
   "line": "rows 0-3 are the four comcen systems"
  },
  "60FC": {
   "unit": "game/mainProgram0800",
   "line": "the (EXIT) row has no schematic marker"
  },
  "60FE": {
   "unit": "game/mainProgram0800",
   "line": "$922A bit 7 = the comcen is knocked out"
  },
  "6101": {
   "unit": "game/mainProgram0800",
   "line": "comcen alive: blink its system marker as well"
  },
  "6103": {
   "unit": "game/mainProgram0800",
   "line": "comcen stunned: discard the return address..."
  },
  "6104": {
   "unit": "game/mainProgram0800",
   "line": "...of the menu-loop caller..."
  },
  "6105": {
   "unit": "game/mainProgram0800",
   "line": "...and force the loop to close on the last item (only valid when called from runMenuLoopWatchUnit)"
  },
  "6108": {
   "unit": "game/mainProgram0800",
   "line": "blink the marker of the selected comcen system on the schematic"
  },
  "610B": {
   "unit": "game/mainProgram0800",
   "line": "first row of the item list",
   "block": [
    "EOR the colour byte of every cell of the selected row. In multicolour bitmap mode the",
    "text engine's screenPtr points into colour RAM $D800, which supplies the colour of the",
    "glyph pixels, so this makes the row alternate between its text colour and black."
   ]
  },
  "610E": {
   "unit": "game/mainProgram0800",
   "line": "clear carry"
  },
  "610F": {
   "unit": "game/mainProgram0800",
   "line": "+ selection = screen row of the selected item"
  },
  "6112": {
   "unit": "game/mainProgram0800",
   "line": "0"
  },
  "6114": {
   "unit": "game/mainProgram0800",
   "line": "start at the left edge of the text window"
  },
  "6116": {
   "unit": "game/mainProgram0800",
   "line": "set the row and recompute screenPtr (which points into colour RAM $D800 in multicolour mode); X and Y are preserved"
  },
  "6119": {
   "unit": "game/mainProgram0800",
   "line": "window width in characters"
  },
  "611B": {
   "unit": "game/mainProgram0800",
   "line": "index of the last cell"
  },
  "611C": {
   "unit": "game/mainProgram0800",
   "line": "colour byte of this cell"
  },
  "611E": {
   "unit": "game/mainProgram0800",
   "line": "EOR with the text colour: a cell holding textColour turns black, and back again on the next call"
  },
  "6120": {
   "unit": "game/mainProgram0800",
   "line": "write it back"
  },
  "6122": {
   "unit": "game/mainProgram0800",
   "line": "previous cell"
  },
  "6123": {
   "unit": "game/mainProgram0800",
   "line": "all cells of the row"
  },
  "6125": {
   "unit": "game/mainProgram0800",
   "line": "flip the state flag..."
  },
  "6128": {
   "unit": "game/mainProgram0800",
   "line": "...between 1 (normal) and 0 (EORed)"
  },
  "612A": {
   "unit": "game/mainProgram0800",
   "line": "store it"
  },
  "612D": {
   "unit": "game/mainProgram0800",
   "line": "done"
  },
  "612E": {
   "unit": "game/mainProgram0800",
   "line": "map-highlight mode of the menu loop: $FF unit menu (animate the path marker), $01 group menu, $00/$20 join-group picker (the value is the player's side bit)"
  },
  "612F": {
   "unit": "game/mainProgram0800",
   "line": "UI level 2",
   "routine": [
    "runJoinGroupMenu - The JOIN GROUP picker. Lists the seven groups ALPHA..GROVER with their current",
    "member counts plus an (EXIT) row from screen row 13, preselecting the group the unit is already in.",
    "The menu loop runs in group-preview mode, so moving the selection highlights that group on the",
    "viewport. Picking a group calls addSelectedUnitToGroup, which queues command $88; if the unit is too",
    "far from the group (C = 1, TOO FAR! shown) the list is redrawn and the question repeated.",
    "In:  selectedUnit $90F8, unitDisplayFlagsTable $FB54 (group number bits 2-4, side bit 5)",
    "Out: uiLevel = 2, menuItemCount = 8, menuFirstRow = 13, menuLoopMode = the unit's side bit,",
    "     selectedGroupKey = the previewed/chosen group, command $88 unit,group queued; $9207 = $FF (dead)",
    "Called from: the UNIT OPTIONS item JOIN GROUP ($5F6E)"
   ]
  },
  "6131": {
   "unit": "game/mainProgram0800",
   "line": "uiLevel 2 = group (info-panel colour 4)"
  },
  "6134": {
   "unit": "game/mainProgram0800",
   "line": "the unit that wants to join"
  },
  "6137": {
   "unit": "game/mainProgram0800",
   "line": "$FB54 flags"
  },
  "613A": {
   "unit": "game/mainProgram0800",
   "line": "group number in bits 2-4"
  },
  "613C": {
   "unit": "game/mainProgram0800",
   "line": "shift it down..."
  },
  "613D": {
   "unit": "game/mainProgram0800",
   "line": "...to 0-6"
  },
  "613E": {
   "unit": "game/mainProgram0800",
   "line": "into X"
  },
  "613F": {
   "unit": "game/mainProgram0800",
   "line": "preselect the group the unit currently belongs to"
  },
  "6142": {
   "unit": "game/mainProgram0800",
   "line": "0",
   "block": [
    "(Re)draw the picker: heading, one row per group with its name and member count, then the",
    "(EXIT) row."
   ]
  },
  "6144": {
   "unit": "game/mainProgram0800",
   "line": "ASCII translation on"
  },
  "6146": {
   "unit": "game/mainProgram0800",
   "line": "no automatic centring"
  },
  "6149": {
   "unit": "game/mainProgram0800",
   "line": "blank with glyph 0"
  },
  "614B": {
   "unit": "game/mainProgram0800",
   "line": "colour 4 = the group-level text colour"
  },
  "614D": {
   "unit": "game/mainProgram0800",
   "line": "ink"
  },
  "614F": {
   "unit": "game/mainProgram0800",
   "line": "pad"
  },
  "6151": {
   "unit": "game/mainProgram0800",
   "line": "clear the info panel"
  },
  "6154": {
   "unit": "game/mainProgram0800",
   "line": "$CB25 = 'WHICH GROUP:'"
  },
  "6156": {
   "unit": "game/mainProgram0800",
   "line": "high byte"
  },
  "6158": {
   "unit": "game/mainProgram0800",
   "line": "print the heading"
  },
  "615B": {
   "unit": "game/mainProgram0800",
   "line": "next row"
  },
  "615E": {
   "unit": "game/mainProgram0800",
   "line": "0"
  },
  "6160": {
   "unit": "game/mainProgram0800",
   "line": "zp_22 is reused here as the group counter 0-6"
  },
  "6162": {
   "unit": "game/mainProgram0800",
   "line": "$C92C = the seven 8-byte group names ALPHA..GROVER",
   "block": [
    "One row per group 0-6: the name from the 8-byte table at $C92C, a space, then the number",
    "of living members of that group on the clicking unit's side, right-aligned to two",
    "columns."
   ]
  },
  "6164": {
   "unit": "game/mainProgram0800",
   "line": "high byte"
  },
  "6166": {
   "unit": "game/mainProgram0800",
   "line": "group number"
  },
  "6168": {
   "unit": "game/mainProgram0800",
   "line": "print the name at $C92C + 8*group"
  },
  "616B": {
   "unit": "game/mainProgram0800",
   "line": "$A0 = space"
  },
  "616D": {
   "unit": "game/mainProgram0800",
   "line": "separate the name from the count"
  },
  "6170": {
   "unit": "game/mainProgram0800",
   "line": "group number..."
  },
  "6172": {
   "unit": "game/mainProgram0800",
   "line": "...times 4..."
  },
  "6173": {
   "unit": "game/mainProgram0800",
   "line": "...= the group-id field of the flag byte"
  },
  "6174": {
   "unit": "game/mainProgram0800",
   "line": "the joining unit"
  },
  "6177": {
   "unit": "game/mainProgram0800",
   "line": "index < 50 = one of player 0's units (a fixed test: the side comes from the index, not from who is playing)"
  },
  "6179": {
   "unit": "game/mainProgram0800",
   "line": "side 0: leave bit 5 clear"
  },
  "617B": {
   "unit": "game/mainProgram0800",
   "line": "side 1: set bit 5 of the group key"
  },
  "617D": {
   "unit": "game/mainProgram0800",
   "line": "A = number of living members of that group"
  },
  "6180": {
   "unit": "game/mainProgram0800",
   "line": "two digits?"
  },
  "6182": {
   "unit": "game/mainProgram0800",
   "line": "yes: no padding"
  },
  "6184": {
   "unit": "game/mainProgram0800",
   "line": "keep the count"
  },
  "6185": {
   "unit": "game/mainProgram0800",
   "line": "$A0 = space"
  },
  "6187": {
   "unit": "game/mainProgram0800",
   "line": "right-align single-digit counts"
  },
  "618A": {
   "unit": "game/mainProgram0800",
   "line": "count back"
  },
  "618B": {
   "unit": "game/mainProgram0800",
   "line": "high byte of the value to print"
  },
  "618D": {
   "unit": "game/mainProgram0800",
   "line": "print the member count"
  },
  "6190": {
   "unit": "game/mainProgram0800",
   "line": "next row"
  },
  "6193": {
   "unit": "game/mainProgram0800",
   "line": "next group"
  },
  "6195": {
   "unit": "game/mainProgram0800",
   "line": "..."
  },
  "6197": {
   "unit": "game/mainProgram0800",
   "line": "seven groups"
  },
  "6199": {
   "unit": "game/mainProgram0800",
   "line": "loop"
  },
  "619B": {
   "unit": "game/mainProgram0800",
   "line": "$CAB2 = ' (EXIT)' as the eighth row"
  },
  "619D": {
   "unit": "game/mainProgram0800",
   "line": "high byte"
  },
  "619F": {
   "unit": "game/mainProgram0800",
   "line": "print it"
  },
  "61A2": {
   "unit": "game/mainProgram0800",
   "line": "screen row 13"
  },
  "61A4": {
   "unit": "game/mainProgram0800",
   "line": "the list starts on row 13 of the info panel"
  },
  "61A7": {
   "unit": "game/mainProgram0800",
   "line": "8"
  },
  "61A9": {
   "unit": "game/mainProgram0800",
   "line": "7 groups + (EXIT)"
  },
  "61AC": {
   "unit": "game/mainProgram0800",
   "line": "$FF"
  },
  "61AE": {
   "unit": "game/mainProgram0800",
   "line": "$9207 is written here and at $639B but never read anywhere - dead store"
  },
  "61B1": {
   "unit": "game/mainProgram0800",
   "line": "the joining unit"
  },
  "61B4": {
   "unit": "game/mainProgram0800",
   "line": "$FB54 flags"
  },
  "61B7": {
   "unit": "game/mainProgram0800",
   "line": "keep only the side bit"
  },
  "61B9": {
   "unit": "game/mainProgram0800",
   "line": "menuLoopMode 0/$20: the loop previews the group the current row stands for"
  },
  "61BC": {
   "unit": "game/mainProgram0800",
   "line": "run the selector without the unit-idle watch"
  },
  "61BF": {
   "unit": "game/mainProgram0800",
   "line": "the selected row = the group number (0-6), 7 = (EXIT)"
  },
  "61C2": {
   "unit": "game/mainProgram0800",
   "line": "(EXIT)?"
  },
  "61C4": {
   "unit": "game/mainProgram0800",
   "line": "yes: nothing to do"
  },
  "61C6": {
   "unit": "game/mainProgram0800",
   "line": "queue $88 unit,group; C = 1 when the unit is too far from the group"
  },
  "61C9": {
   "unit": "game/mainProgram0800",
   "line": "joined"
  },
  "61CB": {
   "unit": "game/mainProgram0800",
   "line": "TOO FAR! was shown: redraw the list and ask again"
  },
  "61CE": {
   "unit": "game/mainProgram0800",
   "line": "back to the unit menu"
  },
  "61CF": {
   "unit": "game/mainProgram0800",
   "line": "0",
   "routine": [
    "runGroupOptionsMenu - Group branch of handleOwnUnitClick. It takes the group key from the clicked",
    "unit's flags, highlights every member, prints the GROUP + name header and waits: a stick deflection",
    "sends the whole group SETTING DESTINATION, a click opens the GROUP OPTIONS menu (only when the UNIT",
    "MENUS option $0BA3 bit 3 is on) offering CLOAKING, DIG or BLITZ, MEMBERSHIP, FORMATION, DIRECT UNIT",
    "and (EXIT). The chosen item either queues a group command ($83/$85/$94/$96/$A1/$A2, argument = the",
    "group key), opens the group editor or the formation sub-menu, or hands the unit to",
    "runUnitOptionsMenu.",
    "In:  selectedUnit $90F8, unit arrays $F898/$F8FC/$F960/$FB54, joyDirection zp_5D, gameTypeOptions",
    "     $0BA3 bit 3",
    "Out: selectedGroupKey/highlightedGroupKey = group key, highlightedUnit = $FF, uiLevel = 2,",
    "     menuLoopMode = 1, cmdParam0 = group key with one group command queued, cursorTargetMode zp_BB",
    "     set for the editor; ends with clearGroupHighlight and exitUnitMenu",
    "Called from: handleOwnUnitClick ($5E21)"
   ]
  },
  "61D1": {
   "unit": "game/mainProgram0800",
   "line": "ASCII translation on"
  },
  "61D3": {
   "unit": "game/mainProgram0800",
   "line": "no automatic centring"
  },
  "61D6": {
   "unit": "game/mainProgram0800",
   "line": "blank with glyph 0"
  },
  "61D8": {
   "unit": "game/mainProgram0800",
   "line": "the clicked unit"
  },
  "61DB": {
   "unit": "game/mainProgram0800",
   "line": "$FB54 flags"
  },
  "61DE": {
   "unit": "game/mainProgram0800",
   "line": "group key = group number (bits 2-4) plus the side bit 5"
  },
  "61E0": {
   "unit": "game/mainProgram0800",
   "line": "this is the group being commanded"
  },
  "61E3": {
   "unit": "game/mainProgram0800",
   "line": "and the group the viewport highlights"
  },
  "61E6": {
   "unit": "game/mainProgram0800",
   "line": "1"
  },
  "61E8": {
   "unit": "game/mainProgram0800",
   "line": "menuLoopMode 1 = animate the path marker, do not preview groups"
  },
  "61EB": {
   "unit": "game/mainProgram0800",
   "line": "$FF"
  },
  "61ED": {
   "unit": "game/mainProgram0800",
   "line": "no single-unit highlight - the whole group is marked instead"
  },
  "61F0": {
   "unit": "game/mainProgram0800",
   "line": "2"
  },
  "61F2": {
   "unit": "game/mainProgram0800",
   "line": "uiLevel 2 = group"
  },
  "61F5": {
   "unit": "game/mainProgram0800",
   "line": "square cell cursor"
  },
  "61F8": {
   "unit": "game/mainProgram0800",
   "line": "repaint the viewport with the group highlighted"
  },
  "61FB": {
   "unit": "game/mainProgram0800",
   "line": "colour 4 = group level"
  },
  "61FD": {
   "unit": "game/mainProgram0800",
   "line": "ink"
  },
  "61FF": {
   "unit": "game/mainProgram0800",
   "line": "pad"
  },
  "6201": {
   "unit": "game/mainProgram0800",
   "line": "clear the info panel"
  },
  "6204": {
   "unit": "game/mainProgram0800",
   "line": "screen row 15"
  },
  "6206": {
   "unit": "game/mainProgram0800",
   "line": "heading row (printGroupTitle sets the column)"
  },
  "6208": {
   "unit": "game/mainProgram0800",
   "line": "print 'GROUP' and the group's name"
  },
  "620B": {
   "unit": "game/mainProgram0800",
   "line": "the clicked unit...",
   "block": [
    "Wait for the player: a stick deflection means 'move the whole group', a click opens the",
    "GROUP OPTIONS menu. The path marker keeps animating meanwhile."
   ]
  },
  "620E": {
   "unit": "game/mainProgram0800",
   "line": "...keeps the info panel"
  },
  "6211": {
   "unit": "game/mainProgram0800",
   "line": "one frame of the battle"
  },
  "6214": {
   "unit": "game/mainProgram0800",
   "line": "walk the path marker along the group's route"
  },
  "6217": {
   "unit": "game/mainProgram0800",
   "line": "joystick nibble"
  },
  "6219": {
   "unit": "game/mainProgram0800",
   "line": "centred?"
  },
  "621B": {
   "unit": "game/mainProgram0800",
   "line": "centred: look for a click"
  },
  "621D": {
   "unit": "game/mainProgram0800",
   "line": "deflected: first let any pending re-position orders be applied"
  },
  "6220": {
   "unit": "game/mainProgram0800",
   "line": "then run SETTING / DESTINATION for the whole group (uiLevel 2 makes it command $81)"
  },
  "6223": {
   "unit": "game/mainProgram0800",
   "line": "done"
  },
  "6226": {
   "unit": "game/mainProgram0800",
   "line": "fresh fire-button press?"
  },
  "6229": {
   "unit": "game/mainProgram0800",
   "line": "clicked: open the GROUP OPTIONS menu"
  },
  "622B": {
   "unit": "game/mainProgram0800",
   "line": "may this UI keep running?"
  },
  "622E": {
   "unit": "game/mainProgram0800",
   "line": "yes: keep waiting"
  },
  "6230": {
   "unit": "game/mainProgram0800",
   "line": "aborted"
  },
  "6233": {
   "unit": "game/mainProgram0800",
   "line": "game type and option bits"
  },
  "6236": {
   "unit": "game/mainProgram0800",
   "line": "bit 3 = the UNIT MENUS option"
  },
  "6238": {
   "unit": "game/mainProgram0800",
   "line": "option off: no group menu in this scenario"
  },
  "623A": {
   "unit": "game/mainProgram0800",
   "line": "0"
  },
  "623C": {
   "unit": "game/mainProgram0800",
   "line": "start on the first row"
  },
  "623F": {
   "unit": "game/mainProgram0800",
   "line": "colour 4",
   "block": [
    "Build the GROUP OPTIONS list. Re-entered from $62B1 when the clicked unit's idle flag",
    "changed. Same first two items as the unit menu, then the group-only items."
   ]
  },
  "6241": {
   "unit": "game/mainProgram0800",
   "line": "ink"
  },
  "6243": {
   "unit": "game/mainProgram0800",
   "line": "pad"
  },
  "6245": {
   "unit": "game/mainProgram0800",
   "line": "clear the info panel"
  },
  "6248": {
   "unit": "game/mainProgram0800",
   "line": "print 'GROUP' at column 4"
  },
  "624B": {
   "unit": "game/mainProgram0800",
   "line": "$CB13 = '   OPTIONS' + CR + CR"
  },
  "624D": {
   "unit": "game/mainProgram0800",
   "line": "high byte"
  },
  "624F": {
   "unit": "game/mainProgram0800",
   "line": "print the second heading line"
  },
  "6252": {
   "unit": "game/mainProgram0800",
   "line": "leftover from the unit-menu version: Y is reloaded at $625A (dead)"
  },
  "6255": {
   "unit": "game/mainProgram0800",
   "line": "0"
  },
  "6257": {
   "unit": "game/mainProgram0800",
   "line": "empty item list"
  },
  "625A": {
   "unit": "game/mainProgram0800",
   "line": "the clicked unit stands for the whole group"
  },
  "625D": {
   "unit": "game/mainProgram0800",
   "line": "item id 2 = CLOAKING ON"
  },
  "625F": {
   "unit": "game/mainProgram0800",
   "line": "$F898 bit 6 = 'cloaking ordered'"
  },
  "6262": {
   "unit": "game/mainProgram0800",
   "line": "test it"
  },
  "6264": {
   "unit": "game/mainProgram0800",
   "line": "not cloaked: CLOAKING ON"
  },
  "6266": {
   "unit": "game/mainProgram0800",
   "line": "item id 3 = NO CLOAKING"
  },
  "6268": {
   "unit": "game/mainProgram0800",
   "line": "append it"
  },
  "626B": {
   "unit": "game/mainProgram0800",
   "line": "unit index"
  },
  "626E": {
   "unit": "game/mainProgram0800",
   "line": "$FB54 flags"
  },
  "6271": {
   "unit": "game/mainProgram0800",
   "line": "keep the snapshot nonzero"
  },
  "6273": {
   "unit": "game/mainProgram0800",
   "line": "patch menuIdleSnapshot+1 ($602A) exactly as the unit menu does"
  },
  "6276": {
   "unit": "game/mainProgram0800",
   "line": "bit 7 clear = moving: offer the blitz items"
  },
  "6278": {
   "unit": "game/mainProgram0800",
   "line": "item id 17 = DIG OUT"
  },
  "627A": {
   "unit": "game/mainProgram0800",
   "line": "$F960 bits 5-7 = dug in / digging"
  },
  "627D": {
   "unit": "game/mainProgram0800",
   "line": "isolate them"
  },
  "627F": {
   "unit": "game/mainProgram0800",
   "line": "already digging: DIG OUT"
  },
  "6281": {
   "unit": "game/mainProgram0800",
   "line": "item id 18 = DIG IN"
  },
  "6282": {
   "unit": "game/mainProgram0800",
   "line": "always taken"
  },
  "6284": {
   "unit": "game/mainProgram0800",
   "line": "item id 10 = SET BLITZ"
  },
  "6286": {
   "unit": "game/mainProgram0800",
   "line": "$F8FC bit 6 = 'blitz ordered'"
  },
  "6289": {
   "unit": "game/mainProgram0800",
   "line": "test it"
  },
  "628B": {
   "unit": "game/mainProgram0800",
   "line": "blitz off: SET BLITZ"
  },
  "628D": {
   "unit": "game/mainProgram0800",
   "line": "item id 11 = BLITZ OFF"
  },
  "628E": {
   "unit": "game/mainProgram0800",
   "line": "append the dig/blitz item"
  },
  "6291": {
   "unit": "game/mainProgram0800",
   "line": "item id 6 = MEMBERSHIP"
  },
  "6293": {
   "unit": "game/mainProgram0800",
   "line": "append it"
  },
  "6296": {
   "unit": "game/mainProgram0800",
   "line": "item id 0 = FORMATION"
  },
  "6298": {
   "unit": "game/mainProgram0800",
   "line": "append it"
  },
  "629B": {
   "unit": "game/mainProgram0800",
   "line": "item id 8 = DIRECT UNIT"
  },
  "629D": {
   "unit": "game/mainProgram0800",
   "line": "append it"
  },
  "62A0": {
   "unit": "game/mainProgram0800",
   "line": "item id 12 = (EXIT)"
  },
  "62A2": {
   "unit": "game/mainProgram0800",
   "line": "append it"
  },
  "62A5": {
   "unit": "game/mainProgram0800",
   "line": "screen row 15"
  },
  "62A7": {
   "unit": "game/mainProgram0800",
   "line": "the list starts on row 15"
  },
  "62AA": {
   "unit": "game/mainProgram0800",
   "line": "run the selector: A = item id, Y = row (or $80)"
  },
  "62AD": {
   "unit": "game/mainProgram0800",
   "line": "$80 = the unit's idle flag changed"
  },
  "62AF": {
   "unit": "game/mainProgram0800",
   "line": "no: act on the item"
  },
  "62B1": {
   "unit": "game/mainProgram0800",
   "line": "yes: rebuild (DIG and BLITZ swap places)"
  },
  "62B4": {
   "unit": "game/mainProgram0800",
   "line": "keep the chosen item id",
   "block": [
    "Dispatch on the chosen item id. All the command branches end at $62D7, which supplies the",
    "group key as the command's argument."
   ]
  },
  "62B7": {
   "unit": "game/mainProgram0800",
   "line": "dead load, as in the unit menu"
  },
  "62BA": {
   "unit": "game/mainProgram0800",
   "line": "the chosen item id"
  },
  "62BD": {
   "unit": "game/mainProgram0800",
   "line": "CLOAKING ON?"
  },
  "62BF": {
   "unit": "game/mainProgram0800",
   "line": "no"
  },
  "62C1": {
   "unit": "game/mainProgram0800",
   "line": "command $83 = cloak on (2 bytes: group key)"
  },
  "62C3": {
   "unit": "game/mainProgram0800",
   "line": "always taken"
  },
  "62C5": {
   "unit": "game/mainProgram0800",
   "line": "NO CLOAKING?"
  },
  "62C7": {
   "unit": "game/mainProgram0800",
   "line": "no"
  },
  "62C9": {
   "unit": "game/mainProgram0800",
   "line": "command $85 = cloak off (2 bytes: group key)"
  },
  "62CB": {
   "unit": "game/mainProgram0800",
   "line": "the clicked unit"
  },
  "62CE": {
   "unit": "game/mainProgram0800",
   "line": "flip only its local cloak bit..."
  },
  "62D1": {
   "unit": "game/mainProgram0800",
   "line": "...bit 6 of $F898..."
  },
  "62D3": {
   "unit": "game/mainProgram0800",
   "line": "...so the menu shows the new state at once (the handler does the whole group)"
  },
  "62D6": {
   "unit": "game/mainProgram0800",
   "line": "command byte back into A"
  },
  "62D7": {
   "unit": "game/mainProgram0800",
   "line": "keep the command byte"
  },
  "62D8": {
   "unit": "game/mainProgram0800",
   "line": "the group key..."
  },
  "62DB": {
   "unit": "game/mainProgram0800",
   "line": "...is the single argument of every group command"
  },
  "62DD": {
   "unit": "game/mainProgram0800",
   "line": "command byte back"
  },
  "62DE": {
   "unit": "game/mainProgram0800",
   "line": "queue 'command, group key'"
  },
  "62E1": {
   "unit": "game/mainProgram0800",
   "line": "done"
  },
  "62E4": {
   "unit": "game/mainProgram0800",
   "line": "MEMBERSHIP?"
  },
  "62E6": {
   "unit": "game/mainProgram0800",
   "line": "no"
  },
  "62E8": {
   "unit": "game/mainProgram0800",
   "line": "0"
  },
  "62EA": {
   "unit": "game/mainProgram0800",
   "line": "zp_BB >= 0 selects membership mode"
  },
  "62EC": {
   "unit": "game/mainProgram0800",
   "line": "run the group editor"
  },
  "62EF": {
   "unit": "game/mainProgram0800",
   "line": "done"
  },
  "62F2": {
   "unit": "game/mainProgram0800",
   "line": "DIRECT UNIT?"
  },
  "62F4": {
   "unit": "game/mainProgram0800",
   "line": "no"
  },
  "62F6": {
   "unit": "game/mainProgram0800",
   "line": "hand the clicked unit to the single-unit menu (which ends in exitUnitMenu)"
  },
  "62F9": {
   "unit": "game/mainProgram0800",
   "line": "FORMATION? (item id 0)"
  },
  "62FB": {
   "unit": "game/mainProgram0800",
   "line": "no"
  },
  "62FD": {
   "unit": "game/mainProgram0800",
   "line": "SWEEP LEFT / SWEEP RIGHT / REVERSE / CUSTOM / (EXIT); Y = the chosen row"
  },
  "6300": {
   "unit": "game/mainProgram0800",
   "line": "row 3 = CUSTOM"
  },
  "6302": {
   "unit": "game/mainProgram0800",
   "line": "the three canned formations are sent by the sub-menu itself (command $A3)"
  },
  "6304": {
   "unit": "game/mainProgram0800",
   "line": "$80"
  },
  "6306": {
   "unit": "game/mainProgram0800",
   "line": "zp_BB bit 7 selects custom-formation mode"
  },
  "6308": {
   "unit": "game/mainProgram0800",
   "line": "always taken: run the editor in formation mode"
  },
  "630A": {
   "unit": "game/mainProgram0800",
   "line": "SET BLITZ?"
  },
  "630C": {
   "unit": "game/mainProgram0800",
   "line": "no"
  },
  "630E": {
   "unit": "game/mainProgram0800",
   "line": "command $94 = blitz on (2 bytes: group key)"
  },
  "6310": {
   "unit": "game/mainProgram0800",
   "line": "always taken"
  },
  "6312": {
   "unit": "game/mainProgram0800",
   "line": "BLITZ OFF?"
  },
  "6314": {
   "unit": "game/mainProgram0800",
   "line": "no"
  },
  "6316": {
   "unit": "game/mainProgram0800",
   "line": "command $96 = blitz off (2 bytes: group key)"
  },
  "6318": {
   "unit": "game/mainProgram0800",
   "line": "the clicked unit"
  },
  "631B": {
   "unit": "game/mainProgram0800",
   "line": "flip its local blitz bit..."
  },
  "631E": {
   "unit": "game/mainProgram0800",
   "line": "...bit 6 of $F8FC..."
  },
  "6320": {
   "unit": "game/mainProgram0800",
   "line": "...for instant feedback"
  },
  "6323": {
   "unit": "game/mainProgram0800",
   "line": "command byte back into A"
  },
  "6324": {
   "unit": "game/mainProgram0800",
   "line": "always taken"
  },
  "6326": {
   "unit": "game/mainProgram0800",
   "line": "DIG OUT?"
  },
  "6328": {
   "unit": "game/mainProgram0800",
   "line": "no"
  },
  "632A": {
   "unit": "game/mainProgram0800",
   "line": "command $A2 = dig out (2 bytes: group key)"
  },
  "632C": {
   "unit": "game/mainProgram0800",
   "line": "always taken"
  },
  "632E": {
   "unit": "game/mainProgram0800",
   "line": "DIG IN?"
  },
  "6330": {
   "unit": "game/mainProgram0800",
   "line": "anything else, including (EXIT): just close"
  },
  "6332": {
   "unit": "game/mainProgram0800",
   "line": "command $A1 = dig in (2 bytes: group key)"
  },
  "6334": {
   "unit": "game/mainProgram0800",
   "line": "always taken"
  },
  "6336": {
   "unit": "game/mainProgram0800",
   "line": "drop the group highlight and repaint the viewport"
  },
  "6339": {
   "unit": "game/mainProgram0800",
   "line": "uiLevel 0, no info-panel unit, return to the battlefield loop"
  },
  "633C": {
   "unit": "game/mainProgram0800",
   "line": "print 'GROUP' + CR at column 4",
   "routine": [
    "printGroupTitleAndName - Header of the group menu: prints GROUP (printGroupTitle) and, on the next",
    "row at column 4, the name of group (selectedGroupKey >> 2) & 7 from the 8-byte name table at $C92C,",
    "followed by a newline.",
    "In:  selectedGroupKey $9206",
    "Out: two lines printed, textCursorCol zp_3F = 4",
    "Called from: runGroupOptionsMenu ($6208)"
   ]
  },
  "633F": {
   "unit": "game/mainProgram0800",
   "line": "column 4"
  },
  "6341": {
   "unit": "game/mainProgram0800",
   "line": "indent the name under the title"
  },
  "6343": {
   "unit": "game/mainProgram0800",
   "line": "recompute the bitmap/colour pointers for the new column"
  },
  "6346": {
   "unit": "game/mainProgram0800",
   "line": "group key"
  },
  "6349": {
   "unit": "game/mainProgram0800",
   "line": "shift out the two low bits..."
  },
  "634A": {
   "unit": "game/mainProgram0800",
   "line": "..."
  },
  "634B": {
   "unit": "game/mainProgram0800",
   "line": "...leaving the group number 0-6 (the side bit is dropped)"
  },
  "634D": {
   "unit": "game/mainProgram0800",
   "line": "index for the name table"
  },
  "634E": {
   "unit": "game/mainProgram0800",
   "line": "$C92C = the seven 8-byte group names"
  },
  "6350": {
   "unit": "game/mainProgram0800",
   "line": "high byte"
  },
  "6352": {
   "unit": "game/mainProgram0800",
   "line": "print the name at $C92C + 8*group"
  },
  "6355": {
   "unit": "game/mainProgram0800",
   "line": "and move to the next row"
  },
  "6358": {
   "unit": "game/mainProgram0800",
   "line": "column 4",
   "routine": [
    "printGroupTitle - Moves the text cursor to column 4 of the info panel and prints the string GROUP",
    "($CB1F, which ends with a CR).",
    "In:  the current text window",
    "Out: one line printed, textCursorCol zp_3F = 4",
    "Called from: runGroupOptionsMenu ($6248) and printGroupTitleAndName ($633C)"
   ]
  },
  "635A": {
   "unit": "game/mainProgram0800",
   "line": "indent the title"
  },
  "635C": {
   "unit": "game/mainProgram0800",
   "line": "recompute the bitmap/colour pointers"
  },
  "635F": {
   "unit": "game/mainProgram0800",
   "line": "$CB1F = 'GROUP' (ends with CR)"
  },
  "6361": {
   "unit": "game/mainProgram0800",
   "line": "high byte"
  },
  "6363": {
   "unit": "game/mainProgram0800",
   "line": "print it and return to the caller"
  },
  "6366": {
   "unit": "game/mainProgram0800",
   "line": "$FF",
   "routine": [
    "clearGroupHighlight - Drops the viewport's group highlight and repaints the 7x5 tactical view.",
    "In:  -",
    "Out: highlightedGroupKey $9205 = $FF, viewport redrawn",
    "Called from: runGroupOptionsMenu ($6336) and runGroupEditor ($64D4)"
   ]
  },
  "6368": {
   "unit": "game/mainProgram0800",
   "line": "no group highlighted any more"
  },
  "636B": {
   "unit": "game/mainProgram0800",
   "line": "repaint the 7x5 viewport without the highlight"
  },
  "636E": {
   "unit": "game/mainProgram0800",
   "line": "colour 4 = group level",
   "routine": [
    "printSettingHeader - Header of the group editor: clears the info panel in colour 4, moves to screen",
    "row 15 and prints SETTING centred, followed by MEMBERSHIP ($CA32) when cursorTargetMode zp_BB is",
    "positive or FORMATION ($C9D2) when its bit 7 is set.",
    "In:  cursorTargetMode zp_BB",
    "Out: textColour/textPadColour = 4, two centred lines printed",
    "Called from: runGroupEditor ($63B0, and again after every hover info panel at $63F8)"
   ]
  },
  "6370": {
   "unit": "game/mainProgram0800",
   "line": "ink"
  },
  "6372": {
   "unit": "game/mainProgram0800",
   "line": "pad"
  },
  "6374": {
   "unit": "game/mainProgram0800",
   "line": "clear the info panel"
  },
  "6377": {
   "unit": "game/mainProgram0800",
   "line": "screen row 15"
  },
  "6379": {
   "unit": "game/mainProgram0800",
   "line": "position the cursor there"
  },
  "637C": {
   "unit": "game/mainProgram0800",
   "line": "print 'SETTING' centred, then a newline"
  },
  "637F": {
   "unit": "game/mainProgram0800",
   "line": "$CA32 = 'MEMBERSHIP' (entry 6 of the 16-byte option strings)"
  },
  "6381": {
   "unit": "game/mainProgram0800",
   "line": "high byte"
  },
  "6383": {
   "unit": "game/mainProgram0800",
   "line": "zp_BB: bit 7 set = custom formation mode"
  },
  "6385": {
   "unit": "game/mainProgram0800",
   "line": "membership mode: print MEMBERSHIP"
  },
  "6387": {
   "unit": "game/mainProgram0800",
   "line": "$C9D2 = 'FORMATION' (entry 0 of the 16-byte option strings)",
   "routine": [
    "printFormationCentred - Prints the word FORMATION ($C9D2) centred in the current text window; also",
    "the tail of printSettingHeader in custom-formation mode.",
    "In:  the current text window",
    "Out: one centred line printed",
    "Called from: runFormationOptionsMenu ($6602) and by fall-through from printSettingHeader"
   ]
  },
  "6389": {
   "unit": "game/mainProgram0800",
   "line": "high byte"
  },
  "638B": {
   "unit": "game/mainProgram0800",
   "line": "print the word centred in the info panel"
  },
  "638E": {
   "unit": "game/mainProgram0800",
   "line": "2",
   "routine": [
    "runGroupEditor - Interactive editor for the group in selectedGroupKey, in MEMBERSHIP mode (zp_BB >=",
    "0) or custom FORMATION mode (zp_BB bit 7 set). It halts the group with command $9B (formation mode",
    "first waits for pending re-positions), then lets the player scroll the viewport with the joystick",
    "and shows hover information for an own unit after 30 idle frames. Clicking an own unit adds it",
    "(command $88, ADDED / TOO FAR!) or removes it (command $89, REMOVED) in membership mode and asks for",
    "a NEW POSITION (command $98) in formation mode; the command centre is always refused with sound 3.",
    "Clicking empty ground or an enemy prints FINISHED and ends the editor. Only the part up to $6467",
    "belongs to this chunk; the routine continues to $64D9.",
    "In:  selectedGroupKey $9206, cursorTargetMode zp_BB (mode), joyDirection zp_5D, joyRepeatTimer zp_6C,",
    "     inputIdleFrames $90EE, comcenUnit $9236, unitDisplayFlagsTable $FB54 and the side-branch opcode",
    "     at groupEditorOwnSideBranch ($63E2)",
    "Out: selectedUnit $90F8 = the unit under the cursor (bit 7 set = empty cell or enemy), uiLevel = 2,",
    "     infoPanelUnit = $FF, $9207 = $FF (dead), highlightedGroupKey, joyRepeatMask/joyHoldCounter,",
    "     inputLockoutTimer, commands $9B/$88/$89/$98 queued, viewport scrolled and redrawn",
    "Called from: the GROUP OPTIONS items MEMBERSHIP and FORMATION/CUSTOM ($62EC)"
   ]
  },
  "6390": {
   "unit": "game/mainProgram0800",
   "line": "uiLevel 2 = group"
  },
  "6393": {
   "unit": "game/mainProgram0800",
   "line": "square cell cursor"
  },
  "6396": {
   "unit": "game/mainProgram0800",
   "line": "$FF"
  },
  "6398": {
   "unit": "game/mainProgram0800",
   "line": "the info panel belongs to the editor, not to a unit"
  },
  "639B": {
   "unit": "game/mainProgram0800",
   "line": "dead store - $9207 is never read (see $61AE)"
  },
  "639E": {
   "unit": "game/mainProgram0800",
   "line": "the group being edited"
  },
  "63A1": {
   "unit": "game/mainProgram0800",
   "line": "highlight all of its members"
  },
  "63A4": {
   "unit": "game/mainProgram0800",
   "line": "repaint the viewport"
  },
  "63A7": {
   "unit": "game/mainProgram0800",
   "line": "0"
  },
  "63A9": {
   "unit": "game/mainProgram0800",
   "line": "ASCII translation on"
  },
  "63AB": {
   "unit": "game/mainProgram0800",
   "line": "no automatic centring"
  },
  "63AE": {
   "unit": "game/mainProgram0800",
   "line": "blank with glyph 0"
  },
  "63B0": {
   "unit": "game/mainProgram0800",
   "line": "'SETTING' + MEMBERSHIP or FORMATION"
  },
  "63B3": {
   "unit": "game/mainProgram0800",
   "line": "zp_BB: bit 7 set = custom formation mode"
  },
  "63B5": {
   "unit": "game/mainProgram0800",
   "line": "membership mode"
  },
  "63B7": {
   "unit": "game/mainProgram0800",
   "line": "formation mode: wait until earlier re-position orders have been applied"
  },
  "63BA": {
   "unit": "game/mainProgram0800",
   "line": "command $9B halts every member so the group stays put while it is edited"
  },
  "63BD": {
   "unit": "game/mainProgram0800",
   "line": "formation mode starts straight away with the unit the player clicked on"
  },
  "63C0": {
   "unit": "game/mainProgram0800",
   "line": "membership mode: halt the group as well"
  },
  "63C3": {
   "unit": "game/mainProgram0800",
   "line": "120 frames"
  },
  "63C5": {
   "unit": "game/mainProgram0800",
   "line": "let the halt take effect; returns early on a click or a stick deflection"
  },
  "63C8": {
   "unit": "game/mainProgram0800",
   "line": "one frame of the battle",
   "block": [
    "Main editor loop: one game frame per pass, hover information for the unit under the",
    "cursor, click handling and joystick scrolling of the viewport."
   ]
  },
  "63CB": {
   "unit": "game/mainProgram0800",
   "line": "may this UI keep running?"
  },
  "63CE": {
   "unit": "game/mainProgram0800",
   "line": "yes"
  },
  "63D0": {
   "unit": "game/mainProgram0800",
   "line": "SPACE / screen change / game over: leave the editor"
  },
  "63D3": {
   "unit": "game/mainProgram0800",
   "line": "joystick nibble"
  },
  "63D5": {
   "unit": "game/mainProgram0800",
   "line": "centred?"
  },
  "63D7": {
   "unit": "game/mainProgram0800",
   "line": "deflected: scroll the viewport"
  },
  "63D9": {
   "unit": "game/mainProgram0800",
   "line": "map byte under the cursor = the centre cell of the 7x5 view"
  },
  "63DC": {
   "unit": "game/mainProgram0800",
   "line": "flip bit 7: a unit cell ($80|index) becomes positive, plain terrain becomes negative"
  },
  "63DE": {
   "unit": "game/mainProgram0800",
   "line": "empty cell: nothing selectable"
  },
  "63E0": {
   "unit": "game/mainProgram0800",
   "line": "unit index < 50 = side 0"
  },
  "63E2": {
   "unit": "game/mainProgram0800",
   "line": "opcode byte patched by patchOwnSideBranches ($7BCF): $90 BCC for side 0, $B0 BCS for side 1, so the branch is taken when the unit is ours"
  },
  "63E4": {
   "unit": "game/mainProgram0800",
   "line": "an enemy unit counts as 'nothing under the cursor'"
  },
  "63E6": {
   "unit": "game/mainProgram0800",
   "line": "bit 7 set = empty cell or enemy unit"
  },
  "63E9": {
   "unit": "game/mainProgram0800",
   "line": "frames since the player last touched the controls"
  },
  "63EC": {
   "unit": "game/mainProgram0800",
   "line": "30 frames"
  },
  "63EE": {
   "unit": "game/mainProgram0800",
   "line": "still moving: no hover info"
  },
  "63F0": {
   "unit": "game/mainProgram0800",
   "line": "the cell under the cursor"
  },
  "63F3": {
   "unit": "game/mainProgram0800",
   "line": "only own units get an info panel"
  },
  "63F5": {
   "unit": "game/mainProgram0800",
   "line": "show its status while the player hovers"
  },
  "63F8": {
   "unit": "game/mainProgram0800",
   "line": "then restore the editor's own heading"
  },
  "63FB": {
   "unit": "game/mainProgram0800",
   "line": "fresh fire-button press?"
  },
  "63FE": {
   "unit": "game/mainProgram0800",
   "line": "clicked: act on the cell"
  },
  "6400": {
   "unit": "game/mainProgram0800",
   "line": "may this UI keep running?"
  },
  "6403": {
   "unit": "game/mainProgram0800",
   "line": "yes"
  },
  "6405": {
   "unit": "game/mainProgram0800",
   "line": "aborted: leave the editor"
  },
  "6408": {
   "unit": "game/mainProgram0800",
   "line": "auto-repeat delay still running?",
   "block": [
    "Scroll the viewport one cell per auto-repeat step. $6418-$6434 is an inline copy of",
    "setJoystickRepeatDelay ($0D49) - the same fourteen instructions, not a JSR."
   ]
  },
  "640A": {
   "unit": "game/mainProgram0800",
   "line": "yes: next frame"
  },
  "640C": {
   "unit": "game/mainProgram0800",
   "line": "joystick nibble as the table index"
  },
  "640E": {
   "unit": "game/mainProgram0800",
   "line": "0"
  },
  "6410": {
   "unit": "game/mainProgram0800",
   "line": "cancel the input lockout: scrolling must respond at once"
  },
  "6413": {
   "unit": "game/mainProgram0800",
   "line": "direction code 0-7 (N,S,E,W,NW,NE,SE,SW), $FF when centred or invalid"
  },
  "6416": {
   "unit": "game/mainProgram0800",
   "line": "no usable direction"
  },
  "6418": {
   "unit": "game/mainProgram0800",
   "line": "16 frames before the first repeat"
  },
  "641A": {
   "unit": "game/mainProgram0800",
   "line": "keep the direction code"
  },
  "641B": {
   "unit": "game/mainProgram0800",
   "line": "count how long the stick has been held"
  },
  "641E": {
   "unit": "game/mainProgram0800",
   "line": "..."
  },
  "6421": {
   "unit": "game/mainProgram0800",
   "line": "the IRQ clears this mask while the stick is centred, so a new press restarts the count at 0"
  },
  "6424": {
   "unit": "game/mainProgram0800",
   "line": "store the masked counter"
  },
  "6427": {
   "unit": "game/mainProgram0800",
   "line": "first step after centring?"
  },
  "6429": {
   "unit": "game/mainProgram0800",
   "line": "yes: keep the 16-frame delay"
  },
  "642B": {
   "unit": "game/mainProgram0800",
   "line": "held: repeat every 6 frames"
  },
  "642D": {
   "unit": "game/mainProgram0800",
   "line": "arm the repeat timer"
  },
  "642F": {
   "unit": "game/mainProgram0800",
   "line": "$7F"
  },
  "6431": {
   "unit": "game/mainProgram0800",
   "line": "let the hold counter grow again"
  },
  "6434": {
   "unit": "game/mainProgram0800",
   "line": "direction code back"
  },
  "6435": {
   "unit": "game/mainProgram0800",
   "line": "scroll the viewport one cell in that direction"
  },
  "6438": {
   "unit": "game/mainProgram0800",
   "line": "next frame"
  },
  "643B": {
   "unit": "game/mainProgram0800",
   "line": "colour 4",
   "block": [
    "The player clicked: act on whatever the cursor stands on. Empty ground or an enemy",
    "finishes the editor, the command centre is refused, and any other own unit is added,",
    "removed or re-positioned by the code that follows this chunk."
   ]
  },
  "643D": {
   "unit": "game/mainProgram0800",
   "line": "ink"
  },
  "643F": {
   "unit": "game/mainProgram0800",
   "line": "pad"
  },
  "6441": {
   "unit": "game/mainProgram0800",
   "line": "clear the info panel for the result message"
  },
  "6444": {
   "unit": "game/mainProgram0800",
   "line": "screen row 16"
  },
  "6446": {
   "unit": "game/mainProgram0800",
   "line": "position the cursor there"
  },
  "6449": {
   "unit": "game/mainProgram0800",
   "line": "the cell under the cursor"
  },
  "644C": {
   "unit": "game/mainProgram0800",
   "line": "one of our own units: act on it"
  },
  "644E": {
   "unit": "game/mainProgram0800",
   "line": "$CB47 = 'FINISHED'"
  },
  "6450": {
   "unit": "game/mainProgram0800",
   "line": "high byte"
  },
  "6452": {
   "unit": "game/mainProgram0800",
   "line": "print it centred"
  },
  "6455": {
   "unit": "game/mainProgram0800",
   "line": "60 frames"
  },
  "6457": {
   "unit": "game/mainProgram0800",
   "line": "show it briefly"
  },
  "645A": {
   "unit": "game/mainProgram0800",
   "line": "clicking empty ground or an enemy ends the editor"
  },
  "645D": {
   "unit": "game/mainProgram0800",
   "line": "is it the player's command centre (unit 49 or 99)?"
  },
  "6460": {
   "unit": "game/mainProgram0800",
   "line": "no: an ordinary unit"
  },
  "6462": {
   "unit": "game/mainProgram0800",
   "line": "sound 3 = rejected"
  },
  "6464": {
   "unit": "game/mainProgram0800",
   "line": "play it"
  },
  "6467": {
   "unit": "game/mainProgram0800",
   "line": "the comcen can never be a group member: ignore the click and go round again"
  }
 },
 "dataTypes": {
  "5E14": [
   "byte",
   3
  ],
  "612E": [
   "byte",
   1
  ]
 },
 "zpComments": {
  "22": "map column of point A for distanceSquared ($3870)/cellDistance ($E82A) and the current column of an area scan; also reused as a plain loop counter, e.g. the group index 0-6 while runJoinGroupMenu ($6160) prints the group list",
  "BB": "target cursor mode: 0 = move order, >0 = range-limited attack cursor, <0 = free cell pick reported in pickedCellCol/Row; the group menus also use it as the group-editor mode (0 = MEMBERSHIP, $80 = custom FORMATION)"
 }
}