
Наверно, как и большинство игроков, вы стали первоклассным специалистом в приземлении на авианосец в игре Top Gun для NES. Но если вы всё же относитесь к тому меньшинству, которое так и не освоило этот навык, то вам повезло: я выполнил небольшой реверс-инжиниринг и разобрался, как именно работает приземление. Надеюсь, в следующем вылете вы справитесь идеально!
tl;dr: высота должна находиться в диапазоне от 100 до 299, скорость должна находиться в диапазоне от 238 до 337 (включая оба значения), а в конце процесса самолёт по горизонтали должен нацелен на авианосец.
Если вы не играли в Top Gun, то напомню, что этап приземления в конце уровня выглядел вот так:

Удобно, что игра подсказывает находиться посередине приемлемого диапазона текстом «Alt. 200 / Speed 288» на многофункциональном дисплее. Высотой (Altitude) и скоростью (speed) управляют дроссель и угол тангажа. На дисплее нет индикатора рыскания (движения влево/вправо), но если игрок находится вне допустимого диапазона, игра выводит подсказку (например, «Right! Right!»). Диапазоны скорости и рыскания довольно узкие, поэтому следует сосредоточиться на них: диапазон высоты гораздо шире.
Примерно спустя минуту игра проверяет состояние самолёта и воспроизводит небольшую катсцену, демонстрирующую или идеальное приземление, или дорогостоящий фейерверк. В любом случае затем отображается сообщение «Миссия выполнена» («Mission Accomplished!»), а игра переходит к следующему уровню (в конце концов, самолёт купили не вы, а налогоплательщики):

Информация для задротов
Важные адреса памяти:
Адрес |
Содержимое |
Приемлемый диапазон (включая указанные значения) |
|---|---|---|
$40-$41 |
Скорость, хранящаяся в двоично-десятичной кодировке (BCD) |
238 - 337 |
$3D-$3E |
Высота, хранящаяся в BCD |
100 - 299 |
$FD |
Рыскание в диапазоне от -32 до +32 |
0 - 7 |
$9E |
Результат проверки состояния приземления |
0; другие значения меняют траекторию самолёта в катсцене с аварией |
Скорость и высота хранятся в виде двоично-десятичного кода, вероятно, для упрощения рендеринга текста на дисплее. Например, число 1234 хранится в виде 4660 (то есть в шестнадцатеричном 0x1234).
Функция по адресу $B6EA выполняет проверку состояния и записывает результат в $9E. Если вы просто хотите впечатлить друзей и не собираетесь это практиковать, то введите код AEPETA Game Genie, гарантированно обеспечивающий вам приземление, которым могли бы гордиться Мэверик и Гусь.
Вот мой дизассемблированный код с аннотациями:
landing_skill_check:
06:B6EA: LDA $3E ; Загрузка разряда сотен высоты
06:B6EC: BEQ $B724 ; Ветвление, если разряд сотен == 0 (высота < 100)
06:B6EE: CMP #$03
06:B6F0: BCS $B720 ; Ветвление, если разряд сотен >= 3 (высота >= 300)
06:B6F2: LDA $41
06:B6F4: CMP #$04
06:B6F6: BCS $B720 ; Ветвление, если разряд сотен >= 04 (скорость >= 400)
06:B6F8: CMP #$02
06:B6FA: BCC $B724 ; Ветвление, если разряд сотен < 02 (скорость < 200)
06:B6FC: BEQ $B706 ; Ветвление, если разряд сотен == 02 (скорость >= 200 && скорость <= 299)
speed_300s:
06:B6FE: LDA $40 ; Загрузка разрядов ниже сотен скорости
06:B700: CMP #$38
06:B702: BCS $B720 ; Ветвление, если разряды ниже сотен >= 38 (скорость >= 338)
06:B704: BCC $B70C ; Ветвление, если разряды ниже сотен < 38 (скорость < 338)
speed_200s:
06:B706: LDA $40
06:B708: CMP #$38
06:B70A: BCC $B724 ; Ветвление, если скорость < 238
speed_ok:
06:B70C: LDA $FD ; Загрузка рыскания
06:B70E: BMI $B718 ; Ветвление, если рыскание < 0 (слишком далеко налево)
06:B710: CMP #$08
06:B712: BCS $B71C ; Ветвление, если рыскание >= 8 (слишком далеко направо)
06:B714: LDX #$00 ; Скорость нормальная, рыскание нормальное; 0 == успех
06:B716: BEQ $B726 ; Ветвление к return
too_far_left:
06:B718: LDX #$02
06:B71A: BNE $B726
too_far_right:
06:B71C: LDX #$04
06:B71E: BNE $B726
too_fast_or_too_high:
06:B720: LDX #$08
06:B722: BNE $B726
too_slow_or_too_low:
06:B724: LDX #$04
return:
06:B726: STX $9E
06:B728: RTS
А теперь запускайте игру и зацепитесь наконец за этот трос.
nin-jin
И никого не смущает, что самолёт смотрит носом вниз, а на дисплее показывается носом вверх.