;
; ╔═════════════════════════════════════════════════════════════════════════╗
; ║     This file is generated by The Interactive Disassembler (IDA)        ║
; ║     Copyright (c) 2006 by DataRescue sa/nv, <ida@datarescue.com>        ║
; ║ Licensed to: Kon v Palto                                                ║
; ╚═════════════════════════════════════════════════════════════════════════╝
;
; Input MD5   : C7A09193CFA59265D73A3CE5E7BDF58D

; File Name   : XENON_GM2_BODY_load0_uncrypt
; Format      : Binary file
; Base Address: 0000h Range: 0000h - 3C24h Loaded length: 3C24h

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

; ═══════════════════════════════════════════════════════════════════════════
.la 0
; Segment type: Pure code
                .word 100000
                .word 74606
word_4:         .word 101760
                .word 200
                .word 1000
                .word 100000
                .word 70332
                .word 0
off_20:         .word DisIot            ; диспетчер IOT
                .word 200
AtCtrlProc:     .word 100000            ; функция обработки элемента управления
                                        ; в меню задания управления
CtrlCnt:        .word 100000            ; счётчик пунктов элементов управления
                                        ; в меню задания управления
                .word 74770
                .word 0
                .word DisTrap           ; диспетчер TRAP
                .word 200
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 101136
                .word 200
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 12
                .word 20000
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
Temp1:          .word 0                 ; временная переменная
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 401
                .word 200
AS:             .word 44400             ; Адрес символа
                .word 1
                .word 2000
                .word 0
                .word 42000
                .word 0
                .word 0
                .word 0
                .word 0
                .word 40000
                .word 2000
                .word 26000
                .word 24000
FON:            .word 0                 ; Фон экрана
MASCW:          .word 177777            ; Маска цвета
                .word 0
                .word 177777
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 14
                .word 0
                .word 0
                .word 0
                .word 1000
                .word 36501
                .word 0
                .word 0
                .word 101362
                .word 200
                .word 0
                .word 0
                .word 1
                .word 320
                .word 550
Temp2:          .word 53271             ; флаг добавления босса 0 - надо !0 - не надо или наоборот
                .word 34
                .word 52654
                .word 37134
                .word 37140
                .word 37000
                .word 37000
                .word 37000
                .word 11
                .word 4440
                .word 52122
                .word 20062
                .word 20040
                .word 20040
                .word 1000
                .word 36501
                .word 42530
                .word 47516
                .word 27116
                .word 40520
                .word 52122
                .word 20062
                .word 20040
                .word 20040
                .word 76640
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 0
                .word 1000
                .word 37000
                .word 0
                .word 112554
                .word 7361
                .word 576
                .word 564
                .word 37777
                .word 0
                .word 31522
                .word 30067
                .word 30060
                .word 6412
                .word 30060
                .word 30060
                .word 51054
                .word 20061
                .word 20040
                .word 20040
                .word 20040
                .word 20040
                .word 20040
                .word 20040
                .word 20000
                .word 20040
                .word 101536
                .word 211
                .word 101322
                .word 101322
                .word 101142
                .word 0
                .word 101322
                .word 101142
                .word 103040
                .word 103040
                .word 107260
                .word 55211
                .word 111430
                .word 103304
                .word 105270
                .word 103304
                .word 111326
                .word 55211
                .word 177631
                .word 103304
                .word 111372
                .word 101322
                .word 103304
                .word 111372
                .word 104176
                .word 44400
                .word 12
                .word 74177
                .word 75032
                .word 75274
                .word 0
                .word 75032
                .word 76360
                .word 76364
                .word 74756
                .word 76602
                .word 100577
                .word 100576
                .word 102573
                .word 102572
                .word 104567
                .word 104566
                .word 106563
                .word 106562
                .word 110557
                .word 110556
                .word 112553
                .word 112552
                .word 114547
                .word 114546
                .word 116543
                .word 116542
                .word 120537
                .word 120536
                .word 122533
                .word 122532
                .word 124527
                .word 124526
                .word 126523
                .word 126522
                .word 130517
                .word 130516
                .word 132513
                .word 132512
                .word 103040
                .word 107260
                .word 42032
                .word 1
                .word 63
                .word 111100
                .word 103040
                .word 107260
                .word 43203
                .word 1
                .word 53
                .word 111100
                .word 112004
                .word 0
                .word 0
                .word 103304
                .word 111372
                .word 104176
                .word 45600
                .word 12
                .word 117346
                .word 103304
                .word 111372
                .word 104176
                .word 51400
                .word 12
                .word 320
                .word 0
                .word 100724
                .word 123
                .word 100134
                .word 0
                .word 70336
                .word 70404
                .word 36000
; 1000, всё что выше - просто не нужно.
; разве что для улучшения показателей случайности

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

                .word 14726
CryptBgn$:      .word 14726
; Спрайт шириной 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
                .byte    4 ;   000404  FT мусор
                .byte    1 ;
                .byte    4 ;   000004   D
                .byte    0 ;
                .byte   10 ;   000010   H
                .byte    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
                .byte   63 ; 3 171463 86S мусор
                .byte  363 ; С
                .byte  377 ; Ъ 141777 1NO
                .byte  303 ; ц
                .byte   10 ;   000010   H
                .byte    0 ;
; спрайт размером 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
                .byte   63 ; 3 171463 86S мусор
                .byte  363 ; С
                .byte  377 ; Ъ 141777 1NO
                .byte  303 ; ц

TerrainSprTbl:  .word SprGround
                .word SprGround2
                .word SprGround3

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

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

PutNewBitTerrain:
                mov     #40000, R0
                mov     #100, R1
                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
                sev                     ; ненужная команда
                cmp     R5, #4          ; меньше 5?
                blos    2$              ; да - ОК
                clr     R5              ; нет - будет 0

2$:             mov     TerrainSprTbl(R5), R5 ; выбираем случайный новый спрайт поверхности
                mov     R5, CurTerrainSpr ; сохраняем
                mov     #1, BitMaskInSpr ; битовая маска в слове спрайта
                br      3$
; ───────────────────────────────────────────────────────────────────────────
CurTerrainSpr:  .word SprGround+16
BitMaskInSpr:   .word 20
; ───────────────────────────────────────────────────────────────────────────

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

4$:             mov     #20, R4         ; высота спрайта, лишняя команда
                mov     BitMaskInSpr, R1 ; берём битовую маску

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

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

7$:             add     R2, R5          ; переходим к следующей строке спрайта
                jmp     jmp_31746
; End of function PutNewBitTerrain

; ───────────────────────────────────────────────────────────────────────────
                .word 100365
; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR PutNewBitTerrain

jmp_2220:       asl     R1              ; двигаем маску
                beq     11$             ; слово кончилось?

10$:            mov     R1, BitMaskInSpr ; нет - сохраняем текущую маску
                return                  ; и выходим
; ───────────────────────────────────────────────────────────────────────────

11$:            inc     R1              ; переходим к следующему слову
                add     #2, CurTerrainSpr ; спрайта
                br      10$
; END OF FUNCTION CHUNK FOR PutNewBitTerrain
; ───────────────────────────────────────────────────────────────────────────
; таблица летящих звёзд
; размер элемента 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

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

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

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

cms_1$:         mov     (R5)+, R0       ; берём адрес экрана
                beq     Ret_10$         ; 0 - конец таблицы
                clr     R1              ; лишняя команда
                clr     R2              ; лишняя команда
                movb    (R5)+, R1       ; берём младший байт, это маска. Так он и не научился использовать bis
                bic     R4, R1          ; убираем расширение знака. Вот нафига перед этим clr делал?
                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$:             ccc                     ; ненужная команда
                asr     R1              ; сдвигаем маску
                bne     7$              ; ещё не обнулилось
; обнулилось - значит надо менять адрес
; да тут и R4 лишнее, и очистка старшего байта в R1 выше лишнее
; куча лишних действий
                movb    #200, 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)       ; сохраняем новую маску
                cmpb    (R5)+, (R5)+    ; переходим к следующему элементу
                br      cms_1$          ; и идём обрабатывать следующий элемент таблицы
; ───────────────────────────────────────────────────────────────────────────

Ret_10$:        return
; ───────────────────────────────────────────────────────────────────────────

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


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

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

InitialDrawStars:
                mov     #StarsTable, R1

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

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


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

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

DrawFlight:     mov     #SprFlight, R1
                mov     #74, R5
                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

; ───────────────────────────────────────────────────────────────────────────
; Спрайт размером 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

GGAddr:         .word 65216             ; текущий адрес спрайта самолётика

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

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

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

2$:             mov     (R2)+, R1
                xor     R1, (R0)
                add     R4, R0
                sob     R3, 2$
                br      3$
; ───────────────────────────────────────────────────────────────────────────
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
; ───────────────────────────────────────────────────────────────────────────

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

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


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

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

ShieldEffectAnim:
                dec     BeforeEffCntr   ; пора включать эффект?
                beq     1$              ; да
                return                  ; нет
; ───────────────────────────────────────────────────────────────────────────
BeforeEffCntr:  .word 1
; ───────────────────────────────────────────────────────────────────────────

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

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

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

Ret_3$:         return
; End of function ShieldEffectAnim


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

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

StartingDrawFlight:
                mov     #60216, R0      ; начальная позиция
                mov     R0, GGAddr      ; текущий адрес спрайта самолётика
                jmp     DrawFlight      ; Вход: R0 - адрес экрана
; End of function StartingDrawFlight

; ───────────────────────────────────────────────────────────────────────────
ShieldFieldFlag:.word 0                 ; флаг включённого защитного поля

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

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

AnimFlight:     mov     #GGAddr, R2     ; текущий адрес спрайта самолётика
                add     (R2), R0        ; новый адрес экрана
                cmp     R0, #TopScreen  ; должен быть
                blo     Ret_3$          ; в пределах рабочей области экрана
                cmp     R0, #BottomScreen-1104
                bhis    Ret_3$
                mov     R0, R1
                bic     #177700, R1
                cmp     R1, #70
                bhis    Ret_3$
                cmp     R1, #4
                blo     Ret_3$
                clr     R3              ; флаг, что нарисовали защитное поле
                                        ; чёт излишне как-то
                                        ; достаточно было просто mov ShieldFieldFlag, R3
                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 - номер смещения в таблице смещений
                inc     R3
                mov     (SP)+, R2
                mov     (SP)+, R0

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

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

