; ───────────────────────────────────────────────────────────────────────────
; Processor:        К1801ВМ1
; Target assembler: Turbo8 Cross Assembler

; оптимизированный вариант, выпрямленный код
; выкинуты всякие проверки целостности и прочая фигня
; файл сделан автономным

; ═══════════════════════════════════════════════════════════════════════════
AtCtrlProc      = 24        ; функция обработки элемента управления
                            ; в меню задания управления
CtrlCnt         = 26        ; счётчик пунктов элементов управления
                            ; в меню задания управления
Temp1           = 126       ; временная переменная
AS              = 160       ; Адрес символа
FON             = 212       ; Фон экрана
MASCW           = 214       ; Маска цвета
Temp2           = 312       ; флаг добавления босса 0 - надо !0 - не надо, его только что убили


TerrainBuffer   = 36000     ; буфер поверхности в памяти
TopScreen       = 50000     ; верх игрового экрана
BottomScreen    = 76000     ; низ игрового экрана
; некоторые адреса экрана
PanelOscAddr    = 41456
PanelGraphAddr  = 41312
PanelIndicAddr  = 45054
PanelDiagrAddr  = 44634
PanelPriseAddr  = 43042
PanelShieldAddr = 43402
PanelScoreAddr  = 46042
PanelLivesAddr  = 42014
StageStrAddr    = 61026

                jmp     Prepare$
; Спрайт шириной 20 байтов, высотой 20 строк
SprGround:      .byte 0, 0, 0, 0, 360, 377, 303, 3, 300, 377, 377, 0, 0, 377, 0, 0
                .byte 0, 0, 0, 0, 74, 63, 77, 77, 374, 63, 363, 3, 360, 377, 17, 0
                .byte 0, 0, 0, 360, 303, 314, 314, 300, 317, 314, 314, 3, 374, 60, 377, 0
                .byte 0, 377, 0, 377, 77, 63, 3, 314, 77, 63, 363, 377, 300, 314, 300, 3
                .byte 360, 377, 317, 377, 377, 0, 0, 360, 303, 14, 377, 377, 17, 63, 63, 17
                .byte 374, 314, 377, 77, 363, 303, 77, 360, 60, 303, 317, 314, 77, 314, 14, 17
                .byte 77, 63, 77, 317, 314, 363, 377, 3, 300, 360, 63, 63, 77, 60, 0, 60
                .byte 314, 14, 74, 60, 63, 317, 314, 17, 14, 360, 314, 314, 374, 14, 360, 377
                .byte 63, 363, 377, 303, 300, 14, 63, 0, 0, 3, 63, 63, 374, 0, 377, 377
                .byte 314, 374, 377, 17, 14, 300, 14, 377, 17, 0, 0, 14, 60, 360, 377, 363
                .byte 3, 77, 63, 77, 0, 3, 303, 377, 377, 360, 60, 300, 377, 374, 317, 314
                .byte 77, 317, 314, 74, 14, 300, 360, 63, 377, 3, 0, 374, 377, 317, 63, 63
                .byte 0, 77, 0, 0, 0, 0, 360, 314, 314, 17, 3, 77, 63, 77, 314, 14
                .byte 300, 17, 374, 377, 300, 60, 74, 63, 63, 77, 300, 317, 314, 74, 63, 60
                .byte 314, 300, 377, 377, 17, 0, 314, 300, 300, 60, 300, 63, 63, 363, 14, 3
                .byte 0, 360, 63, 363, 77, 14, 3, 14, 14, 303, 360, 63, 314, 360, 60, 0
; спрайт размером 10 х 20
SprGround3:     .byte 0, 0, 0, 374, 77, 0, 0, 0
                .byte 0, 0, 300, 3, 300, 3, 0, 0
                .byte 0, 0, 60, 360, 0, 14, 0, 0
                .byte 0, 0, 14, 77, 0, 60, 0, 0
                .byte 0, 0, 314, 3, 0, 60, 0, 0
                .byte 0, 0, 303, 0, 0, 300, 0, 0
                .byte 0, 0, 63, 0, 0, 300, 0, 0
                .byte 0, 0, 3, 0, 0, 300, 0, 0
                .byte 0, 374, 77, 0, 0, 374, 77, 0
                .byte 300, 3, 300, 3, 300, 3, 300, 3
                .byte 60, 360, 0, 14, 60, 360, 0, 14
                .byte 14, 77, 0, 60, 14, 77, 0, 60
                .byte 314, 3, 0, 60, 314, 3, 0, 60
                .byte 303, 0, 0, 300, 303, 0, 0, 300
                .byte 63, 0, 0, 300, 63, 0, 0, 300
                .byte 3, 0, 0, 300, 3, 0, 0, 300
; спрайт размером 10 х 20
SprGround2:     .byte 0, 200, 2, 0, 240, 0, 0, 0
                .byte 0, 0, 12, 50, 200, 2, 0, 0
                .byte 0, 0, 50, 50, 200, 2, 0, 0
                .byte 0, 0, 50, 50, 200, 12, 0, 0
                .byte 0, 0, 240, 240, 200, 12, 0, 0
                .byte 0, 0, 240, 240, 200, 12, 240, 0
                .byte 0, 0, 240, 240, 200, 12, 50, 0
                .byte 0, 0, 240, 250, 202, 212, 12, 0
                .byte 0, 0, 250, 250, 202, 242, 2, 14
                .byte 3, 0, 50, 252, 242, 250, 302, 60
                .byte 300, 0, 52, 252, 242, 250, 300, 60
                .byte 14, 3, 52, 252, 240, 250, 0, 300
                .byte 60, 3, 52, 252, 50, 52, 374, 300
                .byte 60, 374, 250, 250, 202, 52, 363, 317
                .byte 340, 302, 250, 250, 242, 12, 314, 74
                .byte 14, 317, 240, 250, 242, 212, 60, 63
; ───────────────────────────────────────────────────────────────────────────
; Спрайт размером 6 х 11 - самолётик
SprFlight:      .byte 74, 3, 0, 0, 0, 0
                .byte 374, 14, 0, 0, 0, 0
                .byte 374, 63, 3, 0, 0, 0
                .byte 360, 17, 360, 77, 0, 0
                .byte 0, 300, 317, 303, 3, 0
                .byte 74, 374, 77, 3, 74, 0
                .byte 300, 77, 374, 374, 377, 63
                .byte 374, 303, 363, 63, 63, 0
                .byte 0, 360, 303, 317, 0, 0
; ───────────────────────────────────────────────────────────────────────────
; это 5 спрайтов размером 2 х 10 - эффект защитного поля
SprEffect1:     .word ^B0000000000000000
                .word ^B0000000011000000
                .word ^B0000110000001100
                .word ^B0000000011000000
                .word ^B0011001100110011
                .word ^B0000000011000000
                .word ^B0000110000001100
                .word ^B0000000011000000

SprEffect2:     .word ^B0000000000000000
                .word ^B0000000010000000
                .word ^B0000000000000000
                .word ^B0000001000100000
                .word ^B0010000010000010
                .word ^B0000001000100000
                .word ^B0000000000000000
                .word ^B0000000010000000

SprEffect3:     .word ^B0000000000000000
                .word ^B0000000000000000
                .word ^B0000000001000000
                .word ^B0000000000000000
                .word ^B0000010001000100
                .word ^B0000000000000000
                .word ^B0000000001000000
                .word ^B0000000000000000

SprEffect4:     .word ^B0000000000000000
                .word ^B0000000000000000
                .word ^B0000000000000000
                .word ^B0000001100110000
                .word ^B0000000011000000
                .word ^B0000001100110000
                .word ^B0000000000000000
                .word ^B0000000000000000

SprEffect5:     .word ^B0000000000000000
                .word ^B0000000000000000
                .word ^B0000000000000000
                .word ^B0000000000000000
                .word ^B0000000010000000
                .word ^B0000000000000000
                .word ^B0000000000000000
                .word ^B0000000000000000
; ───────────────────────────────────────────────────────────────────────────
; Спрайты размером 4 х 20
SprEnemy1:      .byte 0, 0, 120, 1      ; Trap 0
                .byte 0, 0, 124, 4
                .byte 120, 5, 124, 20
                .byte 124, 125, 120, 20
                .byte 0, 125, 1, 0
                .byte 377, 24, 121, 25
                .byte 17, 124, 124, 121
                .byte 17, 124, 124, 101
                .byte 17, 124, 124, 101
                .byte 17, 24, 124, 101
                .byte 17, 24, 121, 20
                .byte 0, 5, 1, 0
                .byte 124, 121, 120, 20
                .byte 100, 25, 125, 20
                .byte 0, 0, 5, 4
                .byte 0, 0, 124, 1
SprEnemy2:      .byte 0, 0, 334, 1      ; Trap 1
                .byte 0, 300, 167, 67
                .byte 0, 334, 335, 35
                .byte 300, 163, 163, 164
                .byte 360, 300, 315, 321
                .byte 74, 100, 107, 163
                .byte 0, 320, 314, 321
                .byte 167, 167, 103, 60
                .byte 335, 334, 0, 64
                .byte 164, 3, 300, 15
                .byte 0, 40, 63, 0
                .byte 0, 12, 0, 52
                .byte 200, 212, 52, 212
                .byte 200, 242, 212, 200
                .byte 40, 240, 202, 50
                .byte 200, 212, 52, 0
SprEnemy3:      .byte 0, 377, 374, 0    ; Trap 2
                .byte 300, 317, 374, 3
                .byte 300, 0, 74, 3
                .byte 0, 77, 0, 0
                .byte 310, 63, 77, 77
                .byte 312, 317, 77, 377
                .byte 312, 300, 377, 314
                .byte 2, 317, 317, 74
                .byte 310, 77, 77, 0
                .byte 300, 377, 0, 74
                .byte 312, 63, 74, 77
                .byte 12, 77, 77, 63
                .byte 12, 0, 17, 17
                .byte 50, 2, 0, 0
                .byte 200, 212, 240, 0
                .byte 0, 52, 52, 0
SprEnemy4:      .byte 0, 360, 377, 0    ; Trap 3
                .byte 300, 377, 374, 17
                .byte 0, 0, 377, 363
                .byte 0, 0, 377, 17
                .byte 0, 0, 14, 3
                .byte 0, 360, 363, 74
                .byte 360, 374, 317, 363
                .byte 377, 360, 317, 363
                .byte 25, 100, 101, 121
                .byte 120, 24, 4, 0
                .byte 0, 120, 121, 24
                .byte 0, 0, 4, 1
                .byte 0, 0, 125, 5
                .byte 0, 0, 125, 121
                .byte 100, 125, 124, 5
                .byte 0, 120, 125, 0
SprEnemy5:      .byte 0, 0, 0, 0        ; Trap 4
                .byte 377, 77, 77, 3
                .byte 314, 74, 0, 0
                .byte 74, 363, 0, 0
                .byte 360, 377, 0, 0
                .byte 360, 3, 74, 0
                .byte 0, 377, 363, 0
                .byte 377, 0, 14, 0
                .byte 60, 300, 360, 63
                .byte 125, 0, 14, 0
                .byte 0, 125, 121, 0
                .byte 120, 1, 24, 0
                .byte 120, 125, 0, 0
                .byte 24, 121, 0, 0
                .byte 104, 24, 0, 0
                .byte 125, 25, 25, 1
SprEnemy6:      .byte 314, 377, 374, 77 ; Trap 5
                .byte 0, 0, 63, 63
                .byte 0, 300, 377, 77
                .byte 0, 360, 77, 0
                .byte 0, 374, 303, 77
                .byte 300, 60, 374, 363
                .byte 60, 317, 363, 317
                .byte 377, 377, 377, 317
                .byte 5, 0, 20, 104
                .byte 20, 105, 1, 100
                .byte 100, 0, 124, 120
                .byte 0, 104, 100, 25
                .byte 0, 20, 1, 0
                .byte 0, 100, 104, 20
                .byte 0, 0, 21, 1
                .byte 104, 125, 124, 25
SprEnemy7:      .byte 0, 0, 77, 0       ; Trap 6
                .byte 0, 300, 300, 0
                .byte 0, 0, 77, 0
                .byte 0, 300, 377, 74
                .byte 0, 300, 300, 374
                .byte 0, 14, 77, 374
                .byte 360, 317, 377, 374
                .byte 377, 317, 374, 374
                .byte 52, 300, 300, 374
                .byte 240, 302, 363, 74
                .byte 0, 10, 77, 0
                .byte 0, 200, 200, 200
                .byte 0, 200, 252, 50
                .byte 0, 0, 52, 0
                .byte 0, 200, 200, 0
                .byte 0, 0, 52, 0
SprEnemy8:      .byte 0, 0, 0, 0        ; Trap 7
                .byte 0, 377, 0, 54
                .byte 50, 360, 17, 321
                .byte 200, 302, 77, 164
                .byte 214, 362, 377, 34
                .byte 14, 374, 77, 67
                .byte 14, 377, 317, 15
                .byte 14, 374, 163, 7
                .byte 60, 360, 334, 1
                .byte 60, 0, 167, 0
                .byte 300, 303, 35, 60
                .byte 14, 160, 7, 374
                .byte 0, 334, 1, 77
                .byte 103, 167, 0, 214
                .byte 15, 15, 60, 40
                .byte 64, 0, 300, 10
SprEnemy9:      .byte 0, 317, 77, 0     ; Trap 10
                .byte 360, 77, 360, 3
                .byte 14, 377, 303, 17
                .byte 14, 360, 17, 77
                .byte 3, 360, 77, 77
                .byte 0, 360, 77, 374
                .byte 377, 377, 77, 374
                .byte 300, 377, 17, 0
                .byte 52, 0, 0, 52
                .byte 250, 52, 210, 12
                .byte 200, 2, 200, 2
                .byte 0, 240, 12, 0
                .byte 0, 200, 12, 12
                .byte 0, 0, 240, 52
                .byte 200, 252, 52, 250
                .byte 250, 12, 252, 52
SprEnemy10:     .byte 0, 300, 17, 0     ; Trap 11
                .byte 363, 363, 17, 0
                .byte 0, 374, 77, 0
                .byte 0, 377, 77, 0
                .byte 300, 377, 360, 360
                .byte 360, 17, 60, 363
                .byte 374, 3, 300, 363
                .byte 377, 377, 317, 363
                .byte 1, 1, 100, 120
                .byte 4, 4, 20, 1
                .byte 20, 120, 20, 120
                .byte 100, 0, 105, 0
                .byte 0, 1, 100, 0
                .byte 0, 4, 20, 0
                .byte 121, 21, 4, 0
                .byte 0, 100, 5, 0
SprEnemy11:     .byte 0, 0, 0, 0        ; Trap 12
                .byte 0, 360, 10, 0
                .byte 0, 77, 242, 0
                .byte 300, 377, 10, 0
                .byte 360, 77, 42, 10
                .byte 360, 317, 0, 0
                .byte 374, 77, 202, 40
                .byte 374, 317, 0, 40
                .byte 374, 77, 42, 10
                .byte 374, 317, 0, 40
                .byte 360, 77, 202, 0
                .byte 360, 377, 10, 10
                .byte 300, 77, 42, 0
                .byte 0, 377, 210, 0
                .byte 0, 360, 2, 0
                .byte 0, 0, 0, 0
SprEnemy12:     .byte 0, 0, 0, 0        ; Trap 13
                .byte 0, 0, 0, 0
                .byte 0, 0, 0, 0
                .byte 0, 0, 0, 125
                .byte 0, 0, 100, 125
                .byte 0, 0, 120, 25
                .byte 20, 121, 121, 125
                .byte 4, 1, 4, 0
                .byte 77, 363, 377, 377
                .byte 74, 363, 17, 0
                .byte 60, 363, 363, 377
                .byte 0, 0, 360, 77
                .byte 0, 0, 300, 377
                .byte 0, 0, 0, 377
                .byte 0, 0, 0, 0
                .byte 0, 0, 0, 0
SprChain1:      .byte 20, 105, 0, 0     ; Trap 14
                .byte 24, 105, 1, 0
                .byte 24, 4, 5, 0
                .byte 120, 0, 5, 0
                .byte 120, 20, 24, 0
                .byte 100, 121, 21, 0
                .byte 0, 105, 1, 0
                .byte 0, 0, 5, 0
                .byte 0, 20, 105, 0
                .byte 0, 24, 105, 1
                .byte 0, 24, 4, 5
                .byte 0, 120, 0, 5
                .byte 0, 120, 20, 24
                .byte 0, 100, 121, 21
                .byte 0, 0, 105, 21
                .byte 0, 0, 0, 5
SprChain2:      .byte 0, 0, 121, 4      ; Trap 15
                .byte 0, 100, 121, 24
                .byte 0, 120, 20, 24
                .byte 0, 120, 0, 5
                .byte 0, 24, 4, 5
                .byte 0, 104, 105, 1
                .byte 0, 100, 121, 0
                .byte 0, 120, 0, 0
                .byte 0, 121, 4, 0
                .byte 100, 121, 24, 0
                .byte 120, 20, 24, 0
                .byte 120, 0, 5, 0
                .byte 24, 4, 5, 0
                .byte 104, 105, 1, 0
                .byte 104, 121, 0, 0
                .byte 120, 0, 0, 0
SprPrise1:      .byte 0, 0, 0, 0        ; Trap 16
                .byte 0, 0, 0, 0
                .byte 0, 0, 0, 0
                .byte 60, 360, 74, 0
                .byte 0, 3, 300, 3
                .byte 314, 360, 74, 14
                .byte 0, 360, 374, 63
                .byte 60, 360, 374, 77
                .byte 14, 363, 374, 77
                .byte 0, 360, 374, 77
                .byte 314, 360, 374, 17
                .byte 0, 363, 374, 3
                .byte 60, 360, 74, 0
                .byte 0, 0, 0, 0
                .byte 0, 0, 0, 0
                .byte 0, 0, 0, 0
SprPrise2:      .byte 0, 0, 0, 0        ; Trap 17
                .byte 300, 3, 300, 3
                .byte 360, 317, 363, 17
                .byte 360, 363, 317, 17
                .byte 360, 363, 317, 17
                .byte 360, 363, 317, 17
                .byte 360, 363, 317, 17
                .byte 60, 363, 317, 17
                .byte 60, 363, 17, 17
                .byte 60, 63, 17, 17
                .byte 60, 63, 17, 17
                .byte 60, 63, 17, 17
                .byte 0, 60, 17, 0
                .byte 60, 3, 60, 17
                .byte 0, 60, 17, 0
                .byte 0, 0, 0, 0
SprPrise3:      .byte 0, 0, 0, 0        ; Trap 20
                .byte 360, 0, 300, 3
                .byte 360, 63, 360, 3
                .byte 300, 317, 374, 0
                .byte 0, 317, 74, 0
                .byte 0, 360, 303, 0
                .byte 0, 77, 77, 0
                .byte 0, 300, 0, 0
                .byte 0, 77, 77, 0
                .byte 300, 360, 3, 0
                .byte 0, 317, 74, 0
                .byte 300, 317, 374, 0
                .byte 360, 3, 363, 3
                .byte 360, 0, 300, 3
                .byte 0, 0, 0, 0
                .byte 0, 0, 0, 0
SprPrise4:      .byte 0, 0, 0, 0        ; Trap 21
                .byte 0, 0, 0, 0
                .byte 0, 0, 1, 0
                .byte 0, 120, 25, 0
                .byte 0, 124, 125, 0
                .byte 0, 125, 125, 1
                .byte 0, 125, 125, 1
                .byte 100, 125, 125, 5
                .byte 100, 125, 125, 5
                .byte 0, 125, 125, 1
                .byte 0, 125, 125, 1
                .byte 0, 124, 125, 0
                .byte 0, 120, 25, 0
                .byte 0, 0, 1, 0
                .byte 0, 0, 0, 0
                .byte 0, 0, 0, 0
SprPrise5:      .byte 0, 0, 0, 0        ; Trap 22
                .byte 0, 300, 17, 0
                .byte 0, 374, 377, 0
                .byte 0, 377, 377, 3
                .byte 300, 377, 377, 17
                .byte 300, 377, 377, 17
                .byte 360, 377, 377, 77
                .byte 360, 377, 377, 77
                .byte 360, 377, 377, 77
                .byte 360, 377, 377, 77
                .byte 300, 377, 377, 17
                .byte 300, 377, 377, 17
                .byte 0, 377, 377, 3
                .byte 0, 374, 377, 0
                .byte 0, 300, 17, 0
                .byte 0, 0, 0, 0
SprMiniBlow1:   .byte 0, 0, 3, 0        ; Trap 23
                .byte 60, 300, 3, 0
                .byte 360, 303, 63, 14
                .byte 300, 317, 317, 17
                .byte 300, 77, 360, 3
                .byte 317, 377, 377, 3
                .byte 74, 377, 74, 14
                .byte 300, 377, 363, 0
                .byte 314, 363, 317, 17
                .byte 360, 377, 360, 77
                .byte 360, 77, 377, 0
                .byte 374, 374, 3, 3
                .byte 14, 374, 374, 0
                .byte 300, 374, 374, 0
                .byte 0, 74, 303, 3
                .byte 0, 14, 0, 0
SprMiniBlow2:   .byte 0, 0, 0, 0        ; Trap 24
                .byte 0, 0, 0, 0
                .byte 0, 14, 3, 0
                .byte 60, 60, 0, 14
                .byte 0, 0, 314, 0
                .byte 14, 63, 63, 0
                .byte 60, 14, 314, 60
                .byte 0, 60, 3, 0
                .byte 314, 314, 317, 3
                .byte 60, 377, 63, 0
                .byte 303, 63, 17, 0
                .byte 0, 314, 63, 14
                .byte 60, 63, 314, 300
                .byte 314, 300, 0, 14
                .byte 0, 14, 14, 3
                .byte 60, 60, 0, 0
SprCurve1:      .byte 3, 0, 0, 300      ; Trap 25
                .byte 3, 0, 0, 300
                .byte 14, 0, 0, 60
                .byte 14, 0, 0, 60
                .byte 14, 0, 0, 60
                .byte 14, 0, 0, 60
                .byte 60, 0, 0, 14
                .byte 60, 0, 0, 14
                .byte 60, 0, 0, 14
                .byte 300, 0, 0, 3
                .byte 300, 0, 0, 3
                .byte 0, 3, 300, 0
                .byte 0, 3, 300, 0
                .byte 0, 14, 60, 0
                .byte 0, 74, 74, 0
                .byte 0, 360, 17, 0
SprCurve2:      .byte 3, 0, 0, 300      ; Trap 26
                .byte 17, 0, 0, 360
                .byte 17, 0, 0, 360
                .byte 63, 0, 0, 314
                .byte 63, 0, 0, 314
                .byte 74, 0, 0, 74
                .byte 314, 0, 0, 63
                .byte 314, 0, 0, 63
                .byte 314, 0, 0, 63
                .byte 60, 3, 300, 14
                .byte 60, 3, 300, 14
                .byte 60, 14, 60, 14
                .byte 300, 14, 60, 3
                .byte 300, 60, 14, 3
                .byte 0, 303, 303, 0
                .byte 0, 374, 77, 0
SprCurve3:      .byte 5, 0, 0, 120      ; Trap 27
                .byte 25, 0, 0, 124
                .byte 21, 0, 0, 104
                .byte 101, 0, 0, 101
                .byte 101, 0, 0, 101
                .byte 1, 1, 100, 100
                .byte 1, 1, 100, 100
                .byte 4, 4, 20, 20
                .byte 4, 4, 20, 20
                .byte 4, 4, 20, 20
                .byte 4, 20, 4, 20
                .byte 4, 20, 4, 20
                .byte 20, 100, 1, 4
                .byte 20, 100, 1, 4
                .byte 100, 120, 5, 1
                .byte 0, 25, 124, 0
SprCurve4:      .byte 74, 0, 0, 74      ; Trap 30
                .byte 363, 0, 0, 317
                .byte 303, 0, 0, 303
                .byte 3, 3, 300, 300
                .byte 3, 3, 300, 300
                .byte 3, 14, 60, 300
                .byte 3, 14, 60, 300
                .byte 3, 60, 14, 300
                .byte 3, 60, 14, 300
                .byte 3, 300, 3, 300
                .byte 3, 300, 3, 300
                .byte 14, 300, 3, 60
                .byte 14, 300, 3, 60
                .byte 14, 60, 14, 60
                .byte 60, 14, 60, 14
                .byte 360, 3, 300, 17
SprCurve5:      .byte 250, 0, 0, 52     ; Trap 31
                .byte 10, 2, 200, 40
                .byte 10, 10, 40, 40
                .byte 2, 10, 40, 200
                .byte 2, 40, 10, 200
                .byte 2, 40, 10, 200
                .byte 2, 200, 2, 200
                .byte 2, 200, 2, 200
                .byte 2, 200, 2, 200
                .byte 2, 200, 2, 200
                .byte 2, 40, 10, 200
                .byte 2, 40, 10, 200
                .byte 2, 10, 40, 200
                .byte 10, 10, 40, 40
                .byte 10, 2, 200, 40
                .byte 250, 0, 0, 52
