3472 lines
100 KiB
JSON
3472 lines
100 KiB
JSON
{
|
|
"chunk": "game_mainProgram0800_3023",
|
|
"unit": "game/mainProgram0800",
|
|
"unitLabels": {
|
|
"game/mainProgram0800": {
|
|
"3232": "spritePlotOperation",
|
|
"3238": "circlePointIndex",
|
|
"32DA": "circlePointX0",
|
|
"32DB": "circlePointX1",
|
|
"32DC": "circlePointX2",
|
|
"32DD": "circlePointX3",
|
|
"32DE": "circlePointX4",
|
|
"32DF": "circlePointX5",
|
|
"32E0": "circlePointX6",
|
|
"32E1": "circlePointX7",
|
|
"32E2": "circlePointY0",
|
|
"32E3": "circlePointY1",
|
|
"32E4": "circlePointY2",
|
|
"32E5": "circlePointY3",
|
|
"32E6": "circlePointY4",
|
|
"32E7": "circlePointY5",
|
|
"32E8": "circlePointY6",
|
|
"32E9": "circlePointY7",
|
|
"33C2": "explosionMarkerXOffset",
|
|
"33C4": "explosionMarkerYOffset",
|
|
"33C6": "explosionMarkerRingCount",
|
|
"33C8": "showExplosionMarker",
|
|
"3405": "startExplosionMarkerTimer",
|
|
"341F": "updateExplosionMarker",
|
|
"3424": "loadExplosionMarkerCol",
|
|
"3436": "loadExplosionMarkerRow",
|
|
"3458": "drawRingsInSprite4",
|
|
"34C6": "applyMoveOrder",
|
|
"34D5": "setUnitDestination",
|
|
"355D": "clampMapCoord"
|
|
}
|
|
},
|
|
"notes": {
|
|
"3023": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"mapCellToSpriteXY - Converts a battlefield cell (X = column 0-39, Y = row 0-39) into the sprite",
|
|
"coordinates that put a marker on that cell of the overview (mini) map in the left panel. While a",
|
|
"group formation box is being dragged (groupBoxActive $920A bit 7 set) the cell is first shifted by",
|
|
"the box's top-left offsets, so the formation ghost sprite is anchored at the corner of the box",
|
|
"instead of at the cursor cell, and the result is nudged one pixel right and down to line up with",
|
|
"the 4x4 pixel blocks the overview map is drawn with.",
|
|
"In: X = map column, Y = map row, groupBoxActive $920A, groupBoxLeftOffset $922F, groupBoxTopOffset $9231",
|
|
"Out: X = sprite X coordinate, Y = sprite Y coordinate; A clobbered",
|
|
"Called from: positionMarkerSprite ($2585), positionCursorSprite ($3055), the unit-follow code ($483F)"
|
|
],
|
|
"line": "$920A = $FF while a group formation box is being dragged around the map"
|
|
},
|
|
"3026": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "branch if no group box is active: convert the cell as it stands"
|
|
},
|
|
"3028": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "group box: start from the requested map column"
|
|
},
|
|
"3029": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry for the offset addition"
|
|
},
|
|
"302A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$922F = column offset of the box's left edge from the cursor cell (may be negative)"
|
|
},
|
|
"302D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X = column of the top-left cell of the box"
|
|
},
|
|
"302E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "same for the row"
|
|
},
|
|
"302F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry for the row offset addition"
|
|
},
|
|
"3030": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9231 = row offset of the box's top edge from the cursor cell"
|
|
},
|
|
"3033": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y = row of the top-left cell of the box"
|
|
},
|
|
"3034": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "convert that corner cell to overview-map sprite coordinates"
|
|
},
|
|
"3037": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "+1 pixel in X: the 4x4 cell blocks are drawn one pixel into their cell"
|
|
},
|
|
"3038": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "+1 pixel in Y, likewise"
|
|
},
|
|
"3039": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "return with the shifted sprite coordinates"
|
|
},
|
|
"303A": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"mapCellToSpriteXYRaw - The plain cell-to-sprite conversion for the overview map: spriteX =",
|
|
"column*4 + $1F, spriteY = row*4 + $39. The whole 40x40 battlefield is drawn in the left panel at",
|
|
"4x4 pixels per cell starting at screen pixel (7,7); $1F and $39 are that origin plus the VIC sprite",
|
|
"coordinate offsets ($18 horizontally, $32 vertically).",
|
|
"In: X = map column 0-39, Y = map row 0-39",
|
|
"Out: X = sprite X coordinate, Y = sprite Y coordinate; A clobbered",
|
|
"Called from: mapCellToSpriteXY ($3026/$3034), showExplosionMarker ($33E5), the shot-line setup ($3A70, $3A7B)"
|
|
],
|
|
"line": "map column 0-39"
|
|
},
|
|
"303B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "column*2"
|
|
},
|
|
"303C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "column*4 - the overview map uses 4 pixels per cell"
|
|
},
|
|
"303D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry before adding the map origin"
|
|
},
|
|
"303E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "sprite X of overview column 0 = 24 (sprite origin) + 7 (left edge of the map)"
|
|
},
|
|
"3040": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "return the sprite X in X"
|
|
},
|
|
"3041": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "map row 0-39"
|
|
},
|
|
"3042": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "row*2"
|
|
},
|
|
"3043": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "row*4"
|
|
},
|
|
"3044": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry before adding the map origin"
|
|
},
|
|
"3045": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "sprite Y of overview row 0 = 50 (sprite origin) + 7 (top edge of the map)"
|
|
},
|
|
"3047": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "return the sprite Y in Y"
|
|
},
|
|
"3048": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"3049": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"positionCursorSprite - Puts the sprite named by activeSpriteIndex ($91CC) over the cursor cell of",
|
|
"the overview map. The cursor cell is always the middle of the 7x5 tactical view, i.e. (viewOriginCol",
|
|
"+ 3, viewOriginRow + 2). Nothing happens when activeSpriteIndex is negative (no cursor sprite).",
|
|
"In: viewOriginCol zp_A5, viewOriginRow zp_A6, activeSpriteIndex $91CC, group-box state",
|
|
"Out: spriteXShadow/spriteYShadow of that sprite, spriteEnableShadow bit set; A/X/Y clobbered",
|
|
"Called from: the viewport scroller ($1D46), battlefield entry ($2012), buildGroupFormationSprite",
|
|
" ($31A0, by JMP) and the map generator overlay ($83F2)"
|
|
],
|
|
"line": "map column of the left edge of the 7x5 tactical view"
|
|
},
|
|
"304B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry before stepping to the cursor column"
|
|
},
|
|
"304C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "+3 = the middle column of the seven, where the cursor sits"
|
|
},
|
|
"304E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X = cursor column"
|
|
},
|
|
"304F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "map row of the top edge of the view"
|
|
},
|
|
"3051": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry before stepping to the cursor row"
|
|
},
|
|
"3052": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "+2 = the middle row of the five"
|
|
},
|
|
"3054": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y = cursor row"
|
|
},
|
|
"3055": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "cell -> overview sprite coordinates (shifted when a group box is active)"
|
|
},
|
|
"3058": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "keep the sprite X byte"
|
|
},
|
|
"3059": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$91CC = which sprite is currently acting as the cursor"
|
|
},
|
|
"305C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "negative = no cursor sprite wanted, leave everything alone"
|
|
},
|
|
"305E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9010+n: shadow of the VIC sprite X register, copied out by the raster IRQ"
|
|
},
|
|
"3061": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "sprite Y"
|
|
},
|
|
"3062": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9018+n: shadow of the VIC sprite Y register"
|
|
},
|
|
"3065": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$2F85[n] = 1 << n, the enable bit of this sprite"
|
|
},
|
|
"3068": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "turn the sprite on (unless sprites are suppressed)"
|
|
},
|
|
"306B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"306C": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"drawLineInPathSprite - Draws a straight line into the shape of sprite 3 ($8AC0), which is the game's",
|
|
"path/shot-line sprite. It uses the resident high-memory Bresenham stepper ($FBB8 init, $FBFA step),",
|
|
"but here its zp_92-zp_95 coordinates are pixel positions inside the 24x21 sprite, not map cells.",
|
|
"A negative argument makes the walker skip two pixels after every plotted one, giving a dotted line",
|
|
"(used for a BOOMER's arcing shot).",
|
|
"In: A = 0 solid / $80 dotted; lineCurRow/Col zp_92/zp_93 = start pixel, lineEndRow/Col zp_94/zp_95 = end pixel",
|
|
"Out: pixels set in $8AC0-$8AFF; the line-walker state is consumed, zp_92/zp_93 left at the end point",
|
|
"Called from: the shot-line builder ($3B11) and the drone heading indicator in overlay B ($8266)"
|
|
],
|
|
"line": "patch the LDA # at $307C with the dot flag: 0 = solid, $80 = dotted"
|
|
},
|
|
"306F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$FBB8: set up the Bresenham walk from (zp_93,zp_92) to (zp_95,zp_94)"
|
|
},
|
|
"3072": {
|
|
"unit": "game/mainProgram0800",
|
|
"block": [
|
|
"Walk the line one pixel at a time, plotting into sprite 3."
|
|
],
|
|
"line": "set the pixel the walker is standing on"
|
|
},
|
|
"3075": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "steps still to be taken"
|
|
},
|
|
"3077": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "branch when the end point has been reached"
|
|
},
|
|
"3079": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$FBFA: advance the walker one pixel"
|
|
},
|
|
"307C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "dot flag patched at $306C"
|
|
},
|
|
"307E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "solid line: plot every pixel"
|
|
},
|
|
"3080": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "dotted line: skip this pixel..."
|
|
},
|
|
"3083": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "...and the next one, so only every third pixel is drawn"
|
|
},
|
|
"3086": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "plot the pixel we landed on"
|
|
},
|
|
"3089": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "line finished"
|
|
},
|
|
"308A": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"plotPathCross - Marks the end of a path/shot line by plotting the four orthogonal neighbours of the",
|
|
"walker's current pixel into sprite 3: left, up, down and (by falling through into",
|
|
"plotPathSpritePixel) right. Together with the line's own last pixel this makes a small cross over",
|
|
"the target.",
|
|
"In: lineCurRow zp_92, lineCurCol zp_93 = the pixel to mark",
|
|
"Out: 4 more pixels set in $8AC0; zp_93 left one greater than on entry",
|
|
"Called from: the shot-line builder ($3B14), immediately after drawLineInPathSprite"
|
|
],
|
|
"line": "one pixel to the left of the end point"
|
|
},
|
|
"308C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "plot it"
|
|
},
|
|
"308F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "back to the end column"
|
|
},
|
|
"3091": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "one pixel above the end point"
|
|
},
|
|
"3093": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "plot it"
|
|
},
|
|
"3096": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "back to the end row"
|
|
},
|
|
"3098": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "one pixel below the end point"
|
|
},
|
|
"309A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "plot it"
|
|
},
|
|
"309D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "back to the end row"
|
|
},
|
|
"309F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "one pixel to the right - fall through and plot that one too"
|
|
},
|
|
"30A1": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"plotPathSpritePixel - Sets one pixel in the shape of sprite 3 at $8AC0. A sprite row is 3 bytes, so",
|
|
"the byte index is row*3 + column/8 and the bit is taken from the $80>>n mask table at $C008. The",
|
|
"column/8 part is patched into the ADC # at $30B3 rather than added with a register.",
|
|
"In: lineCurRow zp_92 = pixel row 0-20, lineCurCol zp_93 = pixel column 0-23",
|
|
"Out: one bit set in $8AC0-$8AFF; A/X/Y clobbered, the operand at $30B4 patched",
|
|
"Called from: drawLineInPathSprite ($3072), plotPathCross ($308C/$3093/$309A and by fall-through),",
|
|
" and directly by overlay B ($7852, $785E)"
|
|
],
|
|
"line": "pixel column 0-23 inside the sprite"
|
|
},
|
|
"30A3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "column/2"
|
|
},
|
|
"30A4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "column/4"
|
|
},
|
|
"30A5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "column/8 = which of the three bytes of a sprite row holds the pixel"
|
|
},
|
|
"30A6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patch the ADC # at $30B3 with that byte offset"
|
|
},
|
|
"30A9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the column again"
|
|
},
|
|
"30AB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit number 0-7 inside the byte"
|
|
},
|
|
"30AD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "index into the bit mask table"
|
|
},
|
|
"30AE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "pixel row 0-20"
|
|
},
|
|
"30B0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "row*2"
|
|
},
|
|
"30B1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "row*3 = offset of the start of that sprite row (3 bytes per row)"
|
|
},
|
|
"30B3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "+ byte within the row, patched at $30A6"
|
|
},
|
|
"30B5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y = byte offset inside the 63-byte shape"
|
|
},
|
|
"30B6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$8AC0 = shape of sprite 3, the path/shot line sprite"
|
|
},
|
|
"30B9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$C008[bit] = $80 >> bit"
|
|
},
|
|
"30BC": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "set the pixel"
|
|
},
|
|
"30BF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"30C0": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"buildGroupFormationSprite - Builds the 'formation ghost' shown while a whole group is being ordered",
|
|
"to a new place: every living member of the selected group is drawn as one 2x2-pixel dot into sprite",
|
|
"0, laid out exactly as the group's ordered destinations are laid out on the map. Because sprite 0",
|
|
"is X- and Y-expanded, one dot covers the 4x4 pixels the overview map gives a cell. The bounding box",
|
|
"of the destinations is turned into offsets relative to the dragged unit, so the ghost follows the",
|
|
"cursor, groupBoxActive is set, the view is scrolled until the box fits on the map and the ghost is",
|
|
"positioned.",
|
|
"In: selectedGroupKey $9206, selectedUnit $90F8, unit arrays $F76C/$FB54/$F7D0/$F834",
|
|
"Out: sprite 0 shape, spriteBuildBuffer $9025, groupBox offsets $922E-$9231, groupBoxActive $920A = $FF,",
|
|
" spritePlotMode $91F3 = $40, X/Y expand shadows bits 0-1 set, view origin possibly moved",
|
|
"Called from: runTargetCursorLoop ($21A2), when the group being ordered has 2 or more members"
|
|
],
|
|
"line": "$9206 = group id bits of the group being ordered"
|
|
},
|
|
"30C3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 7 = measure the members' ordered destinations, not their current cells"
|
|
},
|
|
"30C5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$4B5E -> zp_18/zp_19 = min column/row, zp_1B/zp_1C = max column/row"
|
|
},
|
|
"30C8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear the 64-byte shape build buffer"
|
|
},
|
|
"30CA": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "with zeroes"
|
|
},
|
|
"30CC": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9025 = scratch sprite shape used while the ghost is assembled"
|
|
},
|
|
"30CF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "next byte down"
|
|
},
|
|
"30D0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "loop over all 64 bytes"
|
|
},
|
|
"30D2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 6 = 'set the pixel'"
|
|
},
|
|
"30D4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$91F3 tells plotSpritePixel which operation to use"
|
|
},
|
|
"30D7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "max column of the group's destinations"
|
|
},
|
|
"30D9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$922E = right edge of the group box"
|
|
},
|
|
"30DC": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "min column"
|
|
},
|
|
"30DE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$922F = left edge of the group box"
|
|
},
|
|
"30E1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "max row"
|
|
},
|
|
"30E3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9230 = bottom edge of the group box"
|
|
},
|
|
"30E6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "min row"
|
|
},
|
|
"30E8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9231 = top edge of the group box"
|
|
},
|
|
"30EB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "group id bits again"
|
|
},
|
|
"30EE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 6 = 'this unit is in a group'"
|
|
},
|
|
"30F0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the value unitDisplayFlags bits 2-6 must have for a member of this group"
|
|
},
|
|
"30F2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "start at unit 99, the last unit record"
|
|
},
|
|
"30F4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "keep the loop counter in memory (X is needed for the pixel plotter)"
|
|
},
|
|
"30F6": {
|
|
"unit": "game/mainProgram0800",
|
|
"block": [
|
|
"Walk units 99..0 and plot a 2x2 dot for every living member of the group at its",
|
|
"ordered destination, relative to the top-left corner of the group box."
|
|
],
|
|
"line": "$F76C[unit] = type byte, bit 7 set = destroyed"
|
|
},
|
|
"30F9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "skip dead units"
|
|
},
|
|
"30FB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$FB54[unit] = local flags copy"
|
|
},
|
|
"30FE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "keep the group id (bits 2-4) and the in-a-group bit (6)"
|
|
},
|
|
"3100": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "does it belong to the group being ordered?"
|
|
},
|
|
"3102": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "no - try the next unit"
|
|
},
|
|
"3104": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F834[unit] = ordered destination row, bit 7 = already standing there"
|
|
},
|
|
"3107": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "drop that flag, keep the row"
|
|
},
|
|
"3109": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "set carry for the subtraction"
|
|
},
|
|
"310A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "row inside the group box"
|
|
},
|
|
"310D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "x2: two sprite pixels per map cell (the sprite is Y-expanded)"
|
|
},
|
|
"310E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y = pixel row of this member's dot"
|
|
},
|
|
"310F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "stash it, plotSpritePixel needs Y for each of the four pixels"
|
|
},
|
|
"3111": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F7D0[unit] = ordered destination column"
|
|
},
|
|
"3114": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "drop the 'already there' flag"
|
|
},
|
|
"3116": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "set carry for the subtraction"
|
|
},
|
|
"3117": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "column inside the group box"
|
|
},
|
|
"311A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "x2: two sprite pixels per map cell (the sprite is X-expanded)"
|
|
},
|
|
"311B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X = pixel column of this member's dot"
|
|
},
|
|
"311C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "stash it too"
|
|
},
|
|
"311E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 7 set = plot into spriteBuildBuffer $9025 instead of a real sprite"
|
|
},
|
|
"3120": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "top-left pixel of the 2x2 dot"
|
|
},
|
|
"3123": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "pixel column again"
|
|
},
|
|
"3125": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "one pixel to the right"
|
|
},
|
|
"3126": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "same pixel row"
|
|
},
|
|
"3128": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "again into the build buffer"
|
|
},
|
|
"312A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "top-right pixel"
|
|
},
|
|
"312D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "pixel column"
|
|
},
|
|
"312F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "pixel row"
|
|
},
|
|
"3131": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "one pixel down"
|
|
},
|
|
"3132": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "build buffer"
|
|
},
|
|
"3134": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bottom-left pixel"
|
|
},
|
|
"3137": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "pixel column"
|
|
},
|
|
"3139": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "one right"
|
|
},
|
|
"313A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "pixel row"
|
|
},
|
|
"313C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "one down"
|
|
},
|
|
"313D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "build buffer"
|
|
},
|
|
"313F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bottom-right pixel - the dot is complete"
|
|
},
|
|
"3142": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "step to the next unit"
|
|
},
|
|
"3144": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "reload the loop counter"
|
|
},
|
|
"3146": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "keep going until unit 0 has been handled"
|
|
},
|
|
"3148": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "64 bytes to copy"
|
|
},
|
|
"314A": {
|
|
"unit": "game/mainProgram0800",
|
|
"block": [
|
|
"Publish the finished shape and set up the sprite geometry."
|
|
],
|
|
"line": "the assembled ghost"
|
|
},
|
|
"314D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$8A00 = shape of sprite 0"
|
|
},
|
|
"3150": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "next byte down"
|
|
},
|
|
"3151": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "loop"
|
|
},
|
|
"3153": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9023 = shadow of VIC_SPR_EXP_X"
|
|
},
|
|
"3156": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "double the width of sprites 0 and 1"
|
|
},
|
|
"3158": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store the shadow back"
|
|
},
|
|
"315B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9024 = shadow of VIC_SPR_EXP_Y"
|
|
},
|
|
"315E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "double the height too, so one 2x2 dot covers a whole 4x4 overview cell"
|
|
},
|
|
"3160": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store the shadow back"
|
|
},
|
|
"3163": {
|
|
"unit": "game/mainProgram0800",
|
|
"block": [
|
|
"Turn the absolute box corners into offsets from the dragged unit's destination so that",
|
|
"mapCellToSpriteXY can keep the box under the cursor while the player scrolls."
|
|
],
|
|
"line": "$90F8 = the unit the player is actually dragging"
|
|
},
|
|
"3166": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "its ordered destination column"
|
|
},
|
|
"3169": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "without the 'already there' flag"
|
|
},
|
|
"316B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "keep it"
|
|
},
|
|
"316D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "its ordered destination row"
|
|
},
|
|
"3170": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "without the flag"
|
|
},
|
|
"3172": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "keep it"
|
|
},
|
|
"3174": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "left edge of the box"
|
|
},
|
|
"3177": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "set carry for the subtraction"
|
|
},
|
|
"3178": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "minus the dragged unit's column"
|
|
},
|
|
"317A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$922F is now an offset relative to the cursor"
|
|
},
|
|
"317D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "right edge"
|
|
},
|
|
"3180": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "set carry for the subtraction"
|
|
},
|
|
"3181": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "minus the dragged unit's column"
|
|
},
|
|
"3183": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$922E likewise"
|
|
},
|
|
"3186": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "top edge"
|
|
},
|
|
"3189": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "set carry for the subtraction"
|
|
},
|
|
"318A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "minus the dragged unit's row"
|
|
},
|
|
"318C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9231 likewise"
|
|
},
|
|
"318F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bottom edge"
|
|
},
|
|
"3192": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "set carry for the subtraction"
|
|
},
|
|
"3193": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "minus the dragged unit's row"
|
|
},
|
|
"3195": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9230 likewise"
|
|
},
|
|
"3198": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "flag value"
|
|
},
|
|
"319A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$920A: from now on mapCellToSpriteXY applies the box offsets"
|
|
},
|
|
"319D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$1F4E: scroll the view until the whole box fits inside the 40x40 map"
|
|
},
|
|
"31A0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "place the ghost over the cursor cell and switch it on, then return to the caller"
|
|
},
|
|
"31A3": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"enableSprites - ORs the sprite mask in A into spriteEnableShadow ($9022), the shadow the raster IRQ",
|
|
"copies into VIC_SPR_ENA. The store is skipped while comcenStunStatus ($922A) bit 6 marks the comcen",
|
|
"knock-out blackout round, so no sprite can reappear during it; A still returns the combined mask.",
|
|
"In: A = sprite bit mask (1 << sprite number)",
|
|
"Out: spriteEnableShadow updated unless suppressed; A = old shadow OR the mask",
|
|
"Called from: everywhere a cursor, marker or ghost is switched on - $2539, $2566, $2FF0, $3068,",
|
|
" $333D, $3380, $33AE, $3402, $344A, $3B19, $3D04, $484A, the $C000 overlay and both $6F00 overlays"
|
|
],
|
|
"line": "$9022 = shadow of VIC_SPR_ENA, one bit per sprite"
|
|
},
|
|
"31A6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$922A = comcen stun/knock-out status"
|
|
},
|
|
"31A9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 6 set = knock-out blackout round: keep every sprite off"
|
|
},
|
|
"31AB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the raster IRQ writes this to $D015 next frame"
|
|
},
|
|
"31AE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "A holds the combined mask either way"
|
|
},
|
|
"31AF": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"plotSpritePixel - Sets, clears or toggles one pixel of a sprite shape. The operation is chosen by",
|
|
"spritePlotMode ($91F3): bit 7 = toggle (EOR), bit 6 = set (ORA), neither = clear (AND with the",
|
|
"inverted mask). It works by patching the opcode and the mask of the read-modify-write instruction",
|
|
"at $3232. A negative sprite number selects the 64-byte build buffer at $9025 instead of the real",
|
|
"sprite data at $8A00 + n*64.",
|
|
"In: A = sprite number 0-7 (bit 7 set = use $9025), X = pixel column 0-23, Y = pixel row 0-20,",
|
|
" spritePlotMode $91F3",
|
|
"Out: one pixel modified; spritePlotPtr zp_98/zp_99 = byte pointer, spritePlotWork clobbered;",
|
|
" self-modifies $31EE (sprite number), $3232 (opcode) and $3233 (mask)",
|
|
"Called from: plotCircleOctantPoints ($32CE) and, through setSpritePixel, buildGroupFormationSprite"
|
|
],
|
|
"line": "$91F3 selects the operation"
|
|
},
|
|
"31B2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 7 set = toggle the pixel"
|
|
},
|
|
"31B4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 6 set = set the pixel"
|
|
},
|
|
"31B6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear mode: stash the sprite number in the LDX # operand at $31EE"
|
|
},
|
|
"31B9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "opcode of AND #imm"
|
|
},
|
|
"31BB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patch the read-modify-write instruction at $3232"
|
|
},
|
|
"31BE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "always taken ($29 is never zero)"
|
|
},
|
|
"31C0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "toggle mode: stash the sprite number"
|
|
},
|
|
"31C3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "opcode of EOR #imm"
|
|
},
|
|
"31C5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patch the operation"
|
|
},
|
|
"31C8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "always taken"
|
|
},
|
|
"31CA": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"setSpritePixel - Entry point of plotSpritePixel that forces the ORA (set) operation. Note that the",
|
|
"mask is still inverted further down unless spritePlotMode has bit 6 or 7 set, so callers set",
|
|
"spritePlotMode = $40 first; buildGroupFormationSprite does exactly that.",
|
|
"In: A = sprite number (bit 7 = build buffer), X = pixel column, Y = pixel row",
|
|
"Out: the pixel is set",
|
|
"Called from: buildGroupFormationSprite ($3120, $312A, $3134, $313F) and by branch from $31B4"
|
|
],
|
|
"line": "stash the sprite number in the LDX # operand at $31EE"
|
|
},
|
|
"31CD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "opcode of ORA #imm"
|
|
},
|
|
"31CF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patch the operation at $3232"
|
|
},
|
|
"31D2": {
|
|
"unit": "game/mainProgram0800",
|
|
"block": [
|
|
"Shared body: build a pointer to the byte holding the pixel and the bit mask to apply."
|
|
],
|
|
"line": "keep the pixel column"
|
|
},
|
|
"31D5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the sprite number stashed above"
|
|
},
|
|
"31D8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "0-7 = a real sprite"
|
|
},
|
|
"31DA": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "negative: use the scratch shape buffer at $9025..."
|
|
},
|
|
"31DC": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "low byte of the pointer"
|
|
},
|
|
"31DE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "high byte $90"
|
|
},
|
|
"31E0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "pointer = $9025"
|
|
},
|
|
"31E2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "...which needs no per-sprite offset"
|
|
},
|
|
"31E5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "real sprite: base of the sprite data block"
|
|
},
|
|
"31E7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "low byte"
|
|
},
|
|
"31E9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "high byte $8A"
|
|
},
|
|
"31EB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "pointer = $8A00"
|
|
},
|
|
"31ED": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "sprite number, patched at $31B6/$31C0/$31CA"
|
|
},
|
|
"31EF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "add the sprite's 64-byte offset"
|
|
},
|
|
"31F1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry for the 16-bit addition of the sprite offset"
|
|
},
|
|
"31F2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$2F95[n] = low byte of n*64"
|
|
},
|
|
"31F5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store it back"
|
|
},
|
|
"31F7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "high byte of the pointer"
|
|
},
|
|
"31F9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$2F9D[n] = high byte of n*64"
|
|
},
|
|
"31FC": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "pointer now addresses the shape of sprite n"
|
|
},
|
|
"31FE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the pixel column"
|
|
},
|
|
"3201": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "keep a copy in X"
|
|
},
|
|
"3202": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit number inside the byte"
|
|
},
|
|
"3204": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "save it for the mask lookup"
|
|
},
|
|
"3207": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "column again"
|
|
},
|
|
"3208": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "column/2"
|
|
},
|
|
"3209": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "column/4"
|
|
},
|
|
"320A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "column/8 = byte 0, 1 or 2 of a sprite row"
|
|
},
|
|
"320B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry before folding the byte offset into the pointer"
|
|
},
|
|
"320C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "fold it into the pointer"
|
|
},
|
|
"320E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "low byte"
|
|
},
|
|
"3210": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "no carry out"
|
|
},
|
|
"3212": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "carry into the high byte"
|
|
},
|
|
"3214": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit number"
|
|
},
|
|
"3217": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$C008[bit] = $80 >> bit"
|
|
},
|
|
"321A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "which operation was chosen?"
|
|
},
|
|
"321D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "toggle: EOR with the plain mask"
|
|
},
|
|
"321F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "set: ORA with the plain mask"
|
|
},
|
|
"3221": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear: AND with the inverted mask"
|
|
},
|
|
"3223": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patch the immediate operand of the operation at $3232"
|
|
},
|
|
"3226": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "pixel row 0-20"
|
|
},
|
|
"3227": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "keep it"
|
|
},
|
|
"322A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "row*2"
|
|
},
|
|
"322B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry for row*2 + row"
|
|
},
|
|
"322C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "row*3 = byte index of that sprite row (3 bytes per row)"
|
|
},
|
|
"322F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y = index into the shape"
|
|
},
|
|
"3230": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "read the shape byte"
|
|
},
|
|
"3232": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patched: ORA/AND/EOR with the patched mask"
|
|
},
|
|
"3234": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "write the modified byte back"
|
|
},
|
|
"3236": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"3237": {
|
|
"unit": "game/mainProgram0800",
|
|
"block": [
|
|
"Two work bytes living inside the code."
|
|
],
|
|
"line": "scratch used by plotSpritePixel: pixel column, then bit number, then pixel row"
|
|
},
|
|
"3238": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "which of the eight mirrored circle points plotCircleOctantPoints is plotting (7 down to 0)"
|
|
},
|
|
"3239": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"drawCircleInSprite - Draws a circle of radius X (1-10) centred on pixel (12,10) - the middle of a",
|
|
"24x21 sprite - into sprite A, using 8-way octant symmetry. The dx/dy point lists of each radius live",
|
|
"in $9F69.. and are reached through the pointer tables at $9F37/$9F41 (dx) and $9F4B/$9F55 (dy); the",
|
|
"index of the last point of the octant comes from $9F5F. spritePlotMode decides whether the pixels",
|
|
"are set, cleared or toggled. Radius 1 degenerates into a filled 3x3 dot.",
|
|
"In: A = sprite number (bit 7 = build buffer), X = radius 1-10, spritePlotMode $91F3",
|
|
"Out: the circle is plotted; activeSpriteIndex $91CC = A, circleStepsLeft $91F2 = $FF,",
|
|
" circleDxPtr/circleDyPtr zp_AD-zp_B0 point at the two lists",
|
|
"Called from: drawRingsInSprite4 ($3471), the unit blob markers ($3D13, $3D43) and overlay B's",
|
|
" range rings ($7190-$71DA)"
|
|
],
|
|
"line": "$91CC: plotCircleOctantPoints will plot into this sprite"
|
|
},
|
|
"323C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the tables are indexed by radius-1"
|
|
},
|
|
"323D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9F37[r-1] = low byte of the dx list"
|
|
},
|
|
"3240": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "zp_AD"
|
|
},
|
|
"3242": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9F41[r-1] = high byte (always $9F)"
|
|
},
|
|
"3245": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "zp_AE"
|
|
},
|
|
"3247": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9F4B[r-1] = low byte of the dy list"
|
|
},
|
|
"324A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "zp_AF"
|
|
},
|
|
"324C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9F55[r-1] = high byte"
|
|
},
|
|
"324F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "zp_B0"
|
|
},
|
|
"3251": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9F5F[r-1] = index of the last point of the octant"
|
|
},
|
|
"3254": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$91F2 = octant point counter"
|
|
},
|
|
"3257": {
|
|
"unit": "game/mainProgram0800",
|
|
"block": [
|
|
"Walk the octant point list from the last entry down to entry 0."
|
|
],
|
|
"line": "mirror point Y into the 8 symmetric coordinates"
|
|
},
|
|
"325A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "plot those 8 pixels"
|
|
},
|
|
"325D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "previous point of the octant"
|
|
},
|
|
"3260": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "reload it as the index"
|
|
},
|
|
"3263": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "loop until point 0 has been plotted"
|
|
},
|
|
"3265": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "circle complete"
|
|
},
|
|
"3266": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"computeCircleOctantPoints - Expands one octant point (dx,dy) of a circle into the coordinates of all",
|
|
"eight mirrored points, writing them into circlePointX0-7 ($32DA) and circlePointY0-7 ($32E2). The",
|
|
"centre is pixel (12,10), the middle of a 24x21 sprite.",
|
|
"In: Y = index into the octant lists, circleDxPtr zp_AD/zp_AE, circleDyPtr zp_AF/zp_B0",
|
|
"Out: $32DA-$32E9 filled with 8 X and 8 Y coordinates",
|
|
"Called from: drawCircleInSprite ($3257)"
|
|
],
|
|
"line": "prepare the additions"
|
|
},
|
|
"3267": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "12 = centre column of a 24-pixel-wide sprite"
|
|
},
|
|
"3269": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "+dx of this octant point"
|
|
},
|
|
"326B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X of mirrored point 0"
|
|
},
|
|
"326E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X of mirrored point 7"
|
|
},
|
|
"3271": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "prepare the subtractions"
|
|
},
|
|
"3272": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "centre column again"
|
|
},
|
|
"3274": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "12-dx"
|
|
},
|
|
"3276": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X of mirrored point 3"
|
|
},
|
|
"3279": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X of mirrored point 4"
|
|
},
|
|
"327C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry for the next addition"
|
|
},
|
|
"327D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "centre column"
|
|
},
|
|
"327F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "12+dy - the octant swap that mirrors about the diagonal"
|
|
},
|
|
"3281": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X of mirrored point 1"
|
|
},
|
|
"3284": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X of mirrored point 6"
|
|
},
|
|
"3287": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "set carry for the next subtraction"
|
|
},
|
|
"3288": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "centre column"
|
|
},
|
|
"328A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "12-dy"
|
|
},
|
|
"328C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X of mirrored point 2"
|
|
},
|
|
"328F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X of mirrored point 5"
|
|
},
|
|
"3292": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry for the next addition"
|
|
},
|
|
"3293": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "10 = centre row of a 21-pixel-high sprite"
|
|
},
|
|
"3295": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "10+dy"
|
|
},
|
|
"3297": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y of mirrored point 0"
|
|
},
|
|
"329A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y of mirrored point 3"
|
|
},
|
|
"329D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "set carry for the next subtraction"
|
|
},
|
|
"329E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "centre row"
|
|
},
|
|
"32A0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "10-dy"
|
|
},
|
|
"32A2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y of mirrored point 4"
|
|
},
|
|
"32A5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y of mirrored point 7"
|
|
},
|
|
"32A8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry for the next addition"
|
|
},
|
|
"32A9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "centre row"
|
|
},
|
|
"32AB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "10+dx"
|
|
},
|
|
"32AD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y of mirrored point 1"
|
|
},
|
|
"32B0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y of mirrored point 2"
|
|
},
|
|
"32B3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "set carry for the next subtraction"
|
|
},
|
|
"32B4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "centre row"
|
|
},
|
|
"32B6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "10-dx"
|
|
},
|
|
"32B8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y of mirrored point 5"
|
|
},
|
|
"32BB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y of mirrored point 6"
|
|
},
|
|
"32BE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "all eight points ready"
|
|
},
|
|
"32BF": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"plotCircleOctantPoints - Plots the eight mirrored points prepared by computeCircleOctantPoints into",
|
|
"the sprite named by activeSpriteIndex, counting circlePointIndex ($3238) down from 7 to 0.",
|
|
"In: circlePointX0-7 $32DA, circlePointY0-7 $32E2, activeSpriteIndex $91CC, spritePlotMode $91F3",
|
|
"Out: 8 pixels plotted; circlePointIndex = $FF",
|
|
"Called from: drawCircleInSprite ($325A)"
|
|
],
|
|
"line": "eight symmetric points per octant step"
|
|
},
|
|
"32C1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "keep the point index in memory, X is needed by the plotter"
|
|
},
|
|
"32C4": {
|
|
"unit": "game/mainProgram0800",
|
|
"block": [
|
|
"Plot the eight mirrored points of the current octant step."
|
|
],
|
|
"line": "$32E2[n] = Y coordinate of point n"
|
|
},
|
|
"32C7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$32DA[n] = X coordinate of point n"
|
|
},
|
|
"32CA": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X = pixel column"
|
|
},
|
|
"32CB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the sprite chosen by drawCircleInSprite"
|
|
},
|
|
"32CE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "set/clear/toggle the pixel"
|
|
},
|
|
"32D1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "next point"
|
|
},
|
|
"32D4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "reload the index"
|
|
},
|
|
"32D7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "loop until point 0 has been plotted"
|
|
},
|
|
"32D9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"32DA": {
|
|
"unit": "game/mainProgram0800",
|
|
"block": [
|
|
"Sixteen RAM bytes inside the code: the eight X coordinates ($32DA-$32E1) and the eight Y",
|
|
"coordinates ($32E2-$32E9) of the mirrored points of one circle step. Written by",
|
|
"computeCircleOctantPoints and read, indexed 0-7, by plotCircleOctantPoints."
|
|
],
|
|
"line": "X coordinate of mirrored circle point 0"
|
|
},
|
|
"32DB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X coordinate of mirrored circle point 1"
|
|
},
|
|
"32DC": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X coordinate of mirrored circle point 2"
|
|
},
|
|
"32DD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X coordinate of mirrored circle point 3"
|
|
},
|
|
"32DE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X coordinate of mirrored circle point 4"
|
|
},
|
|
"32DF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X coordinate of mirrored circle point 5"
|
|
},
|
|
"32E0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X coordinate of mirrored circle point 6"
|
|
},
|
|
"32E1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "X coordinate of mirrored circle point 7"
|
|
},
|
|
"32E2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y coordinate of mirrored circle point 0"
|
|
},
|
|
"32E3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y coordinate of mirrored circle point 1"
|
|
},
|
|
"32E4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y coordinate of mirrored circle point 2"
|
|
},
|
|
"32E5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y coordinate of mirrored circle point 3"
|
|
},
|
|
"32E6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y coordinate of mirrored circle point 4"
|
|
},
|
|
"32E7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y coordinate of mirrored circle point 5"
|
|
},
|
|
"32E8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y coordinate of mirrored circle point 6"
|
|
},
|
|
"32E9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y coordinate of mirrored circle point 7"
|
|
},
|
|
"32EA": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"hideSprite1 - Clears bit 1 of the sprite enable shadow and writes the result straight to",
|
|
"VIC_SPR_ENA, so the unit marker sprite disappears in the current frame instead of at the next",
|
|
"raster interrupt.",
|
|
"In: spriteEnableShadow $9022",
|
|
"Out: $9022 and $D015 with bit 1 cleared; A clobbered",
|
|
"Called from: the battlefield cursor and selection code ($229F, $22F4, $2359, $253C, $2540, $3D4E)"
|
|
],
|
|
"line": "$9022 = shadow of VIC_SPR_ENA"
|
|
},
|
|
"32ED": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear bit 1 = sprite 1, the unit marker on the overview map"
|
|
},
|
|
"32EF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "keep the shadow in step"
|
|
},
|
|
"32F2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "write $D015 at once so the marker vanishes immediately"
|
|
},
|
|
"32F5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"32F6": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"hideSprite0Dead - Dead code: a byte-for-byte copy of hideSprite1 that clears bit 0 (sprite 0)",
|
|
"instead of bit 1. No traced code refers to $32F6, and callers that want sprite 0 off clear the",
|
|
"shadow themselves, so this is a leftover of an earlier build.",
|
|
"In: none (never called)",
|
|
"Out: would clear bit 0 of $9022 and $D015"
|
|
],
|
|
"line": "dead code: sprite enable shadow"
|
|
},
|
|
"32F9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear bit 0 = sprite 0"
|
|
},
|
|
"32FB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store the shadow"
|
|
},
|
|
"32FE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "write it to $D015"
|
|
},
|
|
"3301": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "return"
|
|
},
|
|
"3302": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"showCrosshairSprite - Loads the 63-byte diamond crosshair (the second shape of the pair at $9EA4,",
|
|
"bytes $9EE3-$9F21) into sprite 2 and falls into the shared body at $3308, which paints it black,",
|
|
"doubles it in both directions, parks it over the centre cell of the 7x5 tactical view and enables it.",
|
|
"In: none",
|
|
"Out: sprite 2 shape/colour/size/position set, sprite 2 enabled",
|
|
"Called from: runTargetCursorLoop ($21AB) when the player is choosing an attack target"
|
|
],
|
|
"line": "$7D = last byte of shape 1 ($9EE3-$9F21), the diamond crosshair"
|
|
},
|
|
"3304": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "always taken"
|
|
},
|
|
"3306": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"showCursorBoxSprite - Same as showCrosshairSprite but copies the first shape of the pair ($9EA4-",
|
|
"$9EE2), the hollow box that frames the cursor cell of the tactical view.",
|
|
"In: none",
|
|
"Out: sprite 2 holds the box, black, expanded, at sprite X 256 / Y $4D, enabled",
|
|
"Called from: battlefield entry ($1FEB, $2260) and the order-cancel path ($4C56, by JMP)"
|
|
],
|
|
"line": "$3E = last byte of shape 0 ($9EA4-$9EE2), the hollow cursor box"
|
|
},
|
|
"3308": {
|
|
"unit": "game/mainProgram0800",
|
|
"block": [
|
|
"Shared body: copy 63 bytes backwards into sprite 2, then make it a black, double-sized",
|
|
"frame sitting over the centre cell of the 7x5 tactical view."
|
|
],
|
|
"line": "63 bytes, copied from the end backwards"
|
|
},
|
|
"330A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9EA4 holds the two 63-byte shapes back to back"
|
|
},
|
|
"330D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$8A80 = shape of sprite 2"
|
|
},
|
|
"3310": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "previous source byte"
|
|
},
|
|
"3311": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "previous destination byte"
|
|
},
|
|
"3312": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "loop over all 63 bytes"
|
|
},
|
|
"3314": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "colour 0"
|
|
},
|
|
"3316": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$900A = sprite 2 colour shadow: black"
|
|
},
|
|
"3319": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9023 = X expansion shadow"
|
|
},
|
|
"331C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "double the width of sprite 2"
|
|
},
|
|
"331E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store it back"
|
|
},
|
|
"3321": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9024 = Y expansion shadow"
|
|
},
|
|
"3324": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "double the height too, so the frame covers a whole 16x16 view cell"
|
|
},
|
|
"3326": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store it back"
|
|
},
|
|
"3329": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "low byte of the sprite X coordinate"
|
|
},
|
|
"332B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9012 = sprite 2 X shadow"
|
|
},
|
|
"332E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9020 = shadow of the sprite X MSB register"
|
|
},
|
|
"3331": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "set bit 2: sprite 2 X coordinate becomes 256"
|
|
},
|
|
"3333": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store it back"
|
|
},
|
|
"3336": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "sprite Y 77"
|
|
},
|
|
"3338": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$901A: the centre cell of the 7x5 tactical view"
|
|
},
|
|
"333B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "sprite 2 enable bit"
|
|
},
|
|
"333D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "switch it on and return to the caller"
|
|
},
|
|
"3340": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"loadDirectionShapeSprite - Copies sprite shape number A (0-7, one per facing direction) from the",
|
|
"decompressed shape buffer at $0200 + A*64 into sprite 0 ($8A00) when activeSpriteIndex is 0, or into",
|
|
"sprite 5 ($8B40) otherwise, and enables that sprite. The buffer is filled by the RLE decompressor",
|
|
"at $67CB from the compressed shape sets at $FD70/$FE24.",
|
|
"In: A = shape index 0-7, activeSpriteIndex $91CC = target sprite (0 or 5)",
|
|
"Out: 63 bytes of sprite 0 or 5 rewritten and the sprite enabled; spritePlotPtr zp_98/zp_99 clobbered;",
|
|
" self-modifies the destination address of the STA at $3373",
|
|
"Called from: the unit direction display ($5322) and overlay B ($802A, $810B, $829E)"
|
|
],
|
|
"line": "shape number in the high byte = shape*256"
|
|
},
|
|
"3342": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "low byte starts at 0"
|
|
},
|
|
"3344": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "16-bit shift right..."
|
|
},
|
|
"3346": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "...through the low byte"
|
|
},
|
|
"3347": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "and again"
|
|
},
|
|
"3349": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "shape*64"
|
|
},
|
|
"334A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "low byte of the source pointer"
|
|
},
|
|
"334C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "no extra low offset"
|
|
},
|
|
"334E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0200 = base of the decompressed shape buffer"
|
|
},
|
|
"3350": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry for the 16-bit pointer addition"
|
|
},
|
|
"3351": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "add the shape offset"
|
|
},
|
|
"3353": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "source pointer low byte"
|
|
},
|
|
"3355": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "base page $02"
|
|
},
|
|
"3356": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "plus the high byte of shape*64"
|
|
},
|
|
"3358": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "source pointer = $0200 + shape*64"
|
|
},
|
|
"335A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "default destination low byte"
|
|
},
|
|
"335C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "default destination high byte: $8A00 = sprite 0"
|
|
},
|
|
"335E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$91CC = which sprite to load"
|
|
},
|
|
"3361": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "sprite 0 keeps the default"
|
|
},
|
|
"3363": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "otherwise $8B40..."
|
|
},
|
|
"3365": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "...= the shape of sprite 5"
|
|
},
|
|
"3367": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patch the low byte of the STA absolute,x at $3373"
|
|
},
|
|
"336A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patch its high byte"
|
|
},
|
|
"336D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "63 bytes to copy"
|
|
},
|
|
"336F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "same index for source and destination"
|
|
},
|
|
"3371": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "read from the shape buffer"
|
|
},
|
|
"3373": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patched to $8A00,x or $8B40,x; the $FFFF resting value is never used"
|
|
},
|
|
"3376": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "previous destination byte"
|
|
},
|
|
"3377": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "previous source byte"
|
|
},
|
|
"3378": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "loop over all 63 bytes"
|
|
},
|
|
"337A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "which sprite was loaded"
|
|
},
|
|
"337D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$2F85[n] = 1 << n"
|
|
},
|
|
"3380": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "switch it on and return to the caller"
|
|
},
|
|
"3383": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"showComcenCrossMarker - Puts the small cross marker at $9F22 into rows 7-13 of sprite 2, colours it",
|
|
"light red and parks it on the comcen's cell of overlay B's 21x17 radar grid (grid column 10, row 8 -",
|
|
"the grid is always drawn centred on the comcen).",
|
|
"In: none",
|
|
"Out: sprite 2 shape/colour/position set and enabled, gridCursorCol zp_67 = 10, gridCursorRow zp_68 = 8",
|
|
"Called from: overlay B ($75B6) while the RADAR/MISSILE screen is being built"
|
|
],
|
|
"line": "sprite 2"
|
|
},
|
|
"3385": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "blank its 64 shape bytes first"
|
|
},
|
|
"3388": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "21 bytes = 7 sprite rows of 3 bytes"
|
|
},
|
|
"338A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9F22 = the small cross/plus shape"
|
|
},
|
|
"338D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$8A95 = sprite 2 shape + $15, i.e. row 7 of the sprite"
|
|
},
|
|
"3390": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "previous byte"
|
|
},
|
|
"3391": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "loop over the 21 bytes"
|
|
},
|
|
"3393": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "colour $0A = light red"
|
|
},
|
|
"3395": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$900A = sprite 2 colour shadow"
|
|
},
|
|
"3398": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "grid column 10 - where the own comcen always sits"
|
|
},
|
|
"339A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "zp_67 = radar grid cursor column"
|
|
},
|
|
"339C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "grid row 8"
|
|
},
|
|
"339E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "zp_68 = radar grid cursor row"
|
|
},
|
|
"33A0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "overlay B range test; its carry result is never examined here, so the call is a leftover"
|
|
},
|
|
"33A3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "grid cell -> sprite coordinates"
|
|
},
|
|
"33A6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9012 = sprite 2 X shadow"
|
|
},
|
|
"33A9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$901A = sprite 2 Y shadow"
|
|
},
|
|
"33AC": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "sprite 2 enable bit"
|
|
},
|
|
"33AE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "switch it on and return to the caller"
|
|
},
|
|
"33B1": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"gridCellToSpriteCoords - Converts a cell of overlay B's 21x17 radar grid (one map cell per 8x8",
|
|
"character cell) into sprite coordinates: spriteX = column*8 + $27, spriteY = row*8 + $43. The grid",
|
|
"starts at character position (3,3); the two constants fold in the VIC sprite origin (24,50) and the",
|
|
"offset of the marker shapes inside their sprite.",
|
|
"In: X = grid column 0-20, Y = grid row 0-16",
|
|
"Out: X = sprite X, Y = sprite Y; A clobbered",
|
|
"Called from: showComcenCrossMarker ($33A3), getUnitSpriteCentreOnGrid ($3410) and overlay B",
|
|
" ($7709, $77BC)"
|
|
],
|
|
"line": "grid column"
|
|
},
|
|
"33B2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "column*2"
|
|
},
|
|
"33B3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "column*4"
|
|
},
|
|
"33B4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "column*8 - the radar grid uses one 8x8 character cell per map cell"
|
|
},
|
|
"33B5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry before adding the grid origin"
|
|
},
|
|
"33B6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "sprite X of grid column 0"
|
|
},
|
|
"33B8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "return it in X"
|
|
},
|
|
"33B9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "grid row"
|
|
},
|
|
"33BA": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "row*2"
|
|
},
|
|
"33BB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "row*4"
|
|
},
|
|
"33BC": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "row*8"
|
|
},
|
|
"33BD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry before adding the grid origin"
|
|
},
|
|
"33BE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "sprite Y of grid row 0"
|
|
},
|
|
"33C0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "return it in Y"
|
|
},
|
|
"33C1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"33C2": {
|
|
"unit": "game/mainProgram0800",
|
|
"block": [
|
|
"Three 2-entry tables indexed by explosion type: 0 = comcen missile strike, 1 = drone",
|
|
"detonation. They give the sprite offsets that centre the ring blob on the target cell and",
|
|
"the number of concentric rings that make the blob."
|
|
],
|
|
"line": "X offsets: 10 pixels for a missile strike, 8 for a drone blast"
|
|
},
|
|
"33C4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "matching Y offsets: 8 and 9 pixels"
|
|
},
|
|
"33C6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "ring counts: 2 rings for a missile strike, 4 for the bigger drone blast"
|
|
},
|
|
"33C8": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"showExplosionMarker - Shows the explosion marker for a weapon effect at map cell (X,Y). On the",
|
|
"battlefield screen it draws a blob of concentric rings into sprite 4 and puts it straight on the",
|
|
"4x4-per-cell overview map; a missile strike that arrives while a drone is in the air instead just",
|
|
"records the cell in the two patched operands of updateExplosionMarker, which keeps the marker in",
|
|
"step with the scrolling drone camera window. Either way markerSpriteTimer is set to 90 frames, and",
|
|
"the per-frame update in updateGameFrame switches sprite 4 off when it expires. The survey called",
|
|
"this routine dead; it is not - it is called by two command handlers.",
|
|
"In: A = effect type (0 = comcen missile strike, 1 = drone detonation), X = map column, Y = map row;",
|
|
" droneControlFlags $920D, currentScreen $90FB",
|
|
"Out: sprite 4 shape/position/colour, markerSpriteTimer $923E = 90; self-modifies $33EA (the effect",
|
|
" index) and, on the drone path, $3425/$3437 (the marker cell)",
|
|
"Called from: cmdDroneDetonate ($5375, A=1) and cmdMissileStrike ($541C, A=0)"
|
|
],
|
|
"line": "patch the LDX # at $33E9 with the effect index (0 missile, 1 drone)"
|
|
},
|
|
"33CB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "is this the comcen missile strike?"
|
|
},
|
|
"33CD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "no - a drone blast always goes on the overview map"
|
|
},
|
|
"33CF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$920D = drone control flags"
|
|
},
|
|
"33D2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 7 clear = no drone in the air, so the drone camera is not on screen"
|
|
},
|
|
"33D4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "start the 90-frame marker countdown"
|
|
},
|
|
"33D7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "remember the blast column in the LDA # of updateExplosionMarker"
|
|
},
|
|
"33DA": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "and the blast row"
|
|
},
|
|
"33DD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "position sprite 4 inside the drone camera window and return"
|
|
},
|
|
"33E0": {
|
|
"unit": "game/mainProgram0800",
|
|
"block": [
|
|
"Battlefield path: build the ring blob and drop it straight on the overview map."
|
|
],
|
|
"line": "$90FB = which screen is showing; 0 = the battlefield"
|
|
},
|
|
"33E3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "not on the battlefield - there is nothing to draw on"
|
|
},
|
|
"33E5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "blast cell -> overview map sprite coordinates"
|
|
},
|
|
"33E8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "sprite X of the cell"
|
|
},
|
|
"33E9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "effect index, patched at $33C8"
|
|
},
|
|
"33EB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "set carry for the centring subtraction"
|
|
},
|
|
"33EC": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "shift left so the ring blob is centred on the cell"
|
|
},
|
|
"33EF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9014 = sprite 4 X shadow"
|
|
},
|
|
"33F2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "sprite Y of the cell"
|
|
},
|
|
"33F3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "set carry for the centring subtraction"
|
|
},
|
|
"33F4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "shift up by the matching Y offset"
|
|
},
|
|
"33F7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$901C = sprite 4 Y shadow"
|
|
},
|
|
"33FA": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "how many concentric rings this effect uses"
|
|
},
|
|
"33FD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "draw them into sprite 4"
|
|
},
|
|
"3400": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "sprite 4 enable bit"
|
|
},
|
|
"3402": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "switch the marker on"
|
|
},
|
|
"3405": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"startExplosionMarkerTimer - Two-instruction tail shared by both paths of showExplosionMarker: arms",
|
|
"the explosion marker for 90 frames (about 1.5 seconds).",
|
|
"In: none",
|
|
"Out: markerSpriteTimer $923E = $5A",
|
|
"Called from: showExplosionMarker ($33D4) and by fall-through from $3402"
|
|
],
|
|
"line": "$5A = 90 frames"
|
|
},
|
|
"3407": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$923E; updateGameFrame counts it down and hides sprite 4 at zero"
|
|
},
|
|
"340A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "return (also the exit taken when the battlefield screen is not showing)"
|
|
},
|
|
"340B": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"getUnitSpriteCentreOnGrid - Maps a battlefield cell onto overlay B's radar grid and returns the",
|
|
"sprite coordinates of the centre of that grid cell, or C=1 when the cell lies outside the 21x17",
|
|
"grid drawn around the comcen.",
|
|
"In: X = map column, Y = map row",
|
|
"Out: C=0 with X/Y = sprite coordinates of the cell centre, or C=1 and X/Y meaningless",
|
|
"Called from: the unit tracking code ($5307) and overlay B ($7A03)"
|
|
],
|
|
"line": "overlay B $7A13: map cell -> radar grid cell relative to the comcen, C=1 when off-grid"
|
|
},
|
|
"340E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "outside the 21x17 grid: return with C=1"
|
|
},
|
|
"3410": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "grid cell -> sprite coordinates of its top-left"
|
|
},
|
|
"3413": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "sprite Y"
|
|
},
|
|
"3414": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry before adding the half-cell offset"
|
|
},
|
|
"3415": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "+4 = half a character cell, i.e. the centre of the cell"
|
|
},
|
|
"3417": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "back into Y"
|
|
},
|
|
"3418": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "sprite X"
|
|
},
|
|
"3419": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry before adding the half-cell offset"
|
|
},
|
|
"341A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "+4 for the same reason"
|
|
},
|
|
"341C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "back into X"
|
|
},
|
|
"341D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "C=0 = the cell is on the grid"
|
|
},
|
|
"341E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "return"
|
|
},
|
|
"341F": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"updateExplosionMarker - Keeps the explosion marker (sprite 4) on the right cell of the drone camera",
|
|
"window, which is 14 columns by 12 rows of 8x8 pixel cells starting at the view origin. The marker",
|
|
"cell lives in the two immediate operands at $3425 and $3437, patched by showExplosionMarker. When",
|
|
"the countdown has expired or the cell has scrolled out of the window, sprite 4 is switched off",
|
|
"instead. The survey believed nothing ever patched the operands; showExplosionMarker does.",
|
|
"In: markerSpriteTimer $923E, viewOriginCol zp_A5, viewOriginRow zp_A6, the operands at $3425/$3437",
|
|
"Out: sprite 4 position shadows $9014/$901C and its enable bit; A clobbered",
|
|
"Called from: showExplosionMarker ($33DD, by JMP) and overlay B's drone camera step ($827E)"
|
|
],
|
|
"line": "$923E, counted down once per frame by updateGameFrame"
|
|
},
|
|
"3422": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "zero = no explosion pending: make sure sprite 4 is off"
|
|
},
|
|
"3424": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "blast column, patched at $33D7"
|
|
},
|
|
"3426": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "set carry for the subtraction of the view origin"
|
|
},
|
|
"3427": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "column relative to the left edge of the drone camera window"
|
|
},
|
|
"3429": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the window is 14 cells wide"
|
|
},
|
|
"342B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "outside it (this also catches negative differences): hide the marker"
|
|
},
|
|
"342D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "x2"
|
|
},
|
|
"342E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "x4"
|
|
},
|
|
"342F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "x8 - the drone camera draws one map cell per 8x8 character cell"
|
|
},
|
|
"3430": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry before adding the window origin"
|
|
},
|
|
"3431": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "sprite X that centres the ring blob on window column 0"
|
|
},
|
|
"3433": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9014 = sprite 4 X shadow"
|
|
},
|
|
"3436": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "blast row, patched at $33DA"
|
|
},
|
|
"3438": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "set carry for the subtraction of the view origin"
|
|
},
|
|
"3439": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "row relative to the top of the window"
|
|
},
|
|
"343B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the window is 12 cells high"
|
|
},
|
|
"343D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "outside it: hide the marker"
|
|
},
|
|
"343F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "x2"
|
|
},
|
|
"3440": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "x4"
|
|
},
|
|
"3441": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "x8"
|
|
},
|
|
"3442": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry before adding the window origin"
|
|
},
|
|
"3443": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "sprite Y that centres the blob on window row 0"
|
|
},
|
|
"3445": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$901C = sprite 4 Y shadow"
|
|
},
|
|
"3448": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "sprite 4 enable bit"
|
|
},
|
|
"344A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "switch it on and return to the caller"
|
|
},
|
|
"344D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9022 = sprite enable shadow"
|
|
},
|
|
"3450": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear bit 4 = sprite 4, the explosion marker"
|
|
},
|
|
"3452": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store it back (the raster IRQ writes $D015)"
|
|
},
|
|
"3455": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"3456": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"drawComcenRingSprite - Builds the comcen marker of the drone screen: two concentric rings (radius 2",
|
|
"then radius 1, which is a filled 3x3 dot) in sprite 4, coloured with the flashing pair $12 so it",
|
|
"alternates between white and red.",
|
|
"In: none",
|
|
"Out: sprite 4 shape rebuilt, sprite4ColourShadow $900C = $12, sprite 4 left disabled here,",
|
|
" activeSpriteIndex $91CC = 4, spritePlotMode $91F3 = $40",
|
|
"Called from: overlay B ($80E1), right after the view has been centred on the comcen"
|
|
],
|
|
"line": "two concentric rings for the comcen marker"
|
|
},
|
|
"3458": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"drawRingsInSprite4 - Shared body of drawComcenRingSprite: clears sprite 4 and draws A concentric",
|
|
"rings into it, radius A down to radius 1, then gives it the flashing colour pair $12. The ring count",
|
|
"is held in the LDX # operand at $346E and counted down there.",
|
|
"In: A = number of rings / radius of the outermost one",
|
|
"Out: sprite 4 shape and colour; sprite 4 disabled while it is rebuilt; self-modifies $346E",
|
|
"Called from: showExplosionMarker ($33FD, A = 2 or 4) and by fall-through from drawComcenRingSprite"
|
|
],
|
|
"line": "patch the LDX # at $346D with the outermost radius / ring count"
|
|
},
|
|
"345B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9022 = sprite enable shadow"
|
|
},
|
|
"345E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear bit 4: hide sprite 4 while its shape is rebuilt"
|
|
},
|
|
"3460": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store it back"
|
|
},
|
|
"3463": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 6 = 'set the pixel'"
|
|
},
|
|
"3465": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$91F3 = plot mode for drawCircleInSprite"
|
|
},
|
|
"3468": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "sprite 4"
|
|
},
|
|
"346A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "blank its 64 shape bytes"
|
|
},
|
|
"346D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "current radius, patched at $3458 and decremented below"
|
|
},
|
|
"346F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "draw into sprite 4"
|
|
},
|
|
"3471": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "one circle of that radius, centred on sprite pixel (12,10)"
|
|
},
|
|
"3474": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "next smaller radius"
|
|
},
|
|
"3477": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "loop down to radius 1, which fills the centre with a 3x3 dot"
|
|
},
|
|
"3479": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$12 = flashing colour pair: alternates colour 2 (red) and colour 1 (white)"
|
|
},
|
|
"347B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$900C = sprite 4 colour shadow"
|
|
},
|
|
"347E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"347F": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"orderSelectedUnitToCursor - Issues a MOVE order for the selected unit to the cell under the cursor:",
|
|
"takes the unit out of its group, queues command $80 unit,col,row into the outgoing ring (so the",
|
|
"engine, the opponent and the game film all see the same bytes) and refreshes the 'already at the",
|
|
"destination' flag.",
|
|
"In: selectedUnit $90F8, viewOriginCol zp_A5, viewOriginRow zp_A6",
|
|
"Out: cmdParam0-2 zp_73-zp_75 = unit/column/row, $FB54[unit] bit 6 cleared and bit 7 refreshed,",
|
|
" 4 bytes queued for the command interpreter, C=0",
|
|
"Called from: the fire-button handler of the battlefield cursor loop ($2212)"
|
|
],
|
|
"line": "left edge column of the tactical view"
|
|
},
|
|
"3481": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry before stepping to the cursor column"
|
|
},
|
|
"3482": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "+3 = the cursor column"
|
|
},
|
|
"3484": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "zp_74 = command argument 1 (destination column)"
|
|
},
|
|
"3486": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "top edge row of the tactical view"
|
|
},
|
|
"3488": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry before stepping to the cursor row"
|
|
},
|
|
"3489": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "+2 = the cursor row"
|
|
},
|
|
"348B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "zp_75 = command argument 2 (destination row)"
|
|
},
|
|
"348D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$90F8 = the unit being ordered"
|
|
},
|
|
"3490": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$FB54[unit] = local display/group flags"
|
|
},
|
|
"3493": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear bit 6: a unit given its own order leaves its group"
|
|
},
|
|
"3495": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store the flags back"
|
|
},
|
|
"3498": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "zp_73 = command argument 0 (unit index)"
|
|
},
|
|
"349A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "command byte $80 = MOVE unit,col,row"
|
|
},
|
|
"349C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$560A: queue the 4 bytes for the engine, the link and the film"
|
|
},
|
|
"349F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "set or clear the 'standing on its destination' bit"
|
|
},
|
|
"34A2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "C=0 tells the cursor loop the order was accepted"
|
|
},
|
|
"34A3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"34A4": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"updateUnitAtDestinationFlag - Sets bit 7 of unitDisplayFlags ($FB54) for the unit in cmdParam0 when",
|
|
"its current cell is the same as the ordered destination in cmdParam1/cmdParam2, and clears it",
|
|
"otherwise. The bit is what the console and the map drawing use to tell a moving unit from an idle one.",
|
|
"In: cmdParam0 zp_73 = unit, cmdParam1 zp_74 = destination column, cmdParam2 zp_75 = destination row",
|
|
"Out: $FB54[unit] bit 7; self-modifies the ORA operand at $34C1",
|
|
"Called from: orderSelectedUnitToCursor ($349F) and the command executors at $4A4D and $4C10"
|
|
],
|
|
"line": "zp_73 = unit index"
|
|
},
|
|
"34A6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "assume the unit still has somewhere to go"
|
|
},
|
|
"34A8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F640[unit] = current map column"
|
|
},
|
|
"34AB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "same as the ordered column?"
|
|
},
|
|
"34AD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "no - it is still travelling"
|
|
},
|
|
"34AF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F6A4[unit] = current map row"
|
|
},
|
|
"34B2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "same as the ordered row?"
|
|
},
|
|
"34B4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "no - still travelling"
|
|
},
|
|
"34B6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 7 = the unit is already standing on its destination"
|
|
},
|
|
"34B8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patch the ORA # at $34C0 with $80 or $00"
|
|
},
|
|
"34BB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$FB54[unit]"
|
|
},
|
|
"34BE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear the old 'at destination' bit"
|
|
},
|
|
"34C0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patched: put the freshly computed bit back"
|
|
},
|
|
"34C2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store the flags"
|
|
},
|
|
"34C5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"34C6": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"applyMoveOrder - Executor of command $80 MOVE (unit, column, row). It takes the unit out of its",
|
|
"group, republishes the group bits into the local flags copy, and falls into setUnitDestination to",
|
|
"store the clamped destination. The survey listed this as an unreferenced older version; it is in",
|
|
"fact live - cmdMoveUnit jumps here from $5017 - and there is no other move executor in the build.",
|
|
"In: cmdParam0 zp_73 = unit, cmdParam1/cmdParam2 zp_74/zp_75 = destination (already mirrored for a",
|
|
" remote command)",
|
|
"Out: $F708[unit] bit 6 cleared, $FB54[unit] group bits refreshed, then everything setUnitDestination does",
|
|
"Called from: cmdMoveUnit ($5017, by JMP)"
|
|
],
|
|
"line": "zp_73 = the unit being ordered"
|
|
},
|
|
"34C8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F708[unit] = authoritative unit flags (facing, side, group)"
|
|
},
|
|
"34CB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear bit 6: an individual move order takes the unit out of its group"
|
|
},
|
|
"34CD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store the flags back"
|
|
},
|
|
"34D0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$4C6B: copy the group bits into the $FB54 display flags"
|
|
},
|
|
"34D3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y = unit index for the destination code below"
|
|
},
|
|
"34D5": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"setUnitDestination - Stores a destination for unit Y. A comcen whose speed option is class 4 (fixed)",
|
|
"has its destination forced back to its own cell; a destination equal to the current cell is stored",
|
|
"with bit 7 set, which marks the unit idle and is mirrored into unitDisplayFlags bit 7; anything else",
|
|
"is clamped to the 40x40 map. The walking waypoint is reset to the unit's current cell (except for the",
|
|
"solo trainer's own units, which keep theirs), and the order cancels any dig-in in progress.",
|
|
"In: Y = unit index, cmdParam1/cmdParam2 zp_74/zp_75 = destination column/row, gamePhase zp_B1,",
|
|
" comcenSpeedClass $92B4 / opponentComcenSpeedClass $92B5, comcenUnit $9236, soloTrainerAtGameStart $92FE",
|
|
"Out: $F7D0/$F834 destination, $FB54 bit 7, $F898/$F8FC waypoint, $F960 bits 5-7 cleared,",
|
|
" $F76C bit 6 cleared; self-modifies the ORA operand at $3521",
|
|
"Called from: the group formation move ($4A31, $4A9B), the destination command ($4D21), the group",
|
|
" order tail ($4C68, by JMP) and by fall-through from applyMoveOrder"
|
|
],
|
|
"line": "zp_B1 = 0 only while the battle is actually running"
|
|
},
|
|
"34D7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "in the setup, film and menu phases the comcen speed rule does not apply"
|
|
},
|
|
"34D9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "unit 49 = player 0's comcen"
|
|
},
|
|
"34DB": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "it is a comcen"
|
|
},
|
|
"34DD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "unit 99 = player 1's comcen"
|
|
},
|
|
"34DF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "not a comcen: nothing special"
|
|
},
|
|
"34E1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92B4 = the local player's COMCEN SPEED option"
|
|
},
|
|
"34E4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9236 = index of the local player's comcen"
|
|
},
|
|
"34E7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "it is our own comcen, use our own option"
|
|
},
|
|
"34E9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92B5 = the opponent's comcen speed class"
|
|
},
|
|
"34EC": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "class 4 = the comcen may not move at all"
|
|
},
|
|
"34EE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "any other class: the ordered destination stands"
|
|
},
|
|
"34F0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "immobile comcen: destination column..."
|
|
},
|
|
"34F3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "...forced to where it already stands"
|
|
},
|
|
"34F5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "and the same for the row"
|
|
},
|
|
"34F8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "zp_75"
|
|
},
|
|
"34FA": {
|
|
"unit": "game/mainProgram0800",
|
|
"block": [
|
|
"Store the destination: equal to the current cell means 'idle', anything else is clamped to",
|
|
"the map, and the idle bit is mirrored into the display flags."
|
|
],
|
|
"line": "destination column"
|
|
},
|
|
"34FC": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F640[unit] = current column"
|
|
},
|
|
"34FF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "different - the unit really has to move"
|
|
},
|
|
"3501": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "destination row"
|
|
},
|
|
"3503": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F6A4[unit] = current row"
|
|
},
|
|
"3506": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "different - the unit really has to move"
|
|
},
|
|
"3508": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "same cell: take the column again"
|
|
},
|
|
"350A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 7 = 'destination reached, nothing to do'"
|
|
},
|
|
"350C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "always taken (bit 7 was just set)"
|
|
},
|
|
"350E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "destination column"
|
|
},
|
|
"3510": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "keep it inside the 40x40 battlefield"
|
|
},
|
|
"3513": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F7D0[unit] = destination column (bit 7 = idle)"
|
|
},
|
|
"3516": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "isolate the idle bit"
|
|
},
|
|
"3518": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patch the ORA # at $3520 with it"
|
|
},
|
|
"351B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$FB54[unit] = display flags"
|
|
},
|
|
"351E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear the old idle bit"
|
|
},
|
|
"3520": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patched: mirror the new idle bit into bit 7"
|
|
},
|
|
"3522": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store the display flags"
|
|
},
|
|
"3525": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "destination row"
|
|
},
|
|
"3527": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clamp it to the map as well"
|
|
},
|
|
"352A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F834[unit] = destination row"
|
|
},
|
|
"352D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$92FE bit 7 = this game is against the solo trainer"
|
|
},
|
|
"3530": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "modem or film game: always reset the waypoint"
|
|
},
|
|
"3532": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "units 50-99 are the trainer's own units"
|
|
},
|
|
"3534": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the trainer maintains their waypoints itself"
|
|
},
|
|
"3536": {
|
|
"unit": "game/mainProgram0800",
|
|
"block": [
|
|
"Reset the walking waypoint to the cell the unit is standing on, keeping the two flag bits",
|
|
"in the top of those bytes."
|
|
],
|
|
"line": "$F898[unit] = waypoint column, bits 6-7 are flags"
|
|
},
|
|
"3539": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "keep only those two flag bits"
|
|
},
|
|
"353B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "waypoint column = the cell the unit is standing on"
|
|
},
|
|
"353E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store it back"
|
|
},
|
|
"3541": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F8FC[unit] = waypoint row, bits 6-7 are flags"
|
|
},
|
|
"3544": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "keep the flag bits"
|
|
},
|
|
"3546": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "waypoint row = current row"
|
|
},
|
|
"3549": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store it back"
|
|
},
|
|
"354C": {
|
|
"unit": "game/mainProgram0800",
|
|
"block": [
|
|
"An order to move cancels any dig-in the unit had started or completed."
|
|
],
|
|
"line": "$F960[unit]: low nibble stun counter, bits 5-7 dig progress"
|
|
},
|
|
"354F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear bits 5-7 - the unit stops digging in"
|
|
},
|
|
"3551": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store it back"
|
|
},
|
|
"3554": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F76C[unit] = type byte"
|
|
},
|
|
"3557": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear bit 6 = no longer dug in / fortified"
|
|
},
|
|
"3559": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store it back"
|
|
},
|
|
"355C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the order is stored"
|
|
},
|
|
"355D": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"clampMapCoord - Clamps a signed map coordinate to the battlefield: negative becomes 0, anything from",
|
|
"40 upwards becomes 39.",
|
|
"In: A = coordinate",
|
|
"Out: A = 0..39",
|
|
"Called from: setUnitDestination ($3510 for the column, $3527 for the row)"
|
|
],
|
|
"line": "already zero or positive"
|
|
},
|
|
"355F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "negative coordinates clamp to column/row 0"
|
|
},
|
|
"3561": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "40 = width and height of the battlefield"
|
|
},
|
|
"3563": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "inside the map"
|
|
},
|
|
"3565": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "39 = last valid column/row"
|
|
},
|
|
"3567": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"3568": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"markAllUnitsVisible - Sets bits 6 and 7 (spotted this cycle, currently visible) of unitEnergy for",
|
|
"all 100 units, i.e. reveals the whole battlefield. Used at the end of a game and whenever no game",
|
|
"is in progress.",
|
|
"In: none",
|
|
"Out: $F9C4[0..99] bits 6-7 set; Y = $FF, A clobbered",
|
|
"Called from: the game reset at $4018 and ageUnitVisibility ($3579, by branch)"
|
|
],
|
|
"line": "unit 99 down to unit 0"
|
|
},
|
|
"356A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F9C4[unit]: bits 0-5 energy, bit 6 spotted, bit 7 visible"
|
|
},
|
|
"356D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "mark it both spotted and visible"
|
|
},
|
|
"356F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store it back"
|
|
},
|
|
"3572": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "previous unit"
|
|
},
|
|
"3573": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "loop over all 100 units"
|
|
},
|
|
"3575": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"3576": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"ageUnitVisibility - Run once per unit-processing cycle, before the spotting passes: every unit that",
|
|
"was spotted during the last cycle (energy bit 6) stays visible (bit 7) and everything else fades",
|
|
"out, and bit 6 is cleared ready for the coming scan. It also resets the unit-scan side filter to",
|
|
"'accept every unit'. When the game is over it simply reveals everything instead.",
|
|
"In: gameEndReason $0BA8, unitEnergyTable $F9C4",
|
|
"Out: $F9C4 visibility bits rewritten, the collectUnitsInRadius filter at $37FF/$3800 set to",
|
|
" compare against 0 with BCC; self-modifies $359C",
|
|
"Called from: finishRound ($4660)"
|
|
],
|
|
"line": "$0BA8 = nonzero once the game has ended"
|
|
},
|
|
"3579": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "game over: show every unit instead of ageing the flags"
|
|
},
|
|
"357B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "compare value 0..."
|
|
},
|
|
"357D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "...into the CMP # of the unit scan filter at $37FE"
|
|
},
|
|
"3580": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "opcode of BCC"
|
|
},
|
|
"3582": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "so the filter at $3800 accepts every unit index"
|
|
},
|
|
"3585": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "unit 0 upwards"
|
|
},
|
|
"3587": {
|
|
"unit": "game/mainProgram0800",
|
|
"block": [
|
|
"Shift each unit's visibility: bit 6 (spotted last cycle) becomes bit 7 (visible now)."
|
|
],
|
|
"line": "assume the unit stays visible"
|
|
},
|
|
"3589": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F9C4[unit]"
|
|
},
|
|
"358C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 6 = it was spotted during the last scan cycle"
|
|
},
|
|
"358E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "it was - keep it visible"
|
|
},
|
|
"3590": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "it was not - it fades out of sight"
|
|
},
|
|
"3592": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "read the byte again"
|
|
},
|
|
"3595": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "keep the energy value, drop both visibility bits"
|
|
},
|
|
"3597": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patch the ORA # at $359B with it"
|
|
},
|
|
"359A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$80 (visible) or $00 (hidden)"
|
|
},
|
|
"359B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patched energy value"
|
|
},
|
|
"359D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 7 = visible, bit 6 cleared ready for this cycle's scan"
|
|
},
|
|
"35A0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "next unit"
|
|
},
|
|
"35A1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "100 units"
|
|
},
|
|
"35A3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "loop"
|
|
},
|
|
"35A5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "done"
|
|
},
|
|
"35A6": {
|
|
"unit": "game/mainProgram0800",
|
|
"block": [
|
|
"sightRangeByType - base range in cells, indexed by unit type for the spotting pass (entries",
|
|
"0-4) and by type+5 for the attack pass (entries 5-9). The terrain bonus below is added on top",
|
|
"and the sum is capped at 10."
|
|
],
|
|
"line": "spotting: GRUNT 3, RIDER 3, BOOMER 3, SPY 5, COMCEN 3; attack: GRUNT 3, RIDER 3, BOOMER 6"
|
|
},
|
|
"35AE": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "attack range of SPY 5 and COMCEN 3 (entries 8 and 9)"
|
|
},
|
|
"35B0": {
|
|
"unit": "game/mainProgram0800",
|
|
"block": [
|
|
"rangeDistanceSqTable - r*(r+1) for r = 0..10. scanVisibleEnemies compares the squared",
|
|
"distance of a candidate against this, which rounds the square search box into a circle."
|
|
],
|
|
"line": "r*(r+1) for r = 0..7: 0, 2, 6, 12, 20, 30, 42, 56"
|
|
},
|
|
"35B8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "r*(r+1) for r = 8, 9, 10: 72, 90, 110"
|
|
},
|
|
"35BB": {
|
|
"unit": "game/mainProgram0800",
|
|
"block": [
|
|
"terrainSightBonusTable - extra range given by the terrain class under the observer",
|
|
"(0-7); doubled on the spotting pass, counted once on the attack pass."
|
|
],
|
|
"line": "classes 0-7: 0, 0, 0, 1, 1, 2, 2, 0 extra cells of range"
|
|
},
|
|
"35C3": {
|
|
"unit": "game/mainProgram0800",
|
|
"routine": [
|
|
"scanVisibleEnemies - Builds the list of enemy units that unit Y can see (X bit 7 clear, the spotting",
|
|
"pass) or can shoot at (X bit 7 set, the attack-target pass). The effective range is",
|
|
"sightRangeByType[type, +5 when attacking] plus the terrain bonus of the cell the unit stands on",
|
|
"(doubled while spotting), capped at 10 cells. collectUnitsInRadius fills $0400 with the enemy units",
|
|
"in the square and $0432 with their squared distances; this routine then walks that list and strikes",
|
|
"off ($0400[n] = $FF) every candidate that is out of range, dead, not yet visible (attack pass),",
|
|
"protected by the spy/hidden rules (spotting pass) or hidden behind a ridge. $0464[n] receives the",
|
|
"direction 0-3 from the scanner to the candidate. Candidates that are not in the unit's preferred",
|
|
"direction (zp_6B) are pushed one step further away, which biases a unit towards the target it is",
|
|
"already facing. The first sighting of an enemy spy or comcen queues status message $0F / $0D.",
|
|
"Only the head of the routine ($35C3-$366E) belongs to this chunk; it continues to $3745.",
|
|
"In: X = pass (bit 7: 0 = spotting, 1 = attack targets), Y = the scanning unit; unit arrays, the map,",
|
|
" the terrain class table at $077E",
|
|
"Out: $0400 candidate list (entries struck off with $FF), $0432 squared distances, $0464 directions,",
|
|
" scanResultCount zp_2F = index of the last entry ($FF = none), fireTargetDistance $91F1 = range,",
|
|
" scanUnitTerrain/$9227, scanUnitType/$9228, scanUnitTerrainHeight/$9229; self-modifies $35F9",
|
|
" (range table index) and $362B (distance limit)",
|
|
"Called from: the boomer target search ($3C8A) and the two scan passes of processUnitStep ($43AA",
|
|
" spotting, $43DC attack targets)"
|
|
],
|
|
"line": "zp_20 = pass flag: bit 7 clear = who can I see, bit 7 set = who can I shoot at"
|
|
},
|
|
"35C5": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "zp_21 = the unit doing the scanning"
|
|
},
|
|
"35C7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F76C[unit] = type byte"
|
|
},
|
|
"35CA": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "unit type 0-4 (GRUNT, RIDER, BOOMER, SPY, COMCEN)"
|
|
},
|
|
"35CC": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9228 = type of the scanning unit, used by the spy/hidden rules below"
|
|
},
|
|
"35CF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "which pass is this?"
|
|
},
|
|
"35D1": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "spotting pass uses sightRangeByType entries 0-4"
|
|
},
|
|
"35D3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clear carry before shifting to the attack half of the table"
|
|
},
|
|
"35D4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "attack pass uses entries 5-9"
|
|
},
|
|
"35D6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patch the LDX # at $35F8 with that table index"
|
|
},
|
|
"35D9": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$378B: set the collectUnitsInRadius filter to 'units of the other side only'"
|
|
},
|
|
"35DC": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$FAF0[unit] = the terrain tile hidden under the unit"
|
|
},
|
|
"35DF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9227 = that tile, kept for the callers"
|
|
},
|
|
"35E2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "index it"
|
|
},
|
|
"35E3": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$077E[tile] = terrain class 0-7"
|
|
},
|
|
"35E6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "index the class tables with it"
|
|
},
|
|
"35E7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$38B3[class] = height, used by the line-of-sight walk"
|
|
},
|
|
"35EA": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$9229 = height the observer is standing at"
|
|
},
|
|
"35ED": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "extra range for standing on high ground"
|
|
},
|
|
"35F0": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "flat ground: no bonus"
|
|
},
|
|
"35F2": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "which pass?"
|
|
},
|
|
"35F4": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "attack pass: the bonus counts once"
|
|
},
|
|
"35F6": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "spotting pass: high ground doubles the terrain bonus"
|
|
},
|
|
"35F7": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "prepare the addition"
|
|
},
|
|
"35F8": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "range table index, patched at $35D6"
|
|
},
|
|
"35FA": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "base range for this unit type and pass"
|
|
},
|
|
"35FD": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "10 cells is the hard limit"
|
|
},
|
|
"35FF": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "below it"
|
|
},
|
|
"3601": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "clamp to 10"
|
|
},
|
|
"3603": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$91F1 = effective range of this scan"
|
|
},
|
|
"3606": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "index the squared-distance table with it"
|
|
},
|
|
"3607": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "r*(r+1) = the squared distance a target must stay below"
|
|
},
|
|
"360A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patch the CMP # at $362A with that limit"
|
|
},
|
|
"360D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F640[unit] = the scanner's column"
|
|
},
|
|
"3610": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F6A4[unit] = its row"
|
|
},
|
|
"3613": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y = centre row"
|
|
},
|
|
"3614": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "half width of the square to search = the range"
|
|
},
|
|
"3617": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$37AA: gather the enemy units in that square into $0400 / $0432"
|
|
},
|
|
"361A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "zp_2F = index of the last candidate ($FF if none)"
|
|
},
|
|
"361C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "zp_18 = index of the candidate being examined"
|
|
},
|
|
"361E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "at least one candidate"
|
|
},
|
|
"3620": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "nothing in range: return with zp_2F = $FF"
|
|
},
|
|
"3623": {
|
|
"unit": "game/mainProgram0800",
|
|
"block": [
|
|
"Candidate loop: zp_18 walks the list from the last entry down to entry 0. A candidate that",
|
|
"fails any test is struck off at $3735 by writing $FF into $0400[n]."
|
|
],
|
|
"line": "$0400[n] = index of the candidate unit"
|
|
},
|
|
"3626": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "Y = candidate unit"
|
|
},
|
|
"3627": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0432[n] = squared distance from the scanner"
|
|
},
|
|
"362A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "patched at $360A with r*(r+1) for the effective range"
|
|
},
|
|
"362C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "inside the circle"
|
|
},
|
|
"362E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "outside it: strike this candidate off the list"
|
|
},
|
|
"3631": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the scanning unit"
|
|
},
|
|
"3633": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$375D: set up the line walker from scanner to candidate; A = direction 0-3"
|
|
},
|
|
"3636": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "candidate index again"
|
|
},
|
|
"3638": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$0464[n] = direction of this candidate from the scanner"
|
|
},
|
|
"363B": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "zp_6B = the direction the unit prefers (where its current target is)"
|
|
},
|
|
"363D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "same direction: no penalty"
|
|
},
|
|
"363F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "how many candidates were found"
|
|
},
|
|
"3641": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "index 0 means a single candidate"
|
|
},
|
|
"3643": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "only one candidate: no penalty, take it whatever the direction"
|
|
},
|
|
"3645": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "squared distance again"
|
|
},
|
|
"3648": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "squared distance below 3 = an adjacent or diagonal cell"
|
|
},
|
|
"364A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "point blank: no penalty"
|
|
},
|
|
"364C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "otherwise..."
|
|
},
|
|
"364D": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "...count it as one step further away than it is"
|
|
},
|
|
"364F": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "store the penalised distance back"
|
|
},
|
|
"3652": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "did the penalty push it out of range?"
|
|
},
|
|
"3655": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "yes: strike it off"
|
|
},
|
|
"3657": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "$F76C[candidate] = type byte"
|
|
},
|
|
"365A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "bit 7 = destroyed: strike it off"
|
|
},
|
|
"365C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "candidate type 0-4"
|
|
},
|
|
"365E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "which pass?"
|
|
},
|
|
"3660": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "spotting pass: apply the spy and hidden-unit rules"
|
|
},
|
|
"3662": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "attack pass: $F9C4[candidate] bit 7 = the target is currently visible"
|
|
},
|
|
"3665": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "you cannot shoot at something you have not spotted"
|
|
},
|
|
"3667": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "the range table index of this scan"
|
|
},
|
|
"366A": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "index 7 = BOOMER attacking; 5 and 6 are GRUNT and RIDER"
|
|
},
|
|
"366C": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "grunts and riders must have a clear line of sight"
|
|
},
|
|
"366E": {
|
|
"unit": "game/mainProgram0800",
|
|
"line": "boomers, spies and comcens fire without one: accept this candidate"
|
|
}
|
|
},
|
|
"dataTypes": {
|
|
"3237": [
|
|
"byte",
|
|
2
|
|
],
|
|
"32DA": [
|
|
"byte",
|
|
16
|
|
],
|
|
"33C2": [
|
|
"byte",
|
|
6
|
|
],
|
|
"35A6": [
|
|
"byte",
|
|
10
|
|
],
|
|
"35B0": [
|
|
"byte",
|
|
11
|
|
],
|
|
"35BB": [
|
|
"byte",
|
|
8
|
|
]
|
|
},
|
|
"zpComments": {
|
|
"18": "general scratch: multiply/divide operand, character row in the text plotters, min column returned by computeGroupBounds, sprite pixel column in buildGroupFormationSprite, index of the candidate under test in scanVisibleEnemies",
|
|
"19": "general scratch, partner of scratch18: product/quotient, character column in the text plotters, min row returned by computeGroupBounds, sprite pixel row in buildGroupFormationSprite",
|
|
"1A": "general scratch: third math temp, right column of a frame box, unit loop counter in buildGroupFormationSprite, low byte of the trainer's 16-bit scores",
|
|
"1B": "general scratch: bottom row of a frame box, division remainder (lo), max column from computeGroupBounds, the group-membership byte units are matched against in buildGroupFormationSprite",
|
|
"20": "general scratch: half width in magnifyWindow2x, the pass flag of scanVisibleEnemies (bit 7 set = attack-target pass, clear = spotting pass), unit type being counted on the STATS tab",
|
|
"21": "general scratch: half height in magnifyWindow2x, index of the unit doing the scan in scanVisibleEnemies, terrain neighbour mask in the map generator",
|
|
"92": "line stepper: current row - a map row while walking the battlefield, but a sprite pixel row 0-20 while a line is drawn into a sprite shape ($306C/$308A/$30A1); also the cursor row of the battlefield view",
|
|
"93": "line stepper: current column - a map column, or a sprite pixel column 0-23 while a line is drawn into a sprite shape; also the cursor column of the battlefield view",
|
|
"94": "line stepper: target row (a map row, or a sprite pixel row when the line is being drawn inside a sprite shape)",
|
|
"95": "line stepper: target column (a map column, or a sprite pixel column when the line is being drawn inside a sprite shape)",
|
|
"98": "pointer (lo) to the sprite shape byte being modified by plotSpritePixel; loadDirectionShapeSprite reuses it as the $0200 + shape*64 copy source"
|
|
}
|
|
}
|