210 lines
No EOL
11 KiB
JSON
Generated
210 lines
No EOL
11 KiB
JSON
Generated
{
|
|
"_comment": "generated by tools/mergeSurvey.py from survey/*.json - do not edit by hand",
|
|
"notes": {
|
|
"0400": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"checksumXorConstant: byteTable, 1 bytes. $B0 - the constant that verifyProgramChecksum XORs into the final sum before storing it at $0B7E. Excluded from the checksummed range (which starts at $0402)."
|
|
]
|
|
},
|
|
"0401": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"mapNameSeedTable: byteTable, 96 bytes. 32 x 3 bytes used by the manual look-up protection at $09A6: the random seed ($09C3, the immediate operand of the LDA at $09C2) AND $1F picks an entry, the triple is copied to $0B95-$0B97, generateBattlefieldMap draws that map and the player must type its name from the manual; the typed name is packed into zp_5A-zp_5C and compared with the same three bytes. So the triple is both the map generator seed and the expected answer. Also the first byte checksummed is $0402, so entry 0's first byte is outside the sum."
|
|
]
|
|
},
|
|
"04AE": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"scratchPageTail: unknown, 82 bytes. $00 filler on disk; at run time part of the shared $0400 scratch page (tile buffer at $04C8-$04E7, statistics accumulators, blob stacks)."
|
|
]
|
|
},
|
|
"0500": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"messagePtrLoTable: byteTable, 36 bytes. Low bytes of the 36 status-message string pointers, indexed by message id $00-$23; read at $C536/$C5E5 and patched at run time by sub_C924 (ids $1E, $20, $21 are $FFFF placeholders on disk)."
|
|
]
|
|
},
|
|
"0524": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"messagePtrHiTable: byteTable, 36 bytes. High bytes of messagePtrLoTable. Ids resolve to strings in this file ($0548-$0615), in overlay B ($8707-$87F5) and in the loaded message block ($8858-$88FF)."
|
|
]
|
|
},
|
|
"0548": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"chatMessageLine: text, 36 bytes. Message id $00: the chat/typed line. $0548 is a leading marker glyph ($1E cursor; $9E by sub_C62A to terminate immediately = blank line), $0549-$056B hold up to 35 characters mirrored from $9253 with bit 7 set on the last one. On disk it is 35 spaces plus $A0."
|
|
]
|
|
},
|
|
"056C": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"msgWorking: text, 10 bytes. Message id $01 'WORKING...' (bit-7 terminated), sound $80 = silent."
|
|
]
|
|
},
|
|
"0576": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"msgGameAborted: text, 13 bytes. Message id $03 'GAME ABORTED.', sound $03."
|
|
]
|
|
},
|
|
"0583": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"msgNotAGameFilm: text, 16 bytes. Message id $09 'NOT A GAME FILM!', sound $03 (film load rejected)."
|
|
]
|
|
},
|
|
"0593": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"msgSetupUnitsPressF1WhenDone: text, 33 bytes. Message id $0A 'SETUP UNITS. PRESS F 1 WHEN DONE.', silent."
|
|
]
|
|
},
|
|
"05B4": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"msgTimeoutRunStopToResume: text, 28 bytes. Message id $19 'TIMEOUT. RUN/STOP TO RESUME.', sound $19."
|
|
]
|
|
},
|
|
"05D0": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"msgResumed: text, 7 bytes. Message id $1B 'RESUMED', sound $19."
|
|
]
|
|
},
|
|
"05D7": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"msgTheBattleBegins: text, 18 bytes. Message id $1C 'THE BATTLE BEGINS!', sound $03."
|
|
]
|
|
},
|
|
"05E9": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"msgLastQtrWarning: text, 17 bytes. Message id $1D 'LAST QTR WARNING!', sound $19 (the game is played in quarters)."
|
|
]
|
|
},
|
|
"05FA": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"msgPhoneTrouble: text, 14 bytes. Message id $22 'PHONE TROUBLE.', sound $15 (modem link failure)."
|
|
]
|
|
},
|
|
"0608": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"msgTryAgain: text, 10 bytes. Message id $23 'TRY AGAIN.', sound $03."
|
|
]
|
|
},
|
|
"0612": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"messageSoundTable: byteTable, 36 bytes. Sound effect number played when message id X is displayed (read at $C557, played through sub_C89A); $80 = no sound. Notable: $0E for the two 'we lost' messages, $0D for the two 'we won' messages, $19 for GAME OVER / TIMEOUT / RESUMED / LAST QTR WARNING, $15 for PHONE TROUBLE."
|
|
]
|
|
},
|
|
"0636": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"optionSummaryTemplate: text, 23 bytes. ' MENUS XXXX DAMAGE XXX.' (bit-7 terminated) - a rules summary line whose XXXX/XXX fields are overwritten in place by overlay A/B ($870C, $8739-$8751) with OFF,/ON, and FULL/HALF/NONE before it is displayed."
|
|
]
|
|
},
|
|
"064D": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"optionWordTable: text, 17 bytes. Five bit-7 terminated option words at fixed offsets used to fill optionSummaryTemplate: +0 'OFF', +3 'ON', +5 'FULL', +9 'HALF', +13 'NONE'. XREF.txt calls this label eaCopyrightMessage, which is wrong."
|
|
]
|
|
},
|
|
"065E": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"msgClicks: text, 10 bytes. ' CLICKS:' - the score header printed by $C6BC (lda #$5E / ldy #$06 / jsr sub_C133). 'Clicks' are Modem Wars' score units."
|
|
]
|
|
},
|
|
"0668": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"msgUs: text, 7 bytes. ' US:' - printed straight after msgClicks by sub_C137, followed by the local player's 16-bit score from $92A2/$92A4."
|
|
]
|
|
},
|
|
"066F": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"msgThem: text, 8 bytes. ' THEM:' - the opponent's score label, printed by the same $C6B6 routine."
|
|
]
|
|
},
|
|
"0677": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"msgTypeMapName: text, 40 bytes. Three lines separated by $0D: 'TYPE MAP NAME' / ' (F7 RANDOM)' / ' (F5 SYM/RND)' - the prompt of enterMapName (also used by the manual look-up protection at $09EF)."
|
|
]
|
|
},
|
|
"069F": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"msgBtnToAccept: text, 27 bytes. Two lines separated by $0D: 'BTN TO ACCEPT' / '(F 1 TO FLIP)' - shown while the generated map is offered for acceptance."
|
|
]
|
|
},
|
|
"0770": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"tileVariantMaskTable: byteTable, 40 bytes. Indexed by map cell value minus $40 (cells below $40 use cell-$20), covering cells $40-$67. The value is a mask ANDed with a scenario random number and added to the base tile by randomTileVariant ($7872, overlay A): cells $49 and $4B and $65 -> mask 1, cells $4D, $51, $59, $5D, $61 -> mask 3, everything else 0 (no variation)."
|
|
]
|
|
},
|
|
"0798": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"tileVariantPad: unknown, 1 bytes. $00 pad between tileVariantMaskTable and unitGlyphBaseTable."
|
|
]
|
|
},
|
|
"0799": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"unitGlyphBaseTable: byteTable, 5 bytes. Base glyph index of the 1-character overview-map symbol per unit type: $2C GRUNT, $30 RIDER, $34 BOOMER, $38 SPY, $3C COMCEN. The facing (unit flags AND 3) is added, then $2C is subtracted and the result doubled to index the glyph pairs ($28A0, $7512, $7538)."
|
|
]
|
|
},
|
|
"079F": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"terrainClassTable: byteTable, 75 bytes. Map cell value -> terrain class 0-8. It is addressed as D_077E,y with the raw cell value, so the body starts at $077E+$21 = $079F and ends at $077E+$6B = $07E9: cells $21-$34 -> 3 (lower contour), $35-$3F -> $FF (invalid), $40 -> 0 (blank), $41-$54 -> 5 (upper contour), $55-$5C -> 1 (river), $5D-$60 -> 2 (forest), $61-$64 -> 4 (lower hill), $65-$66 -> 6 (summit), $67 -> 7 (recycler), $68-$6B -> 8. The same bytes are also read as D_07BE,x by $5BC8 with the index already reduced to cell-$40 (clamped to < $21)."
|
|
]
|
|
},
|
|
"07EA": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"terrainColourTable: byteTable, 9 bytes. Colour-RAM nibble per terrain class 0-8: 7,3,5,8,8,8,8,0,0 (yellow plain, cyan river, green forest, orange contours/hills/summit, black for classes 7-8). Read at $27AB and $5BCB right after a terrainClassTable lookup."
|
|
]
|
|
},
|
|
"07F3": {
|
|
"unit": "game/scratchAndMessages0400",
|
|
"block": [
|
|
"table0400Tail: unknown, 13 bytes. $00 filler to the end of the page."
|
|
]
|
|
},
|
|
"0461": {
|
|
"routine": [
|
|
"verifyProgramChecksum - Boot-time integrity check, entered by the boot loader's obfuscated RTS (the stack was rigged to hold $0460). Saves randomSeed ($09C3) in zp_19 and zeroes it so the sum is seed independent, then runs a self-modifying ADC/EOR/ROL checksum over $0402-$87FF (132 pages; the operand high bytes at $047C and $0484 are incremented per page and end at $88), adds the carry counter zp_1B, stores the sum at $8800, stores sum EOR $0400 ($B0) in programChecksum ($0B7E), restores randomSeed and does JMP $0800 with Y=2. The ADC carry is deliberately chained from one word to the next (the CLC at $0479 is outside the loop) and the PHP/ASL/BCC/ORA/PLP block is a ROL that preserves that carry.",
|
|
"In: memory $0402-$87FF, $09C3 (random seed, zeroed during the sum), $0400 = $B0",
|
|
"Out: $8800 = raw sum ($69 on this disk image), $0B7E = sum EOR $B0 ($D9), $09C3 restored, zp_19/zp_1A/zp_1B clobbered, $047C/$0484 left at $88, JMP $0800 with Y=2 and S=$FE"
|
|
],
|
|
"unit": "game/scratchAndMessages0400"
|
|
},
|
|
"06BA": {
|
|
"routine": [
|
|
"switchToRequestedScreen - Called from every screen's main loop to honour an F1/F3/F5/F7 screen change. Returns immediately when the chat editor is active (D_929C != 0), when zp_66 has bit 7 set (no request) or when the request equals the current screen. Otherwise it makes the request current, resets the stack to $FD (so it never returns to the caller), turns all sprites off (VIC_SPR_ENA and the shadows $9020/$9022/$9023/$9024), clears $92F9 unless $0B9B bit 7 is set, redraws the bitmap frame and jumps to the new screen's entry point.",
|
|
"In: zp_66 (requested screen 0-3, $FF = none), D_90FB (current screen), D_929C (chat state), D_0B9B bit 7",
|
|
"Out: D_90FB updated, sprites disabled, S=$FD, never returns: JMPs to enterMapScreen (0, also sets $9020=$C4), runMissileScreen (1), enterDroneScreen (2) or enterMainMenu (3)"
|
|
],
|
|
"unit": "game/scratchAndMessages0400"
|
|
},
|
|
"0709": {
|
|
"routine": [
|
|
"runComcenStunnedBlackout - The 'COMCEN STUNNED!' cut-scene, entered by JMP from $4546 when the command centre status byte D_922A has reached $FF and the game is not in solo/film mode. It releases drone control, wipes the message line and screen, resets the stack, then runs the engine unattended (updateGameFrame) with input locked out and D_922A bit 6 set (which keeps sprites off) until unitOrderIndex ($9162) comes back to the value it had on entry, i.e. exactly one full 100-unit update round. It then queues message $0C ('COMCEN STUNNED!'), clears the lockout, masks D_922A with $8F and re-enters whichever screen was active.",
|
|
"In: D_9162 (captured into the CMP operand at $073E), D_922A, D_90FB (current screen), D_92C9 and D_0BA8 (abort conditions), D_90FC (per-frame gate)",
|
|
"Out: one blacked-out engine round; inputLockoutTimer set then cleared; D_922A bits 4-6 cleared; message $0C queued via sub_C566; never returns: jumps to runMapMainLoop (after drawOverviewMap/drawViewport), missileScreenResume, resetDroneScreen or enterMainMenuKeepSelection",
|
|
"(confidence: medium)"
|
|
],
|
|
"unit": "game/scratchAndMessages0400"
|
|
}
|
|
}
|
|
} |