; ───────────────────────────────────────────────────────────────────────────
; Спрайт размером 4 х 10
SprIndicator:   .byte 0, 360, 17, 0
                .byte 0, 374, 77, 0
                .byte 0, 377, 377, 0
                .byte 0, 377, 377, 0
                .byte 0, 377, 377, 0
                .byte 0, 377, 377, 0
                .byte 0, 374, 77, 0
                .byte 0, 360, 17, 0
; ───────────────────────────────────────────────────────────────────────────
; спрайты взрыва размер 6 х 30
sprBlowB1:      .byte 0, 0, 0, 0, 0, 0
                .byte 0, 0, 0, 0, 0, 0
                .byte 0, 0, 0, 0, 0, 0
                .byte 0, 0, 0, 0, 0, 0
                .byte 0, 360, 3, 377, 3, 0
                .byte 0, 374, 374, 374, 17, 0
                .byte 0, 374, 377, 363, 17, 0
                .byte 0, 314, 377, 377, 17, 0
                .byte 0, 360, 363, 377, 60, 0
                .byte 0, 360, 74, 374, 77, 0
                .byte 0, 360, 377, 303, 77, 0
                .byte 0, 374, 377, 377, 77, 0
                .byte 0, 374, 374, 377, 63, 0
                .byte 0, 374, 363, 17, 17, 0
                .byte 0, 314, 14, 363, 17, 0
                .byte 0, 360, 317, 363, 17, 0
                .byte 0, 360, 374, 377, 14, 0
                .byte 0, 60, 377, 363, 3, 0
                .byte 0, 0, 360, 3, 3, 0
                .byte 0, 0, 0, 0, 0, 0
                .byte 0, 0, 0, 0, 0, 0
                .byte 0, 0, 0, 0, 0, 0
                .byte 0, 0, 0, 0, 0, 0
                .byte 0, 0, 0, 0, 0, 0
SprBlowB2:      .byte 0, 0, 0, 0, 0, 0
                .byte 0, 60, 300, 377, 3, 0
                .byte 300, 363, 17, 377, 374, 0
                .byte 360, 377, 77, 377, 377, 3
                .byte 0, 377, 377, 317, 377, 17
                .byte 360, 74, 377, 317, 377, 17
                .byte 374, 77, 377, 77, 360, 17
                .byte 374, 377, 360, 377, 377, 14
                .byte 74, 377, 377, 363, 377, 3
                .byte 314, 377, 377, 317, 377, 74
                .byte 360, 377, 377, 317, 377, 77
                .byte 360, 317, 377, 317, 377, 77
                .byte 360, 317, 377, 377, 377, 17
                .byte 360, 317, 377, 377, 377, 17
                .byte 374, 77, 377, 377, 377, 17
                .byte 374, 377, 360, 77, 374, 3
                .byte 374, 377, 377, 377, 363, 74
                .byte 314, 377, 377, 377, 363, 77
                .byte 360, 377, 377, 377, 374, 77
                .byte 360, 377, 374, 377, 377, 17
                .byte 60, 374, 363, 317, 377, 14
                .byte 0, 377, 363, 317, 377, 3
                .byte 0, 377, 17, 360, 17, 0
                .byte 0, 0, 0, 0, 0, 0
SprBlowB3:      .byte 0, 0, 0, 0, 0, 0
                .byte 0, 0, 377, 17, 0, 0
                .byte 300, 374, 374, 317, 363, 3
                .byte 300, 377, 317, 317, 377, 0
                .byte 360, 77, 317, 77, 77, 17
                .byte 360, 377, 77, 377, 377, 17
                .byte 374, 374, 377, 377, 377, 17
                .byte 374, 363, 374, 17, 377, 63
                .byte 360, 363, 363, 374, 374, 63
                .byte 300, 377, 17, 374, 374, 77
                .byte 360, 377, 3, 300, 377, 77
                .byte 374, 363, 3, 300, 317, 63
                .byte 74, 374, 0, 300, 317, 17
                .byte 374, 377, 0, 0, 377, 17
                .byte 374, 377, 3, 360, 377, 14
                .byte 60, 377, 3, 374, 17, 77
                .byte 300, 363, 374, 74, 377, 63
                .byte 360, 363, 377, 77, 377, 63
                .byte 360, 303, 377, 317, 377, 17
                .byte 300, 377, 317, 377, 17, 14
                .byte 300, 377, 363, 377, 377, 3
                .byte 0, 17, 374, 17, 374, 0
                .byte 0, 74, 17, 377, 3, 0
                .byte 0, 0, 0, 0, 0, 0
SprBlowB4:      .byte 0, 0, 0, 0, 0, 0
                .byte 0, 0, 0, 374, 3, 0
                .byte 0, 0, 74, 377, 17, 0
                .byte 0, 300, 317, 377, 17, 0
                .byte 0, 374, 377, 377, 377, 0
                .byte 0, 14, 377, 377, 377, 0
                .byte 0, 377, 17, 300, 377, 3
                .byte 300, 317, 3, 0, 377, 3
                .byte 300, 377, 0, 0, 374, 3
                .byte 300, 377, 0, 0, 374, 17
                .byte 0, 377, 0, 0, 374, 17
                .byte 300, 77, 0, 0, 360, 14
                .byte 300, 74, 0, 0, 360, 3
                .byte 0, 77, 0, 0, 360, 3
                .byte 0, 77, 0, 0, 300, 3
                .byte 300, 377, 0, 0, 314, 3
                .byte 300, 377, 77, 300, 377, 3
                .byte 300, 377, 317, 377, 377, 3
                .byte 300, 374, 377, 377, 377, 3
                .byte 0, 377, 377, 363, 377, 0
                .byte 0, 74, 377, 317, 377, 0
                .byte 0, 0, 374, 303, 17, 0
                .byte 0, 0, 0, 0, 0, 0
                .byte 0, 0, 0, 0, 0, 0
SprBlowB5:      .byte 0, 0, 0, 0, 0, 0
                .byte 0, 0, 0, 0, 0, 0
                .byte 0, 0, 74, 377, 0, 0
                .byte 0, 300, 317, 377, 17, 0
                .byte 0, 0, 3, 300, 77, 0
                .byte 0, 314, 0, 0, 14, 0
                .byte 0, 377, 0, 0, 374, 0
                .byte 0, 17, 0, 0, 360, 3
                .byte 0, 17, 0, 0, 300, 3
                .byte 300, 17, 0, 0, 300, 17
                .byte 0, 17, 0, 0, 300, 17
                .byte 300, 3, 0, 0, 300, 14
                .byte 300, 0, 0, 0, 300, 3
                .byte 0, 3, 0, 0, 300, 3
                .byte 0, 17, 0, 0, 300, 0
                .byte 300, 17, 0, 0, 300, 3
                .byte 0, 77, 0, 0, 360, 3
                .byte 0, 317, 17, 212, 374, 3
                .byte 0, 374, 3, 17, 77, 0
                .byte 0, 300, 377, 363, 17, 0
                .byte 0, 0, 377, 317, 0, 0
                .byte 0, 0, 0, 0, 0, 0
                .byte 0, 0, 0, 0, 0, 0
                .byte 0, 0, 0, 0, 0, 0
SprBlowSize = SprBlowB2 - SprBlowB1
; ───────────────────────────────────────────────────────────────────────────
; Три спрайта размером 6 х 30
; грибки
SprGrib1:       .byte 0, 0, 0, 0, 0, 0
                .byte 0, 0, 377, 377, 0, 0
                .byte 0, 360, 317, 300, 5, 0
                .byte 0, 374, 77, 3, 24, 0
                .byte 0, 377, 377, 63, 120, 0
                .byte 300, 377, 377, 14, 0, 1
                .byte 300, 377, 377, 63, 100, 1
                .byte 360, 377, 377, 317, 0, 4
                .byte 360, 377, 377, 63, 1, 4
                .byte 374, 377, 377, 317, 0, 24
                .byte 374, 377, 63, 3, 0, 21
                .byte 374, 377, 377, 377, 125, 25
                .byte 0, 0, 0, 0, 0, 0
                .byte 300, 377, 377, 377, 101, 1
                .byte 300, 377, 377, 303, 100, 1
                .byte 300, 377, 377, 377, 101, 1
                .byte 0, 0, 0, 0, 0, 0
                .byte 0, 374, 377, 77, 24, 0
                .byte 0, 374, 77, 3, 24, 0
                .byte 0, 374, 377, 77, 24, 0
                .byte 0, 0, 0, 0, 0, 0
                .byte 0, 300, 377, 303, 1, 0
                .byte 0, 300, 377, 300, 1, 0
                .byte 0, 300, 377, 303, 1, 0
SprGrib2:       .byte 0, 0, 0, 0, 0, 0
                .byte 0, 0, 377, 377, 0, 0
                .byte 0, 360, 317, 300, 5, 0
                .byte 0, 374, 77, 3, 24, 0
                .byte 0, 377, 377, 63, 120, 0
                .byte 300, 377, 377, 14, 0, 1
                .byte 300, 377, 377, 63, 100, 1
                .byte 360, 377, 377, 317, 0, 4
                .byte 360, 377, 377, 63, 1, 4
                .byte 374, 377, 377, 317, 0, 24
                .byte 374, 377, 63, 3, 0, 21
                .byte 374, 377, 377, 377, 125, 25
                .byte 0, 0, 0, 0, 0, 0
                .byte 300, 377, 377, 377, 101, 1
                .byte 300, 377, 377, 303, 100, 1
                .byte 300, 377, 377, 377, 101, 1
                .byte 0, 0, 0, 0, 0, 0
                .byte 0, 374, 377, 14, 24, 0
                .byte 0, 374, 377, 77, 24, 0
                .byte 0, 0, 0, 0, 0, 0
                .byte 0, 300, 377, 303, 1, 0
                .byte 0, 0, 0, 0, 0, 0
                .byte 0, 0, 0, 0, 0, 0
                .byte 0, 0, 0, 0, 0, 0
SprGrib3:       .byte 0, 0, 0, 0, 0, 0
                .byte 0, 0, 377, 377, 0, 0
                .byte 0, 360, 317, 300, 5, 0
                .byte 0, 374, 77, 3, 24, 0
                .byte 0, 377, 377, 63, 120, 0
                .byte 300, 377, 377, 14, 0, 1
                .byte 300, 377, 377, 63, 100, 1
                .byte 360, 377, 377, 317, 0, 4
                .byte 360, 377, 377, 63, 1, 4
                .byte 374, 377, 377, 317, 0, 24
                .byte 374, 377, 63, 3, 0, 21
                .byte 374, 377, 377, 377, 125, 25
                .byte 0, 0, 0, 0, 0, 0
                .byte 300, 377, 377, 377, 101, 1
                .byte 0, 0, 0, 0, 0, 0
                .byte 0, 374, 377, 77, 24, 0
                .byte 0, 0, 0, 0, 0, 0
                .byte 0, 300, 377, 303, 1, 0
                .byte 0, 0, 0, 0, 0, 0
                .byte 0, 0, 0, 0, 0, 0
                .byte 0, 0, 0, 0, 0, 0
                .byte 0, 0, 0, 0, 0, 0
                .byte 0, 0, 0, 0, 0, 0
                .byte 0, 0, 0, 0, 0, 0
SprGribSize = SprGrib2 - SprGrib1
; ───────────────────────────────────────────────────────────────────────────
; Спрайт размерами 14 х 60
; Это БОСС - какая-то насекомая на яйцах
SprBoss:        .byte 0, 0, 0, 0, 0, 300, 377, 377, 0, 0, 0, 0
                .byte 0, 0, 0, 0, 360, 377, 377, 377, 377, 3, 0, 0
                .byte 0, 0, 0, 300, 377, 317, 314, 374, 377, 377, 0, 0
                .byte 0, 0, 0, 374, 377, 0, 0, 317, 377, 377, 17, 0
                .byte 0, 0, 0, 377, 14, 63, 363, 60, 377, 377, 77, 0
                .byte 0, 0, 300, 77, 63, 63, 63, 314, 377, 377, 317, 0
                .byte 0, 0, 300, 77, 63, 3, 0, 63, 377, 377, 377, 3
                .byte 0, 300, 17, 17, 14, 0, 0, 14, 374, 363, 77, 3
                .byte 0, 74, 300, 60, 14, 0, 0, 300, 374, 377, 377, 17
                .byte 0, 3, 0, 300, 3, 0, 0, 0, 360, 317, 377, 14
                .byte 300, 74, 300, 0, 0, 0, 0, 0, 363, 77, 377, 3
                .byte 60, 377, 314, 0, 0, 0, 0, 0, 360, 317, 377, 60
                .byte 60, 377, 314, 14, 0, 0, 0, 0, 374, 77, 377, 3
                .byte 14, 74, 314, 0, 0, 0, 0, 0, 374, 317, 374, 60
                .byte 314, 0, 314, 314, 0, 0, 0, 0, 374, 63, 363, 3
                .byte 14, 0, 317, 14, 3, 60, 0, 74, 374, 14, 314, 60
                .byte 3, 0, 63, 314, 314, 60, 14, 17, 77, 3, 60, 303
                .byte 3, 0, 63, 317, 3, 17, 63, 77, 377, 0, 300, 14
                .byte 3, 300, 63, 303, 317, 300, 317, 317, 77, 14, 300, 303
                .byte 3, 300, 14, 363, 317, 317, 377, 360, 317, 60, 300, 14
                .byte 3, 360, 314, 363, 363, 17, 77, 377, 63, 14, 360, 303
                .byte 3, 77, 303, 300, 3, 303, 377, 317, 14, 3, 360, 0
                .byte 303, 3, 360, 360, 374, 60, 77, 377, 303, 14, 74, 63
                .byte 0, 14, 74, 0, 377, 317, 377, 377, 63, 3, 377, 0
                .byte 377, 3, 0, 0, 60, 74, 77, 317, 314, 360, 63, 14
                .byte 0, 360, 300, 17, 17, 14, 314, 374, 63, 314, 314, 0
                .byte 374, 77, 14, 300, 374, 14, 63, 377, 14, 63, 3, 3
                .byte 0, 0, 0, 60, 60, 0, 314, 74, 3, 0, 60, 0
                .byte 300, 17, 3, 314, 3, 0, 0, 314, 0, 63, 3, 14
                .byte 0, 317, 0, 3, 303, 314, 14, 63, 14, 0, 0, 63
                .byte 0, 0, 0, 377, 300, 14, 0, 0, 374, 77, 360, 0
                .byte 60, 0, 300, 377, 60, 3, 0, 77, 374, 377, 374, 303
                .byte 14, 0, 300, 374, 300, 0, 360, 377, 363, 63, 363, 14
                .byte 17, 0, 300, 0, 60, 0, 374, 377, 314, 317, 300, 303
                .byte 3, 0, 0, 77, 314, 0, 377, 377, 63, 77, 314, 0
                .byte 3, 0, 300, 74, 60, 300, 377, 377, 3, 374, 0, 3
                .byte 17, 0, 300, 0, 300, 300, 377, 377, 317, 74, 63, 0
                .byte 17, 0, 0, 377, 60, 360, 377, 377, 63, 360, 0, 0
                .byte 74, 0, 0, 63, 0, 303, 377, 377, 17, 63, 0, 0
                .byte 374, 0, 0, 303, 17, 77, 360, 377, 63, 300, 0, 3
                .byte 60, 17, 360, 314, 63, 300, 317, 377, 14, 63, 0, 0
                .byte 300, 374, 363, 63, 74, 14, 60, 63, 3, 0, 0, 0
                .byte 0, 77, 300, 314, 303, 17, 3, 314, 0, 0, 0, 0
                .byte 0, 360, 3, 0, 74, 360, 63, 63, 0, 0, 0, 0
                .byte 0, 0, 60, 63, 303, 17, 314, 14, 0, 60, 0, 0
                .byte 0, 0, 0, 0, 0, 360, 0, 0, 0, 3, 0, 0
                .byte 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0
                .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0


; ───────────────────────────────────────────────────────────────────────────
; спрайт размером 22 х 12
SprGameOver:    .byte 374, 17, 360, 3, 17, 74, 374, 17
                .byte 0, 0, 374, 17, 17, 74, 374, 17
                .byte 377, 77, 252, 50, 210, 10, 52, 52
                .byte 252, 50, 0, 0, 252, 50, 12, 50
                .byte 52, 50, 52, 240, 77, 77, 77, 77
                .byte 374, 17, 77, 0, 0, 0, 77, 77
                .byte 17, 74, 77, 0, 77, 360, 52, 0
                .byte 52, 52, 243, 62, 52, 0, 0, 0
                .byte 52, 52, 12, 50, 52, 0, 52, 240
                .byte 77, 77, 77, 0, 317, 74, 317, 17
                .byte 0, 0, 77, 77, 77, 77, 317, 17
                .byte 3, 374, 52, 52, 252, 52, 212, 50
                .byte 362, 0, 0, 0, 52, 52, 50, 12
                .byte 362, 0, 252, 12, 77, 63, 0, 77
                .byte 317, 74, 74, 0, 0, 0, 77, 77
                .byte 374, 17, 74, 0, 3, 374, 52, 50
                .byte 52, 52, 212, 50, 17, 0, 0, 0
                .byte 52, 52, 240, 2, 17, 0, 52, 240
                .byte 377, 77, 77, 77, 17, 74, 363, 74
                .byte 0, 0, 377, 74, 360, 3, 63, 74
                .byte 77, 360, 250, 12, 52, 52, 12, 50
                .byte 250, 12, 0, 0, 250, 12, 200, 0
                .byte 250, 12, 52, 240
; ───────────────────────────────────────────────────────────────────────────
SprBall:        .word ^B0000001010000000
                .word ^B0000101000100000
                .word ^B0010101010001000
                .word ^B0010101010101000
                .word ^B0010101010101000
                .word ^B0000101010100000
                .word ^B0000001010000000

; ───────────────────────────────────────────────────────────────────────────
; шрифт в виде спрайта. шириной 44 байта
; высотой 7 строк
Digits:         .byte 177, 74, 177, 177, 107, 177, 177, 177, 177, 177
                .byte 76, 77, 76, 77, 177, 177, 76, 107, 76, 170
                .byte 107, 7, 107, 107, 76, 77, 76, 77, 76, 177
                .byte 107, 107, 107, 107, 107, 177, 107, 76, 107, 107
                .byte 107, 7, 7, 160, 107, 107, 107, 107, 107, 107
                .byte 7, 7, 107, 107, 34, 160, 107, 7, 157, 107
                .byte 107, 107, 107, 107, 107, 34, 107, 107, 107, 107
                .byte 107, 107, 107, 74, 100, 100, 107, 177, 177, 160
                .byte 107, 107, 107, 107, 7, 107, 7, 7, 7, 107
                .byte 34, 160, 47, 7, 127, 117, 107, 107, 107, 107
                .byte 7, 34, 107, 107, 127, 56, 107, 47, 107, 74
                .byte 177, 170, 107, 100, 107, 160, 177, 177, 107, 77
                .byte 7, 107, 77, 37, 167, 177, 34, 160, 37, 7
                .byte 127, 127, 107, 107, 107, 107, 76, 34, 107, 107
                .byte 127, 34, 176, 20, 107, 74, 7, 100, 177, 107
                .byte 107, 160, 107, 100, 177, 107, 7, 107, 7, 7
                .byte 107, 107, 34, 161, 47, 7, 127, 147, 107, 77
                .byte 127, 77, 100, 34, 107, 107, 127, 56, 100, 17
                .byte 107, 74, 7, 107, 100, 107, 107, 160, 107, 107
                .byte 107, 107, 107, 107, 7, 7, 107, 107, 34, 161
                .byte 107, 7, 107, 107, 107, 7, 47, 107, 107, 34
                .byte 107, 46, 157, 107, 107, 107, 177, 176, 177, 177
                .byte 100, 177, 177, 160, 177, 177, 107, 77, 76, 77
                .byte 177, 7, 76, 107, 76, 76, 107, 177, 107, 107
                .byte 76, 7, 136, 107, 76, 34, 76, 34, 107, 107
                .byte 76, 177
; ───────────────────────────────────────────────────────────────────────────
; шрифт в виде спрайта для рекламы
; размеры 56 х 10
Font:           .byte 10, 24, 0, 0, 76, 36, 76, 177
                .byte 174, 177, 76, 177, 76, 76, 47, 76
                .byte 177, 137, 174, 177, 76, 177, 107, 137
                .byte 133, 137, 176, 157, 137, 76, 177, 176
                .byte 77, 76, 177, 137, 127, 77, 37, 117
                .byte 76, 127, 76, 127, 137, 37, 34, 12
                .byte 0, 0, 137, 37, 137, 137, 136, 1
                .byte 101, 103, 137, 101, 127, 137, 137, 137
                .byte 136, 137, 121, 101, 107, 137, 103, 137
                .byte 101, 121, 137, 101, 101, 137, 101, 101
                .byte 4, 137, 127, 137, 37, 117, 137, 127
                .byte 177, 127, 137, 20, 34, 0, 0, 0
                .byte 137, 36, 137, 57, 137, 77, 37, 160
                .byte 101, 137, 121, 137, 1, 137, 136, 1
                .byte 127, 37, 56, 137, 137, 41, 137, 127
                .byte 101, 137, 137, 137, 137, 137, 74, 137
                .byte 121, 101, 37, 117, 117, 127, 107, 127
                .byte 137, 36, 34, 0, 0, 0, 157, 36
                .byte 100, 20, 137, 100, 77, 160, 76, 176
                .byte 137, 101, 177, 137, 136, 77, 127, 37
                .byte 34, 157, 157, 37, 137, 127, 177, 137
                .byte 137, 102, 137, 37, 74, 101, 76, 77
                .byte 77, 117, 40, 127, 160, 127, 101, 76
                .byte 10, 0, 0, 0, 127, 36, 76, 170
                .byte 101, 137, 137, 70, 101, 100, 121, 177
                .byte 101, 137, 136, 1, 127, 37, 56, 127
                .byte 127, 41, 137, 127, 101, 137, 137, 174
                .byte 77, 37, 74, 176, 121, 101, 101, 121
                .byte 117, 127, 107, 127, 177, 102, 10, 0
                .byte 30, 0, 113, 36, 37, 107, 177, 137
                .byte 137, 70, 137, 137, 127, 101, 137, 137
                .byte 136, 37, 127, 37, 107, 113, 113, 137
                .byte 137, 127, 137, 137, 137, 102, 37, 137
                .byte 74, 100, 127, 137, 137, 127, 137, 127
                .byte 175, 127, 100, 136, 0, 0, 20, 30
                .byte 125, 2, 37, 137, 100, 137, 137, 34
                .byte 137, 137, 127, 137, 137, 41, 100, 137
                .byte 127, 37, 107, 125, 125, 137, 137, 107
                .byte 137, 137, 137, 137, 37, 137, 74, 137
                .byte 127, 137, 137, 127, 101, 121, 101, 61
                .byte 100, 136, 10, 0, 14, 30, 76, 77
                .byte 177, 76, 100, 76, 76, 34, 76, 76
                .byte 47, 137, 177, 137, 177, 177, 76, 37
                .byte 107, 133, 133, 137, 137, 107, 137, 76
                .byte 137, 107, 37, 76, 74, 76, 127, 77
                .byte 77, 117, 76, 177, 76, 137, 100, 76

; ───────────────────────────────────────────────────────────────────────────
;   Таблицы Констант
; ───────────────────────────────────────────────────────────────────────────
TerrainSprTbl:  .word SprGround
                .word SprGround2
                .word SprGround3
; ───────────────────────────────────────────────────────────────────────────
EffectTbl:      .word SprEffect1
                .word SprEffect2
                .word SprEffect3
                .word SprEffect4
                .word SprEffect5

EffectOffsetTbl:.word -1002
                .word -2000
                .word -1776
                .word -1774
                .word -772
                .word 10
                .word 1010
                .word 2006
                .word 3004
                .word 3002
                .word 3000
                .word 1776
                .word 774
                .word -4
EffectOffsetTblEnd:
EffectOffsetTblSize = <EffectOffsetTblEnd - EffectOffsetTbl>/2
; ───────────────────────────────────────────────────────────────────────────
; таблица команд trap для отображения осциллограммы
OscTrpTbl:      trap 125
                trap 126
                trap 127
                trap 130
                trap 131
                trap 230
                trap 227
                trap 226
                trap 225
                trap 226
                trap 227
                trap 230
                trap 231
                trap 130
                trap 127
                trap 126
OscTrpTblEnd:
; ───────────────────────────────────────────────────────────────────────────
EnemyBaseOffsetTbl:
                .word -2
                .word 76
                .word 176
                .word -102
                .word 276
                .word -202
                .word 376
                .word -302
; ───────────────────────────────────────────────────────────────────────────
EnemyTrackOffsetTbl:.word -2
                .word -1002
                .word -1000
                .word -776
                .word 2
                .word 1002
                .word 1000
                .word 776
; ───────────────────────────────────────────────────────────────────────────
Enemy2TrackTbl: .word 66660
                .word 133333
                .word 35555
                .word 111111
                .word 111104
                .word 44444
                .word 22222
                .word 177775
                .word 177777
                .word 66777
                .word 133333
                .word 35555
                .word 111111
                .word 111104
                .word 44444
                .word 22222
                .word 5
                .word 0
