{
 "_comment": "generated by tools/mergeSurvey.py from survey/*.json - do not edit by hand",
 "notes": {
  "EE00": {
   "routine": [
    "flyTrainerDroneStep - One flight step of the solo-trainer AI's drone. The communications module build 1 (T35) JSRs here from $E0A5 once per command exchange, but only while this track-29 s4-5 page is the resident $EE00 image (droneOverlayState $8977 bit 7 set). It returns at once when droneFlags $92F9 bit 7 says the drone has already arrived or been shot down; otherwise it decrements the drone's fuel counter $8973 and, when that goes negative, fabricates the 1-byte command $8F (drone released) in the received-packet buffer and returns. Any other case falls through into pickDroneAimPointAndDecide.",
    "In:  $92F9 droneFlags, $8973 aiDroneFuel, $8974/$8975 drone cell, $8976 target unit index, $8978 detonate threshold, map/unit arrays $F640/$F6A4/$F960",
    "Out: fabricated opponent packet in rxPacketBuffer $E020.. with rxPacketLength $E01E = 1 ($8F), 3 ($8E col row) or 4 ($8D heading col row); $8973 decremented; on the move path $896F, $8974, $8975 updated; zp_18,zp_19,zp_1C,zp_1D,zp_22,zp_24,zp_27,zp_28,zp_92-zp_95 clobbered"
   ],
   "unit": "game/droneAiEE00"
  },
  "EE15": {
   "routine": [
    "pickDroneAimPointAndDecide - Fall-through block (branch target of $EE08 only): decides between blowing the drone up here and flying one more cell. It measures the distance from the drone to its target unit ($8976); inside 6 cells and with both drone coordinates on the map it scores the 2x2 block under the drone with scoreTargetBlock ($E9A6) and detonates when the score reaches aiDroneDetonateThreshold $8978, or only 3/4 of it when the target unit is stunned ($F960 low nibble non-zero). Otherwise it scores the four 2x2 blocks that touch the target's cell, leaves the best corner in zp_95/zp_94, sets the line-stepper start from the drone position (clamping a negative coordinate to 0 and shifting the end point by the same amount) and calls getStepDirection ($E80E); a stepper that finds no direction (drone already on the aim cell) also detonates.",
    "In:  $8976, $F640/$F6A4 unit col/row, $8974/$8975 drone cell, $8978, $F960, zp_1C = 0 on entry",
    "Out: zp_1C best block score, zp_1D best player unit, zp_94/zp_95 aim cell, zp_92/zp_93 line start, Y = heading 0-7 from getStepDirection; falls into emitDroneDetonateCommand or maybeJinkDroneHeading"
   ],
   "unit": "game/droneAiEE00"
  },
  "EE2D": {
   "routine": [
    "midCheckDroneOnMapEE2D - NOT an entry point in this image: $EE2D is the middle of pickDroneAimPointAndDecide (the 'ldx $8974 / bmi' on-map test before scoreTargetBlock). The sub_ prefix is imported from the other code images that share these addresses (comm build 2 has a real routine at $EE2D).",
    "In:  -",
    "Out: -"
   ],
   "unit": "game/droneAiEE00"
  },
  "EE55": {
   "routine": [
    "midStoreDetonateThresholdEE55 - NOT an entry point in this image: $EE55 is the 'sta zp_18' that stores the 3/4 detonate threshold for a stunned target inside pickDroneAimPointAndDecide. The label comes from the other images of this page.",
    "In:  -",
    "Out: -"
   ],
   "unit": "game/droneAiEE00"
  },
  "EE85": {
   "routine": [
    "midScanDiagonalBlockEE85 - NOT an entry point in this image: $EE85 is the 'dey' inside the four-block scan around the target cell (scoring the block at col-1,row-1). The label is an artifact of the T35/T34 images of this page.",
    "In:  -",
    "Out: -"
   ],
   "unit": "game/droneAiEE00"
  },
  "EEED": {
   "routine": [
    "midCheckFuelForJinkEEED - NOT an entry point in this image: $EEED is the 'lda $8973 / cmp #$0C' fuel test inside maybeJinkDroneHeading. The label is an artifact of the other images of this page.",
    "In:  -",
    "Out: -"
   ],
   "unit": "game/droneAiEE00"
  },
  "EEB6": {
   "routine": [
    "emitDroneDetonateCommand - Detonation path (branch target of $EE3F and $EE5B): writes command $8E plus the drone's current cell, mirrored with mirrorBlockCornerForOpponent ($EA38), into the fake received packet and sets its length to 3. The engine's cmdDroneDetonate ($5336) mirrors the coordinates back and plays the blast.",
    "In:  $8974/$8975 drone cell",
    "Out: $E020=$8E, $E021/$E022 = mirrored col/row, $E01E=3; X/Y clobbered; returns"
   ],
   "unit": "game/droneAiEE00"
  },
  "EED0": {
   "routine": [
    "maybeJinkDroneHeading - Flight path (branch target of $EEB4): stores the heading returned by getStepDirection in zp_19 and then, only when the human player still has missiles ($92B0), the drone's cell falls inside the radar window drawn around the human's comcen (mapCellToRadarGrid $7A13 with $9236 unchanged), the radar/drone screen is the one on show ($90FB = 1), the drone still has at least 12 fuel and is at least 3 cells away from its aim point, replaces the heading 2 times in 3 (nextGameRandom >= $56) with a random 0-7 value. Inferred purpose: an evasive weave while the player can watch the drone and shoot it down with a missile strike (confidence medium).",
    "In:  Y = heading from $E80E, $92B0 missilesLeft, $8974/$8975, $9236 comcenUnit, $90FB currentScreen, $8973, zp_94/zp_95 aim cell",
    "Out: zp_19 = desired heading 0-7; zp_22/zp_24/zp_27/zp_28 clobbered; falls into steerDroneAndEmitMove",
    "(confidence: medium)"
   ],
   "unit": "game/droneAiEE00"
  },
  "EF0F": {
   "routine": [
    "steerDroneAndEmitMove - Turns the drone one step toward the desired heading and reports the move. The code is a copy of overlay B's steerDrone ($731E) with the AI's variables and without the turn sound: $896F is rotated by +1 or -1 (the short way round, then AND #$07) toward zp_19, converted through headingToDirectionTable ($7316), directionDeltaTable ($20F0) and diagonalDirectionTable ($1FB2) into dx/dy and added to $8974/$8975. It then emits command $8D with (heading+4)&7 - the heading as the mirrored map sees it - and the new cell mirrored by $EA38, length 4. Note that neither coordinate is clamped, so the drone can walk off the map.",
    "In:  zp_19 desired heading, $896F current heading, $8974/$8975 drone cell",
    "Out: $896F, $8974, $8975 updated; $E020=$8D, $E021=(heading+4)&7, $E022/$E023 mirrored col/row, $E01E=4; returns"
   ],
   "unit": "game/droneAiEE00"
  },
  "EF9E": {
   "routine": [
    "droneDistanceToCell - Helper called at $EE26 and $EEFC: copies the drone's cell $8974/$8975 into the distance routine's second point zp_27/zp_28 and tail-jumps to cellDistance ($E82A), which returns the integer distance between (zp_22,zp_24) and the drone in A and X. Y is preserved, which is what lets the caller keep the target unit index in Y across the call.",
    "In:  zp_22/zp_24 = cell to measure against, $8974/$8975 drone cell",
    "Out: A = X = distance 0-16, zp_27/zp_28 = drone cell; Y preserved"
   ],
   "unit": "game/droneAiEE00"
  },
  "EFAB": {
   "unit": "game/droneAiEE00",
   "block": [
    "staleCommTailBytes: unknown, 37 bytes. $EFAB-$EFCF: 37 bytes that are byte-for-byte identical in all four images of this address range (comm build 1 T35, comm build 2 T34, the track-29 s0-3 $EC00 sub-overlay and this one). In build 1 they are the tail of the AI's drone target picker (inc zp_1F / cmp #$0F / ... / sta $8979 / rts) and in build 2 they are the middle of the message 'INSERT DATA DISK AND PRESS SPACE.' ($EFAF, with the 4-character disk name patched into $EFB6). Nothing in this image reaches them - they are carried along only so that the shared strings below land at their fixed addresses."
   ]
  },
  "EFD0": {
   "unit": "game/droneAiEE00",
   "block": [
    "msgDataDiskName: text, 4 bytes. 'DATA' - the 4-character disk name that overlay A's promptInsertDataDisk ($81B2) patches into the INSERT-DISK message. The disassembler merges $EFD0-$EFE1 into one label msgDatagamecustomOff4; it is really three strings."
   ]
  },
  "EFD4": {
   "unit": "game/droneAiEE00",
   "block": [
    "msgGameDiskName: text, 4 bytes. 'GAME' - the disk name used by overlay A's promptInsertGameDisk ($81A5)."
   ]
  },
  "EFD8": {
   "unit": "game/droneAiEE00",
   "block": [
    "msgCustomOff: text, 10 bytes. 'CUSTOM OF','F'|$80 - installed as message slot $1E by overlay A ($EFD8), which also points its ON/OFF patch at $EFDF ('OFF')."
   ]
  },
  "EFE2": {
   "unit": "game/droneAiEE00",
   "block": [
    "msgDestroyOff: text, 11 bytes. 'DESTROY OF','F'|$80 - message slot $1E for the DESTROY toggle; overlay A patches ON/OFF at $EFEA."
   ]
  },
  "EFED": {
   "unit": "game/droneAiEE00",
   "block": [
    "msgAccepted: text, 8 bytes. 'ACCEPTE','D'|$80 - printed centred on row 15 by overlay A when the fire button confirms a value."
   ]
  },
  "EFF5": {
   "unit": "game/droneAiEE00",
   "block": [
    "trailingPadEFF5: unknown, 11 bytes. $C0,$DF,$00,$FF,$00,$FF,$00,$FF,$00,$FF,$FF - unreferenced trailing bytes, the same in every image of this page except the last byte ($FF here and in build 1, $00 in build 2). Probably padding left by the mastering system."
   ]
  }
 }
}