; Проверка на верхнюю-нижнюю границы экрана
; Выход: V !=0 - в пределах, V == 0 - за пределами

sub_3544:       ccc                     ; ненужная команда
                cmp     R0, #TopScreen
                blo     5$
                cmp     R0, #BottomScreen-1000
                bhi     5$
                sev
5$:             return
; End of function sub_3544

; ───────────────────────────────────────────────────────────────────────────
MaxShoots:      .word 1                 ; максимальное количество одновременных выстрелов
NumShoots:      .word 0                 ; текущее количество выстрелов
; Массив выстрелов ГГ
ShootsTbl:      .blkw 5
ShootsTblEnd:

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

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

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

1$:             tst     (R1)+
                beq     3$              ; нашли пустой элемент
                cmp     #ShootsTblEnd, R1
                bne     1$
2$:             return
; ───────────────────────────────────────────────────────────────────────────

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

                inc     NumShoots       ; текущее количество выстрелов
                return
; End of function AddShootFlight


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

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

ShootsFlightAnim:
                mov     #ShootsTbl, R1

sfa_1$:         tst     (R1)
                bne     3$
                tst     (R1)+

jmp_3702:       cmp     #ShootsTblEnd, R1
                bne     sfa_1$
                return
; ───────────────────────────────────────────────────────────────────────────

3$:             mov     (R1), R0        ; адрес экрана
                mov     SprFlightBullet, R2 ; пулька
                call    sub_24542       ; Продолжение анимации выстрелов ГГ
                                        ; эту п/п надо вставить сюда
                mov     R0, R3          ; проверим
                bic     #177700, R3     ; за экран вылетела?
                beq     8$              ; да - надо удалить
                mov     R0, (R1)+       ; нет - новый адрес в массив
                xor     R2, (R0)        ; нарисуем на новом месте
                br      jmp_3702
; ───────────────────────────────────────────────────────────────────────────

8$:             clr     (R1)+
                dec     @#NumShoots     ; текущее количество выстрелов
                br      jmp_3702
; End of function ShootsFlightAnim


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

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

GGShootSound:   mov     #GGShootSndPtr, R5 ; адрес адреса
                tst     (R5)            ; там пусто?
                beq     1$              ; да - ничего не надо делать
                mov     (R5), R1        ; берём адрес
                tst     (R1)+           ; +2
                cmp     R1, #ShootSndEnd-14  ; до конца дошли?
                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          ; звучок
                bis     #100, @100250   ; bis #100, @#177716

                sob     R0, .
                mov     R1, R0
                bic     #100, @100452   ; bic #100, @#177716

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

; ───────────────────────────────────────────────────────────────────────────
; Спрайты размером 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
                .word 0
                .word 0
; ───────────────────────────────────────────────────────────────────────────
; обозначение трапов:
; 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          ; n * 100 (на размер спрайта)
                asl     R1
                asl     R1
                asl     R1
                asl     R1
                asl     R1
                asl     R1
                add     #SprEnemy1, R1  ; получим адрес спрайта
                cmp     R5, #31         ; проверим, какой тип вывода спрайта задали
                bhi     6$              ; другой
                mov     R0, R3          ; первый
                bic     #177700, R3     ; посмотрим смещение
                cmp     #76, R3         ; если совсем справа
                beq     2$              ; пойдём туда
                call    @#sub_11212     ; проверка на верхнюю границу
                bcs     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$
                rti
; ───────────────────────────────────────────────────────────────────────────
; тут вывод с отсечкой границ

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

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

4$:             rti
; ───────────────────────────────────────────────────────────────────────────

5$:             xor     R3, (R0)+       ; выводим первое слово
                tst     (R1)+           ; пропускаем второе
                br      3$
; ───────────────────────────────────────────────────────────────────────────

6$:             cmp     R5, #200        ; номер спрайта больше 200?
                bhis    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
; ───────────────────────────────────────────────────────────────────────────

10$:            cmp     (R1)+, (R0)+    ; тогда пропускаем всю линию спрайта и адрес экрана++
                br      3$
; End of function DisTrap

; ───────────────────────────────────────────────────────────────────────────
StageNum:       .word 0                 ; Номер текущего этапа
; таблица команд 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:

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

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

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

1$:             mov     R1, @#OscTrpTblPtr ; и сохраним указатель в таблице
                mov     (R1)+, @#0OscTrapCmd$ ; и снова задаём очередную команду
                mov     #PanelOscAddr, R0 ; адрес экрана

0OscTrapCmd$:   trap    230             ; рисуем осциллограмму
; теперь анимируем график слева вверху
                mov     #PanelGraphAddr, R0
                clc
                mov     #5, R1

2$:             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$:             br      6$
; ───────────────────────────────────────────────────────────────────────────
; Спрайт размером 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
PanelDiagram:   .word PanelDiagrAddr    ; адрес
                .word 2                 ; маска
; ───────────────────────────────────────────────────────────────────────────
; анимируем диаграмму на панели

6$:             mov     #PanelDiagram, R5 ; адрес в панели
                mov     R5, R1
                tst     (R1)+           ; маска в панели
                bis     (R1), @(R5)+    ; устанавливаем
                tst     -(R5)
                asl     (R1)            ; маску двинем
                asl     (R1)
                bne     7$              ; слово не кончилось - переход
                inc     (R5)            ; кончилось - переходим к новому слову
                inc     (R5)
                inc     (R1)            ; и делаем новую маску
                inc     (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

; ───────────────────────────────────────────────────────────────────────────
; таблица врагов
; размер элемента - 10 байтов (4 слова)
; .word адрес экрана
; .word параметр 1
; .word параметр 2
; .word адрес подпрограммы обработки
EnemyBuffer:    .word 75542, 2000, 12074, 11330
                .word 75224, 177776, 0, 34614
                .word 67442, 10000, 12073, 11330
                .word 70144, 1000, 12073, 11330
                .word 71130, 76, 0, 34614
                .word 65264, 4000, 12067, 11330
                .word 111530, 476, 0, 34614
                .word 63266, 20000, 12066, 11330
                .word 74436, 177576, 0, 34614
                .word 62662, 476, 0, 34614
                .word 74136, 76, 0, 34614
                .word 71442, 177576, 0, 34614
                .word 62164, 177176, 0, 34614
                .word 0, 0, 0, 0
                .word 0, 0, 0, 0
EnemyBufferEnd:
; Последний элемент особенный. Для Босса
BossAddr:       .word 0
BossParam1:     .word 0
                .word 0
BossMoveProc:   .word 0
EnemyBufferFullEnd:
EnemyBufferItemSize = 10

; ███████████████ 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 ███████████████████████████████████████


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

jmp_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 ███████████████████████████████████████

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

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

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

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

; ───────────────────────────────────────────────────────────────────────────
GetRndAddrAcc:  .word 5450

; ███████████████ 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

; ───────────────────────────────────────────────────────────────────────────
EnemyBaseOffsetTbl:
                .word -2
                .word 76
                .word 176
                .word -102
                .word 276
                .word -202
                .word 376
                .word -302

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

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

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

1$:             clr     (R1)            ; удаляем из массива элемент
                br      3$              ; и сотрём
; ───────────────────────────────────────────────────────────────────────────
                .word 3757
PriseNum:       .word 0                 ; номер пойманного приза
; ───────────────────────────────────────────────────────────────────────────

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

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

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

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


; ███████████████ 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$:       .word 16272             ; сюда записывается 4733 при правильном пароле
                                        ; выполнение подпрограммы обработки поведения врага
; ───────────────────────────────────────────────────────────────────────────
                mov     (SP)+, R1

2$:             cmp     (R1)+, (R1)+    ; тут надо просто add #10, R1. команда занимает
                cmp     (R1)+, (R1)+    ; так же 2 слова, но работает гораздо быстрее
                cmp     R1, #EnemyBufferFullEnd ; до конца дошли?
                blo     ena_1$          ; нет - продолжим
                return                  ; выходим
; End of function EnemysAnim


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


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

jmp_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 ███████████████████████████████████████

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

MoveEnemy12Proc:mov     R0, -(SP)
                bic     #177700, R0
                bne     2$              ; если долетел до левого края экрана
                clr     (R1)            ; удаляем из массива

1$:             mov     (SP)+, R0       ; и с экрана
                trap    13
                return
; ───────────────────────────────────────────────────────────────────────────

2$:             mov     (SP), R0        ; иначе - вычисляем новый адрес
                tst     -(R0)
                mov     R0, (R1)        ; сохраняем в массиве
                trap    13              ; рисуем на новом месте
                br      1$
; End of function MoveEnemy12Proc


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


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

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

0Enemy3Spr$:    trap    2

Ret_1$:         return
; End of function AddNewEnemyStg1

; ───────────────────────────────────────────────────────────────────────────
ROMAddrSnd:     .word 0                 ; указатель на данные из ПЗУ для звука шума

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

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

AddNewEnemy:    jmp     NextAddNewEnemy$ ; сперва туда, там проверка некоего условия
                                        ; и если не удовлетворяет, то возврат сюда обратно.
; ───────────────────────────────────────────────────────────────────────────

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

2$:             mov     @(R1)+, R1      ; берём число
                sub     177710, R1      ; получим случайное
                cmp     StageNum, #2    ; текущий этап больше 1
                bhis    3$              ; да
                bic     #177720, R1     ; нет, очищаем биты

3$:             bne     4$              ; какая-то извратная логика. Или ошибка.
                                        ; если этап больше 2, или в R1 что-то есть, то переход
                bic     #177720, R1     ; а иначе снова очищаем то же, бессмысленно
                br      5$
; ───────────────────────────────────────────────────────────────────────────

4$:             bic     #177620, R1     ; очищаем другой маской, но до этого более большей маской очищали
                                        ; значит тут тоже бессмысленное действие
5$:             cmp     R1, @#StageNum  ; то, что получилось, больше номера текущего этапа?
                bhi     Ret_1$          ; да - выход
                asl     R1              ; а иначе - добавление врага, соответствующего этапу.
                jmp     @FuncNewEnemys(R1)
; 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

; ███████████████ 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)

me5_1$:         trap    4
2$:             return
; End of function AddNewEnemyStg7