; ───────────────────────────────────────────────────────────────────────────
Enemy9TrackTbl: .word 0
                .word 0
                .word 20000
                .word 132221
                .word 162221
                .word 44446
                .word 11
                .word 177400
                .word 17777
                .word 0
                .word 0
                .word 0
; ───────────────────────────────────────────────────────────────────────────
Enemy6TrackTbl: .word 0
                .word 0
                .word 222
                .word 77700
                .word 133333
                .word 111333
                .word 33344
                .word 111111
                .word 222
                .word 177700
                .word 66777
                .word 111333
                .word 33344
                .word 111
                .word 0
                .word 0
                .word 44000
                .word 176
                .word 0
; ───────────────────────────────────────────────────────────────────────────
Enemy8TrackTbl: .word 66666
                .word 133333
                .word 155555
                .word 77666
                .word 110440
                .word 44444
                .word 22222
                .word 51111
                .word 176002
                .word 66666
                .word 133333
                .word 155555
                .word 176666
                .word 104403
                .word 44444
                .word 22222
                .word 111111
                .word 44444
                .word 170011
                .word 133333
                .word 155555
                .word 66666
                .word 173333
                .word 22017
                .word 22222
                .word 111111
                .word 44444
                .word 122222
; ───────────────────────────────────────────────────────────────────────────
Enemy1TrackTbl: .word 167766
                .word 177737
                .word 22001
                .word 21122
                .word 105105
                .word 22
                .word 167767
                .word 133733
                .word 17757
                .word 7010
                .word 111044
                .word 22444
; ───────────────────────────────────────────────────────────────────────────
Enemy4TrackTbl: .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 40000
                .word 132222
                .word 66221
                .word 155555
                .word 66666
                .word 37733
                .word 42200
                .word 22222
                .word 22221
                .word 131111
                .word 66665
                .word 3773
                .word 0
                .word 0
; ───────────────────────────────────────────────────────────────────────────
EnemyStg6TrackTbl:.word 177777
                .word 3777
                .word 16
                .word 70
                .word 400
                .word 42220
                .word 122222
                .word 22155
                .word 111113
                .word 44344
                .word 26222
                .word 155311
                .word 76
                .word 144444
                .word 177777
                .word 111117
                .word 177444
                .word 1
; ───────────────────────────────────────────────────────────────────────────
Enemy10TrackTbl:.word 1122
                .word 173374
                .word 22017
                .word 43322
                .word 173266
                .word 176017
                .word 45566
                .word 51156
                .word 176002
                .word 7766
                .word 151044
                .word 133106
                .word 7766
                .word 51044
                .word 22002
                .word 43322
                .word 173266
                .word 176017
                .word 21100
                .word 62155
                .word 177553
                .word 67700
                .word 162267
                .word 22446
                .word 67700
                .word 377
; ───────────────────────────────────────────────────────────────────────────
Enemy7.1TrackTbl:.word 154444
                .word 133332
                .word 155777
                .word 65556
                .word 3773
                .word 220
Enemy7.2TrackTbl:.word 22334
                .word 110451
                .word 44664
                .word 32112
                .word 51
                .word 0
; ───────────────────────────────────────────────────────────────────────────
Enemy7.3TrackTbl:.word 0
                .word 23333
                .word 155555
                .word 0
                .word 111110
                .word 44444
                .word 2222
                .word 133000
                .word 15555
                .word 0
                .word 110000
                .word 44444
                .word 44422
                .word 133332
                .word 155555
                .word 66666
                .word 100333
                .word 104444
                .word 44444
                .word 33322
                .word 0
                .word 0
                .word 0
                .word 44444
                .word 22222
                .word 22111
                .word 155555
                .word 66
                .word 0
; ───────────────────────────────────────────────────────────────────────────
; Таблица смещений адреса ГГ соответствующих направлению движения
MoveOffsets:    .word -2
                .word -1002
                .word -1000
                .word -776
                .word 2
                .word 1002
                .word 1000
                .word 776
                .word 100000            ; "FIRE"
; ───────────────────────────────────────────────────────────────────────────
TrexValue:      .word -100
                .word -200
                .word -300
                .word -400
                .word -300
                .word -200
                .word -100
                .word 0
                .word 100
                .word 200
                .word 300
                .word 400
                .word 300
                .word 200
                .word 100
                .word 0
TrexValueEnd:
; ───────────────────────────────────────────────────────────────────────────
;  номера спрайтов гриба - последовательность анимации
word_26174:     .word 0
                .word 1
                .word 2
                .word 1
; ───────────────────────────────────────────────────────────────────────────
; таблица смещений взрывов на боссе
word_31432:     .word 512
                .word 2376
                .word 4602
                .word 2104
                .word -576
                .word 0
                .word 1000
                .word 3210
                .word 0
; ───────────────────────────────────────────────────────────────────────────
; дисперсия шаров
word_34554:     .word -2
                .word -102
                .word 76
                .word -202
                .word 176
                .word -302
                .word 276
                .word -402
                .word 376
                .word 476
                .word -502
                .word 576
                .word -602
                .word -2
                .word -202
                .word 76

; ───────────────────────────────────────────────────────────────────────────
; ───────────────────────────────────────────────────────────────────────────
;   Таблицы переменных
; ───────────────────────────────────────────────────────────────────────────
; таблица летящих звёзд
; размер элемента 2 слова:
; первое слово - адрес
; затем байт - битовая маска
;       байт - счётчик (скорость перемещения)
; так же используется для генерации звука шума выстрела
StarsTable:     .word 50543
                .byte 2, 0
                .word 51322
                .byte 1, 2
                .word 52674
                .byte 2, 0
                .word 53343
                .byte 10, 102
                .word 54010
                .byte 10, 2
                .word 55232
                .byte 2, 0
                .word 55735
                .byte 10, 107
                .word 56430
                .byte 20, 3
                .word 56651
                .byte 1, 0
                .word 57247
                .byte 100, 101
                .word 57616
                .byte 1, 3
                .word 61045
                .byte 1, 0
                .word 61354
                .byte 20, 1
                .word 62441
                .byte 40, 102
                .word 63135
                .byte 2, 0
                .word 64072
                .byte 40, 110
                .word 64212
                .byte 200, 3
                .word 65367
                .byte 40, 0
                .word 66202
                .byte 20, 1
                .word 67176
                .byte 100, 101
ShootSndEnd:    .word 70421
                .byte 2, 0
                .word 71073
                .byte 10, 1
                .word 71673
                .byte 10, 102
                .word 72577
                .byte 20, 0
                .word 73317
                .byte 20, 107
                .word 74031
                .byte 20, 3
                .word 72131
                .byte 1, 110
                .word 57225
                .byte 1, 3
                .word 65421
                .byte 40, 103
                .word 0
; ───────────────────────────────────────────────────────────────────────────
; Массив выстрелов ГГ
ShootsTbl:      .blkw 5
ShootsTblEnd:
; индексы в таблице TrexValue для каждой пульки
TrexValIdx:     .blkw 5
; ───────────────────────────────────────────────────────────────────────────
; таблица врагов, размер таблицы 16. элементов
; размер элемента - 10 байтов (4 слова)
; .word адрес экрана
; .word параметр 1
; .word параметр 2
; .word адрес подпрограммы обработки
EnemyBuffer:    .blkw 15. * 4
EnemyBufferEnd:
; Последний элемент особенный. Для Босса
BossAddr:       .word 0
BossParam1:     .word 0
BossParam2:     .word 0
BossMoveProc:   .word 0
EnemyBufferFullEnd:
EnemyBufferItemSize = 10

; ───────────────────────────────────────────────────────────────────────────
JoyTab:
JoyLt$:         .word 40
JoyRt$:         .word 2
JoyUp$:         .word 4
JoyDn$:         .word 100
JoyFire$:       .word 200
JoyTabEnd:

KeyTab:         .word 10
                .word 34
                .word 32
                .word 35
                .word 31
                .word 36
                .word 33
                .word 37
KeyFire$:       .word 40
KeyTabEnd:
; ───────────────────────────────────────────────────────────────────────────
; Таблица комбинаций джойстика для движений по диагоналям
off_17240:      .word JoyLt$
                .word JoyLt$
                .word JoyLt$
                .word JoyUp$
                .word JoyUp$
                .word JoyUp$
                .word JoyRt$
                .word JoyUp$
                .word JoyRt$
                .word JoyRt$
                .word JoyDn$
                .word JoyRt$
                .word JoyDn$
                .word JoyDn$
                .word JoyLt$
                .word JoyDn$
off_17240End:
; ───────────────────────────────────────────────────────────────────────────
;   Переменные
; ───────────────────────────────────────────────────────────────────────────
CurTerrainSpr:  .word 0
BitMaskInSpr:   .word 0
GGAddr:         .word 0                 ; текущий адрес спрайта самолётика
BeforeEffCntr:  .word 2 ; проинициализированная переменная, скорость анимации защитного поля
                        ; нельзя делать 0
ShieldEffectOffset:.word 0
MaxShoots:      .word 0                 ; максимальное количество одновременных выстрелов
NumShoots:      .word 0                 ; текущее количество выстрелов
StageNum:       .word 0                 ; Номер текущего этапа
PriseNum:       .word 0                 ; номер пойманного приза
Score:          .word 0                 ; Счёт игры
Lives:          .word 0                 ; жизни
ShieldFieldFlag:.word 0                 ; флаг включённого защитного поля

PanelDiagram:   .word PanelDiagrAddr    ; адрес / проинициализированные переменные
                .word 2                 ; маска /
GGShootSndPtr:  .word 0                 ; указатель на начало данных шума звука выстрела
GetRndAddrAcc:  .word 512   ; проинициализированная переменная
ROMAddrSnd:     .word 0                 ; указатель на данные из ПЗУ для звука шума
AtBlowFlightAnim:.word NoAnims          ; адрес п/п отработки анимации взрыва самолётика
                                        ; либо указатель на 207, если ещё не взрыв
AddLiveVal:     .word 0                 ; граничное значение для добавления доп.жизней
GribOnScreen:   .word 0                 ; флаг врага типа "Гриб" на экране
EnterValidPassFlag:.word 0
BossFlag:       .word 0                 ; флаг наличия босса на экране
BossHealth:     .word 0                 ; здоровье Босса


; ───────────────────────────────────────────────────────────────────────────
; буфер ввода чита
CheatBuf:       .blkb 6
; ───────────────────────────────────────────────────────────────────────────
; буфер пароля или имени, 6 байтов
InputBuf:       .blkb 6
; ───────────────────────────────────────────────────────────────────────────
; Таблица рекордов
; сперва слово - число, затем 6 символов - имя
HiScoreRecord:  .word 74162
RecordTable:    .ascii "SERGEJ"
                .word 64027
                .ascii "LARRY "
                .word 53127
                .ascii "ROBERT"
                .word 44172
                .ascii "JOHN  "
                .word 36570
                .ascii "DAVID "
                .word 34771
                .ascii "CATTY "
                .word 30165
                .ascii "STIVE "
                .word 24517
                .ascii "GEORGE"
                .word 16270
                .ascii "MIKE  "
LoScoreRecord:  .word 6572
                .ascii "ERIC  "
RecordTableEnd:
RecordTableItemSize = 10
RecordTableSize = <RecordTableEnd - HiScoreRecord> / RecordTableItemSize
; ───────────────────────────────────────────────────────────────────────────
strStage:       .asciz "STAGE *"
strCongratulations:.asciz "CONGRATULATIONS"
strEnterYourName:.asciz "ENTER YOUR NAME"
strEnterPassword:.asciz "ENTER PASSWORD"
strWrongPassword:.asciz "WRONG PASSWORD"
; ───────────────────────────────────────────────────────────────────────────
strAbout:       .asciz "GAME BY SSV"
                .asciz "NICOLAEV  1992"
strPressFire:   .asciz "PRESS FIRE BUTTON"
strXenon:       .asciz "XENON"
                .asciz "K..KEYBOARD"
                .asciz "J..JOYSTICK"
strPressOptionKey:.asciz "PRESS OPTION KEY..."
; ───────────────────────────────────────────────────────────────────────────
strCtrlKbd:     .asciz "LEFT"
                .asciz "UP.LEFT"
                .asciz "UP"
                .asciz "UP.RIGHT"
                .asciz "RIGHT"
                .asciz "DOWN.RIGHT"
                .asciz "DOWN"
                .asciz "DOWN.LEFT"
                .asciz "FIRE"

strCtrlJoy:     .asciz "LEFT"
                .asciz "RIGHT"
                .asciz "UP"
                .asciz "DOWN"
                .asciz "FIRE"
                .even
; ───────────────────────────────────────────────────────────────────────────
; таблица для вывода строк рекламы
; первое слово - адрес экрана, 0 - конец таблицы
; второе слово - цветовая маска
ReclDataTbl:    .word 51730
                .word 52525
                .word 54404
                .word 0
                .word 56004
                .word 0
                .word 57404
                .word 0
                .word 61004
                .word 0
                .word 62404
                .word 0
                .word 64004
                .word 0
                .word 65404
                .word 0
                .word 72016
                .word 52525
                .word 73414
                .word 52525
                .word 0
strReclama:     .asciz "ВНИМАНИЕ !"
                .asciz "ЕСЛИ ВЫ ХОТИТЕ  НАЙТИ ЛУЧШИЕ"
                .asciz "ПРОГРАММЫ  ПО НИЗКИМ  ЦЕНАМ,"
                .asciz "ТО НЕМЕДЛЕННО  ОБРАЩАЙТЕСЬ В"
                .asciz /ФИРМУ  "СНЕК". ДЛЯ  НЕЕ  НЕТ/
                .asciz /НЕВОЗМОЖНОГО.  ФИРМА  "СНЕК"/
                .asciz "СТАНЕТ ВАШИМ ЛУЧШИМ ДРУГОМ В"
                .asciz "МИРЕ БИЗНЕСА И РАЗВЛЕЧЕНИЙ !"
                .asciz "142407  НОГИНСК 7"
                .asciz /А.Я 53  ФИРМА "СНЕК"/
                .even
; ───────────────────────────────────────────────────────────────────────────
; обозначение трапов:
; trap 0  - враг 1    дирижабль
; trap 1  - враг 2    лягушка на воздушной подушке
; trap 2  - враг 3    икра
; trap 3  - враг 4    самолётик 1
; trap 4  - враг 5    самолётик слева-направо
; trap 5  - враг 6    самолётик 2
; trap 6  - враг 7    бомба ФАБ
; trap 7  - враг 8    бомба ядерная
; trap 10 - враг 9    кабинка на лыжах
; trap 11 - враг 10   самолётик 3
; trap 12 - враг 11   неубиваемый шар
; trap 13 - враг 12   ракета реактивная
; trap 14 - цепь 1
; trap 15 - цепь 2
; trap 16 - ускорение                                     | приз1 - ускорение корабля
; trap 17 - стрельба                                      | приз2 - повышение скорострельности
; trap 20 - крест - это бомба                             | приз3 - бомба (уничтожает всех на экране)
; trap 21 - шар синий мелкий - эти 2 шара - мигающий приз | приз4 - автоматическая стрельба
; trap 22 - шар красный      /        который надо ловить | приз5 - трекс (извилистая траектория пуль)
; trap 23 - взрыв врага 1                                 | приз6 - защита (силовое поле)
; trap 24 - взрыв врага 2
; trap 25 - осциллограмма 1
; trap 26 - осциллограмма 2
; trap 27 - осциллограмма 3
; trap 30 - осциллограмма 4
; trap 31 - осциллограмма 5
; призов у нас 6, а в спрайтах только три пиктограммки.
; поэтому для остальных трёх используются следующие, идущие по порядку спрайты

; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Trap диспетчер - вывод спрайтов
; Вход: R0 - адрес экрана для вывода
; номера 0..31 - вывод спрайта xorом с отсечкой края экрана.
; номера 100..131 - просто вывод movом, без отсечек
; номера 200..231 - вывод movом, зеркально по вертикали


DisTrap:        mov     (SP), R5
                mov     -(R5), R5
                sub     #104400, R5     ; номер трапа
                mov     #20, R2         ; высота спрайта
                mov     #76, R4         ; pitch
                mov     R5, R1
                swab    R1              ; n * 100 (на размер спрайта)
                ror     R1              ; подходит только для чисел меньше 256
                asr     R1
                add     #SprEnemy1, R1  ; получим адрес спрайта
                cmp     R5, #31         ; проверим, какой тип вывода спрайта задали
                bhi     6$              ; другой
                ; первый
                mov     R0, R3          ; адрес экрана
                bic     #177700, R3     ; посмотрим смещение
                cmp     #76, R3         ; если совсем справа
                beq     2$              ; пойдём туда

                cmp     R0, #TopScreen-1700 ; если выше вот этой границы
                blo     11$             ; то вообще выход из прерывания
                cmp     R0, #TopScreen  ; и проверка на игровую границу
                blo     2$              ; если выше - то пойдём туда
                cmp     R0, #BottomScreen-2000 ; и проверка на нижнюю границу
                bhi     2$              ; если ниже - то пойдём туда

1$:             mov     (R1)+, R3       ; выводим спрайт полностью
                xor     R3, (R0)+
                mov     (R1)+, R3
                xor     R3, (R0)
                add     R4, R0
                sob     R2, 1$
11$:            rti
; ───────────────────────────────────────────────────────────────────────────
; тут вывод с отсечкой границ

2$:             mov     (R1)+, R3       ; берём первое слово спрайта
                cmp     R0, #TopScreen  ; адрес вывода выше верхней границы?
                bhis    10$             ; нет, проверяем дальше
                cmp     (R1)+, (R0)+    ; тогда пропускаем всю линию спрайта и адрес экрана++
                br      3$

10$:            cmp     R0, #BottomScreen-4 ; ниже нижней?
                bhi     4$              ; да - просто выходим, нечего рисовать
; тут есть отсечка по правому краю
; но нету отсечки по левому, т.к. автор не стал усложнять
; если объект уезжает за левый край, то сразу появляется справа
                mov     R0, -(SP)
                bic     #177700, (SP)   ; теперь смотрим позицию по горизонтали
                cmp     (SP)+, #76      ; мы у самого правого края?
                bne     5$              ; нет - можем выводить спрайт полностью
                ; да
                xor     R3, (R0)+       ; выводим первое слово
                tst     (R1)+           ; пропускаем второе
                br      3$
; ───────────────────────────────────────────────────────────────────────────

5$:             xor     R3, (R0)+
                mov     (R1)+, R3
                xor     R3, (R0)

3$:             add     R4, R0          ; переходим к следующей строке
                sob     R2, 2$
4$:             rti
; ───────────────────────────────────────────────────────────────────────────

6$:             tstb    R5              ; номер спрайта больше 200?
                bmi     8$              ; да - туда
                ; номера трапов 100..131 - вывод спрайтов просто movом
                sub     #10000, R1      ; корректируем адрес.
                ; мы 100 умножили на 100, и теперь вычитаем лишнее из номера
7$:             mov     (R1)+, (R0)+
                mov     (R1)+, (R0)
                add     R4, R0
                sob     R2, 7$
                rti
; ───────────────────────────────────────────────────────────────────────────
                ; номера трапов 200..231 - вывод спрайтов просто movом, но
                ; зеркально по горизонтали
8$:             sub     #17700, R1      ; 200 * 100 - 100

9$:             mov     -(R1), R3
                mov     -(R1), (R0)+
                mov     R3, (R0)
                add     R4, R0
                sob     R2, 9$
                rti
; End of function DisTrap


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Прерывание по команде IOT, Вывод на экран символа.
; Вход: R0 - код символа

DisIot:         cmp     @#AS, #40000    ; Адрес символа за пределами экрана?
                blo     4$              ; да -выход
                mov     R4, -(SP)
                cmpb    R0, #'9         ; если больше 71
                bhi     6$              ; пойдём смотреть дальше
                cmpb    #'., R0         ; если '.'
                bne     1$
                mov     #112171, R1     ; то берём знак из ПЗУ монитора
                br      8$
; ───────────────────────────────────────────────────────────────────────────

1$:             cmpb    #40, R0
                bne     2$
                call    DrawSpace
                br      10$
; ───────────────────────────────────────────────────────────────────────────

2$:             sub     #'0, R0         ; если цифра, то идём выводить цифры
                blo     3$              ; иначе - игнорим всё остальное
5$:             mov     #Digits, R1
                br      7$
; ───────────────────────────────────────────────────────────────────────────

6$:             cmpb    R0, #'Z
                bhi     3$              ; игнорим всё, что больше буквы 'Z'
                sub     #'A, R0
                blo     3$              ; и всё, что не буквы
                mov     #<Digits+10.>, R1 ; там уже буквы

7$:             add     R0, R1          ; подводим к адресу символа

8$:             mov     #6, R4          ; высота символа 7 строк
                mov     @#AS, R0        ; Адрес символа
                call    DrawChrLine     ; выводим линию
                clr     (R0)            ; затем пустую строку
                add     #100, R0

9$:             call    DrawChrLine     ; а затем остальные 6 линий
                sob     R4, 9$

10$:            add     #2, @#AS        ; Адрес символа
3$:             mov     (SP)+, R4
4$:             rti
; End of function DisIot


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


DrawSpace:      mov     @#AS, R0        ; Адрес символа
                mov     #8., R5

1$:             clr     (R0)
                add     #100, R0
                sob     R5, 1$
                return
; End of function DrawSpace


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


DrawChrLine:    mov     #8., R5         ; в байте 8 бит
                movb    (R1), R3        ; берём очередной байт
                add     #44, R1         ; подводим указатель к следующему байту символа

1$:             asr     R3              ; расширяем байт в слово
                ror     (R0)
                asr     (R0)
                sob     R5, 1$
                bic     @#FON, (R0)     ; Фон экрана
                add     #100, R0
                return
; End of function DrawChrLine


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Сдвиг буфера влево и
; Выводим новый бит спрайта в буфер поверхности справа

PutNewBitTerrain:
                mov     #TerrainBuffer+2000, R0
                call    RorBuffer       ; Сдвиг буфера поверхности
                mov     CurTerrainSpr, R5 ; адрес в текущем отображаемом спрайте
                cmp     #<SprGround+20>, R5 ; до конца спрайта дошли?
                beq     1$              ; да
                cmp     #<SprGround3+10>, R5
                beq     1$              ; да
                cmp     #<SprGround2+10>, R5
                bne     3$              ; нет
; дошли до конца спрайта, надо менять его

1$:             mov     @#177710, R5    ; берём случайное число
                bic     #177770, R5     ; оставляем 0..7
                cmp     R5, #4          ; меньше 5?
                blos    2$              ; да - ОК
                clr     R5              ; нет - будет 0

2$:             mov     TerrainSprTbl(R5), R5 ; выбираем случайный новый спрайт поверхности
                mov     R5, CurTerrainSpr ; сохраняем
                mov     #1, BitMaskInSpr ; битовая маска в слове спрайта

3$:             mov     #TerrainBuffer+76, R0 ; адрес правого края буфера
                mov     #10, R2         ; ширина в байтах
                cmp     R5, #SprGround2 ; если это не первый спрайт
                bhis    4$              ; то переход
                asl     R2              ; а первый - в 2 раза шире

4$:             mov     BitMaskInSpr, R1 ; берём битовую маску

5$:             bit     (R5), R1        ; в спрайте есть этот бит?
                bne     6$              ; да
                bic     #100000, (R0)   ; нет - и на экране тоже не будет
                br      7$
; ───────────────────────────────────────────────────────────────────────────

6$:             bis     #100000, (R0)   ; да - и на экране будет

7$:             add     R2, R5          ; переходим к следующей строке спрайта
                add     #100, R0        ; переходим к следующей строке экрана
                cmp     R0, #TerrainBuffer+2000 ; всю высоту обработали?
                blo     5$              ; нет - продолжаем в цикле по высоте

8$:             asl     R1              ; двигаем маску
                bne     10$             ; пока слово не кончилось
                ; а если кончилось
                inc     R1              ; переходим к следующему слову
                add     #2, CurTerrainSpr ; спрайта
10$:            mov     R1, BitMaskInSpr ; сохраняем текущую маску
                return                  ; и выходим
; End of function PutNewBitTerrain


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Сдвиг буфера поверхности

RorBuffer:      mov     #100, R1
1$:             ror     -(R0)
                ror     -(R0)
                ror     -(R0)
                ror     -(R0)
                ror     -(R0)
                ror     -(R0)
                ror     -(R0)
                ror     -(R0)
                sob     R1, 1$
                return
; End of function RorBuffer


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; подготовка в буфере и отображение на экране поверхности земли

DrawTerrain:    mov     @#4, -(SP)      ; вектор 4 сохраним
                mov     #CheckStop, @#4 ; туда поместим новую п/п - признак нажатия на СТОП
                clr     StopFlag        ; флаг обнулим
                call    PutNewBitTerrain ; Сдвиг буфера влево и
                                        ; Выводим новый бит спрайта в буфер поверхности справа
                mov     #1, R1
                mov     BitMaskInSpr, R0 ; если маски нет
                beq     3$              ; то ничего не делать

1$:             inc     R1              ; так узнаем номер текущего бита
                clc
                ror     R0
                bne     1$
                asr     R1              ; если нечётный - пропускаем
                bcs     3$
