modemwars/annotations/30_game_modemDriverE000_EF08.json
2026-08-23 02:09:40 -05:00

212 lines
No EOL
15 KiB
JSON

{
"chunk": "EF08",
"unit": "game/modemDriverE000",
"unitLabels": {
"game/modemDriverE000": {
"EF52": "msgHandicap",
"EFB6": "diskNameSlot",
"EFCD": "msgInsertDiskTail"
}
},
"notes": {
"EF08": {
"unit": "game/modemDriverE000",
"block": [
"msgDisplayPromptPrefix: text, 8 bytes, 'F 1 FOR ' with no terminator. First third of a single 32-byte string that runs $EF08-$EF27: this prefix, the eight-character mode-name hole at $EF10, and ' BATTLE DISPLAY' + the bit-7 terminator '.' at $EF18. toggleBattleDisplayMode in this file loads $EF08 at $EEFB/$EEFD, registers it as message slot $20 with setMessageSlot ($C924) and queues it ($EF05), so the status line reads 'F 1 FOR BEGINNER BATTLE DISPLAY.' or 'F 1 FOR STANDARD BATTLE DISPLAY.'",
"Solo-trainer text, and setup-phase only. Both users test isSoloTrainer $0BA5 bit 7 first: handleDisplayToggleKey ($EEB9), polled from the menu/idle loop at $600A, and overlay A's call at $824B when the game-type screen opens. $600A is only reached while gamePhase zp_B1 = $FF, the pre-battle setup phase. In a modem game the 74 bytes $EF08-$EF51 are resident but never read; in a solo game they are used during setup only, because startGameFromSetup ($0B4F) then replaces $EC00-$EFFF with the trainer's own tail from track 35.",
"The L_xxxx / sub_xxxx labels that chop these strings into pieces are not part of the data. $EC00-$EFFF is a slot that four different overlays occupy at different times - this comm tail (track 34 sectors 12-15), the solo trainer's tail (track 35 sectors 12-15), the trainer setup overlay (track 29 sectors 0-3) and the drone-flight AI (track 29 sectors 4-5) - and the disassembler shares one label set across all of them, so every branch target of those other builds surfaces here in the middle of the text."
],
"line": "'F 1 FO' - message slot $20 points here ($EEFB/$EEFD)"
},
"EF0E": {
"unit": "game/modemDriverE000",
"line": "'R' - end of 'F 1 FOR'; the split is only the foreign label L_EF0E"
},
"EF0F": {
"unit": "game/modemDriverE000",
"line": "the space in front of the eight-character mode name"
},
"EF10": {
"unit": "game/modemDriverE000",
"block": [
"displayModeNameSlot: text, 8 bytes. A hole inside the prompt above, patched at run time by copyModeNameLoop ($EEED-$EEF8: LDA msgBeginnerDisplaySet,Y / STA $EF10,X for X = 0..7; XREF lists w:EEF0 from this file as the only writer). Y = 0 copies 'BEGINNER' from $EF28, Y = $15 copies 'STANDARD' from $EF3D. The word written is always the mode F1 will switch to NEXT, because toggleBattleDisplayMode chooses it after flipping revealAllUnits $92FC.",
"The shipped bytes are eight '*' ($2A). They can never appear on screen: the only code that queues message slot $20 is the same routine that patches them first."
],
"line": "'********' - placeholder, always overwritten with BEGINNER or STANDARD before the message is queued"
},
"EF18": {
"unit": "game/modemDriverE000",
"block": [
"msgBattleDisplaySuffix: text, 16 bytes, ' BATTLE DISPLAY' followed by '.' with bit 7 set ($AE). Tail of the message slot $20 prompt that starts at $EF08; bit 7 on the last character is the string terminator every printString ($C133) call looks for."
],
"line": "' BATTLE ' - runs straight on from the patched mode name at $EF10"
},
"EF28": {
"unit": "game/modemDriverE000",
"block": [
"msgBeginnerDisplaySet: text, 21 bytes, 'BEGINNER DISPLAY SET' + '.'|$80. Two jobs. (1) announceAndToggleDisplayMode loads it at $EEC5/$EEC7, makes it message slot $21 and queues it, so the status line reports the mode that is being switched on - the announcement happens before revealAllUnits $92FC is flipped, while the prompt at $EF08 names the other mode. (2) its first eight characters are the source of the 'BEGINNER' patch word copied into $EF10 (XREF: r:EEED from this file)."
],
"line": "'BEGINNER DISPLAY SET.' - message slot $21; the first 8 bytes double as the patch word"
},
"EF3D": {
"unit": "game/modemDriverE000",
"block": [
"msgStandardDisplaySet: text, 21 bytes, 'STANDARD DISPLAY SET' + '.'|$80. Never addressed directly: both users reach it as msgBeginnerDisplaySet + $15 (ADC #$15 at $EECF for the message pointer, LDY #$15 at $EEE9 for the patch word), so the two strings have to stay exactly 21 bytes apart and in this order."
],
"line": "'STANDARD DISPLAY SET.' = $EF28+$15; its first 8 bytes are the 'STANDARD' patch word"
},
"EF52": {
"unit": "game/modemDriverE000",
"block": [
"Setup-menu label block, $EF52-$EFAE, 93 bytes: ten bit-7 terminated strings printed by the setup, option and film menus of overlay A (the map generator / setup build of $6F00-$87FF). Overlay A never names them: it loads each address as two immediates (LDA #low / LDY #$EF) and calls a printer, which is why XREF.txt has an entry for only one of them. Because loadOverlayA chains into loadCommTailBuild2 ($1070), this page is present in both modem and solo games, so overlay A can print these strings whichever opponent module is loaded. The survey calls the whole run gameOptionLabels; each entry is labelled separately here.",
"msgHandicap: text, 8 bytes, 'HANDICA' + 'P'|$80. Title of the one-row number editor (beginValueEdit, overlay A $84D0) for the DEFENDER handicap: 0-50, displayed multiplied by ten as 0-500 points, offered only under CUSTOM rules ($92F3 bit 7) and only to side 1."
],
"line": "'HANDICAP' - title of the handicap value editor (overlay A $84D0)"
},
"EF59": {
"unit": "game/modemDriverE000",
"line": "'P' with bit 7 set = the end-of-string marker"
},
"EF5A": {
"unit": "game/modemDriverE000",
"block": [
"msgTerrainPts: text, 11 bytes, 'TERRAIN PT' + 'S'|$80. Title of the TERRAIN PTS value editor (overlay A $84F5, editTerrainPointsForSide): a per-side 0-2 setting taken from terrainPointsBySide, edited with the joystick and sent to the opponent."
],
"line": "'TERRAIN PTS' - value editor title, overlay A $84F5"
},
"EF65": {
"unit": "game/modemDriverE000",
"block": [
"msgDrones: text, 6 bytes, 'DRONE' + 'S'|$80. Title of the first half of editDronesAndMissiles (overlay A $8514): the drone count, 0-9. Its companion label 'MISSILES' is not here but at $CC9E in the text overlay; both numbers are then sent together as command $90."
],
"line": "'DRONES' - value editor title, overlay A $8514 (0-9)"
},
"EF6B": {
"unit": "game/modemDriverE000",
"block": [
"msgComcenSpeed: text, 12 bytes, 'COMCEN SPEE' + 'D'|$80. Title of the COMCEN SPEED editor (overlay A $85BF, editComcenSpeed): a class 0-3 sent as command $A5 kind 3 and mapped through the table at $78BF into the comcen's actual step rate."
],
"line": "'COMCEN SPEED' - value editor title, overlay A $85BF (0-3)"
},
"EF77": {
"unit": "game/modemDriverE000",
"block": [
"msgMapType: text, 10 bytes, 'MAP TYPE' then $0D and $8D. $0D is a carriage return (handleControlChar $C03D) and $8D is the same code carrying the terminator bit, so printing the string leaves the cursor two rows lower and the STANDARD / CUSTOM items land under the title. Used as the menu title by runMapTypeMenu (overlay A $82C7). Centring counts the two CRs as characters, so the title probably sits one column left of exact centre.",
"The only entry of this block with a real XREF entry: showCustomSummaryMessage reads it with LDA $EF77,X at $86DF (from game/mapGenerator6F00) and copies just the first three characters, masked with AND #$7F, to build the 'CUSTOM:MAP,...' status line."
],
"line": "'MAP TYPE' + CR + CR|$80 - menu title ($82C7); $86DF also lifts the 'MAP' out of it"
},
"EF81": {
"unit": "game/modemDriverE000",
"block": [
"msgMore: text, 8 bytes, ' (MORE)' + CR|$80. The extra item of the game-film slot menu, shown only when a data disk is in the drive (diskIdIndex non-zero): overlay A $7F15 prints it as the eleventh line when the menu is built, and $8136 re-prints it when the selector highlights that row. On the game disk the menu stops at ten slots plus ' (EXIT)' ($CAB2)."
],
"line": "' (MORE)' + CR|$80 - extra film-menu item on a data disk ($7F15/$8136)"
},
"EF89": {
"unit": "game/modemDriverE000",
"block": [
"msgLocating: text, 9 bytes, 'LOCATING' + CR|$80. First line of the two-line banner shown while the player positions the recycler: overlay A $83E5 prints it centred and immediately calls printNextStringCentred ($83EC), which carries on with whatever string follows in memory - msgRecycler. The two strings therefore have to stay adjacent and in this order."
],
"line": "'LOCATING' + CR|$80 - line 1 of the recycler banner ($83E5), continued at $EF92"
},
"EF92": {
"unit": "game/modemDriverE000",
"block": [
"msgRecycler: text, 9 bytes, 'RECYCLER' + CR|$80. Title of the FULL / HALF / NONE recycler menu (overlay A $83A0, printed centred above the three words at $0652), and the second line of the 'LOCATING RECYCLER' banner when it is reached by fall-through from $EF89."
],
"line": "'RECYCLER' + CR|$80 - recycler menu title ($83A0), also line 2 of the banner"
},
"EF9B": {
"unit": "game/modemDriverE000",
"block": [
"msgUnitMenus: text, 12 bytes, 'UNIT MENUS' + $0D + $8D. Title handed to editOptionBitOnOff (overlay A $82AF) with X = mask $08: a two-item OFF / ON menu that clears or sets bit 3 of gameTypeOptions $0BA3. As with 'MAP TYPE' the two carriage returns drop the OFF / ON items two rows below the title.",
"The sub_EF9E label in the middle of the string is not a routine of this build: it is the entry point droneDistanceToCell of the drone-AI overlay that occupies this page in a solo game, and the disassembler's label set is shared between the two."
],
"line": "'UNIT MENUS' + CR + CR|$80 - OFF/ON menu for gameTypeOptions bit 3 ($82AF)"
},
"EFA7": {
"unit": "game/modemDriverE000",
"block": [
"msgDamage: text, 8 bytes, 'DAMAGE' + $0D + $8D. The second CUSTOM sub-menu, same treatment at overlay A $82B8 with X = mask $10 = bit 4 of gameTypeOptions $0BA3. This is the last entry of the label block that began at $EF52."
],
"line": "'DAMAGE' + CR + CR|$80 - OFF/ON menu for gameTypeOptions bit 4 ($82B8)"
},
"EFAF": {
"unit": "game/modemDriverE000",
"block": [
"msgInsertDiskTemplate: text, 33 bytes, 'INSERT DATA DISK AND PRESS SPACE' + '.'|$80, occupying $EFAF-$EFCF. promptInsertDiskAndWaitSpace (overlay A $81B6) registers it as message slot $1E at $81BE/$81C0 and leaves it as the persistent status message while the game-film save / load flow waits for the space bar. The four characters at $EFB6 are a patch hole, so the same template serves both prompts."
],
"line": "'INSERT xxxx DISK AND PRESS SPACE.' - message slot $1E (overlay A $81BE)"
},
"EFB6": {
"unit": "game/modemDriverE000",
"block": [
"diskNameSlot: the four characters 'DATA' inside the template above are a hole, not text of their own. promptInsertDiskAndWaitSpace copies a four-character disk name over them with a self-modified LDA / STA pair at overlay A $81C7-$81CA (this is the XREF entry w:81CA from game/mapGenerator6F00): 'DATA' ($EFD0) via promptInsertDataDisk ($81B2) or 'GAME' ($EFD4) via promptInsertGameDisk ($81A5). The image on disk holds 'DATA', the same four bytes as $EFD0, so the unpatched template already reads correctly."
]
},
"EFBA": {
"unit": "game/modemDriverE000",
"line": "the fixed part of the template resumes here: ' DISK AND PRESS SPACE.'"
},
"EFCC": {
"unit": "game/modemDriverE000",
"line": "'A' of SPACE - the last byte of this page that differs between the four $EC00 overlays"
},
"EFCD": {
"unit": "game/modemDriverE000",
"block": [
"msgInsertDiskTail: 'CE' + '.'|$80, the last three characters of the message above (a separate block only because the other builds of this page have a branch target at $EFCC).",
"From here to $EFFE the page is shared. $EFCD-$EFFE is byte-for-byte identical in all four images that can occupy $EC00-$EFFF - track 34 s12-15 (this comm tail), track 35 s12-15 (trainer tail), track 29 s0-3 (trainer setup) and track 29 s4-5 (drone AI); only $EFFF differs, $00 here and $FF in the other three. Evidence: a byte comparison of the four decrypted sector images. The strings from $EFCD on were therefore assembled into the tail of every build, which is why overlay A can print them no matter which module is resident."
],
"line": "'CE.' - end of 'INSERT xxxx DISK AND PRESS SPACE.'; from here on the page is common to all four builds"
},
"EFD0": {
"unit": "game/modemDriverE000",
"block": [
"wordData: text, 4 bytes, 'DATA' with no terminator - a patch word, never printed on its own. promptInsertDataDisk (overlay A $81B2) passes $EFD0 in A/Y and the four bytes are copied into the hole at $EFB6."
],
"line": "'DATA' - patch word for $EFB6 (overlay A $81B2)"
},
"EFD4": {
"unit": "game/modemDriverE000",
"block": [
"wordGame: text, 4 bytes, 'GAME' with no terminator - the other patch word for $EFB6, passed by promptInsertGameDisk (overlay A $81A5) before it waits for the OZ game disk to be put back in the drive."
],
"line": "'GAME' - patch word for $EFB6 (overlay A $81A5)"
},
"EFD8": {
"unit": "game/modemDriverE000",
"block": [
"msgCustomOff: text, 10 bytes, 'CUSTOM OF' + 'F'|$80. beginGameTypeSelection (overlay A $8218) registers it as message slot $1E for the GAME TYPE screen and $821F/$8224 point the store operand at $869A/$869B at $EFDF, the 'OFF' inside it. Every time the player presses '*', showToggleStateMessage ($8673) copies three bytes over $EFDF-$EFE1 - 'OFF' from $064D or 'ON'|$80 plus the stray 'F' that follows it at $0650 - so the same slot reads 'CUSTOM ON' or 'CUSTOM OFF' and mirrors gameTypeOptions $0BA3 bit 6 (CUSTOM rules)."
],
"line": "'CUSTOM OFF' - message slot $1E; $EFDF-$EFE1 is rewritten with ON/OFF by the store at $8699"
},
"EFE2": {
"unit": "game/modemDriverE000",
"block": [
"msgDestroyOff: text, 11 bytes, 'DESTROY OF' + 'F'|$80. The same machinery for the unit placement phase: setDestroyModeMessage (overlay A $86B1) makes it message slot $1E and $86B8 aims the ON/OFF store at $EFEA, so '*' switches the line between 'DESTROY OFF' and 'DESTROY ON' while the off state also restores persistent message $0A ('SETUP UNITS. PRESS F 1 WHEN DONE.')."
],
"line": "'DESTROY OFF' - message slot $1E; $EFEA-$EFEC is the ON/OFF hole"
},
"EFED": {
"unit": "game/modemDriverE000",
"block": [
"msgAccepted: text, 8 bytes, 'ACCEPTE' + 'D'|$80. Printed centred on text row 15 by acceptCurrentMap (overlay A $7708-$7714) when the player accepts the battlefield currently on screen. Last string of the block."
],
"line": "'ACCEPTED' - printed centred by overlay A $7710"
},
"EFF5": {
"unit": "game/modemDriverE000",
"block": [
"commTailFiller: 11 unused bytes, $EFF5-$EFFF - $C0,$DF then $00,$FF repeated four times and a final $00. Nothing points at them: XREF.txt has no entry for any address in the range, no immediate pair in this file or in overlay A forms an address inside it, and they sit behind the last string of the block, so this is padding left at the end of track 34 sector 15. The same 11 bytes end the trainer tail, the trainer setup overlay and the drone-AI overlay, except that their last byte is $FF."
],
"line": "$C0,$DF then alternating $00/$FF - unreferenced padding at the end of the sector"
},
"EFFD": {
"unit": "game/modemDriverE000",
"line": "$EFFF is $00 in this track 34 image but $FF in the track 35 and track 29 images of the page"
}
},
"dataTypes": {}
}