; ███████████████ 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
                bne     2$
                clr     (R1)

1$:             mov     (SP)+, R0
                br      me5_1$
; ───────────────────────────────────────────────────────────────────────────

2$:             mov     R0, (R1)
                trap    4
                br      1$
; End of function MoveEnemy5Proc


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

; Проверка на верхнюю границу экрана
; Вход: R0 - адрес экрана

sub_11212:      cmp     R0, #TopScreen-1700 ; если выше вот этой границы
                blo     1$              ; то вообще выход из прерывания
                cmp     R0, #TopScreen  ; и проверка на игровую границу
                return
; ───────────────────────────────────────────────────────────────────────────

1$:             clr     (SP)+
                rti
; End of function sub_11212


; ███████████████ 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

; ───────────────────────────────────────────────────────────────────────────
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

; ███████████████ 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
                clr     R4
                inc     R4              ; 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

; ───────────────────────────────────────────────────────────────────────────
EnemyTrackOffsetTbl:.word -2
                .word -1002
                .word -1000
                .word -776
                .word 2
                .word 1002
                .word 1000
                .word 776

; ███████████████ 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

; ───────────────────────────────────────────────────────────────────────────
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

; ███████████████ 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

; ───────────────────────────────────────────────────────────────────────────
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

; ███████████████ 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

; ───────────────────────────────────────────────────────────────────────────
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

; ███████████████ 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

; ───────────────────────────────────────────────────────────────────────────
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

; ███████████████ 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

; ───────────────────────────────────────────────────────────────────────────
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

; ███████████████ 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

; ───────────────────────────────────────────────────────────────────────────
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

; ███████████████ 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

; ───────────────────────────────────────────────────────────────────────────
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
; ───────────────────────────────────────────────────────────────────────────

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


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

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

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

; ───────────────────────────────────────────────────────────────────────────
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

; ███████████████ 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

; ───────────────────────────────────────────────────────────────────────────
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

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

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

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

loc_12664:      tst     (R1)            ; элемент пуст?
                beq     loc_12730       ; да
                br      3$              ; нет
; ───────────────────────────────────────────────────────────────────────────

loc_12672:      cmp     R1, #ShootsTblEnd ; таблица закончилась?
                blo     loc_12664       ; нет ещё
                return                  ; выход
; ───────────────────────────────────────────────────────────────────────────

3$:             mov     #EnemyBuffer, R5 ; таблица врагов

loc_12706:      mov     (R5), R3        ; адрес экрана врага
                                        ; тут надо проверять на 0 и если да - переходить к следующему элементу
                mov     (R1), R2        ; адрес экрана пули
                cmp     R2, R3          ; если адрес пули >= адреса врага
                bhis    7$              ; то идём проверять дальше
                                        ; иначе - пуля пролетает над врагом
loc_12716:      cmp     (R5)+, (R5)+    ; add #EnemyBufferItemSize, R5
                cmp     (R5)+, (R5)+
                cmp     R5, #EnemyBufferFullEnd-2 ; таблица закончилась?
                blo     loc_12706       ; нет ещё
                                        ; да
loc_12730:      tst     (R1)+           ; переходим к следующей пуле
                br      loc_12672       ; проверим на конец таблицы
; ───────────────────────────────────────────────────────────────────────────

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

9$:             cmp     #MoveEnemyProc2, R3 ; Вход: R1 - адрес элемента массива в EnemyBuffer
                                        ;       R4 - параметр 1 (мл байт - номер трапа, ст.байт - битовая маска)
                                        ;       R0 - адрес экрана
                                        ;       R2 - параметр 2 (адрес таблицы)
                bne     10$
                bic     #177400, R4     ; получаем номер трапа
                call    @#sub_15462     ; получим номер команды в R4 и начислим очки
                br      12$
; ───────────────────────────────────────────────────────────────────────────

10$:            cmp     #MoveEnemy5Proc, R3 ; Обработчик движения врага 5.
                                        ; Вход: R1 - адрес элемента массива в EnemyBuffer
                                        ;       R0 - адрес экрана
                bne     11$
                call    @#sub_15432     ; получим номер команды в R4 и начислим очки
                br      12$
; End of function CheckEnemyHit


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

; очистка переменных

sub_13066:      clr     @#GGShootSndPtr
                clr     (PC)+
DelayGetPrise:  .word 6                 ; задержка при нажатии на "Fire" перед применением приза
                cmp     #"СН, aFirmuSnek_DlqN+10 ; проверка целостности
                bne     DelayGetPrise   ; проверка не пройдена
                return
; End of function sub_13066

; ───────────────────────────────────────────────────────────────────────────
                .word 743

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


11$:            cmp     #MoveEnemy12Proc, R3 ; Обработчик движения врага 12.
                                        ; Вход: R1 - адрес элемента массива в EnemyBuffer
                                        ;       R0 - адрес экрана
                bne     loc_12730       ; остальных врагов пули не берут
                call    @#sub_15446     ; получим номер команды в R4 и начислим очки

12$:            xor     R2, (R0)        ; удаляем пулю с экрана
                clr     (R1)            ; убираем её из массива
                dec     @#NumShoots     ; текущее количество выстрелов
                mov     R4, 13$         ; задаём команду стирания врага
                mov     (R5), R0        ; снова берём адрес экрана врага
                mov     R1, -(SP)
                mov     R5, -(SP)

13$:            trap    0               ; стираем его с экрана
                mov     (SP), R5
                mov     (R5), R0        ; снова берём адрес экрана врага
                trap    23              ; спрайт взрыва врага
                mov     (SP)+, R5
                mov     (SP)+, R1
                mov     #MoveBlowEnemyProc, 6(R5) ; Функция анимации взрыва врага
                clr     2(R5)           ; начальные значения
                clr     4(R5)           ; параметров
                mov     #100200, @#ROMAddrSnd ; запускаем звук взрыва врага
                br      loc_12730       ; идём к следующей пуле
; End of function 11$


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

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

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$ ; константа значения счётчика до появления приза
                call    sub_16150
                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 == 0
;       R0 - адрес экрана
;       R2 - параметр 2 == 0

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 ███████████████████████████████████████

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

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

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

jmp_13436:      add     (R1), CmdPriseType$

CmdPriseType$:  trap    117

Ret_2$:         return                  ; без очков
; End of function IndicatePrise

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

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

6$:             call    @#ApplyPrise    ; Применяем текущий приз
                br      7CatchPriseNext$
; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR IndicatePrise

3IndicatePrise$:add     #230., @#Score
                cmp     #"SS, strAbout+10 ; проверка целостности
                beq     Ret_2$
                swab    PC
; END OF FUNCTION CHUNK FOR IndicatePrise

; ███████████████ 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$
                bis     #100, @101104
                br      6$
; ───────────────────────────────────────────────────────────────────────────

5$:             bic     #100, @102066

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


; ███████████████ 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
                bne     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
                br      CatchPriseNext5$
; END OF FUNCTION CHUNK FOR CatchPrise
; ───────────────────────────────────────────────────────────────────────────
                .word 242
; ───────────────────────────────────────────────────────────────────────────

7CatchPriseNext$:
                clr     @#PriseNum      ; номер пойманного приза
                call    @#sub_15662
                trap    116

8CatchPriseNext$:
                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 ███████████████████████████████████████

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

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


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

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

NextShieldOn:   tst     @#ShieldFieldFlag ; флаг включённого защитного поля
                bne     Ret_4$
                inc     @#ShieldFieldFlag ; флаг включённого защитного поля

jmp_14064:      mov     @#ShieldEffectOffset, R1
                dec     R1
                jmp     @#DrawShieldEffect ; рисовать эффект защитного поля
                                        ; Вход: R1 - номер смещения в таблице смещений
; End of function NextShieldOn


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

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

BlowBombFunc:   call    @#sub_26636
                mov     #BottomScreen, R1 ; эффект вспышки на экране
                bic     100262, @102610 ; bic #1000, @#177664

1$:             comb    (R0)+
                cmpb    (R0)+, (R0)+
                cmp     R0, R1
                blo     1$
                bis     100444, @104764 ; bis #1000, @#177664
                mov     #6666, R0
                sob     R0, .
                bic     107646, @105024 ; bic #1000, @#177664
                mov     #TopScreen, R0
                mov     #13000, R1

2$:             clr     (R0)+
                sob     R1, 2$

                mov     #EnemyBuffer, R5

3$:             mov     (R5), R0
                bne     7$

4$:             add     #EnemyBufferItemSize, R5
                cmp     R5, #EnemyBufferFullEnd-2
                blo     3$
                bis     113166, @102610 ; bis #1000, @#177664
                mov     #ShootsTbl, R1

5$:             clr     (R1)+
                cmp     R1, #ShootsTblEnd
                bne     5$
                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 - номер смещения в таблице смещений
; ───────────────────────────────────────────────────────────────────────────

7$:             mov     R5, -(SP)       ; взрыв врага
                trap    23
                mov     (SP)+, R5
                clr     4(R5)
                clr     2(R5)
                mov     #MoveBlowEnemyProc, 6(R5) ; Функция анимации взрыва врага
                mov     #100200, @#ROMAddrSnd
                br      4$
; End of function BlowBombFunc


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

; Ускорение

SpeedUp:        tst     @#SpeedValue    ; есть куда ускоряться?
                beq     Ret_6$          ; всё уже, максимум
                dec     @#SpeedValue    ; есть - ускоряемся

Ret_6$:         return
; End of function SpeedUp


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

; анимация движения самолётика

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

1$:             jmp     GoAnimFlight1$
; End of function AnimFlightSub


; ███████████████ 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$
                br      NextShieldOn    ; Включение защитного поля
; End of function ShieldOn


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

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

sub_14440:      tst     ShieldFieldFlag ; щит включён?
                beq     1$              ; нет
                dec     (PC)+           ; да, пришла пора уменьшать?
ShieldFallSpeed:.word 2                 ; скорость уменьшения щита
                beq     2$              ; да - пойдём обрабатывать

1$:             jmp     @#EnemysAnim    ; тут вот как обычно неоптимальное использование beq/bne
; ───────────────────────────────────────────────────────────────────────────
                ; уменьшаем полоску шкалы уровня защитного поля