; если чётный - отобразим текущий буфер на экране
                mov     #TerrainBuffer, R1
                mov     #BottomScreen, R2
                mov     #100, R0

2$:             mov     (R1)+, (R2)+
                mov     (R1)+, (R2)+
                mov     (R1)+, (R2)+
                mov     (R1)+, (R2)+
                mov     (R1)+, (R2)+
                mov     (R1)+, (R2)+
                mov     (R1)+, (R2)+
                mov     (R1)+, (R2)+
                sob     R0, 2$

3$:             mov     (SP)+, @#4      ; восстановим вектор 4
                tst     (PC)+           ; кнопку СТОП нажимали?
StopFlag:       .word 0
                bne     4$              ; да
                return                  ; нет - просто выходим
; ───────────────────────────────────────────────────────────────────────────

4$:             jmp     @4              ; да - ну и перейдём по вектору
; End of function DrawTerrain


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


CheckStop:      inc     StopFlag
                rti
; End of function CheckStop


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Вычисляем новые координаты звёзд и отображаем их

CalcMoveStars:  mov     #StarsTable, R5 ; таблица

1$:             mov     (R5)+, R0       ; берём адрес экрана
                beq     10$             ; 0 - конец таблицы
                clr     R1
                bisb    (R5)+, R1       ; берём младший байт, это маска.
                movb    (R5), R2        ; берём старший байт, это счётчик
                beq     3$              ; 0 - пора обрабатывать
                decb    R2              ; не 0, - минус 1
                beq     2$              ; стало 0 - переходим
                cmpb    #100, R2        ; стало 100?
                bne     11$             ; нет - просто сохраним новое значение счётчика
                movb    #110, (R5)      ; да - значит зададим 110
                br      3$              ; и идём обрабатывать
; ───────────────────────────────────────────────────────────────────────────

2$:             movb    #3, (R5)        ; стало 0 - зададим значение 3

3$:             bitb    R1, (R0)        ; звезда на экране была?
                beq     4$              ; нет
                bicb    R1, (R0)        ; да - погасим
                br      5$
; ───────────────────────────────────────────────────────────────────────────

4$:             bisb    R1, (R0)        ; нет - высветим

5$:             asr     R1              ; сдвигаем маску
                bne     7$              ; ещё не обнулилось
                ; обнулилось - значит надо менять адрес
                rorb    R1              ; задаём новую маску
                mov     R0, R3
                bic     #177700, R3     ; проверим границу перехода через 0
                bne     6$
                add     #100, R0        ; и делаем циклический переход на эту же линию экрана справа

6$:             dec     R0
                mov     R0, -3(R5)      ; сохраняем новый адрес

7$:             bitb    R1, (R0)        ; теперь заново - гасим высвечиваем звезду на новом месте
                bne     8$
                bisb    R1, (R0)
                br      9$
; ───────────────────────────────────────────────────────────────────────────

8$:             bicb    R1, (R0)

9$:             movb    R1, -(R5)       ; сохраняем новую маску
                tst    (R5)+            ; переходим к следующему элементу
                br      1$              ; и идём обрабатывать следующий элемент таблицы
; ───────────────────────────────────────────────────────────────────────────
11$:            movb    R2, (R5)+       ; просто сохраним новое значение счётчика
                br      1$              ; и идём обрабатывать следующий элемент таблицы
10$:            return
; End of function CalcMoveStars


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Начальное отображение звёзд по таблице на экране

InitialDrawStars:
                mov     #StarsTable, R1

1$:             mov     (R1)+, R0       ; адрес экрана
                beq     3$              ; 0 - конец таблицы
                mov     (R1)+, R2       ; значение в мл. байте, ст. байт не используем
                bitb    R2, (R0)        ; если там оно есть
                beq     2$
                bicb    R2, (R0)        ; то убираем его
                br      1$
; ───────────────────────────────────────────────────────────────────────────

2$:             bisb    R2, (R0)        ; если нету - устанавливаем
                br      1$

3$:             return
; End of function InitialDrawStars


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; отображение самолётика с начальной позиции

StartingDrawFlight:
                mov     #60216, R0      ; начальная позиция
                mov     R0, GGAddr      ; текущий адрес спрайта самолётика

; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Вход: R0 - адрес экрана

DrawFlight:     mov     #SprFlight, R1  ; Спрайт размером 6 х 11
                mov     #74, R5         ; pitch
                mov     #11, R2         ; высота спрайта
                cmp     R0, #40000
                blo     2$

1$:             mov     (R1)+, R4       ; три слова в строке
                xor     R4, (R0)+
                mov     (R1)+, R4
                xor     R4, (R0)+
                mov     (R1)+, R4
                xor     R4, (R0)
                add     R5, R0
                sob     R2, 1$

2$:             return
; End of function DrawFlight
; End of function StartingDrawFlight



; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; рисовать эффект защитного поля
; Вход: R1 - номер смещения в таблице смещений

DrawShieldEffect:
                mov     #4, R4          ; количество спрайтов 4..0
                                        ; это индекс в таблице EffectTbl
1$:             mov     R1, -(SP)
                mov     R4, -(SP)
                asl     R1
                asl     R4
                mov     EffectTbl(R4), R2 ; таблица спрайтов
                mov     GGAddr, R0      ; текущий адрес спрайта самолётика
                sub     #300, R0
                add     EffectOffsetTbl(R1), R0 ; вычисляем адрес, где выводить спрайт
                ; проверка на выход за границы экрана - верхнюю и нижнюю
                cmp     R0, #TopScreen
                blo     3$              ; за границей - пропускаем
                cmp     R0, #BottomScreen-1000
                bhi     3$              ; за границей - пропускаем
                mov     #10, R3         ; иначе - рисуем
                mov     #100, R4

2$:             mov     (R2)+, R1
                xor     R1, (R0)
                add     R4, R0
                sob     R3, 2$

3$:             mov     (SP)+, R4
                mov     (SP)+, R1
                inc     R1
                cmp     #EffectOffsetTblSize, R1
                bne     4$
                clr     R1              ; циклично

4$:             dec     R4              ; и так все 5 спрайтов
                bpl     1$
                return
; End of function DrawShieldEffect


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; анимация защитного поля

ShieldEffectAnim:
                dec     BeforeEffCntr   ; пора включать эффект?
                bne     3$              ; нет

1$:             mov     #2, BeforeEffCntr ; инициализируем счётчик
                mov     ShieldEffectOffset, R1 ; начальный номер смещения эффекта

                mov     R1, -(SP)
                mov     R1, -(SP)
                call    DrawShieldEffect ; рисовать эффект защитного поля
                                        ; Вход: R1 - номер смещения в таблице смещений
                mov     (SP)+, R1
                bne     2$
                mov     #EffectOffsetTblSize, R1

2$:             dec     R1
                call    DrawShieldEffect ; рисовать эффект защитного поля
                                        ; Вход: R1 - номер смещения в таблице смещений
                mov     (SP)+, R1
                inc     R1              ; циклически изменяем номер начального смещения
                cmp     #EffectOffsetTblSize, R1
                bne     4$
                clr     R1
4$:             mov     R1, ShieldEffectOffset

3$:             return
; End of function ShieldEffectAnim


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; обработка стрельбы ГГ

sub_22574:      cmp     #207, @AtBlowFlightAnim ; анимация взрыва самолётика есть?
                bne     3$              ; да - выход
                call    CheckPressFire  ; Выход: R5 - флаг: !0 - было нажато "FIRE", 0 - всё остальное
                tst     R5              ; стреляли?
                bne     1$              ; да
                clr     0MakeShootFlag$ ; нет

1$:             tst     AutoShootFlag   ; автострельба включена?
                bne     2$              ; да
                tst     R5              ; нет, а стреляли?
                bne     4$              ; да
                br      5$              ; нет
; ───────────────────────────────────────────────────────────────────────────

2$:             dec     (PC)+
0AutoShootDelay$:.word 3                 ; Задержка между выстрелами при автоматической стрельбе
                bne     5$
                mov     #5, 0AutoShootDelay$

4$:             tst     (PC)+
0MakeShootFlag$: .word 0                ; флаг, чтобы при нажатой кнопке стрельбы засчитывать только один выстрел
                bne     5$
                inc     0MakeShootFlag$ ; флаг, чтобы при нажатой кнопке стрельбы засчитывать только один выстрел
                mov     R0, -(SP)
                call    AddShootFlight  ; Добавление нового выстрела ГГ в таблицу
                mov     (SP)+, R0
5$:             jmp     AnimFlightSub
; ───────────────────────────────────────────────────────────────────────────

3$:             return
; End of function sub_22574


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Рисуется самолётик и эффект защитного поля
; Вход: R0 - смещение, на которое он должен сместиться

AnimFlightSub:  tst     (PC)+           ; что скорость?
SpeedValue:     .word 3                 ; это проинициализированные переменные
                beq     11$             ; максимум
                ; иначе используем замедление
                dec     (PC)+
0SpeedValue$:   .word 3                 ; это проинициализированные переменные
                                        ; тут вообще нельзя допускать нулевое значение
                bne     3$
                mov     SpeedValue, 0SpeedValue$

11$:            tst     R0
                beq     3$

0AnimFlight$:   mov     #GGAddr, R2     ; текущий адрес спрайта самолётика
                add     (R2), R0        ; новый адрес экрана
                cmp     R0, #TopScreen  ; должен быть
                blo     3$              ; в пределах рабочей области экрана
                cmp     R0, #BottomScreen-1104
                bhis    3$
                mov     R0, R1
                bic     #177700, R1
                cmp     R1, #70
                bhis    3$
                cmp     R1, #4
                blo     3$
                tst     ShieldFieldFlag ; защитное поле включено?
                beq     2$              ; нет
                ; да - стираем со старого места
                mov     R0, -(SP)
                mov     R2, -(SP)
                mov     ShieldEffectOffset, R1
                bne     1$
                mov     #EffectOffsetTblSize, R1

1$:             dec     R1
                mov     R1, @#Temp1     ; сохраняем значение во временной ячейке
                call    DrawShieldEffect ; рисовать эффект защитного поля
                                        ; Вход: R1 - номер смещения в таблице смещений
                mov     (SP)+, R2
                mov     (SP)+, R0

2$:             mov     (R2), -(SP)     ; текущий адрес экрана сохраним
                mov     R0, (R2)        ; новый адрес запомним.
                call    DrawFlight      ; Вход: R0 - адрес экрана Рисуем на новом месте
                mov     (SP)+, R0       ; стираем со старого
                call    DrawFlight      ; Вход: R0 - адрес экрана
                tst     ShieldFieldFlag ; защитное поле было?
                beq     3$              ; нет
                mov     @#Temp1, R1     ; да, тогда и его рисуем на новом месте
                jmp     DrawShieldEffect ; рисовать эффект защитного поля
                                        ; Вход: R1 - номер смещения в таблице смещений
3$:             return
; End of function AnimFlightSub


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Добавление нового выстрела ГГ в таблицу

AddShootFlight: cmp     NumShoots, MaxShoots ; количество выстрелов достигло предела?
                bhis    2$              ; да - выходим
                mov     #ShootsTbl, R1  ; нет - поищем в таблице

asf_1$:         tst     (R1)+
                bne     3$
                ; нашли пустой элемент
                mov     GGAddr, R0      ; текущий адрес спрайта самолётика
                add     #606, R0        ; адрес начала выстрела
                mov     R0, -(R1)       ; поместим в таблицу
                mov     (PC)+, R1
SprFlightBullet:.word 176363            ; изображение пульки на экране
                xor     R1, (R0)        ; нарисуем на экране
                mov     #StarsTable, GGShootSndPtr
                inc     NumShoots       ; текущее количество выстрелов
                return

3$:             cmp     #ShootsTblEnd, R1
                bhi     asf_1$
2$:             return
; End of function AddShootFlight


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Анимация выстрелов ГГ

ShootsFlightAnim:
                mov     #ShootsTbl, R1  ; таблица выстрелов
                mov     #TrexValIdx, R4 ; индекс в массиве TrexValIdx
1$:             mov     (R1), R0        ; адрес экрана
                beq     3$              ; если пусто - пропускаем
                mov     SprFlightBullet, R2 ; пулька

                xor     R2, (R0)        ; стираем пульку со старого места
                tst     (R0)+           ; новый адрес
                tst     TrexMode        ; режим ТРЕКС (изменение траектории полёта пуль)
                beq     7$              ; нет
                ; обработка режима ТРЕКС

                add     #2, (R4)        ; увеличим значение
                cmp     #TrexValueEnd-TrexValue, (R4) ; максимум?
                bne     4$              ; нет ещё
                clr     (R4)            ; да - обнулим

4$:             mov     (R4), R3        ; берём значение
                add     TrexValue(R3), R0 ; берём изменение траектории
                cmp     R0, #TopScreen  ; если пулька вылетела за экран
                blo     8$              ; удаляем её
                cmp     R0, #BottomScreen
                bhi     8$

7$:             mov     R0, R3          ; проверим
                bic     #177700, R3     ; за экран вылетела?
                beq     8$              ; да - надо удалить
                mov     R0, (R1)+       ; нет - новый адрес в массив
                xor     R2, (R0)        ; нарисуем на новом месте
                br      2$
; ───────────────────────────────────────────────────────────────────────────

8$:             clr     (R1)+
                dec     NumShoots       ; текущее количество выстрелов
                br      2$

3$:             tst     (R1)+
2$:             tst     (R4)+
                cmp     #ShootsTblEnd, R1
                bhi     1$
                return
; End of function ShootsFlightAnim


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Звук выстрела самолётика

GGShootSound:   mov     #GGShootSndPtr, R5 ; адрес адреса
                mov     (R5), R1        ; берём адрес
                beq     1$              ; если пусто - ничего не надо делать
                tst     (R1)+           ; +2
                cmp     R1, #ShootSndEnd ; до конца дошли?
                blo     2$              ; нет
                clr     (R5)            ; да - очищаем адрес, чтобы больше ничего не надо было делать
1$:             return
; ───────────────────────────────────────────────────────────────────────────

2$:             mov     R1, (R5)        ; сохраняем новый адрес
                mov     (R1), R1        ; берём значение
                bic     #177770, R1     ; оставляем младшие 3 бита
                mov     #2, R2          ; длительность
                inc     R1              ; тон

3$:             mov     R1, R0          ; звучок
                mov     #320, @#177716

                sob     R0, .
                mov     R1, R0
                mov     #220, @#177716

                sob     R0, .
                sob     R2, 3$
                return
; End of function GGShootSound


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Звук взрыва врага

NoiseSound:     mov     #ROMAddrSnd, R5
                tst     (R5)            ; если там 0
                beq     1$              ; то ничего не надо делать
                mov     (R5), R1        ; берём адрес
                cmp     R1, #100300     ; до конца дошли?
                blo     2$              ; нет - звучим
                clr     (R5)            ; да - выключаем звук до следующего раза

1$:             return
; ───────────────────────────────────────────────────────────────────────────

2$:             mov     #6, R0          ; шумозвук

3$:             mov     #16., R2
                mov     (R1)+, R3

4$:             asr     R3
                bcs     5$
                mov     #320, @#177716
                br      6$
; ───────────────────────────────────────────────────────────────────────────

5$:             mov     #220, @#177716

6$:             mov     #2, R4
                sob     R4, .
                sob     R2, 4$
                sob     R0, 3$
                mov     #220, @#177716
                mov     R1, (R5)
                return
; End of function NoiseSound


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


Cls1:           mov     #TopScreen, R0
                mov     #13000, R1

1$:             clr     (R0)+
                sob     R1, 1$
                return              ; секретный переход при правильно введённом пароле
; End of function Cls1


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; прорисовка осциллограммы, мигающей лампочки и прочих элементов панели

AnimPanel:      mov     (PC)+, R1       ; текущий указатель в таблице
OscTrpTblPtr:  .word   OscTrpTbl
                mov     (R1)+, 0OscTrapCmd$ ; задаём очередную команду
                cmp     R1, #OscTrpTblEnd  ; дошли до конца таблицы?
                blo     1$              ; нет ещё
                mov     #OscTrpTbl, R1  ; да - значит начнём с начала

1$:             mov     R1, OscTrpTblPtr ; и сохраним указатель в таблице
                mov     #PanelOscAddr, R0 ; адрес экрана
0OscTrapCmd$:   trap    230             ; рисуем осциллограмму
                ; теперь анимируем график слева вверху
                mov     #PanelGraphAddr, R0
                mov     #5, R1
2$:             clc
                ror     -(R0)
                ror     -(R0)
                ror     -(R0)
                ror     -(R0)
                bcc     3$
                bis     #100000, 6(R0)

3$:             add     #110, R0
                sob     R1, 2$
                ; мигаем лампочкой
                dec     (PC)+
0IndicFlashCntr$: .word 1               ; проинициализированная переменная, не
                                        ; должна быть 0
                bne     5$
                mov     #7, 0IndicFlashCntr$
                mov     #PanelIndicAddr, R0
                mov     #SprIndicator, R1
                mov     #10, R2

4$:             mov     (R1)+, R3
                xor     R3, (R0)+
                mov     (R1)+, R3
                xor     R3, (R0)
                add     #76, R0
                sob     R2, 4$
5$:             ; анимируем диаграмму на панели
                mov     #PanelDiagram, R5 ; адрес в панели
                mov     R5, R1
                tst     (R1)+           ; маска в панели
                bis     (R1), @(R5)+    ; устанавливаем
                tst     -(R5)
                asl     (R1)            ; маску двинем
                asl     (R1)
                bne     7$              ; слово не кончилось - переход
                add     #2, (R5)        ; кончилось - переходим к новому слову
                mov     #2, (R1)        ; и делаем новую маску
                cmp     #PanelDiagrAddr+6, (R5) ; дошли до конца вправо?
                bne     7$              ; нет
                mov     #PanelDiagrAddr, (R5) ; да - начинаем с начала
                br      8$
; ───────────────────────────────────────────────────────────────────────────

7$:             mov     @#177710, R0
                bic     #177770, R0     ; диаграмму сдвигать?
                bne     12$             ; нет

8$:             mov     #74, R3         ; да - двигаем
                mov     #PanelDiagrAddr-1500, R4
                mov     #PanelDiagrAddr-1400, R2
                mov     #16, R0

9$:             mov     (R2)+, (R4)+
                mov     (R2)+, (R4)+
                mov     (R2), (R4)
                add     R3, R4
                add     R3, R2
                sob     R0, 9$
                mov     @#177710, R0
                mov     #2, (R1)
                bic     #175670, R0
                beq     11$
                cmp     R0, #10
                bhi     11$

10$:            asl     (R1)
                asl     (R1)
                sob     R0, 10$

11$:            mov     #PanelDiagrAddr, (R5)

12$:            return
; End of function AnimPanel


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Сменить значок приза на экране

IndicatePrise:  mov     #PriseNum, R1   ; номер пойманного приза
                mov     #PanelPriseAddr, R0
                cmp     #5, (R1)        ; если 5
                bne     1$
                clr     (R1)            ; то 0
                trap    116             ; и выведем значок ускорения
                add     #230., Score    ; добавим очков
                return
; ───────────────────────────────────────────────────────────────────────────

1$:             inc     (R1)            ; если не 5, то +1
                mov     #104516, 0CmdPriseType$ ; и заменим значок приза
                add     (R1), 0CmdPriseType$

0CmdPriseType$: trap    117
                return                  ; без очков
; End of function IndicatePrise


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; уменьшение уровня защитного поля
; обработка звука взрыва врага
; обработка анимации взрыва самолётика

sub_22654:      com     #0
                bne     1$
                ; эту п/п вызываем через раз
                call    sub_14440       ; индикация уровня защитного поля на панели
                call    EnemysAnim      ; Анимация и обработка всех врагов

1$:             call    NoiseSound      ; Звук взрыва врага
                jmp     @AtBlowFlightAnim ; адрес п/п отработки анимации взрыва самолётика
                                        ; либо указатель на 207, если ещё не взрыв
; End of function sub_22654


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; индикация уровня защитного поля на панели

sub_14440:      tst     ShieldFieldFlag ; щит включён?
                beq     1$              ; нет
                dec     (PC)+           ; да, пришла пора уменьшать?
ShieldFallSpeed:.word 2                 ; скорость уменьшения щита
                bne     1$              ; не, ещё рано
                ; уменьшаем полоску шкалы уровня защитного поля
                mov     #3, ShieldFallSpeed ; снова инициализируем счётчик
                mov     (PC)+, R1
ShieldScaleMask:.word 100000            ; маска

                mov     (PC)+, R0
ShieldScaleAddr:.word PanelShieldAddr-2 ; адрес

                bic     R1, (R0)        ; очищаем бит на шкале на игровой панели
                bic     R1, 100(R0)
                bic     R1, 200(R0)
                bis     #31463, 100(R0) ; устанавливаем значение по умолчанию
                ccc
                ror     R1              ; сдвигаем маску
                bne     5$              ; слово ещё не кончилось
                ror     R1              ; кончилось - задаём новую маску
                tst     -(R0)           ; переходим к следующему слову
                cmp     R0, #PanelShieldAddr-2 ; дошли до конца?
                bne     4$              ; нет ещё
                mov     R1, -(SP)       ; да - всё, щит закончился
                mov     R0, -(SP)
                mov     ShieldEffectOffset, R1 ; гасим щит
                bne     3$
                mov     #EffectOffsetTblSize, R1

3$:             dec     R1
                call    DrawShieldEffect ; рисовать эффект защитного поля
                                        ; Вход: R1 - номер смещения в таблице смещений
                clr     ShieldFieldFlag ; сбрасываем флаг
                mov     (SP)+, R0
                mov     (SP)+, R1

4$:             mov     R0, ShieldScaleAddr
5$:             mov     R1, ShieldScaleMask
1$:             return
; End of function sub_14440


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Поиск свободного элемента в массиве EnemyBuffer
; Выход: R1 - адрес пустого элемента
; Если элемент не найден, то выход на уровень выше.

SearchFreeItem: mov     #EnemyBuffer, R1

1$:             tst     (R1)            ; элемент пуст?
                beq     2$              ; да - выходим
                add     #EnemyBufferItemSize, R1 ; идём к следующему
                cmp     R1, #EnemyBufferEnd ; дошли до конца массива?
                blo     1$              ; нет, смотрим дальше
                clr     (SP)+           ; массив заполнен выходим на уровень выше

2$:             return
; End of function SearchFreeItem


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Получение случайного адреса экрана
; Выход: R0 - адрес экрана с правого края

GetRNDScrAddr:  mov     #GetRndAddrAcc, R0
                add     #2, (R0)
                cmp     #40000, (R0)    ; если < 40000
                bhi     1$              ; то переход
                mov     #712, (R0)      ; иначе - вот такое значение

1$:             mov     @(R0)+, R0      ; получаем значение по адресу адреса

                add     @#177710, R0    ; прибавляем случайное число
                bic     #140077, R0     ; очищаем ненужное
                add     #40076, R0      ; получаем случайный адрес экрана
                return
; End of function GetRNDScrAddr


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Получение случайного смещения к адресу экрана
; (направления движения)
; Выход: R2 - смещение

GetRNDOffset:   mov     @#177710, R2
                bic     #177770, R2
                asl     R2
                mov     EnemyBaseOffsetTbl(R2), R2
                return
; End of function GetRNDOffset


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Вход: R1 - адрес элемента массива в EnemyBuffer
;       R4 - команда trap чтобы рисовать/стирать врага
;       R0 - адрес экрана
;       R2 - смещение (приращение к адресу экрана)

MoveEnemyProc1: mov     R0, -(SP)
                mov     R4, 0EnemySprSet$ ; зададим команду для стирания спрайта врага с экрана
                mov     R4, 0EnemySprCls$ ; и рисования на ново месте
                cmp     R0, #107000     ; если адрес экрана больше такого
                bhi     1$              ;  то удалить из массива
                bic     #177700, R0
                bne     2$              ; если долетел до левого края экрана

1$:             clr     (R1)            ; удаляем из массива элемент
                br      3$              ; и сотрём
; ───────────────────────────────────────────────────────────────────────────

2$:             mov     (SP), R0
                add     R2, R0          ; вычислим новый адрес
                mov     R0, (R1)        ; сохраним в массиве

0EnemySprSet$:  trap    2               ; нарисуем на новом месте

3$:             mov     (SP)+, R0       ; старый адрес

0EnemySprCls$:  trap    2               ; сотрём со старого
                return
; End of function MoveEnemyProc1


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Вход: R1 - адрес элемента массива в EnemyBuffer
;       R4 - параметр 1 (мл байт - номер трапа, ст.байт - битовая маска)
;       R0 - адрес экрана
;       R2 - параметр 2 (адрес таблицы)

MoveEnemyProc2: clr     R5              ; ну прям вот зачем вот так-то?
                movb    R4, R5          ; берём младший байт параметра
                add     (PC)+, R5       ; это - номер спрайта врага
                        trap 0
                mov     R5, 0EnemySprSet1$ ; задаём команды для вывода/стирания
                mov     R5, 0EnemySprCls1$
                mov     #3, R3
                mov     #1, R4
                clr     R5
                add     R3, R1          ; перемещаем указатель к старшему байту параметра 1

1$:             bitb    (R1), (R2)      ; есть там такой бит?
                beq     2$              ; нету
                bis     R4, R5          ; есть - и в R5 будет
                br      3$
