{
 "chunk": "820B",
 "unit": "game/mapGenerator6F00",
 "unitLabels": {
  "game/mapGenerator6F00": {
   "87CE": "msgWeWonByAKnockout",
   "879F": "msgWeWonOnPointsTail"
  }
 },
 "notes": {
  "820B": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "beginGameTypeSelection - one-off prologue of the game-type selection screen, run only by the side that",
    "picks the scenario (side 0).  Throws away any queued status message, forces the map screen, tells",
    "showToggleStateMessage that the '*' toggle is OFF-with-no-message, installs 'CUSTOM OFF' ($EFD8) as",
    "message slot $1E and falls into runGameTypeMenu.",
    "In:  nothing (message slot $1E and the patch operand at $868D are the things it sets up)",
    "Out: D_90FB = 0, $868D = 0 (off-state persistent message id), message slot $1E -> $EFD8",
    "Called from: startGameSession $79A1 (side 0 only; side 1 waits with message $1A instead)"
   ],
   "line": "drop everything still queued in the status-message ring before the setup screen appears"
  },
  "820E": {
   "unit": "game/mapGenerator6F00",
   "line": "0 = the normal map/battlefield screen (not a comcen panel)"
  },
  "8210": {
   "unit": "game/mapGenerator6F00",
   "line": "currentScreen $90FB = 0"
  },
  "8213": {
   "unit": "game/mapGenerator6F00",
   "line": "patch the LDX operand at $868D: with the toggle OFF show persistent message id 0 (none)"
  },
  "8216": {
   "unit": "game/mapGenerator6F00",
   "line": "X = message slot $1E, the reusable 'toggle state' slot"
  },
  "8218": {
   "unit": "game/mapGenerator6F00",
   "line": "low byte of 'CUSTOM OFF' at $EFD8 (in the comm module's $EC00 tail)"
  },
  "821A": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $EFD8"
  },
  "821C": {
   "unit": "game/mapGenerator6F00",
   "line": "register $EFD8 as message $1E, then fall into runGameTypeMenu"
  },
  "821F": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "runGameTypeMenu - the GAME TYPE: selection screen.  Aims the ON/OFF patch at the word inside 'CUSTOM",
    "OFF', derives the '*' toggle ($92F3 bit 7) from gameTypeOptions bit 6, redraws the screen, lists the",
    "seven scenario names and runs the selector.  A new scenario takes its options byte from",
    "gameTypeOptionsByMenuItem ($78CA); re-choosing the same scenario under CUSTOM rules keeps the byte the",
    "player already tuned.  With CUSTOM rules the two OFF/ON sub-menus 'UNIT MENUS' (bit 3) and 'DAMAGE'",
    "(bit 4) follow, then it falls into runMapTypeMenu.",
    "In:  D_0BA3 gameTypeOptions, D_0BA5 isSoloTrainer, D_92F3, joystick/menu input",
    "Out: D_0BA3, D_92F3, D_91D4 = 7, D_91D5, zp_3D/zp_42 = 9, zp_B1 = $BF on the custom path;",
    "     self-modifies $829E (previous game type), $8319 (chosen game type) and $869A/$869B",
    "Called from: fall-through from beginGameTypeSelection.  The JMP $2E07 listed in XREF is the main",
    "     program jumping to overlay variant B's routine at this address, not this code."
   ],
   "block": [
    "Aim the '*' toggle machinery at the 'CUSTOM OFF' message and seed the toggle from the options byte."
   ],
   "line": "low byte of $EFDF - the 'OFF' inside 'CUSTOM OFF'"
  },
  "8221": {
   "unit": "game/mapGenerator6F00",
   "line": "patch the STA operand at $869A: showToggleStateMessage writes ON/OFF there"
  },
  "8224": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $EFDF"
  },
  "8226": {
   "unit": "game/mapGenerator6F00",
   "line": "patch $869B, the high half of that STA operand"
  },
  "8229": {
   "unit": "game/mapGenerator6F00",
   "line": "gameTypeOptions $0BA3"
  },
  "822C": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 6 = CUSTOM rules"
  },
  "822E": {
   "unit": "game/mapGenerator6F00",
   "line": "shift bit 6 up into bit 7"
  },
  "822F": {
   "unit": "game/mapGenerator6F00",
   "line": "setupToggleFlag $92F3 bit 7 = '*' toggle; here it means 'CUSTOM rules on'"
  },
  "8232": {
   "unit": "game/mapGenerator6F00",
   "line": "grey the bitmap and redraw the whole game screen frame"
  },
  "8235": {
   "unit": "game/mapGenerator6F00",
   "line": "blank the 20x20 character overview window on the left"
  },
  "8238": {
   "unit": "game/mapGenerator6F00",
   "line": "text colour code 9 (brown)"
  },
  "823A": {
   "unit": "game/mapGenerator6F00",
   "line": "colour byte written for every printed character cell"
  },
  "823C": {
   "unit": "game/mapGenerator6F00",
   "line": "same colour for the blanks that pad a centred string"
  },
  "823E": {
   "unit": "game/mapGenerator6F00",
   "line": "no unit selected, viewport parked off the map so it stays blank"
  },
  "8241": {
   "unit": "game/mapGenerator6F00",
   "line": "text cursor row 12"
  },
  "8243": {
   "unit": "game/mapGenerator6F00",
   "line": "clear the info panel in colour 8 and put the cursor on row 12"
  },
  "8246": {
   "unit": "game/mapGenerator6F00",
   "line": "isSoloTrainer $0BA5, bit 7 = PRACTICE WITH SOLO TRAINER"
  },
  "8249": {
   "unit": "game/mapGenerator6F00",
   "line": "branch when this is a modem game"
  },
  "824B": {
   "unit": "game/mapGenerator6F00",
   "line": "solo game: flip the beginner/standard battle display and queue the 'F 1 FOR ...' prompt"
  },
  "824E": {
   "unit": "game/mapGenerator6F00",
   "line": "the CUSTOM toggle just derived from $0BA3 bit 6"
  },
  "8251": {
   "unit": "game/mapGenerator6F00",
   "line": "branch when CUSTOM rules are off - nothing to announce"
  },
  "8253": {
   "unit": "game/mapGenerator6F00",
   "line": "show 'CUSTOM ON' as the persistent status message"
  },
  "8256": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "Validate the stored game type (0-6), preselect it and print the seven scenario names."
   ],
   "line": "gameTypeOptions"
  },
  "8259": {
   "unit": "game/mapGenerator6F00",
   "line": "bits 0-2 = game type"
  },
  "825B": {
   "unit": "game/mapGenerator6F00",
   "line": "only 0-6 exist (0 SCRIMAGE .. 6 DEFENDER)"
  },
  "825D": {
   "unit": "game/mapGenerator6F00",
   "line": "branch if the stored type is valid"
  },
  "825F": {
   "unit": "game/mapGenerator6F00",
   "line": "out of range: fall back to SCRIMAGE"
  },
  "8261": {
   "unit": "game/mapGenerator6F00",
   "line": "and reset the whole options byte"
  },
  "8264": {
   "unit": "game/mapGenerator6F00",
   "line": "patch the CPY operand at $829E with the game type in force before the menu"
  },
  "8267": {
   "unit": "game/mapGenerator6F00",
   "line": "X = preselected menu row = current game type"
  },
  "8268": {
   "unit": "game/mapGenerator6F00",
   "line": "'GAME TYPE:' title at $CCBD"
  },
  "826A": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $CCBD"
  },
  "826C": {
   "unit": "game/mapGenerator6F00",
   "line": "print it centred, set the menu column and record the first item row"
  },
  "826F": {
   "unit": "game/mapGenerator6F00",
   "line": "seven scenarios"
  },
  "8271": {
   "unit": "game/mapGenerator6F00",
   "line": "menuItemCount $91D4"
  },
  "8274": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_18 also counts the print loop"
  },
  "8276": {
   "unit": "game/mapGenerator6F00",
   "line": "print the next scenario name; printStringAtPointer walks on to the following 8-byte entry"
  },
  "8279": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "printGameTypeNamesLoop - not a routine in variant A: this is the body of runGameTypeMenu's loop that",
    "prints the seven scenario names at $CCC8, one per line, counting down zp_18.  The label exists only",
    "because overlay variant B has a real routine (advanceDroneCamera) at this address.",
    "In:  zp_18 = names left, string pointer zp_A2/zp_A3 already inside the $CCC8 table",
    "Out: seven lines of text, zp_18 = 0",
    "Called from: nothing in variant A (fall-through / JMP $8280 inside runGameTypeMenu)"
   ],
   "line": "one name printed"
  },
  "827B": {
   "unit": "game/mapGenerator6F00",
   "line": "after the seventh do not add another newline"
  },
  "827D": {
   "unit": "game/mapGenerator6F00",
   "line": "next line"
  },
  "8280": {
   "unit": "game/mapGenerator6F00",
   "line": "print the next name"
  },
  "8283": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "Run the selector, then turn the chosen row into a gameTypeOptions byte."
   ],
   "line": "run the menu selector with a 10-character highlight bar; A = chosen row"
  },
  "8286": {
   "unit": "game/mapGenerator6F00",
   "line": "Y = chosen game type 0-6"
  },
  "8287": {
   "unit": "game/mapGenerator6F00",
   "line": "patch the LDY operand at $8319 so runMapTypeMenu knows which scenario was picked"
  },
  "828A": {
   "unit": "game/mapGenerator6F00",
   "line": "0 - reset the row for the next menu"
  },
  "828C": {
   "unit": "game/mapGenerator6F00",
   "line": "reset menuSelectedItem for the next menu"
  },
  "828F": {
   "unit": "game/mapGenerator6F00",
   "line": "default options byte for this scenario (gameTypeOptionsByMenuItem $78CA)"
  },
  "8292": {
   "unit": "game/mapGenerator6F00",
   "line": "test the CUSTOM toggle in $92F3"
  },
  "8295": {
   "unit": "game/mapGenerator6F00",
   "line": "branch when CUSTOM rules are on"
  },
  "8297": {
   "unit": "game/mapGenerator6F00",
   "line": "STANDARD rules: take the preset unchanged"
  },
  "829A": {
   "unit": "game/mapGenerator6F00",
   "line": "and skip the two custom sub-menus"
  },
  "829D": {
   "unit": "game/mapGenerator6F00",
   "line": "compare the chosen row with the game type in force (operand patched at $8264)"
  },
  "829F": {
   "unit": "game/mapGenerator6F00",
   "line": "a different scenario -> use the table preset in A"
  },
  "82A1": {
   "unit": "game/mapGenerator6F00",
   "line": "same scenario re-chosen -> keep the options byte the player already tuned (bits 3/4/7)"
  },
  "82A4": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "applyCustomPresetTail - not a routine in variant A: the continuation inside runGameTypeMenu that ORs",
    "the CUSTOM bit ($40) into the scenario's options byte, stores it and runs the two OFF/ON sub-menus",
    "'UNIT MENUS' (bit 3) and 'DAMAGE' (bit 4).  Variant B has a real routine",
    "(readDroneHeadingFromJoystick) at this address.",
    "In:  A = options byte to install",
    "Out: D_0BA3 with bit 6 set and bits 3/4 from the sub-menus, zp_B1 = $BF",
    "Called from: nothing in variant A (fall-through / BNE $829F)"
   ],
   "line": "bit 6 = CUSTOM rules"
  },
  "82A6": {
   "unit": "game/mapGenerator6F00",
   "line": "gameTypeOptions $0BA3"
  },
  "82A9": {
   "unit": "game/mapGenerator6F00",
   "line": "$BF - non-battle phase with bits 7 and 6 set for the setup menus"
  },
  "82AB": {
   "unit": "game/mapGenerator6F00",
   "line": "gamePhase zp_B1"
  },
  "82AD": {
   "unit": "game/mapGenerator6F00",
   "line": "X = mask $08 = UNIT MENUS"
  },
  "82AF": {
   "unit": "game/mapGenerator6F00",
   "line": "'UNIT MENUS' label at $EF9B"
  },
  "82B1": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $EF9B"
  },
  "82B3": {
   "unit": "game/mapGenerator6F00",
   "line": "OFF/ON menu for bit 3"
  },
  "82B6": {
   "unit": "game/mapGenerator6F00",
   "line": "X = mask $10 = DAMAGE"
  },
  "82B8": {
   "unit": "game/mapGenerator6F00",
   "line": "'DAMAGE' label at $EFA7"
  },
  "82BA": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $EFA7"
  },
  "82BC": {
   "unit": "game/mapGenerator6F00",
   "line": "OFF/ON menu for bit 4, then fall into runMapTypeMenu"
  },
  "82BF": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "runMapTypeMenu - second half of the setup menus: the STANDARD / CUSTOM map choice (gameTypeOptions",
    "bit 7).  Sends the finished options byte to the opponent (command $A4), loads the scenario's unit",
    "start-position template, and forces playsFirstFlag when the options changed since the last game.  A",
    "CUSTOM map jumps to the 'TYPE MAP NAME' screen; a STANDARD map takes a fresh 24-bit map seed from the",
    "shared game RNG - with the low 5 bits forced to 1 (a name ending in '=' = point-symmetric map) for",
    "every scenario except QB SNEAK and DEFENDER, which get an asymmetric seed and only when this side has",
    "1ST PLAY (otherwise the previous map is kept so the two sides can swap roles on it).",
    "In:  D_0BA3, D_0BA4 prevGameTypeOptions, D_0BA1 playsFirstFlag, zp_57-zp_59 game RNG, menu input",
    "Out: D_0BA3 bit 7, D_0BA1, D_0B95-D_0B97 mapSeed, zp_B1 = $FF, zp_73, command $A4 queued",
    "Called from: fall-through from editOptionBitOnOff / runGameTypeMenu.  The JSR $82BF at $3A30",
    "     (resolveAttack) targets overlay variant B's drawShotLineInViewport, not this code."
   ],
   "line": "hide the viewport and clear the selection state"
  },
  "82C2": {
   "unit": "game/mapGenerator6F00",
   "line": "text cursor row 14"
  },
  "82C4": {
   "unit": "game/mapGenerator6F00",
   "line": "clear the info panel, cursor to row 14"
  },
  "82C7": {
   "unit": "game/mapGenerator6F00",
   "line": "'MAP TYPE' title at $EF77"
  },
  "82C9": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $EF77"
  },
  "82CB": {
   "unit": "game/mapGenerator6F00",
   "line": "preselect row 0 = STANDARD"
  },
  "82CD": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 7 of gameTypeOptions = custom (named) map"
  },
  "82D0": {
   "unit": "game/mapGenerator6F00",
   "line": "branch when a random map is in force"
  },
  "82D2": {
   "unit": "game/mapGenerator6F00",
   "line": "preselect row 1 = CUSTOM"
  },
  "82D3": {
   "unit": "game/mapGenerator6F00",
   "line": "print the title, set the menu column, record the first item row"
  },
  "82D6": {
   "unit": "game/mapGenerator6F00",
   "line": "two items"
  },
  "82D8": {
   "unit": "game/mapGenerator6F00",
   "line": "menuItemCount $91D4"
  },
  "82DB": {
   "unit": "game/mapGenerator6F00",
   "line": "'STANDARD' at $CC11"
  },
  "82DD": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $CC11"
  },
  "82DF": {
   "unit": "game/mapGenerator6F00",
   "line": "print item 0"
  },
  "82E2": {
   "unit": "game/mapGenerator6F00",
   "line": "next line"
  },
  "82E5": {
   "unit": "game/mapGenerator6F00",
   "line": "print item 1 - 'CUSTOM' follows immediately at $CC19"
  },
  "82E8": {
   "unit": "game/mapGenerator6F00",
   "line": "run the selector, 10-character bar"
  },
  "82EB": {
   "unit": "game/mapGenerator6F00",
   "line": "current options byte"
  },
  "82EE": {
   "unit": "game/mapGenerator6F00",
   "line": "clear bit 7 (map type)"
  },
  "82F0": {
   "unit": "game/mapGenerator6F00",
   "line": "0 = STANDARD, 1 = CUSTOM"
  },
  "82F3": {
   "unit": "game/mapGenerator6F00",
   "line": "branch when STANDARD was chosen"
  },
  "82F5": {
   "unit": "game/mapGenerator6F00",
   "line": "set bit 7 = custom (named) map"
  },
  "82F7": {
   "unit": "game/mapGenerator6F00",
   "line": "store the finished gameTypeOptions"
  },
  "82FA": {
   "unit": "game/mapGenerator6F00",
   "line": "tell the opponent the whole options byte (command $A4)"
  },
  "82FD": {
   "unit": "game/mapGenerator6F00",
   "line": "copy this scenario's 400-byte unit start template into the live unit arrays"
  },
  "8300": {
   "unit": "game/mapGenerator6F00",
   "line": "$FF = menu / setup phase"
  },
  "8302": {
   "unit": "game/mapGenerator6F00",
   "line": "gamePhase zp_B1"
  },
  "8304": {
   "unit": "game/mapGenerator6F00",
   "line": "the new options byte"
  },
  "8307": {
   "unit": "game/mapGenerator6F00",
   "line": "compare with the options of the previous game"
  },
  "830A": {
   "unit": "game/mapGenerator6F00",
   "line": "branch when nothing changed - keep the alternating 1ST PLAY flag"
  },
  "830C": {
   "unit": "game/mapGenerator6F00",
   "line": "1 = this side has 1ST PLAY"
  },
  "830E": {
   "unit": "game/mapGenerator6F00",
   "line": "a new scenario always gives this side 1ST PLAY"
  },
  "8311": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "Map seed.  A CUSTOM map is typed in by the player; a STANDARD map is drawn from the shared 24-bit",
    "game RNG state zp_57-zp_59, so both machines end up with the same battlefield."
   ],
   "line": "map type chosen above"
  },
  "8314": {
   "unit": "game/mapGenerator6F00",
   "line": "CUSTOM map -> let the player type the five-character map name"
  },
  "8316": {
   "unit": "game/mapGenerator6F00",
   "line": "byte 0 of the shared game RNG state"
  },
  "8318": {
   "unit": "game/mapGenerator6F00",
   "line": "Y = chosen game type (operand patched at $8287)"
  },
  "831A": {
   "unit": "game/mapGenerator6F00",
   "line": "6 = DEFENDER (asymmetric scenario)"
  },
  "831C": {
   "unit": "game/mapGenerator6F00",
   "line": "DEFENDER - handle it with QB SNEAK"
  },
  "831E": {
   "unit": "game/mapGenerator6F00",
   "line": "1 = QB SNEAK (asymmetric scenario)"
  },
  "8320": {
   "unit": "game/mapGenerator6F00",
   "line": "any other scenario -> symmetric map"
  },
  "8322": {
   "unit": "game/mapGenerator6F00",
   "line": "asymmetric scenario: does this side have 1ST PLAY?"
  },
  "8325": {
   "unit": "game/mapGenerator6F00",
   "line": "no -> leave mapSeed alone, so the same map is replayed with the roles swapped"
  },
  "8327": {
   "unit": "game/mapGenerator6F00",
   "line": "yes -> store the RNG state unchanged (asymmetric map)"
  },
  "8329": {
   "unit": "game/mapGenerator6F00",
   "line": "force the low 5 bits, i.e. a map name ending in '=' - the generator then mirrors the map"
  },
  "832B": {
   "unit": "game/mapGenerator6F00",
   "line": "mapSeed byte 0 $0B95"
  },
  "832E": {
   "unit": "game/mapGenerator6F00",
   "line": "byte 1 of the RNG state"
  },
  "8330": {
   "unit": "game/mapGenerator6F00",
   "line": "mapSeed byte 1"
  },
  "8333": {
   "unit": "game/mapGenerator6F00",
   "line": "byte 2 of the RNG state"
  },
  "8335": {
   "unit": "game/mapGenerator6F00",
   "line": "mapSeed byte 2"
  },
  "8338": {
   "unit": "game/mapGenerator6F00",
   "line": "done - the caller at $79A7 sends the seed to the opponent as command $8B/$A6"
  },
  "8339": {
   "unit": "game/mapGenerator6F00",
   "line": "custom map: 'TYPE MAP NAME' screen (which comes back through startGameSession)"
  },
  "833C": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "sendGameTypeCommand - queues the 2-byte command $A4 (cmdSetGameType, handler $559C) carrying the",
    "chosen gameTypeOptions byte, so the opponent's $0BA3 ends up identical.",
    "In:  A = gameTypeOptions byte",
    "Out: zp_73 = A, command $A4 queued, D_929F incremented",
    "Called from: runMapTypeMenu $82FA"
   ],
   "line": "cmdParam0 = the options byte"
  },
  "833E": {
   "unit": "game/mapGenerator6F00",
   "line": "command $A4 = cmdSetGameType"
  },
  "8340": {
   "unit": "game/mapGenerator6F00",
   "line": "queue command + 1 argument"
  },
  "8343": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "printMenuTitle - common menu prologue: preselects row X, prints the title string A/Y centred in the",
    "current window, then moves the text window to column $1C (28) and records the row the first item will",
    "be printed on as menuFirstRow.",
    "In:  X = row to preselect, A/Y = bit-7 terminated title string",
    "Out: D_91D5 = X, D_91D6 = first item row, zp_3B = $1C, cursor pointers updated",
    "Called from: $826C (GAME TYPE:), $82D3 (MAP TYPE), $8588 ('  SCENARIO'), $862A (OFF/ON menus)"
   ],
   "line": "menuSelectedItem = the preselected row"
  },
  "8346": {
   "unit": "game/mapGenerator6F00",
   "line": "print the title centred in the current window width"
  },
  "8349": {
   "unit": "game/mapGenerator6F00",
   "line": "column 28 - left edge of the menu column"
  },
  "834B": {
   "unit": "game/mapGenerator6F00",
   "line": "textWindowLeft zp_3B"
  },
  "834D": {
   "unit": "game/mapGenerator6F00",
   "line": "recompute the bitmap/colour pointers for the new column"
  },
  "8350": {
   "unit": "game/mapGenerator6F00",
   "line": "the row the cursor now sits on"
  },
  "8352": {
   "unit": "game/mapGenerator6F00",
   "line": "menuFirstRow $91D6 - the selector highlights menuFirstRow + menuSelectedItem"
  },
  "8355": {
   "unit": "game/mapGenerator6F00",
   "line": "menu title and first row are set up"
  },
  "8356": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "runMenuWidth10 - runs the generic selector with a 10-character highlight bar; falls into",
    "runMenuWithWidth.",
    "In:  menu state D_91D4/D_91D5/D_91D6",
    "Out: A = D_91D5 = chosen row",
    "Called from: $8283 (game type), $82E8 (map type), $8599 (STANDARD/CUSTOM scenario)"
   ],
   "line": "highlight bar 10 characters wide"
  },
  "8358": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "runMenuWithWidth - sets the highlight width, backs the window up one column so the bar has a leading",
    "blank, and runs the generic menu selector with C = 0 (no extra slow-down row before the last item).",
    "In:  A = highlight width, D_91D4 item count, D_91D5 preselected row, D_91D6 first row",
    "Out: A = D_91D5 = chosen row, zp_3C = width, zp_3B decremented",
    "Called from: runMenuWidth10 (fall-through) and editOptionBitOnOff $8641"
   ],
   "line": "textWindowWidth zp_3C is also the width of the highlight bar"
  },
  "835A": {
   "unit": "game/mapGenerator6F00",
   "line": "start the bar one column left of the text"
  },
  "835C": {
   "unit": "game/mapGenerator6F00",
   "line": "C = 0 -> no slow-down row in the selector"
  },
  "835D": {
   "unit": "game/mapGenerator6F00",
   "line": "joystick/fire driven selection loop"
  },
  "8360": {
   "unit": "game/mapGenerator6F00",
   "line": "return the chosen row"
  },
  "8363": {
   "unit": "game/mapGenerator6F00",
   "line": "A = the chosen row"
  },
  "8364": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "resetSelectionAndView - blanks the tactical viewport for a full-screen menu: sets $9242 bit 7 (the",
    "overview then draws plain terrain instead of unit blips), clears the selected unit, forces the map",
    "screen and parks the view origin at (45,45), which is outside the 40x40 map.",
    "In:  nothing",
    "Out: D_9242 = $FE, D_90F8 = $FE, D_90FB = 0, zp_A5 = zp_A6 = $2D",
    "Called from: $823E, $82BF, $8398, $8422, $854B, $8614"
   ],
   "line": "$FE - bit 7 set, low bits 'no unit'"
  },
  "8366": {
   "unit": "game/mapGenerator6F00",
   "line": "$9242 bit 7 makes the overview map draw the terrain under each unit"
  },
  "8369": {
   "unit": "game/mapGenerator6F00",
   "line": "selectedUnit $90F8 = $FE = nothing selected"
  },
  "836C": {
   "unit": "game/mapGenerator6F00",
   "line": "0 = map screen"
  },
  "836E": {
   "unit": "game/mapGenerator6F00",
   "line": "currentScreen 0 = map screen"
  },
  "8371": {
   "unit": "game/mapGenerator6F00",
   "line": "45 - past the last map row/column (0-39)"
  },
  "8373": {
   "unit": "game/mapGenerator6F00",
   "line": "view origin column"
  },
  "8375": {
   "unit": "game/mapGenerator6F00",
   "line": "view origin row: the 7x5 viewport now shows nothing"
  },
  "8377": {
   "unit": "game/mapGenerator6F00",
   "line": "viewport is now blank"
  },
  "8378": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "chooseRecycler - RECYCLER setup for the scenarios that have one (game types 4-6).  Solo games force",
    "both sides to NONE.  With CUSTOM options a FULL/HALF/NONE menu is shown, otherwise the scenario",
    "default stands and NONE returns at once.  For FULL or HALF the player drives the target cursor over",
    "the map until he picks a cell whose terrain is blank ($40, looked up under a unit if one stands",
    "there); the result goes out as command $9C (mode, column, row), NONE as $9C with column/row = $FF.",
    "In:  D_0BA5, D_0B9F playerSide, D_92A6 recyclerMode[side], D_8450 customSetupChosen, player input",
    "Out: D_92A6/D_92A7 (solo), D_91D5, zp_73-zp_75, command $9C queued, D_9022 = 0, zp_BB = $FF;",
    "     self-modifies the LDA operand at $8433 with the chosen mode",
    "Called from: runGameStartOptions $85B6 (only for game types >= 4)"
   ],
   "line": "isSoloTrainer $0BA5"
  },
  "837B": {
   "unit": "game/mapGenerator6F00",
   "line": "modem game -> keep the per-side settings"
  },
  "837D": {
   "unit": "game/mapGenerator6F00",
   "line": "2 = NONE"
  },
  "837F": {
   "unit": "game/mapGenerator6F00",
   "line": "side 0 recycler mode $92A6"
  },
  "8382": {
   "unit": "game/mapGenerator6F00",
   "line": "side 1 recycler mode $92A7 - the solo trainer never uses a recycler"
  },
  "8385": {
   "unit": "game/mapGenerator6F00",
   "line": "playerSide 0/1"
  },
  "8388": {
   "unit": "game/mapGenerator6F00",
   "line": "this side's recycler mode"
  },
  "838B": {
   "unit": "game/mapGenerator6F00",
   "line": "preselect it in the menu"
  },
  "838E": {
   "unit": "game/mapGenerator6F00",
   "line": "customSetupChosen $8450 - nonzero when CUSTOM was picked at game start"
  },
  "8391": {
   "unit": "game/mapGenerator6F00",
   "line": "CUSTOM -> show the RECYCLER menu"
  },
  "8393": {
   "unit": "game/mapGenerator6F00",
   "line": "2 = NONE"
  },
  "8395": {
   "unit": "game/mapGenerator6F00",
   "line": "a preset FULL or HALF still has to be placed on the map"
  },
  "8397": {
   "unit": "game/mapGenerator6F00",
   "line": "NONE and no menu -> nothing to do at all"
  },
  "8398": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "The RECYCLER menu: title plus the three option words FULL / HALF / NONE from $0652."
   ],
   "line": "hide the viewport behind the menu"
  },
  "839B": {
   "unit": "game/mapGenerator6F00",
   "line": "text cursor row 14"
  },
  "839D": {
   "unit": "game/mapGenerator6F00",
   "line": "clear the info panel, cursor to row 14"
  },
  "83A0": {
   "unit": "game/mapGenerator6F00",
   "line": "'RECYCLER' at $EF92"
  },
  "83A2": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $EF92"
  },
  "83A4": {
   "unit": "game/mapGenerator6F00",
   "line": "print it centred"
  },
  "83A7": {
   "unit": "game/mapGenerator6F00",
   "line": "column 30"
  },
  "83A9": {
   "unit": "game/mapGenerator6F00",
   "line": "textWindowLeft zp_3B"
  },
  "83AB": {
   "unit": "game/mapGenerator6F00",
   "line": "recompute the cursor pointers for the new column"
  },
  "83AE": {
   "unit": "game/mapGenerator6F00",
   "line": "row of the first item"
  },
  "83B0": {
   "unit": "game/mapGenerator6F00",
   "line": "menuFirstRow $91D6"
  },
  "83B3": {
   "unit": "game/mapGenerator6F00",
   "line": "three items"
  },
  "83B5": {
   "unit": "game/mapGenerator6F00",
   "line": "menuItemCount $91D4"
  },
  "83B8": {
   "unit": "game/mapGenerator6F00",
   "line": "option word 0 = FULL"
  },
  "83BA": {
   "unit": "game/mapGenerator6F00",
   "line": "print it and a newline"
  },
  "83BD": {
   "unit": "game/mapGenerator6F00",
   "line": "option word 1 = HALF"
  },
  "83BF": {
   "unit": "game/mapGenerator6F00",
   "line": "print it and a newline"
  },
  "83C2": {
   "unit": "game/mapGenerator6F00",
   "line": "option word 2 = NONE"
  },
  "83C4": {
   "unit": "game/mapGenerator6F00",
   "line": "print it and a newline"
  },
  "83C7": {
   "unit": "game/mapGenerator6F00",
   "line": "highlight bar starts one column left of the words"
  },
  "83C9": {
   "unit": "game/mapGenerator6F00",
   "line": "bar 6 characters wide"
  },
  "83CB": {
   "unit": "game/mapGenerator6F00",
   "line": "textWindowWidth zp_3C"
  },
  "83CD": {
   "unit": "game/mapGenerator6F00",
   "line": "C = 0 -> no slow-down row"
  },
  "83CE": {
   "unit": "game/mapGenerator6F00",
   "line": "run the selector; Y comes back holding the chosen row"
  },
  "83D1": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "Turn the chosen mode into command $9C.  NONE needs no map cell, FULL/HALF make the player pick one."
   ],
   "line": "patch the LDA operand at $8433 - the mode becomes cmdParam0"
  },
  "83D4": {
   "unit": "game/mapGenerator6F00",
   "line": "2 = NONE"
  },
  "83D6": {
   "unit": "game/mapGenerator6F00",
   "line": "FULL or HALF -> place it on the map"
  },
  "83D8": {
   "unit": "game/mapGenerator6F00",
   "line": "$FF = no cell"
  },
  "83DA": {
   "unit": "game/mapGenerator6F00",
   "line": "cmdParam1 = column"
  },
  "83DC": {
   "unit": "game/mapGenerator6F00",
   "line": "cmdParam2 = row"
  },
  "83DE": {
   "unit": "game/mapGenerator6F00",
   "line": "always taken ($FF is negative) - jump straight to the send"
  },
  "83E0": {
   "unit": "game/mapGenerator6F00",
   "line": "text cursor row 15"
  },
  "83E2": {
   "unit": "game/mapGenerator6F00",
   "line": "clear the info panel, cursor to row 15"
  },
  "83E5": {
   "unit": "game/mapGenerator6F00",
   "line": "'LOCATING' at $EF89"
  },
  "83E7": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $EF89"
  },
  "83E9": {
   "unit": "game/mapGenerator6F00",
   "line": "print 'LOCATING' centred"
  },
  "83EC": {
   "unit": "game/mapGenerator6F00",
   "line": "and the string that follows it, 'RECYCLER' at $EF92"
  },
  "83EF": {
   "unit": "game/mapGenerator6F00",
   "line": "put the view origin over this side's home end of the map"
  },
  "83F2": {
   "unit": "game/mapGenerator6F00",
   "line": "show the cursor sprite over the centre cell"
  },
  "83F5": {
   "unit": "game/mapGenerator6F00",
   "line": "draw the 7x5 cell tactical view"
  },
  "83F8": {
   "unit": "game/mapGenerator6F00",
   "line": "draw the whole-map overview"
  },
  "83FB": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "Pick loop: the recycler may only stand on empty terrain, so a cell holding anything else beeps and",
    "the cursor comes back."
   ],
   "line": "$FF = free cell pick (result reported, no command executed)"
  },
  "83FD": {
   "unit": "game/mapGenerator6F00",
   "line": "cursorTargetMode zp_BB"
  },
  "83FF": {
   "unit": "game/mapGenerator6F00",
   "line": "drive the cursor until fire; the cell lands in $91D8/$91D9"
  },
  "8402": {
   "unit": "game/mapGenerator6F00",
   "line": "chosen column"
  },
  "8405": {
   "unit": "game/mapGenerator6F00",
   "line": "chosen row"
  },
  "8408": {
   "unit": "game/mapGenerator6F00",
   "line": "A = the map byte of that cell"
  },
  "840B": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 7 clear -> plain terrain, use it directly"
  },
  "840D": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 7 set: Y = $80|unitIndex"
  },
  "840E": {
   "unit": "game/mapGenerator6F00",
   "line": "$FA70 + $80 + unit = unitTerrainUnderTable[unit], the terrain hidden by that unit"
  },
  "8411": {
   "unit": "game/mapGenerator6F00",
   "line": "$40 = blank terrain"
  },
  "8413": {
   "unit": "game/mapGenerator6F00",
   "line": "blank -> accept the cell"
  },
  "8415": {
   "unit": "game/mapGenerator6F00",
   "line": "sound 3 - cell rejected"
  },
  "8417": {
   "unit": "game/mapGenerator6F00",
   "line": "play it"
  },
  "841A": {
   "unit": "game/mapGenerator6F00",
   "line": "ask for another cell"
  },
  "841D": {
   "unit": "game/mapGenerator6F00",
   "line": "0 - no sprites"
  },
  "841F": {
   "unit": "game/mapGenerator6F00",
   "line": "turn every sprite off again"
  },
  "8422": {
   "unit": "game/mapGenerator6F00",
   "line": "park the view off the map"
  },
  "8425": {
   "unit": "game/mapGenerator6F00",
   "line": "clear the text area under the viewport"
  },
  "8428": {
   "unit": "game/mapGenerator6F00",
   "line": "chosen column"
  },
  "842B": {
   "unit": "game/mapGenerator6F00",
   "line": "cmdParam1"
  },
  "842D": {
   "unit": "game/mapGenerator6F00",
   "line": "chosen row"
  },
  "8430": {
   "unit": "game/mapGenerator6F00",
   "line": "cmdParam2"
  },
  "8432": {
   "unit": "game/mapGenerator6F00",
   "line": "operand patched at $83D1 with the recycler mode"
  },
  "8434": {
   "unit": "game/mapGenerator6F00",
   "line": "cmdParam0 = mode"
  },
  "8436": {
   "unit": "game/mapGenerator6F00",
   "line": "command $9C = cmdSetRecycler"
  },
  "8438": {
   "unit": "game/mapGenerator6F00",
   "line": "queue command + 3 arguments"
  },
  "843B": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "printOptionWordLine - prints option word A (0 FULL, 1 HALF, 2 NONE, from the 4-byte entries at $0652)",
    "followed by a newline.",
    "In:  A = word index 0-2",
    "Out: one line of text at the cursor",
    "Called from: chooseRecycler $83BA, $83BF, $83C4"
   ],
   "line": "print the 4-character word from $0652 + A*4"
  },
  "843E": {
   "unit": "game/mapGenerator6F00",
   "line": "and end the line"
  },
  "8441": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "clearInfoPanelSetRow - sets the text and pad colours to 8 (orange), blanks the info panel window and",
    "puts the cursor on row A.  Used before every setup panel in this overlay.",
    "In:  A = text cursor row",
    "Out: zp_3D = zp_42 = 8, panel cleared, zp_40 = A, cursor pointers updated",
    "Called from: $8243, $82C4, $839D, $83E2, $8572, $85E6, $8619, $8758"
   ],
   "line": "remember the wanted row across the clear"
  },
  "8442": {
   "unit": "game/mapGenerator6F00",
   "line": "colour code 8 (orange)"
  },
  "8444": {
   "unit": "game/mapGenerator6F00",
   "line": "text colour zp_3D"
  },
  "8446": {
   "unit": "game/mapGenerator6F00",
   "line": "pad colour zp_42"
  },
  "8448": {
   "unit": "game/mapGenerator6F00",
   "line": "set the info-panel text window and blank it"
  },
  "844B": {
   "unit": "game/mapGenerator6F00",
   "line": "the wanted row again"
  },
  "844C": {
   "unit": "game/mapGenerator6F00",
   "line": "position the cursor on it"
  },
  "844F": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "Two one-byte variables of the value editors, sitting between the routines that use them."
   ],
   "line": "current value of the joystick value editor (limits and meaning depend on the caller)"
  },
  "8450": {
   "unit": "game/mapGenerator6F00",
   "line": "0 = STANDARD scenario options, 1 = CUSTOM chosen on the game-start screen ($40 briefly at $8564)"
  },
  "8451": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "editValueWithJoystick - the generic numeric option editor of the custom setup.  It repeatedly prints",
    "editValue * Y in decimal at column 1 of the one-row value window, keeps the link and the blinking",
    "highlight alive, and applies joystick up as +1 and down as -1, rejecting anything that is not below",
    "the limit (a decrement below 0 wraps to $FF and is rejected the same way).  Returns when the fire",
    "button is clicked.",
    "In:  A = exclusive upper limit, Y = display multiplier, D_844F = starting value, window set up by",
    "     beginValueEdit, zp_5D joystick, zp_6C repeat timer, zp_6E blink timer",
    "Out: D_844F = edited value, D_92C5 = 1, number printed, sound 2 on every change;",
    "     self-modifies the CMP operand at $8493 (limit) and the LDY operand at $846A (multiplier)",
    "Called from: applyHandicapPoints $84DB, editTerrainPoints $8500, editDronesAndMissiles $851F/$8536,",
    "     editComcenSpeed $85CA"
   ],
   "line": "patch the CMP operand at $8493 with the exclusive upper limit"
  },
  "8454": {
   "unit": "game/mapGenerator6F00",
   "line": "patch the LDY operand at $846A with the display multiplier"
  },
  "8457": {
   "unit": "game/mapGenerator6F00",
   "line": "1 = un-highlighted"
  },
  "8459": {
   "unit": "game/mapGenerator6F00",
   "line": "menuBlinkState 1 = the row is currently un-highlighted"
  },
  "845C": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "Redraw pass: un-highlight the row, print value * multiplier, then wait in the input loop."
   ],
   "line": "take the highlight off so the number can be redrawn"
  },
  "845F": {
   "unit": "game/mapGenerator6F00",
   "line": "column 1 of the value window (window left is 29, so absolute column 30)"
  },
  "8461": {
   "unit": "game/mapGenerator6F00",
   "line": "textCursorCol zp_3F"
  },
  "8463": {
   "unit": "game/mapGenerator6F00",
   "line": "recompute the cursor pointers"
  },
  "8466": {
   "unit": "game/mapGenerator6F00",
   "line": "current value"
  },
  "8469": {
   "unit": "game/mapGenerator6F00",
   "line": "multiplier (operand patched at $8454)"
  },
  "846B": {
   "unit": "game/mapGenerator6F00",
   "line": "16-bit multiply: A = product low, Y = product high"
  },
  "846E": {
   "unit": "game/mapGenerator6F00",
   "line": "print it as decimal without leading zeros"
  },
  "8471": {
   "unit": "game/mapGenerator6F00",
   "line": "blank the rest of the line so a shorter number leaves no digits behind"
  },
  "8474": {
   "unit": "game/mapGenerator6F00",
   "line": "keep the lock-step command exchange running while the player thinks"
  },
  "8477": {
   "unit": "game/mapGenerator6F00",
   "line": "frames left before the next highlight flip"
  },
  "8479": {
   "unit": "game/mapGenerator6F00",
   "line": "not yet"
  },
  "847B": {
   "unit": "game/mapGenerator6F00",
   "line": "flip the highlight of the value row"
  },
  "847E": {
   "unit": "game/mapGenerator6F00",
   "line": "joystick auto-repeat delay still running?"
  },
  "8480": {
   "unit": "game/mapGenerator6F00",
   "line": "yes -> only look at the fire button"
  },
  "8482": {
   "unit": "game/mapGenerator6F00",
   "line": "active-low joystick nibble (bit 0 up, bit 1 down, bit 2 left, bit 3 right)"
  },
  "8484": {
   "unit": "game/mapGenerator6F00",
   "line": "force the left/right bits high so they are ignored"
  },
  "8486": {
   "unit": "game/mapGenerator6F00",
   "line": "$0F = neither up nor down"
  },
  "8488": {
   "unit": "game/mapGenerator6F00",
   "line": "stick centred (or only sideways) -> no change"
  },
  "848A": {
   "unit": "game/mapGenerator6F00",
   "line": "up -> $1C, down -> $1A"
  },
  "848B": {
   "unit": "game/mapGenerator6F00",
   "line": "borrow into the subtraction"
  },
  "848C": {
   "unit": "game/mapGenerator6F00",
   "line": "$1C-$1B = +1 (up), $1A-$1B = -1 (down)"
  },
  "848E": {
   "unit": "game/mapGenerator6F00",
   "line": "no carry into the add"
  },
  "848F": {
   "unit": "game/mapGenerator6F00",
   "line": "apply the step to the current value"
  },
  "8492": {
   "unit": "game/mapGenerator6F00",
   "line": "limit (operand patched at $8451); a decrement below 0 wraps to $FF and fails here too"
  },
  "8494": {
   "unit": "game/mapGenerator6F00",
   "line": "out of range -> leave the value alone"
  },
  "8496": {
   "unit": "game/mapGenerator6F00",
   "line": "store the new value"
  },
  "8499": {
   "unit": "game/mapGenerator6F00",
   "line": "sound 2 - the value changed"
  },
  "849B": {
   "unit": "game/mapGenerator6F00",
   "line": "play it"
  },
  "849E": {
   "unit": "game/mapGenerator6F00",
   "line": "16 frames before the first repeat, 6 between repeats"
  },
  "84A1": {
   "unit": "game/mapGenerator6F00",
   "line": "redraw the number"
  },
  "84A4": {
   "unit": "game/mapGenerator6F00",
   "line": "new fire click?"
  },
  "84A7": {
   "unit": "game/mapGenerator6F00",
   "line": "no -> keep servicing the link and blinking"
  },
  "84A9": {
   "unit": "game/mapGenerator6F00",
   "line": "value confirmed"
  },
  "84AA": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "applyHandicapPoints - last step of the game-start options.  Works out the default handicap of the two",
    "asymmetric scenarios (QB SNEAK gives side 0 a 2, DEFENDER gives side 1 a $14) and, under CUSTOM rules,",
    "lets the player edit it (0..50, displayed multiplied by 10).  A nonzero result is sent as command $A5",
    "kind 0, which cmdSetupOption turns into value*10 points for the sender's side; zero is not sent.",
    "In:  D_0BA3 bits 0-2 game type, D_0B9F playerSide, D_92F3 bit 7 CUSTOM toggle",
    "Out: zp_74 = 0, zp_75 = value, command $A5 queued (only when nonzero); info panel used",
    "Called from: JMP from runGameStartOptions $85B9"
   ],
   "line": "default handicap 0"
  },
  "84AC": {
   "unit": "game/mapGenerator6F00",
   "line": "gameTypeOptions"
  },
  "84AF": {
   "unit": "game/mapGenerator6F00",
   "line": "bits 0-2 = game type"
  },
  "84B1": {
   "unit": "game/mapGenerator6F00",
   "line": "1 = QB SNEAK"
  },
  "84B3": {
   "unit": "game/mapGenerator6F00",
   "line": "not QB SNEAK"
  },
  "84B5": {
   "unit": "game/mapGenerator6F00",
   "line": "playerSide"
  },
  "84B8": {
   "unit": "game/mapGenerator6F00",
   "line": "only side 0 (the side on offence) gets the QB SNEAK handicap"
  },
  "84BA": {
   "unit": "game/mapGenerator6F00",
   "line": "2 -> 20 points"
  },
  "84BC": {
   "unit": "game/mapGenerator6F00",
   "line": "6 = DEFENDER (A is the game type, or playerSide 0 after the branch above)"
  },
  "84BE": {
   "unit": "game/mapGenerator6F00",
   "line": "not DEFENDER"
  },
  "84C0": {
   "unit": "game/mapGenerator6F00",
   "line": "playerSide"
  },
  "84C3": {
   "unit": "game/mapGenerator6F00",
   "line": "only side 1 gets the DEFENDER handicap"
  },
  "84C5": {
   "unit": "game/mapGenerator6F00",
   "line": "$14 = 20 -> 200 points"
  },
  "84C7": {
   "unit": "game/mapGenerator6F00",
   "line": "CUSTOM toggle $92F3 bit 7"
  },
  "84CA": {
   "unit": "game/mapGenerator6F00",
   "line": "custom rules -> let the player edit the number"
  },
  "84CC": {
   "unit": "game/mapGenerator6F00",
   "line": "A = the scenario default"
  },
  "84CD": {
   "unit": "game/mapGenerator6F00",
   "line": "zero -> send nothing at all"
  },
  "84CF": {
   "unit": "game/mapGenerator6F00",
   "line": "no handicap in this scenario for this side"
  },
  "84D0": {
   "unit": "game/mapGenerator6F00",
   "line": "'HANDICAP' at $EF52"
  },
  "84D2": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $EF52"
  },
  "84D4": {
   "unit": "game/mapGenerator6F00",
   "line": "X still holds the default, which becomes the starting value"
  },
  "84D7": {
   "unit": "game/mapGenerator6F00",
   "line": "limit $33 = 51, so 0..50"
  },
  "84D9": {
   "unit": "game/mapGenerator6F00",
   "line": "displayed multiplied by 10 (0..500 points)"
  },
  "84DB": {
   "unit": "game/mapGenerator6F00",
   "line": "edit it with the joystick"
  },
  "84DE": {
   "unit": "game/mapGenerator6F00",
   "line": "the edited value"
  },
  "84E1": {
   "unit": "game/mapGenerator6F00",
   "line": "cmdParam2 = the handicap"
  },
  "84E3": {
   "unit": "game/mapGenerator6F00",
   "line": "kind 0 = handicap points"
  },
  "84E5": {
   "unit": "game/mapGenerator6F00",
   "line": "cmdParam1"
  },
  "84E7": {
   "unit": "game/mapGenerator6F00",
   "line": "command $A5 = cmdSetupOption"
  },
  "84E9": {
   "unit": "game/mapGenerator6F00",
   "line": "queue command + 2 arguments"
  },
  "84EC": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "editTerrainPoints - the CUSTOM option 'TERRAIN PTS' (0..2).  $92AC is indexed with the complement of",
    "the side, so the entry this routine edits (index playerSide EOR 1) is exactly the one $47A9 uses when",
    "one of this player's own units reaches enemy ground.  Sent as command $A5 kind 1, which cmdSetupOption",
    "stores at the same complemented index on both machines.",
    "In:  D_0B9F playerSide, D_92AC",
    "Out: zp_74 = 1, zp_75 = value, command $A5 queued",
    "Called from: runGameStartOptions $85A7"
   ],
   "line": "playerSide"
  },
  "84EF": {
   "unit": "game/mapGenerator6F00",
   "line": "$92AC is indexed 1-side, so this picks this player's own entry"
  },
  "84F1": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "editTerrainPointsForSide - entry into editTerrainPoints with the $92AC index already in A.  Nothing in",
    "variant A reaches it (the XREF caller $83DE belongs to overlay variant B, where $84F1 is",
    "plotDiamondMarker).",
    "In:  A = $92AC index (0 or 1)",
    "Out: as editTerrainPoints",
    "Called from: fall-through only in variant A"
   ],
   "line": "Y = the table index"
  },
  "84F2": {
   "unit": "game/mapGenerator6F00",
   "line": "current TERRAIN PTS setting = starting value"
  },
  "84F5": {
   "unit": "game/mapGenerator6F00",
   "line": "'TERRAIN PTS' at $EF5A"
  },
  "84F7": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $EF5A"
  },
  "84F9": {
   "unit": "game/mapGenerator6F00",
   "line": "set up the one-row value window"
  },
  "84FC": {
   "unit": "game/mapGenerator6F00",
   "line": "limit 3, so 0..2"
  },
  "84FE": {
   "unit": "game/mapGenerator6F00",
   "line": "displayed as it is"
  },
  "8500": {
   "unit": "game/mapGenerator6F00",
   "line": "edit it with the joystick"
  },
  "8503": {
   "unit": "game/mapGenerator6F00",
   "line": "the edited value"
  },
  "8506": {
   "unit": "game/mapGenerator6F00",
   "line": "cmdParam2"
  },
  "8508": {
   "unit": "game/mapGenerator6F00",
   "line": "kind 1 = terrain points"
  },
  "850A": {
   "unit": "game/mapGenerator6F00",
   "line": "cmdParam1"
  },
  "850C": {
   "unit": "game/mapGenerator6F00",
   "line": "command $A5 = cmdSetupOption"
  },
  "850E": {
   "unit": "game/mapGenerator6F00",
   "line": "queue command + 2 arguments"
  },
  "8511": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "editDronesAndMissiles - the CUSTOM options 'DRONES' (0..9) and 'MISSILES' (0..36), edited one after",
    "the other and sent together as command $90; during the setup phase cmdMissileStrike simply stores the",
    "two numbers as the sender's dronesLeft/missilesLeft.",
    "In:  D_92AE dronesLeft[own], D_92B0 missilesLeft[own]",
    "Out: zp_74 = drones, zp_75 = missiles, command $90 queued; self-modifies the LDA operand at $853A",
    "Called from: runGameStartOptions $85AA"
   ],
   "line": "own drone count = starting value"
  },
  "8514": {
   "unit": "game/mapGenerator6F00",
   "line": "'DRONES' at $EF65"
  },
  "8516": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $EF65"
  },
  "8518": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "editDronesAndMissilesBody - not a real entry point in variant A: it is the JSR beginValueEdit inside",
    "editDronesAndMissiles.  The label only exists because the main program's JSR $8518 at $1460/$14D3",
    "targets overlay variant B's drawStatsTab.",
    "In:  A/Y = label string, X = starting value (already loaded by editDronesAndMissiles)",
    "Out: as editDronesAndMissiles",
    "Called from: fall-through only in variant A"
   ],
   "line": "set up the one-row value window for DRONES"
  },
  "851B": {
   "unit": "game/mapGenerator6F00",
   "line": "limit $0A, so 0..9"
  },
  "851D": {
   "unit": "game/mapGenerator6F00",
   "line": "displayed as it is"
  },
  "851F": {
   "unit": "game/mapGenerator6F00",
   "line": "edit it"
  },
  "8522": {
   "unit": "game/mapGenerator6F00",
   "line": "the drone count"
  },
  "8525": {
   "unit": "game/mapGenerator6F00",
   "line": "patch the LDA operand at $853A so it survives the second edit"
  },
  "8528": {
   "unit": "game/mapGenerator6F00",
   "line": "own missile count = starting value"
  },
  "852B": {
   "unit": "game/mapGenerator6F00",
   "line": "'MISSILES' at $CC9E"
  },
  "852D": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $CC9E"
  },
  "852F": {
   "unit": "game/mapGenerator6F00",
   "line": "set up the value window again"
  },
  "8532": {
   "unit": "game/mapGenerator6F00",
   "line": "limit $25 = 37, so 0..36"
  },
  "8534": {
   "unit": "game/mapGenerator6F00",
   "line": "displayed as it is"
  },
  "8536": {
   "unit": "game/mapGenerator6F00",
   "line": "edit it"
  },
  "8539": {
   "unit": "game/mapGenerator6F00",
   "line": "drone count (operand patched at $8525)"
  },
  "853B": {
   "unit": "game/mapGenerator6F00",
   "line": "cmdParam1 = drones"
  },
  "853D": {
   "unit": "game/mapGenerator6F00",
   "line": "missile count"
  },
  "8540": {
   "unit": "game/mapGenerator6F00",
   "line": "cmdParam2 = missiles"
  },
  "8542": {
   "unit": "game/mapGenerator6F00",
   "line": "command $90 = cmdMissileStrike (a setup-phase store here, a missile launch during battle)"
  },
  "8544": {
   "unit": "game/mapGenerator6F00",
   "line": "queue command + 2 arguments"
  },
  "8547": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "runGameStartOptions - the screen shown once per game after the setup has been saved and before unit",
    "placement.  It draws the 'STANDARD/CUSTOM <scenario> SCENARIO' banner and waits for a click, then, if",
    "the scenario carries CUSTOM rules ($0BA3 bit 6), offers a STANDARD/CUSTOM choice; picking CUSTOM runs",
    "the COMCEN SPEED, TERRAIN PTS, DRONES and MISSILES editors.  Scenarios 4-6 then place the recycler,",
    "and it finishes in applyHandicapPoints.",
    "In:  D_0BA3 gameTypeOptions, D_0B9F playerSide, menu/text engine state",
    "Out: zp_B1 = $7F, D_8450 customSetupChosen, D_92F3 bit 7, setup commands $A5/$90/$9C queued",
    "Called from: startGameSession $7AF7"
   ],
   "line": "$7F = setup phase with drawing enabled"
  },
  "8549": {
   "unit": "game/mapGenerator6F00",
   "line": "gamePhase zp_B1"
  },
  "854B": {
   "unit": "game/mapGenerator6F00",
   "line": "park the viewport off the map"
  },
  "854E": {
   "unit": "game/mapGenerator6F00",
   "line": "playerSide"
  },
  "8551": {
   "unit": "game/mapGenerator6F00",
   "line": "side 1 needs the whole screen redrawn"
  },
  "8553": {
   "unit": "game/mapGenerator6F00",
   "line": "side 0 only refreshes the overview map"
  },
  "8556": {
   "unit": "game/mapGenerator6F00",
   "line": "skip the side-1 redraw"
  },
  "8559": {
   "unit": "game/mapGenerator6F00",
   "line": "grey the bitmap and redraw the game screen frame"
  },
  "855C": {
   "unit": "game/mapGenerator6F00",
   "line": "show the scenario banner and wait for the fire button"
  },
  "855F": {
   "unit": "game/mapGenerator6F00",
   "line": "gameTypeOptions"
  },
  "8562": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 6 = CUSTOM rules"
  },
  "8564": {
   "unit": "game/mapGenerator6F00",
   "line": "$40 or 0 (overwritten with 0/1 by the menu below)"
  },
  "8567": {
   "unit": "game/mapGenerator6F00",
   "line": "shift bit 6 up into bit 7"
  },
  "8568": {
   "unit": "game/mapGenerator6F00",
   "line": "setupToggleFlag $92F3 bit 7"
  },
  "856B": {
   "unit": "game/mapGenerator6F00",
   "line": "STANDARD rules -> skip the whole custom block"
  },
  "856D": {
   "unit": "game/mapGenerator6F00",
   "line": "put 'CUSTOM: ... MENUS x, DAMAGE y.' on the status line"
  },
  "8570": {
   "unit": "game/mapGenerator6F00",
   "line": "text cursor row 13"
  },
  "8572": {
   "unit": "game/mapGenerator6F00",
   "line": "clear the info panel, cursor to row 13"
  },
  "8575": {
   "unit": "game/mapGenerator6F00",
   "line": "gameTypeOptions"
  },
  "8578": {
   "unit": "game/mapGenerator6F00",
   "line": "bits 0-2 = game type"
  },
  "857A": {
   "unit": "game/mapGenerator6F00",
   "line": "X = scenario index"
  },
  "857B": {
   "unit": "game/mapGenerator6F00",
   "line": "scenario name table at $CCC8 (8-byte entries)"
  },
  "857D": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $CCC8"
  },
  "857F": {
   "unit": "game/mapGenerator6F00",
   "line": "print the scenario name centred in 13 columns"
  },
  "8582": {
   "unit": "game/mapGenerator6F00",
   "line": "'  SCENARIO' at $CC04"
  },
  "8584": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $CC04"
  },
  "8586": {
   "unit": "game/mapGenerator6F00",
   "line": "preselect row 0 = STANDARD"
  },
  "8588": {
   "unit": "game/mapGenerator6F00",
   "line": "print it as the menu title"
  },
  "858B": {
   "unit": "game/mapGenerator6F00",
   "line": "two items"
  },
  "858D": {
   "unit": "game/mapGenerator6F00",
   "line": "menuItemCount $91D4"
  },
  "8590": {
   "unit": "game/mapGenerator6F00",
   "line": "'STANDARD' follows at $CC11"
  },
  "8593": {
   "unit": "game/mapGenerator6F00",
   "line": "next line"
  },
  "8596": {
   "unit": "game/mapGenerator6F00",
   "line": "'CUSTOM' follows at $CC19"
  },
  "8599": {
   "unit": "game/mapGenerator6F00",
   "line": "run the selector"
  },
  "859C": {
   "unit": "game/mapGenerator6F00",
   "line": "0 = STANDARD, 1 = CUSTOM"
  },
  "859F": {
   "unit": "game/mapGenerator6F00",
   "line": "redundant reload - A already holds the choice"
  },
  "85A2": {
   "unit": "game/mapGenerator6F00",
   "line": "STANDARD -> keep the scenario defaults"
  },
  "85A4": {
   "unit": "game/mapGenerator6F00",
   "line": "COMCEN SPEED"
  },
  "85A7": {
   "unit": "game/mapGenerator6F00",
   "line": "TERRAIN PTS"
  },
  "85AA": {
   "unit": "game/mapGenerator6F00",
   "line": "DRONES and MISSILES"
  },
  "85AD": {
   "unit": "game/mapGenerator6F00",
   "line": "gameTypeOptions"
  },
  "85B0": {
   "unit": "game/mapGenerator6F00",
   "line": "bits 0-2 = game type"
  },
  "85B2": {
   "unit": "game/mapGenerator6F00",
   "line": "types 4-6 are SLUGGERS, FULL WAR and DEFENDER"
  },
  "85B4": {
   "unit": "game/mapGenerator6F00",
   "line": "the other scenarios have no recycler"
  },
  "85B6": {
   "unit": "game/mapGenerator6F00",
   "line": "choose and place the recycler"
  },
  "85B9": {
   "unit": "game/mapGenerator6F00",
   "line": "finish with the handicap"
  },
  "85BC": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "editComcenSpeed - the CUSTOM option 'COMCEN SPEED' (0..3).  Sent as command $A5 kind 3, which",
    "cmdSetupOption stores in $92B4 of the sender; at $7B6E the setting is mapped through the table at",
    "$78BF into the comcen's actual step rate, and $34D5 refuses to move a comcen whose class is 4.",
    "In:  D_92B4 comcenSpeedClass[own]",
    "Out: zp_74 = 3, zp_75 = value, command $A5 queued",
    "Called from: runGameStartOptions $85A4"
   ],
   "line": "own comcen speed class = starting value"
  },
  "85BF": {
   "unit": "game/mapGenerator6F00",
   "line": "'COMCEN SPEED' at $EF6B"
  },
  "85C1": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $EF6B"
  },
  "85C3": {
   "unit": "game/mapGenerator6F00",
   "line": "set up the one-row value window"
  },
  "85C6": {
   "unit": "game/mapGenerator6F00",
   "line": "limit 4, so 0..3"
  },
  "85C8": {
   "unit": "game/mapGenerator6F00",
   "line": "displayed as it is"
  },
  "85CA": {
   "unit": "game/mapGenerator6F00",
   "line": "edit it with the joystick"
  },
  "85CD": {
   "unit": "game/mapGenerator6F00",
   "line": "the edited value"
  },
  "85D0": {
   "unit": "game/mapGenerator6F00",
   "line": "cmdParam2"
  },
  "85D2": {
   "unit": "game/mapGenerator6F00",
   "line": "kind 3 = comcen speed"
  },
  "85D4": {
   "unit": "game/mapGenerator6F00",
   "line": "cmdParam1"
  },
  "85D6": {
   "unit": "game/mapGenerator6F00",
   "line": "command $A5 = cmdSetupOption"
  },
  "85D8": {
   "unit": "game/mapGenerator6F00",
   "line": "queue command + 2 arguments"
  },
  "85DB": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "beginValueEdit - common prologue of all four value editors: remembers the label string in two",
    "self-modified operands, seeds editValue, clears the info panel to row 15, prints the label centred,",
    "then moves the text window to column $1D (29) and makes the next line the single menu row.  Falls into",
    "setValueEditWindow.",
    "In:  A/Y = bit-7 terminated label, X = starting value",
    "Out: D_844F = X, D_91D5 = 0, D_91D6 = the value row, D_90F8 = $FE, zp_3B = $1D, zp_3C = 5;",
    "     self-modifies $85EA/$85EC with the label pointer",
    "Called from: $84D4 (HANDICAP), $84F9 (TERRAIN PTS), $8518 (DRONES), $852F (MISSILES), $85C3",
    "     (COMCEN SPEED)"
   ],
   "line": "patch the LDA operand at $85EA with the label's low byte"
  },
  "85DE": {
   "unit": "game/mapGenerator6F00",
   "line": "patch the LDY operand at $85EC with its high byte"
  },
  "85E1": {
   "unit": "game/mapGenerator6F00",
   "line": "editValue = the starting value"
  },
  "85E4": {
   "unit": "game/mapGenerator6F00",
   "line": "text cursor row 15"
  },
  "85E6": {
   "unit": "game/mapGenerator6F00",
   "line": "clear the info panel, cursor to row 15"
  },
  "85E9": {
   "unit": "game/mapGenerator6F00",
   "line": "label low byte (patched at $85DB)"
  },
  "85EB": {
   "unit": "game/mapGenerator6F00",
   "line": "label high byte (patched at $85DE)"
  },
  "85ED": {
   "unit": "game/mapGenerator6F00",
   "line": "print the label centred"
  },
  "85F0": {
   "unit": "game/mapGenerator6F00",
   "line": "column 29 - where the number goes"
  },
  "85F2": {
   "unit": "game/mapGenerator6F00",
   "line": "textWindowLeft zp_3B"
  },
  "85F4": {
   "unit": "game/mapGenerator6F00",
   "line": "the value goes on the next line"
  },
  "85F7": {
   "unit": "game/mapGenerator6F00",
   "line": "that row"
  },
  "85F9": {
   "unit": "game/mapGenerator6F00",
   "line": "menuFirstRow $91D6 - the single row the editor blinks"
  },
  "85FC": {
   "unit": "game/mapGenerator6F00",
   "line": "0 = the only row"
  },
  "85FE": {
   "unit": "game/mapGenerator6F00",
   "line": "menuSelectedItem 0 - a one-row menu"
  },
  "8601": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "setValueEditWindow - tail of beginValueEdit: marks the menu as a plain one (no unit attached) and sets",
    "the highlight bar to 5 characters.  The separate label exists only because $8601 is a real routine",
    "(printNumberRightAligned) in overlay variant B; in A it is reached by fall-through alone.",
    "In:  nothing",
    "Out: D_90F8 = $FE, zp_3C = 5",
    "Called from: fall-through only in variant A"
   ],
   "line": "$FE = plain menu, no unit behind it (keeps the REPAIR-menu special case out of the blinker)"
  },
  "8603": {
   "unit": "game/mapGenerator6F00",
   "line": "selectedUnit $90F8"
  },
  "8606": {
   "unit": "game/mapGenerator6F00",
   "line": "highlight bar 5 characters wide"
  },
  "8608": {
   "unit": "game/mapGenerator6F00",
   "line": "textWindowWidth zp_3C"
  },
  "860A": {
   "unit": "game/mapGenerator6F00",
   "line": "the value window is ready"
  },
  "860B": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "editOptionBitOnOff - a two-row OFF/ON menu for one bit of gameTypeOptions, used by the game-type",
    "screen for 'UNIT MENUS' (mask $08) and 'DAMAGE' (mask $10).  The label pointer and the mask go into",
    "self-modified operands, the current state of the bit preselects the row, and the chosen row writes the",
    "bit back into $0BA3.",
    "In:  A/Y = label string, X = bit mask, D_0BA3",
    "Out: D_0BA3 with that bit updated, D_91D4 = 2, D_91D5 = chosen row;",
    "     self-modifies $8622 (mask), $8627/$8629 (label pointer)",
    "Called from: runGameTypeMenu $82B3 (UNIT MENUS) and $82BC (DAMAGE)"
   ],
   "line": "patch the LDA operand at $8627 with the label's low byte"
  },
  "860E": {
   "unit": "game/mapGenerator6F00",
   "line": "patch the LDY operand at $8629 with its high byte"
  },
  "8611": {
   "unit": "game/mapGenerator6F00",
   "line": "patch the AND operand at $8622 with the bit mask"
  },
  "8614": {
   "unit": "game/mapGenerator6F00",
   "line": "park the viewport off the map"
  },
  "8617": {
   "unit": "game/mapGenerator6F00",
   "line": "text cursor row 14"
  },
  "8619": {
   "unit": "game/mapGenerator6F00",
   "line": "clear the info panel, cursor to row 14"
  },
  "861C": {
   "unit": "game/mapGenerator6F00",
   "line": "preselect row 0 = OFF"
  },
  "861E": {
   "unit": "game/mapGenerator6F00",
   "line": "gameTypeOptions"
  },
  "8621": {
   "unit": "game/mapGenerator6F00",
   "line": "mask (operand patched at $8611)"
  },
  "8623": {
   "unit": "game/mapGenerator6F00",
   "line": "bit clear -> leave OFF preselected"
  },
  "8625": {
   "unit": "game/mapGenerator6F00",
   "line": "bit set -> preselect row 1 = ON"
  },
  "8626": {
   "unit": "game/mapGenerator6F00",
   "line": "label low byte (patched at $860B)"
  },
  "8628": {
   "unit": "game/mapGenerator6F00",
   "line": "label high byte (patched at $860E)"
  },
  "862A": {
   "unit": "game/mapGenerator6F00",
   "line": "print the label as the menu title"
  },
  "862D": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "runOnOffMenuAndApplyBit - tail of editOptionBitOnOff that sets the item count and falls into the",
    "printing part.  Only a real entry point in overlay variant B (setTextColumn).",
    "In:  menu title already printed, mask in the operand at $8622",
    "Out: D_0BA3 updated",
    "Called from: fall-through only in variant A"
   ],
   "line": "two items"
  },
  "862F": {
   "unit": "game/mapGenerator6F00",
   "line": "menuItemCount $91D4"
  },
  "8632": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "printOnOffMenuAndApplyBit - inner tail of editOptionBitOnOff: prints the words OFF ($064D) and ON",
    "($0650), runs the 5-wide selector and clears or sets the mask bit in gameTypeOptions.  The main",
    "program's JSR $8632 at $176B targets overlay variant B's drawComcenSchematic, not this code.",
    "In:  menu state, mask in the operand at $8622, D_0BA3",
    "Out: D_0BA3 bit cleared or set, D_91D5 = chosen row",
    "Called from: fall-through only in variant A"
   ],
   "line": "'OFF' at $064D"
  },
  "8634": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $064D"
  },
  "8636": {
   "unit": "game/mapGenerator6F00",
   "line": "print row 0"
  },
  "8639": {
   "unit": "game/mapGenerator6F00",
   "line": "next line"
  },
  "863C": {
   "unit": "game/mapGenerator6F00",
   "line": "'ON' follows at $0650"
  },
  "863F": {
   "unit": "game/mapGenerator6F00",
   "line": "highlight bar 5 characters wide"
  },
  "8641": {
   "unit": "game/mapGenerator6F00",
   "line": "run the selector"
  },
  "8644": {
   "unit": "game/mapGenerator6F00",
   "line": "Y = 0 OFF, 1 ON"
  },
  "8645": {
   "unit": "game/mapGenerator6F00",
   "line": "$FF - build the inverse of the mask"
  },
  "8647": {
   "unit": "game/mapGenerator6F00",
   "line": "invert the mask (operand at $8622)"
  },
  "864A": {
   "unit": "game/mapGenerator6F00",
   "line": "clear that bit in gameTypeOptions"
  },
  "864D": {
   "unit": "game/mapGenerator6F00",
   "line": "was ON chosen?"
  },
  "864F": {
   "unit": "game/mapGenerator6F00",
   "line": "no - leave the bit clear"
  },
  "8651": {
   "unit": "game/mapGenerator6F00",
   "line": "yes - set it again"
  },
  "8654": {
   "unit": "game/mapGenerator6F00",
   "line": "store the updated options byte"
  },
  "8657": {
   "unit": "game/mapGenerator6F00",
   "line": "the option bit is updated"
  },
  "8658": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "handleStarKeyToggle - per-frame hook the main program calls while overlay A is resident and the game",
    "is not in the battle phase.  A '*' keypress ($AA) that is not part of a chat line is consumed and",
    "flips bit 7 of setupToggleFlag; the routine then falls into showToggleStateMessage and returns C = 1.",
    "Any other key returns C = 0.  The flag means CUSTOM rules on the scenario setup screen and DESTROY",
    "mode during unit placement (where clicking one of your own units sends $91 self destruct at $209F).",
    "In:  D_929C chatState, D_9248 lastTypedKey, D_92F3 setupToggleFlag",
    "Out: C = 1 with D_92F3 bit 7 flipped and D_9248 = $FF when '*' was pressed, otherwise C = 0",
    "Called from: main program trampoline $25C4 (JMP, battlefield loop when zp_B1 != 0) and runMenuLoop",
    "     $6002 (JSR, when zp_B1 == $FF)"
   ],
   "line": "chatState $929C, bit 7 set while a chat line is being typed"
  },
  "865B": {
   "unit": "game/mapGenerator6F00",
   "line": "typing -> the '*' belongs to the text"
  },
  "865D": {
   "unit": "game/mapGenerator6F00",
   "line": "last typed key (PETSCII with bit 7 set)"
  },
  "8660": {
   "unit": "game/mapGenerator6F00",
   "line": "$AA = '*'"
  },
  "8662": {
   "unit": "game/mapGenerator6F00",
   "line": "it is the toggle key"
  },
  "8664": {
   "unit": "game/mapGenerator6F00",
   "line": "C = 0: key not handled here"
  },
  "8665": {
   "unit": "game/mapGenerator6F00",
   "line": "C = 0, key not handled"
  },
  "8666": {
   "unit": "game/mapGenerator6F00",
   "line": "$FF = no key pending"
  },
  "8668": {
   "unit": "game/mapGenerator6F00",
   "line": "consume the '*' so nothing else sees it"
  },
  "866B": {
   "unit": "game/mapGenerator6F00",
   "line": "setupToggleFlag"
  },
  "866E": {
   "unit": "game/mapGenerator6F00",
   "line": "flip bit 7"
  },
  "8670": {
   "unit": "game/mapGenerator6F00",
   "line": "store it back and fall into showToggleStateMessage"
  },
  "8673": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "showToggleStateMessage - shows the state of the '*' toggle.  It empties the message queue, patches the",
    "three characters 'ON'+terminator or 'OFF' into the message text at the address held in the operand at",
    "$869A/$869B ($EFDF inside 'CUSTOM OFF', or $EFEA inside 'DESTROY OFF'), makes $1E the persistent",
    "message while the mode is on (and the id in the operand at $868D - 0 on the setup screen, $0A =",
    "'SETUP UNITS. PRESS F 1 WHEN DONE.' during placement - while it is off) and queues message $1E.",
    "In:  D_92F3 bit 7; operands $868D and $869A/$869B set by $820B/$821F or setDestroyModeMessage",
    "Out: D_9252 = D_9251 (queue emptied), D_92A1, zp_48/zp_49, zp_72 = 0, message $1E queued, C = 1",
    "Called from: fall-through from handleStarKeyToggle, and directly from runGameTypeMenu $8253"
   ],
   "line": "message queue write index"
  },
  "8676": {
   "unit": "game/mapGenerator6F00",
   "line": "read index = write index -> the queue is empty"
  },
  "8679": {
   "unit": "game/mapGenerator6F00",
   "line": "0 - show the next message immediately"
  },
  "867B": {
   "unit": "game/mapGenerator6F00",
   "line": "messageTimer 0 so the new message appears at once"
  },
  "867D": {
   "unit": "game/mapGenerator6F00",
   "line": "'ON' at $0650"
  },
  "867F": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $0650"
  },
  "8681": {
   "unit": "game/mapGenerator6F00",
   "line": "persistent message id $1E while the mode is on"
  },
  "8683": {
   "unit": "game/mapGenerator6F00",
   "line": "setupToggleFlag bit 7"
  },
  "8686": {
   "unit": "game/mapGenerator6F00",
   "line": "toggle on -> keep 'ON' and id $1E"
  },
  "8688": {
   "unit": "game/mapGenerator6F00",
   "line": "'OFF' at $064D"
  },
  "868A": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $064D"
  },
  "868C": {
   "unit": "game/mapGenerator6F00",
   "line": "off-state persistent message id (operand patched at $8213 = 0, or at $86AC = $0A)"
  },
  "868E": {
   "unit": "game/mapGenerator6F00",
   "line": "persistentMessageId $92A1"
  },
  "8691": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_48 = word pointer low"
  },
  "8693": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_49 = word pointer high"
  },
  "8695": {
   "unit": "game/mapGenerator6F00",
   "line": "copy three bytes (for 'ON' that is 'O', 'N'|$80 and the stray 'F' of the next word)"
  },
  "8697": {
   "unit": "game/mapGenerator6F00",
   "line": "read the word"
  },
  "8699": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "The STA operand below is a variable: $820B/$821F point it at $EFDF ('CUSTOM OFF') and",
    "setDestroyModeMessage points it at $EFEA ('DESTROY OFF').  The $FFFF assembled here is just the",
    "byte pattern that happens to be on disk."
   ],
   "line": "destination patched at $869A/$869B ($EFDF inside 'CUSTOM OFF' or $EFEA inside 'DESTROY OFF'); the $FFFF assembled here is only the byte pattern on disk"
  },
  "869C": {
   "unit": "game/mapGenerator6F00",
   "line": "next byte down"
  },
  "869D": {
   "unit": "game/mapGenerator6F00",
   "line": "three bytes copied?"
  },
  "869F": {
   "unit": "game/mapGenerator6F00",
   "line": "0 again"
  },
  "86A1": {
   "unit": "game/mapGenerator6F00",
   "line": "redundant - messageTimer was already zeroed at $867B"
  },
  "86A3": {
   "unit": "game/mapGenerator6F00",
   "line": "message id $1E"
  },
  "86A5": {
   "unit": "game/mapGenerator6F00",
   "line": "queue it"
  },
  "86A8": {
   "unit": "game/mapGenerator6F00",
   "line": "C = 1: the key was handled"
  },
  "86A9": {
   "unit": "game/mapGenerator6F00",
   "line": "C = 1, key handled"
  },
  "86AA": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "setDestroyModeMessage - re-aims the '*' toggle at the unit-placement phase: the off-state persistent",
    "message becomes id $0A ('SETUP UNITS. PRESS F 1 WHEN DONE.'), message slot $1E becomes 'DESTROY OFF'",
    "($EFE2) and the ON/OFF patch address becomes $EFEA, the 'OFF' inside that string.  The setup screen",
    "does the same at $820B/$821F with 'CUSTOM OFF' ($EFD8/$EFDF) and off-message 0.",
    "In:  nothing",
    "Out: $868D = $0A, message slot $1E -> $EFE2, $869A/$869B = $EFEA",
    "Called from: startGameSession $7B4B, just before the unit placement loop"
   ],
   "line": "message id $0A = 'SETUP UNITS. PRESS F 1 WHEN DONE.'"
  },
  "86AC": {
   "unit": "game/mapGenerator6F00",
   "line": "patch the LDX operand at $868D"
  },
  "86AF": {
   "unit": "game/mapGenerator6F00",
   "line": "message slot $1E"
  },
  "86B1": {
   "unit": "game/mapGenerator6F00",
   "line": "'DESTROY OFF' at $EFE2"
  },
  "86B3": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $EFE2"
  },
  "86B5": {
   "unit": "game/mapGenerator6F00",
   "line": "register it as message $1E"
  },
  "86B8": {
   "unit": "game/mapGenerator6F00",
   "line": "$EFEA = the 'OFF' inside 'DESTROY OFF'"
  },
  "86BA": {
   "unit": "game/mapGenerator6F00",
   "line": "patch $869A"
  },
  "86BD": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $EFEA"
  },
  "86BF": {
   "unit": "game/mapGenerator6F00",
   "line": "patch $869B"
  },
  "86C2": {
   "unit": "game/mapGenerator6F00",
   "line": "the '*' toggle now drives the DESTROY message"
  },
  "86C3": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "showCustomSummaryMessage - builds the status line 'CUSTOM:' [+ 'MAP,' when a named map is in use] +",
    "' MENUS OFF,/ON,  DAMAGE OFF./ON.' in the buffer at $0332 and registers it as the persistent message.",
    "The prefix is copied character by character from 'CUSTOM' ($CC19) and 'MAP TYPE' ($EF77); the option",
    "part is punched into the template ' MENUS XXXX DAMAGE XXX.' at $0636 by appendOnOffWord from bits 3",
    "and 4 of gameTypeOptions, and the finished template is then appended behind the prefix.",
    "In:  D_0BA3 bits 3, 4 and 7; the template at $0636 and the words at $064D",
    "Out: text in $0332.., the $0636 template overwritten in place, message slot $1E = $0332,",
    "     D_92A1 = $1E, message queued; self-modifies the ADC operand at $8712 with the prefix length",
    "Called from: startFilmPlayback $7D4B and runGameStartOptions $856D"
   ],
   "line": "start of the output buffer"
  },
  "86C5": {
   "unit": "game/mapGenerator6F00",
   "line": "'CUSTOM' at $CC19"
  },
  "86C8": {
   "unit": "game/mapGenerator6F00",
   "line": "strip the bit-7 string terminator"
  },
  "86CA": {
   "unit": "game/mapGenerator6F00",
   "line": "message buffer at $0332"
  },
  "86CD": {
   "unit": "game/mapGenerator6F00",
   "line": "next output position"
  },
  "86CE": {
   "unit": "game/mapGenerator6F00",
   "line": "six characters of 'CUSTOM'"
  },
  "86D0": {
   "unit": "game/mapGenerator6F00",
   "line": "keep copying until six are done"
  },
  "86D2": {
   "unit": "game/mapGenerator6F00",
   "line": "':'"
  },
  "86D4": {
   "unit": "game/mapGenerator6F00",
   "line": "append it to the buffer"
  },
  "86D7": {
   "unit": "game/mapGenerator6F00",
   "line": "next output position"
  },
  "86D8": {
   "unit": "game/mapGenerator6F00",
   "line": "gameTypeOptions bit 7 = custom (named) map"
  },
  "86DB": {
   "unit": "game/mapGenerator6F00",
   "line": "random map -> no 'MAP,' in the summary"
  },
  "86DD": {
   "unit": "game/mapGenerator6F00",
   "line": "start at the first character of 'MAP TYPE'"
  },
  "86DF": {
   "unit": "game/mapGenerator6F00",
   "line": "'MAP TYPE' at $EF77"
  },
  "86E2": {
   "unit": "game/mapGenerator6F00",
   "line": "strip any terminator bit"
  },
  "86E4": {
   "unit": "game/mapGenerator6F00",
   "line": "append to the buffer"
  },
  "86E7": {
   "unit": "game/mapGenerator6F00",
   "line": "next source character"
  },
  "86E8": {
   "unit": "game/mapGenerator6F00",
   "line": "next output position"
  },
  "86E9": {
   "unit": "game/mapGenerator6F00",
   "line": "only the first three characters, 'MAP'"
  },
  "86EB": {
   "unit": "game/mapGenerator6F00",
   "line": "keep copying until three are done"
  },
  "86ED": {
   "unit": "game/mapGenerator6F00",
   "line": "','"
  },
  "86EF": {
   "unit": "game/mapGenerator6F00",
   "line": "append it to the buffer"
  },
  "86F2": {
   "unit": "game/mapGenerator6F00",
   "line": "next output position"
  },
  "86F3": {
   "unit": "game/mapGenerator6F00",
   "line": "patch the ADC operand at $8712 with the length of the prefix built so far"
  },
  "86F6": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "Fill the two XXXX fields of the ' MENUS XXXX DAMAGE XXX.' template at $0636, put the terminator right",
    "behind the last word, then copy the whole template backwards onto the end of the prefix."
   ],
   "line": "template index 7 = the first X of ' MENUS XXXX'"
  },
  "86F8": {
   "unit": "game/mapGenerator6F00",
   "line": "gameTypeOptions"
  },
  "86FB": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 3 = UNIT MENUS"
  },
  "86FD": {
   "unit": "game/mapGenerator6F00",
   "line": "write 'OFF,' or 'ON, ' there"
  },
  "8700": {
   "unit": "game/mapGenerator6F00",
   "line": "template index 19 = the XXX of ' DAMAGE XXX'"
  },
  "8702": {
   "unit": "game/mapGenerator6F00",
   "line": "gameTypeOptions"
  },
  "8705": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 4 = DAMAGE"
  },
  "8707": {
   "unit": "game/mapGenerator6F00",
   "line": "write 'OFF,' or 'ON, ' there"
  },
  "870A": {
   "unit": "game/mapGenerator6F00",
   "line": "'.' with bit 7 set = end of string"
  },
  "870C": {
   "unit": "game/mapGenerator6F00",
   "line": "put it right behind the last word written"
  },
  "870F": {
   "unit": "game/mapGenerator6F00",
   "line": "X = index of that terminator"
  },
  "8710": {
   "unit": "game/mapGenerator6F00",
   "line": "no carry into the add"
  },
  "8711": {
   "unit": "game/mapGenerator6F00",
   "line": "+ prefix length (operand patched at $86F3)"
  },
  "8713": {
   "unit": "game/mapGenerator6F00",
   "line": "Y = destination index of the last template byte"
  },
  "8714": {
   "unit": "game/mapGenerator6F00",
   "line": "copy the template backwards so source and destination cannot collide"
  },
  "8717": {
   "unit": "game/mapGenerator6F00",
   "line": "into the message buffer"
  },
  "871A": {
   "unit": "game/mapGenerator6F00",
   "line": "next destination byte down"
  },
  "871B": {
   "unit": "game/mapGenerator6F00",
   "line": "next template byte down"
  },
  "871C": {
   "unit": "game/mapGenerator6F00",
   "line": "down to template index 0"
  },
  "871E": {
   "unit": "game/mapGenerator6F00",
   "line": "the finished string at $0332"
  },
  "8720": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $0332"
  },
  "8722": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "setPersistentMessage - registers the string A/Y as message slot $1E (setMessageSlot writes the pointer",
    "tables at $0500/$0524), makes $1E the persistent status message and queues it.",
    "In:  A/Y = bit-7 terminated string",
    "Out: D_0500[$1E]/D_0524[$1E] = A/Y, D_92A1 = $1E, message queued, X = $1E",
    "Called from: showScenarioBannerAndWaitForButton $8787, plus fall-through from",
    "     showCustomSummaryMessage"
   ],
   "line": "message slot $1E"
  },
  "8724": {
   "unit": "game/mapGenerator6F00",
   "line": "setMessageSlot leaves X alone"
  },
  "8727": {
   "unit": "game/mapGenerator6F00",
   "line": "A = $1E"
  },
  "8728": {
   "unit": "game/mapGenerator6F00",
   "line": "persistentMessageId $92A1 - the line reappears after any transient message"
  },
  "872B": {
   "unit": "game/mapGenerator6F00",
   "line": "queue it for display"
  },
  "872E": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "appendOnOffWord - writes 'OFF,' (A = 0) or 'ON, ' (A != 0) into the template at $0636 starting at",
    "index X: copies the bit-7 terminated word from $064D (OFF) or $064D+3 (ON), adds a comma and, for ON,",
    "a trailing space so both forms occupy four characters.  X comes back pointing at the comma.",
    "In:  A = option state (0 = off), X = destination index inside $0636",
    "Out: four characters written at $0636+X, X = index of the comma",
    "Called from: showCustomSummaryMessage $86FD (UNIT MENUS) and $8707 (DAMAGE)"
   ],
   "line": "remember the state for the trailing-space decision"
  },
  "872F": {
   "unit": "game/mapGenerator6F00",
   "line": "Y = 0 selects 'OFF' at $064D"
  },
  "8730": {
   "unit": "game/mapGenerator6F00",
   "line": "off -> keep Y = 0"
  },
  "8732": {
   "unit": "game/mapGenerator6F00",
   "line": "on -> 'ON' at $064D+3"
  },
  "8734": {
   "unit": "game/mapGenerator6F00",
   "line": "next character of the word"
  },
  "8737": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 7 set = last character"
  },
  "8739": {
   "unit": "game/mapGenerator6F00",
   "line": "store it in the template"
  },
  "873C": {
   "unit": "game/mapGenerator6F00",
   "line": "next template position"
  },
  "873D": {
   "unit": "game/mapGenerator6F00",
   "line": "next source character"
  },
  "873E": {
   "unit": "game/mapGenerator6F00",
   "line": "always - continue with the next character"
  },
  "8740": {
   "unit": "game/mapGenerator6F00",
   "line": "strip the terminator bit"
  },
  "8742": {
   "unit": "game/mapGenerator6F00",
   "line": "store the last character"
  },
  "8745": {
   "unit": "game/mapGenerator6F00",
   "line": "next template position"
  },
  "8746": {
   "unit": "game/mapGenerator6F00",
   "line": "','"
  },
  "8748": {
   "unit": "game/mapGenerator6F00",
   "line": "store it"
  },
  "874B": {
   "unit": "game/mapGenerator6F00",
   "line": "the saved state"
  },
  "874C": {
   "unit": "game/mapGenerator6F00",
   "line": "'OFF,' is already four characters"
  },
  "874E": {
   "unit": "game/mapGenerator6F00",
   "line": "one position past the comma"
  },
  "874F": {
   "unit": "game/mapGenerator6F00",
   "line": "' ' so that 'ON, ' is four too"
  },
  "8751": {
   "unit": "game/mapGenerator6F00",
   "line": "store the padding blank"
  },
  "8754": {
   "unit": "game/mapGenerator6F00",
   "line": "leave X on the comma"
  },
  "8755": {
   "unit": "game/mapGenerator6F00",
   "line": "X points at the comma"
  },
  "8756": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "showScenarioBannerAndWaitForButton - prints 'STANDARD' or 'CUSTOM' (from $CC11, chosen by $0BA3 bit",
    "6), the scenario name (from $CCC8, bits 0-2) and '  SCENARIO' ($CC04), each centred in 13 columns,",
    "puts 'PRESS BUTTON WHEN READY.' ($CBBE) on the status line and then services the link until the fire",
    "button is clicked.",
    "In:  D_0BA3, the fire button, the command exchange",
    "Out: info panel text, D_92A1 = $1E, status line cleared on exit",
    "Called from: runGameStartOptions $855C"
   ],
   "line": "text cursor row 15"
  },
  "8758": {
   "unit": "game/mapGenerator6F00",
   "line": "clear the info panel, cursor to row 15"
  },
  "875B": {
   "unit": "game/mapGenerator6F00",
   "line": "entry 0 = STANDARD"
  },
  "875D": {
   "unit": "game/mapGenerator6F00",
   "line": "gameTypeOptions"
  },
  "8760": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 6 = CUSTOM rules"
  },
  "8762": {
   "unit": "game/mapGenerator6F00",
   "line": "standard rules"
  },
  "8764": {
   "unit": "game/mapGenerator6F00",
   "line": "entry 1 = CUSTOM"
  },
  "8765": {
   "unit": "game/mapGenerator6F00",
   "line": "rules name table at $CC11 (8-byte entries)"
  },
  "8767": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $CC11"
  },
  "8769": {
   "unit": "game/mapGenerator6F00",
   "line": "print it centred in 13 columns"
  },
  "876C": {
   "unit": "game/mapGenerator6F00",
   "line": "next line"
  },
  "876F": {
   "unit": "game/mapGenerator6F00",
   "line": "gameTypeOptions"
  },
  "8772": {
   "unit": "game/mapGenerator6F00",
   "line": "bits 0-2 = game type"
  },
  "8774": {
   "unit": "game/mapGenerator6F00",
   "line": "X = scenario index"
  },
  "8775": {
   "unit": "game/mapGenerator6F00",
   "line": "scenario name table at $CCC8 (8-byte entries)"
  },
  "8777": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $CCC8"
  },
  "8779": {
   "unit": "game/mapGenerator6F00",
   "line": "print the scenario name centred"
  },
  "877C": {
   "unit": "game/mapGenerator6F00",
   "line": "'  SCENARIO' at $CC04 (it starts and ends with a CR)"
  },
  "877E": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $CC04"
  },
  "8780": {
   "unit": "game/mapGenerator6F00",
   "line": "print it centred"
  },
  "8783": {
   "unit": "game/mapGenerator6F00",
   "line": "'PRESS BUTTON WHEN READY.' at $CBBE"
  },
  "8785": {
   "unit": "game/mapGenerator6F00",
   "line": "high byte of $CBBE"
  },
  "8787": {
   "unit": "game/mapGenerator6F00",
   "line": "show it as the persistent status message"
  },
  "878A": {
   "unit": "game/mapGenerator6F00",
   "line": "keep the two machines in lock step while waiting"
  },
  "878D": {
   "unit": "game/mapGenerator6F00",
   "line": "new fire click?"
  },
  "8790": {
   "unit": "game/mapGenerator6F00",
   "line": "no -> keep servicing"
  },
  "8792": {
   "unit": "game/mapGenerator6F00",
   "line": "erase the status line and return"
  },
  "8795": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "printCentredTableEntry - sets the centring field width to 13 columns and prints entry X of a table of",
    "8-byte bit-7 terminated strings whose base is in A/Y.  Used for the STANDARD/CUSTOM words and for the",
    "seven scenario names.",
    "In:  A/Y = table base, X = entry index",
    "Out: D_90EF = $0D, string printed centred (printStringAtPointer clears D_90EF again)",
    "Called from: $857F, $8769, $8779"
   ],
   "line": "keep the table base low byte across the store"
  },
  "8796": {
   "unit": "game/mapGenerator6F00",
   "line": "13 columns"
  },
  "8798": {
   "unit": "game/mapGenerator6F00",
   "line": "textCentreWidth $90EF - the field the next string is centred in"
  },
  "879B": {
   "unit": "game/mapGenerator6F00",
   "line": "table base low byte again"
  },
  "879C": {
   "unit": "game/mapGenerator6F00",
   "line": "print entry X (base + X*8)"
  },
  "879F": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "Result and alert message strings shared with overlay variant B.  From $879F on the bytes are",
    "identical in both variants; only $8789-$879E differ, so in variant A messages $11 ('WE LOST ON",
    "POINTS!') and $12 ('WE WON ON POINTS!') are broken while messages $13-$16 and 'DRONE ALERT!' still",
    "read correctly.  They are only ever shown at game end, when variant B is resident."
   ],
   "line": "tail of message $12 'WE WON ON POINTS!'; its first four bytes at $879B are code here"
  },
  "87AC": {
   "unit": "game/mapGenerator6F00",
   "line": "message $13 (pointer $0500/$0524 index $13 = $87AC)"
  },
  "87BA": {
   "unit": "game/mapGenerator6F00",
   "line": "message $14"
  },
  "87CE": {
   "unit": "game/mapGenerator6F00",
   "line": "message $15; the solo trainer overlay (T35) reuses $87CE+unit as a per-unit work table ($EB29/$EB53 store the game clock there), so these strings are clobbered in a solo game"
  },
  "87E3": {
   "unit": "game/mapGenerator6F00",
   "line": "message $16"
  },
  "87ED": {
   "unit": "game/mapGenerator6F00",
   "line": "installed as run-time message slot $20 by overlay A at $7BA6"
  },
  "87F9": {
   "unit": "game/mapGenerator6F00",
   "line": "six unused bytes between the last string and the identity flag; referenced by nothing"
  },
  "87FF": {
   "unit": "game/mapGenerator6F00",
   "line": "$00 = variant A (map generator and setup) is resident; bit 7 is tested at $1036/$1080"
  }
 },
 "dataTypes": {
  "844F": [
   "byte",
   1
  ],
  "8450": [
   "byte",
   1
  ],
  "879F": [
   "text",
   13
  ],
  "87AC": [
   "text",
   14
  ],
  "87BA": [
   "text",
   20
  ],
  "87CE": [
   "text",
   21
  ],
  "87E3": [
   "text",
   10
  ],
  "87ED": [
   "text",
   12
  ],
  "87F9": [
   "byte",
   6
  ],
  "87FF": [
   "byte",
   1
  ]
 }
}