2$:             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$              ; слово ещё не кончилось
                tst     -(R0)           ; кончилось - переходим к следующему
                mov     #100000, R1     ; задаём новую маску
                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
                jmp     @#EnemysAnim    ; Анимация и обработка всех врагов
; End of function sub_14440

; ───────────────────────────────────────────────────────────────────────────
; шрифт в виде спрайта. шириной 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

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

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

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

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

2$:             sub     #'0, R0
                bhis    5$              ; если цифра, то идём выводить цифры
                                        ; иначе - игнорим всё остальное
3$:             mov     (SP)+, R4
4$:             rti
; ───────────────────────────────────────────────────────────────────────────

5$:             mov     #Digits, R1
                br      7$
; ───────────────────────────────────────────────────────────────────────────

6$:             cmp     R0, #'Z
                bhi     3$              ; игнорим всё, что больше буквы 'Z'
                sub     #'A, R0
                blo     3$              ; и всё, что не буквы
                mov     #<Digits+12>, 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        ; Адрес символа
                br      3$
; End of function DisIot


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


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

1$:             asr     R3              ; расширяем байт в слово
                bcs     2$
                clc
                ror     (R0)
                clc
                br      3$
; ───────────────────────────────────────────────────────────────────────────

2$:             sec
                ror     (R0)
                sec

3$:             ror     (R0)
                sob     R5, 1$
                bic     @#FON, (R0)     ; Фон экрана
                add     #100, R0
                return
; End of function DrawChrLine

; ───────────────────────────────────────────────────────────────────────────
Score:          .word 0                 ; Счёт игры

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


sub_15432:      mov     (PC)+, R4       ; получим номер команды
                        trap 4
                add     #25., @#Score   ; начисляем очки
                return
; End of function sub_15432


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


sub_15446:      mov     (PC)+, R4       ; получим номер команды
                        trap 13
                add     #5, @#Score     ; начисляем очки
                return
; End of function sub_15446


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


sub_15462:      add     #104400, R4     ; получим номер команды
                add     #15., @#Score   ; начисляем очки
Ret_7$:         return
; End of function sub_15462

; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR CheckoutScore

NextCheckoutScore$:
                call    @#CalcMoveStars ; Вычисляем новые координаты звёзд и отображаем их
                dec     (PC)+           ; пора?
word_15504:     .word 20
                bne     Ret_7$          ; нет ещё
                mov     #70, @#word_15504 ; да - выводим счёт на экран, но почему-то не кратно 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
                bmi     2$
                inc     R0
                br      1$
; ───────────────────────────────────────────────────────────────────────────

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

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

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

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

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

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

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


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


sub_15662:      mov     #PanelPriseAddr, R0
                add     #50., Score
Ret_8$:         return
; End of function sub_15662

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

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

CheckFlightHit: call    @#CatchPrise    ; Включение защитного поля, если пойман соответствующий приз
                                        ; Проверка на призы и пойман ли приз
                                        ; Нужно ли применять эффект приза
                call    @#CheckFlightDamageAnim ; уже отрабатывается анимация подбития?
                bne     Ret_8$          ; да - дальше не идём
                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    Ret_8$          ; ### то всё ещё в порядке
                ;br      Ret_8$          ; ### то всё ещё в порядке
                mov     @#GGAddr, R0    ; текущий адрес спрайта самолётика
                call    @#sub_16024     ; стираем самолётик, рисуем взрыв
                mov     #BlowFlightAnim, @#AtBlowFlightAnim ; задаём п/п анимации подбития

NoAnims:        return                  ; нет анимации подбития самолётика
; End of function CheckFlightHit

; ───────────────────────────────────────────────────────────────────────────
AtBlowFlightAnim:.word NoAnims          ; адрес п/п отработки анимации взрыва самолётика
                                        ; либо указатель на 207, если ещё не взрыв

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


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


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


sub_16024:      call    @#DrawFlight    ; Вход: R0 - адрес экрана
                clr     @#CurBlowAnimSpr ; номер текущего спрайта анимации взрыва самолётика
                clr     R5
                jmp     @#BlowFlight    ; Взрыв самолётика
; End of function sub_16024             ; Вход: R5 - номер спрайта в анимации 0..4

; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR BlowFlightAnim

NextBlowFlightAnim$:
                com     #-1             ; отрабатывать через раз
                beq     CheckFlightDamageAnim+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
                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     NextAfterBlowFlightAnim$
                return
; End of function AfterBlowFlightAnim

; ───────────────────────────────────────────────────────────────────────────
                .word 0
                .word 0
                .word 0
                .word 0

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


sub_16150:      clr     4(R1)
                cmp     #207, @AtBlowFlightAnim ; адрес п/п отработки анимации взрыва самолётика
                                        ; либо указатель на 207, если ещё не взрыв
                beq     4$
                clr     (SP)+
                clr     (R1)
4$:             return
; End of function sub_16150


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


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

InitGameValues2:bic     113522, @102610 ; bic #1000, @#177664
                call    @#Cls1
                clr     @#AutoShootFlag ; выключаем автоматическую стрельбу
                call    @#InitVars3     ; Инициализация переменных
                call    @#StartingDrawFlight ; отображение самолётика с начальной позиции
                call    @#InitialDrawStars ; Начальное отображение звёзд по таблице на экране
                call    sub_30420       ; очистка переменных
                mov     #EnemyBuffer, R1 ; очистка буфера врагов

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

2$:             clr     (R1)+
                sob     R0, 2$
                call    @#TestShieldOn  ; если защитное поле включено, оставить включённым
                bis     113654, @105024 ; bis #1000, @#177664

Ret_11$:        return
; End of function InitGameValues

; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR AfterBlowFlightAnim

NextAfterBlowFlightAnim$:
                dec     @#Lives
                beq     FlightDead
                call    @#ShowLives     ; Отображение на панели количества жизней
                br      InitGameValues
; END OF FUNCTION CHUNK FOR AfterBlowFlightAnim
; ───────────────────────────────────────────────────────────────────────────
Lives:          .word 0                 ; жизни

; ███████████████ 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     Ret_11$

3$:             mov     #6, R2

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


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


sub_16436:      cmp     (PC)+, R4     ; если враг - Enemy11
                        trap 12
                beq     1$              ; то выход
                add     #3, @#Score     ; а за остальных начисляются очки
1$:             return
; End of function sub_16436

; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR AddEnemys

loc_16454:      jmp     jmp_34660
; END OF FUNCTION CHUNK FOR AddEnemys
; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR AfterBlowFlightAnim

FlightDead:     call    @#ShowLives     ; Отображение на панели количества жизней
                mov     #43040, strPressFire+5 ; " F" что-то непонятное
                mov     strEnterYourName, strXenon+1 ; непонятно зачем делаемое
                call    ShowGameOver
                clr     R0
                mov     #<SprEnemy1+5>, R1
                br      16520$
; END OF FUNCTION CHUNK FOR AfterBlowFlightAnim
; ───────────────────────────────────────────────────────────────────────────
AddLiveVal:     .word 0                 ; граничное значение для добавления доп.жизней
GribOnScreen:   .word 0                 ; флаг врага типа "Гриб" на экране
; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR AfterBlowFlightAnim

16520$:         call    sub_32476       ; проверка целостности
                                        ; R0 = 67700, R1 = 7243
                xor     R1, R0          ; R0 = 60543
                swab    R0              ; R0 = 61541
                sub     #42101, R0      ; R0 = 17440
                jmp     (R0)            ; jmp loc_17440
; END OF FUNCTION CHUNK FOR AfterBlowFlightAnim

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

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

AddEnemys:      tst     (PC)+           ; смотрим этот счётчик
StageDurationCnt1:.word 724
                bne     1$              ; пока не 0 - идём его уменьшать
; когда первый счётчик обнулится
; начинаем уменьшать второй
                dec     (PC)+           ; уменьшаем счётчик длительности этапа
StageDurationCnt2:.word 1500
                beq     loc_16454       ; 0 - пора переходить к следующему этапу
                jmp     @#AddNewEnemy   ; Функция добавления нового врага
; ───────────────────────────────────────────────────────────────────────────

1$:             dec     @#StageDurationCnt1 ; уменьшаем
                call    @#GetRNDScrAddr ; Получение случайного адреса экрана
                                        ; Выход: R0 - адрес экрана с правого края
                bic     #176077, R0
                cmp     #600, R0
                bne     Ret_11$
                mov     @#StageNum, R0  ; Номер текущего этапа
                asl     R0
                jmp     @FuncNewEnemys(R0) ; и добавим нового врага, соответствующего этапу
; End of function AddEnemys


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


NewStage:       bic     115260, @104764 ; bic #1000, @#177664
                mov     #TopScreen, R1  ; очищаем экран
                mov     #13000, R0

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

2$:             call    @#DynamicSplash ; Движение динамических объектов в заставке
                beq     2$              ; теперь, пока не нажмём "FIRE" в цикле крутим анимацию
                call    @#InitGameValues2 ; снова инициализация
                br      16732$
; ───────────────────────────────────────────────────────────────────────────
strStage:       .asciz "STAGE *"
                .even
; ───────────────────────────────────────────────────────────────────────────

16732$:         cmp     #13., @#StageNum ; Номер текущего этапа
                beq     3$              ; конец игры
                call    @#StageUp       ; иначе увеличиваем номер этапа
                                        ; т.е. на экране номер этапа на 1 меньше, чем в игре получается
                mov     #2000, @#StageDurationCnt1
                mov     #2700, @#StageDurationCnt2
                return
; ───────────────────────────────────────────────────────────────────────────

3$:             jmp     @#GameFinish
; End of function NewStage

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


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

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

; ───────────────────────────────────────────────────────────────────────────
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:

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

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

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

1$:             tst     (R1)+
                cmp     (R2)+, @101016  ; 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

; ───────────────────────────────────────────────────────────────────────────
; Таблица смещений адреса ГГ соответствующих направлению движения
MoveOffsets:    .word -2
                .word -1002
                .word -1000
                .word -776
                .word 2
                .word 1002
                .word 1000
                .word 776
                .word 100000            ; "FIRE"

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

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

CheckJoystick:  mov     100242, R2      ; 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

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

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

; ───────────────────────────────────────────────────────────────────────────
; Таблица комбинаций джойстика для движений по диагоналям
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:
; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR sub_22574