; ───────────────────────────────────────────────────────────────────────────

2$:             bic     R4, R5          ; нету - и в R5 не будет

3$:             asl     R4              ; сдвигаем биты
                aslb    (R1)
                bne     4$              ; байт ещё не кончился
                                        ; кончился
                inc     R2              ; переходим к следующему
                                        ; и новая маска
                incb    (R1)
                mov     R2, 2(R1)       ; сохраняем параметр 2

4$:             sob     R3, 1$          ; и так для трёх битов
                sub     #3, R1          ; указатель назад возвращаем как было
                mov     R0, -(SP)
                asl     R5              ; это оказывается номер смещения в массиве
                bit     #77, R0         ; объект до левого края экрана дошёл?
                beq     8$              ; да
                add     EnemyTrackOffsetTbl(R5), R0 ; нет - применяем смещение

5$:             mov     R0, (R1)        ; сохраняем новый адрес

0EnemySprSet1$: trap    0               ; рисуем на новом месте
                br      7$
; ───────────────────────────────────────────────────────────────────────────

6$:             clr     (R1)
7$:             mov     (SP)+, R0

0EnemySprCls1$: trap    0               ; стираем на старом месте
                return
; ───────────────────────────────────────────────────────────────────────────
; обработка если на самом левом краю экрана

8$:             add     EnemyTrackOffsetTbl(R5), R0 ; применяем смещение
                mov     R0, R2          ; посмотрим, что получилось
                bic     #177700, R2
                cmp     #76, R2         ; если попал на правый край экрана
                beq     6$              ; то удаляем объект
                br      5$              ; иначе - продолжим как обычно
; End of function MoveEnemyProc2


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Обработчик движения врага 5.
; Вход: R1 - адрес элемента массива в EnemyBuffer
;       R0 - адрес экрана

MoveEnemy5Proc: mov     R0, -(SP)
                call    GetRNDOffset    ; Получение случайного смещения к адресу экрана
                                        ; (направления движения)
                                        ; Выход: R2 - смещение
                sub     R2, R0
                bit     #77, R0
                beq     2$
                mov     R0, (R1)
                trap    4
                br      1$
; ───────────────────────────────────────────────────────────────────────────
2$:             clr     (R1)
1$:             mov     (SP)+, R0
                trap    4
                return
; End of function MoveEnemy5Proc


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Обработчик движения врага 12.
; Вход: R1 - адрес элемента массива в EnemyBuffer
;       R0 - адрес экрана

MoveEnemy12Proc:mov     R0, -(SP)
                bic     #177700, R0
                beq     2$              ; если долетел до левого края экрана
                mov     (SP), R0        ; иначе - вычисляем новый адрес
                tst     -(R0)
                mov     R0, (R1)        ; сохраняем в массиве
                trap    13              ; рисуем на новом месте
                br      1$
; ───────────────────────────────────────────────────────────────────────────
2$:             clr     (R1)            ; удаляем из массива
1$:             mov     (SP)+, R0       ; и с экрана
                trap    13
                return
; End of function MoveEnemy12Proc


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Функция анимации гриба
; Вход: R1 - адрес элемента массива в EnemyBuffer
;       R4 - параметр 1
;       R0 - адрес экрана
;       R2 - параметр 2

MoveEnemyGribProc:
                mov     (R1)+, R0
                mov     (R1), R2
                mov     R1, R3
                mov     word_26174(R2), R1
                call    DrawGrib        ; вывод спрайта грибка
                                        ; Вход: R0 - адрес экрана
                                        ;       R1 - номер спрайта 0..2
                mov     R3, R1
                tst     (R2)+
                cmp     R2, #10
                bne     1$
                clr     R2

1$:             mov     R2, (R1)
                mov     GGAddr, R2      ; текущий адрес спрайта самолётика
                sub     #1000, R2
                bic     #777, R2
                mov     R0, R4
                bic     #177700, R4
                bis     R4, R2
                mov     #500, R3
                mov     R0, R4
                bic     #700, R4
                cmp     R4, R2
                beq     4$
                blo     2$
                neg     R3

2$:             add     R3, R0

3$:             mov     R0, -2(R1)
                mov     (R1), R1
                mov     word_26174(R1), R1
                jmp     DrawGrib        ; вывод спрайта грибка
                                        ; Вход: R0 - адрес экрана
                                        ;       R1 - номер спрайта 0..2
; ───────────────────────────────────────────────────────────────────────────

4$:             mov     GGAddr, R2      ; текущий адрес спрайта самолётика
                bic     #177700, R2
                mov     R0, R3
                bic     #177700, R3
                mov     #2, R4
                cmp     R2, R3
                beq     3$
                bhi     5$
                neg     R4

5$:             add     R4, R0
                br      3$
; End of function MoveEnemyGribProc


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; вывод спрайта грибка
; Вход: R0 - адрес экрана
;       R1 - номер спрайта 0..2

DrawGrib:       jsr     R4, @#110346
                mov     #SprGrib1, R3
                tst     R1
                beq     2$

1$:             add     #SprGribSize, R3 ; размер спрайта
                sob     R1, 1$

2$:             mov     #30, R2
                cmp     R0, #TopScreen
                blo     5$
                cmp     R0, #BottomScreen-3000+74
                bhi     5$

3$:             mov     (R3)+, R1
                xor     R1, (R0)+
                mov     (R3)+, R1
                xor     R1, (R0)+
                mov     (R3)+, R1
                xor     R1, (R0)
                add     #74, R0
                sob     R2, 3$
                br      4$
; ───────────────────────────────────────────────────────────────────────────

5$:             cmp     R0, #TopScreen
                bhi     6$
                add     #6, R3
                cmp     (R0)+, (R0)+
                br      7$
; ───────────────────────────────────────────────────────────────────────────

6$:             cmp     R0, #BottomScreen
                bhis    4$
                mov     (R3)+, R1
                xor     R1, (R0)+
                mov     (R3)+, R1
                xor     R1, (R0)+
                mov     (R3)+, R1
                xor     R1, (R0)

7$:             add     #74, R0
                sob     R2, 5$

4$:             jsr     R4, @#110362
                return
; End of function DrawGrib


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Функция анимации взрыва врага
; Вход: R1 - адрес элемента массива в EnemyBuffer
;       R4 - параметр 1
;       R0 - адрес экрана
;       R2 - параметр 2

MoveBlowEnemyProc:
                tst     R4              ; параметр 1 == 0?
                beq     2$              ; да - это первый запуск
                mov     R1, -(SP)       ; иначе
                mov     R0, -(SP)
                trap    24              ; стираем с экрана
                mov     (SP)+, R0
                mov     (SP)+, R1
                dec     (PC)+           ; сколько до появления приза?
PriseCounter$: .word 3
                bne     1$              ; ещё не время
                                        ; делаем новый приз
Secret5$:       mov     #7, PriseCounter$ ; константа значения счётчика до появления приза
                clr     4(R1)
                cmp     #207, @AtBlowFlightAnim ; адрес п/п отработки анимации взрыва самолётика
                                        ; либо указатель на 207, если ещё не взрыв
                bne     1$              ; если самолётик подбили, призов не будет

                mov     #MovePriseProc, 6(R1)
                trap    21              ; спрайт приза
                return
; ───────────────────────────────────────────────────────────────────────────

1$:             clr     (R1)
                return
; ───────────────────────────────────────────────────────────────────────────

2$:             com     4(R1)           ; инвертируем параметр 2
                bne     3$              ; !0 - выходим
                inc     2(R1)           ; иначе параметр 1 ++
                mov     R0, -(SP)       ; меняем вид
                trap    23
                mov     (SP)+, R0
                trap    24
3$:             return
; End of function MoveBlowEnemyProc


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Функция анимации взрыва врага
; Вход: R1 - адрес элемента массива в EnemyBuffer
;       R4 - параметр 1
;       R0 - адрес экрана
;       R2 - параметр 2

MoveGribBlowProc:
                mov     (R1)+, R0
                mov     (R1), R5
                inc     R5
                cmp     #5, R5
                bne     1$
                clr     4(R1)
                clr     -2(R1)
                add     #111., Score
                br      2$
; ───────────────────────────────────────────────────────────────────────────

1$:             mov     R0, -(SP)
                mov     R1, -(SP)
                call    BlowEnemy       ; Взрыв Врага
                                        ; Вход: R5 - номер спрайта в анимации 0..4
                                        ;       R0 - адрес экрана
                mov     (SP)+, R1
                mov     (SP)+, R0

2$:             mov     (R1), R5
                inc     (R1)
                jmp     BlowEnemy       ; Взрыв Врага
                                        ; Вход: R5 - номер спрайта в анимации 0..4
                                        ;       R0 - адрес экрана
; End of function MoveGribBlowProc


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Взрыв самолётика
; Вход: R5 - номер спрайта в анимации 0..4

BlowFlight:     mov     GGAddr, R0      ; текущий адрес спрайта самолётика

; Взрыв Врага
; Вход: R5 - номер спрайта в анимации 0..4
;       R0 - адрес экрана

BlowEnemy:      mov     #sprBlowB1, R1  ; адрес спрайта
                tst     R5
                beq     2$

1$:             add     #SprBlowSize, R1 ; размер спрайта
                sob     R5, 1$

2$:             mov     #30, R3         ; высота спрайта
                sub     #1002, R0

3$:             cmp     R0, #TopScreen
                bhi     4$              ; если выше верхней части экрана - отсекаем
                add     #6, R1          ; ширина спрайта
                cmp     (R0)+, (R0)+
                br      5$
; ───────────────────────────────────────────────────────────────────────────

4$:             cmp     R0, #BottomScreen ; если ниже нижней части экрана - выходим
                bhis    6$
                mov     (R1)+, R2       ; иначе - рисуем
                xor     R2, (R0)+
                mov     (R1)+, R2
                xor     R2, (R0)+
                mov     (R1)+, R2
                xor     R2, (R0)

5$:             add     #74, R0
                sob     R3, 3$

6$:             return
; End of function BlowFlight


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Функция анимации полёта приза
; Вход: R1 - адрес элемента массива в EnemyBuffer
;       R4 - параметр 1
;       R0 - адрес экрана
;       R2 - параметр 2

MovePriseProc:  mov     #104421, R4     ; одна команда приза
                mov     #104422, R5     ; другая
                tst     R2              ; чё параметр 2?
                beq     1$              ; 0
                xor     R5, R4          ; не 0 - R4 <-> R5
                xor     R4, R5
                xor     R5, R4

1$:             com     4(R1)           ; параметр 2
                mov     R4, 0PriseCmdClr$
                mov     R5, 0PriseCmdSet$
                mov     R0, -(SP)
                mov     R1, -(SP)

0PriseCmdClr$:  trap    22              ; стираем с экрана
                mov     (SP)+, R1
                mov     (SP)+, R0
                bit     #77, R0         ; до левого края долетел?
                bne     2$              ; нет ещё
                clr     (R1)            ; да - удаляем из массива
                return
; ───────────────────────────────────────────────────────────────────────────

2$:             dec     R0              ; уменьшаем адрес
                mov     R0, (R1)        ; сохраняем

0PriseCmdSet$:  trap    21              ; рисуем на новом месте
                return
; End of function MovePriseProc


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Функция анимации перемещений Босса
; Вход: R1 - адрес элемента массива в EnemyBuffer
;       R4 - параметр 1
;       R0 - адрес экрана
;       R2 - параметр 2


MoveBossProc:   mov     (R1)+, R0
                mov     (R1), R5
                call    DrawBoss
                add     (R1), R0
                cmp     R0, #BottomScreen-6110 ;67670
                blo     1$
                neg     (R1)

1$:             tst     (R1)
                bpl     2$
                cmp     R0, #TopScreen+200
                bhi     2$
                neg     (R1)

2$:             mov     R0, -(R1)
                return
; End of function MoveBossProc


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


DrawBoss:       jsr     R4, @#110346
                mov     #SprBoss, R1
                mov     #60, R3

1$:             cmp     R0, #TopScreen
                bhis    3$
                add     #14, R1
                add     #100, R0
                br      2$
; ───────────────────────────────────────────────────────────────────────────

3$:             mov     #6, R4

4$:             mov     (R1)+, R2
                xor     R2, (R0)
                add     R5, R0
                xor     R2, (R0)+
                sub     R5, R0
                sob     R4, 4$
                add     #64, R0

2$:             sob     R3, 1$
                jsr     R4, @#110362
                mov     #TopScreen+54, R3
                mov     #6, R4

5$:             clr     (R3)+
                sob     R4, 5$
                return
; End of function DrawBoss


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Функция анимации полёта выстрелов врага
; Вход: R1 - адрес элемента массива в EnemyBuffer
;       R4 - параметр 1
;       R0 - адрес экрана
;       R2 - параметр 2

MoveEnemyBall:  mov     (R1), R0
                add     2(R1), R0
                mov     R0, R2
                ; сделаем отсечку. если вылетел за экран - удалим
                cmp     R2, #TopScreen - 700
                blos    3$
                cmp     R2, #BottomScreen + 700
                bhis    3$
                bic     #177700, R2
                cmp     #76, R2
                bne     2$              ; края экрана ещё не достигли
3$:             mov     (R1), R0        ; старый адрес
                clr     6(R1)           ; удаляем из массива
                clr     (R1)
                ; стираем с экрана
1$:             jmp     DrawBall
; ───────────────────────────────────────────────────────────────────────────
                ; рисуем на новом месте
2$:             call    DrawBall
                mov     (R1), R3        ; старый адрес
                mov     R0, (R1)        ; сохраним новый адрес
                mov     R3, R0          ; и пойдём сотрём со старого места
                br      1$
; End of function MoveEnemyBall


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Вывод на экран шарика
; Вход: R0 - адрес экрана

DrawBall:       jsr     R4, @#110346
                mov     #SprBall, R1
                mov     #7, R2

1$:             cmp     R0, #TopScreen
                blo     2$
                cmp     R0, #BottomScreen
                bhis    3$
                mov     (R1), R3
                xor     R3, (R0)

2$:             add     #100, R0
                tst     (R1)+
                sob     R2, 1$

3$:             jsr     R4, @#110362
                return
; End of function DrawBall




; ███████████████ S U B R O U T I N E ███████████████████████████████████████


AddNewEnemyStg0:call    SearchFreeItem  ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
                call    GetRNDScrAddr   ; Получение случайного адреса экрана
                                        ; Выход: R0 - адрес экрана с правого края
                mov     R0, (R1)+
                mov     #400, (R1)+
                mov     #Enemy1TrackTbl, (R1)+
                mov     #MoveEnemyProc2, (R1) ; Вход: R1 - адрес элемента массива в EnemyBuffer
                                        ;       R4 - параметр 1 (мл байт - номер трапа, ст.байт - битовая маска)
                                        ;       R0 - адрес экрана
                                        ;       R2 - параметр 2 (адрес таблицы)
                trap    0
                return
; End of function AddNewEnemyStg0


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

                ; третий тип врага при Боссе
OnBossEnemy3:   call    SearchFreeItem  ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
                mov     BossAddr, R0
                add     #2274, R0
                call    sub_24370       ; Проверка, пусто ли под объектом
                                        ; Вход: R0 - адрес экрана
                                        ; Если не пусто, то выход на уровень выше
                br      10742$
; ───────────────────────────────────────────────────────────────────────────

AddNewEnemyStg1:call    SearchFreeItem  ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
                call    GetRNDScrAddr   ; Получение случайного адреса экрана
                                        ; Выход: R0 - адрес экрана с правого края

10742$:         mov     R0, (R1)+
                mov     0Enemy3Spr$, (R1)+
                call    GetRNDOffset    ; Получение случайного смещения к адресу экрана
                                        ; (направления движения)
                                        ; Выход: R2 - смещение
                mov     R2, (R1)+
                mov     #MoveEnemyProc1, (R1)

0Enemy3Spr$:    trap    2
                return
; End of function AddNewEnemyStg1


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

                ; второй тип врага при Боссе
OnBossEnemy2:   call    SearchFreeItem  ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
                mov     BossAddr, R0
                add     #2074, R0
                call    sub_24370       ; Проверка, пусто ли под объектом
                                        ; Вход: R0 - адрес экрана
                                        ; Если не пусто, то выход на уровень выше
                br      10404$
; ───────────────────────────────────────────────────────────────────────────

AddNewEnemyStg2:call    SearchFreeItem  ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
                call    GetRNDScrAddr   ; Получение случайного адреса экрана
                                        ; Выход: R0 - адрес экрана с правого края

10404$:         mov     R0, (R1)+       ; запоминаем адрес
                mov     0Enemy11Spr$, (R1)+ ; запоминаем параметр 1
                call    GetRNDOffset    ; Получение случайного смещения к адресу экрана
                                        ; (направления движения)
                                        ; Выход: R2 - смещение
                mov     R2, (R1)+       ; запоминаем параметр 2
                mov     #MoveEnemyProc1, (R1) ; и подпрограмму обработки

0Enemy11Spr$:   trap    12              ; выводим на экран
                return
; End of function AddNewEnemyStg2



; ███████████████ S U B R O U T I N E ███████████████████████████████████████

                ; первый тип врага при Боссе
OnBossEnemy1:   call    SearchFreeItem  ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
                mov     BossAddr, R0
                add     #2574, R0
                call    sub_24370       ; Проверка, пусто ли под объектом
                                        ; Вход: R0 - адрес экрана
                                        ; Если не пусто, то выход на уровень выше
                br      10664$
; ───────────────────────────────────────────────────────────────────────────

AddNewEnemyStg3:call    SearchFreeItem  ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
                mov     GGAddr, R0      ; текущий адрес спрайта самолётика
                call    sub_24364       ; Проверка, пусто ли в правом краю экрана напротив ГГ
                                        ; Вход: R0 - адрес экрана ГГ
                                        ; Если не пусто, то выход на уровень выше
                                        ; Иначе - R0 - адрес экрана с правого края

10664$:         mov     R0, (R1)+       ; сохраним адрес
                cmp     (R1)+, (R1)+    ; без параметров
                mov     #MoveEnemy12Proc, (R1) ; и адрес обработчика
                trap    13
                return
; End of function AddNewEnemyStg3


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


AddNewEnemyStg4:call    SearchFreeItem  ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
                mov     #BottomScreen-2000+76, R0
                tst     1000(R0)
                bne     1$
                mov     R0, (R1)+
                mov     #410, (R1)+
                mov     #Enemy9TrackTbl, (R1)+
                mov     #MoveEnemyProc2, (R1)
                trap    10
1$:             return
; End of function AddNewEnemyStg4


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


AddNewEnemyStg5:call    SearchFreeItem  ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
                call    sub_24412       ; Проверка, пусто ли в правом верхнем углу экрана
                                        ; Выход: R0 - адрес экрана
                                        ; Если не пусто, то выход на уровень выше
                mov     R0, (R1)+
                mov     #407, (R1)+
                mov     #Enemy8TrackTbl, (R1)+
                mov     #MoveEnemyProc2, (R1)
                trap    7
                return
; End of function AddNewEnemyStg5


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


AddNewEnemyStg6:call    SearchFreeItem  ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
                call    GetRNDScrAddr   ; Получение случайного адреса экрана
                                        ; Выход: R0 - адрес экрана с правого края
                mov     R0, (R1)+
                mov     #400, (R1)+
                mov     #EnemyStg6TrackTbl, (R1)+
                mov     #MoveEnemyProc2, (R1)
                trap    0
                return
; End of function AddNewEnemyStg6


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


AddNewEnemyStg7:call    SearchFreeItem  ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
                call    GetRNDScrAddr   ; Получение случайного адреса экрана
                                        ; Выход: R0 - адрес экрана с правого края
                bic     #77, R0
                tst     (R0)+
                cmp     R0, #TopScreen-1300
                blo     2$
                mov     R0, (R1)+
                cmp     (R1)+, (R1)+    ; без параметров
                mov     #MoveEnemy5Proc, (R1)

                trap    4
2$:             return
; End of function AddNewEnemyStg7


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


AddNewEnemyStg8:bit     #140000, @#177710
                beq     15$             ; идём добавлять обычных врагов
                ;будем добавлять гриб
1$:             mov     #EnemyBuffer, R1 ; ищем в таблице

11$:            tst     (R1)            ; не пустой элемент
                beq     12$
                cmp     6(R1), #MoveEnemyGribProc ; и если это гриб
                beq     15$             ; то его добавлять не будет

12$:            add     #EnemyBufferItemSize, R1
                cmp     R1, #EnemyBufferFullEnd
                blo     11$
                ; а иначе - добавим
                call    SearchFreeItem  ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
                com     #-1
                bne     2$
                mov     #TopScreen-3000+100, R0 ; сверху
                br      3$
; ───────────────────────────────────────────────────────────────────────────

2$:             mov     #BottomScreen, R0 ; снизу

3$:             inc     GribOnScreen
                mov     GGAddr, R2      ; самонаведение на ГГ
                bic     #177700, R2
                add     R2, R0
                tst     (R0)+
                mov     R0, (R1)+
                clr     (R1)+
                mov     #MoveEnemyGribProc, 2(R1)
                clr     R1
                jmp     DrawGrib        ; вывод спрайта грибка
                                        ; Вход: R0 - адрес экрана
                                        ;       R1 - номер спрайта 0..2
; ───────────────────────────────────────────────────────────────────────────

15$:            call    SearchFreeItem  ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
                com     #-1
                beq     21$
                mov     #TopScreen, R0
                mov     #Enemy7.1TrackTbl, R2
                br      22$
; ───────────────────────────────────────────────────────────────────────────

21$:            mov     #BottomScreen-2000, R0
                mov     #Enemy7.2TrackTbl, R2

22$:            mov     R0, (R1)+
                mov     #406, (R1)+
                mov     R2, (R1)+
                mov     #MoveEnemyProc2, (R1)
                trap    6
                return
; End of function AddNewEnemyStg8


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


AddNewEnemyStg9:call    SearchFreeItem  ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
                call    GetRNDScrAddr   ; Получение случайного адреса экрана
                                        ; Выход: R0 - адрес экрана с правого края
                mov     R0, (R1)+
                mov     #403, (R1)+
                mov     #Enemy4TrackTbl, (R1)+
                mov     #MoveEnemyProc2, (R1)
                trap    3
                return
; End of function AddNewEnemyStg9


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


AddNewEnemyStg10:
                call    SearchFreeItem  ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
                call    GetRNDScrAddr   ; Получение случайного адреса экрана
                                        ; Выход: R0 - адрес экрана с правого края
                mov     R0, (R1)+
                mov     #405, (R1)+
                mov     #Enemy6TrackTbl, (R1)+
                mov     #MoveEnemyProc2, (R1)
                trap    5
                return
; End of function AddNewEnemyStg10


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


AddNewEnemyStg11:
                call    SearchFreeItem  ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
                call    GetRNDScrAddr   ; Получение случайного адреса экрана
                                        ; Выход: R0 - адрес экрана с правого края
                mov     R0, (R1)+
                mov     #401, (R1)+     ; параметр 1 - мл байт - номер трапа, ст.байт - битовая маска
                mov     #Enemy2TrackTbl, (R1)+
                mov     #MoveEnemyProc2, (R1)
                trap    1
                return
; End of function AddNewEnemyStg11


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


AddNewEnemyStg12:
                call    SearchFreeItem  ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
                call    GetRNDScrAddr   ; Получение случайного адреса экрана
                                        ; Выход: R0 - адрес экрана с правого края
                mov     R0, (R1)+
                mov     #411, (R1)+
                mov     #Enemy10TrackTbl, (R1)+
                mov     #MoveEnemyProc2, (R1)
                trap    11
                return
; End of function AddNewEnemyStg12


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


AddNewEnemyStg13:
                call    SearchFreeItem  ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
                call    GetRNDScrAddr   ; Получение случайного адреса экрана
                                        ; Выход: R0 - адрес экрана с правого края
                mov     R0, (R1)+
                mov     #406, (R1)+
                mov     #Enemy7.3TrackTbl, (R1)+
                mov     #MoveEnemyProc2, (R1)
                trap    6
                return
; End of function AddNewEnemyStg13


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Проверка, пусто ли в правом краю экрана напротив ГГ
; Вход: R0 - адрес экрана ГГ
; Если не пусто, то выход на уровень выше
; Иначе - R0 - адрес экрана с правого края

sub_24364:      bis     #76, R0
; End of function sub_24364


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Проверка, пусто ли под объектом
; Вход: R0 - адрес экрана
; Если не пусто, то выход на уровень выше

sub_24370:      tst     500(R0)
                bne     RetL1$
                tst     1100(R0)
                bne     RetL1$
                return
; ───────────────────────────────────────────────────────────────────────────

RetL1$:         clr     (SP)+
                return
; End of function sub_24370


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Проверка, пусто ли в правом верхнем углу экрана
; Выход: R0 - адрес экрана
; Если не пусто, то выход на уровень выше

sub_24412:      mov     #TopScreen-102, R0
                tst     @#TopScreen+1276
                bne     RetL1$
                tst     @#TopScreen+376
                bne     RetL1$
                return
; End of function sub_24412



; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Анимация и обработка всех врагов

EnemysAnim:     mov     #EnemyBuffer, R1

