{ "chunk": "game_ovl_6F00_A_844F", "unit": "game/ovl_6F00_A", "routines": [ { "addr": "8451", "name": "editValueWithJoystick", "summary": "Generic numeric option editor used by the custom-scenario setup. A = exclusive upper limit (patched into the CMP at $8492), Y = display multiplier (patched into $8469). Loops: un-highlights the one-row menu, prints editValue*Y in decimal at column 1 of the value window (multiply8x8 $FCCD -> A=lo/Y=hi, then $C17D), clears the rest of the line, services the link (serviceCommandExchange), blinks the row, and applies joystick up/down as +1/-1 (rejecting values >= limit or below 0, playing sound 2 on a change, auto-repeat via setJoystickRepeatDelay). Returns when the fire button is pressed (checkFirePressed).", "inputs": "A = limit (value must stay < A), Y = multiplier for display, D_844F initial value, zp_5D joystick, zp_6C repeat timer, zp_6E blink timer, menu window set up by beginValueEdit", "outputs": "D_844F = edited value; D_92C5 = 1; text printed in the info panel; sounds 2", "confidence": "high" }, { "addr": "84AA", "name": "applyHandicapPoints", "summary": "Tail of runGameStartOptions (reached by JMP from $85B9). Computes the default handicap for the asymmetric scenarios: game type 1 (QB SNEAK) gives side 0 a handicap of 2 (20 points), game type 6 (DEFENDER) gives side 1 a handicap of $14 (200 points), everything else 0. When the custom toggle (D_92F3 bit 7) is set the player edits the value instead ('HANDICAP', 0..50 shown x10) starting from that default. A nonzero result is sent as command $A5 kind 0 (value*10 points for the sender's side, cmdSetupOption); zero is not sent.", "inputs": "D_0BA3 bits 0-2 game type, D_0B9F playerSide, D_92F3 bit 7 custom flag", "outputs": "command $A5 00 value queued via queueCmd3 (zp_74 = 0, zp_75 = value); info panel used", "confidence": "high" }, { "addr": "84EC", "name": "editTerrainPoints", "summary": "Custom option 'TERRAIN PTS': starts from D_92AC[opponent side] (points awarded for entering the enemy zone), lets the player pick 0..2 with editValueWithJoystick and sends command $A5 kind 1 (cmdSetupOption stores it in $92AC of the other side).", "inputs": "D_0B9F playerSide, D_92AC", "outputs": "command $A5 01 value queued (zp_74 = 1, zp_75 = value)", "confidence": "medium" }, { "addr": "84F1", "name": "editTerrainPointsForSide", "summary": "Entry into editTerrainPoints with the side index already in A (A -> Y, X = D_92AC[Y]). In variant A nothing calls it; the XREF caller at $83DE belongs to overlay variant B, where $84F1 is a different routine.", "inputs": "A = side index 0/1", "outputs": "as editTerrainPoints", "confidence": "medium" }, { "addr": "8511", "name": "editDronesAndMissiles", "summary": "Custom options 'DRONES' (0..9, from D_92AE) and 'MISSILES' (label $CC9E, 0..36, from D_92B0), each edited with beginValueEdit + editValueWithJoystick. The two results are sent as one command $90 x=drones y=missiles; in the setup phase cmdMissileStrike ($53C0) stores them as dronesLeft/missilesLeft for the sender.", "inputs": "D_92AE dronesLeft, D_92B0 missilesLeft", "outputs": "command $90 drones missiles queued (zp_74 = drones, zp_75 = missiles)", "confidence": "medium" }, { "addr": "8518", "name": "editDronesAndMissilesBody", "summary": "Not a real entry point in variant A: it is the JSR beginValueEdit inside editDronesAndMissiles (A/Y/X must already hold the label and value). The label exists because the main program calls $8518 at $1460/$14D3, which is a routine of overlay variant B (menu screen).", "inputs": "A/Y = label, X = value (must be preset)", "outputs": "as editDronesAndMissiles", "confidence": "high" }, { "addr": "8547", "name": "runGameStartOptions", "summary": "Called once from the new-game start sequence ($7AF7) after the setup has been saved and before unit placement. Sets gamePhase $7F, hides the viewport (sub_8364), draws the overview (side 0: drawOverviewMap, side 1: clearScreenAndRedrawGameScreen), shows the 'STANDARD/CUSTOM SCENARIO - PRESS BUTTON WHEN READY.' banner (showScenarioBannerAndWaitForButton), copies gameTypeOptions bit 6 into D_8450 and (shifted to bit 7) into D_92F3. If CUSTOM rules are on it shows the custom summary message, prints the game type name and a 2-item STANDARD/CUSTOM menu (rows at column 28, width 10, runMenuLoopWithFlag); choosing CUSTOM (D_8450 = 1) runs editComcenSpeed, editTerrainPoints and editDronesAndMissiles. Then, for game types 4-6 (SLUGGERS, FULL WAR, DEFENDER), sub_8378 sets up the recycler, and finally it jumps to applyHandicapPoints.", "inputs": "D_0BA3 gameTypeOptions, D_0B9F playerSide, menu/text engine state", "outputs": "zp_B1 = $7F, D_8450, D_92F3, setup commands $A5/$90/$9C queued, screen redrawn", "confidence": "medium" }, { "addr": "85BC", "name": "editComcenSpeed", "summary": "Custom option 'COMCEN SPEED': starts from D_92B4 (own comcen speed setting 0..3), edits it with editValueWithJoystick (limit 4) and sends command $A5 kind 3 (cmdSetupOption writes $92B4 of the sender's side; $7B6E later maps the setting through the table at $78BF).", "inputs": "D_92B4", "outputs": "command $A5 03 value queued (zp_74 = 3, zp_75 = value)", "confidence": "medium" }, { "addr": "85DB", "name": "beginValueEdit", "summary": "Common prologue of the value editors: stores the label pointer (patched into $85EA/$85EC), sets editValue = X, clears the info panel in colour 8 and sets row 15 (sub_8441), prints the label centred, moves the text window left edge to column 29, starts a new line and records that row as menuFirstRow with menuSelectedItem = 0. Falls into the tail at $8601 which sets selectedUnit = $FE (plain menu, no unit) and the window width to 5 for the highlight bar.", "inputs": "A/Y = label string (bit-7 terminated), X = initial value", "outputs": "D_844F = X, D_91D5 = 0, D_91D6 = row, D_90F8 = $FE, zp_3B = $1D, zp_3C = 5, label printed", "confidence": "high" }, { "addr": "8601", "name": "setValueEditWindow", "summary": "Tail of beginValueEdit: selectedUnit = $FE and textWindowWidth = 5. The sub_ label only exists because $8601 is a routine entry in overlay variant B; in A it is only reached by fall-through.", "inputs": "-", "outputs": "D_90F8 = $FE, zp_3C = 5", "confidence": "high" }, { "addr": "860B", "name": "editOptionBitOnOff", "summary": "Two-row OFF/ON menu for one bit of gameTypeOptions, used by the scenario setup screen for 'UNIT MENUS' (mask $08, $82B3) and 'DAMAGE' (mask $10, $82BC). Stores the label pointer and mask in self-modifying operands, hides the viewport, clears the panel to row 14, prints the label centred with the current state pre-selected (row 0 = OFF from $064D, row 1 = ON via sub_C137), runs runMenuLoopWithFlag with width 5 at column 27 and then clears or sets the mask bit in D_0BA3 according to the chosen row.", "inputs": "A/Y = label string, X = bit mask, D_0BA3", "outputs": "D_0BA3 bit updated; D_91D4 = 2, D_91D5 = choice", "confidence": "high" }, { "addr": "862D", "name": "runOnOffMenuAndApplyBit", "summary": "Tail of editOptionBitOnOff (menuItemCount = 2, print OFF/ON, run the menu, apply the mask at $8621+1). Only an entry point in overlay variant B.", "inputs": "label already printed, mask operand at $8622", "outputs": "D_0BA3 updated", "confidence": "high" }, { "addr": "8632", "name": "printOnOffMenuAndApplyBit", "summary": "Inner tail of editOptionBitOnOff starting at the OFF/ON printing. The main program's JSR $8632 at $176B targets overlay variant B's routine of the same address, not this code.", "inputs": "menu state, mask operand at $8622", "outputs": "D_0BA3 updated", "confidence": "high" }, { "addr": "8658", "name": "handleStarKeyToggle", "summary": "Per-frame hook called while overlay A is resident in non-battle phases (battlefield loop via the trampoline $25C4 when zp_B1 != 0, and runMenuLoop at $6002 when zp_B1 == $FF). If no chat entry is pending (D_929C bit 7 clear) and the last key is '*' ($AA) it consumes the key, toggles bit 7 of D_92F3 and falls into showToggleStateMessage (returns C = 1). Otherwise returns C = 0. During unit placement the flag means DESTROY mode (clicking an own unit sends $91 self destruct, $209F); on the scenario setup screen it means CUSTOM rules.", "inputs": "D_929C chatState, D_9248 lastKeyCode, D_92F3", "outputs": "C = 1 and D_92F3 bit 7 toggled when '*' was pressed (D_9248 = $FF), else C = 0", "confidence": "high" }, { "addr": "8673", "name": "showToggleStateMessage", "summary": "Shows the state of the '*' toggle: empties the message queue (tail = head), patches the word 'ON' ($0650) or 'OFF' ($064D) into the message text (3 bytes copied to the address patched at $869A/$869B: $EFDF inside 'CUSTOM OFF' or $EFEA inside 'DESTROY OFF'), sets persistentMessageId to $1E while the mode is on (or to the operand at $868D when off: 0 on the setup screen, 10 = 'SETUP UNITS...' during placement), clears the message timer and queues message $1E. Returns C = 1. Also called directly from the setup screen ($8253) to show 'CUSTOM ON' initially.", "inputs": "D_92F3 bit 7, operands patched by $820B/$821F or setDestroyModeMessage", "outputs": "D_9252 = D_9251, D_92A1, zp_72 = 0, message $1E queued, C = 1, zp_48/49 = word pointer", "confidence": "high" }, { "addr": "86AA", "name": "setDestroyModeMessage", "summary": "Prepares the '*' toggle for the unit-placement phase (called at $7B4B before the placement loop): off-state persistent message = 10 ('SETUP UNITS. PRESS F 1 WHEN DONE.'), message slot $1E -> 'DESTROY OFF' ($EFE2 in the T34 $EC00 sub-overlay), and the ON/OFF patch address = $EFEA (the 'OFF' inside that string). The setup-screen code at $820B/$821F does the same with 'CUSTOM OFF' ($EFD8/$EFDF) and off-message 0.", "inputs": "-", "outputs": "$868D = $0A, message slot $1E (D_0500/D_0524 index $1E) = $EFE2, $869A/$869B = $EFEA", "confidence": "high" }, { "addr": "86C3", "name": "showCustomSummaryMessage", "summary": "Builds the status line 'CUSTOM:' [+ 'MAP,' when D_0BA3 bit 7 is set] + ' MENUS OFF,/ON, DAMAGE OFF./ON.' into the buffer at $0332 (prefix from $CC19 'CUSTOM' and $EF77 'MAP TYPE'; the option part is filled into the template at $0636 ' MENUS XXXX DAMAGE XXX.' by appendOnOffWord with bits 3 and 4 of gameTypeOptions) and registers it as the persistent message $1E (setPersistentMessage). Called when a game starts or resumes with CUSTOM rules ($7D4B, $856D).", "inputs": "D_0BA3 bits 3, 4, 7; templates at $0636 and $064D; strings $CC19, $EF77", "outputs": "$0332.. text, $0636 template overwritten, message slot $1E = $0332, D_92A1 = $1E, message queued", "confidence": "high" }, { "addr": "8722", "name": "setPersistentMessage", "summary": "Registers the string A/Y as message slot $1E (sub_C924 writes the pointer tables at $0500/$0524), makes $1E the persistent status message (D_92A1) and queues it with sub_C566. Used for 'PRESS BUTTON WHEN READY.' and the custom summary; the entry at $8722 is also the tail of showCustomSummaryMessage.", "inputs": "A/Y = string pointer", "outputs": "D_0500[$1E]/D_0524[$1E], D_92A1 = $1E, message queued, X = $1E", "confidence": "high" }, { "addr": "872E", "name": "appendOnOffWord", "summary": "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 $0650 (ON), adds a comma, and for ON adds a trailing space so both forms are 4 characters; returns X pointing at the comma.", "inputs": "A = option state (0 = off), X = destination index in $0636", "outputs": "$0636+X.. written, X = index of the comma", "confidence": "high" }, { "addr": "8756", "name": "showScenarioBannerAndWaitForButton", "summary": "Clears the info panel (row 15) and prints, centred in 13 columns, 'STANDARD' or 'CUSTOM' (table $CC11, chosen by D_0BA3 bit 6), the game type name (table $CCC8, bits 0-2) and the string ' SCENARIO' ($CC04). Sets 'PRESS BUTTON WHEN READY.' ($CBBE) as persistent message $1E, then loops on serviceCommandExchange until checkFirePressed reports a click, and finally clears the status line (sub_C39F).", "inputs": "D_0BA3, fire button, link", "outputs": "info panel text, D_92A1 = $1E, status line cleared", "confidence": "high" }, { "addr": "8795", "name": "printCentredTableEntry", "summary": "Sets textCentreWidth (D_90EF) to 13 and prints entry X of a table of 8-byte bit-7 terminated strings at A/Y through sub_C100 (used for the STANDARD/CUSTOM words and the game type names).", "inputs": "A/Y = table base, X = entry index", "outputs": "text printed, D_90EF = $0D", "confidence": "high" } ], "variables": [ { "addr": "844F", "scope": "abs", "name": "editValue", "meaning": "value being edited by editValueWithJoystick (initialised by beginValueEdit from X, read back by the option editors)", "confidence": "high" }, { "addr": "8450", "scope": "abs", "name": "customSetupChosen", "meaning": "nonzero while custom options are being set at game start: first D_0BA3 & $40, then the STANDARD(0)/CUSTOM(1) menu choice; sub_8378 only offers the recycler mode menu when it is set", "confidence": "high" }, { "addr": "87FF", "scope": "abs", "name": "overlayVariantFlag", "meaning": "last byte of the $6F00 overlay: $00 in variant A, $FF in variant B; bit 7 is tested by the main program ($1036, $1080) to decide whether variant B must be (re)loaded", "confidence": "high" }, { "addr": "92F3", "scope": "abs", "name": "setupToggleFlag", "meaning": "bit 7 = state of the '*' key toggle handled by handleStarKeyToggle: CUSTOM rules on the scenario setup screen (mirrors D_0BA3 bit 6 << 1), DESTROY mode during unit placement (clicking an own unit sends $91 and clears it)", "confidence": "high" }, { "addr": "0BA3", "scope": "abs", "name": "gameTypeOptions", "meaning": "bits 0-2 game type (0 SCRIMAGE .. 6 DEFENDER, names at $CCC8), bit 3 UNIT MENUS, bit 4 DAMAGE (both edited by editOptionBitOnOff), bit 6 CUSTOM rules, bit 7 custom MAP (adds 'MAP,' to the custom summary)", "confidence": "medium" }, { "addr": "0B9F", "scope": "abs", "name": "playerSide", "meaning": "local side 0/1; EOR 1 = opponent (index into the per-side tables $92A6/$92AC)", "confidence": "high" }, { "addr": "0BA5", "scope": "abs", "name": "commBuildFlag", "meaning": "bit 7 = comm build 1 (T35, solo trainer) resident: sub_8378 then forces recycler mode NONE for both sides", "confidence": "medium" }, { "addr": "92A1", "scope": "abs", "name": "persistentMessageId", "meaning": "id of the status-line message that stays/returns after transient messages (0 none, $0A 'SETUP UNITS...', $1E the dynamic slot used by this code)", "confidence": "high" }, { "addr": "92A6", "scope": "abs", "name": "recyclerModeBySide", "meaning": "2 bytes: recycler setting per side, 0 FULL, 1 HALF, 2 NONE (words at $0652); chosen in sub_8378 and sent with command $9C", "confidence": "high" }, { "addr": "92AC", "scope": "abs", "name": "terrainPointsBySide", "meaning": "2 bytes: 'TERRAIN PTS' (0..2) per side, edited by editTerrainPoints for the opponent index and sent as $A5 kind 1", "confidence": "medium" }, { "addr": "92AE", "scope": "abs", "name": "dronesLeft", "meaning": "2 bytes (own, opponent): number of drones, 'DRONES' custom option 0..9, sent as the x byte of command $90 during setup", "confidence": "high" }, { "addr": "92B0", "scope": "abs", "name": "missilesLeft", "meaning": "2 bytes: number of missiles, 'MISSILES' custom option 0..36, sent as the y byte of command $90 during setup", "confidence": "high" }, { "addr": "92B4", "scope": "abs", "name": "comcenSpeedSetting", "meaning": "2 bytes per side: 'COMCEN SPEED' option 0..3 at setup time (sent as $A5 kind 3), later replaced by the speed class looked up at $7B6E", "confidence": "medium" }, { "addr": "91D4", "scope": "abs", "name": "menuItemCount", "meaning": "number of rows of the current menu (2 for OFF/ON and STANDARD/CUSTOM, 3 for the recycler mode menu)", "confidence": "high" }, { "addr": "91D5", "scope": "abs", "name": "menuSelectedItem", "meaning": "highlighted/chosen menu row; the value editors keep it at 0 (single row)", "confidence": "high" }, { "addr": "91D6", "scope": "abs", "name": "menuFirstRow", "meaning": "screen row of menu row 0 (the value editors use the row below the label)", "confidence": "high" }, { "addr": "91D8", "scope": "abs", "name": "pickedCellX", "meaning": "map column returned by runTargetCursorLoop in free-pick mode (recycler location)", "confidence": "high" }, { "addr": "91D9", "scope": "abs", "name": "pickedCellY", "meaning": "map row returned by runTargetCursorLoop in free-pick mode", "confidence": "high" }, { "addr": "92C5", "scope": "abs", "name": "menuBlinkState", "meaning": "0 while the menu row is drawn highlighted, 1 normal; editValueWithJoystick sets 1 before redrawing the value", "confidence": "high" }, { "addr": "9248", "scope": "abs", "name": "lastKeyCode", "meaning": "last typed key with bit 7 set ($AA = '*'), $FF = none; consumed by handleStarKeyToggle", "confidence": "high" }, { "addr": "929C", "scope": "abs", "name": "chatState", "meaning": "bit 7 set = chat text entry in progress; handleStarKeyToggle ignores keys then", "confidence": "medium" }, { "addr": "9251", "scope": "abs", "name": "messageQueueHead", "meaning": "message queue index; showToggleStateMessage copies it to the tail to flush the queue", "confidence": "medium" }, { "addr": "9252", "scope": "abs", "name": "messageQueueTail", "meaning": "message queue index (8-entry queue at $9249)", "confidence": "medium" }, { "addr": "9242", "scope": "abs", "name": "unitDrawOverride", "meaning": "set to $FE by sub_8364 together with selectedUnit while the viewport is hidden", "confidence": "low" }, { "addr": "90F8", "scope": "abs", "name": "selectedUnit", "meaning": "unit the menus act on; $FE = plain menu without a unit (set by beginValueEdit and sub_8364)", "confidence": "high" }, { "addr": "90FB", "scope": "abs", "name": "currentScreen", "meaning": "0 = battlefield screen; sub_8364 forces it to 0", "confidence": "high" }, { "addr": "90EF", "scope": "abs", "name": "textCentreWidth", "meaning": "nonzero = the next string is centred in this many columns (13 for the banner words, zp_3C via sub_C121)", "confidence": "high" }, { "addr": "9022", "scope": "abs", "name": "spriteEnableShadow", "meaning": "shadow of $D015; cleared after the recycler has been located", "confidence": "high" }, { "addr": "FA70", "scope": "abs", "name": "unitUnderCellAlias", "meaning": "terrain under a unit indexed by the raw map byte ($80|unit); sub_8378 uses it so a cell occupied by a unit counts as its underlying terrain when checking for a plain ($40) recycler site", "confidence": "high" }, { "addr": "0332", "scope": "abs", "name": "customSummaryText", "meaning": "text buffer (in the $0200 setup block area) that receives 'CUSTOM:[MAP,] MENUS xxx, DAMAGE xxx.' built by showCustomSummaryMessage; registered as message slot $1E", "confidence": "high" }, { "addr": "0636", "scope": "abs", "name": "optionSummaryTemplate", "meaning": "23-byte template ' MENUS XXXX DAMAGE XXX.' (bit-7 terminated) whose XXXX/XXX fields are filled with OFF,/ON, by appendOnOffWord", "confidence": "high" }, { "addr": "064D", "scope": "abs", "name": "wordOff", "meaning": "'OFF' (bit-7 terminated), followed by 'ON' at $0650 and the option words FULL/HALF/NONE at $0652", "confidence": "high" }, { "addr": "0650", "scope": "abs", "name": "wordOn", "meaning": "'ON' (bit-7 terminated); 3 bytes from here (O, N|$80, F) are copied over the OFF in the CUSTOM/DESTROY message", "confidence": "high" }, { "addr": "0500", "scope": "abs", "name": "messagePtrLo", "meaning": "low bytes of the status message pointer table indexed by message id (high bytes at $0524); slot $1E is rewritten at run time by sub_C924 from this overlay", "confidence": "high" }, { "addr": "EFDF", "scope": "abs", "name": "customOnOffWord", "meaning": "the 'OFF' inside 'CUSTOM OFF' ($EFD8, T34 $EC00 sub-overlay), overwritten with ON/OFF by showToggleStateMessage while the setup screen uses it", "confidence": "high" }, { "addr": "EFEA", "scope": "abs", "name": "destroyOnOffWord", "meaning": "the 'OFF' inside 'DESTROY OFF' ($EFE2), overwritten with ON/OFF by showToggleStateMessage during unit placement", "confidence": "high" }, { "addr": "3B", "scope": "zp", "name": "textWindowLeft", "meaning": "text window left column (28 for the OFF/ON and STANDARD/CUSTOM menus, 29 for the value editors, 30 for the recycler menu; decremented once more before the menu loop)", "confidence": "high" }, { "addr": "3C", "scope": "zp", "name": "textWindowWidth", "meaning": "text window width = width of the menu highlight bar (5 value editor / OFF-ON, 10 STANDARD/CUSTOM, 6 recycler) and centring width for sub_C121", "confidence": "high" }, { "addr": "3D", "scope": "zp", "name": "textColour", "meaning": "text colour byte (8 for all panels drawn by this code)", "confidence": "high" }, { "addr": "3F", "scope": "zp", "name": "textCursorCol", "meaning": "text cursor column relative to the window (1 for the value)", "confidence": "high" }, { "addr": "40", "scope": "zp", "name": "textCursorRow", "meaning": "text cursor row; copied into menuFirstRow", "confidence": "high" }, { "addr": "42", "scope": "zp", "name": "textPadColour", "meaning": "colour of centring padding, kept equal to textColour (8)", "confidence": "high" }, { "addr": "48", "scope": "zp", "name": "wordPtr", "meaning": "in this chunk: pointer (lo) to the ON/OFF word copied by showToggleStateMessage (general fill/map pointer elsewhere)", "confidence": "high" }, { "addr": "49", "scope": "zp", "name": "wordPtrHi", "meaning": "high byte of wordPtr", "confidence": "high" }, { "addr": "5D", "scope": "zp", "name": "joyDirection", "meaning": "joystick direction bits, active low, $0F centred; the value editor ORs with $0C and maps up/down to +1/-1", "confidence": "high" }, { "addr": "6C", "scope": "zp", "name": "joyRepeatTimer", "meaning": "frame countdown gating joystick auto-repeat in the value editor", "confidence": "high" }, { "addr": "6E", "scope": "zp", "name": "menuBlinkTimer", "meaning": "frame countdown; when 0 the value editor toggles the row highlight", "confidence": "high" }, { "addr": "72", "scope": "zp", "name": "messageTimer", "meaning": "status message countdown, cleared by showToggleStateMessage so the new message appears at once", "confidence": "medium" }, { "addr": "73", "scope": "zp", "name": "cmdParam0", "meaning": "first parameter of an outgoing command (recycler mode for $9C)", "confidence": "high" }, { "addr": "74", "scope": "zp", "name": "cmdParam1", "meaning": "second command parameter (option kind for $A5, drones for $90, x for $9C)", "confidence": "high" }, { "addr": "75", "scope": "zp", "name": "cmdParam2", "meaning": "third command parameter (option value for $A5, missiles for $90, y for $9C)", "confidence": "high" }, { "addr": "A5", "scope": "zp", "name": "viewOriginCol", "meaning": "map column of the viewport's left edge; sub_8364 parks it at 45 (off the map) to blank the viewport", "confidence": "high" }, { "addr": "A6", "scope": "zp", "name": "viewOriginRow", "meaning": "map row of the viewport's top edge; 45 = viewport blanked", "confidence": "high" }, { "addr": "B1", "scope": "zp", "name": "gamePhase", "meaning": "0 battle; $7F during the game-start option dialogs (runGameStartOptions), $3F/$FF during unit placement where handleStarKeyToggle is polled", "confidence": "high" }, { "addr": "BB", "scope": "zp", "name": "cursorTargetMode", "meaning": "$FF = free cell pick for runTargetCursorLoop (recycler location)", "confidence": "high" }, { "addr": "18", "scope": "zp", "name": "productLo", "meaning": "low byte of the multiply8x8 product (unused here; A already holds it)", "confidence": "medium" } ], "dataBlocks": [ { "addr": "844F", "length": 1, "type": "byteTable", "name": "editValue", "description": "current value of the joystick value editor" }, { "addr": "8450", "length": 1, "type": "byteTable", "name": "customSetupChosen", "description": "nonzero = CUSTOM options chosen at game start" }, { "addr": "879F", "length": 13, "type": "text", "name": "msgWonOnPointsTail", "description": "'ON ON POINTS!' - the tail of message $12 'WE WON ON POINTS!' whose first four bytes ($879B-$879E) are overlaid by code in variant A (pla / jmp sub_C100); overlay variant B holds the complete string at $879B. Message pointer table slots $11-$16 ($0500/$0524) point to $8789, $879B, $87AC, $87BA, $87CE, $87E3 and are only valid with variant B resident." }, { "addr": "87AC", "length": 14, "type": "text", "name": "msgItWasADraw", "description": "'IT WAS A DRAW.' = message $13 (game result)" }, { "addr": "87BA", "length": 20, "type": "text", "name": "msgWeWereKnockedOut", "description": "'WE WERE KNOCKED OUT!' = message $14" }, { "addr": "87CE", "length": 21, "type": "text", "name": "msgWeWonByKnockout", "description": "'WE WON BY A KNOCKOUT!' = message $15. Comm build 1 (T35, solo trainer) reuses $87CE+unit as a per-unit work table ($EB29/$EB53 store the game clock there), so with the trainer resident these strings are clobbered." }, { "addr": "87E3", "length": 10, "type": "text", "name": "msgGameOver", "description": "'GAME OVER.' = message $16" }, { "addr": "87ED", "length": 12, "type": "text", "name": "msgDroneAlert", "description": "'DRONE ALERT!' - installed as message slot $20 by overlay A at $7BA6 (sub_C924 X=$20)" }, { "addr": "87F9", "length": 6, "type": "unknown", "name": "overlayTailPadding", "description": "six zero bytes of padding before the variant flag" }, { "addr": "87FF", "length": 1, "type": "byteTable", "name": "overlayVariantFlag", "description": "$00 = variant A, $FF = variant B (bit 7 tested by the main program at $1036/$1080)" } ], "misclassified": [], "insights": [ "Chunk location: the task quoted file lines 2896-3677 but in disassembly/game/ovl_6F00_A.s the address range $844F-$87FF is at lines 3198-3676 (lines 2896-3197 hold $820B-$844E); this survey covers the address range.", "This chunk is the custom-scenario option dialog of overlay A, run once per new game from $7AF7 (runGameStartOptions). Dialog order: banner 'STANDARD/CUSTOM SCENARIO' + 'PRESS BUTTON WHEN READY.'; if CUSTOM rules are on: STANDARD/CUSTOM menu, then COMCEN SPEED (0-3), TERRAIN PTS (0-2), DRONES (0-9) and MISSILES (0-36); for game types 4-6 the recycler (mode FULL/HALF/NONE only in custom mode, then 'LOCATING RECYCLER' free cell pick on a plain cell, command $9C mode x y); finally the handicap (default 2 = 20 points for side 0 in QB SNEAK, 20 = 200 points for side 1 in DEFENDER, or custom 0-500 step 10) as command $A5 kind 0. The values reach both machines only through the lock-step commands $A5 kind/value, $90 drones/missiles and $9C.", "Value editor pattern: beginValueEdit(A/Y label, X start) + editValueWithJoystick(A limit, Y display multiplier) -> D_844F. The editor is a one-row 'menu' (width 5 at column 29) so it reuses the menu highlight/blink code (sub_60E5/sub_60EA, D_92C5, zp_6E). The display multiplies with multiply8x8 ($FCCD), which returns A = product low byte and Y = high byte (the game_high_FBB8 survey's description 'A = Y = high byte' is inverted) and prints via sub_C17D(A=lo, Y=hi).", "The '*' key toggle (handleStarKeyToggle, $8658) is the overlay-A hook behind the main program's trampoline sub_25C4 and the runMenuLoop call at $6002. D_92F3 bit 7 is reused for two meanings: CUSTOM rules on the scenario setup screen ($821F initialises it from D_0BA3 bit 6 and message text 'CUSTOM OFF' $EFD8) and DESTROY mode during unit placement (setDestroyModeMessage $86AA selects 'DESTROY OFF' $EFE2; with the flag set a click on an own unit sends $91 self destruct at $209F). The ON/OFF word is patched directly into the string in the T34 $EC00 sub-overlay ($EFDF / $EFEA) using the words at $064D/$0650, and the message is always slot $1E, which is a run-time slot (pointer $FFFF on disk) rewritten with sub_C924; persistentMessageId D_92A1 decides what the status line falls back to.", "Message slot $1E is the overlay's scratch message: 'PRESS BUTTON WHEN READY.' ($CBBE), the 'CUSTOM:MAP, MENUS ON, DAMAGE OFF.' summary built at $0332 from the template at $0636, 'CUSTOM ON/OFF' or 'DESTROY ON/OFF'. Slot $20 is set to 'DRONE ALERT!' ($87ED) at $7BA6.", "gameTypeOptions D_0BA3 bit map as used here: bits 0-2 game type, bit 3 UNIT MENUS (editOptionBitOnOff with label $EF9B), bit 4 DAMAGE (label $EFA7), bit 6 CUSTOM rules (banner word, D_8450, D_92F3), bit 7 custom MAP (adds 'MAP,' to the summary; corresponds to the $A6 custom map seed command / D_0B9D).", "Labels sub_84F1, sub_8518, sub_8601, sub_862D and sub_8632 are entry points of overlay variant B only (the main program's JSR $8518 at $1460/$14D3 and JSR $8632 at $176B target variant B code); in variant A they fall in the middle of editTerrainPoints, editDronesAndMissiles, beginValueEdit and editOptionBitOnOff. Likewise the XREF callers 83A1/83DE listed for $84B2/$84F1 are variant-B call sites.", "The game-result strings at $879B-$87EC (message ids $11-$16 via the pointer table at $0500/$0524) and the variant flag $87FF are the shared tail of both overlay variants; variant A's code runs through $879E, so message $11 ($8789) and the first four bytes of message $12 are code in A. They are only displayed during battle when variant B is resident, so no visible corruption results. The $0332 buffer used for the custom summary lives in the $0200-$03FF setup block area and is not referenced by anything else (XREF)." ] }