GoAnimFlight1$: tst     R0
                beq     Ret_12$
                jmp     @#AnimFlight    ; Рисуется самолётик и эффект защитного поля
; END OF FUNCTION CHUNK FOR sub_22574

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

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

TestShieldOn:   call    sub_13066       ; очистка переменных
                tst     @#ShieldFieldFlag ; флаг включённого защитного поля
                beq     Ret_12$
                jmp     @#jmp_14064     ; запускаем анимацию защитного поля
; End of function TestShieldOn


; ███████████████ 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$:             call    @#sub_22264
                mov     R4, R0
                iot
                return
; End of function DecOut2

; ───────────────────────────────────────────────────────────────────────────
EnterValidPassFlag:.word 1

; ███████████████ 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    sub_32144
                tst     R5
                return
; End of function DynamicSplash


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


sub_17430:      call    @#CalcMoveStars ; Вычисляем новые координаты звёзд и отображаем их
                jmp     DrawTerrain     ; подготовка в буфере и отображение на экране поверхности земли
; End of function sub_17430

; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR AddEnemys

loc_17440:      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"
                br      loc_17602
; END OF FUNCTION CHUNK FOR AddEnemys
; ───────────────────────────────────────────────────────────────────────────
                .byte    0 ;
                .byte    0 ;

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


StageUp:        inc     @#StageNum      ; Номер текущего этапа
                clr     @#FON           ; Фон экрана
Ret_13$:        return
; End of function StageUp
; ───────────────────────────────────────────────────────────────────────────

; START OF FUNCTION CHUNK FOR AddEnemys

GameFinish:     call    @#InitGameValues
                mov     #56022, @#AS    ; Адрес символа
                mov     #strCongratulations, R4 ; "CONGRATULATIONS"
                call    @#DrawText      ; Вывод текста
                                        ; Вход: R4 - адрес текста
                br      loc_17440
; END OF FUNCTION CHUNK FOR AddEnemys

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

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

DrawText:       movb    (R4)+, R0
                beq     Ret_13$
                iot
                br      DrawText        ; Вывод текста
                                    ; Вход: R4 - адрес текста
; End of function DrawText

; ───────────────────────────────────────────────────────────────────────────
strCongratulations:.asciz "CONGRATULATIONS"
                .even
; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR AddEnemys

loc_17602:      call    @#Cls1
                cmp     @#Score, @#LoScoreRecord
                blos    17724$
                br      17636$
; END OF FUNCTION CHUNK FOR AddEnemys

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


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

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

; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR AddEnemys

17636$:         mov     #strEnterYourName, R4 ; "ENTER YOUR NAME"
; END OF FUNCTION CHUNK FOR AddEnemys

; ███████████████ 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 ; Начальное отображение звёзд по таблице на экране
                br      17750$
; ───────────────────────────────────────────────────────────────────────────

17724$:         jmp     RecTblSplash1$  ; Отображать в заставке таблицу рекордов
; ───────────────────────────────────────────────────────────────────────────
strEnterYourName:.asciz "ENTER YOUR NAME"
                .even
; ───────────────────────────────────────────────────────────────────────────

17750$:         mov     (PC)+, R4
InputBufAddr:   .word   InputBuf

LoopEnterPass$: mov     R4, -(SP)

1$:             call    sub_20026
                mov     #1300, R0

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

3$:             mov     #127, R0

4$:             bit     #100, @110344   ; bit #100, @#177716
                beq     5$
                sob     R0, 4$
                call    sub_20026
                br      3$
; End of function InputString


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


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

; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR InputString

5$:             mov     (SP)+, R4
                mov     @102120, R0     ; mov @#177662, R0
                cmp     R0, #30         ; забой?
                bne     6$              ; нет
                cmp     R4, @#InputBufAddr ; до начала дошли?
                beq     LoopEnterPass$  ; да - игнорируем
                movb    #40, -(R4)      ; удаляем последний введённый символ
                sub     #2, @#AS        ; Адрес символа
                mov     #56, 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     GoWorkRecTbk    ; для ввода пароля тут переход на адрес 17634
                                        ; а сейчас - переход на обработку таблицы рекордов
                movb    #40, (R4)+
                br      EndEnterPass$
; END OF FUNCTION CHUNK FOR InputString
; ───────────────────────────────────────────────────────────────────────────
; буфер пароля или имени, 6 байтов
InputBuf:       .byte 156, 17, 333, 11, 40, 45

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

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

AfterDeadAnim:  mov     #<Digits+116>, @113654 ; mov #14726,@#1000 - какая-то фигня, которая портит первое слово
                call    @#EnemysAnim    ; Анимация и обработка всех врагов
                call    @#AddNewEnemy   ; Функция добавления нового врага
                jmp     @#DynamicSplash ; Движение динамических объектов в заставке
; End of function AfterDeadAnim

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

GoWorkRecTbk:   call    @#Cls1
                br      20400$
; ───────────────────────────────────────────────────────────────────────────
; Таблица рекордов
; сперва слово - число, затем 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
; ───────────────────────────────────────────────────────────────────────────

20400$:         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
                br      StartSplash
; End of function RecTblSplash1$

; ───────────────────────────────────────────────────────────────────────────
BossFlag:     .word 0                   ; флаг наличия босса на экране

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


PutRecordTable: bic     100262, @104764 ; 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 ; размер таблицы рекордов
                bne     1$
                call    @#InitialDrawStars ; Начальное отображение звёзд по таблице на экране
                bis     100444, @105024 ; bis #1000, @#177664

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

; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR CountToReclama

StartSplash:    bic     113522, @104764 ; bic #1000, @#177664
                call    CheckCheat      ; Здесь проверяется условие ввода чита
; Рисуем ромбик из цепочек
                mov     #50630, R0      ; адрес экрана
                mov     #1776, R3       ; смещение для адреса экрана
                mov     #104515, R4
                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
                br      NextSplash1$
; END OF FUNCTION CHUNK FOR CountToReclama

; ███████████████ 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

; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR CountToReclama

NextSplash1$:   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 - адрес текста
                br      NextSplash2$
; END OF FUNCTION CHUNK FOR CountToReclama
; ───────────────────────────────────────────────────────────────────────────
strAbout:       .asciz "GAME BY SSV"
                .asciz "NICOLAEV  1992"
strPressFire:   .asciz "PRESS FIRE BUTTON"
strXenon:       .asciz "XENON"
                .asciz "K..KEYBOARD"
                .asciz "J..JOYSTICK"
                .even
; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR CountToReclama

NextSplash2$:   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     107646, @105024 ; bis #1000, @#177664
                mov     #742, SP
                mov     #RecTblSplash, @110172 ; 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$
; ───────────────────────────────────────────────────────────────────────────

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

LoopSplash:     mov     #740, SP
                jmp     @#StartSplash
; ───────────────────────────────────────────────────────────────────────────

6$:             mov     #LoopSplash, @104354 ; mov #LoopSplash,@#4
                jmp     jmp_26714
; ───────────────────────────────────────────────────────────────────────────

SetKeyboard$:   bic     113522, @102610 ; 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     115756, @104764 ; bic #1000, @#177664
                call    @#Cls1
                mov     #JoyTab, R5
                mov     #55232, @#AS    ; Адрес символа
                mov     #strCtrlJoy, R4 ; "LEFT"
                mov     #5, @#CtrlCnt
                mov     #SetJoyProc, @#AtCtrlProc
                br      21746$
; END OF FUNCTION CHUNK FOR CountToReclama
; ───────────────────────────────────────────────────────────────────────────
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
; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR CountToReclama

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     113166, @102610 ; bis #1000, @#177664
                call    @AtCtrlProc
                mov     R0, (R5)+
                dec     @#CtrlCnt
                bne     2$
                br      LoopSplash
; END OF FUNCTION CHUNK FOR CountToReclama

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


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

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

SetJoyProc:     mov     100242, R2      ; 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
                bis     R2, @117544     ; bis R2,@#177716
                mov     R2, R3

                sob     R3, .
                bic     R2, @117600     ; bic R2,@#177716

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


; ███████████████ 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
Ret_14$:        return
; End of function DynamicSplashSR


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

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

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


; ███████████████ 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$:             jmp     @#NextCheckoutScore$
; End of function CheckoutScore


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


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

1$:             iot
2$:             add     #'0, R4
                return
; End of function sub_22264

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

GoNext1$:       reset

0Wrong$:        bic     113616, @105024 ; bic #1000, @#177664
                call    Cls1
                tst     42014           ; проверка целостности (тут всегда не 0)
                beq     0Wrong$+2
                mov     115650, R0      ; R0 = 36000 = TerrainBuffer
                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$
                com     #0              ; этот код должен выполняться единожды
                beq     0Wrong$+2       ; поэтому этот переход не должен срабатывать
                mov     #SprGround2, CurTerrainSpr
                mov     #1, BitMaskInSpr
                mov     #222, 177712
                jmp     StartSplash
; ───────────────────────────────────────────────────────────────────────────
; тут на каждую функцию навешано слишком много действий
; чтоб можно было как-то актуально их назвать
; и счётчики, очень много счётчиков, так что непонятно, что когда происходит

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

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

Secret1$:       call    @#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 ███████████████████████████████████████

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

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

1$:             call    CheckShoot      ; проверка, не пора ли делать выстрел.
                                        ; Если пора - то выход из функции
                                        ; Если не пора - то выход на уровень вверх
                tst     (PC)+
MakeShootFlag$: .word 0                 ; флаг, чтобы при нажатой кнопке стрельбы засчитывать только один выстрел
                bne     jmp_22646
                inc     MakeShootFlag$  ; флаг, чтобы при нажатой кнопке стрельбы засчитывать только один выстрел
                mov     R0, -(SP)
                call    @#AddShootFlight ; Добавление нового выстрела ГГ в таблицу
                mov     (SP)+, R0

jmp_22646:      jmp     @#AnimFlightSub
; ───────────────────────────────────────────────────────────────────────────

3$:             return
; End of function sub_22574


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

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

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

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


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

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

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

; ───────────────────────────────────────────────────────────────────────────
; спрайты взрыва размер 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

; ███████████████ 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 ███████████████████████████████████████

; Проверка, пусто ли в правом краю экрана напротив ГГ
; Вход: 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 ███████████████████████████████████████