ena_1$:         mov     R1, R3          ; текущий элемент
                mov     (R3)+, R0       ; адрес экрана
                beq     2$              ; 0 - элемент пуст
                mov     (R3)+, R4       ; параметр 1
                mov     (R3)+, R2       ; параметр 2
                mov     R1, -(SP)
Secret2$:       call    @(R3)+          ; сюда записывается 4733 при правильном пароле
                                        ; выполнение подпрограммы обработки поведения врага
                mov     (SP)+, R1

2$:             add     #EnemyBufferItemSize, R1
                cmp     R1, #EnemyBufferFullEnd ; до конца дошли?
                blo     ena_1$          ; нет - продолжим
                return                  ; выходим
; End of function EnemysAnim


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; добавление нового врага

AddEnemys:      tst     (PC)+           ; смотрим этот счётчик
StageDurationCnt1:.word 0
                beq     2$              ; стало 0 - началась вторая стадия
                ; первая стадия этапа
                ; тут редкие враги
                dec     StageDurationCnt1 ; уменьшаем
                call    GetRNDScrAddr   ; Получение случайного адреса экрана
                                        ; Выход: R0 - адрес экрана с правого края
                bic     #177077, R0
                cmp     #600, R0        ; потому что условие появления очень не очень
                bne     1$              ; такое редко случается
                                        ; даже как-то пусто лететь
                mov     StageNum, R0    ; Номер текущего этапа
                asl     R0
                jmp     @FuncNewEnemys(R0) ; и добавим нового врага, соответствующего этапу
; ───────────────────────────────────────────────────────────────────────────
1$:             return
; ───────────────────────────────────────────────────────────────────────────
                ; вторая стадия
                ; пока не 0, просто добавляем врагов
                ; как обнулится - добавляем босса
2$:             dec     (PC)+           ; уменьшаем счётчик длительности этапа
StageDurationCnt2:.word 0
                bne     4$              ; пока не 0, просто добавим нового врага
                cmp     StageNum, #3    ; если номер текущего этапа меньше 3
                blo     5$              ; просто перейдём к новому этапу
                tst     @#Temp2         ; босса добавлять надо?
                beq     3$              ; да, надо
5$:             jmp     NewStage        ; просто перейдём к новому этапу
; ───────────────────────────────────────────────────────────────────────────
3$:             mov     #BossAddr, R1
                tst     (R1)            ; босс уже добавлен?
                bne     4$              ; да - просто добавляем врагов
                ; добавляем Босса
                mov     #TopScreen-10000+54, (R1)+
                mov     #100, (R1)+
                clr     (R1)+
                mov     #MoveBossProc, (R1)
                inc     BossFlag
                mov     StageNum, R0  ; Номер текущего этапа
                inc     R0
                asl     R0
                asl     R0
                asl     R0
                add     #23, R0
                mov     R0, BossHealth
4$:             ;jmp     AddNewEnemy     ; Функция добавления нового врага
; End of function AddEnemys


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Функция добавления нового врага

AddNewEnemy:    tst     BossFlag        ; на экране Босс?
                beq     11$             ; нет, всё как обычно
                ; на экране Босс
                mov     @#177710, R0    ; получим случайное число
                sub     Score, R0
                bic     #177760, R0
                cmp     R0, #2
                bhi     16$              ; больше 2 - врага не добавляем
                asl     R0              ; тут добавляем врагов
                jmp     @OnBossEnemyTbl(R0) ; которые босс выплёвывает
; ───────────────────────────────────────────────────────────────────────────

11$:            mov     #GetRndAddrAcc, R1
                add     #2, (R1)
                cmp     (R1), #40000    ; дошли до конца?
                blo     12$             ; нет
                mov     #512, (R1)      ; да, а теперь другое начальное значение

12$:            mov     @(R1)+, R1      ; берём число
                sub     @#177710, R1    ; получим случайное
                cmp     StageNum, #2    ; текущий этап больше 1
                bhis    14$             ; да
                bit     #500, R1        ; нет, делаем доп условие
                bne     16$             ; чтобы не добавлять врага

14$:            bic     #177760, R1     ; очистим ненужные биты
                cmp     R1, StageNum    ; то, что получилось, больше номера текущего этапа?
                bhi     16$             ; да - выход
                asl     R1              ; а иначе - добавление врага, соответствующего этапу.
                jmp     @FuncNewEnemys(R1)
16$:            return
; End of function AddNewEnemy


; ───────────────────────────────────────────────────────────────────────────
FuncNewEnemys:  .word AddNewEnemyStg0   ; этап 0
                .word AddNewEnemyStg1   ; этап 1
                .word AddNewEnemyStg2   ; этап 2
                .word AddNewEnemyStg3   ; этап 3
                .word AddNewEnemyStg4   ; этап 4
                .word AddNewEnemyStg5   ; этап 5
                .word AddNewEnemyStg6   ; этап 6
                .word AddNewEnemyStg7   ; этап 7
                .word AddNewEnemyStg8   ; этап 8
                .word AddNewEnemyStg9   ; этап 9
                .word AddNewEnemyStg10  ; этап 10
                .word AddNewEnemyStg11  ; этап 11
                .word AddNewEnemyStg12  ; этап 12
                .word AddNewEnemyStg13  ; этап 13

OnBossEnemyTbl: .word OnBossEnemy1
                .word OnBossEnemy2
                .word OnBossEnemy3


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Проверка попаданий в мелких врагов
; Начисление счёта и запуск анимации взрыва врага

CheckEnemyHit:  mov     #ShootsTbl, R1  ; таблица выстрелов ГГ

1$:             mov     (R1), R0        ; адрес экрана пули
                beq     6$              ; если элемент пуст, идём к следующему
                ; не пуст, обработаем
                mov     #EnemyBuffer, R5 ; таблица врагов

4$:             mov     (R5), R3        ; адрес экрана врага
                bne     2$              ; не пуст, значит надо проверять
5$:             add     #EnemyBufferItemSize, R5
                cmp     R5, #EnemyBufferFullEnd ; таблица закончилась?
                blo     4$              ; нет ещё
                                        ; да
6$:             tst     (R1)+           ; переходим к следующей пуле
                cmp     R1, #ShootsTblEnd ; таблица закончилась?
                blo     1$              ; нет ещё
                return                  ; выход
; ───────────────────────────────────────────────────────────────────────────

2$:             cmp     R0, R3          ; если адрес пули меньше адреса врага
                blo     5$              ; то, пуля пролетает над врагом
                add     #2100, R3       ; теперь нижняя граница врага
                cmp     R0, R3          ; если адрес пули > нижней границы адреса врага
                bhi     5$              ; то пуля пролетает под врагом
                ; иначе пуля может попасть во врага
                mov     R0, R2
                bic     #177700, R2     ; получим горизонтальную позицию
                bic     #177700, R3
                cmp     R2, R3          ; если равны
                beq     8$              ; то попали во врага
                tst     (R2)+           ; враг большой, занимает 2 слова
                cmp     R2, R3          ; можем и туда попасть
                bne     5$              ; не, пока не попали
                ; попали во врага
8$:             mov     SprFlightBullet, R2
                mov     6(R5), R3       ; функция обработки анимации врага
                mov     2(R5), R4       ; параметр 1
                ; проверим тип врага, и соответственно обработаем
                cmp     #MoveEnemyProc1, R3
                bne     9$
                cmp     (PC)+, R4       ; если враг - Enemy11
                        trap 12
                beq     3$              ; то это неубиваемый шар
                add     #3, Score       ; а за остальных начисляются очки
                br      12$             ; и обработаем попадание
                ; с неубиваемым шаром ничего не делается
3$:             xor     R2, (R0)        ; иначе - удаляем пулю с экрана
                clr     (R1)            ; убираем её из массива
                dec     NumShoots       ; текущее количество выстрелов
                br      6$              ; переходим к следующей пуле
; ───────────────────────────────────────────────────────────────────────────

9$:             cmp     #MoveEnemyProc2, R3
                bne     10$
                bic     #177400, R4     ; получаем номер трапа
                add     #104400, R4     ; получим номер команды
                add     #15., Score     ; начисляем очки
                br      12$
; ───────────────────────────────────────────────────────────────────────────

10$:            cmp     #MoveEnemy5Proc, R3
                bne     11$
                mov     (PC)+, R4       ; получим номер команды
                        trap 4
                add     #25., Score     ; начисляем очки
                br      12$

11$:            cmp     #MoveEnemy12Proc, R3
                bne     6$              ; остальных врагов пули не берут
                mov     (PC)+, R4       ; получим номер команды
                        trap 13
                add     #5, Score       ; начисляем очки

12$:            xor     R2, (R0)        ; удаляем пулю с экрана
                clr     (R1)            ; убираем пулю из массива
                dec     NumShoots       ; текущее количество выстрелов
                mov     (R5), R0        ; снова берём адрес экрана врага
                mov     R1, -(SP)
                mov     R5, -(SP)
                mov     R4, (PC)        ; задаём команду стирания врага
                trap    0               ; стираем его с экрана
                mov     (SP), R5
                mov     (R5), R0        ; снова берём адрес экрана врага
                trap    23              ; спрайт взрыва врага
                mov     (SP)+, R5
                mov     (SP)+, R1
                tst     (R5)+
                clr     (R5)+           ; начальные значения
                clr     (R5)+           ; параметров
                mov     #MoveBlowEnemyProc, (R5)+ ; Функция анимации взрыва врага
                mov     #100200, ROMAddrSnd ; запускаем звук взрыва врага
                br      6$              ; идём к следующей пуле
; End of function CheckEnemyHit



; ███████████████ S U B R O U T I N E ███████████████████████████████████████


CheckBossHit:   tst     BossFlag        ; если на экране Босс
                beq     1$              ; нету - просто выход
                ; есть пойдём проверим попадания в Босса
                mov     BossAddr, R2    ; адрес Босса
                mov     #ShootsTbl, R1

2$:             mov     (R1)+, R5       ; адрес пули
                bne     4$              ; если есть - идём проверять

3$:             cmp     R1, #ShootsTblEnd
                bne     2$
1$:             return
; ───────────────────────────────────────────────────────────────────────────

4$:             cmp     R5, R2          ; адрес пули меньше адреса босса?
                blo     3$              ; да - пуля летит выше
                mov     R2, R0
                add     #6000, R0       ; нижняя граница босса
                cmp     R5, R0          ; адрес пули больше адреса босса?
                bhi     3$              ; да -пуля летит ниже
                mov     R5, R3
                bic     #177700, R3     ; теперь позиция по горизонтали
                bic     #177700, R0
                cmp     R3, R0          ; адрес пули меньше адреса босса?
                blo     3$              ; да - пуля ещё не долетела
                add     #14, R0         ; правая граница Босса
                cmp     R3, R0          ; адрес пули больше равен адресу босса?
                bhis    3$              ; да - пуля уже перелетела
                ; попали
                mov     SprFlightBullet, R3
                xor     R3, (R5)        ; удаляем пулю с экрана
                clr     -2(R1)          ; удаляем её из массива
                dec     NumShoots       ; текущее количество выстрелов
                dec     BossHealth      ; отнимаем у босс здоровье
                beq     9$              ; кончилось, Босс подбит
                ; звук попадания в босса
                jsr     R4, @#110346
                mov     #100300, R1
                mov     #6, R2

5$:             mov     #20, R3
                mov     (R1)+, R0

6$:             asr     R0
                bcs     7$
                mov     #320, @#177716
                br      8$
; ───────────────────────────────────────────────────────────────────────────

7$:             mov     #220, @#177716

8$:             mov     #25, R4
                sob     R4, .
                sob     R3, 6$
                sob     R2, 5$
                mov     #220, @#177716
                jsr     R4, @#110362
                br      3$              ; и пойдём смотреть следующую пулю
; ───────────────────────────────────────────────────────────────────────────
                ; убили Босса
9$:             clr     BossFlag        ; всё убили Босса
                clr     BossAddr        ; удаляем из массива
                clr     BossMoveProc
                mov     #100200, ROMAddrSnd
                mov     #50, StageDurationCnt2
                mov     R2, R0
                mov     #60, R3
                mov     #SprBoss, R1    ; удаляем с экрана

10$:            mov     #6, R5

11$:            mov     (R1)+, R4
                xor     R4, (R0)+
                sob     R5, 11$
                add     #64, R0
                sob     R3, 10$
                mov     #word_31432, R5 ; таблица смещений взрывов на боссе

12$:            tst     (R5)            ; таблица закончилась?
                beq     13$             ; да - идём дальше
                mov     R2, R0          ; адрес босса на экране
                add     (R5)+, R0       ; + смещение
                call    SearchFreeItem  ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
                mov     R0, (R1)+       ; заполняем анимациями взрывов
                clr     (R1)+
                clr     (R1)+
                mov     #MoveBlowEnemyProc, (R1)+ ; Функция анимации взрыва врага
                mov     R5, -(SP)
                mov     R2, -(SP)
                trap    23
                mov     (SP)+, R2
                mov     (SP)+, R5
                br      12$
; ───────────────────────────────────────────────────────────────────────────

13$:            tst     (R5)+           ; теперь вторая таблица

14$:            mov     R2, R0          ; то же самое, но с большими взрывами
                add     (R5)+, R0
                call    SearchFreeItem  ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
                mov     R0, (R1)+
                clr     (R1)+
                clr     (R1)+
                mov     #MoveGribBlowProc, (R1)+
                jsr     R4, @#110346
                mov     R5, -(SP)
                clr     R5
                call    BlowEnemy       ; Взрыв Врага
                                        ; Вход: R5 - номер спрайта в анимации 0..4
                                        ;       R0 - адрес экрана
                mov     (SP)+, R5
                jsr     R4, @#110362
                tst     (R5)
                bne     14$
                mov     #66, StageDurationCnt2
                inc     @#Temp2         ; всё, босса подбили
                return
; END OF FUNCTION CHUNK FOR CheckBossHit

; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; проверка на попадание пульками во врагов

CheckAllEnemyHit:call    CheckEnemyHit  ; Проверка попаданий в мелких врагов
                                        ; Начисление счёта и запуск анимации взрыва врага
                call    CheckBossHit    ; проверка попаданий в босса
                ; и проверка попаданий в гриб
                tst     GribOnScreen    ; гриб на экране есть?
                beq     3$              ; нету - и делать нечего
                ; иначе проверим, попали ли в гриб
                mov     #ShootsTbl, R1  ; таблица пуль
2$:             mov     (R1)+, R0       ; берём очередную пулю
                beq     7$              ; нету - идём к следующему элементу
                ; поищем гриб в массиве врагов
                mov     #EnemyBuffer, R5

5$:             mov     (R5), R3        ; смотрим очередной элемент
                beq     6$              ; пусто - идём к следующему
                cmp     #MoveEnemyGribProc, 6(R5) ; это гриб?
                beq     8$              ; да идём посмотрим, попали ли

6$:             add     #EnemyBufferItemSize, R5
                cmp     R5, #EnemyBufferFullEnd
                blo     5$

7$:             cmp     R1, #ShootsTblEnd
                blo     2$
3$:             return
; ───────────────────────────────────────────────────────────────────────────

8$:             cmp     R0, R3          ; адрес пули меньше адреса гриба?
                blo     6$              ; да, пуля летит выше
                add     #2600, R3       ; теперь нижняя граница
                cmp     R0, R3          ; адрес пули больше адреса гриба?
                bhi     6$              ; да, пуля летит ниже
                mov     R0, R2
                bic     #177700, R2     ; теперь горизонтальные позиции
                bic     #177700, R3
                cmp     R2, R3          ; адрес пули меньше адреса гриба?
                blo     6$              ; да - ещё не долетела
                cmp     (R3)+, (R3)+    ; правый адрес гриба
                cmp     R3, R2          ; адрес гриба меньше адреса пули?
                blo     6$              ; да - пуля уже перелетела
                ; иначе - попали в гриб
                clr     -2(R1)          ; удаляем из массива
                mov     SprFlightBullet, R2 ; пуля
                xor     R2, (R0)        ; стираем с экрана
                mov     R1, -(SP)
                mov     (R5)+, R0       ; адрес гриба
                mov     (R5), R1        ; тип анимации
                clr     (R5)+
                clr     (R5)+
                mov     #MoveGribBlowProc, (R5)
                mov     word_26174(R1), R1 ; номер спрайта
                call    DrawGrib        ; вывод спрайта грибка
                                        ; Вход: R0 - адрес экрана
                                        ;       R1 - номер спрайта 0..2
                clr     GribOnScreen    ; сбрасываем флаг гриба на экране
                dec     NumShoots       ; текущее количество выстрелов
                mov     #100200, ROMAddrSnd
                clr     R5
                call    BlowEnemy       ; Взрыв Врага
                                        ; Вход: R5 - номер спрайта в анимации 0..4
                                        ;       R0 - адрес экрана
                mov     (SP)+, R1
                br      7$              ; пойдём осмотрим другие пули
; End of function CheckAllEnemyHit


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Включение защитного поля, если пойман соответствующий приз
; Проверка на призы и пойман ли приз
; Нужно ли применять эффект приза

CatchPrise:     tst     ShieldFieldFlag ; защитное поле включено?
                beq     1$              ; нет
                call    ShieldEffectAnim ; да - отобразим

1$:             mov     #EnemyBuffer, R4 ; осмотрим буфер врагов

2$:             tst     (R4)
                beq     3$
                cmp     #MovePriseProc, 6(R4) ; если это приз
                beq     4$              ; идём проверять, поймали ли

3$:             add     #EnemyBufferItemSize, R4
                cmp     R4, #EnemyBufferFullEnd
                blo     2$
                return
; ───────────────────────────────────────────────────────────────────────────

4$:             mov     GGAddr, R2      ; то проверим, поймали ли его
                sub     #2000, R2
                mov     (R4), R0
                cmp     R0, R2
                blo     3$
                add     #3100, R2
                cmp     R0, R2
                bhi     3$
                bic     #177700, R2
                mov     R0, R3
                bic     #177700, R3
                sub     #2, R2
                cmp     R2, R3
                bhi     3$
                add     #10, R2
                cmp     R2, R3
                blo     3$
; да поймали, уберём с экрана
                mov     #104421, 0CmdPriseOff$
                tst     4(R4)
                beq     5$
                inc     0CmdPriseOff$

5$:             clr     (R4)
                mov     R4, -(SP)

0CmdPriseOff$:  trap    21
                cmp     DelayGetPriseConst$+2, DelayGetPrise ; приз применять пора?
                beq     6$              ; да
                call    IndicatePrise   ; нет - только меняем индикацию на экране
                br      8$
; ───────────────────────────────────────────────────────────────────────────

6$:             call    ApplyPrise      ; Применяем текущий приз
                clr     PriseNum        ; номер пойманного приза
                mov     #PanelPriseAddr, R0
                add     #50., Score
                trap    116
8$:             mov     (SP)+, R4
                br      3$
; End of function CatchPrise


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Применяем текущий приз

ApplyPrise:     mov     PriseNum, R0    ; номер пойманного приза
                asl     R0
                jmp     @PriseTbl(R0)
; End of function ApplyPrise

; ───────────────────────────────────────────────────────────────────────────
PriseTbl:       .word SpeedUp
                .word SpeedShoot
                .word UseBobm
                .word AutoShoot
                .word SetTrex
                .word ShieldOn

; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Ускорение

SpeedUp:        tst     SpeedValue      ; есть куда ускоряться?
                beq     1$              ; всё уже, максимум
                dec     SpeedValue      ; есть - ускоряемся
1$:             return
; End of function SpeedUp

; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; ускорение стрельбы

SpeedShoot:     cmp     #5, MaxShoots   ; максимальное количество одновременных выстрелов
                beq     1$
                inc     MaxShoots       ; максимальное количество одновременных выстрелов
1$:             return
; End of function SpeedShoot


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Взрыв бомбы (уничтожает всех на экране)

UseBobm:        clr     BombOnBossFlag  ; очистим флаг
                cmp     #MoveBossProc, BossMoveProc ; на экране БОСС есть?
                bne     1ub$            ; нет
                ; есть
                inc     (PC)+           ; установим флаг
BombOnBossFlag: .word 0

TmpBossParam1:  mov     BossParam1, #0  ; сохраним направление движения БОССа
1ub$:           ;jmp     BlowBombFunc    ; идём взрывать бомбу
; End of function UseBobm

; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; анимация взрыва бомбы

BlowBombFunc:   clr     GribOnScreen
                mov     #TopScreen, R0
                mov     #BottomScreen, R1 ; эффект вспышки на экране
                bic     #1000, @#177664

1$:             comb    (R0)+
                tst     (R0)+
                cmp     R0, R1
                blo     1$
                bis     #1000, @#177664
                mov     #6666, R0
                sob     R0, .
                bic     #1000, @#177664
                call    Cls1
                ; теперь обработаем всех врагов
                mov     #EnemyBuffer, R5

3$:             mov     (R5), R0        ; элемент пуст?
                beq     4$              ; да
                mov     R5, -(SP)       ; взрыв врага
                trap    23
                mov     (SP)+, R5
                clr     4(R5)
                clr     2(R5)
                mov     #MoveBlowEnemyProc, 6(R5) ; Функция анимации взрыва врага
                mov     #100200, ROMAddrSnd

4$:             add     #EnemyBufferItemSize, R5
                cmp     R5, #EnemyBufferFullEnd
                blo     3$
                bis     #1000, @#177664
                call    ClrShootTbl     ; очистка буфера пуль
                call    BlowBoss        ; Взрыв босса бомбой
                mov     GGAddr, R0      ; текущий адрес спрайта самолётика
                call    DrawFlight      ; Вход: R0 - адрес экрана
                call    InitialDrawStars ; Начальное отображение звёзд по таблице на экране
                tst     ShieldFieldFlag ; флаг включённого защитного поля
                beq     Ret_4$
                mov     ShieldEffectOffset, R1
                bne     6$
                mov     #EffectOffsetTblSize, R1

6$:             dec     R1
                jmp     DrawShieldEffect ; рисовать эффект защитного поля
                                        ; Вход: R1 - номер смещения в таблице смещений
; End of function BlowBombFunc


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Взрыв босса бомбой

BlowBoss:       clr     NumShoots       ; текущее количество выстрелов
                tst     BombOnBossFlag  ; босс на экране есть?
                beq     5$              ; нету - выходим
                mov     TmpBossParam1+4, BossParam1 ; восстанавливаем параметр 1 Босса
                mov     #MoveBossProc, BossMoveProc ; а так же его функцию анимации
                mov     BossAddr, R0    ; адрес экрана
                mov     R0, -(SP)
                trap    23              ; взрыв
                mov     (SP)+, R0
                mov     #60, R1
                mov     #SprBoss, R3

1$:             cmp     R0, #TopScreen+100 ; босс на верху экрана?
                bhi     2$              ; да
                add     #14, R3         ; нет + строка спрайта
                add     #100, R0        ; + строка экрана
                br      4$
; ───────────────────────────────────────────────────────────────────────────

2$:             mov     #6, R2          ; ширина спрайта в словах

3$:             mov     (R3)+, R4       ; стираем босса
                xor     R4, (R0)+
                sob     R2, 3$
                add     #64, R0

4$:             sob     R1, 1$
                sub     #15, BossHealth ; отбираем здоровье
                bhi     5$              ; если больше 0, то норм
                mov     #1, BossHealth  ; иначе - сделаем больше нуля
5$:             return
; End of function BlowBoss


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


AutoShoot:      inc     (PC)+
AutoShootFlag:  .word 0                 ; флаг автострельбы
                return
; End of function AutoShoot


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Установить режим ТРЕКС (изменение траектории полёта пуль)

SetTrex:        inc     (PC)+
TrexMode:       .word 0                 ; режим ТРЕКС (изменение траектории полёта пуль)
                return
; End of function SetTrex


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Включение защитного поля

ShieldOn:       mov     #PanelShieldAddr, R0
                mov     #PanelShieldAddr+6, ShieldScaleAddr
                mov     #100000, ShieldScaleMask
                mov     #-1, R1         ; нарисуем полную шкалу защитного поля
                mov     #4, R2

1$:             mov     R1, (R0)+
                mov     R1, 76(R0)
                mov     R1, 176(R0)
                sob     R2, 1$
                tst     ShieldFieldFlag ; флаг включённого защитного поля
                bne     Ret_4$
                inc     ShieldFieldFlag ; флаг включённого защитного поля
                br      14064$       ; запускаем анимацию защитного поля
; ───────────────────────────────────────────────────────────────────────────
; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; если защитное поле включено, оставить включённым

TestShieldOn:   tst     ShieldFieldFlag ; флаг включённого защитного поля
                beq     Ret_4$

14064$:         mov     ShieldEffectOffset, R1
                dec     R1
                jmp     DrawShieldEffect ; рисовать эффект защитного поля
                                        ; Вход: R1 - номер смещения в таблице смещений
Ret_4$:         return
; End of function TestShieldOn
; End of function ShieldOn


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Увеличение жизней за каждые 5000. очков,
; движение звёзд и вывод счёта на экран

CheckoutScore:  mov     Score, R5       ; берём счёт
                sub     AddLiveVal, R5  ; вычитаем граничное значение
                cmp     R5, (PC)+       ; достигло нужной величины?
