{ "chunk": "game_comcenScreens6F00_6F00", "unit": "game/comcenScreens6F00", "unitLabels": { "game/comcenScreens6F00": { "6F91": "drawRadarInnerBezel", "701C": "printDroneCaption", "7097": "setLaunchIconOrigin", "70D9": "printStrikeCaption", "73EE": "storeGlyphBitmapPtr", "7444": "storeRadarBitmapPtr", "74FE": "testUnitAliveForRadar", "74EE": "glyphFromLowCellCode", "74F6": "unitCellToGlyph", "750A": "radarSideBranchOpcode", "7522": "hiddenEnemyCell", "72F6": "queueComcenStunnedMessage" } }, "notes": { "6F00": { "unit": "game/comcenScreens6F00", "routine": [ "drawDroneHeadingPanel - Draws the compass / heading dial in the top-left corner of the DRONE screen (game screen 2): frame window $0D (columns 1-9, rows 3-11), the 7x7 character picture at $97D1 at row 4 column 2, the 5x5 picture at $97B6 at row 5 column 3, and a 3x3 screen-RAM colour fill of $6E (blue %01 pixels over light-blue %10 pixels) at row 6 column 4.", "Sprites 3 and 0 (the heading line plus its white shadow) and sprite 5 (the red aircraft silhouette) are parked over this panel by the screen-2 entry code, so the panel is only the dial they sit in.", "In: nothing; expects the glyph-plotter parameter block $2A29-$2A2C to be all zero (buildDroneScreen clears it just before)", "Out: frame, two character pictures and 6 colour cells drawn; D_2A2D = 6 and D_2A2E = 4 left pointing at the colour patch; frameWidth/frameHeight ($9221/$9222) left at 5x5 by the last drawCharBlock", "Called from: buildDroneScreen ($7122) - the only caller in this overlay variant" ], "line": "window $0D = left 1, top 3, 9x9 - the compass panel outline" }, "6F02": { "unit": "game/comcenScreens6F00", "line": "draw the panel frame from that window's 9-tile set" }, "6F05": { "unit": "game/comcenScreens6F00", "line": "character-block origin row 4 (one row inside the frame top)" }, "6F07": { "unit": "game/comcenScreens6F00", "line": "D_2A2D is the glyph plotters' window row" }, "6F0A": { "unit": "game/comcenScreens6F00", "line": "character-block origin column 2 (one column inside the frame left)" }, "6F0C": { "unit": "game/comcenScreens6F00", "line": "D_2A2E is the glyph plotters' window column" }, "6F0F": { "unit": "game/comcenScreens6F00", "line": "low byte of the picture block at $97D1 (header 7,7 then 49 character codes)" }, "6F11": { "unit": "game/comcenScreens6F00", "line": "high byte -> $97D1: the 7x7 outer dial face" }, "6F13": { "unit": "game/comcenScreens6F00", "line": "stamp it over rows 4-10, columns 2-8" }, "6F16": { "unit": "game/comcenScreens6F00", "line": "next block starts one row lower, row 5" }, "6F18": { "unit": "game/comcenScreens6F00", "line": "set the window row for the inner picture" }, "6F1B": { "unit": "game/comcenScreens6F00", "line": "and one column further right, column 3" }, "6F1D": { "unit": "game/comcenScreens6F00", "line": "set the window column" }, "6F20": { "unit": "game/comcenScreens6F00", "line": "low byte of the picture block at $97B6 (header 5,5 then 25 character codes)" }, "6F22": { "unit": "game/comcenScreens6F00", "line": "high byte -> $97B6: the 5x5 inner dial face" }, "6F24": { "unit": "game/comcenScreens6F00", "line": "stamp it over rows 5-9, columns 3-7" }, "6F27": { "unit": "game/comcenScreens6F00", "line": "step the fill origin down to row 6" }, "6F2A": { "unit": "game/comcenScreens6F00", "line": "and right to column 4 - the 3x3 centre of the dial (label L_6F2A is a variant-A branch target only)" }, "6F2D": { "unit": "game/comcenScreens6F00", "line": "screen-RAM colour byte $6E: %01 pixels blue, %10 pixels light blue" }, "6F2F": { "unit": "game/comcenScreens6F00", "line": "3 columns wide" }, "6F31": { "unit": "game/comcenScreens6F00", "line": "3 rows high" }, "6F33": { "unit": "game/comcenScreens6F00", "line": "paint rows 6-8, columns 4-6 and return through fillScreenColourRect" }, "6F36": { "unit": "game/comcenScreens6F00", "routine": [ "drawDroneFuelPanel - Draws the fuel gauge panel in the bottom-left corner of the DRONE screen: frame window $0E (columns 1-9, rows 12-20), the same 7x7 picture as the compass ($97D1) at row 13 column 2 but forced to colour $BC (dark grey over medium grey), then the three caption characters $57,$58,$59 at row 17 columns 4-6 in colour $0C (black over medium grey).", "drawDroneFuelDigits writes the three tall digits into rows 15-16 of the same panel.", "In: nothing", "Out: frame, picture and caption drawn; the fixed-colour override textDrawParams ($2A29) and D_2A2A are cleared again on exit; D_2A2B = 0 (block-fill off); zp_18 = 17, zp_19 = 6", "Called from: buildDroneScreen ($7125) only" ], "line": "window $0E = left 1, top 12, 9x9 - the fuel panel outline" }, "6F38": { "unit": "game/comcenScreens6F00", "line": "draw its frame" }, "6F3B": { "unit": "game/comcenScreens6F00", "line": "non-zero = 'use the fixed colour in D_2A2A' instead of the per-character colour table $93B4" }, "6F3D": { "unit": "game/comcenScreens6F00", "line": "textDrawParams ($2A29) is the plotter's useFixedColour flag" }, "6F40": { "unit": "game/comcenScreens6F00", "line": "screen-RAM colour $BC: %01 pixels dark grey, %10 pixels medium grey" }, "6F42": { "unit": "game/comcenScreens6F00", "line": "D_2A2A is the fixed colour byte used by every glyph plotted from now on" }, "6F45": { "unit": "game/comcenScreens6F00", "line": "character-block origin row 13" }, "6F47": { "unit": "game/comcenScreens6F00", "line": "set the window row" }, "6F4A": { "unit": "game/comcenScreens6F00", "line": "character-block origin column 2" }, "6F4C": { "unit": "game/comcenScreens6F00", "line": "set the window column" }, "6F4F": { "unit": "game/comcenScreens6F00", "line": "low byte of the 7x7 picture at $97D1" }, "6F51": { "unit": "game/comcenScreens6F00", "line": "high byte -> $97D1, the same dial art reused as the gauge body" }, "6F53": { "unit": "game/comcenScreens6F00", "line": "stamp it over rows 13-19, columns 2-8" }, "6F56": { "unit": "game/comcenScreens6F00", "line": "0 = do not replace the block characters with a fill character" }, "6F58": { "unit": "game/comcenScreens6F00", "line": "D_2A2B is drawCharBlock's block-fill flag" }, "6F5B": { "unit": "game/comcenScreens6F00", "line": "keep the fixed-colour override on for the caption too" }, "6F5D": { "unit": "game/comcenScreens6F00", "line": "textDrawParams = $FF" }, "6F60": { "unit": "game/comcenScreens6F00", "line": "screen-RAM colour $0C: %01 pixels black, %10 pixels medium grey" }, "6F62": { "unit": "game/comcenScreens6F00", "line": "fixed colour for the caption characters" }, "6F65": { "unit": "game/comcenScreens6F00", "line": "caption row 17 (two rows below the digits at rows 15-16)" }, "6F67": { "unit": "game/comcenScreens6F00", "line": "zp_18 is drawCharAt's cell row" }, "6F69": { "unit": "game/comcenScreens6F00", "line": "caption starts at column 4, under the leftmost digit" }, "6F6B": { "unit": "game/comcenScreens6F00", "line": "zp_19 is drawCharAt's cell column" }, "6F6D": { "unit": "game/comcenScreens6F00", "line": "caption glyph $57 (first third of the 3-character 'fuel' legend)" }, "6F6F": { "unit": "game/comcenScreens6F00", "line": "plot it at row 17, column 4" }, "6F72": { "unit": "game/comcenScreens6F00", "line": "advance to column 5" }, "6F74": { "unit": "game/comcenScreens6F00", "line": "caption glyph $58" }, "6F76": { "unit": "game/comcenScreens6F00", "line": "plot it at row 17, column 5" }, "6F79": { "unit": "game/comcenScreens6F00", "line": "advance to column 6" }, "6F7B": { "unit": "game/comcenScreens6F00", "line": "caption glyph $59" }, "6F7D": { "unit": "game/comcenScreens6F00", "line": "plot it at row 17, column 6" }, "6F80": { "unit": "game/comcenScreens6F00", "line": "release the colour override again..." }, "6F82": { "unit": "game/comcenScreens6F00", "line": "...so later text uses the per-character colour table" }, "6F85": { "unit": "game/comcenScreens6F00", "line": "and clear the fixed colour byte" }, "6F88": { "unit": "game/comcenScreens6F00", "line": "done" }, "6F89": { "unit": "game/comcenScreens6F00", "routine": [ "drawDroneRadarFrame - Draws the double frame around the drone camera window and clears the window: builds a fresh set of radar noise masks, draws window $0F (left 11, top 4, 18x16) and window $10 (left 12, top 5, 16x14), then falls through into clearRadarWindowBlack which blanks the 14x12 camera area and re-centres the view on the player's own comcen.", "In: comcenUnit ($9236), unit column/row arrays", "Out: two frames drawn; radarNoiseMasks ($9210-$921F) re-randomised; camera area filled with colour 0; radarGhostCountdown ($920F) = 0; viewOriginCol/Row (zp_A5/zp_A6) = comcen - (6,5); radarWipeColour ($7134) = 0", "Called from: buildDroneScreen ($712B) only" ], "line": "re-roll the 16 noise masks used for unspotted enemy blips" }, "6F8C": { "unit": "game/comcenScreens6F00", "line": "window $0F = left 11, top 4, 18 wide x 16 rows - outer camera bezel" }, "6F8E": { "unit": "game/comcenScreens6F00", "line": "draw it (label L_6F8E is a variant-A branch target only)" }, "6F91": { "unit": "game/comcenScreens6F00", "line": "window $10 = left 12, top 5, 16 wide x 14 rows - inner camera bezel", "block": [ "The label at $6F91 is a variant-A entry point (serviceLinkWhileGenerating) that XREF merges into", "this file; in overlay variant B it is just the next instruction of drawDroneRadarFrame." ] }, "6F93": { "unit": "game/comcenScreens6F00", "line": "draw it" }, "6F96": { "unit": "game/comcenScreens6F00", "line": "blank the camera area and centre the view on the own comcen; returns from there" }, "6F99": { "unit": "game/comcenScreens6F00", "routine": [ "drawDroneFuelDigits - Prints droneFuel ($9220) as three tall (2-row) digits at rows 15-16, columns 4-6 of the fuel panel. splitDecimalDigits splits the value into hundreds ($C44E), tens ($C44F) and ones ($C450) and drawTallGlyph draws each digit as a pair of characters from the glyph-pair table at $9810.", "The colour is a fuel warning: $30 (cyan over black) above 20, $B7 (dark grey over yellow) for 11-20, $21 (red over white) for 10 or less; below 21 the two nibbles are swapped on even fuel values, so the read-out flashes as it counts down towards empty.", "In: droneFuel ($9220), 0-100", "Out: six characters drawn; $C44E-$C450 = the decimal digits; textDrawParams/D_2A2A cleared on exit; zp_18 = 15, zp_19 = 6, zp_1A used as the nibble-rotate carry buffer", "Called from: buildDroneScreen ($7128), playDroneLostAnimation ($71FC, fuel forced to 0), launchDrone ($80B5, fuel set to 100), endDroneFlight ($81DA) and advanceDroneCamera ($82A1, once per exchange)" ], "line": "current fuel, counted down one per command exchange" }, "6F9C": { "unit": "game/comcenScreens6F00", "line": "split it into hundreds/tens/ones at $C44E/$C44F/$C450" }, "6F9F": { "unit": "game/comcenScreens6F00", "line": "digits go on row 15 (drawTallGlyph also uses row 16)" }, "6FA1": { "unit": "game/comcenScreens6F00", "line": "zp_18 = cell row" }, "6FA3": { "unit": "game/comcenScreens6F00", "line": "leftmost digit column 4" }, "6FA5": { "unit": "game/comcenScreens6F00", "line": "zp_19 = cell column" }, "6FA7": { "unit": "game/comcenScreens6F00", "line": "force the fixed draw colour instead of the per-character table" }, "6FA9": { "unit": "game/comcenScreens6F00", "line": "textDrawParams = $FF" }, "6FAC": { "unit": "game/comcenScreens6F00", "line": "default colour $30: %01 cyan, %10 black - plenty of fuel" }, "6FAE": { "unit": "game/comcenScreens6F00", "line": "reload the fuel level for the range tests" }, "6FB1": { "unit": "game/comcenScreens6F00", "line": "21 or more?" }, "6FB3": { "unit": "game/comcenScreens6F00", "line": "yes - keep $30 and skip the flashing logic entirely" }, "6FB5": { "unit": "game/comcenScreens6F00", "line": "warning colour $B7: %01 dark grey, %10 yellow" }, "6FB7": { "unit": "game/comcenScreens6F00", "line": "11 or more?" }, "6FB9": { "unit": "game/comcenScreens6F00", "line": "yes - keep $B7" }, "6FBB": { "unit": "game/comcenScreens6F00", "line": "critical colour $21: %01 red, %10 white" }, "6FBD": { "unit": "game/comcenScreens6F00", "line": "test the fuel level's parity (A still holds the fuel)" }, "6FBF": { "unit": "game/comcenScreens6F00", "line": "odd exchange - draw in the plain colour" }, "6FC1": { "unit": "game/comcenScreens6F00", "line": "even exchange: A is 0 here, so this clears the rotate buffer" }, "6FC3": { "unit": "game/comcenScreens6F00", "line": "take the colour byte into A for the nibble swap" }, "6FC4": { "unit": "game/comcenScreens6F00", "line": "shift the colour left one bit..." }, "6FC5": { "unit": "game/comcenScreens6F00", "line": "...catching the bit that falls out in zp_1A (rotate left through 8 bits)" }, "6FC7": { "unit": "game/comcenScreens6F00", "line": "bit 2 of 4" }, "6FC8": { "unit": "game/comcenScreens6F00", "line": "collect it" }, "6FCA": { "unit": "game/comcenScreens6F00", "line": "bit 3 of 4" }, "6FCB": { "unit": "game/comcenScreens6F00", "line": "collect it" }, "6FCD": { "unit": "game/comcenScreens6F00", "line": "bit 4 of 4 - the byte has now rotated left by four" }, "6FCE": { "unit": "game/comcenScreens6F00", "line": "collect the last carried bit" }, "6FD0": { "unit": "game/comcenScreens6F00", "line": "merge the two halves: the nibbles are now swapped" }, "6FD2": { "unit": "game/comcenScreens6F00", "line": "back into X as the colour byte" }, "6FD3": { "unit": "game/comcenScreens6F00", "line": "install the chosen colour as the plotter's fixed colour" }, "6FD6": { "unit": "game/comcenScreens6F00", "line": "hundreds digit (1 only when fuel is 100)" }, "6FD9": { "unit": "game/comcenScreens6F00", "line": "draw it as a 2-row glyph pair at row 15/16, column 4" }, "6FDC": { "unit": "game/comcenScreens6F00", "line": "move to column 5" }, "6FDE": { "unit": "game/comcenScreens6F00", "line": "tens digit" }, "6FE1": { "unit": "game/comcenScreens6F00", "line": "draw it at column 5" }, "6FE4": { "unit": "game/comcenScreens6F00", "line": "move to column 6" }, "6FE6": { "unit": "game/comcenScreens6F00", "line": "ones digit" }, "6FE9": { "unit": "game/comcenScreens6F00", "line": "draw it at column 6" }, "6FEC": { "unit": "game/comcenScreens6F00", "line": "restore the normal colour handling..." }, "6FEE": { "unit": "game/comcenScreens6F00", "line": "...clear the fixed-colour flag..." }, "6FF1": { "unit": "game/comcenScreens6F00", "line": "...and the fixed colour byte" }, "6FF4": { "unit": "game/comcenScreens6F00", "line": "done" }, "6FF5": { "unit": "game/comcenScreens6F00", "routine": [ "drawDroneCountPanel - Draws the 'DRONE' counter panel at the top right of the DRONE screen: resets the text window to the full screen, draws window $11 (left 29, top 3, 11x7) with the four inner corner marks, window $12 (left 32, top 4, 5x4), fills the 3x2 colour box for the digit at row 5 column 33 with $30, and prints the caption 'DRONE' ($868C) at row 7 column 32 in colour $CF with the bitmap draw mode set to OR.", "In: nothing", "Out: frames, colour box and caption drawn; textColour zp_3D = $CF, textCursorCol zp_3F = 32, textCursorRow zp_40 = 7; both draw modes reset to replace on exit", "Called from: buildDroneScreen ($7119) only" ], "line": "text window = whole 40x25 screen so the absolute column below is not shifted" }, "6FF8": { "unit": "game/comcenScreens6F00", "line": "window $11 = left 29, top 3, 11 wide x 7 rows - outer counter panel" }, "6FFA": { "unit": "game/comcenScreens6F00", "line": "draw its frame" }, "6FFD": { "unit": "game/comcenScreens6F00", "line": "add character $38 just inside the four corners of that frame" }, "7000": { "unit": "game/comcenScreens6F00", "line": "window $12 = left 32, top 4, 5 wide x 4 rows - the box around the digit" }, "7002": { "unit": "game/comcenScreens6F00", "line": "draw its frame" }, "7005": { "unit": "game/comcenScreens6F00", "line": "colour fill origin row 5" }, "7007": { "unit": "game/comcenScreens6F00", "line": "D_2A2D = window row" }, "700A": { "unit": "game/comcenScreens6F00", "line": "colour fill origin column 33" }, "700C": { "unit": "game/comcenScreens6F00", "line": "D_2A2E = window column" }, "700F": { "unit": "game/comcenScreens6F00", "line": "screen-RAM colour $30: %01 cyan, %10 black - the digit's background" }, "7011": { "unit": "game/comcenScreens6F00", "line": "3 columns" }, "7013": { "unit": "game/comcenScreens6F00", "line": "2 rows (the tall digit is 2 cells high)" }, "7015": { "unit": "game/comcenScreens6F00", "line": "paint rows 5-6, columns 33-35" }, "7018": { "unit": "game/comcenScreens6F00", "line": "colour RAM value for the caption ($F = light grey for the %11 pixels)" }, "701A": { "unit": "game/comcenScreens6F00", "line": "zp_3D is the colour the $C000 text plotter writes per cell" }, "701C": { "unit": "game/comcenScreens6F00", "line": "bitmap draw mode 1 = OR the glyph into the existing bitmap (label is a variant-A entry point only)" }, "701E": { "unit": "game/comcenScreens6F00", "line": "patch the plotter's read instruction accordingly" }, "7021": { "unit": "game/comcenScreens6F00", "line": "caption column 32" }, "7023": { "unit": "game/comcenScreens6F00", "line": "zp_3F = cursor column, relative to the window left edge (0 here)" }, "7025": { "unit": "game/comcenScreens6F00", "line": "caption row 7 (the bottom frame row of window $12)" }, "7027": { "unit": "game/comcenScreens6F00", "line": "zp_40 = cursor row" }, "7029": { "unit": "game/comcenScreens6F00", "line": "recompute the bitmap and colour-RAM pointers for that cell" }, "702C": { "unit": "game/comcenScreens6F00", "line": "low byte of the string 'DRONE' at $868C" }, "702E": { "unit": "game/comcenScreens6F00", "line": "high byte -> $868C" }, "7030": { "unit": "game/comcenScreens6F00", "line": "print it (strings end on a byte with bit 7 set)" }, "7033": { "unit": "game/comcenScreens6F00", "line": "put both draw modes back to plain replace and return" }, "7036": { "unit": "game/comcenScreens6F00", "routine": [ "drawDroneCountDigit - Draws the number of drones still available (radarDronesLeft $9233) as a single tall digit at rows 5-6, column 34, in the fixed colour $30. When no drones are left the colour byte is forced to 0, which makes the digit the same colour as its background, i.e. invisible.", "In: radarDronesLeft ($9233), 0-9", "Out: one glyph pair drawn; textDrawParams/D_2A2A cleared on exit; zp_18 = 5, zp_19 = 34", "Called from: buildDroneScreen ($711C) and launchDrone ($80BB) after the counter is decremented" ], "line": "digit row 5" }, "7038": { "unit": "game/comcenScreens6F00", "line": "zp_18 = cell row" }, "703A": { "unit": "game/comcenScreens6F00", "line": "digit column 34 (centre of the 33-35 colour box)" }, "703C": { "unit": "game/comcenScreens6F00", "line": "zp_19 = cell column" }, "703E": { "unit": "game/comcenScreens6F00", "line": "use the fixed colour in D_2A2A..." }, "7040": { "unit": "game/comcenScreens6F00", "line": "...rather than the per-character colour table" }, "7043": { "unit": "game/comcenScreens6F00", "line": "normal digit colour $30 (%01 cyan, %10 black)" }, "7045": { "unit": "game/comcenScreens6F00", "line": "drones left" }, "7048": { "unit": "game/comcenScreens6F00", "line": "at least one left?" }, "704A": { "unit": "game/comcenScreens6F00", "line": "yes - keep colour $30" }, "704C": { "unit": "game/comcenScreens6F00", "line": "none left: colour byte 0, so the glyph vanishes into the background" }, "704D": { "unit": "game/comcenScreens6F00", "line": "install the colour" }, "7050": { "unit": "game/comcenScreens6F00", "line": "reload the count - it is also the glyph-pair index for drawTallGlyph" }, "7053": { "unit": "game/comcenScreens6F00", "line": "no-op branch: both paths continue at $7055 (probably a leftover leading-zero test)" }, "7055": { "unit": "game/comcenScreens6F00", "line": "draw the digit as a 2-row glyph pair at rows 5-6, column 34" }, "7058": { "unit": "game/comcenScreens6F00", "line": "restore normal colour handling..." }, "705A": { "unit": "game/comcenScreens6F00", "line": "...clear the fixed-colour flag..." }, "705D": { "unit": "game/comcenScreens6F00", "line": "...and the fixed colour" }, "7060": { "unit": "game/comcenScreens6F00", "line": "done" }, "7061": { "unit": "game/comcenScreens6F00", "routine": [ "blinkDroneCountBox - Alternates the background of the drones-left box (3x2 colour cells at row 5, column 33) between $30 and its nibble-swapped twin $03 according to bit 0 of the frame counter, which swaps the foreground and background of the tall digit sitting in it and makes the counter flash.", "In: frameCounter (zp_45) bit 0", "Out: 6 screen-RAM colour cells rewritten; D_2A2D = 5, D_2A2E = 33, D_2A2A = the colour used; zp_1A used as the rotate buffer", "Called from: droneScreenIdleLoop ($8067, every 11 frames) and droneFlightLoop ($813E, every 40 frames), in both cases only while fewer than two drones remain" ], "line": "colour fill origin row 5" }, "7063": { "unit": "game/comcenScreens6F00", "line": "D_2A2D = window row" }, "7066": { "unit": "game/comcenScreens6F00", "line": "colour fill origin column 33" }, "7068": { "unit": "game/comcenScreens6F00", "line": "D_2A2E = window column" }, "706B": { "unit": "game/comcenScreens6F00", "line": "base colour $30 (%01 cyan, %10 black)" }, "706D": { "unit": "game/comcenScreens6F00", "line": "free-running frame counter maintained by the raster IRQ" }, "706F": { "unit": "game/comcenScreens6F00", "line": "look at its parity" }, "7071": { "unit": "game/comcenScreens6F00", "line": "odd frame - use $30 unchanged" }, "7073": { "unit": "game/comcenScreens6F00", "line": "even frame: A is 0, so this clears the rotate buffer" }, "7075": { "unit": "game/comcenScreens6F00", "line": "colour byte into A for the nibble swap" }, "7076": { "unit": "game/comcenScreens6F00", "line": "rotate the byte left by four bits, one shift..." }, "7077": { "unit": "game/comcenScreens6F00", "line": "...catching the bit that leaves the byte" }, "7079": { "unit": "game/comcenScreens6F00", "line": "shift 2" }, "707A": { "unit": "game/comcenScreens6F00", "line": "catch" }, "707C": { "unit": "game/comcenScreens6F00", "line": "shift 3" }, "707D": { "unit": "game/comcenScreens6F00", "line": "catch" }, "707F": { "unit": "game/comcenScreens6F00", "line": "shift 4" }, "7080": { "unit": "game/comcenScreens6F00", "line": "catch" }, "7082": { "unit": "game/comcenScreens6F00", "line": "merge - $30 has become $03 (%01 black, %10 cyan)" }, "7084": { "unit": "game/comcenScreens6F00", "line": "keep it in X" }, "7085": { "unit": "game/comcenScreens6F00", "line": "colour byte back into A for the fill call" }, "7086": { "unit": "game/comcenScreens6F00", "line": "3 columns (33-35)" }, "7088": { "unit": "game/comcenScreens6F00", "line": "2 rows (5-6)" }, "708A": { "unit": "game/comcenScreens6F00", "line": "repaint the box and return through fillScreenColourRect" }, "708D": { "unit": "game/comcenScreens6F00", "routine": [ "drawLaunchStrikeButtons - Draws the two-button panel down the right edge of the DRONE screen: frame window $13 (left 30, top 10, 10 wide x 11 rows) with inner corner marks, the 2x2 button icon from $9804 (characters $45-$48) at row 12 column 34 painted colour $05, the caption 'LAUNCH' ($8691) at row 14 column 32, the same icon again at row 16 column 34, and the caption 'STRIKE' ($8697) at row 18 column 32.", "The screen-2 loops afterwards recolour these two 2x2 icon blocks: colour $05 when LAUNCH is pressed, colour $02 when STRIKE is pressed and an XOR of $08 for the idle blink.", "In: nothing", "Out: frame, two icons and two captions drawn; zp_3D/zp_3F/zp_40 left at $C7/32/18; both draw modes reset to replace", "Called from: buildDroneScreen ($711F) only", "Note: the survey's window geometry was wrong - windowLeftTable[$13] = 30 and windowWidthTable[$13] = 10, not left 29 / width 14." ], "line": "window $13 = left 30, top 10, 10 wide x 11 rows - the button panel" }, "708F": { "unit": "game/comcenScreens6F00", "line": "draw its frame" }, "7092": { "unit": "game/comcenScreens6F00", "line": "add the four inner corner marks (character $38)" }, "7095": { "unit": "game/comcenScreens6F00", "line": "LAUNCH icon row 12" }, "7097": { "unit": "game/comcenScreens6F00", "line": "D_2A2D = window row (label is a variant-A entry point only)" }, "709A": { "unit": "game/comcenScreens6F00", "line": "LAUNCH icon column 34" }, "709C": { "unit": "game/comcenScreens6F00", "line": "D_2A2E = window column" }, "709F": { "unit": "game/comcenScreens6F00", "line": "low byte of the 2x2 icon block at $9804 (header 2,2 then characters $45,$46,$47,$48)" }, "70A1": { "unit": "game/comcenScreens6F00", "line": "high byte -> $9804" }, "70A3": { "unit": "game/comcenScreens6F00", "line": "stamp the icon at rows 12-13, columns 34-35" }, "70A6": { "unit": "game/comcenScreens6F00", "line": "screen-RAM colour $05: %01 black, %10 green - the unpressed button" }, "70A8": { "unit": "game/comcenScreens6F00", "line": "2 columns" }, "70AA": { "unit": "game/comcenScreens6F00", "line": "2 rows" }, "70AC": { "unit": "game/comcenScreens6F00", "line": "paint the icon's 4 colour cells" }, "70AF": { "unit": "game/comcenScreens6F00", "line": "colour RAM value for the caption ($D = light green for the %11 pixels)" }, "70B1": { "unit": "game/comcenScreens6F00", "line": "zp_3D = text colour" }, "70B3": { "unit": "game/comcenScreens6F00", "line": "text window = whole screen so column 32 is absolute" }, "70B6": { "unit": "game/comcenScreens6F00", "line": "caption column 32" }, "70B8": { "unit": "game/comcenScreens6F00", "line": "zp_3F = cursor column" }, "70BA": { "unit": "game/comcenScreens6F00", "line": "caption row 14, just under the icon" }, "70BC": { "unit": "game/comcenScreens6F00", "line": "zp_40 = cursor row" }, "70BE": { "unit": "game/comcenScreens6F00", "line": "recompute the cell pointers" }, "70C1": { "unit": "game/comcenScreens6F00", "line": "low byte of 'LAUNCH' at $8691" }, "70C3": { "unit": "game/comcenScreens6F00", "line": "high byte -> $8691" }, "70C5": { "unit": "game/comcenScreens6F00", "line": "print it" }, "70C8": { "unit": "game/comcenScreens6F00", "line": "STRIKE icon row 16" }, "70CA": { "unit": "game/comcenScreens6F00", "line": "D_2A2D = window row" }, "70CD": { "unit": "game/comcenScreens6F00", "line": "STRIKE icon column 34" }, "70CF": { "unit": "game/comcenScreens6F00", "line": "D_2A2E = window column" }, "70D2": { "unit": "game/comcenScreens6F00", "line": "the same 2x2 icon block at $9804..." }, "70D4": { "unit": "game/comcenScreens6F00", "line": "...high byte" }, "70D6": { "unit": "game/comcenScreens6F00", "line": "stamp it at rows 16-17, columns 34-35 (its colour cells are left as the frame drew them until a strike is armed)" }, "70D9": { "unit": "game/comcenScreens6F00", "line": "colour RAM value for the caption (7 = yellow for the %11 pixels) (label is a variant-A entry point only)" }, "70DB": { "unit": "game/comcenScreens6F00", "line": "zp_3D = text colour" }, "70DD": { "unit": "game/comcenScreens6F00", "line": "text window = whole screen" }, "70E0": { "unit": "game/comcenScreens6F00", "line": "caption column 32" }, "70E2": { "unit": "game/comcenScreens6F00", "line": "zp_3F = cursor column" }, "70E4": { "unit": "game/comcenScreens6F00", "line": "caption row 18" }, "70E6": { "unit": "game/comcenScreens6F00", "line": "zp_40 = cursor row" }, "70E8": { "unit": "game/comcenScreens6F00", "line": "recompute the cell pointers" }, "70EB": { "unit": "game/comcenScreens6F00", "line": "low byte of 'STRIKE' at $8697" }, "70ED": { "unit": "game/comcenScreens6F00", "line": "high byte -> $8697" }, "70EF": { "unit": "game/comcenScreens6F00", "line": "print it" }, "70F2": { "unit": "game/comcenScreens6F00", "line": "restore both draw modes and return" }, "70F5": { "unit": "game/comcenScreens6F00", "routine": [ "buildDroneScreen - Paints the whole DRONE screen (game screen 2) from scratch: clears the glyph plotter's parameter block, sets border and background shadows to $0C (medium grey), sets the radar cell background nibble to $0A (light red) and marks the screen as built, then draws every panel in turn and finishes by redrawing the status line through the $C000 overlay.", "In: droneFuel ($9220), radarDronesLeft ($9233), comcenUnit ($9236)", "Out: complete screen 2; vicBorderShadow/vicBg0Shadow ($9003/$9004) = $0C, cellBackgroundColour ($9226) = $0A, screenBuiltFlag (zp_41) = 1, $2A29-$2A2C = 0; jumps away into redrawStatusMessage", "Called from: resetDroneScreen ($7FF3), which is entered from the screen-2 entry $7FE6 and from the comcen knock-out sequence at $076A" ], "line": "clear the glyph plotter parameter block..." }, "70F7": { "unit": "game/comcenScreens6F00", "line": "...useFixedColour flag off" }, "70FA": { "unit": "game/comcenScreens6F00", "line": "...fixed colour byte 0" }, "70FD": { "unit": "game/comcenScreens6F00", "line": "...block-fill flag off" }, "7100": { "unit": "game/comcenScreens6F00", "line": "...block-fill character 0" }, "7103": { "unit": "game/comcenScreens6F00", "line": "$0C = medium grey" }, "7105": { "unit": "game/comcenScreens6F00", "line": "background colour 0 shadow (written to $D021 by the raster IRQ)" }, "7108": { "unit": "game/comcenScreens6F00", "line": "border colour shadow ($D020)" }, "710B": { "unit": "game/comcenScreens6F00", "line": "$0A = light red" }, "710D": { "unit": "game/comcenScreens6F00", "line": "cellBackgroundColour supplies the low nibble (%10 pixels) of every radar cell on this screen" }, "7110": { "unit": "game/comcenScreens6F00", "line": "every screen builder stores 1 here" }, "7112": { "unit": "game/comcenScreens6F00", "line": "zp_41 screenBuiltFlag; nothing ever reads it" }, "7114": { "unit": "game/comcenScreens6F00", "line": "redundant - D_2A2B was already cleared at $70FD" }, "7116": { "unit": "game/comcenScreens6F00", "line": "block-fill flag off (again)" }, "7119": { "unit": "game/comcenScreens6F00", "line": "top-right 'DRONE' counter panel" }, "711C": { "unit": "game/comcenScreens6F00", "line": "the drones-left digit inside it" }, "711F": { "unit": "game/comcenScreens6F00", "line": "the LAUNCH / STRIKE button panel" }, "7122": { "unit": "game/comcenScreens6F00", "line": "top-left compass dial" }, "7125": { "unit": "game/comcenScreens6F00", "line": "bottom-left fuel gauge panel" }, "7128": { "unit": "game/comcenScreens6F00", "line": "the three fuel digits" }, "712B": { "unit": "game/comcenScreens6F00", "line": "camera bezels; also blanks the camera and centres the view on the comcen" }, "712E": { "unit": "game/comcenScreens6F00", "line": "the outer main window / status bar frame (window 4 while a screen id is active)" }, "7131": { "unit": "game/comcenScreens6F00", "line": "re-show whatever the status line was displaying, and return from there" }, "7134": { "unit": "game/comcenScreens6F00", "block": [ "Radar/camera wipe state byte, shared by clearRadarWindowGrey, clearRadarWindowBlack,", "flashRadarAndWipe and drawRadarIrisWipe. It doubles as (a) the colour the camera window is", "blanked with and (b) a flag: non-zero makes the iris wipe pause 3 game frames per ring, zero", "makes it close instantly." ], "line": "$BB = animated grey wipe (after a launch), $00 = instant black wipe" }, "7135": { "unit": "game/comcenScreens6F00", "routine": [ "clearRadarWindowGrey - Blanks the 14x12 drone camera window (row 6, column 13) to colour $BB (dark grey on dark grey, i.e. static) and re-centres the view origin on the player's own comcen, leaving radarWipeColour ($7134) non-zero so the iris wipe that follows animates with 3-frame pauses.", "In: comcenUnit ($9236), unitColTable/unitRowTable", "Out: radarWipeColour = $BB; camera window filled with $BB; radarGhostCountdown ($920F) = 0; viewOriginCol/Row (zp_A5/zp_A6) = comcen column - 6, comcen row - 5", "Called from: launchDrone ($8116) only" ], "line": "$BB = dark grey in both multicolour nibbles - looks like blank static" }, "7137": { "unit": "game/comcenScreens6F00", "line": "remember it as both the fill colour and the 'animate the wipe' flag" }, "713A": { "unit": "game/comcenScreens6F00", "line": "always taken ($BB is non-zero); joins the shared tail" }, "713C": { "unit": "game/comcenScreens6F00", "routine": [ "clearRadarWindowBlack - Same as clearRadarWindowGrey but with colour 0: blanks the drone camera window to black and re-centres the view on the own comcen. radarWipeColour is left 0, so a following iris wipe runs with no pauses.", "In: comcenUnit ($9236), unitColTable/unitRowTable", "Out: radarWipeColour = 0; camera window black; radarGhostCountdown ($920F) = 0; viewOriginCol/Row = comcen - (6,5)", "Called from: drawDroneRadarFrame ($6F96, screen build) and endDroneFlight ($81F8)" ], "line": "colour 0 = all pixels black" }, "713E": { "unit": "game/comcenScreens6F00", "line": "0 also means 'no pauses in the iris wipe'" }, "7141": { "unit": "game/comcenScreens6F00", "block": [ "Shared tail of the two window clears: paint the camera area, forget any pending noise ghost", "and park the map view so that the own comcen sits in the middle of the 14x12 window", "(the drone starts its flight over the comcen)." ], "line": "fill the 14 column x 12 row camera window at row 6, column 13 with the colour in A" }, "7144": { "unit": "game/comcenScreens6F00", "line": "clear the countdown that decides when the next unspotted enemy is drawn as a ghost blip" }, "7146": { "unit": "game/comcenScreens6F00", "line": "radarGhostCountdown ($920F)" }, "7149": { "unit": "game/comcenScreens6F00", "line": "the player's own comcen (unit 49 for side 0, 99 for side 1)" }, "714C": { "unit": "game/comcenScreens6F00", "line": "its map column (unit arrays are 100-byte arrays $64 apart from $F640)" }, "714F": { "unit": "game/comcenScreens6F00", "line": "prepare the subtraction" }, "7150": { "unit": "game/comcenScreens6F00", "line": "the window is 14 cells wide, so back off 6 to put the comcen at cell 6" }, "7152": { "unit": "game/comcenScreens6F00", "line": "zp_A5 = map column of the window's left edge" }, "7154": { "unit": "game/comcenScreens6F00", "line": "the comcen's map row ($F6A4 = $F640 + $64)" }, "7157": { "unit": "game/comcenScreens6F00", "line": "prepare the subtraction" }, "7158": { "unit": "game/comcenScreens6F00", "line": "the window is 12 cells high, so back off 5 to put the comcen at cell 5" }, "715A": { "unit": "game/comcenScreens6F00", "line": "zp_A6 = map row of the window's top edge" }, "715C": { "unit": "game/comcenScreens6F00", "line": "done" }, "715D": { "unit": "game/comcenScreens6F00", "block": [ "Six bytes with no reference anywhere in overlay variant B ($21,$A1,$21,$81,$A1,$11).", "They are code or data of overlay variant A, which shares this address range; the label", "L_7161 is a branch target only in variant A. Dead in this variant." ], "line": "unreferenced filler in variant B (variant A code/data)" }, "7161": { "unit": "game/comcenScreens6F00", "line": "continuation of the same unreferenced filler" }, "7163": { "unit": "game/comcenScreens6F00", "routine": [ "playDroneLostAnimation - The 'drone is gone' effect, used when the drone is shot down, detonated by its own strike or runs out of fuel. It switches sprite 4 (the comcen range rings) off, flashes the camera window white and irises it shut, then rebuilds sprite 2 (the drone reticle) as a solid disc of radius 3 and lets it shrink and fade (white -> light grey -> medium grey -> dark grey) by erasing one ring at a time, disables sprite 2, zeroes the fuel read-out and waits 30 game frames.", "In: nothing meaningful (droneHeading is copied to a byte nobody reads)", "Out: spriteEnableShadow ($9022) bits 4 and 2 cleared; sprite 2 shape and colour changed; spritePlotMode ($91F3) = 0; droneFuel ($9220) = 0 and redrawn; textDrawParams/D_2A2A = 0; roughly 50 game frames elapse (the battle keeps running inside runGameFrames)", "Called from: playStrikeZoomAnimation ($7582, after a strike) and droneFlightLoop ($8177, drone lost)", "Dead code: 'sta zp_30' at $716A (only magnifyWindow2x uses zp_30, and it initialises it itself) and the store to savedDroneHeading at $717C (never read back)." ], "line": "force the fixed draw colour for everything drawn from here" }, "7165": { "unit": "game/comcenScreens6F00", "line": "textDrawParams = $FF" }, "7168": { "unit": "game/comcenScreens6F00", "line": "dead store: 5 into magnifySrcRow..." }, "716A": { "unit": "game/comcenScreens6F00", "line": "...zp_30, which magnifyWindow2x always initialises itself" }, "716C": { "unit": "game/comcenScreens6F00", "line": "current sprite enable mask shadow" }, "716F": { "unit": "game/comcenScreens6F00", "line": "clear bit 4 = sprite 4, the comcen range rings" }, "7171": { "unit": "game/comcenScreens6F00", "line": "the raster IRQ copies this to $D015" }, "7174": { "unit": "game/comcenScreens6F00", "line": "fixed colour 0 (black) for the wipe frames" }, "7176": { "unit": "game/comcenScreens6F00", "line": "D_2A2A = fixed colour byte" }, "7179": { "unit": "game/comcenScreens6F00", "line": "current drone heading 0-7" }, "717C": { "unit": "game/comcenScreens6F00", "line": "dead store - savedDroneHeading ($7271) is never read" }, "717F": { "unit": "game/comcenScreens6F00", "line": "flash the camera window white and iris it shut" }, "7182": { "unit": "game/comcenScreens6F00", "line": "sprite 2 = the drone reticle" }, "7184": { "unit": "game/comcenScreens6F00", "line": "zero its 64 shape bytes at $8A80" }, "7187": { "unit": "game/comcenScreens6F00", "line": "sprite plot mode $40 = OR pixels in (draw)" }, "7189": { "unit": "game/comcenScreens6F00", "line": "spritePlotMode ($91F3)" }, "718C": { "unit": "game/comcenScreens6F00", "line": "sprite 2" }, "718E": { "unit": "game/comcenScreens6F00", "line": "radius 3" }, "7190": { "unit": "game/comcenScreens6F00", "line": "draw a radius-3 circle centred at (12,10) in the sprite" }, "7193": { "unit": "game/comcenScreens6F00", "line": "sprite 2 again" }, "7195": { "unit": "game/comcenScreens6F00", "line": "X = 2 (A was 2) - radius 2" }, "7196": { "unit": "game/comcenScreens6F00", "line": "fill in the radius-2 ring, making the shape a solid disc" }, "7199": { "unit": "game/comcenScreens6F00", "line": "sprite 2 again" }, "719B": { "unit": "game/comcenScreens6F00", "line": "radius 1 = the 3x3 centre dot" }, "719D": { "unit": "game/comcenScreens6F00", "line": "complete the disc" }, "71A0": { "unit": "game/comcenScreens6F00", "line": "bit 2 = sprite 2" }, "71A2": { "unit": "game/comcenScreens6F00", "line": "switch it on (unless sprites are suppressed by $922A bit 6)" }, "71A5": { "unit": "game/comcenScreens6F00", "line": "colour 1 = white" }, "71A7": { "unit": "game/comcenScreens6F00", "line": "sprite 2 colour shadow ($900A -> $D029)" }, "71AA": { "unit": "game/comcenScreens6F00", "line": "hold the white disc for 3 frames..." }, "71AC": { "unit": "game/comcenScreens6F00", "line": "...while the battle keeps updating" }, "71AF": { "unit": "game/comcenScreens6F00", "line": "sprite plot mode 0 = clear pixels (erase)" }, "71B1": { "unit": "game/comcenScreens6F00", "line": "spritePlotMode" }, "71B4": { "unit": "game/comcenScreens6F00", "line": "sprite 2" }, "71B6": { "unit": "game/comcenScreens6F00", "line": "radius 3" }, "71B8": { "unit": "game/comcenScreens6F00", "line": "erase the outer ring - the disc shrinks" }, "71BB": { "unit": "game/comcenScreens6F00", "line": "colour $0F = light grey" }, "71BD": { "unit": "game/comcenScreens6F00", "line": "fade step 1" }, "71C0": { "unit": "game/comcenScreens6F00", "line": "3 more frames" }, "71C2": { "unit": "game/comcenScreens6F00", "line": "run them" }, "71C5": { "unit": "game/comcenScreens6F00", "line": "sprite 2" }, "71C7": { "unit": "game/comcenScreens6F00", "line": "radius 2" }, "71C9": { "unit": "game/comcenScreens6F00", "line": "erase the next ring" }, "71CC": { "unit": "game/comcenScreens6F00", "line": "colour $0C = medium grey" }, "71CE": { "unit": "game/comcenScreens6F00", "line": "fade step 2" }, "71D1": { "unit": "game/comcenScreens6F00", "line": "5 frames" }, "71D3": { "unit": "game/comcenScreens6F00", "line": "run them" }, "71D6": { "unit": "game/comcenScreens6F00", "line": "sprite 2" }, "71D8": { "unit": "game/comcenScreens6F00", "line": "radius 1" }, "71DA": { "unit": "game/comcenScreens6F00", "line": "erase the last dot - the sprite is now empty" }, "71DD": { "unit": "game/comcenScreens6F00", "line": "colour $0B = dark grey" }, "71DF": { "unit": "game/comcenScreens6F00", "line": "fade step 3" }, "71E2": { "unit": "game/comcenScreens6F00", "line": "6 frames" }, "71E4": { "unit": "game/comcenScreens6F00", "line": "run them" }, "71E7": { "unit": "game/comcenScreens6F00", "line": "sprite enable shadow" }, "71EA": { "unit": "game/comcenScreens6F00", "line": "clear bit 2 = sprite 2 off" }, "71EC": { "unit": "game/comcenScreens6F00", "line": "store it back" }, "71EF": { "unit": "game/comcenScreens6F00", "line": "restore normal colour handling..." }, "71F1": { "unit": "game/comcenScreens6F00", "line": "...fixed-colour flag off..." }, "71F4": { "unit": "game/comcenScreens6F00", "line": "...and fixed colour 0" }, "71F7": { "unit": "game/comcenScreens6F00", "line": "the drone is gone, so the tank reads empty" }, "71F9": { "unit": "game/comcenScreens6F00", "line": "droneFuel ($9220) = 0" }, "71FC": { "unit": "game/comcenScreens6F00", "line": "redraw '000' in the critical colour" }, "71FF": { "unit": "game/comcenScreens6F00", "line": "30 frames = about half a second" }, "7201": { "unit": "game/comcenScreens6F00", "line": "wait them out and return from runGameFrames" }, "7204": { "unit": "game/comcenScreens6F00", "routine": [ "flashRadarAndWipe - Paints the whole 14x12 drone camera window white for two game frames, then clears radarWipeColour and falls into drawRadarIrisWipe, so the iris closes over the white flash with no pauses.", "In: nothing", "Out: camera window colour 1; radarWipeColour ($7134) = 0; then see drawRadarIrisWipe", "Called from: playDroneLostAnimation ($717F) only" ], "line": "fill origin row 6 = top of the camera window" }, "7206": { "unit": "game/comcenScreens6F00", "line": "D_2A2D = window row" }, "7209": { "unit": "game/comcenScreens6F00", "line": "fill origin column 13 = left edge of the camera window" }, "720B": { "unit": "game/comcenScreens6F00", "line": "D_2A2E = window column" }, "720E": { "unit": "game/comcenScreens6F00", "line": "14 columns" }, "7210": { "unit": "game/comcenScreens6F00", "line": "12 rows" }, "7212": { "unit": "game/comcenScreens6F00", "line": "colour byte $01: %01 pixels black, %10 pixels white - a bright flash" }, "7214": { "unit": "game/comcenScreens6F00", "line": "paint it" }, "7217": { "unit": "game/comcenScreens6F00", "line": "hold for 2 frames" }, "7219": { "unit": "game/comcenScreens6F00", "line": "while the battle keeps running" }, "721C": { "unit": "game/comcenScreens6F00", "line": "0 = close the iris with no pauses" }, "721E": { "unit": "game/comcenScreens6F00", "line": "radarWipeColour; falls straight into drawRadarIrisWipe" }, "7221": { "unit": "game/comcenScreens6F00", "routine": [ "drawRadarIrisWipe - Closes (or opens) an iris over the drone camera window: it first draws window $16 (the camera area itself, left 13, top 6, 14x12) and then repeatedly draws a rectangular frame out of the all-$03 solid tile set at $9848, starting 12x12 cells at row 6 column 14 and shrinking two cells and moving in one cell each pass until the height drops below 3. The centre is finished off with a 2x2 block of character $05 at row 11, column 19.", "Each pass waits for raster line $B0 so the frame appears in one go, and when radarWipeColour is non-zero it also runs 3 game frames per pass, turning the wipe into a visible animation.", "In: radarWipeColour ($7134); the current fixed colour in $2A29/$2A2A ($AA light red after a launch, 0 during the loss animation)", "Out: the camera area is covered by concentric frames; D_2A2D = 11, D_2A2E = 19; frameWidth/frameHeight ($9221/$9222) clobbered", "Called from: flashRadarAndWipe ($721E, fall-through) and launchDrone ($8121, as the iris-open effect)" ], "line": "window $16 = left 13, top 6, 14x12 - the camera area drawn as a plain frame" }, "7223": { "unit": "game/comcenScreens6F00", "line": "draw it" }, "7226": { "unit": "game/comcenScreens6F00", "line": "the first iris ring is 12x12 cells" }, "7228": { "unit": "game/comcenScreens6F00", "line": "frameWidth ($9221)" }, "722B": { "unit": "game/comcenScreens6F00", "line": "frameHeight ($9222)" }, "722E": { "unit": "game/comcenScreens6F00", "line": "first ring's top row 6" }, "7230": { "unit": "game/comcenScreens6F00", "line": "D_2A2D = frame row" }, "7233": { "unit": "game/comcenScreens6F00", "line": "first ring's left column 14" }, "7235": { "unit": "game/comcenScreens6F00", "line": "D_2A2E = frame column" }, "7238": { "unit": "game/comcenScreens6F00", "block": [ "Iris loop: draw one concentric frame, then shrink it by two cells and move its origin in by one", "cell, so the ring closes in on the centre of the camera window. drawFrameBox itself decrements", "width and height once and this loop decrements them again, hence two cells per pass." ], "line": "current ring height" }, "723B": { "unit": "game/comcenScreens6F00", "line": "smaller than 3 cells?" }, "723D": { "unit": "game/comcenScreens6F00", "line": "yes - the iris is shut, go and plug the centre" }, "723F": { "unit": "game/comcenScreens6F00", "line": "poll the raster..." }, "7242": { "unit": "game/comcenScreens6F00", "line": "...for line $B0, below the picture, so the ring is drawn between frames" }, "7244": { "unit": "game/comcenScreens6F00", "line": "keep polling until it matches" }, "7246": { "unit": "game/comcenScreens6F00", "line": "low byte of the 9-byte frame tile set at $9848 (all nine tiles are character $03 = solid)" }, "7248": { "unit": "game/comcenScreens6F00", "line": "high byte -> $9848" }, "724A": { "unit": "game/comcenScreens6F00", "line": "draw the ring; this also decrements frameWidth/frameHeight by one" }, "724D": { "unit": "game/comcenScreens6F00", "line": "second decrement: the ring loses one cell on each side" }, "7250": { "unit": "game/comcenScreens6F00", "line": "same for the height" }, "7253": { "unit": "game/comcenScreens6F00", "line": "animated wipe?" }, "7256": { "unit": "game/comcenScreens6F00", "line": "no - draw the next ring immediately" }, "7258": { "unit": "game/comcenScreens6F00", "line": "3 game frames of pause..." }, "725A": { "unit": "game/comcenScreens6F00", "line": "...so the iris is visible as an animation" }, "725D": { "unit": "game/comcenScreens6F00", "line": "move the origin one row down..." }, "7260": { "unit": "game/comcenScreens6F00", "line": "...and one column right, keeping the ring centred" }, "7263": { "unit": "game/comcenScreens6F00", "line": "always taken - next ring" }, "7265": { "unit": "game/comcenScreens6F00", "line": "centre column 19" }, "7267": { "unit": "game/comcenScreens6F00", "line": "D_2A2E; D_2A2D is already 11 after the last pass" }, "726A": { "unit": "game/comcenScreens6F00", "line": "low byte of the 2x2 block at $980A (header 2,2 then four copies of character $05)" }, "726C": { "unit": "game/comcenScreens6F00", "line": "high byte -> $980A" }, "726E": { "unit": "game/comcenScreens6F00", "line": "plug the 2x2 hole at rows 11-12, columns 19-20 and return from drawCharBlock" }, "7271": { "unit": "game/comcenScreens6F00", "line": "written by playDroneLostAnimation ($717C) and never read - a dead copy of droneHeading" }, "7272": { "unit": "game/comcenScreens6F00", "block": [ "Eight AND masks that clear a single bit: index n clears bit n.", "buildRadarNoiseMasks picks the index with a random number 0-7." ], "line": "$FE,$FD,$FB,$F7,$EF,$DF,$BF,$7F - clear bit 0..7 respectively" }, "727A": { "unit": "game/comcenScreens6F00", "routine": [ "buildRadarNoiseMasks - Fills the 16-byte table radarNoiseMasks ($9210-$921F) with $FF and then knocks four randomly chosen bits out of each byte. drawRadarGlyph ANDs the eight rows of a glyph with eight consecutive entries of this table (starting at a random offset 0-7, which is why the table is 16 and not 8 bytes long) to turn an unspotted enemy blip into a speckled 'ghost'.", "In: the game RNG state $57-$59", "Out: radarNoiseMasks ($9210-$921F); zp_1A = 0; Y = $FF; A/X clobbered", "Called from: drawDroneRadarFrame ($6F89), drawDroneRadarWindow ($742D), redrawEnemyUnitsOnRadar ($7926) and drawRadarMap ($7BA2) - i.e. the noise pattern is re-rolled on every radar redraw" ], "line": "16 masks, index 15 down to 0" }, "727C": { "unit": "game/comcenScreens6F00", "line": "start from 'all bits set' = no noise" }, "727E": { "unit": "game/comcenScreens6F00", "block": [ "Clear the table to $FF." ], "line": "radarNoiseMasks[Y] = $FF" }, "7281": { "unit": "game/comcenScreens6F00", "line": "next entry down" }, "7282": { "unit": "game/comcenScreens6F00", "line": "until index 0 has been written" }, "7284": { "unit": "game/comcenScreens6F00", "line": "second pass, again from index 15" }, "7286": { "unit": "game/comcenScreens6F00", "block": [ "For every mask byte, punch out four random bits (they may collide, so between one and four", "bits actually end up clear)." ], "line": "four bits to clear per mask byte" }, "7288": { "unit": "game/comcenScreens6F00", "line": "zp_1A = per-byte bit counter" }, "728A": { "unit": "game/comcenScreens6F00", "line": "step the shared 24-bit game RNG (both machines run the same sequence)" }, "728D": { "unit": "game/comcenScreens6F00", "line": "keep a bit number 0-7" }, "728F": { "unit": "game/comcenScreens6F00", "line": "use it as the index into clearBitMaskTable" }, "7290": { "unit": "game/comcenScreens6F00", "line": "AND mask that clears just that bit" }, "7293": { "unit": "game/comcenScreens6F00", "line": "combine with the mask built so far" }, "7296": { "unit": "game/comcenScreens6F00", "line": "store it back" }, "7299": { "unit": "game/comcenScreens6F00", "line": "one of the four bits done" }, "729B": { "unit": "game/comcenScreens6F00", "line": "repeat until four have been cleared" }, "729D": { "unit": "game/comcenScreens6F00", "line": "next mask byte" }, "729E": { "unit": "game/comcenScreens6F00", "line": "until all 16 are done" }, "72A0": { "unit": "game/comcenScreens6F00", "line": "done" }, "72A1": { "unit": "game/comcenScreens6F00", "routine": [ "applyDroneBlast - Resolves a drone detonation: damages every unit standing in the 2x2 block of map cells whose top-left corner is (cmdParam1, cmdParam2) - (x,y), (x+1,y), (x+1,y+1) and (x,y+1) - by calling applyDroneBlastToCell four times.", "The blast strength arrives in A and is written into the LDA # operand at $7310+1, so each cell's damage call ends with 'LDA #strength / JSR applyHitToUnit'.", "In: A = blast strength (cmdDroneDetonate at $536C passes $19 = 25), cmdParam1/cmdParam2 (zp_74/zp_75) = the top-left map cell of the blast", "Out: up to four units damaged and stunned; the operand at $7311 is patched; cmdParam1 is restored to x but cmdParam2 is left at y+1, which is what the caller then uses to place the explosion marker sprite", "Called from: cmdDroneDetonate in the main program ($536C) only" ], "line": "self-modifying code: store the blast strength into the operand byte of the 'lda #$FF' at $7310" }, "72A4": { "unit": "game/comcenScreens6F00", "line": "cell (x, y) - the top-left of the 2x2 blast" }, "72A7": { "unit": "game/comcenScreens6F00", "line": "step to column x+1" }, "72A9": { "unit": "game/comcenScreens6F00", "line": "cell (x+1, y)" }, "72AC": { "unit": "game/comcenScreens6F00", "line": "step to row y+1" }, "72AE": { "unit": "game/comcenScreens6F00", "line": "cell (x+1, y+1)" }, "72B1": { "unit": "game/comcenScreens6F00", "line": "back to column x; falls straight into the fourth call for cell (x, y+1)" }, "72B3": { "unit": "game/comcenScreens6F00", "routine": [ "applyDroneBlastToCell - Applies the drone blast to the single map cell (cmdParam1, cmdParam2). It returns at once if the cell is outside the 40x40 map or holds no unit. Otherwise, if the blast strength is at least 15 and the game type is not THE BOMB (type 2), the unit's stun counter is set to 15 and haltStunnedUnit stops it where it stands.", "If the unit is the player's own comcen, the cloak lock is refreshed and - with the DAMAGE option on ($0BA3 bit 4) and not in a solo/film game - all three comcen systems are marked damaged and comcenStunStatus is set to $FF, which triggers the knock-out cut-scene at $0709. Without DAMAGE the 'COMCEN STUNNED!' message (id $0C) is queued instead. Finally the unit takes the blast damage.", "In: cmdParam1/cmdParam2 = map cell, blast strength in the operand at $7311, gameTypeOptions ($0BA3), filmPlaybackMode ($0B9B), comcenUnit ($9236)", "Out: unit stun/halt, possibly the comcen knock-out flags, and applyHitToUnit with A = strength, Y = the unit index", "Called from: applyDroneBlast ($72A4/$72A9/$72AE plus the fall-through at $72B1)", "Note: the labels L_72B1, L_72D3, L_72D5, L_72E1, L_72E5, L_72F2, L_72F5, sub_72F6 and L_730D are XREF artefacts of overlay variant A sharing these addresses; only sub_72F6 ($72F6) is also a real branch target here." ], "line": "map column of the cell" }, "72B5": { "unit": "game/comcenScreens6F00", "line": "the map is 40 cells wide" }, "72B7": { "unit": "game/comcenScreens6F00", "line": "off the map - nothing to damage" }, "72B9": { "unit": "game/comcenScreens6F00", "line": "map row of the cell" }, "72BB": { "unit": "game/comcenScreens6F00", "line": "the map is 40 cells high" }, "72BD": { "unit": "game/comcenScreens6F00", "line": "off the map - nothing to damage" }, "72BF": { "unit": "game/comcenScreens6F00", "line": "read map[$F000 + row*40 + col]" }, "72C2": { "unit": "game/comcenScreens6F00", "line": "bit 7 clear = terrain only, no unit standing here" }, "72C4": { "unit": "game/comcenScreens6F00", "line": "strip the 'unit here' bit..." }, "72C6": { "unit": "game/comcenScreens6F00", "line": "...leaving the unit index 0-99 in Y" }, "72C7": { "unit": "game/comcenScreens6F00", "line": "the blast strength patched in by applyDroneBlast" }, "72CA": { "unit": "game/comcenScreens6F00", "line": "weaker than 15?" }, "72CC": { "unit": "game/comcenScreens6F00", "line": "yes - just apply damage, no stun" }, "72CE": { "unit": "game/comcenScreens6F00", "line": "game options byte" }, "72D1": { "unit": "game/comcenScreens6F00", "line": "bits 0-2 = game type" }, "72D3": { "unit": "game/comcenScreens6F00", "line": "type 2 = THE BOMB" }, "72D5": { "unit": "game/comcenScreens6F00", "line": "in THE BOMB nothing gets stunned - just apply damage" }, "72D7": { "unit": "game/comcenScreens6F00", "line": "the unit's stun / dug-in counter" }, "72DA": { "unit": "game/comcenScreens6F00", "line": "set the low nibble to 15 = fully stunned" }, "72DC": { "unit": "game/comcenScreens6F00", "line": "store it back" }, "72DF": { "unit": "game/comcenScreens6F00", "line": "cancel the unit's orders so it stops where it is" }, "72E2": { "unit": "game/comcenScreens6F00", "line": "is this the local player's own comcen?" }, "72E5": { "unit": "game/comcenScreens6F00", "line": "no - just apply damage" }, "72E7": { "unit": "game/comcenScreens6F00", "line": "refresh comcenCloakedFlag ($9245) from the comcen's cloak bit" }, "72EA": { "unit": "game/comcenScreens6F00", "line": "game options byte" }, "72ED": { "unit": "game/comcenScreens6F00", "line": "bit 4 = the DAMAGE option" }, "72EF": { "unit": "game/comcenScreens6F00", "line": "DAMAGE off - only announce the stun" }, "72F1": { "unit": "game/comcenScreens6F00", "line": "solo trainer / film playback flag" }, "72F4": { "unit": "game/comcenScreens6F00", "line": "bit 7 clear = real linked game, so knock the comcen out" }, "72F6": { "unit": "game/comcenScreens6F00", "block": [ "Soft outcome: announce the stun on the status line and skip the knock-out." ], "line": "message id $0C = 'COMCEN STUNNED!'" }, "72F8": { "unit": "game/comcenScreens6F00", "line": "queue it in the $C000 overlay's sorted message ring" }, "72FB": { "unit": "game/comcenScreens6F00", "line": "reload the unit index for applyHitToUnit" }, "72FE": { "unit": "game/comcenScreens6F00", "line": "always taken: comcenUnit is 49 or 99, never 0 - so the knock-out block below is skipped" }, "7300": { "unit": "game/comcenScreens6F00", "block": [ "Hard outcome: the comcen is knocked out. All three of its subsystems are marked damaged and", "comcenStunStatus is set, which the main loop turns into the black-out cut-scene at $0709." ], "line": "$80 = system damaged" }, "7302": { "unit": "game/comcenScreens6F00", "line": "comcenSystemStatus[1]: the overview map drawing" }, "7305": { "unit": "game/comcenScreens6F00", "line": "comcenSystemStatus[2]: screen 1, the radar/missile scanner" }, "7308": { "unit": "game/comcenScreens6F00", "line": "comcenSystemStatus[3]: the drone system" }, "730B": { "unit": "game/comcenScreens6F00", "line": "$FF = comcen stunned" }, "730D": { "unit": "game/comcenScreens6F00", "line": "comcenStunStatus ($922A); the knock-out sequence polls this" }, "7310": { "unit": "game/comcenScreens6F00", "line": "operand $7311 is patched by applyDroneBlast with the blast strength (25 for a drone)" }, "7312": { "unit": "game/comcenScreens6F00", "line": "apply the damage to unit Y (halved and score-adjusted inside applyHitToUnit)" }, "7315": { "unit": "game/comcenScreens6F00", "line": "done" }, "7316": { "unit": "game/comcenScreens6F00", "block": [ "Maps a clockwise compass heading 0-7 (0 N, 1 NE, 2 E, 3 SE, 4 S, 5 SW, 6 W, 7 NW) to the", "engine's direction code 0-7 (0 N, 1 S, 2 E, 3 W, 4 NW, 5 NE, 6 SE, 7 SW), which is what", "directionDeltaTable ($20F0) and diagonalDirectionTable ($1FB2) are indexed with.", "joyDirToHeadingTable ($7FCE) is the inverse mapping." ], "line": "headings N,NE,E,SE -> direction codes 0,5,2,6" }, "731A": { "unit": "game/comcenScreens6F00", "line": "headings S,SW,W,NW -> direction codes 1,7,3,4" }, "731E": { "unit": "game/comcenScreens6F00", "routine": [ "steerDrone - Advances the locally flown drone by one map cell. Called once per command exchange from sendOutgoingPacket ($5639) while droneControlFlags ($920D) bit 6 says the drone is under local control, just before the $8D heading,col,row report is queued.", "It turns droneHeading ($920B) at most one 45-degree step towards the heading the joystick is asking for, taking the shorter way round and playing sound $10 on each turn, then converts the heading to a direction code and adds that direction's dx/dy to droneViewOriginCol/Row ($92F6/$92F7).", "In: droneJoyDirection (zp_5E) = direction code of the last joystick reading, droneHeading ($920B), droneViewOriginCol/Row ($92F6/$92F7)", "Out: droneHeading turned by at most one step and kept in 0-7; the drone's map position advanced by one cell; sound $10 when it turned; A/X/Y clobbered", "Called from: sendOutgoingPacket ($5639) in the main program" ], "line": "the direction code the joystick last produced (0 N, 1 S, 2 E, 3 W, 4 NW, 5 NE, 6 SE, 7 SW)" }, "7320": { "unit": "game/comcenScreens6F00", "line": "convert it to a clockwise heading 0-7 through joyDirToHeadingTable ($7FCE)" }, "7323": { "unit": "game/comcenScreens6F00", "line": "prepare the subtraction" }, "7324": { "unit": "game/comcenScreens6F00", "line": "how far is that from the heading we are flying?" }, "7327": { "unit": "game/comcenScreens6F00", "line": "already on heading - no turn" }, "7329": { "unit": "game/comcenScreens6F00", "line": "wanted heading is numerically smaller - handle the negative case" }, "732B": { "unit": "game/comcenScreens6F00", "line": "assume a turn of -1 (anticlockwise)" }, "732D": { "unit": "game/comcenScreens6F00", "line": "is the difference 4 or more?" }, "732F": { "unit": "game/comcenScreens6F00", "line": "yes - going anticlockwise is the short way round" }, "7331": { "unit": "game/comcenScreens6F00", "line": "difference 1-3: turn +1, clockwise, is shorter" }, "7333": { "unit": "game/comcenScreens6F00", "line": "always taken" }, "7335": { "unit": "game/comcenScreens6F00", "line": "negative difference: assume +1 (clockwise)" }, "7337": { "unit": "game/comcenScreens6F00", "line": "difference of -4..-1 (i.e. $FC..$FF)?" }, "7339": { "unit": "game/comcenScreens6F00", "line": "no - the gap is bigger than 4, so clockwise is shorter" }, "733B": { "unit": "game/comcenScreens6F00", "line": "-1..-4: turn anticlockwise" }, "733D": { "unit": "game/comcenScreens6F00", "line": "the turn step (+1 or -1) into A" }, "733E": { "unit": "game/comcenScreens6F00", "line": "prepare the addition" }, "733F": { "unit": "game/comcenScreens6F00", "line": "apply it to the current heading" }, "7342": { "unit": "game/comcenScreens6F00", "line": "wrap into the range 0-7" }, "7344": { "unit": "game/comcenScreens6F00", "line": "the drone has swung 45 degrees" }, "7347": { "unit": "game/comcenScreens6F00", "line": "sound effect $10 = the turn" }, "7349": { "unit": "game/comcenScreens6F00", "line": "play it" }, "734C": { "unit": "game/comcenScreens6F00", "block": [ "Translate the (possibly just updated) heading into a map step and move the drone." ], "line": "current heading 0-7" }, "734F": { "unit": "game/comcenScreens6F00", "line": "-> direction code 0-7" }, "7352": { "unit": "game/comcenScreens6F00", "line": "Y will hold the row delta, default 0" }, "7354": { "unit": "game/comcenScreens6F00", "line": "X will hold the column delta, default 0" }, "7356": { "unit": "game/comcenScreens6F00", "line": "codes 4-7 are the diagonals" }, "7358": { "unit": "game/comcenScreens6F00", "line": "handle a diagonal" }, "735A": { "unit": "game/comcenScreens6F00", "line": "codes 2-3 are east/west" }, "735C": { "unit": "game/comcenScreens6F00", "line": "handle a pure column move" }, "735E": { "unit": "game/comcenScreens6F00", "line": "codes 0-1 (N/S): index directionDeltaTable with the code" }, "735F": { "unit": "game/comcenScreens6F00", "line": "$20F0[0] = -1 for north, [1] = +1 for south" }, "7362": { "unit": "game/comcenScreens6F00", "line": "that is the row delta" }, "7363": { "unit": "game/comcenScreens6F00", "line": "go and apply the step" }, "7366": { "unit": "game/comcenScreens6F00", "line": "codes 2-3 (E/W): index directionDeltaTable with the code" }, "7367": { "unit": "game/comcenScreens6F00", "line": "$20F0[2] = +1 for east, [3] = -1 for west" }, "736A": { "unit": "game/comcenScreens6F00", "line": "that is the column delta" }, "736B": { "unit": "game/comcenScreens6F00", "line": "go and apply the step" }, "736E": { "unit": "game/comcenScreens6F00", "line": "codes 4-7 (NW/NE/SE/SW): use the packed table" }, "736F": { "unit": "game/comcenScreens6F00", "line": "$1FB2[4..7] = $30,$20,$21,$31 - high nibble = column index, low nibble = row index" }, "7372": { "unit": "game/comcenScreens6F00", "line": "keep the packed byte" }, "7373": { "unit": "game/comcenScreens6F00", "line": "low nibble = index into directionDeltaTable for the row" }, "7375": { "unit": "game/comcenScreens6F00", "line": "into Y" }, "7376": { "unit": "game/comcenScreens6F00", "line": "fetch the row delta" }, "7379": { "unit": "game/comcenScreens6F00", "line": "Y = row delta" }, "737A": { "unit": "game/comcenScreens6F00", "line": "packed byte back" }, "737B": { "unit": "game/comcenScreens6F00", "line": "shift the high nibble down, 1 of 4" }, "737C": { "unit": "game/comcenScreens6F00", "line": "2 of 4" }, "737D": { "unit": "game/comcenScreens6F00", "line": "3 of 4" }, "737E": { "unit": "game/comcenScreens6F00", "line": "4 of 4 - now the column index" }, "737F": { "unit": "game/comcenScreens6F00", "line": "into X" }, "7380": { "unit": "game/comcenScreens6F00", "line": "fetch the column delta" }, "7383": { "unit": "game/comcenScreens6F00", "line": "X = column delta" }, "7384": { "unit": "game/comcenScreens6F00", "line": "column delta into A" }, "7385": { "unit": "game/comcenScreens6F00", "line": "prepare the addition" }, "7386": { "unit": "game/comcenScreens6F00", "line": "the drone's current map column ($92F6, the camera window's centre)" }, "7389": { "unit": "game/comcenScreens6F00", "line": "move it one cell" }, "738C": { "unit": "game/comcenScreens6F00", "line": "row delta into A" }, "738D": { "unit": "game/comcenScreens6F00", "line": "prepare the addition" }, "738E": { "unit": "game/comcenScreens6F00", "line": "the drone's current map row ($92F7)" }, "7391": { "unit": "game/comcenScreens6F00", "line": "move it one cell" }, "7394": { "unit": "game/comcenScreens6F00", "line": "done - the caller now queues the $8D heading,col,row report" }, "7395": { "unit": "game/comcenScreens6F00", "line": "scratch byte holding drawRadarGlyph's entry Y (the colour-cell offset), restored on exit" }, "7396": { "unit": "game/comcenScreens6F00", "routine": [ "drawRadarGlyph - Plots one 8x8 map glyph into the bitmap cell pointed at by bitmapPtr (zp_B4/zp_B5) and writes its colour through screenPtr (zp_B6/zp_B7) at offset Y. The glyph source is the 8-bytes-per-tile set at $9C6E, selected by setTerrainTilePtr from A & $7F.", "Two effects can be applied: if radarHalfToneFlag ($922D) is set (a cloaked unit) the even bitmap rows are blanked and only the odd rows copied, so the unit shows up as a half-tone; if bit 7 of A is set (a noise 'ghost') every row is ANDed with eight consecutive entries of radarNoiseMasks starting at a random offset 0-7.", "The colour byte in tileColour (zp_32) is written raw on screen 1 - where the caller has biased screenPtr into colour RAM at $D800 - and as (tileColour << 4) | cellBackgroundColour on screen 2, where screenPtr points into screen RAM at $8C00 and supplies both multicolour nibbles.", "In: A = glyph index (bit 7 = draw with noise), Y = colour-cell offset, X free, tileColour (zp_32), bitmapPtr, screenPtr, radarHalfToneFlag ($922D), currentScreen ($90FB), cellBackgroundColour ($9226), radarNoiseMasks ($9210)", "Out: 8 bitmap bytes and 1 colour byte written; bitmapPtr advanced 8 bytes to the next cell to the right; radarHalfToneFlag cleared; A = glyph & $7F, X and Y restored via self-modified operands; radarGlyphSavedY = entry Y", "Called from: drawDroneRadarWindow ($7474), drawRadarMap ($7C0E) and the main program's drawScreen1Cell ($5DF5)", "Dead code: the 'lda textDrawParams / beq' test at $73F9 can never take the non-zero path, because setTerrainTilePtr at $73A4 always clears textDrawParams first - so the forced colour 8 at $73FE is unreachable." ], "line": "self-modifying: save the raw glyph byte (bit 7 = noise flag) into the 'lda #' operand at $73B7" }, "7399": { "unit": "game/comcenScreens6F00", "line": "strip the noise flag" }, "739B": { "unit": "game/comcenScreens6F00", "line": "save the plain glyph index into the 'lda #' operand at $7415 so it can be returned in A" }, "739E": { "unit": "game/comcenScreens6F00", "line": "save the caller's Y (the colour-cell offset within the row)" }, "73A1": { "unit": "game/comcenScreens6F00", "line": "save the caller's X into the 'ldx #' operand at $741A" }, "73A4": { "unit": "game/comcenScreens6F00", "line": "glyphPtr (zp_B2/B3) = $9C6E + glyph*8; also clears textDrawParams" }, "73A7": { "unit": "game/comcenScreens6F00", "line": "half-tone flag, set by getRadarCellGlyph for a cloaked unit" }, "73AA": { "unit": "game/comcenScreens6F00", "line": "not cloaked - leave all eight rows to the copy loop" }, "73AC": { "unit": "game/comcenScreens6F00", "block": [ "Cloaked unit: blank the four even bitmap rows first; the copy loop below will then only", "write the odd rows, so the unit appears on alternate scanlines." ], "line": "start at bitmap row 6" }, "73AE": { "unit": "game/comcenScreens6F00", "line": "blank byte" }, "73B0": { "unit": "game/comcenScreens6F00", "line": "clear this row of the cell" }, "73B2": { "unit": "game/comcenScreens6F00", "line": "step two rows..." }, "73B3": { "unit": "game/comcenScreens6F00", "line": "...i.e. rows 6, 4, 2, 0" }, "73B4": { "unit": "game/comcenScreens6F00", "line": "until row 0 has been cleared" }, "73B6": { "unit": "game/comcenScreens6F00", "line": "operand patched at $7396 with the glyph byte including its bit 7" }, "73B8": { "unit": "game/comcenScreens6F00", "line": "bit 7 set = draw this blip as noise" }, "73BA": { "unit": "game/comcenScreens6F00", "block": [ "Plain copy of the glyph into the bitmap cell, bottom row upwards.", "When the half-tone flag is set the loop steps two rows at a time (odd rows only)." ], "line": "bitmap rows 7 down to 0" }, "73BC": { "unit": "game/comcenScreens6F00", "line": "glyph row from the $9C6E tile set" }, "73BE": { "unit": "game/comcenScreens6F00", "line": "into the bitmap cell" }, "73C0": { "unit": "game/comcenScreens6F00", "line": "cloaked?" }, "73C3": { "unit": "game/comcenScreens6F00", "line": "no - step one row" }, "73C5": { "unit": "game/comcenScreens6F00", "line": "cloaked: skip a row so only odd rows are written" }, "73C6": { "unit": "game/comcenScreens6F00", "line": "next row up" }, "73C7": { "unit": "game/comcenScreens6F00", "line": "until row 0 is done" }, "73C9": { "unit": "game/comcenScreens6F00", "line": "always taken - go to the colour write" }, "73CB": { "unit": "game/comcenScreens6F00", "block": [ "Noise variant: the glyph is ANDed row by row with eight consecutive noise masks, starting at a", "random offset 0-7 within the 16-byte table. That is why the table holds 16 masks: the walk of", "eight never runs off the end." ], "line": "random number from the shared game RNG" }, "73CE": { "unit": "game/comcenScreens6F00", "line": "start offset 0-7 into radarNoiseMasks" }, "73D0": { "unit": "game/comcenScreens6F00", "line": "X = mask index" }, "73D1": { "unit": "game/comcenScreens6F00", "line": "bitmap rows 7 down to 0" }, "73D3": { "unit": "game/comcenScreens6F00", "line": "glyph row" }, "73D5": { "unit": "game/comcenScreens6F00", "line": "knock out four random bits of it" }, "73D8": { "unit": "game/comcenScreens6F00", "line": "store the speckled row" }, "73DA": { "unit": "game/comcenScreens6F00", "line": "next mask for the next row" }, "73DB": { "unit": "game/comcenScreens6F00", "line": "cloaked as well?" }, "73DE": { "unit": "game/comcenScreens6F00", "line": "no - step one row" }, "73E0": { "unit": "game/comcenScreens6F00", "line": "cloaked: skip a row" }, "73E1": { "unit": "game/comcenScreens6F00", "line": "next row up" }, "73E2": { "unit": "game/comcenScreens6F00", "line": "until row 0 is done" }, "73E4": { "unit": "game/comcenScreens6F00", "block": [ "Common tail: clear the one-shot half-tone flag, step the bitmap pointer to the next cell", "and write the cell's colour." ], "line": "Y = 0 for the flag clear" }, "73E6": { "unit": "game/comcenScreens6F00", "line": "radarHalfToneFlag is per cell - clear it for the next one" }, "73E9": { "unit": "game/comcenScreens6F00", "line": "prepare the 16-bit add" }, "73EA": { "unit": "game/comcenScreens6F00", "line": "bitmap pointer low byte" }, "73EC": { "unit": "game/comcenScreens6F00", "line": "one character cell = 8 bytes to the right" }, "73EE": { "unit": "game/comcenScreens6F00", "line": "store it back (label sub_73EE is a variant-A entry point only)" }, "73F0": { "unit": "game/comcenScreens6F00", "line": "bitmap pointer high byte" }, "73F2": { "unit": "game/comcenScreens6F00", "line": "propagate the carry" }, "73F4": { "unit": "game/comcenScreens6F00", "line": "bitmapPtr now addresses the next cell of the row" }, "73F6": { "unit": "game/comcenScreens6F00", "line": "restore the colour-cell offset" }, "73F9": { "unit": "game/comcenScreens6F00", "line": "dead test: setTerrainTilePtr cleared textDrawParams at $73A4, so this is always 0" }, "73FC": { "unit": "game/comcenScreens6F00", "line": "always taken" }, "73FE": { "unit": "game/comcenScreens6F00", "line": "unreachable: forced colour 8" }, "7400": { "unit": "game/comcenScreens6F00", "line": "unreachable" }, "7402": { "unit": "game/comcenScreens6F00", "line": "the colour getRadarCellGlyph chose for this cell" }, "7404": { "unit": "game/comcenScreens6F00", "line": "which screen are we drawing?" }, "7407": { "unit": "game/comcenScreens6F00", "line": "screen 1 = the RADAR / MISSILE screen" }, "7409": { "unit": "game/comcenScreens6F00", "line": "yes - screenPtr already points into colour RAM, store the raw nibble" }, "740B": { "unit": "game/comcenScreens6F00", "line": "screen 2: move the colour into the high nibble, shift 1..." }, "740C": { "unit": "game/comcenScreens6F00", "line": "...2..." }, "740D": { "unit": "game/comcenScreens6F00", "line": "...3..." }, "740E": { "unit": "game/comcenScreens6F00", "line": "...4 - it is now the %01 pixel colour" }, "740F": { "unit": "game/comcenScreens6F00", "line": "the %10 pixel colour comes from cellBackgroundColour ($0A on the drone screen)" }, "7412": { "unit": "game/comcenScreens6F00", "line": "write the cell's colour byte" }, "7414": { "unit": "game/comcenScreens6F00", "line": "operand patched at $739B - return the glyph index in A" }, "7416": { "unit": "game/comcenScreens6F00", "line": "restore the caller's Y" }, "7419": { "unit": "game/comcenScreens6F00", "line": "operand patched at $73A1 - restore the caller's X" }, "741B": { "unit": "game/comcenScreens6F00", "line": "done" }, "741C": { "unit": "game/comcenScreens6F00", "routine": [ "drawDroneRadarWindow - Redraws the whole 14x12 drone camera window (character rows 6-17, columns 13-26, one character per map cell) from the map around the view origin zp_A5/zp_A6. It sets the three radar colours, re-rolls the noise masks, walks the map row by row and calls getRadarCellGlyph followed by drawRadarGlyph for every cell.", "The bitmap pointer is built from the $9300 address tables biased to row 6 / column 13 (D_9306/D_931F and D_933F/D_9367) and the screen RAM pointer from the screen row table biased to row 6 (D_9388/D_93A1) plus column 13. It waits for raster line $90 before starting so the redraw is not torn.", "In: viewOriginCol/Row (zp_A5/zp_A6), the 40x40 map at $F000, the unit arrays, droneRadarOwnColour ($9224) and droneRadarEnemyColour ($9225)", "Out: the camera window redrawn; radarTerrainColour ($9239) = 8, radarOwnUnitColour ($9237) and radarEnemyUnitColour ($9238) set; noise masks re-rolled; drawCellSaveCol/Row ($90F6/$90F7) hold the saved view origin, which is restored on exit; zp_48/49, zp_B4-zp_B7 clobbered", "Called from: advanceDroneCamera ($8281), i.e. once per lock-step command exchange while the drone flies" ], "line": "terrain colour 8 = orange for the %01 pixels of every terrain cell" }, "741E": { "unit": "game/comcenScreens6F00", "line": "radarTerrainColour ($9239)" }, "7421": { "unit": "game/comcenScreens6F00", "line": "own-side unit colour for the drone camera ($0B dark grey, set by overlay A at $7904)" }, "7424": { "unit": "game/comcenScreens6F00", "line": "radarOwnUnitColour ($9237)" }, "7427": { "unit": "game/comcenScreens6F00", "line": "enemy unit colour for the drone camera ($09 brown, set by overlay A at $78FB)" }, "742A": { "unit": "game/comcenScreens6F00", "line": "radarEnemyUnitColour ($9238)" }, "742D": { "unit": "game/comcenScreens6F00", "line": "re-roll the noise masks so ghost blips shimmer between frames" }, "7430": { "unit": "game/comcenScreens6F00", "line": "zp_48/49 = map address of the cell at (zp_A5, zp_A6), handling negative origins" }, "7433": { "unit": "game/comcenScreens6F00", "line": "the view origin column..." }, "7435": { "unit": "game/comcenScreens6F00", "line": "...is saved so the per-cell walk can trample zp_A5" }, "7438": { "unit": "game/comcenScreens6F00", "line": "the view origin row..." }, "743A": { "unit": "game/comcenScreens6F00", "line": "...likewise" }, "743D": { "unit": "game/comcenScreens6F00", "line": "prepare the 16-bit add" }, "743E": { "unit": "game/comcenScreens6F00", "line": "bitmap row table entry for row 6 ($9300 + 6)" }, "7441": { "unit": "game/comcenScreens6F00", "line": "plus the column offset for column 13 ($9332 + 13 = col*8)" }, "7444": { "unit": "game/comcenScreens6F00", "line": "bitmapPtr low (label sub_7444 is a variant-A entry point only)" }, "7446": { "unit": "game/comcenScreens6F00", "line": "high byte of the row address" }, "7449": { "unit": "game/comcenScreens6F00", "line": "high byte of the column offset" }, "744C": { "unit": "game/comcenScreens6F00", "line": "bitmapPtr now addresses bitmap cell (6,13)" }, "744E": { "unit": "game/comcenScreens6F00", "line": "prepare the 16-bit add" }, "744F": { "unit": "game/comcenScreens6F00", "line": "screen RAM row table entry for row 6 ($9382 + 6, base $8C00)" }, "7452": { "unit": "game/comcenScreens6F00", "line": "plus column 13" }, "7454": { "unit": "game/comcenScreens6F00", "line": "screenPtr low" }, "7456": { "unit": "game/comcenScreens6F00", "line": "high byte of the screen row address" }, "7459": { "unit": "game/comcenScreens6F00", "line": "propagate the carry" }, "745B": { "unit": "game/comcenScreens6F00", "line": "screenPtr addresses screen RAM cell (6,13)" }, "745D": { "unit": "game/comcenScreens6F00", "block": [ "Wait until the raster is below the visible picture (line $90) so the whole window is", "redrawn between two displayed frames." ], "line": "read the raster line counter" }, "7460": { "unit": "game/comcenScreens6F00", "line": "line $90" }, "7462": { "unit": "game/comcenScreens6F00", "line": "keep polling" }, "7464": { "unit": "game/comcenScreens6F00", "line": "X = camera row 0" }, "7466": { "unit": "game/comcenScreens6F00", "block": [ "Outer loop over the 12 camera rows; inner loop over the 14 cells of a row. zp_A5/zp_A6 are", "walked cell by cell so getRadarCellGlyph can tell whether the cell is off the 40x40 map." ], "line": "Y = camera column 0" }, "7468": { "unit": "game/comcenScreens6F00", "line": "column index into A" }, "7469": { "unit": "game/comcenScreens6F00", "line": "prepare the add" }, "746A": { "unit": "game/comcenScreens6F00", "line": "plus the saved origin column" }, "746D": { "unit": "game/comcenScreens6F00", "line": "zp_A5 = map column of this cell" }, "746F": { "unit": "game/comcenScreens6F00", "line": "the map byte for this cell" }, "7471": { "unit": "game/comcenScreens6F00", "line": "classify it into a glyph index (A) and a colour (zp_32)" }, "7474": { "unit": "game/comcenScreens6F00", "line": "plot it; this also advances bitmapPtr to the next cell" }, "7477": { "unit": "game/comcenScreens6F00", "line": "next camera column" }, "7478": { "unit": "game/comcenScreens6F00", "line": "and the matching map column" }, "747A": { "unit": "game/comcenScreens6F00", "line": "column counter into A" }, "747B": { "unit": "game/comcenScreens6F00", "line": "the window is 14 cells wide" }, "747D": { "unit": "game/comcenScreens6F00", "line": "more cells on this row" }, "747F": { "unit": "game/comcenScreens6F00", "line": "row finished - step the map row" }, "7481": { "unit": "game/comcenScreens6F00", "line": "map pointer low" }, "7483": { "unit": "game/comcenScreens6F00", "line": "prepare the add" }, "7484": { "unit": "game/comcenScreens6F00", "line": "one map row = 40 bytes" }, "7486": { "unit": "game/comcenScreens6F00", "line": "store it" }, "7488": { "unit": "game/comcenScreens6F00", "line": "map pointer high" }, "748A": { "unit": "game/comcenScreens6F00", "line": "propagate the carry" }, "748C": { "unit": "game/comcenScreens6F00", "line": "zp_48/49 now addresses the next map row" }, "748E": { "unit": "game/comcenScreens6F00", "line": "prepare the add" }, "748F": { "unit": "game/comcenScreens6F00", "line": "screen RAM pointer low" }, "7491": { "unit": "game/comcenScreens6F00", "line": "one screen row = 40 bytes" }, "7493": { "unit": "game/comcenScreens6F00", "line": "store it" }, "7495": { "unit": "game/comcenScreens6F00", "line": "screen RAM pointer high" }, "7497": { "unit": "game/comcenScreens6F00", "line": "propagate the carry" }, "7499": { "unit": "game/comcenScreens6F00", "line": "zp_B6/B7 now addresses the next screen row" }, "749B": { "unit": "game/comcenScreens6F00", "line": "next camera row" }, "749C": { "unit": "game/comcenScreens6F00", "line": "back to column 0 for the bitmap address" }, "749E": { "unit": "game/comcenScreens6F00", "line": "prepare the add" }, "749F": { "unit": "game/comcenScreens6F00", "line": "bitmap row address for row 6+X" }, "74A2": { "unit": "game/comcenScreens6F00", "line": "plus the column offset for column 13+0" }, "74A5": { "unit": "game/comcenScreens6F00", "line": "bitmapPtr low" }, "74A7": { "unit": "game/comcenScreens6F00", "line": "high byte of the row address" }, "74AA": { "unit": "game/comcenScreens6F00", "line": "high byte of the column offset" }, "74AD": { "unit": "game/comcenScreens6F00", "line": "bitmapPtr = first cell of the next camera row" }, "74AF": { "unit": "game/comcenScreens6F00", "line": "12 rows in the window" }, "74B1": { "unit": "game/comcenScreens6F00", "line": "more rows to draw" }, "74B3": { "unit": "game/comcenScreens6F00", "line": "already 0 - setTerrainTilePtr clears it on every glyph" }, "74B5": { "unit": "game/comcenScreens6F00", "line": "redundant clear of textDrawParams" }, "74B8": { "unit": "game/comcenScreens6F00", "line": "restore the view origin column..." }, "74BB": { "unit": "game/comcenScreens6F00", "line": "...into zp_A5" }, "74BD": { "unit": "game/comcenScreens6F00", "line": "restore the view origin row..." }, "74C0": { "unit": "game/comcenScreens6F00", "line": "...into zp_A6" }, "74C2": { "unit": "game/comcenScreens6F00", "line": "done" }, "74C3": { "unit": "game/comcenScreens6F00", "routine": [ "getRadarCellGlyph - Turns one map cell byte into the glyph index and colour that drawRadarGlyph needs. X and Y are preserved through self-modified operands, so it can be called from inside a rendering loop.", "Cells outside the 40x40 map become one of four hatch glyphs ($28-$2B, chosen by (row+column) & 3) in the terrain colour. Terrain cells become glyph (cell - $40) in radarTerrainColour ($9239). A cell holding a unit ($80 | index) becomes unitGlyphBaseTable[type] + facing: in radarOwnUnitColour ($9237) for the local player's units, and for the opponent's units in radarEnemyUnitColour ($9238) only while the unit is spotted (unitEnergyTable bit 7). An unspotted enemy normally shows the terrain saved under it, except that roughly every 1-8th one (countdown radarGhostCountdown $920F, reseeded from the RNG) is drawn as a speckled 'ghost' blip (glyph | $80) in the terrain colour. A dead unit (unitTypeTable bit 7) also shows the terrain hidden under it. A cloaked unit (unitPathColTable bit 7) sets radarHalfToneFlag so it is drawn on alternate scanlines.", "In: A = the map cell byte, zp_A5/zp_A6 = that cell's map coordinates, radarOwnUnitColour/radarEnemyUnitColour/radarTerrainColour, radarGhostCountdown, unit arrays $F708/$F76C/$F898/$F9C4/$FAF0, unitGlyphBaseTable ($0799)", "Out: A = glyph index (bit 7 set = draw with noise), tileColour (zp_32) = colour byte, radarHalfToneFlag ($922D) = $FF for a cloaked unit, radarGhostCountdown updated; X and Y restored", "Called from: drawDroneRadarWindow ($7471), drawRadarMap ($7C0B) and the main program's drawScreen1Cell ($5DF2)", "Self-modifying: $750A is NOT a constant BCS. loadOverlayB in the main program copies the side-dependent opcode from $206B into it right after loading this overlay ($10A5): $B0 (BCS) when the local player is side 0 so units 50-99 are the enemy, $90 (BCC) when the local player is side 1 so units 0-49 are. Treat $750A as a variable.", "Quirk: a dead unit's terrain is emitted with tileColour still set to radarOwnUnitColour (set at $74F6) rather than the terrain colour; on screen 1 both are $0B so it is invisible, on the drone camera it tints dead units' ground dark grey instead of orange. If the saved terrain byte happens to be 0 the 'bne' at $7503 falls through and the dead unit is drawn as a live GRUNT - terrain 0 does not occur on a real map ($40 is blank)." ], "line": "self-modifying: save the caller's X into the 'ldx #' operand at $754D" }, "74C6": { "unit": "game/comcenScreens6F00", "line": "and the caller's Y into the 'ldy #' operand at $754F" }, "74C9": { "unit": "game/comcenScreens6F00", "line": "keep the map cell byte in Y while the coordinates are range-checked" }, "74CA": { "unit": "game/comcenScreens6F00", "line": "this cell's map column" }, "74CC": { "unit": "game/comcenScreens6F00", "line": "the map is 40 columns wide" }, "74CE": { "unit": "game/comcenScreens6F00", "line": "off the map - draw hatching" }, "74D0": { "unit": "game/comcenScreens6F00", "line": "this cell's map row" }, "74D2": { "unit": "game/comcenScreens6F00", "line": "the map is 40 rows high" }, "74D4": { "unit": "game/comcenScreens6F00", "line": "on the map - use the real cell byte" }, "74D6": { "unit": "game/comcenScreens6F00", "block": [ "Off-map cell: pick one of the four hatch patterns so the border round the battlefield gets a", "woven look instead of a flat block." ], "line": "row..." }, "74D8": { "unit": "game/comcenScreens6F00", "line": "prepare the add" }, "74D9": { "unit": "game/comcenScreens6F00", "line": "...plus column" }, "74DB": { "unit": "game/comcenScreens6F00", "line": "pick one of four patterns" }, "74DD": { "unit": "game/comcenScreens6F00", "line": "prepare the add" }, "74DE": { "unit": "game/comcenScreens6F00", "line": "map codes $68-$6B are the four hatch tiles" }, "74E0": { "unit": "game/comcenScreens6F00", "line": "pretend the map held that code" }, "74E1": { "unit": "game/comcenScreens6F00", "block": [ "Default: the cell is plain terrain, drawn in the terrain colour." ], "line": "terrain colour ($9239): 8 on the drone camera, $0B on screen 1" }, "74E4": { "unit": "game/comcenScreens6F00", "line": "zp_32 is the colour drawRadarGlyph will write" }, "74E6": { "unit": "game/comcenScreens6F00", "line": "the cell byte back into A" }, "74E7": { "unit": "game/comcenScreens6F00", "line": "bit 7 set = a unit stands on this cell" }, "74E9": { "unit": "game/comcenScreens6F00", "line": "terrain codes start at $40..." }, "74EA": { "unit": "game/comcenScreens6F00", "line": "...so the glyph index in the $9C6E tile set is cell - $40" }, "74EC": { "unit": "game/comcenScreens6F00", "line": "normal terrain - return the glyph" }, "74EE": { "unit": "game/comcenScreens6F00", "line": "cell below $40 (should not happen): wrap to cell - $20" }, "74F0": { "unit": "game/comcenScreens6F00", "line": "return the glyph" }, "74F3": { "unit": "game/comcenScreens6F00", "block": [ "A unit stands here. Work out its glyph from type and facing, and its colour from the side,", "whether it is spotted, dead or cloaked." ], "line": "strip the 'unit here' bit..." }, "74F5": { "unit": "game/comcenScreens6F00", "line": "...leaving the unit index 0-99 in Y" }, "74F6": { "unit": "game/comcenScreens6F00", "line": "assume it is one of ours" }, "74F9": { "unit": "game/comcenScreens6F00", "line": "zp_32 = own unit colour" }, "74FB": { "unit": "game/comcenScreens6F00", "line": "the unit's type byte (bit 7 = destroyed)" }, "74FE": { "unit": "game/comcenScreens6F00", "line": "alive - carry on (label sub_74FE is a variant-A entry point only)" }, "7500": { "unit": "game/comcenScreens6F00", "line": "dead: show the terrain that was hidden under it" }, "7503": { "unit": "game/comcenScreens6F00", "line": "and render it as terrain (note: the colour is still the own-unit colour)" }, "7505": { "unit": "game/comcenScreens6F00", "line": "type 0 GRUNT, 1 RIDER, 2 BOOMER, 3 SPY, 4 COMCEN" }, "7507": { "unit": "game/comcenScreens6F00", "line": "X = unit type, the index into unitGlyphBaseTable" }, "7508": { "unit": "game/comcenScreens6F00", "line": "units 0-49 are side 0, 50-99 are side 1" }, "750A": { "unit": "game/comcenScreens6F00", "line": "SIDE-DEPENDENT OPCODE: patched by loadOverlayB ($10A5) from $206B - $B0 (BCS) for side 0, $90 (BCC) for side 1; taken when this unit belongs to the opponent" }, "750C": { "unit": "game/comcenScreens6F00", "line": "the unit's flags byte" }, "750F": { "unit": "game/comcenScreens6F00", "line": "bits 0-1 = facing" }, "7511": { "unit": "game/comcenScreens6F00", "line": "prepare the add" }, "7512": { "unit": "game/comcenScreens6F00", "line": "base glyph per type ($2C GRUNT, $30 RIDER, $34 BOOMER, $38 SPY, $3C COMCEN) plus the facing" }, "7515": { "unit": "game/comcenScreens6F00", "line": "go and check the cloak flag" }, "7518": { "unit": "game/comcenScreens6F00", "block": [ "The unit belongs to the opponent. It is only drawn if we can currently see it; otherwise the", "terrain under it is shown, with an occasional random 'ghost' blip to keep the radar noisy." ], "line": "enemy colour (1 = white on screen 1, so the sweep can find these cells; $09 brown on the camera)" }, "751B": { "unit": "game/comcenScreens6F00", "line": "zp_32 = enemy colour" }, "751D": { "unit": "game/comcenScreens6F00", "line": "the unit's energy byte; bit 7 = currently visible/spotted" }, "7520": { "unit": "game/comcenScreens6F00", "line": "spotted - draw it normally in the enemy colour" }, "7522": { "unit": "game/comcenScreens6F00", "line": "not spotted: fall back to the terrain hidden under it" }, "7525": { "unit": "game/comcenScreens6F00", "line": "count down towards the next ghost blip" }, "7528": { "unit": "game/comcenScreens6F00", "line": "not due yet - just show the terrain" }, "752A": { "unit": "game/comcenScreens6F00", "line": "due: reseed the countdown from the shared RNG..." }, "752D": { "unit": "game/comcenScreens6F00", "line": "...with 0-7, so about one unspotted enemy in five is ghosted" }, "752F": { "unit": "game/comcenScreens6F00", "line": "radarGhostCountdown ($920F)" }, "7532": { "unit": "game/comcenScreens6F00", "line": "the unit's flags byte" }, "7535": { "unit": "game/comcenScreens6F00", "line": "bits 0-1 = facing" }, "7537": { "unit": "game/comcenScreens6F00", "line": "prepare the add" }, "7538": { "unit": "game/comcenScreens6F00", "line": "the unit's real glyph" }, "753B": { "unit": "game/comcenScreens6F00", "line": "bit 7 = tell drawRadarGlyph to speckle it with the noise masks" }, "753D": { "unit": "game/comcenScreens6F00", "line": "and draw the ghost in the terrain colour, not the enemy colour" }, "7540": { "unit": "game/comcenScreens6F00", "line": "zp_32 = terrain colour" }, "7542": { "unit": "game/comcenScreens6F00", "block": [ "Cloak test, reached for every unit glyph: a cloaked unit is drawn on alternate scanlines only." ], "line": "the unit's waypoint-column byte, whose bit 7 is the CLOAK flag" }, "7545": { "unit": "game/comcenScreens6F00", "line": "not cloaked - done" }, "7547": { "unit": "game/comcenScreens6F00", "line": "$FF = half-tone" }, "7549": { "unit": "game/comcenScreens6F00", "line": "radarHalfToneFlag ($922D); drawRadarGlyph clears it again after the cell" }, "754C": { "unit": "game/comcenScreens6F00", "line": "operand patched at $74C3 - restore the caller's X" }, "754E": { "unit": "game/comcenScreens6F00", "line": "operand patched at $74C6 - restore the caller's Y" }, "7550": { "unit": "game/comcenScreens6F00", "line": "done; A = glyph index, zp_32 = colour" } }, "dataTypes": { "7134": [ "byte", 1 ], "715D": [ "byte", 6 ], "7271": [ "byte", 1 ], "7272": [ "byte", 8 ], "7316": [ "byte", 8 ], "7395": [ "byte", 1 ] }, "zpComments": { "32": "colour byte of the map tile / radar glyph being rendered: written by getRadarCellGlyph and consumed by drawRadarGlyph (raw colour-RAM nibble on screen 1, high nibble of the screen-RAM byte on the drone screen)", "5E": "direction code 0-7 of the last joystick steer on the drone screen; steerDrone maps it to a clockwise heading through joyDirToHeadingTable ($7FCE)", "A5": "map column of the left edge of the current cell window; on the drone screen it is the camera origin (comcen or drone position minus 6) and getRadarCellGlyph walks it cell by cell to test for off-map cells", "A6": "map row of the top edge of the current cell window; on the drone screen the camera origin (position minus 5), walked cell by cell by the radar renderers" } }