AutoShoot:      inc     (PC)+
AutoShootFlag:  .word 0
                return
; End of function AutoShoot


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

; проверка, не пора ли делать выстрел.
; Если пора - то выход из функции
; Если не пора - то выход на уровень вверх

CheckShoot:     tst     @#AutoShootFlag
                bne     2$
                tst     R5
                bne     Ret_15$

cs_1$:          clr     (SP)+
                jmp     @#jmp_22646
; ───────────────────────────────────────────────────────────────────────────

2$:             dec     (PC)+
AutoShootDelay: .word 3                 ; Задержка между выстрелами при автоматической стрельбе
                bne     cs_1$
                jmp     jmp_27164
; End of function CheckShoot


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

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

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

; ───────────────────────────────────────────────────────────────────────────
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:

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

; Продолжение анимации выстрелов ГГ
; обработка режима trex

sub_24542:      xor     R2, (R0)        ; стираем пульку со старого места
                tst     (R0)+           ; новый адрес
                tst     TrexMode        ; режим ТРЕКС (изменение траектории полёта пуль)
                beq     7$              ; нет
                mov     R1, R4          ; текущий указатель в массиве
                sub     #ShootsTbl, R4  ; индекс пульки в массиве
                add     #TrexValIdx, R4 ; теперь это индекс в этом массиве
                add     #2, (R4)        ; увеличим значение
                cmp     #TrexValueEnd-TrexValue, (R4) ; максимум?
                bne     4$              ; нет ещё
                clr     (R4)            ; да - обнулим

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

5$:             clr     (SP)+           ; то её удаляем из массива и идём смотреть следующую
                clr     (R1)+           ; это есть уже по адресу 8$
                                        ; зачем дублировать было надо?
                dec     @#NumShoots     ; текущее количество выстрелов
                jmp     @#jmp_3702
; ───────────────────────────────────────────────────────────────────────────

6$:             cmp     R0, #BottomScreen
                bhi     5$

7$:             return
; End of function sub_24542

; ───────────────────────────────────────────────────────────────────────────
; индексы в таблице TrexValue для каждой пульки
TrexValIdx:     .word 26
                .word 30
                .word 22
                .word 24
                .word 6

; ███████████████ 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

; ───────────────────────────────────────────────────────────────────────────
; Три спрайта размером 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
; ███████████████ 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$

4$:             jsr     R4, @#110362
                return
; ───────────────────────────────────────────────────────────────────────────

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$
                br      4$
; End of function DrawGrib

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

AddNewEnemyStg8:
                bit     #140000, @#177710
                bne     1$

loc_25734:      jmp     @#AddNewEnemy7
; ───────────────────────────────────────────────────────────────────────────

1$:             call    @#sub_26204
                com     #-1
                bne     2$
                mov     #TopScreen-3000+100, R0
                br      3$
; ───────────────────────────────────────────────────────────────────────────

2$:             mov     #BottomScreen, R0

3$:             call    @#sub_26624
                bic     #177700, R2
                add     R2, R0
                tst     (R0)+
                mov     R0, (R1)+
                clr     (R1)+
                mov     #MoveEnemyGribProc, 2(R1)
                clr     R1
                br      DrawGrib        ; вывод спрайта грибка
                                        ; Вход: R0 - адрес экрана
                                        ;       R1 - номер спрайта 0..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
                br      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$
; ───────────────────────────────────────────────────────────────────────────
word_26174:     .word 0
                .word 1
                .word 2
                .word 1

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


sub_26204:      mov     #<EnemyBuffer+6>, R1

1$:             tst     -6(R1)
                beq     2$
                cmp     (R1), #MoveEnemyGribProc
                beq     3$

2$:             add     #EnemyBufferItemSize, R1
                cmp     R1, #EnemyBufferFullEnd-2
                blos    1$
                jmp     @#SearchFreeItem ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
; ───────────────────────────────────────────────────────────────────────────

3$:             clr     (SP)+
                br      loc_25734
; End of function sub_26204


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

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

CheckAllEnemyHit: call    CheckBossHit

jmp_26252:      call    @#sub_26650

loc_26256:      tst     (R1)
                beq     loc_26322
                br      4$
; ───────────────────────────────────────────────────────────────────────────

loc_26264:      cmp     R1, #ShootsTblEnd
                blo     loc_26256
                return
; ───────────────────────────────────────────────────────────────────────────

4$:             mov     #EnemyBuffer, R5

loc_26300:      mov     (R5), R3
                mov     (R1), R2
                cmp     R2, R3
                bhis    8$

jmp_26310:      add     #EnemyBufferItemSize, R5
                cmp     R5, #EnemyBufferFullEnd-2
                blo     loc_26300

loc_26322:      tst     (R1)+
                br      loc_26264
; ───────────────────────────────────────────────────────────────────────────

8$:             cmp     #MoveEnemyGribProc, 6(R5)
                bne     jmp_26310
                jmp     jmp_27174
; End of function CheckAllEnemyHit

; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR CheckAllEnemyHit

jmp_26342:      cmp     R2, R3
                bhi     loc_26322
                bic     #177700, R2
                bic     #177700, R3
                cmp     R2, R3
                blo     loc_26322
                cmp     (R3)+, (R3)+
                cmp     R3, R2
                blo     loc_26322
                mov     (R1), R0
                mov     @#SprFlightBullet, R2
                clr     (R1)
                xor     R2, (R0)
                mov     (R5), R0
                mov     2(R5), R1
                mov     word_26174(R1), R1
                mov     #MoveGribBlowProc, 6(R5)
                clr     2(R5)
                call    @#sub_26612
                clr     R5
                dec     @#NumShoots     ; текущее количество выстрелов
                mov     #100200, @#ROMAddrSnd
                jmp     @#BlowEnemy     ; Взрыв Врага
                                        ; Вход: R5 - номер спрайта в анимации 0..4
                                        ;       R0 - адрес экрана
; END OF FUNCTION CHUNK FOR CheckAllEnemyHit

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


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 ███████████████████████████████████████

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

CheckPause:     call    @#GGShootSound  ; Звук выстрела самолётика
                bit     #100, @116110   ; bit #100, @#177716 клавиша нажата?
                bne     1$              ; нет
                clr     R1              ; да
                xor     R0, R4          ; чё то непонятное
                cmp     #'P, @111610    ; 177662 это P?
                beq     GamePause
                cmp     #'p, @101016    ; 177662 или p?
                beq     GamePause       ; да - ставим игру на паузу

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

GamePause:      call    @#sub_27150
                call    @#CheckPressFire ; Выход: R5 - флаг: !0 - было нажато "FIRE", 0 - всё остальное
                tst     R5
                beq     GamePause
                return
; End of function CheckPause


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


sub_26612:      call    @#DrawGrib      ; вывод спрайта грибка
                                        ; Вход: R0 - адрес экрана
                                        ;       R1 - номер спрайта 0..2
                clr     @#GribOnScreen
                return
; End of function sub_26612


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


sub_26624:      inc     @#GribOnScreen
                mov     @#GGAddr, R2    ; текущий адрес спрайта самолётика
                return
; End of function sub_26624


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


sub_26636:      mov     #TopScreen, R0
                clr     @#GribOnScreen
                return
; End of function sub_26636


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


sub_26650:      mov     #ShootsTbl, R1
                tst     @#GribOnScreen
                bne     1$
                clr     (SP)+
1$:             return
; End of function sub_26650


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

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

InitVars3:      clr     @#TrexMode      ; режим ТРЕКС (изменение траектории полёта пуль)
                clr     @#GribOnScreen
                clr     @#ROMAddrSnd
                return
; End of function InitVars3

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

EntryPoint$:    clr     EnterValidPassFlag
                jmp     GoNext1$
; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR CountToReclama

jmp_26714:      tst     @#EnterValidPassFlag
                beq     1$

Secret3$:       jmp     @#BlowFlight    ; здесь становится адрес перехода 22440==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
; END OF FUNCTION CHUNK FOR CountToReclama
; ───────────────────────────────────────────────────────────────────────────
strEnterPassword:.asciz "ENTER PASSWORD"
                .even
strWrongPassword:.asciz "WRONG PASSWORD"
                .even
; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR CountToReclama

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

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


sub_27150:      call    @#AnimPanel     ; прорисовка осциллограммы, мигающей лампочки и прочих элементов панели
                mov     #16666, R0
                sob     R0, .
                return
; End of function sub_27150

; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR CheckShoot

jmp_27164:      mov     #5, AutoShootDelay ; Задержка между выстрелами при автоматической стрельбе
                return
; END OF FUNCTION CHUNK FOR CheckShoot
; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR CheckAllEnemyHit

jmp_27174:      tst     (R5)
                beq     10$
                add     #2600, R3
                jmp     jmp_26342
; ───────────────────────────────────────────────────────────────────────────

10$:            jmp     jmp_26310
; END OF FUNCTION CHUNK FOR CheckAllEnemyHit
; ───────────────────────────────────────────────────────────────────────────
; вот сюда не нашёл, как попасть 27214
                clr     (R1)
                add     #100., Score
                jmp     jmp_13436