AddLiveBound$:  .word   5000.           ; за каждые 5000. очков даётся жизнь
                blo     1$              ; нет ещё
                add     AddLiveBound$, AddLiveVal ; да - задаём следующее граничное значение
                inc     Lives           ; увеличиваем число жизней
                call    ShowLives       ; Отображение на панели количества жизней

1$:             call    CalcMoveStars   ; Вычисляем новые координаты звёзд и отображаем их
                dec     (PC)+           ; пора?
0Counter$:      .word 20
                bne     Ret_7$          ; нет ещё
                mov     #70, @#0Counter$ ; да - выводим счёт на экран, но почему-то не кратно 5
                mov     #PanelScoreAddr, AS ; Адрес символа
                mov     Score, R4
; END OF FUNCTION CHUNK FOR CheckoutScore

; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Вывод десятичного числа.
; Вход: R4 - число

DecOut:         mov     #'0, R0

1$:             sub     #10000., R4
                bcs     2$
                inc     R0
                br      1$
; ───────────────────────────────────────────────────────────────────────────

2$:             add     #10000., R4
                iot
                mov     #'0, R0

3$:             sub     #1000., R4
                bcs     4$
                inc     R0
                br      3$
; ───────────────────────────────────────────────────────────────────────────

4$:             add     #1000., R4
                iot
                mov     #'0, R0

5$:             sub     #100., R4
                bcs     6$
                inc     R0
                br      5$
; ───────────────────────────────────────────────────────────────────────────

6$:             add     #100., R4
                iot
                mov     #'0, R0

7$:             sub     #10., R4
                bcs     8$
                inc     R0
                br      7$
; ───────────────────────────────────────────────────────────────────────────

8$:             add     #10., R4
                iot
                mov     #'0, R0
                add     R4, R0
                iot
Ret_7$:         return
; End of function DecOut


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Проверка на попадание в самолётик

CheckFlightHit: call    CatchPrise      ; Включение защитного поля, если пойман соответствующий приз
                                        ; Проверка на призы и пойман ли приз
                                        ; Нужно ли применять эффект приза
                call    CheckFlightDamageAnim ; уже отрабатывается анимация подбития?
                bne     4$              ; да - дальше не идём
                mov     GGAddr, R0      ; текущий адрес спрайта самолётика
                mov     #SprFlight, R1  ; проверка на коллизию
                clr     R5
                mov     #11, R2

1$:             mov     #6, R3

2$:             tstb    (R1)
                beq     3$
                cmpb    (R1), (R0)      ; не попало ли что-нибудь в самолётик
                beq     3$
                inc     R5              ; счётчик несовпадений

3$:             cmpb    (R1)+, (R0)+
                sob     R3, 2$
                add     #72, R0
                sob     R2, 1$
                cmp     R5, #4          ; если не больше критического значения
                ; ### а иначе - самолётик подбили, меняем blos на br и становимся бессмертными
                ;blos    4$              ; ### то всё ещё в порядке
                br      4$              ; ### то всё ещё в порядке
                mov     GGAddr, R0      ; текущий адрес спрайта самолётика
                ; стираем самолётик, рисуем взрыв
                call    DrawFlight    ; Вход: R0 - адрес экрана
                clr     CurBlowAnimSpr ; номер текущего спрайта анимации взрыва самолётика
                clr     R5
                call    BlowFlight      ; Взрыв самолётика
                                        ; Вход: R5 - номер спрайта в анимации 0..4
                mov     #BlowFlightAnim, AtBlowFlightAnim ; задаём п/п анимации подбития
4$:             return                  ; нет анимации подбития самолётика
; End of function CheckFlightHit

; ───────────────────────────────────────────────────────────────────────────

; ███████████████ S U B R O U T I N E ███████████████████████████████████████


CheckFlightDamageAnim:
                cmp     #207, @AtBlowFlightAnim ; уже отрабатывается анимация?
                bne     NoAnims         ; да - выйдем с признаком
                tst     ShieldFieldFlag ; или если включено защитное поле
                ; то тоже не дадим запустить анимацию
NoAnims:        return                  ; нет анимации подбития самолётика
; End of function CheckFlightDamageAnim


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


BlowFlightAnim: mov     #134, StageDurationCnt2
                com     #-1             ; отрабатывать через раз
                beq     2$
                mov     (PC)+, R5
CurBlowAnimSpr: .word 5                 ; номер текущего спрайта анимации взрыва самолётика
                call    BlowFlight      ; Взрыв самолётика
                                        ; Вход: R5 - номер спрайта в анимации 0..4
                inc     CurBlowAnimSpr  ; номер текущего спрайта анимации взрыва самолётика
                mov     CurBlowAnimSpr, R5 ; номер текущего спрайта анимации взрыва самолётика
                cmp     #5, R5
                beq     1$
                call    BlowFlight      ; Взрыв самолётика
                                        ; Вход: R5 - номер спрайта в анимации 0..4
                mov     #100200, ROMAddrSnd
2$:             return
; ───────────────────────────────────────────────────────────────────────────

1$:             mov     #14, AfterBlowFlightAnimCntr ; счётчик, сколько ещё играть анимацию после взрыва самолётика
                                        ; перед темь как уменьшить жизни и продолжить
                mov     #AfterBlowFlightAnim, AtBlowFlightAnim ; адрес п/п отработки анимации взрыва самолётика
                                        ; либо указатель на 207, если ещё не взрыв
                return
; END OF FUNCTION CHUNK FOR BlowFlightAnim

; ███████████████ S U B R O U T I N E ███████████████████████████████████████


AfterBlowFlightAnim:
                dec     (PC)+
AfterBlowFlightAnimCntr:.word 0         ; счётчик, сколько ещё играть анимацию после взрыва самолётика
                                        ; перед темь как уменьшить жизни и продолжить
                beq     1$
                return

1$:             dec     Lives
                bne     0SteelAlive$
FlightDead:     call    ShowLives       ; Отображение на панели количества жизней
                call    ShowGameOver
                jmp     NextGameEnd$
; End of function AfterBlowFlightAnim

0SteelAlive$:   call    ShowLives       ; Отображение на панели количества жизней
                ;jmp     InitGameValues

; ███████████████ S U B R O U T I N E ███████████████████████████████████████


InitGameValues: call    InitGamePanel   ; Инициализация индикаторов панели и переменных
                mov     #1, MaxShoots   ; максимальное количество одновременных выстрелов
                mov     #3, SpeedValue  ; начальная скорость
                mov     #NoAnims, AtBlowFlightAnim ; адрес п/п отработки анимации взрыва самолётика
                                        ; либо указатель на 207, если ещё не взрыв

InitGameValues2:bic     #1000, @#177664
                call    Cls1
                clr     AutoShootFlag   ; выключаем автоматическую стрельбу
                clr     TrexMode        ; выключаем режим ТРЕКС (изменение траектории полёта пуль)
                clr     GribOnScreen    ; инициализируем флаг гриба на экране
                clr     ROMAddrSnd      ; выключаем звук взрыва врага

                call    StartingDrawFlight ; отображение самолётика с начальной позиции
                call    InitialDrawStars ; Начальное отображение звёзд по таблице на экране
                clr     NumShoots       ; текущее количество выстрелов
                clr     @#Temp2         ; временный флаг Босса, нужно будет показать
                clr     BossFlag        ; флаг Босса на экране
                mov     #EnemyBuffer, R1 ; очистка буфера врагов

1$:             clr     (R1)+
                cmp     R1, #EnemyBufferFullEnd
                blo     1$
                call    ClrShootTbl     ; очистка буфера пуль
                mov     #5, R0

2$:             clr     (R1)+
                sob     R0, 2$
                clr     GGShootSndPtr   ; выключаем звук стрельбы
                clr     (PC)+
DelayGetPrise:  .word 6                 ; задержка при нажатии на "Fire" перед применением приза
                call    TestShieldOn    ; если защитное поле включено, оставить включённым
                bis     #1000, @#177664
                return
; End of function InitGameValues

; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; инициализация переменных

InitGameValues3:clr     Score           ; обнуляем счёт
                mov     #10., Lives     ; зададим начальное количество жизней
                call    ShowLives       ; Отображение на панели количества жизней
                clr     StageNum        ; обнулим номер этапа
                mov     #1000, StageDurationCnt1 ; зададим начальную длительность
                mov     #1500, StageDurationCnt2 ; 0-го этапа
                clr     AddLiveVal      ; и граничное значение увеличения жизней обнулим
                return
; End of function InitGameValues3


; ───────────────────────────────────────────────────────────────────────────
; очистка буфера пуль
ClrShootTbl:    mov     #ShootsTbl, R1

1$:             clr     (R1)+
                cmp     R1, #ShootsTblEnd
                bne     1$
                return
; ───────────────────────────────────────────────────────────────────────────


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Отображение на панели количества жизней

ShowLives:      mov     #PanelLivesAddr, R0
                mov     R0, R1
                mov     #5, R2          ; очищаем шкалу жизней, 5 слов 10. байт

1$:             mov     #8., R3

2$:             clr     (R1)
                add     #100, R1
                sob     R3, 2$
                sub     #776, R1
                sob     R2, 1$
                mov     Lives, R3       ; рисуем текущее количество жизней
                beq     5$

3$:             mov     #6, R2

4$:             add     #100, R0
                movb    #74, (R0)
                sob     R2, 4$
                sub     #577, R0
                cmp     R0, #PanelLivesAddr+12
                beq     5$
                sob     R3, 3$
5$:             return
; End of function ShowLives


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


NewStage:       bic     #1000, @#177664
                call    Cls1
                mov     #StageStrAddr, @#AS ; Адрес символа
                mov     #125252, @#FON  ; Фон экрана
                mov     #strStage, R4   ; "STAGE *"
                call    DrawText        ; Вывод текста
                                        ; Вход: R4 - адрес текста
                clr     AutoShootFlag
                mov     StageNum, R4    ; Номер текущего этапа
                call    DecOut2         ; Вывод двузначного десятичного числа.
                                        ; Вход: R4 - число
                bis     #1000, @#177664
                call    NewStageAnim    ; В начале нового этапа, инициализация звёзд,
                                        ; и немного движения их и поверхности

2$:             call    DynamicSplash   ; Движение динамических объектов в заставке
                beq     2$              ; теперь, пока не нажмём "FIRE" в цикле крутим анимацию
                call    InitGameValues2 ; снова инициализация

                cmp     StageNum, #13.  ; Номер текущего этапа
                beq     GameFinish      ; конец игры
                inc     StageNum        ; иначе увеличиваем номер этапа
                                        ; т.е. на экране номер этапа на 1 меньше, чем в игре получается
                clr     @#FON           ; Фон экрана
                mov     #2000, StageDurationCnt1
                mov     #2700, StageDurationCnt2
                return
; ───────────────────────────────────────────────────────────────────────────

GameFinish:     call    InitGameValues
                mov     #56022, @#AS    ; Адрес символа
                mov     #strCongratulations, R4 ; "CONGRATULATIONS"
                call    DrawText        ; Вывод текста
                                        ; Вход: R4 - адрес текста
NextGameEnd$:   mov     #2, R4

1$:             mov     #TopScreen, R1
                mov     #70, R5
                mov     #62, R3

2$:             mov     R1, R0

3$:             comb    (R0)
                add     R3, R0
                cmp     R0, #BottomScreen
                blo     3$
                inc     R1
                sob     R5, 2$
                sob     R4, 1$

4$:             call    AfterDeadAnim   ; Показываем всякое движение на экране
                                        ; на фоне надписи "GAME OVER" или "CONGRATULATIONS"
                beq     4$              ; в цикле, пока не будет нажато "FIRE"
                call    Cls1
                cmp     Score, LoScoreRecord
                bhi     5$
                jmp     RecTblSplash1$  ; Отображать в заставке таблицу рекордов
; ───────────────────────────────────────────────────────────────────────────

5$:             mov     #strEnterYourName, R4 ; "ENTER YOUR NAME"
                jmp     InputString

; End of function NewStage


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; В начале нового этапа, инициализация звёзд,
; и немного движения их и поверхности

NewStageAnim:   call    InitialDrawStars ; Начальное отображение звёзд по таблице на экране
                mov     #13, 0DynCounter$

1$:             call    DynamicSplash ; Движение динамических объектов в заставке
                dec     (PC)+
0DynCounter$:   .word 0
                bne     1$
                return
; End of function NewStageAnim


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Вывод двузначного десятичного числа.
; Вход: R4 - число

DecOut2:        inc     R4
                mov     #'0, R0

1$:             cmp     R4, #10.
                blo     2$
                sub     #10., R4
                inc     R0
                br      1$
; ───────────────────────────────────────────────────────────────────────────

2$:             cmp     #'0, R0
                bne     3$
                add     #2, @#AS        ; Адрес символа
                br      4$
; ───────────────────────────────────────────────────────────────────────────

3$:             iot
4$:             add     #'0, R4
                mov     R4, R0
                iot
                return
; End of function DecOut2


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Выход: R5 - флаг: !0 - было нажато "FIRE", 0 - всё остальное

CheckPressFire: clr     R0
                clr     R5              ; флаг
                bit     #100,@#177716
                bne     CheckJoystick   ; никакая клавиша не нажата
                ; что-то нажато
                mov     #MoveOffsets, R1 ; таблица смещений адреса ГГ соответствующих направлению движения
                mov     #KeyTab, R2     ; таблица заданных клавиш управления

1$:             tst     (R1)+
                cmp     (R2)+, @#177662
                beq     2$              ; нажали что-то из клавиш управления
                cmp     R2, #KeyTabEnd  ; до конца таблицы дошли?
                bne     1$              ; нет - продолжим
                return
; ───────────────────────────────────────────────────────────────────────────

2$:             mov     -(R1), R0       ; возьмём соответствующее значение
                cmp     #100000, R0     ; было нажато "FIRE"?
                bne     3$              ; нет
                inc     R5              ; да
                clr     R0              ; а для клавиатуры - нет
3$:             return
; End of function CheckPressFire

; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; проверка, что нажато на джойстике.
; Выход: R5 - !0 - нажато "FIRE"
;        R0 - смещение для перемещения

CheckJoystick:  mov     #177714, R2
                mov     #-1, (R2)       ; отправим в порт -1, зачем-то
                mov     (R2), R2        ; смотрим, джойстик нажат?
                beq     4$              ; нет - выход
                bit     JoyFire$, R2    ; было нажато "FIRE"?
                beq     1$              ; нет
                bic     JoyFire$, R2    ; да - сбросим
                inc     R5              ; отметим факт

1$:             mov     #MoveOffsets, R3
                mov     #off_17240, R4

2$:             mov     @(R4)+, R1
                bis     @(R4)+, R1
                cmp     R1, R2
                bne     3$
; Суть вот в чём, ищем комбинации джойстика, соответствующие
; движениям по диагоналям и назначаем им значение из таблицы
                mov     (R3), R0         ; смещение перемещения
                return
; ───────────────────────────────────────────────────────────────────────────

3$:             tst     (R3)+
                cmp     R4, #off_17240End
                blo     2$
4$:             return
; End of function CheckJoystick


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Показываем всякое движение на экране
; на фоне надписи "GAME OVER" или "CONGRATULATIONS"

AfterDeadAnim:  call    EnemysAnim      ; Анимация и обработка всех врагов
                call    AddNewEnemy     ; Функция добавления нового врага
                ;jmp     DynamicSplash   ; Движение динамических объектов в заставке
; End of function AfterDeadAnim

; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Движение динамических объектов в заставке

DynamicSplash:  call    CalcMoveStars   ; Вычисляем новые координаты звёзд и отображаем их
                call    DrawTerrain     ; подготовка в буфере и отображение на экране поверхности земли
                call    CalcMoveStars   ; Вычисляем новые координаты звёзд и отображаем их
                call    AnimPanel       ; прорисовка осциллограммы, мигающей лампочки и прочих элементов панели
                call    CalcMoveStars   ; Вычисляем новые координаты звёзд и отображаем их
                mov     #2174, R0
                sob     R0, .
                call    DrawTerrain     ; подготовка в буфере и отображение на экране поверхности земли
                call    CheckPressFire  ; Выход: R5 - флаг: !0 - было нажато "FIRE", 0 - всё остальное
                tst     R5
                return
; End of function DynamicSplash


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Вывод текста
; Вход: R4 - адрес текста

DrawText:       movb    (R4)+, R0
                beq     1$
                iot
                br      DrawText

1$:             return
; End of function DrawText


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Приём строки в буфер

InputString:    mov     #54022, @#AS    ; Адрес символа
                mov     #125252, @#FON  ; Фон экрана
                call    DrawText        ; Вывод текста
                                        ; Вход: R4 - адрес текста

1Scr$:          mov     #57032, @#AS    ; Адрес символа
                clr     @#FON           ; Фон экрана
                mov     #6, R4

2$:             mov     #'., R0
                iot
                sob     R4, 2$
                mov     1Scr$+2, @#AS   ; Адрес символа
                call    InitialDrawStars ; Начальное отображение звёзд по таблице на экране
                mov     (PC)+, R4
InputBufAddr:   .word   InputBuf

LoopEnterPass$: mov     R4, -(SP)

1$:             call    sub_20026       ; анимации при ожидании нажатия клавиши
                mov     #1300, R0

2$:             bit     #100, @#177716
                bne     3$
                sob     R0, 2$
                br      1$
; ───────────────────────────────────────────────────────────────────────────

3$:             mov     #127, R0

4$:             bit     #100, @#177716
                beq     5$
                sob     R0, 4$
                call    sub_20026       ; анимации при ожидании нажатия клавиши
                br      3$
; ───────────────────────────────────────────────────────────────────────────
; нажали клавишу, обработаем
5$:             mov     (SP)+, R4
                mov     @#177662, R0
                cmp     R0, #30         ; забой?
                bne     6$              ; нет
                cmp     R4, InputBufAddr ; до начала дошли?
                beq     LoopEnterPass$  ; да - игнорируем
                movb    #40, -(R4)      ; удаляем последний введённый символ
                sub     #2, @#AS        ; Адрес символа
                mov     #'., R0
                iot
                sub     #2, @#AS        ; Адрес символа
                br      LoopEnterPass$
; ───────────────────────────────────────────────────────────────────────────

6$:             cmp     R0, #40
                beq     7$
                cmp     R0, #'.
                beq     7$
                cmp     R0, #12
                beq     EndEnterPass$
                cmp     R0, #'0
                blo     LoopEnterPass$
                cmp     R0, #'9
                blos    7$
                bic     #40, R0         ; делаем большие буквы
                cmp     R0, #'A
                blo     LoopEnterPass$
                cmp     R0, #'Z
                bhi     LoopEnterPass$

7$:             cmp     R4, #<InputBuf+5>
                bhi     MorphPassCmd$
                movb    R0, (R4)+
                iot
                br      LoopEnterPass$
; ───────────────────────────────────────────────────────────────────────────

EndEnterPass$:  cmp     R4, #<InputBuf+5>
MorphPassCmd$:  bhi     GoWorkRecTbl    ; для ввода пароля тут переход на адрес SecMorphBR$
                                        ; а сейчас - переход на обработку таблицы рекордов
                movb    #40, (R4)+
                br      EndEnterPass$

SecMorphBR$:    return                  ; секретный переход при правильно введённом пароле
                                        ; он не должен быть далеко от MorphPassCmd$
; End of function InputString


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; анимации при ожидании нажатия клавиши

sub_20026:      call    CalcMoveStars   ; Вычисляем новые координаты звёзд и отображаем их
                call    AnimPanel       ; прорисовка осциллограммы, мигающей лампочки и прочих элементов панели
                call    CalcMoveStars   ; Вычисляем новые координаты звёзд и отображаем их
                call    DrawTerrain     ; подготовка в буфере и отображение на экране поверхности земли
                jmp     DrawTerrain     ; подготовка в буфере и отображение на экране поверхности земли
; End of function sub_20026


; ───────────────────────────────────────────────────────────────────────────
; Поместить новое имя в таблицу рекордов

GoWorkRecTbl:   call    Cls1
                mov     #HiScoreRecord, R1
                mov     Score, R5

1$:             cmp     R5, (R1)
                bhi     2$
                add     #RecordTableItemSize, R1
                br      1$
; ───────────────────────────────────────────────────────────────────────────

2$:             cmp     R1, #LoScoreRecord
                beq     4$
                mov     #RecordTableEnd, R2
                mov     #LoScoreRecord, R3

3$:             mov     -(R3), -(R2)
                mov     -(R3), -(R2)
                mov     -(R3), -(R2)
                mov     -(R3), -(R2)
                cmp     R3, R1
                bhi     3$

4$:             mov     R5, (R1)+
                mov     #InputBuf, R2
                mov     (R2)+, (R1)+
                mov     (R2)+, (R1)+
                mov     (R2)+, (R1)+

; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Отображать в заставке таблицу рекордов

RecTblSplash1$: call    PutRecordTable
; End of function RecTblSplash1$

StartSplash:    bic     #1000, @#177664
                call    CheckCheat      ; Здесь проверяется условие ввода чита
; Рисуем ромбик из цепочек
                mov     #50630, R0      ; адрес экрана
                mov     #1776, R3       ; смещение для адреса экрана
                mov     (PC)+, R4
                        trap 115
                call    DrawSprChain    ; Вход: R0 - адрес экрана
                                        ;       R3 - смещение к адресу экрана
                                        ;       R4 - код команды Trap n
                tst     (R0)+
                mov     #2002, R3
                dec     R4
                call    DrawSprChain    ; Вход: R0 - адрес экрана
                                        ;       R3 - смещение к адресу экрана
                                        ;       R4 - код команды Trap n
                mov     #50646, R0
                call    DrawSprChain    ; Вход: R0 - адрес экрана
                                        ;       R3 - смещение к адресу экрана
                                        ;       R4 - код команды Trap n
                tst     -(R0)
                mov     #1776, R3
                inc     R4
                call    DrawSprChain    ; Вход: R0 - адрес экрана
                                        ;       R3 - смещение к адресу экрана
                                        ;       R4 - код команды Trap n
                ; выводим текст
                clr     @#FON           ; Фон экрана
                mov     #strAbout, R4   ; Выведем информацию об авторе
                mov     #52026, @#AS    ; Адрес символа
                call    DrawText        ; Вывод текста
                                        ; Вход: R4 - адрес текста
                mov     #55024, @#AS    ; Адрес символа
                call    DrawText        ; Вывод текста
                                        ; Вход: R4 - адрес текста
                mov     #57320, @#AS    ; Адрес символа
                call    DrawText        ; Вывод текста
                                        ; Вход: R4 - адрес текста
                mov     #61534, @#AS    ; Адрес символа
                call    DrawText        ; Вывод текста
                                        ; Вход: R4 - адрес текста
                mov     #65726, @#AS    ; Адрес символа
                call    DrawText        ; Вывод текста
                                        ; Вход: R4 - адрес текста
                mov     #70126, @#AS    ; Адрес символа
                call    DrawText        ; Вывод текста
                                        ; Вход: R4 - адрес текста
                ; название игры растягиваем по вертикали и меняем цвет
                mov     #62534, R1
                mov     R1, R2
                add     #2000, R2
                mov     #11, R0

1$:             mov     #5, R3
                mov     R3, R4

2$:             mov     (R1)+, (R2)+
                sob     R3, 2$
                mov     R4, R3
                sub     #12, R1
                sub     #112, R2

3$:             mov     (R1)+, (R2)
                bic     #52525, (R2)+
                sob     R4, 3$
                sub     #12, R1
                sub     #112, R2

4$:             mov     (R1)+, (R2)
                bic     #125252, (R2)+
                sob     R3, 4$
                sub     #112, R1
                sub     #112, R2
                sob     R0, 1$

                call    InitStars
                bis     #1000, @#177664
                mov     #742, SP
                mov     #RecTblSplash, @#4

5$:             call    CountToReclama  ; считаем время до показа рекламы
                                        ; и по истечении - показываем
                bne     6$
                call    Inkey$          ; Получение кода клавиши
                                        ; Выход: R0 - скан код
                bic     #40, R0
                cmp     R0, #'K
                beq     SetKeyboard$
                cmp     R0, #'J
                bne     5$
                br      SetJoystick$
; ───────────────────────────────────────────────────────────────────────────
6$:             mov     #LoopSplash, @#4
InputPassword:  tst     EnterValidPassFlag
                beq     1$

                jmp     @(PC)+
Secret3$:       .word   BlowFlight    ; здесь становится адрес перехода StartGame при правильном пароле
; ───────────────────────────────────────────────────────────────────────────

1$:             call    Cls1
; придётся самому вычислять смещение и команду
; потому что используется относительная адресация приёмника
; и тут нет проверки на переполнение и неправильный переход
cmd_br_offs = SecMorphBR$-<MorphPassCmd$+2>
cmd_br = 101000 + [[cmd_br_offs/2] & 0xff]
                mov     #cmd_br, MorphPassCmd$
                mov     #strEnterPassword, R4 ; "ENTER PASSWORD"
                call    InputString     ; Приём строки в буфер
                mov     #InputBuf, R1
                clr     R0              ; посчитаем сумму двухбуквий
                add     (R1), R0        ; пароль MISLED
                add     2(R1), R0
                add     4(R1), R0
                cmp     #154745, R0     ; сумма вот такая
                beq     3$
                clr     @#FON           ; Фон экрана
                mov     #64022, AS      ; Адрес символа
                mov     #strWrongPassword, R4 ; "WRONG PASSWORD"
                call    DrawText        ; Вывод текста
                                        ; Вход: R4 - адрес текста
                mov     #752, SP
