; ============================================================================ ; $F000-$F6FF - unit start-position templates (track 18 sectors 8-14) ; ============================================================================ ; What is STORED here is four 400-byte templates at $F000, $F190, $F320 and $F4B0; each is four parallel ; 100-entry arrays - starting column, starting row, flags (facing in bits 0-1, side in bit 5, grouped in ; bit 6, group id in bits 2-4) and unit type. One template is chosen per game type and copied into the ; live unit arrays. The standard roster is 28 GRUNT, 12 RIDER, 6 BOOMER, 3 SPY and 1 COMCEN per side. ; What the same addresses hold at RUN TIME is different: $F000-$F63F becomes the 40x40 battlefield map ; (one byte per cell) and the unit record arrays start at $F640 in 100-byte slices, so the templates are ; overwritten as soon as a game starts. ; The 192 bytes at $F640-$F6FF are not used at all: they are a fragment of an older build of the game's ; own options-list printer, left in the sector by the development system. .setcpu "6502" .include "c64.inc" .include "zeropage.inc" .org $F000 ; unitStartTemplatesF000 - the whole file. Track 18 sectors 8-14 hold pure data: four 400-byte unit ; start-position templates at $F000, $F190, $F320 and $F4B0, followed by 192 bytes at $F640-$F6FF that ; are not data at all but a fragment of an older build's code (see the note there). Nothing in this ; file is a battlefield: the 40x40 map that occupies $F000-$F63F at run time is built from the 24-bit ; map seed by generateBattlefieldMap ($6F04) and overwrites all four templates before the first frame. ; Loaded by loadMapAndSetup ($10AB): setLoadDest $F000, then 7 sectors from track 18 sector 8, once ; per session from startGameFromSetup ($0B35). Read by exactly one routine, loadUnitStartTemplate ; ($ECF3, in the comm tail that track 34 sectors 12-15 put at $EC00), which overlay A calls at $79E6 ; and $82FD: n = unitLayoutByGameType[$78B8 + (gameTypeOptions $0BA3 & 7)] = 2,2,2,1,3,0,0 for game ; types 0-6, and it then copies two whole pages (512 bytes) from $F000 + 400*n to $F640, where the ; live unit records begin. Only the first 400 bytes are the template; the extra 112 bytes overwrite ; unitDestCol ($F7D0-$F833) and the first twelve entries of unitDestRow ($F834-$F83F), which ; initAllUnits rewrites at once, so the spill is harmless. For templates 0-2 the spill is the head of ; the next template; for template 3 the source ($F4B0-$F6AF) overlaps the destination ($F640-$F83F) ; and, because the copy runs upwards, it re-reads what it has just written and duplicates template 3's ; own first 112 bytes - which is also why the leftover code at $F640-$F6AF is destroyed before it ; could ever be read as data. The copy is guarded by 'bit 7 of $F640 set' = 'the arrays still hold the ; disk image'. As loaded from disk $F640 is $0A (an opcode of the leftover code), which fails that ; test, so startGameSession stores $FF there first ($78E4). Game type -> template: 0 SCRIMAGE, 1 QB ; SNEAK, 2 THE BOMB -> template 2; 3 FACE-OFF -> template 1; 4 SLUGGERS -> template 3; 5 FULL WAR, 6 ; DEFENDER -> template 0. (There is no game type 7; it would index $78BF = $04 and copy from $F000 + ; 1600 = $F640.) Each template is four parallel 100-entry arrays - +$000 starting column, +$064 ; starting row, +$0C8 flags, +$12C type - i.e. exactly the first four of the fourteen 100-byte ; unit-record arrays that live from $F640 upwards $64 apart. Entry i describes unit i: 0-49 side 0, ; 50-99 side 1, 49 and 99 the two COMCENs. Coordinates are cells of the 40x40 field: columns 3-36, ; side 0 in the bottom half (rows 20-33), side 1 in the top half (rows 6-19). Player 1's machine ; rotates the map and every unit coordinate to 39-x (rotateMapAndMirrorCodes $EC58, ; mirrorAllUnitCoordinates $EC91), so both players see their own army at the bottom. How much of a ; template survives the copy: initAllUnits ($3D8A) -> initUnitRecord ($3DA0) keeps the column, the ; row, flags bits 2-4 (group id) and bit 6 (belongs to a group), and type bits 0-2 (the unit type) ; plus bit 7 ($FF = empty slot). It rebuilds the facing (flags bits 0-1) and the side (flags bit 5) ; from the unit index and clears type bits 3-4, so those bits of the stored data are consistent with ; the rest but are never actually used. unitStartTemplate0 ($F000-$F18F) - the full roster, used by ; game types 5 FULL WAR and 6 DEFENDER. All 100 slots are in play: per side 28 GRUNT (units 0-27), 12 ; RIDER (28-39), 6 BOOMER (40-45), 3 SPY (46-48) and 1 COMCEN (49). Three wings, each an eleven-unit ; group of nine grunts and two boomers in rows 25-28 with a four-rider group in front of it in rows ; 30-31. Side 0: group 3 DELTA = units 4,7,10,11,14,15,18,19,20,40,44 on the left (columns 3-7), ; group 4 EASY = 1,2,3,13,16,17,22,23,27,41,45 in the centre (17-21), group 5 FOXTROT = ; 0,5,8,9,12,21,24,25,26,42,43 on the right (32-36); rider group 0 ALPHA = 28,29,30,32 (columns 5-6), ; 1 BAKER = 31,33,34,37 (19-20), 2 CHARLIE = 35,36,38,39 (33-34). Loose (flags $00): the three spies ; 46-48 in row 23, and in the back row 33 the COMCEN 49 at column 20 with one GRUNT, unit 6, beside it ; at column 19. Side 1 is the exact 180-degree mirror of side 0 as a formation - every ; (column,row,type,group) of side 0 occurs on side 1 as (39-column, 39-row, same type, same group) - ; but the indices within a group are not mirrored, so unit i+50 is not the mirror image of unit i. unitStartTemplate0: .byte $22,$13,$11,$13,$04,$23,$13,$03,$24,$21; F000 "....#..$! unitCol[0-49]: side 0's starting map column, ten units per row; the last entry is the COMCEN .byte $05,$07,$21,$12,$06,$05,$14,$13,$04,$06; F00A ..!....... .byte $05,$22,$14,$12,$22,$20,$23,$15,$06,$05; F014 .".." #... .byte $06,$13,$05,$13,$14,$22,$22,$14,$21,$21; F01E ....."".!! .byte $06,$14,$21,$23,$04,$12,$13,$22,$05,$14; F028 ..!#...".. .byte $06,$07,$23,$05,$04,$03,$22,$22,$06,$12; F032 ..#..."".. unitCol[50-99]: side 1's columns; the last entry is unit 99, side 1's COMCEN .byte $15,$16,$13,$14,$21,$13,$04,$24,$14,$23; F03C ....!..$.# .byte $22,$21,$20,$15,$05,$14,$05,$14,$22,$21; F046 "! ....."! .byte $14,$13,$14,$22,$21,$05,$05,$06,$06,$13; F050 ..."!..... .byte $13,$23,$21,$15,$04,$06,$22,$14,$05,$13; F05A .#!..."... ; unitRow - array 2 of 4 ($F064-$F0C7): the starting map row 0-39 of each unit, copied to unitRowTable ; $F6A4. Side 0 occupies rows 23-33 in this template and side 1 the mirrored rows 6-16. template0StartRow: .byte $1B,$19,$1B,$1A,$1A,$1B,$21,$1B,$1B,$1A; F064 ......!... unitRow[0-49]: side 0's rows, the bottom half of the field .byte $19,$1B,$1B,$1A,$1B,$1A,$1A,$1B,$1B,$1A; F06E .......... .byte $1B,$19,$1B,$1B,$1A,$1B,$1A,$1B,$1F,$1E; F078 .......... .byte $1E,$1F,$1F,$1E,$1E,$1F,$1E,$1F,$1F,$1E; F082 .......... .byte $1C,$1C,$1C,$1C,$1C,$1C,$17,$17,$17,$21; F08C .........! .byte $0D,$0C,$0D,$0C,$0D,$0C,$0E,$0D,$0C,$0C; F096 .......... unitRow[50-99]: side 1's rows, the 39-row mirror of side 0's .byte $0C,$0C,$0D,$0C,$0D,$0C,$0C,$0C,$06,$0C; F0A0 .......... .byte $0C,$0C,$0C,$0D,$0D,$0E,$0E,$0D,$09,$09; F0AA .......... .byte $08,$09,$09,$08,$08,$09,$08,$09,$08,$08; F0B4 .......... .byte $0B,$0B,$0B,$0B,$0B,$0B,$10,$10,$10,$06; F0BE .......... ; unitFlags - array 3 of 4 ($F0C8-$F12B): bits 0-1 facing (0 = up, 1 = down), bits 2-4 group id 0-6 = ; ALPHA, BAKER, CHARLIE, DELTA, EASY, FOXTROT, GROVER (names at $C92C), bit 5 side, bit 6 = belongs to ; a group, bit 7 (the blitz charge at run time) always 0 here. So a side-0 entry is $00 when loose ; and $40 + 4*g in group g; a side-1 entry is $21 when loose and $61 + 4*g in group g. Copied to ; unitFlagsTable $F708; initUnitRecord ($3DC6) keeps only bits 2-4 and 6 and rebuilds facing and side ; from the unit index, so the group id and the group-member bit are the only part that matters. template0StartFlags: .byte $54,$50,$50,$50,$4C,$54,$00,$4C,$54,$54; F0C8 TPPPLT.LTT unitFlags[0-49]: side 0 - $00 loose, $40/$44/$48/$4C/$50/$54 = groups ALPHA..FOXTROT .byte $4C,$4C,$54,$50,$4C,$4C,$50,$50,$4C,$4C; F0D2 LLTPLLPPLL .byte $4C,$54,$50,$50,$54,$54,$54,$50,$40,$40; F0DC LTPPTTTP@@ .byte $40,$44,$40,$44,$44,$48,$48,$44,$48,$48; F0E6 @D@DDHHDHH .byte $4C,$50,$54,$54,$4C,$50,$00,$00,$00,$00; F0F0 LPTTLP.... .byte $75,$75,$6D,$75,$75,$75,$6D,$6D,$75,$71; F0FA uumuuummuq unitFlags[50-99]: side 1 - $21 loose, $61/$65/$69/$6D/$71/$75 = the same six groups .byte $71,$71,$71,$71,$6D,$71,$75,$6D,$21,$6D; F104 qqqqmqum!m .byte $6D,$6D,$6D,$71,$75,$71,$75,$71,$61,$61; F10E mmmququqaa .byte $65,$65,$65,$61,$61,$69,$69,$69,$69,$65; F118 eeeaaiiiie .byte $71,$6D,$6D,$71,$75,$75,$21,$21,$21,$21; F122 qmmquu!!!! ; unitType - array 4 of 4 ($F12C-$F18F): $10 + type for a side-0 unit and $18 + type for a side-1 ; unit, type 0 GRUNT, 1 RIDER, 2 BOOMER, 3 SPY, 4 COMCEN (names at $C964); $FF marks a slot that is ; not in play. Copied to unitTypeTable $F76C. At run time bits 3-4 of this byte are the 'has already ; scored that end zone' markers and bit 6 is 'dug in', but initUnitRecord ($3DB9) clears bits 3-4 ; while it resets each unit, so of the stored value only bits 0-2 and the $FF (bit 7 = ; destroyed/empty, tested by placeUnitOnMap at $3E11) ever reach the engine. template0StartType: .byte $10,$10,$10,$10,$10,$10,$10,$10,$10,$10; F12C .......... unitType[0-49]: side 0 - $10 GRUNT, $11 RIDER, $12 BOOMER, $13 SPY, $14 COMCEN; 28/12/6/3/1 .byte $10,$10,$10,$10,$10,$10,$10,$10,$10,$10; F136 .......... .byte $10,$10,$10,$10,$10,$10,$10,$10,$11,$11; F140 .......... .byte $11,$11,$11,$11,$11,$11,$11,$11,$11,$11; F14A .......... .byte $12,$12,$12,$12,$12,$12,$13,$13,$13,$14; F154 .......... .byte $18,$18,$18,$18,$18,$18,$18,$18,$18,$18; F15E .......... unitType[50-99]: side 1 - $18 GRUNT .. $1C COMCEN; the same roster as side 0 .byte $18,$18,$18,$18,$18,$18,$18,$18,$18,$18; F168 .......... .byte $18,$18,$18,$18,$18,$18,$18,$18,$19,$19; F172 .......... .byte $19,$19,$19,$19,$19,$19,$19,$19,$19,$19; F17C .......... .byte $1A,$1A,$1A,$1A,$1A,$1A,$1B,$1B,$1B,$1C; F186 .......... ; unitStartTemplate1 ($F190-$F31F) - used by game type 3 FACE-OFF only. Roster per side: 28 RIDER ; (units 0-27), 3 SPY (46-48), 1 COMCEN (49); slots 28-45 are empty ($FF in the type array). The ; riders form seven 2x2 squads, one per group name, drawn up in a single line: side 0 groups 0 ALPHA ; .. 6 GROVER occupy rows 22-23 at columns 22-23, 19-20, 16-17, 13-14, 10-11, 7-8 and 4-5, with the ; three spies in row 21 at columns 5, 14 and 23 and the COMCEN at (14,25). Side 1 is the exact ; per-index 180-degree mirror: unit i+50 stands at (39-column, 39-row) of unit i and carries the same ; type and the same group id. The 18 empty slots on each side still carry column and row bytes, which ; are dead data - they are verbatim runs of template 0: entries 28-45 repeat template 0's entries 7-24 ; and entries 78-95 repeat template 0's entries 57-74, in both the column and the row array. Their ; flag bytes were cleaned to $00 / $21. Only the $FF in the type array is read. unitStartTemplate1: .byte $16,$17,$16,$17,$13,$14,$13,$14,$10,$11; F190 .......... unitCol[0-49] of template 1: entries 28-45 are dead slots, entry 49 the COMCEN .byte $10,$11,$0D,$0E,$0D,$0E,$0A,$0B,$0A,$0B; F19A .......... .byte $07,$08,$07,$08,$04,$05,$04,$05,$03,$24; F1A4 .........$ .byte $21,$05,$07,$21,$12,$06,$05,$14,$13,$04; F1AE !..!...... .byte $06,$05,$22,$14,$12,$22,$05,$0E,$17,$0E; F1B8 .."..".... .byte $11,$10,$11,$10,$14,$13,$14,$13,$17,$16; F1C2 .......... unitCol[50-99]: side 1's columns; entries 78-95 dead, entry 99 the COMCEN .byte $17,$16,$1A,$19,$1A,$19,$1D,$1C,$1D,$1C; F1CC .......... .byte $20,$1F,$20,$1F,$23,$22,$23,$22,$22,$06; F1D6 . .#"#"". .byte $12,$15,$16,$13,$14,$21,$13,$04,$24,$14; F1E0 .....!..$. .byte $23,$22,$21,$20,$15,$05,$22,$19,$10,$19; F1EA #"! .."... template1StartRow: .byte $16,$16,$17,$17,$16,$16,$17,$17,$16,$16; F1F4 .......... unitRow[0-49] (see $F064): rider line rows 22-23, spies row 21, COMCEN row 25 .byte $17,$17,$16,$16,$17,$17,$16,$16,$17,$17; F1FE .......... .byte $16,$16,$17,$17,$16,$16,$17,$17,$1B,$1B; F208 .......... .byte $1A,$19,$1B,$1B,$1A,$1B,$1A,$1A,$1B,$1B; F212 .......... .byte $1A,$1B,$19,$1B,$1B,$1A,$15,$15,$15,$19; F21C .......... .byte $11,$11,$10,$10,$11,$11,$10,$10,$11,$11; F226 .......... unitRow[50-99]: side 1 - rider line 16-17, spies 18, COMCEN 14 .byte $10,$10,$11,$11,$10,$10,$11,$11,$10,$10; F230 .......... .byte $11,$11,$10,$10,$11,$11,$10,$10,$0D,$0C; F23A .......... .byte $0C,$0C,$0C,$0D,$0C,$0D,$0C,$0C,$0C,$06; F244 .......... .byte $0C,$0C,$0C,$0C,$0D,$0D,$12,$12,$12,$0E; F24E .......... template1StartFlags: .byte $40,$40,$40,$40,$44,$44,$44,$44,$48,$48; F258 @@@@DDDDHH unitFlags[0-49] (see $F0C8): seven side-0 squads of four, $40 ALPHA .. $58 GROVER .byte $48,$48,$4C,$4C,$4C,$4C,$50,$50,$50,$50; F262 HHLLLLPPPP .byte $54,$54,$54,$54,$58,$58,$58,$58,$00,$00; F26C TTTTXXXX.. .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00; F276 .......... .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00; F280 .......... .byte $61,$61,$61,$61,$65,$65,$65,$65,$69,$69; F28A aaaaeeeeii unitFlags[50-99]: the same seven squads on side 1, $61 ALPHA .. $79 GROVER .byte $69,$69,$6D,$6D,$6D,$6D,$71,$71,$71,$71; F294 iimmmmqqqq .byte $75,$75,$75,$75,$79,$79,$79,$79,$21,$21; F29E uuuuyyyy!! .byte $21,$21,$21,$21,$21,$21,$21,$21,$21,$21; F2A8 !!!!!!!!!! .byte $21,$21,$21,$21,$21,$21,$21,$21,$21,$21; F2B2 !!!!!!!!!! template1StartType: .byte $11,$11,$11,$11,$11,$11,$11,$11,$11,$11; F2BC .......... unitType[0-49] (see $F12C): 28 x $11 RIDER, 18 x $FF, 3 x $13 SPY, $14 COMCEN .byte $11,$11,$11,$11,$11,$11,$11,$11,$11,$11; F2C6 .......... .byte $11,$11,$11,$11,$11,$11,$11,$11,$FF,$FF; F2D0 .......... .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF; F2DA .......... .byte $FF,$FF,$FF,$FF,$FF,$FF,$13,$13,$13,$14; F2E4 .......... .byte $19,$19,$19,$19,$19,$19,$19,$19,$19,$19; F2EE .......... unitType[50-78]: side 1's 28 riders ($19) and the first empty slot .byte $19,$19,$19,$19,$19,$19,$19,$19,$19,$19; F2F8 .......... .byte $19,$19,$19,$19,$19,$19,$19,$19,$FF; F302 ......... ; Template 1's unitType[79-99]: the rest of the empty slots, then the three SPYs ($1B) and the COMCEN ; ($1C) of side 1. The label here has nothing to do with the template - it is the RUN-TIME meaning of ; the address: map cell (19,19) = $F000 + 40*19 + 19, which the map generator writes at $6F86 ($55, a ; river bend) when a point-symmetric map needs its two river halves joined at the centre. D_F30B: .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF; F30B .......... unitType[79-95] $FF empty, [96-98] $1B SPY, [99] $1C COMCEN .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$1B,$1B,$1B; F315 .......... .byte $1C ; F31F . ; unitStartTemplate2 ($F320-$F4AF) - used by game types 0 SCRIMAGE, 1 QB SNEAK and 2 THE BOMB. Eleven ; units a side and no groups at all (flags $00 / $21 throughout). It is a football formation: units ; 0-6 are the line of scrimmage in row 21 - a RIDER split out at column 7, GRUNTs at 14, 17, 20, 23 ; and 26, a RIDER split out at column 33 - unit 7 is the RIDER 'quarterback' at (20,23), units 8 and 9 ; the two RIDER backs at (18,25) and (22,25), and unit 49 the COMCEN at (20,25). Slots 10-48 are ; empty ($FF). Side 1 is the same formation reflected in the rows (side-1 row = 39 - side-0 row) but ; its columns are 40 - column instead of 39 - column, so on player 1's mirrored display side 1's line ; sits one cell to the left of side 0's; both COMCENs are stored at column 20. applyGameTypeDefaults ; ($7C85, in the map generator overlay) trims this roster once it has been copied: QB SNEAK deletes ; units 0-6, leaving only the quarterback, the two backs and the COMCEN, and THE BOMB deletes units ; 0-98 and puts unit 49 back as a COMCEN, so that game is fought by the two command centres and one ; extra drone each. The 39 empty slots a side are dead data: their column and row bytes are template ; 0's own entries at the same index, so this template was edited from a copy of template 0. The two ; exceptions are slots 10 (33,20) and 60 (27,19), which are not template-0 values - the formation ; evidently had a twelfth unit a side at some point. unitStartTemplate2: .byte $07,$0E,$11,$14,$17,$1A,$21,$14,$12,$16; F320 ......!... unitCol[0-18]: the line of scrimmage (7,14,17,20,23,26,33), the quarterback and the two backs .byte $21,$07,$21,$12,$06,$05,$14,$13,$04; F32A !.!...... ; Template 2's unitCol[19] - part of an empty slot, dead data. The label is the RUN-TIME meaning of ; the address: map cell (19,20) = $F000 + 40*20 + 19, written with $58 by the map generator at $6F81. D_F333: .byte $06 ; F333 . unitCol[19] = $06, unused ; Template 2's unitCol[20-49], all of them empty slots except the COMCEN at the end. The label is ; again the run-time meaning: map cell (20,20), cleared to $40 at $6F8B so that the two halves of a ; mirrored river join cleanly. D_F334: .byte $05,$22,$14,$12,$22,$20,$23,$15,$06,$05; F334 .".." #... unitCol[20] = $05, unused; entries 20-48 dead, entry 49 the COMCEN at column 20 .byte $06,$13,$05,$13,$14,$22,$22,$14,$21,$21; F33E ....."".!! .byte $06,$14,$21,$23,$04,$12,$13,$22,$05,$14; F348 ..!#...".. .byte $21,$1A,$17,$14,$11,$0E,$07,$14,$16,$12; F352 !......... unitCol[50-99]: side 1's line at 33,26,23,20,17,14,7, quarterback 57, backs 58/59, COMCEN 99 .byte $1B,$16,$13,$14,$21,$13,$04,$24,$14,$23; F35C ....!..$.# .byte $22,$21,$20,$15,$05,$14,$05,$14,$22,$21; F366 "! ....."! .byte $14,$13,$14,$22,$21,$05,$05,$06,$06,$13; F370 ..."!..... .byte $13,$23,$21,$15,$04,$06,$22,$14,$05,$14; F37A .#!..."... template2StartRow: .byte $15,$15,$15,$15,$15,$15,$15,$17,$19,$19; F384 .......... unitRow[0-49] (see $F064): row 21 the line, 23 the quarterback, 25 the backs and the COMCEN .byte $14,$1B,$1B,$1A,$1B,$1A,$1A,$1B,$1B,$1A; F38E .......... .byte $1B,$19,$1B,$1B,$1A,$1B,$1A,$1B,$1F,$1E; F398 .......... .byte $1E,$1F,$1F,$1E,$1E,$1F,$1E,$1F,$1F,$1E; F3A2 .......... .byte $1C,$1C,$1C,$1C,$1C,$1C,$17,$17,$17,$19; F3AC .......... .byte $12,$12,$12,$12,$12,$12,$12,$10,$0E,$0E; F3B6 .......... unitRow[50-99]: side 1's mirror - row 18 the line, 16 the quarterback, 14 the backs/COMCEN .byte $13,$0C,$0D,$0C,$0D,$0C,$0C,$0C,$06,$0C; F3C0 .......... .byte $0C,$0C,$0C,$0D,$0D,$0E,$0E,$0D,$09,$09; F3CA .......... .byte $08,$09,$09,$08,$08,$09,$08,$09,$08,$08; F3D4 .......... .byte $0B,$0B,$0B,$0B,$0B,$0B,$10,$10,$10,$0E; F3DE .......... template2StartFlags: .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00; F3E8 .......... unitFlags[0-49]: $00 for every side-0 unit - nothing is in a group in these game types .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00; F3F2 .......... .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00; F3FC .......... .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00; F406 .......... .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00; F410 .......... .byte $21,$21,$21,$21,$21,$21,$21,$21,$21,$21; F41A !!!!!!!!!! unitFlags[50-99]: $21 for every side-1 unit (bit 5 side, bit 0 facing down), no groups .byte $21,$21,$21,$21,$21,$21,$21,$21,$21,$21; F424 !!!!!!!!!! .byte $21,$21,$21,$21,$21,$21,$21,$21,$21,$21; F42E !!!!!!!!!! .byte $21,$21,$21,$21,$21,$21,$21,$21,$21,$21; F438 !!!!!!!!!! .byte $21,$21,$21,$21,$21,$21,$21,$21,$21,$21; F442 !!!!!!!!!! template2StartType: .byte $11,$10,$10,$10,$10,$10,$11,$11,$11,$11; F44C .......... unitType[0-49] (see $F12C): $11, five $10, four $11, then $FF to unit 48 and $14 COMCEN .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF; F456 .......... .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF; F460 .......... .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF; F46A .......... .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$14; F474 .......... .byte $19,$18,$18,$18,$18,$18,$19,$19,$19,$19; F47E .......... unitType[50-99]: the same eleven units on side 1 ($19 RIDER, $18 GRUNT, $1C COMCEN) .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF; F488 .......... .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF; F492 .......... .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF; F49C .......... .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$1C; F4A6 .......... ; unitStartTemplate3 ($F4B0-$F63F) - used by game type 4 SLUGGERS. Roster per side: 12 GRUNT (units ; 0-11), 12 RIDER (12-23), 4 BOOMER (24-27), 3 SPY (46-48) and 1 COMCEN (49); slots 28-45 are empty. ; Every combat unit is in a 2x2 squad of four, one squad per group name: side 0 has the grunt squads 0 ; ALPHA at columns 19-20 rows 26-27, 1 BAKER at 17-18 rows 27-28 and 2 CHARLIE at 21-22 rows 27-28 ; packed around the COMCEN at (20,30); the rider squads 3 DELTA at columns 9-10, 4 EASY at 19-20 and 5 ; FOXTROT at 29-30, all in rows 23-24; and the boomer squad 6 GROVER at 19-20 rows 28-29. The three ; spies stand loose in row 22 at columns 9, 20 and 30. Side 1 is the exact per-index 180-degree ; mirror (unit i+50 = (39-column, 39-row) of unit i, same type, same group). As in template 1 the 18 ; empty slots a side keep dead column and row bytes copied from template 0 (entries 28-45 = template ; 0's 7-24, entries 78-95 = template 0's 57-74); only their $FF type matters. This is also the one ; template whose 512-byte copy reads past its own end, into $F640-$F6AF - see the note there. unitStartTemplate3: .byte $13,$14,$13,$14,$11,$12,$11,$12,$15,$16; F4B0 .......... unitCol[0-49] of template 3: three grunt squads, three rider squads, a boomer squad, then dead slots .byte $15,$16,$09,$0A,$09,$0A,$13,$14,$13,$14; F4BA .......... .byte $1D,$1E,$1D,$1E,$13,$14,$13,$14,$03,$24; F4C4 .........$ .byte $21,$05,$07,$21,$12,$06,$05,$14,$13,$04; F4CE !..!...... .byte $06,$05,$22,$14,$12,$22,$09,$14,$1E,$14; F4D8 .."..".... .byte $14,$13,$14,$13,$16,$15,$16,$15,$12,$11; F4E2 .......... unitCol[50-99]: side 1's columns, the 39-column mirror of side 0's .byte $12,$11,$1E,$1D,$1E,$1D,$14,$13,$14,$13; F4EC .......... .byte $0A,$09,$0A,$09,$14,$13,$14,$13,$22,$06; F4F6 ........". .byte $12,$15,$16,$13,$14,$21,$13,$04,$24,$14; F500 .....!..$. .byte $23,$22,$21,$20,$15,$05,$1E,$13,$09,$13; F50A #"! ...... template3StartRow: .byte $1A,$1A,$1B,$1B,$1B,$1B,$1C,$1C,$1B,$1B; F514 .......... unitRow[0-49] (see $F064): riders 23-24, grunts 26-28, boomers 28-29, spies 22, COMCEN 30 .byte $1C,$1C,$17,$17,$18,$18,$17,$17,$18,$18; F51E .......... .byte $17,$17,$18,$18,$1C,$1C,$1D,$1D,$1B,$1B; F528 .......... .byte $1A,$19,$1B,$1B,$1A,$1B,$1A,$1A,$1B,$1B; F532 .......... .byte $1A,$1B,$19,$1B,$1B,$1A,$16,$16,$16,$1E; F53C .......... .byte $0D,$0D,$0C,$0C,$0C,$0C,$0B,$0B,$0C,$0C; F546 .......... unitRow[50-99]: side 1's rows 9-17, the mirror of side 0's .byte $0B,$0B,$10,$10,$0F,$0F,$10,$10,$0F,$0F; F550 .......... .byte $10,$10,$0F,$0F,$0B,$0B,$0A,$0A,$0D,$0C; F55A .......... .byte $0C,$0C,$0C,$0D,$0C,$0D,$0C,$0C,$0C,$06; F564 .......... .byte $0C,$0C,$0C,$0C,$0D,$0D,$11,$11,$11,$09; F56E .......... template3StartFlags: .byte $40,$40,$40,$40,$44,$44,$44,$44,$48,$48; F578 @@@@DDDDHH unitFlags[0-49] (see $F0C8): seven side-0 squads of four, $40 ALPHA .. $58 GROVER .byte $48,$48,$4C,$4C,$4C,$4C,$50,$50,$50,$50; F582 HHLLLLPPPP .byte $54,$54,$54,$54,$58,$58,$58,$58,$00,$00; F58C TTTTXXXX.. .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00; F596 .......... .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00; F5A0 .......... .byte $61,$61,$61,$61,$65,$65,$65,$65,$69,$69; F5AA aaaaeeeeii unitFlags[50-99]: the same seven squads on side 1, $61 ALPHA .. $79 GROVER .byte $69,$69,$6D,$6D,$6D,$6D,$71,$71,$71,$71; F5B4 iimmmmqqqq .byte $75,$75,$75,$75,$79,$79,$79,$79,$21,$21; F5BE uuuuyyyy!! .byte $21,$21,$21,$21,$21,$21,$21,$21,$21,$21; F5C8 !!!!!!!!!! .byte $21,$21,$21,$21,$21,$21,$21,$21,$21,$21; F5D2 !!!!!!!!!! template3StartType: .byte $10,$10,$10,$10,$10,$10,$10,$10,$10,$10; F5DC .......... unitType[0-35] (see $F12C): 12 x $10 GRUNT, 12 x $11 RIDER, 4 x $12 BOOMER, then $FF .byte $10,$10,$11,$11,$11,$11,$11,$11,$11,$11; F5E6 .......... .byte $11,$11,$11,$11,$12,$12,$12,$12,$FF,$FF; F5F0 .......... .byte $FF,$FF,$FF,$FF,$FF,$FF ; F5FA ...... ; Template 3's unitType[36-49]: the last empty slots, the three SPYs ($13) and the COMCEN ($14) of ; side 0. The label is the RUN-TIME meaning of the address: $F600 is where the 40x40 map's last 64 ; cells begin (cells 1536-1599), the tail that clearMapMarkers walks separately at $7536/$7541 after ; its six full pages. D_F600: .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF; F600 .......... unitType[36-45] $FF empty, [46-48] $13 SPY, [49] $14 COMCEN .byte $13,$13,$13,$14 ; F60A .... .byte $18,$18,$18,$18,$18,$18,$18,$18,$18,$18; F60E .......... unitType[50-99]: 12 x $18, 12 x $19, 4 x $1A, 18 x $FF, 3 x $1B and $1C - side 1's roster .byte $18,$18,$19,$19,$19,$19,$19,$19,$19,$19; F618 .......... .byte $19,$19,$19,$19,$1A,$1A,$1A,$1A,$FF,$FF; F622 .......... .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF; F62C .......... .byte $FF,$FF,$FF,$FF,$FF,$FF,$1B,$1B,$1B,$1C; F636 .......... ; $F640-$F6FF - 192 bytes that belong to no template and that the game never uses. They are a ; fragment of 6502 code from an OLDER build of the game, left in the mastering machine's memory when ; this block was written to the disk; the loader reads all seven sectors, so it comes along for the ; ride. ; Nothing ever reads it as data: the only reader of this file, loadUnitStartTemplate ($ECF3), copies ; at most $F4B0-$F6AF (template 3), and because that copy writes 400 bytes ahead of its own read ; pointer it has already replaced $F640-$F6AF with template 3's data before it gets there. The one ; byte that IS read is $F640 itself, as the 'the arrays still hold the disk image' flag - and it holds ; $0A, bit 7 clear, which would mean 'already loaded', so startGameSession stores $FF over it first ; ($78E4). Once a game starts this area is the live unitCol[0-99] ($F640) and unitRow[0-99] ($F6A4) ; arrays, which is what the labels below name; the bytes printed under them are the leftover code, not ; array data, and the labels fall in the middle of its instructions. Disassembled, the fragment is the ; tail of one routine plus two complete ones, each with a recognisable counterpart in the shipped ; build at a different address: ; $F640 asl a / sta $3F / lda #$14 / jmp $C097 ; the tail of setRepairMessageWindow, which in the shipped build ($19E1) ends 'lda #$0A / ; sta textCursorCol / lda #$14 / jmp setCursorRow': cursor to row 20, column 2*A. ; $F648 lda #$0C sta $3B / lda #$09 sta $39 sta $40 / lda #$12 sta $3C / lda #$00 sta $3F / ; jsr $C099 / lda #$61 sta $3D / lda #$B2 ldy #$CA jsr $C133 ; printOptionsList: text window left column 12, rows 9-18, width 18, colour $61, then the ; heading from $CAB2. The shipped printOptionsList ($19F3) is the same code with column 6, ; width $1D and the heading at $CB13. ; $F668 lda $92CD bne / lda $0881 beq ; 'is a game running?' - $92CD is the old build's gameEndCountdown and $0881 its ; gameEndReason; the shipped test at $1A13 uses $92C9 and $0BA8. ; $F672 lda #$10 ldy #$66 jsr $C133 / jsr $C137 / lda $E03B beq / jsr $C137 / rts ; no game: print the main menu from $6610, then LOAD GAME FILM, then DISCONNECT/SET VOICE if ; the link flag $E03B is set. Shipped: the same sequence at $1A36 with the text at $CC1F. ; $F685 lda #$98 ldy #$66 jsr $C133 / lda $0876 bmi / jsr $C137 / lda #$53 ldy #$CA jmp $C133 ; a game is running: ABORT GAME from $6698, VOICE PAUSE unless the film-playback flag ; $0876 is set, then ' (EXIT)' from $CA53. Shipped ($1A1B): $CCA6, two flag tests, $CAB2. ; $F69B lda #$FF sta $924A / lda $0881 bne $F711 / jsr $1648 / ldy #$02 / lda $0876 bmi / ; lda $087F bmi / iny / sty $91D5 / dey / sty $91D6 / dec $3B / lda $3B sta $3F / ; lda #$0B sta $91D7 / jsr $C097 / jsr $5F41 / ldy $91D6 beq / jsr $1205 / jmp $1648 ; miscTabAction, the MISC-tab options menu: two items, three in a modem game that is not a ; replay, highlight bar from row 11, run the selector, and on '(EXIT)' reprint the list. The ; shipped miscTabAction ($1A49) is instruction for instruction the same, with the menu state ; one byte lower ($91D4/$91D5/$91D6 instead of $91D5/$91D6/$91D7). ; $F6D8 jsr $0CD8 / lda $E03B beq / lda $0877 bmi,beq / lda #$00 sta $73 sta $9164 / ; lda $E044 bmi / jsr $C7FF / lda #$8C jsr $5178 / lda #$26 sta $7F / (jsr, cut off) ; the ABORT GAME path: if the link is up and a game session is agreed, clear the exchange ; throttle, skip the handshake when the opponent module is the trainer ($E044 = the old ; build's commBuildId), show 'WORKING...', queue command $8C reason 0, wait $26 ticks. ; Shipped: $1A86-$1AAE, with commBuildId $E030, showWorkingMessage $C853, queueCmd2 $561F. ; The block ends in the middle of that last JSR: only its $20 opcode fits in the seven sectors. What ; dates the fragment to a different build is that every one of its own addresses differs from the ; shipped equivalent - printOptionsList $1648 vs $19F3, setMenuTextWindow $1205 vs $1575, ; runInGameOptionsMenu $5F41 vs $65A0, queueCmd2 $5178 vs $561F, showWorkingMessage $C7FF vs $C853, ; the mode flags $0876/$0877/$087F/$0881 vs $0B9B/$0B9C/$0BA5/$0BA8, the menu text $6610/$6698/$CA53 ; vs $CC1F/$CCA6/$CAB2, linkPollDelay $9164 vs $9163, commBuildId $E044 vs $E030 - while the low-level ; text engine entries it calls ($C097 setCursorRow, $C099 updateCursorPointers, $C133 printString, ; $C137 printStringAtPointer) and the link-active flag $E03B are at exactly the addresses the shipped ; build uses. So it is the same program a few hundred bytes shorter, before the $0800 and $C000 ; blocks were rearranged. (Confidence: high that it is leftover code and that these are the matching ; routines; which build it came from cannot be pinned down further.) unitColTable: .byte $0A ; F640 map column of each of the 100 units; the parallel unit arrays follow every $64 bytes (0-49 side 0, 50-99 side 1, 49/99 = the comcens) .byte $85,$3F,$A9,$14,$4C,$97,$C0; F641 .?..L.. .byte $A9 ; F648 the old build's printOptionsList starts here; the shipped one is at $19F3 .byte $0C,$85,$3B,$A9,$09,$85,$39,$85; F649 ..;...9. .byte $40,$A9,$12,$85,$3C,$A9,$00,$85; F651 @...<... .byte $3F,$20,$99,$C0,$A9,$61,$85,$3D; F659 ? ...a.= .byte $A9,$B2,$A0,$CA,$20,$33,$C1,$AD; F661 .... 3.. .byte $CD,$92,$D0,$05,$AD,$81,$08,$F0; F669 ........ side0ComcenCol: .byte $13 ; F671 unitColTable[49]: column of side 0's COMCEN side1UnitColTable: .byte $A9 ; F672 unitColTable+50: the columns of side 1's units, indexed by that side's ordinal 0-49 .byte $10,$A0,$66,$20,$33,$C1,$20,$37; F673 ..f 3. 7 .byte $C1,$AD,$3B,$E0,$F0,$03,$20,$37; F67B ..;... 7 .byte $C1,$60 ; F683 .` .byte $A9 ; F685 'a game is running' branch: ABORT GAME / VOICE PAUSE / (EXIT) .byte $98,$A0 ; F686 .. unitFlagsTableAlias: .byte $66 ; F688 unitFlagsTable - $80, so it can be indexed with a raw map byte ($80 | unit) .byte $20,$33,$C1,$AD,$76,$08,$30,$03; F689 3..v.0. .byte $20,$37,$C1,$A9,$53,$A0,$CA,$4C; F691 7..S..L .byte $33,$C1 ; F699 3. .byte $A9 ; F69B the old build's miscTabAction starts here; the shipped one is at $1A49 .byte $FF,$8D,$4A,$92,$AD,$81,$08; F69C ..J.... side1ComcenCol: .byte $D0 ; F6A3 unitColTable[99]: column of side 1's COMCEN unitRowTable: .byte $6C ; F6A4 map row of each of the 100 units .byte $20,$48,$16,$A0,$02,$AD,$76,$08; F6A5 H....v. .byte $30,$06,$AD,$7F,$08,$30,$01,$C8; F6AD 0....0.. .byte $8C,$D5,$91,$88,$8C,$D6,$91,$C6; F6B5 ........ .byte $3B,$A5,$3B,$85,$3F,$A9,$0B,$8D; F6BD ;.;.?... .byte $D7,$91,$20,$97,$C0,$20,$41,$5F; F6C5 .. .. A_ .byte $AC,$D6,$91,$F0,$06,$20,$05,$12; F6CD ..... .. side0ComcenRow: .byte $4C ; F6D5 unitRowTable[49]: row of side 0's COMCEN side1UnitRowTable: .byte $48 ; F6D6 unitRowTable+50: the rows of side 1's units .byte $16 ; F6D7 . .byte $20 ; F6D8 the ABORT GAME path: tell the opponent with command $8C and hang up (shipped $1A86) .byte $D8,$0C,$AD,$3B,$E0,$F0,$2E,$AD; F6D9 ...;.... .byte $77,$08,$30,$29,$F0,$24,$A9,$00; F6E1 w.0).$.. .byte $85,$73,$8D ; F6E9 .s. unitTypeTableAlias: .byte $64 ; F6EC unitTypeTable - $80, so it can be indexed with a raw map byte ($80 | unit) .byte $91,$AD,$44,$E0,$30,$18,$20,$FF; F6ED ..D.0. . .byte $C7,$A9,$8C,$20,$78,$51,$A9,$26; F6F5 ... xQ.& .byte $85,$7F ; F6FD .. .byte $20 ; F6FF $20 = the opcode of a JSR whose address bytes fell outside the seven sectors