; ───────────────────────────────────────────────────────────────────────────
; Спрайт размерами 14 х 60
; заксоренный своими адресами.
; Это БОСС - какая-то насекомая на яйцах
SprBoss:        .byte 232, 56, 234, 56, 236, 356, 137, 321, 242, 56, 244, 56
                .byte 246, 56, 250, 56, 132, 321, 123, 321, 121, 55, 260, 56
                .byte 262, 56, 264, 356, 111, 341, 164, 322, 105, 321, 274, 56
                .byte 276, 56, 300, 322, 75, 56, 304, 341, 71, 321, 307, 56
                .byte 312, 56, 314, 321, 302, 35, 43, 36, 55, 321, 353, 56
                .byte 326, 56, 30, 21, 351, 35, 357, 342, 41, 321, 57, 56
                .byte 342, 56, 44, 21, 325, 55, 350, 35, 25, 321, 23, 55
                .byte 356, 356, 377, 41, 376, 56, 364, 42, 12, 335, 307, 55
                .byte 372, 22, 74, 36, 362, 56, 0, 357, 376, 320, 373, 40
                .byte 6, 54, 10, 357, 11, 57, 14, 57, 376, 340, 357, 43
                .byte 322, 23, 324, 57, 26, 57, 30, 57, 351, 20, 343, 54
                .byte 56, 320, 354, 57, 42, 57, 44, 57, 326, 340, 327, 37
                .byte 32, 320, 340, 43, 56, 57, 60, 57, 316, 20, 313, 54
                .byte 72, 23, 364, 57, 72, 57, 74, 57, 302, 340, 274, 37
                .byte 216, 57, 210, 343, 106, 57, 110, 57, 266, 34, 277, 54
                .byte 102, 57, 237, 43, 121, 37, 124, 23, 252, 43, 224, 37
                .byte 131, 57, 157, 343, 222, 37, 154, 40, 135, 54, 124, 354
                .byte 145, 57, 133, 340, 151, 40, 137, 20, 221, 57, 260, 43
                .byte 161, 357, 107, 354, 271, 357, 267, 340, 105, 43, 274, 354
                .byte 175, 357, 214, 334, 115, 340, 173, 337, 111, 37, 110, 43
                .byte 211, 337, 100, 334, 175, 40, 257, 320, 241, 43, 144, 354
                .byte 225, 20, 133, 357, 231, 354, 143, 340, 222, 54, 120, 57
                .byte 141, 54, 124, 337, 132, 37, 227, 320, 151, 43, 220, 34
                .byte 256, 43, 214, 57, 115, 340, 113, 320, 205, 54, 107, 57
                .byte 105, 54, 274, 57, 216, 23, 377, 340, 16, 337, 367, 43
                .byte 306, 337, 10, 40, 305, 43, 0, 323, 375, 343, 34, 57
                .byte 56, 20, 330, 357, 52, 43, 353, 320, 326, 34, 337, 54
                .byte 336, 57, 340, 37, 322, 57, 50, 23, 345, 57, 330, 57
                .byte 52, 40, 357, 343, 355, 57, 360, 343, 362, 34, 367, 43
                .byte 366, 340, 370, 54, 71, 343, 360, 34, 362, 57, 0, 3
                .byte 2, 60, 4, 317, 306, 74, 10, 60, 366, 17, 374, 60
                .byte 76, 60, 320, 317, 42, 63, 24, 17, 352, 317, 344, 363
                .byte 26, 60, 334, 314, 336, 60, 320, 317, 321, 3, 327, 74
                .byte 51, 60, 350, 60, 32, 60, 320, 317, 342, 377, 360, 363
                .byte 61, 60, 64, 17, 372, 60, 307, 317, 11, 17, 360, 60
                .byte 75, 60, 200, 14, 162, 360, 273, 317, 105, 314, 110, 63
                .byte 105, 60, 214, 60, 216, 360, 257, 317, 235, 14, 147, 60
                .byte 131, 60, 130, 317, 152, 300, 243, 317, 155, 300, 140, 60
                .byte 136, 60, 144, 3, 146, 363, 227, 317, 145, 3, 154, 60
                .byte 222, 60, 160, 363, 175, 17, 204, 317, 105, 360, 170, 63
                .byte 112, 77, 214, 374, 115, 360, 117, 317, 216, 3, 204, 60
                .byte 106, 314, 173, 3, 266, 74, 274, 3, 215, 60, 220, 60
                .byte 222, 17, 124, 374, 125, 77, 233, 374, 232, 60, 234, 60
                .byte 236, 300, 243, 60, 236, 300, 227, 3, 246, 60, 250, 60
                .byte 252, 60, 234, 3, 155, 77, 174, 74, 262, 0, 264, 60
                .byte 266, 60, 270, 60, 272, 300, 274, 60, 276, 63, 300, 60
                .byte 302, 60, 304, 60, 306, 60, 304, 60, 312, 60, 314, 60
                .byte 316, 60, 320, 60, 322, 60, 324, 60, 326, 60, 330, 60
                .byte  232 ;   062232 PC4
                .byte  144 ; d
                .byte  215 ; █ 020615 EN_
                .byte   41 ; !

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


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

loc_30350:      cmp     R0, #TopScreen
                bhis    3$
                add     #14, R1
                add     #100, R0

loc_30366:      sob     R3, loc_30350
                jsr     R4, @#110362
                br      loc_30700
; ───────────────────────────────────────────────────────────────────────────

3$:             mov     #6, R4

loc_30402:      mov     (R1)+, R2
                xor     R1, R2
                br      loc_30666
; End of function DrawBoss

; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR CheckBossHit

loc_30410:      sob     R4, loc_30402
                add     #64, R0
                br      loc_30366
; END OF FUNCTION CHUNK FOR CheckBossHit

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

; очистка переменных

sub_30420:      call    sub_31522       ; очистка переменных стрельбы
                clr     @#BossFlag
                return
; End of function sub_30420

; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR AddEnemys

jmp_30432:      call    sub_31502
                tst     (R1)            ; босс уже добавлен?
                beq     11$             ; нет - надо добавить
                ; да - просто добавляем врагов
                mov     #20, @#RNDOffVal+2 ; делаем какое-то бессмысленное действие

loc_30450:      jmp     @#AddNewEnemy   ; Функция добавления нового врага
; END OF FUNCTION CHUNK FOR CheckBossHit
; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR AddEnemys
                ; добавляем Босса
11$:            mov     #TopScreen-10000+54, (R1)+
                mov     #100, (R1)+
                clr     (R1)+
                mov     #MoveBossProc, (R1)
                inc     @#BossFlag
                br      loc_30766
; END OF FUNCTION CHUNK FOR AddEnemys

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


CheckBossHit:      call    @#CheckEnemyHit ; Проверка попаданий во врагов
                                        ; Начисление счёта и запуск анимации взрыва врага
                tst     @#BossFlag      ; если на экране Босс
                bne     1$              ; то пойдём проверим ещё попадания в Босса
                return
; ───────────────────────────────────────────────────────────────────────────

1$:             clr     (SP)+
                br      loc_31016
; ───────────────────────────────────────────────────────────────────────────
BossHealth:     .word 0                 ; здоровье Босса
; ───────────────────────────────────────────────────────────────────────────

NextAddNewEnemy$:
                tst     @#BossFlag      ; на экране Босс?
                bne     1$              ; да - переход
                mov     #GetRndAddrAcc, R1 ;нет - далее как обычно
                jmp     @#NextAddNewEnemy1$
; ───────────────────────────────────────────────────────────────────────────
                ; на экране Босс
1$:             mov     @#177710, R0    ; получим случайное число
                sub     @#Score, R0
                bic     #177720, R0
                cmp     R0, #2          ; меньше 3
                blos    2$              ; ОК
                return                  ; иначе - врага не добавляем
; ───────────────────────────────────────────────────────────────────────────

2$:             asl     R0              ; тут добавляем врагов
                jmp     @OnBossEnemyTbl(R0) ; которые босс выплёвывает
; ───────────────────────────────────────────────────────────────────────────
OnBossEnemyTbl: .word OnBossEnemy1
                .word OnBossEnemy2
                .word OnBossEnemy3
; ───────────────────────────────────────────────────────────────────────────
                ; первый тип врага при Боссе
OnBossEnemy1:   call    @#SearchFreeItem ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
                mov     @#BossAddr, R0
                add     #2574, R0
                call    @#sub_24370     ; Проверка, пусто ли под объектом
                                        ; Вход: R0 - адрес экрана
                                        ; Если не пусто, то выход на уровень выше
                jmp     @#jmp_10664
; ───────────────────────────────────────────────────────────────────────────

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
; ───────────────────────────────────────────────────────────────────────────

loc_30666:      xor     R2, (R0)
                add     R5, R0
                xor     R2, (R0)+
                sub     R5, R0
                br      loc_30410
; ───────────────────────────────────────────────────────────────────────────

loc_30700:      mov     #TopScreen+54, R3
                mov     #6, R4

4$:             clr     (R3)+
                sob     R4, 4$
                return
; ───────────────────────────────────────────────────────────────────────────
                ; второй тип врага при Боссе
OnBossEnemy2:   call    @#SearchFreeItem ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
                mov     @#BossAddr, R0
                add     #2074, R0
                call    @#sub_24370     ; Проверка, пусто ли под объектом
                                        ; Вход: R0 - адрес экрана
                                        ; Если не пусто, то выход на уровень выше
                jmp     @#jmp_10404
; ───────────────────────────────────────────────────────────────────────────
                ; третий тип врага при Боссе
OnBossEnemy3:   call    @#SearchFreeItem ; Поиск свободного элемента в массиве EnemyBuffer
                                        ; Выход: R1 - адрес пустого элемента
                                        ; Если элемент не найден, то выход на уровень выше.
                mov     @#BossAddr, R0
                add     #2274, R0
                call    @#sub_24370     ; Проверка, пусто ли под объектом
                                        ; Вход: R0 - адрес экрана
                                        ; Если не пусто, то выход на уровень выше
                jmp     @#jmp_10742
; ───────────────────────────────────────────────────────────────────────────

loc_30766:      mov     104132, @sub_16436 ; mov #10., @#Secret4$+2 - это защита от изменения кол-ва жизней
                mov     @#StageNum, R0  ; Номер текущего этапа
                inc     R0
                asl     R0
                asl     R0
                asl     R0
                call    sub_31546
                br      loc_30450
; ───────────────────────────────────────────────────────────────────────────

loc_31016:      mov     @#BossAddr, R2
                mov     #ShootsTbl, R1

2$:             mov     (R1)+, R5
                bne     4$

3$:             cmp     R1, #ShootsTblEnd
                bne     2$
                jmp     @#jmp_26252
; ───────────────────────────────────────────────────────────────────────────

4$:             cmp     R5, R2
                blo     3$
                mov     R5, R3
                mov     R2, R0
                add     #6000, R0
                cmp     R3, R0
                bhi     3$
                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$
                bis     #100, @102066
                br      8$
; ───────────────────────────────────────────────────────────────────────────

7$:             bic     #100, @100250