2$:             call    DynamicSplash   ; Движение динамических объектов в заставке
                beq     2$
                jmp     StartSplash
; ───────────────────────────────────────────────────────────────────────────

3$:             sub     #"MI - AnimPanel, (R1) ; тут стало AnimPanel
                mov     (R1)+, Secret1$
                sub     #"SL - 4733, (R1) ; тут стало 4733
                mov     (R1)+, Secret2$
                sub     #"ED - MorphPassCmd$, (R1) ; тут стало MorphPassCmd$
                mov     (R1), R0        ; R0 = MorphPassCmd$
cmd_br_rctb = GoWorkRecTbl-<MorphPassCmd$+2>
cmd_br1 = 101000 + [[cmd_br_rctb/2] & 0xff]
                sub     #MorphPassCmd$ - cmd_br1, (R1) ; тут стало 'bhi GoWorkRecTbl'
                mov     (R1), (R0)      ; 'bhi GoWorkRecTbl' -> MorphPassCmd$
                                        ; переход при обработке имени в таблицу рекордов
                sub     #cmd_br1 - StartGame, (R1) ; тут стало StartGame
                mov     (R1), Secret3$
                inc     EnterValidPassFlag
                jmp     @(R1)+          ; и переходим к StartGame

RecTblSplash:   mov     #744, SP
                mov     #LoopSplash, @#4
                jmp     RecTblSplash1$  ; Отображать в заставке таблицу рекордов
; ───────────────────────────────────────────────────────────────────────────

SetKeyboard$:   bic     #1000, @#177664
                call    Cls1
                mov     #KeyTab, R5
                mov     #51430, @#AS    ; Адрес символа
                mov     #strCtrlKbd, R4 ; "LEFT"
                mov     #9., @#CtrlCnt
                mov     #SetKbdProc, @#AtCtrlProc
                br      21746$
; ───────────────────────────────────────────────────────────────────────────

SetJoystick$:   bic     #1000, @#177664
                call    Cls1
                mov     #JoyTab, R5
                mov     #55232, @#AS    ; Адрес символа
                mov     #strCtrlJoy, R4 ; "LEFT"
                mov     #5, @#CtrlCnt
                mov     #SetJoyProc, @#AtCtrlProc

21746$:         mov     R5, -(SP)
                call    InitialDrawStars ; Начальное отображение звёзд по таблице на экране
                mov     (SP)+, R5
                mov     #125252, @#FON  ; Фон экрана

2$:             mov     R5, -(SP)
                mov     @#AS, -(SP)     ; Адрес символа
                call    DrawText        ; Вывод текста
                                        ; Вход: R4 - адрес текста
                mov     (SP)+, @#AS     ; Адрес символа
                add     #2100, @#AS     ; Адрес символа
                mov     (SP)+, R5
                bis     #1000, @#177664
                call    @AtCtrlProc
                mov     R0, (R5)+
                dec     @#CtrlCnt
                bne     2$
LoopSplash:     mov     #740, SP
                jmp     StartSplash
; ───────────────────────────────────────────────────────────────────────────


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


InitStars:      mov     (PC)+, (PC)+    ; инициализация счётчика до показа рекламы
                .word 250
BeforeReclCntr: .word 0                 ; счётчик до показа рекламы
                jmp     InitialDrawStars ; Начальное отображение звёзд по таблице на экране
; End of function InitStars


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; считаем время до показа рекламы
; и по истечении - показываем

CountToReclama: dec     BeforeReclCntr  ; счётчик до показа рекламы
                beq     1$
                jmp     DynamicSplash   ; Движение динамических объектов в заставке
; ───────────────────────────────────────────────────────────────────────────
1$:             bic     #1000, @#177664
                call    Cls1
                jmp     ShowReclama
; End of function CountToReclama


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


ShowReclama:    mov     #strReclama, R1 ; "ВНИМАНИЕ !"
                mov     #ReclDataTbl, R5

1$:             mov     (R5)+, R0
                mov     (R5)+, @#FON    ; Фон экрана
                mov     R5, -(SP)
                call    @#DrawString    ; Вход: R1 - адрес строки, конец строки - 0
                mov     (SP)+, R5
                cmp     (R5), #50000
                bhi     1$
                call    @#InitialDrawStars ; Начальное отображение звёзд по таблице на экране
                bis     #1000, @#177664
                mov     (PC)+, (PC)+
                .word 2000
ShowReclCntr:   .word 0                 ; счётчик показа рекламы
; ───────────────────────────────────────────────────────────────────────────

2$:             call    DynamicSplash   ; Движение динамических объектов в заставке
                bne     3$
                dec     ShowReclCntr    ; счётчик показа рекламы
                bne     2$

3$:             jmp     @#RecTblSplash
; End of function ShowReclama


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


SetKbdProc:     call    DynamicSplashSR ; Движение динамических объектов в заставке с сохранением всех регистров
                bit     #100,@#177716
                beq     SetKbdProc

1$:             call    DynamicSplashSR ; Движение динамических объектов в заставке с сохранением всех регистров
                bit     #100,@#177716
                bne     1$
                mov     @#177662, R0
                br      BeepSm
; ───────────────────────────────────────────────────────────────────────────

SetJoyProc:     mov     #177714, R2

1$:             call    DynamicSplashSR ; Движение динамических объектов в заставке с сохранением всех регистров
                mov     #-1, (R2)
                tst     (R2)
                bne     1$

2$:             call    DynamicSplashSR ; Движение динамических объектов в заставке с сохранением всех регистров
                mov     #-1, (R2)
                mov     (R2), R0
                beq     2$

BeepSm:         mov     #17, R1

1$:             mov     #100, R2
                mov     #320, @#177716
                mov     R2, R3

                sob     R3, .
                mov     #220, @#177716

                sob     R2, .
                sob     R1, 1$
                return
; End of function SetKbdProc


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


PutRecordTable: bic     #1000, @#177664
                call    Cls1
                mov     #RecordTable, R1
                clr     R4              ; счётчик пункта таблицы рекордов
                mov     #50516, @#AS    ; Адрес символа

1$:             mov     #52525, @#FON   ; Фон экрана
                mov     R4, -(SP)
                mov     R1, -(SP)
                call    DecOut2         ; Вывод двузначного десятичного числа.
                                        ; Вход: R4 - число
                mov     #'., R0
                iot
                add     #2, @#AS        ; Адрес символа
                clr     @#FON           ; Фон экрана
                mov     #6, R4          ; длина имени
                mov     (SP), R1

2$:             clr     R0
                movb    (R1)+, R0       ; выводим имя
                mov     R1, -(SP)
                iot
                mov     (SP)+, R1
                sob     R4, 2$
                cmpb    (R1)+, (R1)+    ; пропускаем число
                mov     R1, (SP)
                mov     #125252, @#FON  ; Фон экрана
                add     #6, @#AS        ; Адрес символа
                mov     -12(R1), R4     ; берём рекорд этого пункта
                call    DecOut          ; Вывод десятичного числа.
                                        ; Вход: R4 - число
                mov     (SP)+, R1
                mov     (SP)+, R4
                add     #2034, @#AS     ; Адрес символа
                inc     R4
                cmp     R4, #RecordTableSize ; размер таблицы рекордов
                blo     1$
                call    InitialDrawStars ; Начальное отображение звёзд по таблице на экране
                bis     #1000, @#177664

3$:             call    DynamicSplash   ; Движение динамических объектов в заставке
                beq     3$              ; в цикле пока не будет нажато "FIRE"
                return
; End of function PutRecordTable

; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Вход: R0 - адрес экрана
;       R3 - смещение к адресу экрана
;       R4 - код команды Trap n

DrawSprChain:   mov     R3, -(SP)
                mov     R4, -(SP)
                mov     #5, R1
                mov     R4, 2ToSprCmd$

1$:             jsr     R4, @#110346
2ToSprCmd$:     trap    115
                jsr     R4, @#110362

                add     R3, R0
                sob     R1, 1$
                mov     (SP)+, R4
                mov     (SP)+, R3
                return
; End of function DrawSprChain

; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Движение динамических объектов в заставке с сохранением всех регистров

DynamicSplashSR:jsr     R4, @#110346
                mov     R5, -(SP)
                call    DynamicSplash   ; Движение динамических объектов в заставке
                mov     (SP)+, R5
                jsr     R4, @#110362
                return
; End of function DynamicSplashSR


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Получение кода клавиши
; Выход: R0 - скан код

Inkey$:         clr     R0
                bit     #100, @#177716
                bne     1$          ; клавиша не нажата - выход
                mov     @#177662, R0
1$:             return
; End of function Inkey$


; ───────────────────────────────────────────────────────────────────────────

EntryPoint$:    clr     EnterValidPassFlag
                reset

0Wrong$:        bic     #1000, @#177664
                call    Cls1
                tst     @#42014         ; проверка целостности (тут всегда не 0)
                beq     0Wrong$+2       ; вот это вот оставим
                mov     #TerrainBuffer, R0
                mov     #4, R5          ; формируем начальную поверхность

1$:             mov     R0, -(SP)
                mov     #SprGround, R2
                mov     #20, R4

2$:             mov     #10, R3

3$:             mov     (R2)+, (R0)+
                sob     R3, 3$
                add     #60, R0
                sob     R4, 2$
                mov     (SP)+, R0
                add     #20, R0
                sob     R5, 1$
                mov     #SprGround2, CurTerrainSpr
                mov     #1, BitMaskInSpr
                mov     #222, @#177712
                jmp     StartSplash
; ───────────────────────────────────────────────────────────────────────────
; тут на каждую функцию навешано слишком много действий
; чтоб можно было как-то адекватно их назвать

StartGame:      call    InitGameValues
                call    InitGameValues3 ; инициализация переменных

GameLoop:       call    sub_22574       ; обработка стрельбы ГГ
                call    CheckFlightHit  ; Проверка на попадание в самолётик
                call    CheckoutScore   ; Увеличение жизней за каждые 5000. очков,
                                        ; движение звёзд и вывод счёта на экран

                call    sub_34406       ; Обработка звука выстрела самолётика и проверка на паузу
                                        ; и генерация шариков - выстрелов врага
                call    sub_35150
                clr     R5
                call    InputCheatCheck ; Анимация стрельбы и проверка на ввод чита "BROKEN"
                call    CheckPause      ; Обработка звука выстрела самолётика и проверка на паузу
                call    CheckAllEnemyHit       ; проверка на попадание пульками во врагов
                call    sub_22574       ; обработка стрельбы ГГ
                call    CheckoutScore   ; Увеличение жизней за каждые 5000. очков,
                                        ; движение звёзд и вывод счёта на экран
                call    sub_35150

                call    @(PC)+
Secret1$:       .word   100140          ; тут вызов AnimPanel
                call    CheckoutScore   ; Увеличение жизней за каждые 5000. очков,
                                        ; движение звёзд и вывод счёта на экран
                call    CheckPause      ; Обработка звука выстрела самолётика и проверка на паузу
                call    InputCheatCheck ; Анимация стрельбы и проверка на ввод чита "BROKEN"
                call    CheckAllEnemyHit       ; проверка на попадание пульками во врагов
                call    CheckFlightHit  ; Проверка на попадание в самолётик
                call    AddEnemys       ; добавление нового врага
                call    sub_22654       ; уменьшение уровня защитного поля
                                        ; обработка звука взрыва врага
                                        ; обработка анимации взрыва самолётика
                call    CheckAllEnemyHit       ; проверка на попадание пульками во врагов
                br      GameLoop



; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Обработка звука выстрела самолётика и проверка на паузу

CheckPause:     call    GGShootSound    ; Звук выстрела самолётика
                bit     #100, @#177716  ; клавиша нажата?
                bne     1$              ; нет
                clr     R1              ; да
                xor     R0, R4          ; чё то непонятное
                cmp     #'P, @#177662   ; это P?
                beq     GamePause
                cmp     #'p, @#177662   ; или p?
                bne     1$
                ; да - ставим игру на паузу
GamePause:      call    AnimPanel     ; прорисовка осциллограммы, мигающей лампочки и прочих элементов панели
                mov     #16666, R0
                sob     R0, .
                call    CheckPressFire ; Выход: R5 - флаг: !0 - было нажато "FIRE", 0 - всё остальное
                tst     R5
                beq     GamePause
1$:             return
; End of function CheckPause


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


ShowGameOver:   mov     #SprGameOver, R1
                mov     #60030, R0
                mov     #12, R2

1$:             mov     #11, R3

2$:             mov     (R1)+, R4
                xor     R4, (R0)+
                sob     R3, 2$
                add     #56, R0
                sob     R2, 1$
                return
; End of function ShowGameOver


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Вход: R1 - адрес строки, конец строки - 0

DrawString:     movb    (R1)+, R2
                bic     #177400, R2
                bne     1$
                return
; ───────────────────────────────────────────────────────────────────────────

1$:             cmpb    #40, R2
                bne     2$
                tst     (R0)+           ; пробел - просто пропускаем знакоместо
                br      DrawString      ; Вход: R1 - адрес строки, конец строки - 0
; ───────────────────────────────────────────────────────────────────────────

2$:             mov     #Font, R5
                cmpb    #'!, R2
                beq     5$
                inc     R5
                cmpb    #'", R2
                beq     5$
                inc     R5
                cmpb    #',, R2
                beq     5$
                inc     R5
                cmpb    #'., R2
                beq     5$
                cmpb    R2, #'9
                bhi     3$
                sub     #'/, R2
                add     R2, R5
                br      5$
; ───────────────────────────────────────────────────────────────────────────

3$:             add     #12, R5
                sub     #337, R2

4$:             inc     R5
                sob     R2, 4$

5$:             mov     #8., R2         ; высота шрифта

6$:             movb    (R5), R3
                mov     #8., R4         ; в байте 8 бит

7$:             asrb    R3
                ror     (R0)
                asr     (R0)
                sob     R4, 7$
                bic     @#FON, (R0)     ; Фон экрана
                add     #100, R0
                add     #56, R5
                sob     R2, 6$
                sub     #776, R0
                br      DrawString      ; Вход: R1 - адрес строки, конец строки - 0
; End of function DrawString


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Обработка звука выстрела самолётика и проверка на паузу
; и генерация шариков - выстрелов врага

sub_34406:      call    CheckPause      ; Обработка звука выстрела самолётика и проверка на паузу
                add     #2, ROMAddr
                cmp     ROMAddr, #111170
                blo     1$
                mov     #100000, ROMAddr
; ───────────────────────────────────────────────────────────────────────────
1$:             bit     (PC)+, @(PC)+   ; выбираем случайный момент
                .word 157576
ROMAddr:        .word 101666
; ───────────────────────────────────────────────────────────────────────────
                beq     2$              ; не настал
                mov     @#177710, R1
                bic     #177760, R1     ; получим случайное число
                asl     R1              ; * на 8
                asl     R1
                asl     R1
                add     #EnemyBuffer, R1 ; получим индекс в массиве врагов
                cmp     #MoveEnemyProc2, 6(R1) ; там такой враг?
                bne     2$              ; нет - выходим
                mov     (R1), R0        ; иначе берём его адрес экрана
                add     #476, R0        ; + смещение
                call    SearchFreeItem  ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
                mov     R0, (R1)        ; и формируем шар
                mov     #MoveEnemyBall, 6(R1)
                call    DrawBall        ; это как бы некоторые враги стреляют
                mov     @#177710, R0
                sub     ROMAddr, R0
                bic     #177760, R0
                asl     R0
                mov     word_34554(R0), 2(R1) ; параметр 1 - дисперсия
2$:             return
; End of function sub_34406

; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Инициализация индикаторов панели и переменных

InitGamePanel:  clr     ShieldFieldFlag ; выключаем защитное поле
                clr     PriseNum        ; номер пойманного приза
                mov     #PanelPriseAddr, R0 ; выведем на панель
                trap    116             ; значок Ускорения
                mov     #PanelShieldAddr, R0
                mov     #4, R1          ; очистим шкалу защитного поля

1$:             clr     (R0)+
                mov     #146314, 76(R0)
                clr     176(R0)
                sob     R1, 1$
                br      34744$
; End of function InitGamePanel


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; Анимация стрельбы и проверка на ввод чита "BROKEN"

InputCheatCheck:
                call    ShootsFlightAnim ; Анимация выстрелов ГГ
                mov     @#177662, R0
                bic     #40, R0
                cmp     #'B, R0         ; Это клавиша B?
                bne     1$              ; нет
                clr     CtNmCnt         ; да
                clr     CtPrevKey       ; код предыдущей нажатой клавиши

1$:             cmp     R0, (PC)+       ; эту клавишу нажимали в прошлый раз?
CtPrevKey:      .word 0                 ; код предыдущей нажатой клавиши
                beq     3$              ; да выходим
                mov     R0, CtPrevKey   ; нет - сохраним прошлую нажатую клавишу
                mov     #CtNmCnt, R1    ; счётчик введённых символов
                mov     (R1), R5        ; берём значение
                movb    R0, CheatBuf(R5) ; сохраняем  код в буфере
                inc     (R1)            ; +1
                cmp     (R1), #6        ; все символы ввели?
                blo     3$              ; нет ещё, выходим
                ; да - проверим, что ввели
                mov     CheatBuf, R2    ; R2 = "BR
                mov     CheatBuf+2, R0  ; R0 = 45517 = "OK
                mov     CheatBuf+4, R1  ; R1 = 47105 = "EN
                mov     R2, R5
                sub     R1, R5
                add     R0, R5
                cmp     R5, #47514      ; BROKEN
                bne     34744$          ; неправильно
                xor     R1, R0          ; R0 = 2412 = "OK ^ "EN
                sub     CheatBuf, R0    ; R0 = 131310 = "OK ^ "EN - "BR
CheatVal = ["OK ^ "EN] - "BR
                sub     #<CheatVal-Lives>, R0 ; R0 = 16336 = Lives
                mov     #8118., (R0)    ; заносим в счётчик жизней большое значение
                call    ShowLives       ; Отображение на панели количества жизней
                clr     CtPrevKey       ; сделаем так, чтобы можно было ещё раз ввести
                call    BeepSm

34744$:         clr     (PC)+           ; очищаем счётчик символов введённого чита
CtNmCnt:        .word 3                 ; счётчик введённых символов
3$:             return
; End of function InputCheatCheck


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


sub_35150:      call    DrawTerrain     ; подготовка в буфере и отображение на экране поверхности земли
                mov     #PanelPriseAddr, R0
                mov     #-1, @#177714
                bit     JoyFire$, @#177714 ; на джойстике стрельба нажата?
                bne     DelayGetPriseConst$ ; да
                bit     #100, @#177716  ; нет, а клавиша нажата?
                bne     6$              ; нет
                cmp     @#177662, KeyFire$ ; да, и это стрельба?
                bne     6$              ; нет

DelayGetPriseConst$:
                cmp     #15, DelayGetPrise ; пора применять приз?
                bne     4$              ; нет ещё
                dec     (PC)+           ; пора мигать призом?
0PriseFlashDelay$:.word 2
                bne     3$              ; нет ещё
                mov     #4, 0PriseFlashDelay$ ; да - инициализируем счётчик
                                        ; и мигаем xorом
                mov     PriseNum, R1    ; номер пойманного приза
                swab    R1
                ror     R1
                asr     R1              ; R2 <<= 6
                mov     #20, R3
                add     #SprPrise1, R1  ; подведём указатель к началу нужного спрайта

2$:             mov     (R1)+, R4       ; ксорим
                xor     R4, (R0)+
                mov     (R1)+, R4
                xor     R4, (R0)
                add     #76, R0
                sob     R3, 2$
3$:             return
; ───────────────────────────────────────────────────────────────────────────

4$:             inc     DelayGetPrise ; задержка при нажатии на "Fire" перед применением приза
5$:             return
; ───────────────────────────────────────────────────────────────────────────
                ; стрельба не нажата
6$:             cmp     DelayGetPriseConst$+2, DelayGetPrise ; а мы уже на максимуме?
                bne     5$              ; нет, и ладно
                clr     DelayGetPrise   ; да - очистим счётчик
                mov     PriseNum, R1    ; номер пойманного приза
                add     #104516, R1     ; команда вывода приза
                mov     R1, (PC)        ; поместим её в следующее слово
                trap    116             ; и выполним
                return
; End of function sub_35150


; ███████████████ S U B R O U T I N E ███████████████████████████████████████


CheckCheat:     call    Cls1
                mov     #KeyTab, R1
                mov     #9., R2
                clr     R0

1$:             add     (R1)+, R0
                sob     R2, 1$
                cmp     #1213, R0       ; Если вместо задания клавиш набрать TECHNICAL
                bne     3$
                mov     KeyFire$, R3    ; R3 = 114
                sub     #176, R3        ; R3 = 177716
                mov     #KeyTabEnd, R5
                mov     #9., R1
                clr     R0

2$:             sub     -(R5), R0
                swab    R0
                sob     R1, 2$          ; R0 = 105747
                add     #<CheatSub^105747>, R1 ; R1 = 130305
                xor     R1, R0          ; R0 = 35442, SP = 736
                rts     R0              ; R0 = 20714, PC = 35442 (CheatSub)
3$:             return
; End of function CheckCheat


; ███████████████ S U B R O U T I N E ███████████████████████████████████████

; На входе R3 = 177716

CheatSub:       clr     KeyTab+6
                mov     #10, R1

1$:             mov     #320, (R3)
                mov     R1, R0
                sob     R0, .

                mov     #220, (R3)
                mov     R1, R0
                sob     R0, .

                inc     R1
                cmp     R1, #100
                blos    1$
                bic     #1000, @#177664
                mov     #40, KeyFire$
                call    Cls1
                mov     #60016, @#AS    ; Адрес символа
                mov     #strPressOptionKey, R4 ; "PRESS OPTION KEY..."
                clr     @#FON           ; Фон экрана
                call    DrawText        ; Вывод текста
                                        ; Вход: R4 - адрес текста
                call    InitialDrawStars ; Начальное отображение звёзд по таблице на экране
                bis     #1000, @#177664

2$:             call    DynamicSplash   ; Движение динамических объектов в заставке
                bit     #100, @#177716
                bne     2$
                mov     @#177662, R0
                bic     #40, R0
                cmp     #'E, R0
                bne     3$
                clr     (SP)             ; Exit
                jmp     @#100140
; ───────────────────────────────────────────────────────────────────────────

3$:             mov     KeyTab, R3      ; R3 = 124
                neg     R3              ; R3 = -124
                sub     KeyTab+2, R3    ; R3 = 177547
                swab    R3              ; R3 = 63777
                add     #114, R3        ; (R3 += 114) = 64113
                sub     #64113 - <Secret5$+2>, R3 ; R3 = 13236
                cmp     #'B, R0
                bne     4$
                mov     #3, (R3)        ; Увеличить количество призов (Secret5$+2)

4$:             cmp     #'S, R0
                bne     5$
                mov     #1430, @#177664  ; табло с индикаторами - вниз экрана

5$:             cmp     #'N, R0
                bne     6$
                mov     #12, (R3)       ; нормальная игра
                mov     #1330,@#177664

6$:             cmp     #'C, R0
                bne     8$
                mov     #HiScoreRecord, R1 ; очистка таблицы

7$:             clr     (R1)+
                mov     #20040, (R1)
                mov     (R1)+, (R1)
                mov     (R1)+, (R1)+
                cmp     R1, #RecordTableEnd
                blo     7$

8$:             halt
; End of function CheatSub

; ───────────────────────────────────────────────────────────────────────────
Prepare$:       mov     #DisIot, @#20
                mov     #200, @#22
                mov     #DisTrap, @#34
                mov     #200, @#36
                mov     #512, R0
                mov     #RndData$, R1
                ; переносим всякие случайные числа
                ; на своё место, для улучшабельности
1$:             mov     (R1)+, (R0)+
                cmp     R1, #RndDataEnd$
                blo     1$
                call    @#40000
                jmp     EntryPoint$

; это было в оригинальной игре.
; обычно в памяти БК по адресам 512..740 находятся нули и -1
; а в игре содержимое памяти используется для генерации случайных чисел
; вот и поместим это туда, пусть будет как в оригинале.
RndData$:       .word 103040, 103040, 107260, 55211
                .word 111430, 103304, 105270, 103304
                .word 111326, 55211, 177631, 103304
                .word 111372, 101322, 103304, 111372
                .word 104176, 44400, 12, 74177
                .word 75032, 75274, 0, 75032
                .word 76360, 76364, 74756, 76602
                .word 100577, 100576, 102573, 102572
                .word 104567, 104566, 106563, 106562
                .word 110557, 110556, 112553, 112552
                .word 114547, 114546, 116543, 116542
                .word 120537, 120536, 122533, 122532
                .word 124527, 124526, 126523, 126522
                .word 130517, 130516, 132513, 132512
                .word 103040, 107260, 42032, 1
                .word 63, 111100, 103040, 107260
                .word 43203, 1, 53, 111100
                .word 112004, 0, 0, 103304
                .word 111372, 104176, 45600, 12
RndDataEnd$:
                .org 40000

                .END