8$:             mov     #25, R4
                sob     R4, .
                sob     R3, 6$
                sob     R2, 5$
                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     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     #MoveBlowEnemyProc, 6(R1) ; Функция анимации взрыва врага
                call    sub_31454
                mov     R0, (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     #MoveGribBlowProc, 6(R1)
                mov     R0, (R1)
                clr     2(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$
                br      loc_31466
; End of function CheckBossHit

; ───────────────────────────────────────────────────────────────────────────
word_31432:     .word 512
                .word 2376
                .word 4602
                .word 2104
                .word -576
                .word 0
                .word 1000
                .word 3210
                .word 0

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


sub_31454:      clr     2(R1)
                clr     4(R1)
                return
; End of function sub_31454

; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR CheckBossHit

loc_31466:      mov     #66, @#StageDurationCnt2
                inc     @#Temp2

Ret_16$:        return
; END OF FUNCTION CHUNK FOR CheckBossHit

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


sub_31502:      mov     #BossAddr, R1
                tst     @#Temp2         ; босса добавлять надо?
                beq     Ret_16$         ; да
                clr     (SP)+           ; нет - идём к новому этапу
                jmp     @#NewStage
; End of function sub_31502


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

; очистка переменных стрельбы

sub_31522:      clr     @#NumShoots     ; текущее количество выстрелов
                clr     @#Temp2
                return
; End of function sub_31522


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


BlowFlightAnim: mov     #134, @#StageDurationCnt2
                jmp     @#NextBlowFlightAnim$
; End of function BlowFlightAnim


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


sub_31546:      add     #23, R0
                mov     R0, @#BossHealth

Ret_5$:         return
; End of function sub_31546


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

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

UseBobm:        clr     BombOnBossFlag  ; очистим флаг
                cmp     #MoveBossProc, @#BossMoveProc ; на экране БОСС есть?
                beq     2$              ; да

ub_1$:          jmp     @#BlowBombFunc  ; идём взрывать бомбу
; ───────────────────────────────────────────────────────────────────────────

2$:             inc     (PC)+           ; установим флаг
BombOnBossFlag: .word 0

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


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

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

BlowBoss:       clr     @#NumShoots     ; текущее количество выстрелов
                tst     BombOnBossFlag  ; босс на экране есть?
                beq     Ret_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     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

; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR PutNewBitTerrain

jmp_31746:      add     #100, R0        ; переходим к следующей строке экрана
                cmp     R0, #40000      ; всю высоту обработали?
                bhis    8$              ; да
                jmp     @#jmp_2172      ; нет - продолжаем в цикле по высоте
; ───────────────────────────────────────────────────────────────────────────

8$:             jmp     @#jmp_2220
; END OF FUNCTION CHUNK FOR PutNewBitTerrain

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

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

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

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

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

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

4$:             jmp     @word_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 ███████████████████████████████████████

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

RorBuffer:      ror     -(R0)
                ror     -(R0)
                ror     -(R0)
                ror     -(R0)
                ror     -(R0)
                ror     -(R0)
                ror     -(R0)
                ror     -(R0)
                sob     R1, RorBuffer
                return
; End of function RorBuffer


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


sub_32144:      call    @#DrawTerrain   ; подготовка в буфере и отображение на экране поверхности земли
                jmp     @#CheckPressFire ; Выход: R5 - флаг: !0 - было нажато "FIRE", 0 - всё остальное
; End of function sub_32144

; ───────────────────────────────────────────────────────────────────────────
; спрайт размером 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

; ███████████████ 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 ███████████████████████████████████████

; проверка целостности

sub_32476:      sub     (R1)+, R0
                cmp     R1, #<SprCurve5+73>
                blos    sub_32476
                return
; End of function sub_32476


; ███████████████ 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   ; Движение динамических объектов в заставке
; ───────────────────────────────────────────────────────────────────────────

jmp_32534:      call    sub_17430
                jmp     DrawTerrain     ; подготовка в буфере и отображение на экране поверхности земли
; ───────────────────────────────────────────────────────────────────────────

1$:             bic     100444, @104764 ; bic #1000, @#177664
                call    Cls1
                jmp     ShowReclama
; End of function CountToReclama

; ───────────────────────────────────────────────────────────────────────────
; шрифт в виде спрайта для рекламы
; размеры 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
                .byte  377 ; Ъ 031777 HL1
                .byte   63 ; 3
                .byte   77 ; ? 031477 HG9
                .byte   63 ; 3

; ███████████████ 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    #42, 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
                bcs     8$
                clc
                ror     (R0)
                clc
                br      9$
; ───────────────────────────────────────────────────────────────────────────

8$:             sec
                ror     (R0)
                sec

9$:             ror     (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 ███████████████████████████████████████


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     100262, @105024 ; 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

; ───────────────────────────────────────────────────────────────────────────
; таблица для вывода строк рекламы
; первое слово - адрес экрана, 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 "ТО НЕМЕДЛЕННО  ОБРАЩАЙТЕСЬ В"
aFirmuSnek_DlqN:.asciz /ФИРМУ  "СНЕК". ДЛЯ  НЕЕ  НЕТ/
                .asciz /НЕВОЗМОЖНОГО.  ФИРМА  "СНЕК"/
                .asciz "СТАНЕТ ВАШИМ ЛУЧШИМ ДРУГОМ В"
                .asciz "МИРЕ БИЗНЕСА И РАЗВЛЕЧЕНИЙ !"
                .asciz "142407  НОГИНСК 7"
                .asciz /А.Я 53  ФИРМА "СНЕК"/
                .even
SprBall:        .word ^B0000001010000000
                .word ^B0000101000100000
                .word ^B0010101010001000
                .word ^B0010101010101000
                .word ^B0010101010101000
                .word ^B0000101010100000
                .word ^B0000001010000000

; ███████████████ 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

Ret_17$:        return
; End of function DrawBall


; ███████████████ 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     Ret_17$         ; не настал
                mov     @#177710, R1
                bic     #177750, R1     ; получим случайное число (неправильно)
                asl     R1              ; * на 8
                asl     R1
                asl     R1
                add     #EnemyBuffer, R1 ; получим индекс в массиве врагов (неправильно, можем сильно за границу массива выйти)
                cmp     #MoveEnemyProc2, 6(R1) ; Вход: R1 - адрес элемента массива в EnemyBuffer
                                        ;       R4 - параметр 1 (мл байт - номер трапа, ст.байт - битовая маска)
                                        ;       R0 - адрес экрана
                                        ;       R2 - параметр 2 (адрес таблицы)
                bne     Ret_17$         ; если там не вот такого типа враг, то выходим
                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
                return
; End of function sub_34406

; ───────────────────────────────────────────────────────────────────────────
; дисперсия шаров
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
; ───────────────────────────────────────────────────────────────────────────

MoveEnemyBall:  mov     (R1), R0
                add     2(R1), R0
                call    sub_35134
                bne     2$
                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$
; ───────────────────────────────────────────────────────────────────────────
; START OF FUNCTION CHUNK FOR AddEnemys

jmp_34660:      cmp     @#StageNum, #3  ; если номер текущего этапа больше 2
                bhis    3$
                jmp     @#NewStage      ; если меньше трёх - то просто к новому этапу
; ───────────────────────────────────────────────────────────────────────────

3$:             jmp     @#jmp_30432     ; то будем делать дополнительные проверка
; END OF FUNCTION CHUNK FOR AddEnemys

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

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

InitGamePanel1: 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$

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


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

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

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

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

; ───────────────────────────────────────────────────────────────────────────
CheatBuf:       .word 15412
                .word 41400
                .word 20113

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


sub_35134:      mov     R0, R2
                bic     #177700, R2
                cmp     #76, R2
                return
; End of function sub_35134


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


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

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

1$:             asl     R2              ; R2 <<= 6
                sob     R3, 1$
                add     #20, R3
                add     R2, 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     #104516, 0CmdPriseSet2$ ; и просто нарисуем на экране текущий вид приза
                add     @#PriseNum, 0CmdPriseSet2$ ; номер пойманного приза

0CmdPriseSet2$: trap    116

Ret_19$:        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     Ret_19$
                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)
; End of function CheckCheat


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

; На входе R3 = 177716

CheatSub:       clr     @#KeyTab+6
                mov     #10, R1

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

                bic     #100, (R3)
                mov     R1, R0
                sob     R0, .

                inc     R1
                cmp     R1, #100
                blos    1$
                bic     113522, @102610 ; bic #1000, @#177664
                mov     #40, @#KeyFire$
                call    @#Cls1
                mov     #60016, @#AS    ; Адрес символа
                mov     #strPressOptionKey, R4 ; "PRESS OPTION KEY..."
                clr     @#FON           ; Фон экрана
                call    @#DrawText      ; Вывод текста
                                        ; Вход: R4 - адрес текста
                br      NextCheat$
; ───────────────────────────────────────────────────────────────────────────
strPressOptionKey:.asciz "PRESS OPTION KEY..."
                .even
                .word 0
; ───────────────────────────────────────────────────────────────────────────

NextCheat$:     call    @#InitialDrawStars ; Начальное отображение звёзд по таблице на экране
                bis     115260, @104764 ; bis #1000, @#177664

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

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

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

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

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

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

7$:             halt
; End of function CheatSub

; ───────────────────────────────────────────────────────────────────────────
aSsv0:          .ascii "SSV0"

.Script "crypt"
        mov     #CryptBgn$, R1
        mov     #Decoder$, R2
1$:     add     R1, (R1)
        swab    (R1)
        sub     R1, (R1)+
        cmp     R1, R2
        blo     1$
.ends

; ───────────────────────────────────────────────────────────────────────────
; декодирщик тела игры и запускатель
Decoder$:       mov     103344, R1      ; R1 = 1002
                mov     R1, R3          ; R3 = 1002
                mov     115152, R2      ; R2 = 36000

1$:             add     R1, (R1)
                swab    (R1)
                sub     R1, (R1)+
                cmp     R1, R2
                blo     1$              ; декодируем игру
                clr     R5              ; считаем КС
                mov     #16407, R2

2$:             sub     (R3)+, R5
                sob     R2, 2$          ; R3 = 36020, R5 = 61230
                sub     #32324, R5      ; R5 = 26704
                rts     R5

; ───────────────────────────────────────────────────────────────────────────
loc_37044:      clr     R1
                mov     #1000, R2       ; переносим тело по своему адресу

1$:             mov     (R2)+, (R1)+
                cmp     R2, #37044
                bcs     1$
                mov     #740, SP
                jmp     @#36000

                .word    0



                .END
