; Чуточку оптимизированный и причёсанный вариант.
; Чтобы было удобнее в коде ориентироваться.
; игра обессмерчена и обнеуязвимлена, если нужна честная игра,
; найдите строки, содержащие ###, и закомментируйте/раскомментируйте нужное.


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

; ═══════════════════════════════════════════════════════════════════════════

.la 0

GMCBGN:         .word 14747
                .word 0
Vector4:        .word TT4$1$
                .word 340

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

; Вычисление ширины остатка видимого спрайта при
; захождении за левую границу экрана
; а при движении вправо - коррекция адреса экрана
; Вход: R5 - смещение на экране
;       R0 - адрес спрайта
;       R1 - адрес экрана
; Выход: R2 - видимый остаток
;       C=0 - R2 валидно, С=1 - объект полностью за границей экрана

sub_10:         tst     R5              ; это смещение относительно правого края экрана
                bgt     4NoOk$          ; >0 - вышли за границы правого края экрана
                movb    (R0)+, R2       ; ширина спрайта в байтах
                mov     R2, R4          ; ширина
                add     R5, R4          ; прибавим смещение
                beq     3ok$            ; объект целиком помещается на экране
                bmi     2$
; > 0 - спрайт заехал за левый край экрана
                sub     R4, R2          ; узнаем сколько осталось
1$:             movb    (R0)+, R5       ; высота строки
                add     R5, R0          ; пропустим строку
                sob     R4, 1$          ; и так сколько нужно строк
                br      3ok$
; ───────────────────────────────────────────────────────────────────────────
; < 0 - спрайт или заехал за правый край экрана
; или целиком на экране
2$:             cmp     R4, #-74        ; если меньше -74
                blt     4NoOk$          ; то вышли за границы левого края экрана
                sub     R4, R1          ; корректируем адрес экрана
                sub     R2, R4          ; проверим, сколько спрайта видно на экране
                add     #74, R4
                neg     R4
                ble     3ok$            ; целиком видно
                sub     R4, R2          ; не целиком, корректируем ширину

3ok$:           clc
                return
; ───────────────────────────────────────────────────────────────────────────

4NoOk$:         sec
NoSound:        return
; End of function sub_10


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

; анимация живности в заставке

LivingAnim:     cmp     (PC)+, @(PC)+   ; Анимация приседания выключена?
                        br . + <MBR4$BR-MorphBR4$>
                        .word MorphBR4$
                beq     1$              ; да
                clr     HorizMovOffset  ; нет - значит и горизонтального смещения нет

1$:             call    ParticlesAnim   ; Анимация разлёта осколков при попадании в объекты
                call    SporesDropDn    ; Анимация падающих спор, из которых вылупляется живность
                call    TurtlWormAnim   ; Анимация черепах и червяков
                call    SnakeAnim       ; Анимация змей
                call    FrogAnim        ; Анимация лягушек
                call    FlyFlyL2R       ; Анимация мухи летят слева направо
                ;jmp     FlyFlyR2L       ; Анимация мухи летят справа налево
; End of function LivingAnim


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

; Анимация мухи летят справа налево

FlyFlyR2L:      mov     #E.FlyR2L, R3   ; элемент в массиве параметров мухи
                tst     2(R3)           ; муха на экране?
                bne     4$              ; да
                ; нет, может надо показать?
                bit     RNDAccum, #200  ; элемент случайности
                beq     2$              ; не, не надо показывать
                cmp     #1500, Progress ; какой прогресс у нас?
                bgt     2$              ; рано ещё показывать
                ; можно показать
                mov     #SporesParamTbl, R4 ; ищем спору, из которой родится муха
                mov     #SporesParamTblSize, R5

1$:             cmp     #61400, (R4)    ; спора заданной границы экрана достигла?
                blt     3$              ; да - идём рисовать
                add     #SporesParamItemSize, R4
                sob     R5, 1$          ; осмотрим весь массив

2$:             return                  ; ничего подходящего нет
; ───────────────────────────────────────────────────────────────────────────

3$:             mov     (R4)+, R0       ; адрес экрана споры
                bic     #77, R0
                bis     #2, R0          ; теперь адрес экрана мухи
                mov     R0, FlyR2LScrAddr ; сохраним
                mov     #100, R0
                mov     #7, R2
                call    SporeDown       ; Удаление споры с экрана и звук
                                        ; И занесение случайного параметра шарика в блок параметров живности
                                        ; Вход: R4 - указатель на второе слово элемента SporesParamTbl
                                        ;       R3 - указатель на блок параметров живности
                                        ;       R2 - длительность звука
                                        ;       R0 - частота звука

4$:             mov     #E.FlyR2L, R3   ; снова указатель на элемент массива, т.к. функция SporeDown портит R3
                mov     (R3)+, R5       ; смещение от правого края экрана
                mov     FlyR2LScrAddr, R1 ; адрес экрана мухи
                tst     (R3)            ; какой спрайт показывать?
                bmi     5$              ; второй
                mov     #FlySprR2L1, R0 ; первый
                br      6$
; ───────────────────────────────────────────────────────────────────────────

5$:             mov     #FlySprR2L2, R0 ; второй

6$:             dec     -2(R3)          ; уменьшим смещение от правого края экрана
                call    sub_10          ; Вычисление ширины остатка видимого спрайта при
                                        ; захождении за левую границу экрана
                                        ; а при движении вправо - коррекция адреса экрана
                                        ; Вход: R5 - смещение на экране
                                        ;       R0 - адрес спрайта
                                        ;       R1 - адрес экрана
                                        ; Выход: R2 - видимый остаток
                                        ;       C=0 - R2 валидно, С=1 - объект полностью за границей экрана
                bcc     7$
                clr     R2              ; удаляем с экрана

7$:             mov     R2, R5
                mov     #FlyR2LScrAddr, R4
                mov     R3, -(SP)
                jmp     sub_1242
; End of function FlyFlyR2L


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

; Анимация мухи летят слева направо

FlyFlyL2R:      mov     #E.FlyL2R, R3   ; элемент в массиве параметров мухи
                tst     2(R3)           ; муха на экране?
                bne     4$              ; да
                ; нет, может надо показать?
                bit     RNDAccum, #100  ; элемент случайности
                beq     2$              ; не, не надо показывать
                cmp     #1400, Progress ; какой прогресс у нас?
                bgt     2$              ; рано ещё показывать
                ; можно показать
                mov     #SporesParamTbl, R4 ; ищем спору, из которой родится муха
                mov     #SporesParamTblSize, R5

1$:             cmp     #61400, (R4)    ; спора заданной границы экрана достигла?
                blt     3$              ; да - идём рисовать
                add     #SporesParamItemSize, R4
                sob     R5, 1$          ; осмотрим весь массив

2$:             return                  ; ничего подходящего нет
; ───────────────────────────────────────────────────────────────────────────

3$:             mov     (R4)+, R0       ; адрес экрана споры
                bic     #77, R0
                bis     #2, R0          ; теперь адрес экрана мухи
                mov     R0, FlyL2RScrAddr ; сохраним
                mov     #135, R0
                mov     #3, R2
                call    SporeDown       ; Удаление споры с экрана и звук
                                        ; И занесение случайного параметра шарика в блок параметров живности
                                        ; Вход: R4 - указатель на второе слово элемента SporesParamTbl
                                        ;       R3 - указатель на блок параметров живности
                                        ;       R2 - длительность звука
                                        ;       R0 - частота звука

4$:             mov     #E.FlyL2R, R3   ; снова указатель на элемент массива, т.к. функция SporeDown портит R3
                mov     (R3)+, R5       ; смещение от правого края экрана
                mov     FlyL2RScrAddr, R1 ; адрес экрана мухи
                tst     (R3)            ; какой спрайт показывать?
                bmi     5$              ; второй
                mov     #FlySprL2R1, R0 ; первый
                br      6$
; ───────────────────────────────────────────────────────────────────────────

5$:             mov     #FlySprL2R2, R0 ; второй

6$:             inc     -2(R3)          ; увеличиваем смещение от правого края экрана
                call    sub_10          ; Вычисление ширины остатка видимого спрайта при
                                        ; захождении за левую границу экрана
                                        ; а при движении вправо - коррекция адреса экрана
                                        ; Вход: R5 - смещение на экране
                                        ;       R0 - адрес спрайта
                                        ;       R1 - адрес экрана
                                        ; Выход: R2 - видимый остаток
                                        ;       C=0 - R2 валидно, С=1 - объект полностью за границей экрана
                bcc     7$
                clr     R2              ; удаляем с экрана

7$:             mov     R2, R5
                mov     R3, -(SP)
                mov     #FlyL2RScrAddr, R4
                jmp     sub_1242
; End of function FlyFlyL2R


; ███████████████ S U B R O U T I N E ███████████████████████████████████████
; Вход: R4 - адрес ячейки, где содержится адрес экрана мухи
;       R0 - адрес спрайта+1
;       R1 - новый адрес экрана
;       R2 - видимая ширина спрайта
;       R5 - флаг, 0 - не надо рисовать спрайт, !0 - надо
;       в стеке - указатель на элемент массива Enemys+2

sub_1242:       bit     #4, RNDAccum    ; элемент случайности
                bne     1$              ; ничо не надо делать
                cmp     #72400, (R4)    ; нижней границы достигла?
                blt     1$              ; да, пропускаем
                add     #200, (R4)      ; муха снижается
                br      1$

1$:             bit     #10, RNDAccum   ; элемент случайности
                bne     2$              ; ничо не надо делать
                cmp     #61400, (R4)    ; верхней границы достигла?
                bgt     2$              ; да, пропускаем
                sub     #200, (R4)      ; муха поднимается

2$:             call    MoveSprite      ; Стирание спрайта со старого места и рисование на новом
                                        ; Вход: R3 - адрес блока параметров+2
                                        ;       R0 - адрес спрайта+1
                                        ;       R1 - новый адрес экрана
                                        ;       R2 - видимая ширина спрайта
                                        ;       R5 - флаг, 0 - не надо рисовать спрайт, !0 - надо
                mov     (SP), R3        ; восстанавливаем указатель в массиве
                mov     -2(R3), R5      ; смещение от правого края экрана
                cmp     #40, R5         ; за пределы игрового поля вылетела? (вправо)
                blt     7$              ; да - удаляем
                cmp     #-140, R5       ; за пределы игрового поля вылетела? (влево)
                bgt     7$              ; да - удаляем
                ; нет, в пределах ещё
                mov     (R3), R1        ; текущий адрес экрана
                mov     R1, R2
                bic     #100000, R1     ; тут сбрасываем тип спрайта
                bic     #177700, R2     ; тут оставим горизонтальную позицию
                tst     BombBlowFlag    ; бомбу взорвали?
                beq     4$              ; нет
                ; да
                cmp     #2, R2          ; если муха в левой части экрана
                beq     8$              ; то ничего не делаем

3$:             mov     #FlyParticle, R0 ; частицы от взорвавшейся мухи
                sub     #1502, R1       ; адрес экрана
                tst     2(R3)           ; текущая видимая ширина спрайта
                beq     7$              ; 0 - значит муха за экраном, бомба не действует
                call    AddScore4       ; Увеличение счёта на 40
                                        ; Вход: R0 - адрес спрайта частицы
                                        ;       R1 - адрес экрана
                                        ;       R3 - адрес в Enemys+2
                clr     R5              ; стираем муху
                call    MoveSprite      ; Стирание спрайта со старого места и рисование на новом
                                        ; Вход: R3 - адрес блока параметров+2
                                        ;       R0 - адрес спрайта+1
                                        ;       R1 - новый адрес экрана
                                        ;       R2 - видимая ширина спрайта
                                        ;       R5 - флаг, 0 - не надо рисовать спрайт, !0 - надо
                mov     (SP), R3        ; восстанавливаем указатель в массиве
                br      7$
; ───────────────────────────────────────────────────────────────────────────

4$:             tst     CrouchShootFlag ; выстрел из лазерной пушки был
                bpl     8$              ; нет, ничего не делаем
                cmp     #70200, R1      ; муха на какой высоте
                bgt     8$              ; выше выстрела, ничего не делаем
                tst     MoveDir         ; куда смотрим?
                bmi     5$              ; вправо
                ; влево
                cmp     #40, R2         ; муха где?
                blt     8$              ; за спиной
                br      6$              ; спереди - попали
; ───────────────────────────────────────────────────────────────────────────
                ; вправо
5$:             cmp     #40, R2         ; муха где?
                bgt     8$              ; за спиной
                ; попали
6$:             bis     #100000, CurBlowSpr ; флаг попадания чтоль?
                br      3$              ; идём обработаем попадание в муху
; ───────────────────────────────────────────────────────────────────────────

7$:             clr     (R3)            ; всё, мухи на экране нет
8$:             tst     (SP)+
                return
; End of function sub_1242


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

; Анимация змей

SnakeAnim:      mov     #E.Snakes, R3   ; буфер параметров
                mov     #2, -(SP)       ; количество элементов

1$:             mov     R3, -(SP)
                add     #2, (SP)        ; указатель на адрес в стек
                tst     2(R3)           ; адрес экрана есть?
                bne     4$              ; да, объект существует, продолжаем анимацию
                ; нет - нужно создавать
                cmp     #1000, Progress ; каков прогресс, докуда дошли?
                bgt     9$              ; рано ещё, не создавать
                tstb    @#75575         ; если на экране в этом месте пусто
                beq     9$              ; то не создавать
                mov     #SporesParamTbl, R4 ; просмотрим таблицу
                mov     #SporesParamTblSize, R5 ; число элементов

2$:             cmp     #74000, (R4)+   ; спора достигла земли?
                blt     3$              ; да - идём создавать
                tst     (R4)+           ; нет, перейдём к следующей споре
                sob     R5, 2$          ; и так всю таблицу
                br      9$              ; к следующему элементу змеи
; ───────────────────────────────────────────────────────────────────────────

3$:             mov     #5, R2          ; звук появления змеи
                mov     #100, R0
                call    SporeDown       ; Удаление споры с экрана и звук
                                        ; И занесение случайного параметра шарика в блок параметров живности
                                        ; Вход: R4 - указатель на второе слово элемента SporesParamTbl
                                        ;       R3 - указатель на блок параметров живности
                                        ;       R2 - длительность звука
                                        ;       R0 - частота звука

4$:             mov     (SP), R3        ; указатель на адрес экрана
                mov     -2(R3), R5      ; смещение от правого края экрана
                mov     #73702, R1      ; начальный адрес экрана
                mov     (R3), R2        ; объект на экране?
                beq     5$              ; нет
                bic     #177700, R2     ; да, получим горизонтальную позицию
                cmp     #2, R2          ; у левого края экрана?
                beq     5$              ; да
                tst     74003(R2)       ; внизу вода?
                bne     5$              ; нет
                sub     #1400, R1       ; да, настолько вверх
                tst     (R3)            ; какой спрайт показываем?
                bpl     5$              ; первый
                add     #500, R1        ; второй, тогда вот настолько вниз

5$:             tst     (R3)            ; какой спрайт показываем?
                bmi     6$              ; второй
                mov     #SnakeSpr1, R0  ; спрайт 1
                sub     #2, -2(R3)      ; ещё вычитаем 2 от смещения, это движение слева направо
                br      7$
; ───────────────────────────────────────────────────────────────────────────

6$:             mov     #SnakeSpr2, R0  ; спрайт 2
                sub     #500, R1

7$:             call    sub_10          ; Вычисление ширины остатка видимого спрайта при
                                        ; захождении за левую границу экрана
                                        ; а при движении вправо - коррекция адреса экрана
                                        ; Вход: R5 - смещение на экране
                                        ;       R0 - адрес спрайта
                                        ;       R1 - адрес экрана
                                        ; Выход: R2 - видимый остаток
                                        ;       C=0 - R2 валидно, С=1 - объект полностью за границей экрана
                bcc     8$
                clr     R2

8$:             mov     R2, R5
                call    MoveSprite      ; Стирание спрайта со старого места и рисование на новом
                                        ; Вход: R3 - адрес блока параметров+2
                                        ;       R0 - адрес спрайта+1
                                        ;       R1 - новый адрес экрана
                                        ;       R2 - видимая ширина спрайта
                                        ;       R5 - флаг, 0 - не надо рисовать спрайт, !0 - надо
                mov     (SP), R3
                call    sub_3072        ; Проверка на выход за экран и убийство бомбой или выстрелом
                                        ; Вход: R3 - указатель на элемент живности +2
                                        ; Выход: R3 - указатель на элемент живности

9$:             tst     (SP)+           ; убираем не нужный указатель
                dec     (SP)            ; элементы закончились?
                beq     10$             ; да, выход
                add     #EnemysItemSize, R3 ; нет - переходим к следующему
                br      1$
; ───────────────────────────────────────────────────────────────────────────

10$:            tst     (SP)+
                return
; End of function SnakeAnim


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

; Проверка на выход за экран и убийство бомбой или выстрелом
; Вход: R3 - указатель на элемент живности +2
; Выход: R3 - указатель на элемент живности

sub_3072:       mov     -2(R3), R5      ; смотрим смещение
                cmp     #40, R5
                blt     7$              ; за правой границей
                cmp     #-140, R5
                bgt     7$              ; за левой границей
                mov     (R3), R1        ; адрес экрана
                mov     R1, R2
                bic     #100000, R1     ; сбрасываем бит 15
                beq     8$              ; 0 - нету на экране
                bic     #177700, R2     ; получим горизонтальную позицию
                tst     BombBlowFlag    ; бомба взорвана?
                beq     4$              ; нет
                cmp     #2, R2          ; да, а живность у левого края экрана?
                beq     8$              ; да - не считается

1$:             cmp     R3, #E.Frogs    ; это что?
                blt     2$              ; змея
                ; лягушка
                mov     #FrogParticleSpr, R0
                br      3$
; ───────────────────────────────────────────────────────────────────────────

2$:             mov     #SnakParticleSpr, R0

3$:             sub     #1276, R1       ; адрес, откуда будут разлетаться частицы
                tst     2(R3)           ; спрайт на экране видим?
                beq     7$              ; нет - не считается
                call    AddScore2       ; Увеличение счёта на 20
                                        ; Вход: R0 - адрес спрайта частицы
                                        ;       R1 - адрес экрана
                                        ;       R3 - адрес в Enemys+2
                clr     R5              ; рисовать не надо
                call    MoveSprite      ; Стирание спрайта со старого места и рисование на новом
                                        ; Вход: R3 - адрес блока параметров+2
                                        ;       R0 - адрес спрайта+1
                                        ;       R1 - новый адрес экрана
                                        ;       R2 - видимая ширина спрайта
                                        ;       R5 - флаг, 0 - не надо рисовать спрайт, !0 - надо
                mov     2(SP), R3       ; восстановим указатель
                br      7$              ; пойдём удалим
; ───────────────────────────────────────────────────────────────────────────

4$:             tst     CrouchShootFlag ; Флаг приседания, >0 - просто присесть, <0 - ещё и стрелять
                bpl     8$              ; просто присели - не считается
                                        ; стрельнули
                tst     MoveDir         ; Флаг направления движения
                                        ; >0 - идём влево
                                        ; <0 - идём вправо
                bmi     5$
                cmp     #40, R2         ; если живность за спиной
                blt     8$              ; не считается
                br      6$
; ───────────────────────────────────────────────────────────────────────────

5$:             cmp     #40, R2         ; если живность за спиной
                bgt     8$              ; не считается

6$:             bis     #100000, CurBlowSpr ; попали в живность
                br      1$
; ───────────────────────────────────────────────────────────────────────────

7$:             clr     (R3)            ; удаляем с экрана
8$:             tst     -(R3)
                return
; End of function sub_3072


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

; Анимация лягушек

FrogAnim:       mov     #E.Frogs, R3    ; буфер параметров
                mov     #2, -(SP)       ; количество элементов

1$:             mov     R3, -(SP)
                add     #2, (SP)        ; указатель на адрес в стек
                tst     2(R3)           ; адрес экрана есть?
                bne     4$              ; да, объект существует, продолжаем анимацию
                                        ; нет - нужно создавать
                cmp     #1100, Progress ; каков прогресс, докуда дошли?
                bgt     9$              ; рано ещё, не создавать
                tstb    @#75575         ; если на экране в этом месте пусто
                beq     9$              ; то не создавать
                mov     #SporesParamTbl, R4 ; просмотрим таблицу
                mov     #SporesParamTblSize, R5 ; число элементов

2$:             cmp     #74000, (R4)+   ; спора достигла земли?
                blt     3$              ; да - идём создавать
                sob     R5, 2$          ; и так всю таблицу
                br      9$              ; к следующему элементу лягушки
; ───────────────────────────────────────────────────────────────────────────

3$:             mov     #20, R2         ; звук появления лягушки
                mov     #34, R0
                call    SporeDown       ; Удаление споры с экрана и звук
                                        ; И занесение случайного параметра шарика в блок параметров живности
                                        ; Вход: R4 - указатель на второе слово элемента SporesParamTbl
                                        ;       R3 - указатель на блок параметров живности
                                        ;       R2 - длительность звука
                                        ;       R0 - частота звука

4$:             mov     (SP), R3        ; указатель на адрес экрана
                mov     -2(R3), R5      ; смещение от правого края экрана
                mov     #73702, R1      ; начальный адрес экрана
                mov     (R3), R2        ; объект на экране?
                beq     5$              ; нет
                bic     #177700, R2     ; да, получим горизонтальную позицию
                cmp     #2, R2          ; у левого края экрана?
                beq     5$              ; да
                tst     74002(R2)       ; под ногами вода?
                bne     5$              ; нет
                sub     #1400, R1       ; да - настолько вверх
                tst     (R3)            ; какой спрайт?
                bmi     5$              ; второй
                add     #400, R1        ; первый - иначе вот настолько вниз

5$:             tst     (R3)            ; какой спрайт?
                bmi     6$              ; второй
                mov     #FrogSpr1, R0   ; первый - спрайт 1
                sub     #400, R1
                br      7$
; ───────────────────────────────────────────────────────────────────────────

6$:             mov     #FrogSpr2, R0   ; спрайт 2

7$:             inc     -2(R3)          ; корректируем смещение на экране
                call    sub_10          ; Вычисление ширины остатка видимого спрайта при
                                        ; захождении за левую границу экрана
                                        ; а при движении вправо - коррекция адреса экрана
                                        ; Вход: R5 - смещение на экране
                                        ;       R0 - адрес спрайта
                                        ;       R1 - адрес экрана
                                        ; Выход: R2 - видимый остаток
                                        ;       C=0 - R2 валидно, С=1 - объект полностью за границей экрана
                bcc     8$
                clr     R2

8$:             mov     R2, R5
                call    MoveSprite      ; Стирание спрайта со старого места и рисование на новом
                                        ; Вход: R3 - адрес блока параметров+2
                                        ;       R0 - адрес спрайта+1
                                        ;       R1 - новый адрес экрана
                                        ;       R2 - видимая ширина спрайта
                                        ;       R5 - флаг, 0 - не надо рисовать спрайт, !0 - надо
                mov     (SP), R3
                call    sub_3072        ; Проверка на выход за экран и убийство бомбой или выстрелом
                                        ; Вход: R3 - указатель на элемент живности +2
                                        ; Выход: R3 - указатель на элемент живности

9$:             tst     (SP)+           ; убираем не нужный указатель
                dec     (SP)            ; элементы закончились?
                beq     10$             ; да, выход
                add     #EnemysItemSize, R3 ; нет - переходим к следующему
                br      1$
; ───────────────────────────────────────────────────────────────────────────

10$:            tst     (SP)+
                return
; End of function FrogAnim


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

; Анимация черепах и червяков

TurtlWormAnim:  mov     #E.Worms, R3    ; блок параметров червяков
                tst     2(R3)           ; адрес экрана есть?
                bne     3$              ; да - продолжаем анимацию
                cmp     #400, Progress  ; каков прогресс, докуда дошли?
                bgt     20$             ; рано показывать ещё
                tstb    @#75575         ; тама что?
                beq     20$             ; пусто, не показывать
                mov     #SporesParamTbl, R4
                mov     #SporesParamTblSize, R5

1$:             cmp     #74000, (R4)+   ; спора нужной границы достигла?
                blt     2$              ; да, пора
                add     #2, R4          ; нет - переходим к следующей
                sob     R5, 1$          ; и так весь массив
                br      20$             ; ничего подходящего нет
; ───────────────────────────────────────────────────────────────────────────

2$:             mov     #10, R2
                mov     #50, R0
                call    SporeDown       ; Удаление споры с экрана и звук
                                        ; И занесение случайного параметра шарика в блок параметров живности
                                        ; Вход: R4 - указатель на второе слово элемента SporesParamTbl
                                        ;       R3 - указатель на блок параметров живности
                                        ;       R2 - длительность звука
                                        ;       R0 - частота звука

3$:             mov     #E.Worms, R3    ; блок параметров червяков
                mov     (R3)+, R5       ; смещение от правого края экрана
                mov     #73702, R1      ; червяк появится слева экрана
                tst     (R3)            ; какой спрайт отображать?
                bmi     4$              ; второй
                mov     #WormSpr1, R0   ; первый
                br      5$
; ───────────────────────────────────────────────────────────────────────────

4$:             mov     #wormSpr2, R0   ; второй
                dec     -2(R3)

5$:             call    sub_10          ; Вычисление ширины остатка видимого спрайта при
                                        ; захождении за левую границу экрана
                                        ; а при движении вправо - коррекция адреса экрана
                                        ; Вход: R5 - смещение на экране
                                        ;       R0 - адрес спрайта
                                        ;       R1 - адрес экрана
                                        ; Выход: R2 - видимый остаток
                                        ;       C=0 - R2 валидно, С=1 - объект полностью за границей экрана
                bcc     6$
                tstb    @#74075
                beq     12$
                tstb    @#74002
                beq     12$
                clr     R2

6$:             mov     R2, R5
                mov     R3, -(SP)
                call    MoveSprite      ; Стирание спрайта со старого места и рисование на новом
                                        ; Вход: R3 - адрес блока параметров+2
                                        ;       R0 - адрес спрайта+1
                                        ;       R1 - новый адрес экрана
                                        ;       R2 - видимая ширина спрайта
                                        ;       R5 - флаг, 0 - не надо рисовать спрайт, !0 - надо
                mov     (SP), R3
                mov     -2(R3), R5
                cmp     #40, R5
                blt     10$
                cmp     #-140, R5
                bgt     10$
                mov     (R3), R1
                bic     #100000, R1
                tst     BombBlowFlag
                bne     7$
                cmp     #73702, R1
                beq     11$
                tstb    102(R1)
                bne     11$

7$:             cmp     R3, #E.Turtles
                blt     8$
                mov     #TrtlParticleSpr, R0
                br      9$
; ───────────────────────────────────────────────────────────────────────────

8$:             mov     #WormParticleSpr, R0

9$:             sub     #476, R1
                tst     2(R3)
                beq     10$
                call    sub_6564        ; Увеличение счёта на 10, и вывод его на экран
                                        ; И добавление элемента в таблицу разлёта частиц
                                        ; Вход: R0 - адрес спрайта частицы
                                        ;       R1 - адрес экрана
                clr     R5
                call    MoveSprite      ; Стирание спрайта со старого места и рисование на новом
                                        ; Вход: R3 - адрес блока параметров+2
                                        ;       R0 - адрес спрайта+1
                                        ;       R1 - новый адрес экрана
                                        ;       R2 - видимая ширина спрайта
                                        ;       R5 - флаг, 0 - не надо рисовать спрайт, !0 - надо
                mov     (SP), R3
10$:            clr     (R3)
11$:            tst     (SP)+

12$:            tst     -(R3)
                cmp     #E.Turtles, R3
                bne     20$

13$:            return
; ───────────────────────────────────────────────────────────────────────────

20$:            mov     #E.Turtles, R3
                tst     2(R3)
                bne     23$
                cmp     #500, Progress
                bgt     13$
                tstb    @#75575
                beq     13$
                mov     #SporesParamTbl, R4
                mov     #3, R5

21$:            cmp     #74000, (R4)+
                blt     22$
                tst     (R4)+
                sob     R5, 21$
                br      13$
; ───────────────────────────────────────────────────────────────────────────

22$:            mov     #20, R2
                mov     #26, R0
                call    SporeDown       ; Удаление споры с экрана и звук
                                        ; И занесение случайного параметра шарика в блок параметров живности
                                        ; Вход: R4 - указатель на второе слово элемента SporesParamTbl
                                        ;       R3 - указатель на блок параметров живности
                                        ;       R2 - длительность звука
                                        ;       R0 - частота звука

23$:            mov     #E.Turtles, R3
                mov     (R3)+, R5
                mov     #73702, R1
                tst     (R3)
                bmi     24$
                mov     #TurtleSpr2, R0
                br      5$
; ───────────────────────────────────────────────────────────────────────────

24$:            mov     #TurtleSpr1, R0
                inc     -2(R3)
                br      5$
; End of function TurtlWormAnim


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

; Стирание спрайта со старого места и рисование на новом
; Вход: R3 - адрес блока параметров+2
;       R0 - адрес спрайта+1
;       R1 - новый адрес экрана
;       R2 - видимая ширина спрайта
;       R5 - флаг, 0 - не надо рисовать спрайт, !0 - надо

MoveSprite:     mov     R0, -(SP)
                mov     R2, -(SP)
                mov     R3, -(SP)
                mov     R1, -(SP)
                mov     (R3)+, R1       ; текущий адрес экрана
                bmi     1$              ; если <0
                bis     #100000, (SP)   ; если >0, то новый адрес должен быть <0

1$:             bic     #100000, R1     ; сбросим старший бит
                mov     (R3)+, R2       ; текущая ширина спрайта
                beq     5$              ; 0 - спрайт невидим
                mov     (R3)+, R0       ; текущий адрес спрайта

2$:             mov     R1, R4          ; адрес столбца
                movb    (R0)+, R3       ; высота текущего столбца

3$:             cmpb    (R0)+, (R4)     ; стираем столбец
                bne     4$
                clrb    (R4)

4$:             sub     #100, R4        ; снизу вверх
                sob     R3, 3$
                inc     R1              ; переходим к следующему столбцу
                sob     R2, 2$

5$:             mov     (SP)+, R1       ; восстанавливаем регистры
                mov     (SP)+, R3
                mov     (SP)+, R2
                mov     (SP)+, R0
                sub     HorizMovOffset, -2(R3) ; горизонтальное смещение: 1 - при движении влево
                                        ;                         -1 - при движении вправо
                                        ;                          0 - стоим на месте
                mov     R1, (R3)+       ; сохраняем новый адрес экрана
                mov     R2, (R3)+       ; новую видимую ширину
                mov     R0, (R3)+       ; новый адрес спрайта
                bic     #100000, R1
                tst     R5
                beq     10$

6$:             mov     R1, R4
                movb    (R0)+, R3

7$:             movb    (R0)+, R5
                beq     9$
                bitb    #252, (R4)
                beq     8$
                bitb    #125, (R4)
                beq     9$

8$:             movb    R5, (R4)

9$:             sub     #100, R4
                sob     R3, 7$
                inc     R1
                sob     R2, 6$
10$:            return
; End of function MoveSprite


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

; Удаление споры с экрана и звук
; И занесение случайного параметра шарика в блок параметров живности
; Вход: R4 - указатель на второе слово элемента SporesParamTbl
;       R3 - указатель на блок параметров живности
;       R2 - длительность звука
;       R0 - частота звука

SporeDown:      mov     (R4), R5        ; параметр шарика
                mov     -(R4), R1       ; адрес экрана шарика
                clr     (R4)            ; адрес в таблице стираем
                sub     #2, R5
                mov     R5, (R3)+       ; это смещение шарика на экране
                clr     (R3)+           ; адрес экрана
                clr     (R3)+           ; видимая ширина спрайта
                mov     R0, R3          ; частота звука
                mov     #SporeSpr, R0
                inc     R0              ; ширину пропустим
                movb    (R0)+, R4       ; высота в строках

1$:             cmpb    (R0)+, (R1)     ; если на экране яйцо
                bne     2$
                clrb    (R1)            ; то его стираем

2$:             add     #100, R1
                sob     R4, 1$
                jmp     @SoundSub       ; Вход: R2 - длительность звука БИП
                                        ;       R3 - частота звука
; End of function SporeDown

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

; Анимация падающих спор, из которых вылупляется живность

SporesDropDn:   mov     #SporesParamTbl, R3 ; начало массива
                mov     #SporesParamTblSize, R4 ; количество элементов

1$:             add     @#177662, RNDAccum ; делаем случайное число
                add     @#177714, RNDAccum
                mov     R4, -(SP)
                tst     (R3)            ; первое слово
                bne     4$              ; не 0 - что-то есть
                                        ; 0 - пусто
                tst     (PC)+           ; новую спору пора генерировать?
0NewSporeDelay$:.word 0
                bne     2$              ; нет ещё
                mov     #10., 0NewSporeDelay$ ; да - инициализируем счётчик
                mov     RNDAccum, R5    ; берём случайное число
                bis     #177600, R5     ; делаем из него отрицательное число -200..-1
                add     #40, R5         ; делаем число -140..37
                mov     #55502, R1      ; начальный адрес
                mov     R1, (R3)+       ; первое слово - адрес экрана
                mov     R5, (R3)        ; второе - смещение на экране
                mov     R1, R4          ; текущий адрес экрана, а спору рисовать
                call    SporeDropAnim   ; Вывод на экран падающего яйца, из которого вылупляется живность
                                        ; Вход: R4 - текущий адрес экрана
                                        ;       R1 - текущий адрес экрана,
                                        ;            или 0, если спору надо удалить
                                        ;       R3 - указатель на второе слово элемента массива SporesParamTbl
                br      3$
; ───────────────────────────────────────────────────────────────────────────

2$:             bit     (R3)+, (R3)+    ; переходим к следующему элементу массива

3$:             dec     0NewSporeDelay$ ; уменьшаем счётчик
                br      5$              ; идём обрабатывать цикл
; ───────────────────────────────────────────────────────────────────────────

4$:             mov     (R3)+, R1       ; берём адрес споры
                cmp     #73700, R1      ; до низа экрана долетели?
                blt     6$              ; да
                mov     R1, R4          ; нет, значит спору рисовать, а это текущий адрес экрана
                call    SporeDropAnim   ; Вывод на экран падающего яйца, из которого вылупляется живность
                                        ; Вход: R4 - текущий адрес экрана
                                        ;       R1 - текущий адрес экрана,
                                        ;            или 0, если спору надо удалить
                                        ;       R3 - указатель на второе слово элемента массива SporesParamTbl

5$:             mov     (SP)+, R4
                sob     R4, 1$          ; и так весь массив
                return
; ───────────────────────────────────────────────────────────────────────────

6$:             mov     R1, R4          ; до низа экрана долетели, это текущий адрес экрана
                clr     R1              ; спору не рисовать, и удалить из таблицы
                tst     (R3)+           ; когда в R1 0, указатель не сдвигается, и нужно двигать его самому тут
                call    SporeDropAnim   ; Вывод на экран падающего яйца, из которого вылупляется живность
                                        ; Вход: R4 - текущий адрес экрана
                                        ;       R1 - текущий адрес экрана,
                                        ;            или 0, если спору надо удалить
                                        ;       R3 - указатель на второе слово элемента массива SporesParamTbl
                br      5$              ; обработаем следующий элемент массива
; End of function SporesDropDn


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

; Вывод на экран падающего яйца, из которого вылупляется живность
; Вход: R4 - текущий адрес экрана
;       R1 - текущий адрес экрана,
;            или 0, если спору надо удалить
;       R3 - указатель на второе слово элемента массива SporesParamTbl

SporeDropAnim:  mov     R4, -(SP)       ; текущий адрес экрана сохраним
                bic     #77, R1         ; что делаем?
                beq     4$              ; удаляем спору
                add     #502, R1        ; продолжаем, это новый адрес
                sub     HorizMovOffset, (R3) ; корректируем смещение на экране при движении
                mov     (R3)+, R5       ; берём его
                mov     #SporeSpr, R0
                call    sub_10          ; Вычисление ширины остатка видимого спрайта при
                                        ; захождении за левую границу экрана
                                        ; а при движении вправо - коррекция адреса экрана
                                        ; Вход: R5 - смещение на экране
                                        ;       R0 - адрес спрайта
                                        ;       R1 - адрес экрана
                                        ; Выход: R2 - видимый остаток
                                        ;       C=0 - R2 валидно, С=1 - объект полностью за границей экрана
                bcs     4$              ; улетела за экран
                tst     R2              ; или не улетела, но ширина 0
                beq     4$              ; то тоже удаляем
                movb    (R0)+, R2       ; высота спрайта в строках
                mov     R1, R4          ; новый адрес экрана

1$:             bitb    #125252, (R1)   ; рисуем спрайт на новом месте
                beq     2$
                bitb    #52525, (R1)
                beq     3$

2$:             movb    (R0), (R1)

3$:             add     #100, R1
                inc     R0
                sob     R2, 1$
                mov     R4, R1          ; новый адрес экрана

4$:             mov     R1, -4(R3)      ; новый адрес экрана сохраним в таблице
                mov     #SporeSpr, R0   ; а со старого места удалим
                inc     R0              ; ширину пропустим
                mov     (SP)+, R1       ; старый адрес экрана
                movb    (R0)+, R2       ; высота спрайта

5$:             cmpb    (R0)+, (R1)
                bne     6$
                clrb    (R1)

6$:             add     #100, R1
                sob     R2, 5$
                return
; End of function SporeDropAnim


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

; Анимация разлёта осколков при попадании в объекты

ParticlesAnim:  mov     #ParticlesTbl, R5

1$:             mov     (R5)+, R0       ; первое слово - адрес спрайта
                cmp     #2400, (R5)+    ; второе слово равно 2400?
                beq     18$             ; да - пропускаем элемент
                tst     -(R5)           ; возвращаемся ко второму слову
                cmpb    (R5)+, (R5)     ; мл. байт второго слова равен ст. байту?
                bne     2$              ; нет
                incb    (R5)            ; да - увеличим ст.байт
                clrb    -1(R5)          ; обнулим мл.байт
                br      3$
; ───────────────────────────────────────────────────────────────────────────
; мл. байт второго слова неравен ст. байту

2$:             incb    -1(R5)          ; увеличим мл.байт

3$:             movb    (R5)+, R3       ; ст. байт
                asl     R3
                add     #ParticleOffset, R3 ; текущее смещение
                mov     #10, R2         ; количество осколков

4$:             mov     (R5), R1        ; адрес осколка
                beq     10$             ; 0 - нету
                mov     R2, -(SP)       ; стираем с текущего места
                movb    (R0), R2
                mov     #100, R4
                sub     R2, R4
                mov     R4, 0PtklPitch$
                mov     R2, 0PtklWidth$
                movb    1(R0), R4

5$:             mov     (PC)+, R2
0PtklWidth$:    .word 0

6$:             bitb    #252, (R1)
                beq     7$
                bitb    #125, (R1)
                beq     8$

7$:             clrb    (R1)

8$:             inc     R1
                sob     R2, 6$
                add     (PC)+, R1
0PtklPitch$:    .word 0

                sob     R4, 5$
                mov     (SP)+, R2
                mov     (R5), R1        ; вычисляем новый адрес
                add     HorizMovOffset, R1 ; горизонтальное смещение: 1 - при движении влево
                                        ;                         -1 - при движении вправо
                                        ;                          0 - стоим на месте
                add     (R3), R1
                mov     R1, (R5)        ; сохраняем
                cmp     #56300, R1      ; проверка на выход за границы экрана
                bpl     9$
                cmp     #74000, R1
                bmi     9$
                add     #4, R1
                bit     #70, R1
                bne     10$

9$:             clr     (R5)            ; вышел - удаляем из списка обработки

10$:            tst     (R3)+           ; циклическая ротация смещений
                cmp     #ParticleOffsetEnd, R3
                bne     11$
                mov     #ParticleOffset, R3

11$:            tst     (R5)+           ; переходим к следующему осколку
                sob     R2, 4$          ; обработаем все осколки
                sub     #ParticlesTblItemSize-3, R5
                cmpb    #5, (R5)+
                beq     18$
                mov     #10, R2         ; теперь выводим осколки

12$:            mov     (R5)+, R1
                beq     17$
                mov     R0, -(SP)
                movb    (R0)+, R3
                mov     #100, R4
                sub     R3, R4
                mov     R4, 0PtklPitch2$
                mov     R3, 0PtklWidth2$
                movb    (R0)+, R4

13$:            mov     (PC)+, R3
0PtklWidth2$:   .word 0

14$:            bitb    #252, (R1)
                beq     15$
                bitb    #125, (R1)
                beq     16$

15$:            movb    (R0), (R1)

16$:            inc     R0
                inc     R1
                sob     R3, 14$
                add     (PC)+, R1
0PtklPitch2$:   .word 0

                sob     R4, 13$
                mov     (SP)+, R0

17$:            sob     R2, 12$         ; обработаем все осколки
                mov     #6, R3          ; звук при разлёте
                movb    <3-ParticlesTblItemSize>(R5), R2
                inc     R2
                call    @SoundSub       ; Вход: R2 - длительность звука БИП
                                        ;       R3 - частота звука
                br      19$
; ───────────────────────────────────────────────────────────────────────────

18$:            add     #ParticlesTblItemSize-4, R5

19$:            cmp     #ParticlesTblEnd, R5
                bne     1$
                return
; End of function ParticlesAnim


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

; Увеличение счёта на 20
; Вход: R0 - адрес спрайта частицы
;       R1 - адрес экрана
;       R3 - адрес в Enemys+2

AddScore2:      mov     #2, R5
                br      1Add$
; End of function AddScore2


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

; Увеличение счёта на 40
; Вход: R0 - адрес спрайта частицы
;       R1 - адрес экрана
;       R3 - адрес в Enemys+2

AddScore4:      mov     #4, R5
1Add$:          mov     R3, -(SP)

2$:             mov     #Score+5, R3

3$:             incb    -(R3)
                cmpb    #10., (R3)
                bne     4$
                clrb    (R3)
                br      3$
; ───────────────────────────────────────────────────────────────────────────

4$:             sob     R5, 2$
                mov     (SP)+, R3
; End of function AddScore4


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

; Увеличение счёта на 10, и вывод его на экран
; И добавление элемента в таблицу разлёта частиц
; Вход: R0 - адрес спрайта частицы
;       R1 - адрес экрана

sub_6564:       call    AddScore1       ; Увеличение счёта на 10, и вывод его на экран

; Внесение в таблицу разлёта осколков нового элемента
; Вход: R0 - адрес спрайта частицы
;       R1 - адрес экрана
AddParticleItem:mov     R1, R5          ; корректируем адрес экрана,
                                        ; чтобы в пределах экрана был
                sub     #56300, R5
                bpl     1$
                sub     R5, R1

1$:             mov     R1, R5
                sub     #74000, R5
                bmi     2$
                sub     R5, R1

2$:             bic     #177700, R5
                cmp     #1, R5
                blt     3$
                bis     #2, R1

3$:             cmp     #75, R5
                bgt     4$
                bic     #3, R1

4$:             mov     #ParticlesTbl, R5 ; ищем в таблице разлёта частиц свободную позицию

5$:             cmp     #2400, 2(R5)
                beq     6$
                add     #ParticlesTblItemSize, R5
                cmp     #ParticlesTblEnd, R5
                bne     5$
                return                  ; не нашли
; ───────────────────────────────────────────────────────────────────────────

6$:             mov     R0, (R5)+       ; нашли, инициализируем
                clr     (R5)+
                mov     #8., R0         ; 8 частиц

7$:             mov     R1, (R5)+       ; их начальные адреса
                sob     R0, 7$
                return
; End of function sub_6564


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

; Увеличение счёта на 10, и вывод его на экран

AddScore1:      mov     #Score+5, R5
AddScore$:      incb    -(R5)
                cmpb    #10., (R5)
                bne     DrawScore       ; Вывод счёта
                clrb    (R5)
                br      AddScore$
; End of function AddScore1


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

; Вывод счёта

DrawScore:      mov     R0, -(SP)
                mov     R1, -(SP)
                mov     R3, -(SP)
                mov     #45720, R1
                mov     #Score, R2
                mov     #200, R4
                clr     R5              ; масштаба нет

1$:             tst     (R1)+
                movb    (R2)+, R0
                bmi     2$              ; конец, прекращаем цикл
                call    DrawChar        ; Вывод символа
                                        ; Вход: R0 - код символа
                                        ;       R1 - адрес экрана
                                        ;       R4 - маска цвета символа
                                        ;       R5 - масштаб, 0 - нет
                br      1$
; ───────────────────────────────────────────────────────────────────────────

2$:             clr     R0
                call    DrawChar        ; Вывод символа
                                        ; Вход: R0 - код символа
                                        ;       R1 - адрес экрана
                                        ;       R4 - маска цвета символа
                                        ;       R5 - масштаб, 0 - нет
                mov     (SP)+, R3
                mov     (SP)+, R1
                mov     (SP)+, R0
                return
; End of function DrawScore


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

; Прорисовка земной поверхности

DrawFloor:      mov     #GroundData, R0
                mov     #74002, R1
                mov     #16., R2

1$:             mov     #74, R3

2$:             movb    (R0), (R1)+
                sob     R3, 2$
                add     #4, R1
                inc     R0
                sob     R2, 1$
                return
; End of function DrawFloor


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

; Очистка экрана полосками

ClrScrEx2:      mov     #14, R5
                mov     #ClrScrEx2Data, R0

1$:             mov     R5, -(SP)

2$:             mov     #2, R4
                call    ClrScrEx2Helper
                sob     R5, 2$
                mov     (SP), R5

3$:             mov     #10, R4
                call    ClrScrEx2Helper
                sob     R5, 3$
                mov     (SP)+, R5
                asr     R5
                bne     1$
                mov     #56202, R1
                mov     #177, R2

4$:             mov     #36, R3

5$:             clr     (R1)+
                sob     R3, 5$
                cmp     (R1)+, (R1)+
                sob     R2, 4$
                return
; End of function ClrScrEx2


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


ClrScrEx2Helper2:
                cmp     (R0), #176003
                bne     1$
                mov     #ClrScrEx2Data, R0
                br      2$
; ───────────────────────────────────────────────────────────────────────────

1$:             tst     (R0)+
2$:             sob     R4, ClrScrEx2Helper2
                return
; End of function ClrScrEx2Helper2


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


ClrScrEx2Helper:
                call    ClrScrEx2Helper2
                mov     #56202, R1
                mov     #177, R2

1$:             mov     #36, R3

2$:             mov     (R0), (R1)+
                sob     R3, 2$
                mov     #1, R4
                call    ClrScrEx2Helper2
                cmp     (R1)+, (R1)+
                sob     R2, 1$
                return
; End of function ClrScrEx2Helper


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

; Очистка экрана рабочей области с эффектами

ClrScrEx:       clr     R5
                mov     #5, R4

1$:             mov     #75502, R1
                mov     #174, R2

2$:             mov     #36, R3

3$:             mov     (R1)+, R0
                bic     R1, R0
                bic     R5, R0
                mov     R0, 276(R1)
                sob     R3, 3$
                sub     #174, R1
                sob     R2, 2$
                add     #22345, R5
                sob     R4, 1$
                return
; End of function ClrScrEx


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

; Вывод спрайта
; Вход: R1 - адрес экрана снизу
;       R0 - адрес спрайта
;       R2 - ширина спрайта
;       R5 - сколько столбцов рисовать
;       R4 - блок параметров из 3-х слов

DrawGroundSprite:
                mov     R1, -(SP)       ; адрес экрана сохраним
                mov     (R4), R1        ; первое слово блока параметров
                mov     (SP), (R4)+     ; текущий адрес экрана в первое слово блока параметров
                mov     R0, -(SP)       ; адрес спрайта сохраним
                mov     (R4), R0        ; второе слово блока параметров
                mov     (SP), (R4)+     ; текущий адрес спрайта во второе слово блока параметров
                mov     R2, -(SP)       ; ширину сохраним
                mov     (R4), R2        ; третье слово блока параметров
                mov     (SP), (R4)+     ; текущую ширину в третье слово блока параметров
                tst     R2              ; какая прошлая ширина была?
                beq     3$              ; 0 - пропустим стирание

1$:             movb    (R0)+, R3       ; высота спрайта
                add     R3, R0          ; к следующему столбцу
                mov     R1, R4          ; адрес экрана

2$:             clrb    (R4)            ; очищаем столбец
                sub     #100, R4
                sob     R3, 2$
                inc     R1
                sob     R2, 1$

3$:             mov     (SP)+, R2       ; восстанавливаем начальные значения
                mov     (SP)+, R0
                mov     (SP)+, R1
                tst     R5              ; сколько надо рисовать?
                beq     6$              ; 0 - нисколько

4$:             movb    (R0)+, R3       ; высота текущего столбца
                mov     R1, R4          ; адрес экрана

5$:             movb    (R0)+, (R4)     ; выводим столбец
                sub     #100, R4
                sob     R3, 5$
                inc     R1              ; двигаем адрес дальше
                sob     R2, 4$          ; выводим всё

6$:             return
; End of function DrawGroundSprite


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

; Распаковка спрайта для движения влево
; Вход: R0 - адрес сжатого спрайта
;       R1 - адрес во временном буфере распаковки спрайта

UnpSprMv2Lt:    add     #4, R1          ; спрайт надо зеркально отобразить, поэтому начнём с правого столбца
                mov     #5, R5          ; количество столбцов
                clr     0GetNewByte$
                mov     #200., R2       ; размер конечного спрайта - 200. байтов

1$:             mov     #4, R3          ; пачками по 4 бита
                com     (PC)+           ; байт брать надо?
0GetNewByte$:    .word 0

                beq     2$              ; нет
                movb    (R0)+, R4       ; берём очередной байт данных

2$:             nop
                aslb    (R1)            ; формируем цветную двухбитную точку
                aslb    (R1)
                rorb    R4              ; из одного бита
                bcc     3$
                bisb    #3, (R1)

3$:             sob     R3, 2$          ; формируем распакованный байт
                dec     R5              ; строка кончилась?
                bne     4$              ; нет
                add     #12, R1         ; да, переходим к следующей строке
                mov     #5, R5

4$:             dec     R1              ; переходим к предыдущему столбцу
                sob     R2, 1$          ; продолжаем цикл
                return
; End of function UnpSprMv2Lt


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

; Распаковка спрайта для движения вправо
; Вход: R0 - адрес сжатого спрайта
;       R1 - адрес во временном буфере распаковки спрайта

UnpSprMv2Rt:    mov     #100., R2

1$:             movb    (R0)+, R3       ; берём очередной байт
                mov     #10, R4         ; в нём 8 бит
                nop

2$:             asl     (R1)            ; и расширяем байт в слово
                asl     (R1)
                rolb    R3
                bcc     3$
                bis     #3, (R1)

3$:             sob     R4, 2$
                add     #2, R1          ; к следующему слову
                sob     R2, 1$          ; и так весь спрайт
                mov     #3434, R3       ; задержка, чтобы компенсировать разницу во времени
                                        ; между левым и правым алгоритмами.
                sob     R3, .
                return
; End of function UnpSprMv2Rt



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

; расширение спрайтов прыжка в буфер для направления вправо
; Вход: R0 - указатель на текущий сжатый спрайт в массиве спрайтов
;       R1 - адрес буфера

UnpackJumpSprRt:movb    (R0)+, R4
                movb    (R0)+, R3
                movb    R4, (R1)+
                movb    R3, (R1)+
                mov     R4, R2
                add     R2, R2
                ror     R3
                ror     R3
                bcs     1$
                add     R2, R2
                br      2$
; ───────────────────────────────────────────────────────────────────────────

1$:             add     R4, R2

2$:             movb    (R0)+, R3
                mov     #10, R4

3$:             asl     (R1)
                asl     (R1)
                rolb    R3
                bcc     4$
                bis     #3, (R1)

4$:             sob     R4, 3$
                add     #2, R1
                sob     R2, 2$
                return
; End of function UnpackJumpSprRt


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

; расширение спрайтов прыжка в буфер для направления влево
; Вход: R0 - указатель на текущий сжатый спрайт в массиве спрайтов
;       R1 - адрес буфера

UnpackJumpSprLt:movb    (R0)+, R2
                movb    (R0)+, R3
                movb    R2, (R1)
                movb    R3, 1(R1)
                add     R3, R1
                mov     R3, R4
                asl     R3
                asr     R4
                mov     R3, 0Pitch$
                mov     R4, 0Width$

1$:             mov     (PC)+, R5
0Width$:        .word 0
2$:             movb    (R0)+, R3
                mov     #10, R4

3$:             asl     (R1)
                asl     (R1)
                rorb    R3
                bcc     4$
                bis     #3, (R1)

4$:             sob     R4, 3$
                sub     #2, R1
                sob     R5, 2$
                add     (PC)+, R1
0Pitch$:        .word 0
                sob     R2, 1$
                return
; End of function UnpackJumpSprLt


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

; Анимация плеска воды

WaterWaveAnim:  mov     #75076, R1
                mov     #74, R5
                mov     CurWaterWaveSpr, R0
                mov     R0, -(SP)
                mov     #3, R3

1$:             cmpb    #125, -(R1)     ; ищем воду на экране
                bne     2$              ; не нашли
                ; нашли
                mov     #10, R2         ; выводим текущий спрайт волны

5$:             sub     #100, R1
                movb    (R0)+, (R1)
                sob     R2, 5$
                add     #1000, R1
                cmp     #WaterWaveSprEnd, R0
                bne     6$
                mov     #WaterWaveSpr, R0

6$:             dec     R3
                bne     2$
                mov     (SP), R0
                mov     #3, R3

2$:             sob     R5, 1$          ; и так по всему экрану
                mov     (SP)+, R0
                com     #0
                beq     3$              ; менять спрайт не пора
                add     #10, R0         ; меняем спрайт
                cmp     #WaterWaveSprEnd, R0 ; до конца массива дошли?
                bne     3$              ; нет
                mov     #WaterWaveSpr, R0 ; да - задаём начало

3$:             mov     R0, CurWaterWaveSpr ; сохраняем новый спрайт
                return
; End of function WaterWaveAnim


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

; Отображение динамического окружения:
; Звёзды, вулканы, холмы, столбы

DrawDymanicGrnd:mov     #StarAddrTbl, R5 ; Коррекция движения звёзд при движении ГГ
                mov     #StarAddrTblSize, R4 ; размер таблицы
                mov     StarMask, R2
                clr     R3
                tst     HorizMovOffset  ; горизонтальное смещение: 1 - при движении влево
                                        ;                         -1 - при движении вправо
                                        ;                          0 - стоим на месте
                beq     3$
                bpl     1$
                asrb    R2
                asrb    R2
                bne     2$
                mov     #100, R2
                com     R3
                br      2$
; ───────────────────────────────────────────────────────────────────────────

1$:             aslb    R2
                aslb    R2
                bne     2$
                inc     R2
                inc     R3

2$:             mov     R2, StarMask

3$:             add     R3, (R5)
                bit     (R5), #77
                bne     5$
                tst     R3
                bmi     4$
                sub     #77, (R5)
                br      5$
; ───────────────────────────────────────────────────────────────────────────

4$:             add     #77, (R5)

5$:             tst     (R5)+
                sob     R4, 3$
; проверка, пора ли рисовать вулкан
                mov     #VulkanDrawTbl, R4
                mov     #VulkanDrawTblSize, R3 ; размер таблицы
                mov     #73702, R1

11$:            mov     #VulkanSpr, R0

12$:            mov     (R4)+, R5
                bne     13$
                sob     R3, 12$
                clr     VulkanAddr
                br      15$
; ───────────────────────────────────────────────────────────────────────────

13$:            sub     Progress, R5
                mov     R3, -(SP)
                mov     R4, -(SP)
                call    sub_10          ; Вычисление ширины остатка видимого спрайта при
                                        ; захождении за левую границу экрана
                                        ; а при движении вправо - коррекция адреса экрана
                                        ; Вход: R5 - смещение на экране
                                        ;       R0 - адрес спрайта
                                        ;       R1 - адрес экрана
                                        ; Выход: R2 - видимый остаток
                                        ;       C=0 - R2 валидно, С=1 - объект полностью за границей экрана
                bcc     14$
                mov     (SP)+, R4
                mov     (SP)+, R3
                sob     R3, 11$
                clr     VulkanAddr
                br      15$
; ───────────────────────────────────────────────────────────────────────────

14$:            bit     (SP)+, (SP)+
                mov     R1, VulkanAddr  ; рисуем вулкан
                mov     #VulkanParam, R4
                mov     R2, R5
                call    DrawGroundSprite ; Вывод спрайта
                                        ; Вход: R1 - адрес экрана снизу
                                        ;       R0 - адрес спрайта
                                        ;       R2 - ширина спрайта
                                        ;       R5 - сколько столбцов рисовать
                                        ;       R4 - блок параметров из 3-х слов

15$:
; ───────────────────────────────────────────────────────────────────────────
; проверка, пора ли рисовать вертикальную стену?
20$:            mov     #WallDrawTbl, R4
                cmp     (PC)+, @(PC)+   ; Анимация приседания выключена?
                        br . + <MBR4$BR-MorphBR4$>
                        .word MorphBR4$
                bne     25$             ; нет - ничего не надо рисовать
                clr     WallScrAddr     ; адрес экрана стены
                mov     #WallDrawTblSize, R3 ; размер таблицы

21$:            mov     #56202, R1
                mov     #NullSpr, R0

22$:            mov     (R4)+, R5       ; берём очередной параметр
                bne     23$             ; если не 0, то проверяем
                sob     R3, 22$
                jmp     40$
; ───────────────────────────────────────────────────────────────────────────

23$:            bic     #100000, R5
                mov     R3, -(SP)
                mov     R4, -(SP)
                sub     Progress, R5    ; дошли до этого места?
                call    sub_10          ; Вычисление ширины остатка видимого спрайта при
                                        ; захождении за левую границу экрана
                                        ; а при движении вправо - коррекция адреса экрана
                                        ; Вход: R5 - смещение на экране
                                        ;       R0 - адрес спрайта
                                        ;       R1 - адрес экрана
                                        ; Выход: R2 - видимый остаток
                                        ;       C=0 - R2 валидно, С=1 - объект полностью за границей экрана
                bcc     26$             ; да дошли, пора рисовать

24$:            mov     (SP)+, R4
                mov     (SP)+, R3
                sob     R3, 21$         ; просмотрим весь массив

25$:            jmp     40$             ; идём дальше
; ───────────────────────────────────────────────────────────────────────────

26$:            mov     #WallSpr, R0
                mov     #GroundData, R4
                mov     (SP), R5
                tst     R2
                beq     24$
                tst     -2(R5)
                bmi     33$
                mov     #4, R2
                mov     R1, WallScrAddr ; адрес экрана стены
                mov     #156, R3

27$:            clrb    (R1)
                add     #100, R1
                sob     R3, 27$
                mov     #20, R3

28$:            movb    (R4)+, (R1)
                add     #100, R1
                sob     R3, 28$
                br      31$
; ───────────────────────────────────────────────────────────────────────────

29$:            mov     #176, R3

30$:            movb    (R0)+, (R1)
                add     #100, R1
                sob     R3, 30$

31$:            sub     #17601, R1
                bit     #76, R1
                beq     24$
                sob     R2, 29$
                mov     #176, R3

32$:            movb    #252, (R1)
                add     #100, R1
                sob     R3, 32$
                br      24$
; ───────────────────────────────────────────────────────────────────────────

33$:            mov     #byte_13470, R0
                add     #15600, R1
                mov     #20, R2

34$:            movb    (R4)+, (R1)
                add     #100, R1
                sob     R2, 34$
                mov     #3, R4
                br      37$
; ───────────────────────────────────────────────────────────────────────────

35$:            mov     #20, R2

36$:            movb    (R0)+, (R1)
                add     #100, R1
                sob     R2, 36$

37$:            sub     #1775, R1
                bit     #77, R1
                beq     24$
                tst     -(R1)
                sob     R4, 35$
                mov     #20, R2

38$:            clrb    (R1)
                add     #100, R1
                sob     R2, 38$
                br      24$
; ───────────────────────────────────────────────────────────────────────────
; проверка, пора ли рисовать столбы

40$:            mov     #StolbDrawTbl, R2
                mov     #StolbDrawTblSize, R3
                mov     #73702, R1

41$:            mov     #StolbSpr, R0
                mov     (R2)+, R5
                beq     42$
                sub     Progress, R5
                mov     R3, -(SP)
                mov     R2, -(SP)
                call    sub_10          ; Вычисление ширины остатка видимого спрайта при
                                        ; захождении за левую границу экрана
                                        ; а при движении вправо - коррекция адреса экрана
                                        ; Вход: R5 - смещение на экране
                                        ;       R0 - адрес спрайта
                                        ;       R1 - адрес экрана
                                        ; Выход: R2 - видимый остаток
                                        ;       C=0 - R2 валидно, С=1 - объект полностью за границей экрана
                bcc     43$
                mov     (SP)+, R2
                mov     (SP)+, R3

42$:            sob     R3, 41$
                br      50$
; ───────────────────────────────────────────────────────────────────────────

43$:            bit     (SP)+, (SP)+
                mov     #StolbParam, R4
                mov     R2, R5
                call    DrawGroundSprite ; Вывод спрайта
                                        ; Вход: R1 - адрес экрана снизу
                                        ;       R0 - адрес спрайта
                                        ;       R2 - ширина спрайта
                                        ;       R5 - сколько столбцов рисовать
                                        ;       R4 - блок параметров из 3-х слов
; проверка, пора ли рисовать холмы

50$:            mov     #HolmDrawTbl, R2
                mov     #HolmDrawTblSize, R3
                mov     #73702, R1

51$:            mov     #HolmSpr, R0
                mov     (R2)+, R5
                beq     52$
                sub     Progress, R5
                mov     R3, -(SP)
                mov     R2, -(SP)
                call    sub_10          ; Вычисление ширины остатка видимого спрайта при
                                        ; захождении за левую границу экрана
                                        ; а при движении вправо - коррекция адреса экрана
                                        ; Вход: R5 - смещение на экране
                                        ;       R0 - адрес спрайта
                                        ;       R1 - адрес экрана
                                        ; Выход: R2 - видимый остаток
                                        ;       C=0 - R2 валидно, С=1 - объект полностью за границей экрана
                bcc     53$
                mov     (SP)+, R2
                mov     (SP)+, R3

52$:            sob     R3, 51$
                br      54$
; ───────────────────────────────────────────────────────────────────────────

53$:            bit     (SP)+, (SP)+
                mov     #HolmParam, R4
                mov     R2, R5
                call    DrawGroundSprite ; Вывод спрайта
                                        ; Вход: R1 - адрес экрана снизу
                                        ;       R0 - адрес спрайта
                                        ;       R2 - ширина спрайта
                                        ;       R5 - сколько столбцов рисовать
                                        ;       R4 - блок параметров из 3-х слов

54$:
; ───────────────────────────────────────────────────────────────────────────
; проверка, пора ли рисовать воду

60$:            mov     #WaterDrawTbl, R4
                mov     #WaterDrawTblSize, R3

61$:            mov     #74002, R1
                mov     #NullSpr, R0

62$:            mov     (R4)+, R5
                bne     63$
                sob     R3, 62$
                return
; ───────────────────────────────────────────────────────────────────────────

63$:            bic     #100000, R5
                sub     Progress, R5
                mov     R3, -(SP)
                mov     R4, -(SP)
                call    sub_10          ; Вычисление ширины остатка видимого спрайта при
                                        ; захождении за левую границу экрана
                                        ; а при движении вправо - коррекция адреса экрана
                                        ; Вход: R5 - смещение на экране
                                        ;       R0 - адрес спрайта
                                        ;       R1 - адрес экрана
                                        ; Выход: R2 - видимый остаток
                                        ;       C=0 - R2 валидно, С=1 - объект полностью за границей экрана
                bcc     65$

64$:            mov     (SP)+, R4
                mov     (SP)+, R3
                sob     R3, 61$
                return
; ───────────────────────────────────────────────────────────────────────────

65$:            mov     (SP), R4
                mov     R1, -(SP)
                tst     -2(R4)
                bmi     67$
                tst     R2
                beq     66$
                call    sub_20524       ; Рисуем водяное дно
                mov     (SP)+, R1
                movb    #125, 700(R1)
                inc     R1
                cmp     #74076, R1
                beq     64$
                call    sub_20556       ; Рисуем поверхность
                br      64$
; ───────────────────────────────────────────────────────────────────────────

66$:            tst     (SP)+
                dec     R5
                bne     64$
                call    sub_20556       ; Рисуем поверхность
                br      64$
; ───────────────────────────────────────────────────────────────────────────

67$:            tst     R2
                beq     68$
                call    sub_20556       ; Рисуем поверхность
                mov     (SP)+, R1
                inc     R1
                cmp     #74076, R1
                beq     64$
                call    sub_20524       ; Рисуем водяное дно
                br      64$
; ───────────────────────────────────────────────────────────────────────────

68$:            tst     (SP)+
                dec     R5
                bne     64$
                call    sub_20524       ; Рисуем водяное дно
                br      64$
; End of function DrawDymanicGrnd


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

; Рисуем водяное дно

sub_20524:      mov     #10, R2

1$:             movb    #125, 1000(R1)
                clrb    (R1)
                add     #100, R1
                sob     R2, 1$
                movb    #125, 1000(R1)
                return
; End of function sub_20524


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

; Рисуем поверхность

sub_20556:      mov     #20, R2
                mov     #GroundData, R0

1$:             movb    (R0)+, (R1)
                add     #100, R1
                sob     R2, 1$
                clrb    (R1)
                return
; End of function sub_20556


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

; Выключение анимации приседания
; Очистка рабочей области экрана
; Прорисовка поверхности
; Очистка буферов динамических элементов

DrawGround$4:   mov     (PC)+, @(PC)+   ; Выключаем анимацию приседания
                        br . + <MBR4$BR-MorphBR4$>
                        .word MorphBR4$
; End of function DrawGround$4


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

; Очистка рабочей области экрана
; Прорисовка поверхности
; Очистка буферов динамических элементов

DrawGround:     mov     #56202, R1      ; очистка рабочей области экрана
                mov     #177, R2

1$:             mov     #36, R3

2$:             clr     (R1)+
                sob     R3, 2$
                add     #4, R1
                sob     R2, 1$
                clr     WallScrAddr     ; адрес экрана стены
                call    DrawFloor       ; Прорисовка земной поверхности
                ; очистка буферов
                mov     #Enemys, R1
                mov     #<EnemysSize * EnemysItemSize>/2, R2

3$:             clr     (R1)+
                sob     R2, 3$
                mov     #SporesParamTbl, R1
                mov     #<SporesParamTblSize * SporesParamItemSize>/2, R2

4$:             clr     (R1)+
                sob     R2, 4$
                mov     #ParticlesTbl, R1
                mov     #ParticlesTblSize, R2

5$:             mov     #2400, 2(R1)
                add     #ParticlesTblItemSize, R1
                sob     R2, 5$

                bis     #100000, CurBlowSpr ; взрыв принудительно прекращать
                mov     #StolbParam, R1 ; очистим параметры спрайтов объектов
                mov     #9., R2

6$:             clr     (R1)+
                sob     R2, 6$
                mov     #LavaBallArr, R1 ; массив шариков извержения вулкана
                clr     (R1)+
                clr     (R1)+
                clr     VulkanAddr
                call    DrawDymanicGrnd ; Отображение динамического окружения:
                                        ; Звёзды, вулканы холмы столбы
                mov     #75775, R1      ; адрес самой нижней строки поверхности справа экрана
                clr     R3              ; посчитаем длину поверхности
                mov     #73, R2

7$:             inc     R3
                tstb    -(R1)
                beq     8$              ; встретилась пустота
                sob     R2, 7$
                br      11$             ; пустоты не обнаружилось
; ───────────────────────────────────────────────────────────────────────────

8$:             mov     #75776, R1      ; очищаем этот участок поверхности
                mov     #20, R2         ; т.е. рисуем обрыв справа
                mov     #100, R4
                sub     R3, R4
                mov     R4, 10Pitch$
                mov     R3, 10Width$

9$:             mov     (PC)+, R3
10Width$:       .word 0

10$:            clrb    -(R1)
                sob     R3, 10$
                sub     (PC)+, R1
10Pitch$:       .word 0

                sob     R2, 9$
; когда идём в обратном направлении, и спрыгиваем с обрыва
; нужно рисовать стену слева

11$:            mov     #56276, R1      ; теперь сверху экрана справа
                mov     #73, R2

12$:            cmpb    #252, -(R1)     ; ищем стену
                beq     13$             ; нашли
                sob     R2, 12$
                br      18$             ; не нашли
; ───────────────────────────────────────────────────────────────────────────

13$:            mov     #56202, R1      ; и заполняем пространство
                mov     #176, R3
                clr     R4

14$:            tstb    (R1)+
                bne     15$
                inc     R4
                br      14$
; ───────────────────────────────────────────────────────────────────────────

15$:            tst     R4
                beq     18$
                inc     R4

16$:            sub     R4, R1
                mov     R4, R2

17$:            movb    #252, (R1)+
                sob     R2, 17$
                add     #100, R1
                sob     R3, 16$

18$:            mov     #74702, R1      ; прорисовываем воду
                mov     #74, R5

19$:            tstb    1100(R1)
                beq     23$
                tstb    (R1)
                bne     24$
                bic     #700, R1

20$:            call    sub_20524       ; Рисуем водяное дно
                sub     #777, R1
                tstb    (R1)
                beq     22$
                sob     R5, 20$

21$:            return
; ───────────────────────────────────────────────────────────────────────────

22$:            bis     #700, R1
                dec     R5
                beq     21$

23$:            inc     R1
                sob     R5, 19$
                return
; ───────────────────────────────────────────────────────────────────────────

24$:            mov     R1, R4
                bic     #700, R1
                dec     R1

25$:            bit     #76, R1
                beq     26$
                call    sub_20524       ; Рисуем водяное дно
                sub     #1001, R1
                br      25$
; ───────────────────────────────────────────────────────────────────────────

26$:            mov     R4, R1
                br      23$
; End of function DrawGround


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

; Рисуем планету

DrawPlanetSpr:  mov     #57066, R1

DrawPlanetSprA: mov     #PlanetSpr, R0
                mov     #30, R2

1$:             mov     #6, R3

2$:             tstb    (R1)
                bne     3$
                movb    (R0), (R1)

3$:             inc     R1
                inc     R0
                sob     R3, 2$
                add     #72, R1
                sob     R2, 1$
                return
; End of function DrawPlanetSpr


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

; 1. вывод на экран звёзд
; 2. анимация извержения вулкана

DrawStars$VEAn: mov     #StarAddrTbl, R5 ; массив адресов
                mov     #StarAddrTblSize, R4 ; размер массива

1$:             mov     (R5)+, R1       ; берём адрес
                cmpb    CurStarMask, 1(R1)
                bne     2$
                clrb    1(R1)

2$:             cmpb    CurStarMask, (R1)
                bne     3$
                clrb    (R1)

3$:             cmpb    CurStarMask, -1(R1)
                bne     4$
                clrb    -1(R1)

4$:             tstb    (R1)
                bne     5$
                movb    StarMask, (R1)

5$:             sob     R4, 1$          ; рисуем звёзды
                mov     StarMask, CurStarMask
; анимация извержения вулкана
; 1. генерация комков
                mov     VulkanAddr, R1  ; вулкан есть?
                beq     15$             ; нету, нечего делать
                tst     (PC)+           ; новый комок извергать пора?
0EruptDelay$:   .word 0                 ; Задержка появления нового плевка вулкана
                bne     14$             ; нет
                mov     #4, 0EruptDelay$ ; да - задаём новую задержку
                mov     #LavaBallArr, R1 ; массив комков извержения вулкана
                mov     #LavaBallArrSize, R2 ; размер массива

11$:            tst     (R1)+           ; элемент пуст?
                beq     12$             ; да
                sob     R2, 11$         ; нет - ищем
                br      14$             ; массив заполнен, нечего делать
; ───────────────────────────────────────────────────────────────────────────

12$:            mov     VulkanAddr, R3  ; адрес вулкана
                mov     R3, R4
                add     #5, R4
                bit     #70, R4
                bne     13$
                bic     #7, R3
                bit     #70, R3
                bne     13$
                bis     #2, R3          ; сгенерируем адрес появления шарика

13$:            mov     R3, -(R1)       ; сохраним в массиве
                sub     #3676, (R1)     ; должен появляться из вершины вулкана
                mov     #50, R3         ; звук появления шарика из вулкана
                mov     #6, R2
                call    @SoundSub       ; Вход: R2 - длительность звука БИП
                                        ;       R3 - частота звука

14$:            dec     0EruptDelay$    ; Задержка появления нового плевка вулкана

; 2. анимация полёта комков
15$:            mov     #LavaBallArr, R4 ; массив комков извержения вулкана
                mov     #LavaBallArrSize, R5 ; размер массива

16$:            mov     (R4)+, R1       ; берём адрес
                bne     17$             ; если есть - обработаем
                sob     R5, 16$         ; осмотрим весь массив
                br      25$
; ───────────────────────────────────────────────────────────────────────────

17$:            mov     #LavaBallSpr, R0
                mov     R1, R2
                mov     #2, R3
                add     HorizMovOffset, R2 ; горизонтальное смещение: 1 - при движении влево
                                        ;                         -1 - при движении вправо
                                        ;                          0 - стоим на месте
                add     #201, R2
                com     #0
                beq     18$
                sub     #2, R2

18$:            mov     R2, -(SP)
                add     #5, R2
                bit     #70, R2
                beq     19$
                cmp     #74000, R2
                bgt     20$

19$:            clr     (SP)

20$:            mov     #9., R2
                mov     (SP)+, -2(R4)
                mov     R4, -(SP)
                call    ClearObjectSpr  ; Стирание объекта с экрана
                                        ; Вход: R1 - адрес экрана
                                        ;       R2 - высота в строках
                                        ;       R3 - ширина
                mov     (SP), R4
                mov     -2(R4), R1
                beq     24$
                mov     #9., R2

21$:            mov     #2, R3

22$:            tstb    (R1)
                bne     23$
                movb    (R0), (R1)

23$:            inc     R1
                inc     R0
                sob     R3, 22$
                add     #76, R1
                sob     R2, 21$

24$:            mov     (SP)+, R4
                sob     R5, 16$

25$:            return
; End of function DrawStars$VEAn


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


DrawLaserBeam:  mov     ScrAddrGG, -(SP) ; адрес вывода спрайта ГГ
                clr     CurBlowSpr      ; адрес текущего спрайта взрыва, 0 - нет
                mov     #70602, ScrAddrGG ; адрес начала лазерного луча
                tst     MoveDir         ; куда смотрим?
                bpl     1$              ; влево
                add     #44, ScrAddrGG  ; вправо - тогда адрес такой

1$:             mov     ScrAddrGG, CurBlowScrAddr ; адрес взрыва будет такой
                mov     #TmpBuff, R1    ; формируем луч лазера
                mov     #14, R2         ; во временном буфере
                mov     #14002, (R1)+

2$:             mov     #73567, 30(R1)
                mov     #156735, (R1)+
                sob     R2, 2$
                call    DrawCurrGGSpr   ; выводим на экран луч лазера
                mov     (SP)+, ScrAddrGG ; адрес вывода спрайта ГГ
                mov     #540, R3        ; это параметры звука
                mov     #1, R2
                mov     #167, MorphBR7$ ; включаем обработку анимации выстрела
                inc     ShootsFlag      ; установим флаг окончания процедуры стрельбы/бомбы
                clr     CrouchShootFlag ; сбросим признак стрельбы из присяда
                jmp     @SoundSub       ; Вход: R2 - длительность звука БИП
                                        ;       R3 - частота звука
; End of function DrawLaserBeam


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

; Обработка анимации взрыва лазерного луча
; на краю экрана

LaserBlowAnim:  clr     CrouchShootFlag ; сбросим признак стрельбы из присяда
                tst     CurBlowSpr      ; анимация в процессе?
                bne     3$              ; да, идём продолжать
                                        ; нет, тогда начинаем
                com     CrouchShootFlag ; выставим флаг стрельбы в присяде
                mov     CurBlowScrAddr, R1 ; Текущий адрес экрана взрыва, если взрыв
                mov     #30, R3         ; стираем линию лазера
                mov     #2, R2
                call    ClearObjectSpr  ; Стирание объекта с экрана
                                        ; Вход: R1 - адрес экрана
                                        ;       R2 - высота в строках
                                        ;       R3 - ширина
; начинаем анимацию взрыва
                mov     #BlowSpr1, CurBlowSpr ; выставляем первый спрайт взрыва
                mov     #10, R2
                mov     #20, R3
                call    @SoundSub       ; Вход: R2 - длительность звука БИП
                                        ;       R3 - частота звука
                mov     #71502, R1      ; адрес слева
                tst     MoveDir         ; куда смотрим?
                bpl     1$              ; влево
                add     #72, R1         ; вправо, тогда адрес справа

1$:             mov     R1, CurBlowScrAddr ; сохраним

2$:             jmp     CheckBombAnim   ; идём анимировать бомбу, если надо
; ───────────────────────────────────────────────────────────────────────────

3$:             bmi     7$              ; анимацию принудительно прекратить
                cmp     #BlowSprEnd, CurBlowSpr ; анимация закончилась?
                beq     7$              ; да - прекратить
                mov     CurBlowSpr, R0  ; нет - рисуем анимацию
                mov     CurBlowScrAddr, R1 ; Текущий адрес экрана взрыва, если взрыв
                mov     #15, R2
                tst     (R1)
                bne     5$

4$:             sub     #100, R1
                mov     (R0)+, (R1)
                sob     R2, 4$

5$:             add     #BlowSprSize, CurBlowSpr ; размер спрайта взрыва

6$:             mov     #6, R2
                mov     #30, R3
                call    @SoundSub       ; Вход: R2 - длительность звука БИП
                                        ;       R3 - частота звука
                br      2$
; ───────────────────────────────────────────────────────────────────────────
; окончание анимации взрыва.
7$:             mov     (PC)+, @(PC)+   ; Отключаем обработку анимации выстрела
                        br . + <MBR7$BR-MorphBR7$>
                        .word MorphBR7$
                ; очищаем параметры анимации взрыва
                mov     CurBlowScrAddr, R1 ; Текущий адрес экрана взрыва, если взрыв
                clr     CurBlowScrAddr ; Текущий адрес экрана взрыва, если взрыв
                clr     CurBlowSpr    ; адрес текущего спрайта взрыва, 0 - нет
                mov     #15, R2
                ; стираем его с экрана
8$:             sub     #76, R1
                bitb    #125, -(R1)
                beq     9$
                clrb    (R1)

9$:             bitb    #125, -(R1)
                beq     10$
                clrb    (R1)

10$:            sob     R2, 8$
                br      6$
; End of function LaserBlowAnim


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

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

BombBlowAnim:   clr     BombBlowFlag
                tst     Bombs           ; бомбы есть?
                beq     5$              ; нету
                com     BombBlowFlag    ; устанавливаем флаг взрыва бомбы
                inc     ShootsFlag      ; флаг окончания процедуры стрельбы/бомбы
                call    DecreaseBomb    ; уменьшаем количество бомб
                mov     #10, R4         ; анимация процесса

1$:             mov     #56202, R1
                mov     #74002, R5
                com     #0
                bne     2$
                add     #100, R1
                add     #100, R5

2$:             mov     #34, R2

3$:             mov     #36, R3

4$:             com     (R1)+
                com     (R5)+
                sob     R3, 4$
                add     #104, R1
                sub     #274, R5
                sob     R2, 3$
                mov     #30, R3
                mov     #30, R2
                call    @SoundSub       ; Вход: R2 - длительность звука БИП
                                        ;       R3 - частота звука
                sob     R4, 1$

5$:             return
; End of function BombBlowAnim


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

; Опрос клавиатуры или джойстика

ControlProc:    clr     HorizMovOffset  ; очищаем признак горизонтального смещения
                clr     JumpFlag        ; очищаем флаг прыжка
                clr     BombBlowFlag    ; очищаем флаг взрыва бомбы
                clr     CrouchShootFlag ; очищаем признак приседания/выстрела
                mov     @#177714, R0    ; маска битов джойстика
                tst     R0              ; джойстик нажат?
                bne     0JoyPress$      ; да
                bit     @#177716, #100  ; нет, а клавиша нажата?
                bne     16$             ; нет
                mov     @#177662, R0    ; да, берём код
                mov     #KbdTab, R1
                cmpb    R0, (R1)+       ; это влево?
                bne     1$              ; нет
                inc     HorizMovOffset  ; да

1$:             cmpb    R0, (R1)+       ; это вправо?
                bne     2$              ; нет
                com     HorizMovOffset  ; да

2$:             cmpb    R0, (R1)+       ; это вверх?
                bne     3$              ; нет
                com     JumpFlag        ; да

3$:             cmpb    R0, (R1)+       ; это вниз?
                bne     4$              ; нет
                com     CrouchShootFlag ; да
                return
; ───────────────────────────────────────────────────────────────────────────

4$:             cmpb    R0, (R1)+       ; это взрыв бомбы
                bne     16$             ; нет
                com     BombBlowFlag    ; да
                return
; ───────────────────────────────────────────────────────────────────────────

0JoyPress$:     mov     #JoyTab, R1
                bit     R0, (R1)+       ; это влево?
                beq     11$             ; нет
                inc     HorizMovOffset  ; да

11$:            bit     R0, (R1)+       ; это вправо?
                beq     12$             ; нет
                dec     HorizMovOffset  ; да

12$:            bit     R0, (R1)+       ; это вверх?
                beq     13$             ; нет
                com     JumpFlag        ; да

13$:            bit     R0, (R1)+       ; это вниз?
                beq     14$             ; нет
                inc     CrouchShootFlag ; да

14$:            bit     R0, (R1)+       ; это выстрел?
                beq     15$             ; нет
                neg     CrouchShootFlag ; да
                return
; ───────────────────────────────────────────────────────────────────────────

15$:            bit     R0, (R1)+       ; это взрыв бомбы?
                beq     16$             ; нет
                com     BombBlowFlag    ; да
                return
; ───────────────────────────────────────────────────────────────────────────

16$:            clr     (PC)+
ShootsFlag:     .word 0                 ; флаг окончания процедуры стрельбы/бомбы
                return
; End of function ControlProc


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

; Вход: R1 - адрес экрана
;       R2 - адрес строки

DrawCtrlPointMenu:
                mov     R0, -(SP)
                mov     R1, -(SP)
                mov     R2, -(SP)
                mov     #SndParam3, R4
                call    PlaySound
                mov     #200, R4
                clr     R5
                clr     R0
                mov     (SP)+, R2
                mov     (SP)+, R1
                call    DrawString      ; Вывод строки
                                        ; Вход: R1 - адрес экрана
                                        ;       R2 - адрес строки
                                        ;       R0 - начальное значение аккумулятора кодов расшифрованных символов
                                        ;       R5 - масштаб по вертикали
                mov     (SP)+, R0
                return
; End of function DrawCtrlPointMenu


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

; Нужно ли задать управление?

IsSetControls:  bic     #40, R1
                cmp     #'D, R1         ; нажали D?
                beq     SetControls     ; да - зададим управление
                return                  ; нет
; ───────────────────────────────────────────────────────────────────────────

SetControls:    call    ClrScrEx        ; Очистка экрана рабочей области с эффектами
                mov     #61020, R1
                mov     #Text3, R2
                clr     R5
                clr     R0
                mov     #200, R4
                call    DrawString      ; Вывод строки
                                        ; Вход: R1 - адрес экрана
                                        ;       R2 - адрес строки
                                        ;       R0 - начальное значение аккумулятора кодов расшифрованных символов
                                        ;       R5 - масштаб по вертикали
                mov     #KbdTab, R0     ; изначально предполагаем клавиатуру

1$:             bit     #100, @#177716  ; клавиша нажата?
                beq     8SetKey$        ; да
                mov     @#177714, R3    ; нет, а джойстик?
                tst     R3
                beq     1$              ; нет
                add     #JoyTab-KbdTab, R0 ; да - значит назначаем джойстик
                br      5SetJoy$
; ───────────────────────────────────────────────────────────────────────────

2$:             tst     @#177714        ; джойстик нажат?
                bne     2$              ; да, ждём пока отожмут

3$:             mov     @#177714, R3    ; джойстик нажат?
                tst     R3
                beq     3$              ; нет, ждём пока нажмут
                mov     R0, R5          ; адрес слова в таблице, который заполняем

4$:             cmp     #JoyTab, R5     ; проверим, не задавали ли раньше такую маску
                beq     5SetJoy$
                cmp     R3, -(R5)
                bne     4$
                br      3$              ; да, задавали - перезапросим
; ───────────────────────────────────────────────────────────────────────────

5SetJoy$:       mov     R3, (R0)+       ; сохраняем маску
                call    DrawCtrlPointMenu ; выводим следующий пункт управления
                cmp     #JoyTab+14, R0  ; до конца дошли?
                bne     2$              ; нет, дальше опрашиваем только джойстик
                br      12$             ; да - выход
; ───────────────────────────────────────────────────────────────────────────

6$:             bit     #100, @#177716  ; клавиша нажата?
                beq     6$              ; да - ждём пока отпустят

7$:             bit     #100, @#177716  ; клавиша нажата?
                bne     7$              ; нет, ждём пока нажмут

8SetKey$:       mov     @#177662, R3    ; код нажатой клавиши
                mov     R0, R5          ; адрес байта в таблице, который заполняем

9$:             cmp     #KbdTab, R5     ; начало таблицы?
                beq     10$             ; да
                cmpb    R3, -(R5)       ; нет, переключились с джойстика на клавиатуру
                                        ; а такую клавишу уже вводили?
                bne     9$              ; нет - поищем дальше
                br      6$              ; да - надо ввести новую
; ───────────────────────────────────────────────────────────────────────────

10$:            movb    R3, (R0)+       ; сохраняем код клавиши
                cmp     #KbdTab+4, R0   ; предпоследний пункт?
                bne     11$             ; нет
                add     #10, R2         ; да - текст другой
                                        ; у джойстика на 1 пункт больше

11$:            call    DrawCtrlPointMenu ; выводим следующий пункт управления
                cmp     #KbdTab+5, R0   ; до конца дошли?
                bne     6$              ; нет - дальше выбираем только клавиатуру

12$:            call    ClrScrEx        ; Очистка экрана рабочей области с эффектами
                halt                    ; и снова перезапустим всё
; End of function IsSetControls


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

; Вывод на экран текущего спрайта человечка

DrawCurrGGSpr:  mov     ScrAddrGG, R1 ; адрес вывода спрайта ГГ
                mov     #TmpBuff, R0
; Вывод на экран текущего спрайта
; Вход: R0 - адрес спрайта
;       R1 - адрес экрана
DrawCurrTmpSpr: movb    (R0)+, R2
                movb    (R0)+, R3
                mov     #100, R4
                sub     R3, R4
                mov     R4, 11Pitch$
                mov     R3, 11Width$

1$:             mov     (PC)+, R3
11Width$:       .word 0

2$:             movb    (R0)+, R4
                bne     3$
                bitb    #252, (R1)
                beq     5$
                br      6$

3$:             bitb    #252, (R1)
                beq     4$
6$:             bitb    #125, (R1)
                beq     5$

4$:             movb    R4, (R1)

5$:             inc     R1
                sob     R3, 2$
                add     (PC)+, R1
11Pitch$:       .word 0

                sob     R2, 1$
                return
; End of function DrawCurrTmpSpr
; End of function DrawCurrGGSpr


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

; Стирание объекта с экрана
; Вход: R1 - адрес экрана
;       R2 - высота в строках
;       R3 - ширина

ClearObjectSpr: mov     #100, R4
                sub     R3, R4
                mov     R4, 12Pitch$
                mov     R3, 12Width$

1$:             mov     (PC)+, R3
12Width$:       .word 0

2$:             bitb    #252, (R1)
                beq     3$
                bitb    #125, (R1)
                beq     4$

3$:             clrb    (R1)

4$:             inc     R1
                sob     R3, 2$
                add     (PC)+, R1
12Pitch$:       .word 0

                sob     R2, 1$
                return
; End of function ClearObjectSpr


; Вывод символа
; Вход: R0 - код символа
;       R1 - адрес экрана
;       R4 - маска цвета символа
;       R5 - масштаб, 0 - нет

DrawChar:       mov     R0, -(SP)
                mov     R1, -(SP)
                mov     R2, -(SP)
                mov     R4, -(SP)
                mov     R4, ChColorMask
                add     #20, R0
                br      0DC$

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

; Вывод символа
; Вход: R0 - код символа
;       R1 - адрес экрана
;       R4 - маска цвета символа
;       R5 - масштаб, 0 - нет

DrawCharS:      mov     R0, -(SP)
                mov     R1, -(SP)
                mov     R2, -(SP)
                mov     R4, -(SP)
                mov     R4, ChColorMask
                bic     #177400, R0
                cmp     R0, #100        ; если символы 40..77
                blo     4$              ; то их -> 0..37
                ; делаем большие лат. символы и маленькие рус, коды 100..137 и 300..337
                bic     #40, R0
                tstb    R0              ; это русские буквы?
                bpl     4$              ; нет, сделаем из них коды 40..77
                sub     #140, R0        ; а из русских надо сделать 100..137
4$:             sub     #40, R0
                bpl     3$
2$:             clr     R0              ; пробел по умолчанию
3$:
0DC$:           asl     R0              ; с*=2
                mov     R0, R3
                asl     R0              ; с*=4
                add     R3, R0          ; с=с*6
                add     #Font, R0       ; адрес шрифта
                mov     #7, R2          ; высота шрифта
                clr     R3              ; значение байта линии символа

1$:             call    DrawLineChar    ; Вывод одной строки символа
                                        ; Вход: R3 - значение байта линии символа
                                        ;       R1 - адрес экрана
                                        ;       R5 - масштаб, 0 - нет
                movb    (R0)+, R3
                sob     R2, 1$
                clr     R3
                call    DrawLineChar    ; Вывод одной строки символа
                                        ; Вход: R3 - значение байта линии символа
                                        ;       R1 - адрес экрана
                                        ;       R5 - масштаб, 0 - нет
                mov     (SP)+, R4
                mov     (SP)+, R2
                mov     (SP)+, R1
                mov     (SP)+, R0
                return
; End of function DrawChar


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

; Вывод одной строки символа
; Вход: R3 - значение байта линии символа
;       R1 - адрес экрана
;       R5 - масштаб, 0 - нет

DrawLineChar:   mov     R1, -(SP)

dl1$:           mov     #4, R4

dl2$:           clc
                rorb    (R1)
                asrb    (R1)
                asrb    R3
                bcc     3$
                bisb    (PC)+, (R1)
ChColorMask:    .word 0

3$:             sob     R4, dl2$
                inc     R1
                tstb    R3
                bne     dl1$
                mov     R1, R3
                mov     (SP)+, R1
                sub     R1, R3
                dec     R3
                bne     4$
                clrb    1(R1)

4$:             mov     R5, R4
                beq     6$

5$:             movb    (R1)+, 77(R1)
                movb    (R1), 100(R1)
                add     #77, R1
                sob     R4, 5$

6$:             add     #100, R1
                return
; End of function DrawLineChar


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

; Вывод строки
; Вход: R1 - адрес экрана
;       R2 - адрес строки
;       R0 - начальное значение аккумулятора кодов расшифрованных символов
;       R5 - масштаб по вертикали

DrawString:     clr     R0
                bisb    (R2)+, R0       ; берём очередной байт данных
                bne     1$              ; не 0 - это код символа
                return                  ; 0 - конец строки
; ───────────────────────────────────────────────────────────────────────────

1$:             bpl     2$              ; печатный код
                cmpb    R0, #300        ; или русские буквы
                bhis    2$              ; то идём выводить
                sub     #200, R0        ; иначе, это смещение, так сказать, количество пробелов
                add     R0, R1          ; смещаем адрес экрана
                br      DrawString      ; и пойдём читать следующий байт данных
; ───────────────────────────────────────────────────────────────────────────

2$:             cmp     #12, R0         ; это перевод строки?
                bne     4$              ; нет - пойдём выводить
                mov     R5, R3          ; да - перевод строки
                inc     R3              ; в соответствии с масштабом
                bic     #77, R1

3$:             add     #1000, R1
                sob     R3, 3$
                br      DrawString      ; и пойдём читать следующий байт данных
; ───────────────────────────────────────────────────────────────────────────

4$:             call    DrawCharS       ; Вывод символа
                                        ; Вход: R0 - код символа
                                        ;       R1 - адрес экрана
                                        ;       R4 - маска цвета символа
                                        ;       R5 - масштаб, 0 - нет
                tst     (R1)+           ; двигаем адрес экрана
                br      DrawString      ; и пойдём читать следующий байт данных
; End of function DrawString


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

; Уменьшаем количество бомб

DecreaseBomb:   dec     Bombs
                mov     Bombs, R0
                movb    SegmDigits(R0), R0
                mov     #44447, R1
                ;jmp     DrawSegmDigit ; Вывод на экран цифры из сегментов
                                        ; Вход: R0 - код цифры (набор сегментов)
; End of function DecreaseBomb

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

; Вывод на экран цифры из сегментов
; Вход: R0 - код цифры (набор сегментов)

DrawSegmDigit:  mov     R5, -(SP)
                mov     R4, -(SP)
                mov     R3, -(SP)
                mov     R2, -(SP)
                mov     R1, -(SP)
                mov     #20, R2         ; сперва стираем знакоместо

1$:             clrb    (R1)+
                clrb    (R1)
                add     #77, R1
                sob     R2, 1$
                mov     (SP), R1
                asrb    R0
                bcc     2$
                movb    #374, (R1)
                movb    #77, 1(R1)
                movb    #360, 100(R1)
                movb    #17, 101(R1)

2$:             add     #700, R1
                asrb    R0
                bcc     3$
                movb    #374, (R1)
                movb    #77, 1(R1)
                movb    #374, 100(R1)
                movb    #77, 101(R1)

3$:             add     #700, R1
                asrb    R0
                bcc     4$
                movb    #360, (R1)
                movb    #17, 1(R1)
                movb    #374, 100(R1)
                movb    #77, 101(R1)

4$:             mov     #2, R5

5$:             mov     #17, R3
                mov     #360, R4
                asrb    R0
                bcs     6$
                clr     R3

6$:             asrb    R0
                bcs     7$
                clr     R4

7$:             mov     #7, R2

8$:             bisb    R3, (R1)+
                bisb    R4, (R1)
                sub     #101, R1
                sob     R2, 8$
                bic     #3, R3
                bic     #300, R4
                bicb    R3, 100(R1)
                bicb    R4, 101(R1)
                bicb    R3, 700(R1)
                bicb    R4, 701(R1)
                sob     R5, 5$
                mov     (SP)+, R1
                mov     (SP)+, R2
                mov     (SP)+, R3
                mov     (SP)+, R4
                mov     (SP)+, R5
                return
; End of function DrawSegmDigit


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

; Разные анимации ГГ

MorphBR1$:      jmp     JumpOnWall      ; сюда пишется 401 (пропустить команду) и 167 (переход)
MBR1$BR:
MorphBR5$:      jmp     DrawRollToUp    ; сюда пишется 401 (пропустить команду) и 167
MBR5$BR:
MorphBR6$:      jmp     DrawRollToDown  ; сюда пишется 401 (пропустить команду) и 167
MBR6$BR:
MorphBR3$:      jmp     DrawRollFromUp_Fall ; сюда пишется 401 (переход на MBR3$BR) и 167
MBR3$BR:        mov     ScrAddrGG, R1   ; адрес вывода спрайта ГГ
                bic     #177700, R1
                bis     #74000, R1      ; делаем нижний адрес
                mov     #3, R2
                mov     #10, R3
                call    ClearObjectSpr  ; Стирание объекта с экрана
                                        ; Вход: R1 - адрес экрана
                                        ;       R2 - высота в строках
                                        ;       R3 - ширина
                cmp     (PC)+, @(PC)+   ; анимация прыжка выключена?
                        br . + <MBR2$BR-MorphBR2$>
                        .word MorphBR2$
                beq     1$              ; да
                cmp     (PC)+, @(PC)+   ; нет, а какая фаза?
                        br . + <MBR8$BR3-MorphBR8$>
                        .word MorphBR8$
                beq     1$              ; 4-я (приземление)
                tstb    @#75227         ; другая, а есть куда лететь?
                bne     FinalJumpAnim   ; нет, остановимся
                br      2$              ; есть, продолжаем
; ───────────────────────────────────────────────────────────────────────────

1$:             tstb    @#75237         ; препятствие перед собой?
                bne     FinalJumpAnim   ; да - остановимся
                cmp     (PC)+, @(PC)+   ; Анимация приседания выключена?
                        br . + <MBR4$BR-MorphBR4$>
                        .word MorphBR4$
                bne     FinalJumpAnim   ; нет
                ; ГГ при движении вправо спрыгивает.
2$:             mov     #167, MorphBR6$ ; Включаем анимацию спрыгивания ГГ вниз за экран
                mov     #-400, VertGGOffset ; смещение ГГ по вертикали, -400 - присел, 400 - прыжок
                mov     #-400, word_25034
                mov     #4767, MorphBR2$ ; Включаем анимацию прыжка
                mov     (PC)+, @(PC)+   ; и переключаемся сразу на 4-ю фазу прыжка
                        br . + <MBR8$BR3-MorphBR8$>
                        .word MorphBR8$
                mov     #JumpRight, MovAnimGGPtr ; Адрес в массиве сжатых спрайтов разных анимаций
                add     #112, MovAnimGGPtr ; Адрес в массиве сжатых спрайтов разных анимаций
                mov     #ScrAddrGG, R1  ; адрес вывода спрайта ГГ
                bit     #100, (R1)
                bne     3$
                sub     #100, (R1)

3$:             bic     #200, (R1)
                mov     #-400, word_25032
                mov     #70074, R1
                mov     #15, R2
                mov     #2, R3
                call    ClearObjectSpr ; Стирание объекта с экрана
                                        ; Вход: R1 - адрес экрана
                                        ;       R2 - высота в строках
                                        ;       R3 - ширина
                jmp     DrawRollToDown
; ───────────────────────────────────────────────────────────────────────────
; анимация финала запрыгивания
FinalJumpAnim:  mov     WallScrAddr, R0 ; адрес экрана стены
                beq     7$
                bic     #177700, R0
                cmp     #36, R0
                bgt     7$
                cmp     (PC)+, @(PC)+   ; анимация прыжка выключена?
                        br . + <MBR2$BR-MorphBR2$>
                        .word MorphBR2$
                beq     5$              ; нет
                mov     #-1, HorizMovOffset ; движемся вправо
                br      7$
; ───────────────────────────────────────────────────────────────────────────

5$:             bic     #1, HorizMovOffset ; двигались влево?
                beq     6$              ; да, и остановились
                inc     HorizMovOffset  ; нет, двигались вправо, и продолжим так же

6$:             tst     JumpFlag        ; прыжок?
                beq     7$              ; нет
                mov     #167, MorphBR1$ ; Включаем анимацию прыжка
                mov     #400, VertGGOffset ; будем двигаться вверх
                clr     MoveDir         ; стоим на месте
                bis     #100000, CurBlowSpr ; анимацию взрыва лазера прекратить
7$:             jmp     MorphBR4$       ; продолжаем анимации

; ───────────────────────────────────────────────────────────────────────────
; анимация полёта вверх при прыжке
JumpFlyUp:      mov     ScrAddrGG, R1   ; адрес вывода спрайта ГГ
                sub     VertGGOffset, R1 ; применим вертикальное смещение
                mov     R1, ScrAddrGG   ; сохраним новый адрес
                cmp     #56200, R1
                blo     25$
                cmp     #51200, R1
                bhi     24$
                ; продолжаем подниматься вверх
                mov     #15000, R0
                sob     R0, .
                mov     #TmpBuff, R0
                movb    (R0)+, R2
                inc     R0

21$:            cmp     #56200, R1
                blo     22$
                add     #6, R0
                add     #100, R1
                br      23$
; ───────────────────────────────────────────────────────────────────────────

22$:            mov     (R0)+, (R1)+
                mov     (R0)+, (R1)+
                mov     (R0)+, (R1)
                add     #74, R1

23$:            sob     R2, 21$
                br      26$
; ───────────────────────────────────────────────────────────────────────────
; запрыгнули на уровень вверх, нужно его прорисовать
; и включить анимацию появления ГГ
24$:            add     #100, Progress
                call    DrawGround      ; Очистка рабочей области экрана
                                        ; Прорисовка поверхности
                                        ; Очистка буферов динамических элементов
                mov     #76536, ScrAddrGG ; адрес вывода спрайта ГГ
                mov     (PC)+, @(PC)+   ; Выключаем анимацию прыжка
                        br . + <MBR1$BR-MorphBR1$>
                        .word MorphBR1$
                mov     #167, MorphBR5$ ; Включаем анимацию появления ГГ снизу экрана
                br      ExitAnimFunc$
; ───────────────────────────────────────────────────────────────────────────
; Обработка запрыгивания на стену
JumpOnWall:     cmp     #67036, ScrAddrGG ; ГГ стоит?
                beq     FinalJumpAnim   ; да
                bhi     JumpFlyUp       ; нет - уже в прыжке
; анимация начала прыжка
                mov     #66636, ScrAddrGG ; адрес вывода спрайта ГГ

25$:            mov     MovAnimGGPtr, R0 ; Адрес в массиве сжатых спрайтов разных анимаций
                call    sub_24464       ; Вывод текущего спрайта анимации прыжка
                                        ; коррекция горизонтального направления движения
                                        ; проверка на границы этапа, и если конец, то сразу переход на функцию конца
                                        ; Вход: R0 - указатель на текущий сжатый спрайт в массиве спрайтов
26$:            mov     #4, R2
                mov     #6, R3
                call    ClearObjectSpr  ; Стирание объекта с экрана
                                        ; Вход: R1 - адрес экрана
                                        ;       R2 - высота в строках
                                        ;       R3 - ширина
                br      ExitAnimFunc$

; ───────────────────────────────────────────────────────────────────────────
; прорисовка ГГ снизу экрана при запрыгивании на стену
DrawRollToUp:   mov     ScrAddrGG, R1   ; адрес вывода спрайта ГГ
                sub     VertGGOffset, R1 ; применим вертикальное смещение
                cmp     #71000, R1
                bhi     34$

jmp_22546:      mov     R1, ScrAddrGG   ; адрес вывода спрайта ГГ
                mov     #16000, R0
                sob     R0, .
                mov     #TmpBuff, R0
                movb    (R0)+, R2
                inc     R0

32$:            cmp     #76100, R1
                blos    ExitAnimFunc$
33$:            mov     (R0)+, (R1)+
                mov     (R0)+, (R1)+
                mov     (R0)+, (R1)+
                add     #72, R1
                sob     R2, 32$
                br      ExitAnimFunc$
; ───────────────────────────────────────────────────────────────────────────

34$:            cmp     #67000, R1
                blos    JumpFlyUp
35$:            add     #2000, ScrAddrGG ; адрес вывода спрайта ГГ
                mov     (PC)+, @(PC)+   ; Выключаем анимацию появления ГГ снизу экрана
                        br . + <MBR5$BR-MorphBR5$>
                        .word MorphBR5$
                mov     #1, MoveDir     ; идём влево
                clr     WallScrAddr     ; адрес экрана стены
ExitAnimFunc$:  clr     HorizMovOffset  ; стоим на месте
                return
; ───────────────────────────────────────────────────────────────────────────
; Начало анимации спрыгивания со стены
; прорисовка падения вниз за экран
DrawRollToDown: mov     ScrAddrGG, R1   ; адрес вывода спрайта ГГ
                cmp     #70600, R1
                blo     41$
                call    sub_24102
                dec     Progress
                call    DrawDymanicGrnd ; Отображение динамического окружения:
                                        ; Звёзды, вулканы холмы столбы
                br      ExitAnimFunc$
; ───────────────────────────────────────────────────────────────────────────

41$:            cmp     #76000, R1
                blo     42$
                mov     #4, R2
                mov     #6, R3
                call    ClearObjectSpr  ; Стирание объекта с экрана
                                        ; Вход: R1 - адрес экрана
                                        ;       R2 - высота в строках
                                        ;       R3 - ширина
                br      jmp_22546
; ───────────────────────────────────────────────────────────────────────────
; спрыгнули на уровень вниз, нужно его прорисовать
; и включить анимацию появления ГГ
42$:            sub     #100, Progress
                call    DrawGround      ; Очистка рабочей области экрана
                                        ; Прорисовка поверхности
                                        ; Очистка буферов динамических элементов
                mov     #50636, ScrAddrGG ; адрес вывода спрайта ГГ
                mov     (PC)+, @(PC)+   ; Выключаем анимацию спрыгивания ГГ вниз за экран
                        br . + <MBR6$BR-MorphBR6$>
                        .word MorphBR6$
                mov     #167, MorphBR3$ ; Включаем появление ГГ сверху из-за экрана и падение на землю
; ───────────────────────────────────────────────────────────────────────────
; Прорисовка появления ГГ сверху экрана
; и падения на землю
DrawRollFromUp_Fall:
                mov     ScrAddrGG, R1   ; адрес вывода спрайта ГГ
                cmp     #56000, R1
                bhis    51$
                cmp     #66600, R1
                blo     52$
                mov     #4, R2
                mov     #6, R3
                call    ClearObjectSpr  ; Стирание объекта с экрана
                                        ; Вход: R1 - адрес экрана
                                        ;       R2 - высота в строках
                                        ;       R3 - ширина
51$:            jmp     JumpFlyUp
; ───────────────────────────────────────────────────────────────────────────

52$:            mov     (PC)+, @(PC)+   ; Выключаем появление ГГ сверху из-за экрана и падение на землю
                        br . + <MBR3$BR-MorphBR3$>
                        .word MorphBR3$
                br      ExitAnimFunc$
; End of function MorphBR1$


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


MorphBR4$:      call    sub_24604       ; сюда пишется 401 (пропустить команду) и 4767
MBR4$BR:
MorphBR2$:      call    MorphBR8$       ; сюда пишется 402 (переход на MBR2$BR) и 4767
                br      61$
; ───────────────────────────────────────────────────────────────────────────

MBR2$BR:        tst     JumpFlag
                beq     jmp_23154
                mov     #4767, MorphBR2$ ; Включаем анимацию прыжка
                mov     #-1, word_25032
                mov     #400, word_25034
                mov     (PC)+, @(PC)+   ; задаём начальную фазу прыжка
                        nop
                        .word MorphBR8$
                call    sub_24422

61$:            mov     HorizMovOffset, R0 ; горизонтальное смещение: 1 - при движении влево
                                        ;                         -1 - при движении вправо
                                        ;                          0 - стоим на месте
                beq     62$
                add     R0, Progress
                call    DrawDymanicGrnd ; Отображение динамического окружения:
                                        ; Звёзды, вулканы холмы столбы

62$:            clr     CrouchShootFlag ; Флаг приседания, >0 - просто присесть, <0 - ещё и стрелять
                br      MorphBR7$
; ───────────────────────────────────────────────────────────────────────────

jmp_23154:      tst     CrouchShootFlag ; Флаг приседания, >0 - просто присесть, <0 - ещё и стрелять
                beq     jmp_23166
                call    sub_24536

jmp_23166:      call    CheckStageBounds ; Проверка на границы этапа
                                        ; Запрет двигаться назад, и проверка на конец этапа
                mov     #TmpBuff, R1    ; тут будет распакован текущий спрайт
                movb    #50, (R1)+      ; высота
                movb    #5, (R1)+       ; ширина
                mov     MovAnimGGPtr, R0 ; Адрес в массиве сжатых спрайтов разных анимаций
                tst     HorizMovOffset  ; движемся?
                bne     68$             ; да
                mov     R0, R2          ; нет, стоим
                sub     #PackedSprMovAnmSize, R2
                cmp     #PackedSprMovAnm, R2
                beq     65$
                sub     #PackedSprMovAnmSize*2, R2
                cmp     #PackedSprMovAnm, R2
                bne     66$

65$:            sub     #PackedSprMovAnmSize, R0
                mov     R0, MovAnimGGPtr ; Адрес в массиве сжатых спрайтов разных анимаций

66$:            tst     MoveDir         ; куда направление было?
                bmi     67$             ; вправо
                                        ; влево
                call    UnpSprMv2Lt     ; Распаковка спрайта для движения влево
                                        ; Вход: R0 - адрес сжатого спрайта
                                        ;       R1 - адрес во временном буфере распаковки спрайта
                br      71$
; ───────────────────────────────────────────────────────────────────────────

67$:            call    UnpSprMv2Rt     ; Распаковка спрайта для движения вправо
                                        ; Вход: R0 - адрес сжатого спрайта
                                        ;       R1 - адрес во временном буфере распаковки спрайта
                br      71$
; ───────────────────────────────────────────────────────────────────────────

68$:            bmi     69$             ; вправо
                                        ; влево
                call    UnpSprMv2Lt     ; Распаковка спрайта для движения влево
                                        ; Вход: R0 - адрес сжатого спрайта
                                        ;       R1 - адрес во временном буфере распаковки спрайта
                br      70$
; ───────────────────────────────────────────────────────────────────────────

69$:            call    UnpSprMv2Rt     ; Распаковка спрайта для движения вправо
                                        ; Вход: R0 - адрес сжатого спрайта
                                        ;       R1 - адрес во временном буфере распаковки спрайта

70$:            add     HorizMovOffset, Progress ; изменяем прогресс
                call    DrawDymanicGrnd ; Отображение динамического окружения:
                                        ; Звёзды, вулканы холмы столбы
                mov     HorizMovOffset, MoveDir ; задаём направление движения

71$:            add     #PackedSprMovAnmSize, MovAnimGGPtr ; следующий спрайт анимации
                cmp     #PackedSprMovAnmEnd, MovAnimGGPtr
                                        ; до конца массива дошли?
                bgt     72$             ; нет
                mov     #PackedSprMovAnm, MovAnimGGPtr ; да - делаем начало

72$:            call    DrawCurrGGSpr   ; Вывод на экран текущего спрайта человечка

MorphBR7$:      jmp     LaserBlowAnim   ; сюда пишется 401 (пропустить команду) и 167
MBR7$BR:        tst     ShootsFlag      ; процедура стрельбы/бомбы окончена?
                beq     2$              ; нет ещё, продолжаем
                clr     CrouchShootFlag ; да, снимаем флаги
                clr     BombBlowFlag
                return

2$:             tst     CrouchShootFlag ; Флаг приседания, >0 - просто присесть, <0 - ещё и стрелять
                bpl     CheckBombAnim
                call    DrawLaserBeam   ; рисуем луч лазера

CheckBombAnim:  tst     BombBlowFlag    ; бомба взорвалась?
                beq     1$              ; нет
                jmp     BombBlowAnim    ; Анимация взрыва бомбы
; ───────────────────────────────────────────────────────────────────────────

1$:             return
; End of function MorphBR4$

; ───────────────────────────────────────────────────────────────────────────
; Анимация прыжка
MorphBR8$:      nop                     ; сюда пишется 240
                                        ;              526 - переход на 24302 (MBR8$BR3)
                                        ;              454 - переход на 24156 (MBR8$BR1)
;начальная фаза прыжка (толчок-подъём)
                inc     word_25032
                beq     2$
                cmp     #7, word_25032
                blt     1$
                tst     JumpFlag
                bne     sub_24102

1$:             mov     (PC)+, @(PC)+   ; переключаемся на вторую фазу прыжка
                        br . + <MBR8$BR1-MorphBR8$>
                        .word MorphBR8$
                clr     GGFlyDivider
                mov     word_25032, word_25036
                br      sub_24102
; ───────────────────────────────────────────────────────────────────────────

2$:             sub     #1400, ScrAddrGG ; адрес вывода спрайта ГГ

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


sub_24102:      sub     word_25034, ScrAddrGG ; адрес вывода спрайта ГГ
                mov     MovAnimGGPtr, R0 ; Адрес в массиве сжатых спрайтов разных анимаций
                call    sub_24464       ; Вывод текущего спрайта анимации прыжка
                                        ; коррекция горизонтального направления движения
                                        ; проверка на границы этапа, и если конец, то сразу переход на функцию конца
                                        ; Вход: R0 - указатель на текущий сжатый спрайт в массиве спрайтов
                tst     word_25032
                beq     2$
                mov     #4, R2
                mov     #6, R3
                tst     word_25034
                bpl     1$
                sub     #5400, R1

1$:             call    ClearObjectSpr  ; Стирание объекта с экрана
                                        ; Вход: R1 - адрес экрана
                                        ;       R2 - высота в строках
                                        ;       R3 - ширина
2$:             return
; End of function sub_24102

; ───────────────────────────────────────────────────────────────────────────
; вторая фаза прыжка (полёт)

MBR8$BR1:       call    sub_24102
                com     (PC)+
GGFlyDivider:   .word 0
                bne     2$
                asr     word_25034
                bit     #77, word_25034
                beq     1$
                clr     word_25034

1$:             dec     word_25036
                beq     3$

2$:             return
; ───────────────────────────────────────────────────────────────────────────

3$:             mov     (PC)+, @(PC)+   ; переключаемся на третью фазу прыжка
                        br . + <MBR8$BR2-MorphBR8$>
                        .word MorphBR8$
                clr     GGFly2Divider
                mov     #-100, word_25034
                return
; ───────────────────────────────────────────────────────────────────────────
; третья фаза прыжка (конец полёта)

MBR8$BR2:       call    sub_24102
                com     (PC)+
GGFly2Divider:  .word 0

                bne     11$
                asl     word_25034
                bit     #377, word_25034
                beq     12$

11$:            return
; ───────────────────────────────────────────────────────────────────────────

12$:            mov     (PC)+, @(PC)+   ; переключаемся на 4-ю фазу прыжка
                        br . + <MBR8$BR3-MorphBR8$>
                        .word MorphBR8$
                return
; ───────────────────────────────────────────────────────────────────────────
; 4-я фаза прыжка (приземление)

MBR8$BR3:       cmp     ScrAddrGG, #67000 ; адрес вывода спрайта ГГ
                ble     21$

                add     #172, MovAnimGGPtr ; Адрес в массиве сжатых спрайтов разных анимаций
                mov     #67335, ScrAddrGG ; адрес вывода спрайта ГГ
                mov     #-1, word_25034
                mov     (PC)+, @(PC)+   ; переключаемся на последнюю фазу прыжка
                        br . + <MBR8$BR4-MorphBR8$>
                        .word MorphBR8$
21$:            jmp     sub_24102
; ───────────────────────────────────────────────────────────────────────────
; всё, прыжок завершился

MBR8$BR4:       mov     #67036, ScrAddrGG ; адрес вывода спрайта ГГ
                mov     #PackedSprMovAnm, MovAnimGGPtr ; Адрес в массиве сжатых спрайтов разных анимаций
                mov     (PC)+, @(PC)+   ; Выключаем анимацию прыжка
                        br . + <MBR2$BR-MorphBR2$>
                        .word MorphBR2$
                mov     #67043, R1
                mov     #50, R2
                mov     #1, R3
                call    ClearObjectSpr  ; Стирание объекта с экрана
                                        ; Вход: R1 - адрес экрана
                                        ;       R2 - высота в строках
                                        ;       R3 - ширина
                tst     (SP)+
                jmp     jmp_23154
; End of function MBR8$BR1


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


sub_24422:      mov     ScrAddrGG, R1   ; адрес вывода спрайта ГГ
                mov     #20, R2
                mov     #5, R3
                call    ClearObjectSpr  ; Стирание объекта с экрана
                                        ; Вход: R1 - адрес экрана
                                        ;       R2 - высота в строках
                                        ;       R3 - ширина
                mov     R1, ScrAddrGG   ; адрес вывода спрайта ГГ
                mov     #JumpRight, R0
                mov     R0, MovAnimGGPtr ; Адрес в массиве сжатых спрайтов разных анимаций
                add     #112, MovAnimGGPtr ; Адрес в массиве сжатых спрайтов разных анимаций
; End of function sub_24422


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

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

sub_24464:      mov     #TmpBuff, R1
                tst     MoveDir         ; куда движемся?
                bmi     1$              ; вправо
                ; влево
                call    UnpackJumpSprLt ; расширение спрайтов прыжка в буфер для направления влево
                                        ; Вход: R0 - указатель на текущий сжатый спрайт в массиве спрайтов
                                        ;       R1 - адрес буфера
                br      2$
; ───────────────────────────────────────────────────────────────────────────
                ; вправо
1$:             call    UnpackJumpSprRt ; расширение спрайтов прыжка в буфер для направления вправо
                                        ; Вход: R0 - указатель на текущий сжатый спрайт в массиве спрайтов
                                        ;       R1 - адрес буфера
2$:             call    DrawCurrGGSpr   ; Вывод на экран текущего спрайта человечка
                cmp     HorizMovOffset, MoveDir ; горизонтальное смещение и направление совпадают?
                beq     3$              ; да
                add     MoveDir, HorizMovOffset ; нет - корректируем
3$:             jmp     CheckStageBounds ; Запрет двигаться назад, и проверка на конец этапа
; End of function sub_24464


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


sub_24536:      mov     ScrAddrGG, R1   ; адрес вывода спрайта ГГ
                cmp     #67036, R1
                beq     1$
                return
; ───────────────────────────────────────────────────────────────────────────

1$:             mov     #CrouchRight, MovAnimGGPtr ; Адрес в массиве сжатых спрайтов разных анимаций
                mov     #12, R2
                mov     #5, R3
                call    ClearObjectSpr  ; Стирание объекта с экрана
                                        ; Вход: R1 - адрес экрана
                                        ;       R2 - высота в строках
                                        ;       R3 - ширина
                mov     #4767, MorphBR4$ ; Включаем анимацию приседания
                br      2br$
; End of function sub_24536


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


sub_24604:      tst     CrouchShootFlag ; Флаг приседания, >0 - просто присесть, <0 - ещё и стрелять
                bne     2br$
                mov     ScrAddrGG, R1   ; адрес вывода спрайта ГГ
                cmp     #70236, R1
                bne     1$
                add     #5, R1

1$:             mov     #13, R2
                mov     #3, R3
                call    ClearObjectSpr  ; Стирание объекта с экрана
                                        ; Вход: R1 - адрес экрана
                                        ;       R2 - высота в строках
                                        ;       R3 - ширина
                mov     #67036, ScrAddrGG ; адрес вывода спрайта ГГ
                mov     #PackedSprMovAnm, MovAnimGGPtr ; Адрес в массиве сжатых спрайтов разных анимаций
                mov     (PC)+, @(PC)+   ; Выключаем анимацию приседания
                        br . + <MBR4$BR-MorphBR4$>
                        .word MorphBR4$
                tst     (SP)+
                jmp     jmp_23166
; ───────────────────────────────────────────────────────────────────────────

2br$:           mov     MovAnimGGPtr, R0 ; Адрес в массиве сжатых спрайтов разных анимаций
                mov     #70236, ScrAddrGG ; адрес вывода спрайта ГГ
                tst     HorizMovOffset  ; стоим на месте?
                beq     3$              ; да
                mov     HorizMovOffset, MoveDir ; нет - зададим направление

3$:             tst     MoveDir         ; куда идём?
                bmi     4$              ; вправо
                ; влево
                sub     #3, ScrAddrGG   ; адрес вывода спрайта ГГ
                mov     #70543, R1
                br      5$
; ───────────────────────────────────────────────────────────────────────────
                ; вправо
4$:             mov     #70533, R1

5$:             mov     #10, R2
                mov     #3, R3
                call    ClearObjectSpr  ; Стирание объекта с экрана
                                        ; Вход: R1 - адрес экрана
                                        ;       R2 - высота в строках
                                        ;       R3 - ширина
                call    sub_24464       ; Вывод текущего спрайта анимации прыжка
                                        ; коррекция горизонтального направления движения
                                        ; проверка на границы этапа, и если конец, то сразу переход на функцию конца
                                        ; Вход: R0 - указатель на текущий сжатый спрайт в массиве спрайтов
                tst     (SP)+
                jmp     MorphBR7$
; End of function sub_24604


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


ControlAnim:    dec     (PC)+           ; анимацию пора заканчивать?
MenuAnimDuration:.word 177              ; Длительность анимации в меню
                beq     1$              ; да
                jmp     DrawStars$VEAn  ; нет - рисуем звёзды
; ───────────────────────────────────────────────────────────────────────────

1$:             tst     (SP)+           ; да - переходим к началу
                br      Entry2$
; End of function ControlAnim

; ───────────────────────────────────────────────────────────────────────────
; Точка входа, стек должен быть GameTopStack

Entry$:         add     #4, SP
                xor     R0, R0
                mov     (R0), R0        ; = 14747

1$:             xor     R0, (SP)+       ; проверяем стек
                bne     1$              ; доходим до вершины, или если стек неверный - вообще всё портим
                mov     R0, -(SP)       ; возвращаем как было

Entry2$:        mov     #54747, Progress ; для заставки задаём запредельный прогресс
                clr     HorizMovOffset  ; стоим на месте
                clr     BombBlowFlag    ; бомба не взрывается
                clr     CrouchShootFlag ; Флаг приседания, >0 - просто присесть, <0 - ещё и стрелять
                call    DrawGround      ; Очистка рабочей области экрана
                                        ; Прорисовка поверхности
                                        ; Очистка буферов динамических элементов
                call    RestoreScreen   ; восстановление границ окна рабочей области

                mov     #StolbParam, R4
                mov     #73711, R1      ; адрес экрана
                mov     #StolbSpr, R0   ; спрайт
                movb    (R0)+, R2       ; берём первый байт
                mov     R2, R5          ; рисуем всю ширину
                call    DrawGroundSprite ; Вывод спрайта
                                        ; Вход: R1 - адрес экрана снизу
                                        ;       R0 - адрес спрайта
                                        ;       R2 - ширина спрайта
                                        ;       R5 - сколько столбцов рисовать
                                        ;       R4 - блок параметров из 3-х слов
                mov     #73763, R1
                mov     #HolmParam, R4
                mov     #HolmSpr, R0
                movb    (R0)+, R2
                mov     R2, R5
                call    DrawGroundSprite ; Вывод спрайта
                                        ; Вход: R1 - адрес экрана снизу
                                        ;       R0 - адрес спрайта
                                        ;       R2 - ширина спрайта
                                        ;       R5 - сколько столбцов рисовать
                                        ;       R4 - блок параметров из 3-х слов
                mov     #61702, R1      ; Выводим 3 зелёные линии
                mov     #36, R2
                mov     #125252, R3

3$:             mov     R3, 400(R1)
                mov     R3, 200(R1)
                mov     R3, (R1)+
                sob     R2, 3$
                call    sub_32710       ; Вывод названия и этапа
                cmp     SndSubAddr$+2, SoundSub ; Проверяем состояние звука
                beq     4$              ; звук включён
                add     #4, R2          ; это для текста OFF

4$:             call    DrawString      ; Вывод строки
                                        ; Вход: R1 - адрес экрана
                                        ;       R2 - адрес строки
                                        ;       R0 - начальное значение аккумулятора кодов расшифрованных символов
                                        ;       R5 - масштаб по вертикали
; ──────────── начало заставки ──────────────────────────────────────────────
SplashAnim:     mov     #SndParam, R4
                mov     #240, MenuAnimDuration ; Длительность анимации в меню
                call    PlaySound

1$:             call    ControlAnim
                call    LivingAnim      ; анимация живности в заставке
                call    DrawPlanetSpr   ; Рисуем планету
                mov     #24000, R2
                sob     R2, .
                bit     #100, @#177716  ; пока  не нажмём какую-нибудь клавишу
                bne     1$
; ──────────── конец заставки ───────────────────────────────────────────────
                mov     #SndParam2, R4
                call    PlaySound
                mov     @#177662, R1    ; берём код нажатой клавиши
                call    IsSetControls   ; Нужно ли задать управление?
                sub     #'E, R1         ; выход из игры?
                beq     MakeExit        ; да
                call    ClrScrEx2       ; иначе
                br      StartGame       ; запуск игры
; ───────────────────────────────────────────────────────────────────────────

MakeExit:       add     #16, R2         ; на выходе из функции IsSetControls R2 == 0

1$:             mov     ExitData(R1), (R1)+
                sob     R2, 1$
                jmp     @100156         ; -> 100442
; ───────────────────────────────────────────────────────────────────────────
; Кусок кода длиной 16 слов, переписывается по адресу 0
; при выходе из игры
; задумка была такая:
; запускается код по адресу 100442, там emt 4, это вызывает прерывание по вектору 30, а там число 10
; там jmp 100202, а там очистка памяти. Оно должно дойти до адреса 100000 и вызвать прерывание по вектору 4
; а там 0, по адресу 0 код: 100442 -> -(SP) и переход на выполнение emt 14, а дальше СТОП
; вот так оно работало бы на БК10, на БК 11 не работает, т.к. стирает ещё и монитор БК10

ExitData:       br      1e$
                .word 100156
                .word 0, 0
                .word 167, 100166
1e$:            .word 17746, 177762
                .word 177, 77770
                .word 0
                .word 0
                .word 10
                .word 0
; ───────────────────────────────────────────────────────────────────────────

StartGame:      mov     #Score, R0
                mov     #5, R2          ; начальное количество жизней и бомб
                mov     R2, R1          ; а заодно и длина массива счёта
1$:             clrb    (R0)+           ; обнуление счёта
                sob     R2, 1$
                call    DrawScore       ; Вывод счёта
                mov     R1, Lives       ; количество жизней
                mov     R1, Bombs       ; количество бомб
                movb    SegmDigits(R1), R0 ; маска сегментов, соответствующая числу
                mov     R0, -(SP)
                mov     #43015, R1      ; выводим количество жизней
                call    DrawSegmDigit   ; Вывод на экран цифры из сегментов
                                        ; Вход: R0 - код цифры (набор сегментов)
                mov     (SP)+, R0
                mov     #44447, R1      ; выводим количество бомб
                call    DrawSegmDigit   ; Вывод на экран цифры из сегментов
                                        ; Вход: R0 - код цифры (набор сегментов)
                bis     #1, LivesIncDec ; Значение, на которое уменьшается или увеличивается число жизней

ContinueGame$:  mov     #CurrentStageData, R1
                mov     #StageSizeW, R2 ; размер данных этапа в словах
                clr     R0              ; поиск максимального значения в массиве

3$:             mov     (R1)+, R3       ; берём значение
                bic     #100000, R3     ; сбрасываем бит 15
                cmp     R0, R3          ; макс. больше текущего?
                bgt     4$              ; да
                mov     R3, R0          ; нет - нашли большее

4$:             sob     R2, 3$          ; и так весь массив
                add     #55, R0
                mov     R0, MaxProgress+2 ; сохраняем макс. значение прогресса этапа
                mov     #1030, @#177664
                clr     HorizMovOffset  ; пока стоим на месте
                clr     LavaBallArr     ; массив комков извержения вулкана
                clr     VulkanAddr      ; вулкана пока нет.
                mov     #300, Progress  ; начальный прогресс
                mov     #20, StarMask   ; инициализация звёздочек
                mov     StarMask, CurStarMask
                mov     #WaterWaveSpr, CurWaterWaveSpr
                ;bit     #5, Bombs       ; предполагалось, с началом каждого этапа восполнять запас бомб
                mov     #1, MoveDir     ; идём влево
                call    ShowCurrStage   ; Прорисовка поверхности
                                        ; И отображение текущего этапа

GameLoop:       mov     (PC)+, @(PC)+   ; Выключаем анимацию прыжка
                        br . + <MBR1$BR-MorphBR1$>
                        .word MorphBR1$
                mov     (PC)+, @(PC)+   ; Выключаем анимацию прыжка
                        br . + <MBR2$BR-MorphBR2$>
                        .word MorphBR2$
                mov     (PC)+, @(PC)+   ; Выключаем появление ГГ сверху из-за экрана и падение на землю
                        br . + <MBR3$BR-MorphBR3$>
                        .word MorphBR3$
                mov     (PC)+, @(PC)+   ; Выключаем анимацию приседания
                        br . + <MBR4$BR-MorphBR4$>
                        .word MorphBR4$
                mov     (PC)+, @(PC)+   ; Выключаем анимацию появления ГГ снизу экрана
                        br . + <MBR5$BR-MorphBR5$>
                        .word MorphBR5$
                mov     (PC)+, @(PC)+   ; Выключаем анимацию спрыгивания ГГ вниз за экран
                        br . + <MBR6$BR-MorphBR6$>
                        .word MorphBR6$
                mov     (PC)+, @(PC)+   ; Отключаем обработку анимации выстрела
                        br . + <MBR7$BR-MorphBR7$>
                        .word MorphBR7$

                mov     #67036, ScrAddrGG ; адрес вывода спрайта ГГ
                clr     CurBlowSpr      ; адрес текущего спрайта взрыва, 0 - нет
                clr     CurBlowScrAddr  ; Текущий адрес экрана взрыва, если взрыв
                mov     #PackedSprMovAnm, MovAnimGGPtr ; Адрес в массиве сжатых спрайтов разных анимаций
GameLoop2:
;                mov     #73700, R1      ; Восстанавливаем левую границу экрана
;                mov     #14, R2         ; напротив земли. Зачем, не ясно, я не нашёл ситуаций, когда она портится.
;
;1$:             mov     -200(R1), (R1)
;                add     #100, R1
;                sob     R2, 1$
CheckGameOver:  tstb    Lives           ; жизни кончились?
                bne     NextStartGame5$ ; нет ещё, можно играть
                ; да - конец игры
GameOver$:      dec     Progress        ; отматываем прогресс назад
                call    DrawDymanicGrnd ; Отображение динамического окружения:
                                        ; Звёзды, вулканы, холмы, столбы
                call    WaterWaveAnim   ; Анимация плеска воды
                tst     @#75540
                bne     1$
                sub     #102, Progress
                call    DrawGround      ; Очистка рабочей области экрана
                                        ; Прорисовка поверхности
                                        ; Очистка буферов динамических элементов

1$:             bit     #100, @#177716  ; пока не нажата любая клавиша
                bne     GameOver$       ; тут почему-то нету проверки условия на переход прогресса через 0
                mov     #SndParam2, R4
                call    PlaySound
                jmp     StartGame

; ───────────────────────────────────────────────────────────────────────────
NextStartGame5$:cmp     #67000, ScrAddrGG ; что происходит с ГГ?
                bgt     GoCheckColl$    ; в прыжке
; обработка ситуаций, когда ГГ идёт или присел
                tst     word_25034
                bmi     1$
                cmp     (PC)+, @(PC)+   ; анимация прыжка выключена?
                        br . + <MBR2$BR-MorphBR2$>
                        .word MorphBR2$
                bne     GoCheckColl$    ; нет

1$:             cmpb    #125, @#75540   ; на воду наступил?
                ;bne     GoCheckColl$    ; ### это для честной игры
                br      GoCheckColl$    ; ### это чтоб ходить по воде
; ───────────────────────────────────────────────────────────────────────────
; уменьшим жизнь ГГ
DecreaseLives$: sub     LivesIncDec, Lives ; Значение, на которое уменьшается или увеличивается число жизней
; выведем на экран
                mov     Lives, R0       ; количество жизней
                mov     #43015, R1
                movb    SegmDigits(R0), R0
                call    DrawSegmDigit   ; Вывод на экран цифры из сегментов
                                        ; Вход: R0 - код цифры (набор сегментов)
; перерисуем поверхность
                call    DrawGround$4    ; Выключение анимации приседания
                                        ; Очистка рабочей области экрана
                                        ; Прорисовка поверхности
                                        ; Очистка буферов динамических элементов
; добавим в таблицу разлёта осколков осколки от ГГ
                mov     ScrAddrGG, R1   ; адрес вывода спрайта ГГ
                mov     #GGParticleSpr, R0
                add     #3400, R1
                call    AddParticleItem ; Внесение в таблицу разлёта осколков нового элемента
                                        ; Вход: R0 - адрес спрайта частицы
                                        ;       R1 - адрес экрана
                mov     #30, R3
                mov     R3, R2
                call    @SoundSub       ; Вход: R2 - длительность звука БИП
                                        ;       R3 - частота звука
                br      12$
; ───────────────────────────────────────────────────────────────────────────

11$:            sub     MoveDir, Progress ; что-то странное, кода идём влево, тут прогресс уменьшается
                                        ; а когда идём вправо, он должен увеличиваться

12$:            call    ParticlesAnim   ; Анимация разлёта осколков при попадании в объекты
                call    DrawDymanicGrnd ; Отображение динамического окружения:
                                        ; Звёзды, вулканы, холмы, столбы
                call    WaterWaveAnim   ; Анимация плеска воды
                cmpb    #125, @#75536   ; пока вода - продвигаем прогресс
                beq     11$
                cmpb    #125, @#75542
                beq     11$

                tst     VulkanAddr      ; пока вулкан - продвигаем прогресс
                bne     11$
                cmp     #2400, ParticlesTbl+2 ; пока не отработает первый элемент
                bne     12$             ; таблицы разлёта осколков
                jmp     GameLoop

; ───────────────────────────────────────────────────────────────────────────
; проверка на коллизии
                ; сперва с живностью
GoCheckColl$:   mov     #<Enemys+2>, R5
                mov     #600, R3        ; это высота в строках * 100
                mov     #2, R0          ; проверим на встречу с червяками и черепахами
                call    CheckCollision  ; Вход: R5 - указатель в массиве Enemys + 2
                                        ;       R3 - высота объекта в строках * 100
                                        ;       R0 - количество проверяемых элементов в массиве
                mov     #2000, R3
                mov     #4, R0          ; проверим на встречу со змеями и лягушками
                call    CheckCollision  ; Вход: R5 - указатель в массиве Enemys + 2
                                        ;       R3 - высота объекта в строках * 100
                                        ;       R0 - количество проверяемых элементов в массиве
                mov     #2600, R3
                mov     #2, R0          ; проверим на встречу с мухами
                call    CheckCollision  ; Вход: R5 - указатель в массиве Enemys + 2
                                        ;       R3 - высота объекта в строках * 100
                                        ;       R0 - количество проверяемых элементов в массиве
                ; с живностью не встретились, продолжаем,
                ; проверим на встречу с лавой
                mov     #246, R5
                mov     LavaBallArr, R4 ; массив шариков извержения вулкана
                beq     61$
                add     #600, R4
                mov     #400, R3
                mov     #1, R0
                call    CheckCollisionP ; Вход: R5 - указатель в массиве Enemys + 4
                                        ;       R3 - высота объекта в строках * 100
                                        ;       R0 - количество проверяемых элементов в массиве
                                        ;       R4 - адрес экрана проверяемого объекта

61$:            mov     #246, R5
                mov     #1, R0
                mov     LavaBallArr+2, R4
                beq     62$
                add     #600, R4
                call    CheckCollisionP ; Вход: R5 - указатель в массиве Enemys + 4
                                        ;       R3 - высота объекта в строках * 100
                                        ;       R0 - количество проверяемых элементов в массиве
                                        ;       R4 - адрес экрана проверяемого объекта
62$:            ; коллизий нет, продолжаем игру
                call    CheckPause_Hide ; Проверка нажатия клавиш паузы, спрятать игру, показать игру
                call    ControlProc     ; Опрос клавиатуры или джойстика
                call    MorphBR1$       ; Разные анимации ГГ
                call    WaterWaveAnim   ; Анимация плеска воды
                call    DrawStars$VEAn  ; 1. вывод на экран звёзд
                                        ; 2. анимация извержения вулкана
                call    LivingAnim      ; анимация живности в заставке
                call    DrawPlanetSpr   ; Рисуем планету
                tst     HorizMovOffset  ; горизонтальное смещение: 1 - при движении влево
                                        ;                         -1 - при движении вправо
                                        ;                          0 - стоим на месте
                bne     63$
                call    RestoreWall
63$:            tst     BombBlowFlag    ; бомбу взорвали?
                beq     5$              ; нет
                mov     #SporesParamTbl, R1 ; да - все падающие яйца убрать с экрана и из таблицы
                mov     #3, R2          ; количество элементов

1$:             mov     (R1), R3
                beq     4$
                mov     #SporeSpr, R0
                inc     R0
                movb    (R0)+, R4

2$:             cmpb    (R0)+, (R3)
                bne     3$
                clrb    (R3)

3$:             add     #100, R3
                sob     R4, 2$

4$:             clr     (R1)+
                clr     (R1)+
                sob     R2, 1$

5$:             call    sub_31616       ; Стереть с экрана номер текущего этапа, если время пришло
                                        ; и Вкл/выкл звук
                jmp     GameLoop2


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

; Проверка нажатия клавиш паузы, спрятать игру, показать игру

CheckPause_Hide:
                bit     @#177716, #100  ; клавиша нажата?
                bne     3$              ; нет - выход
; КТ - пауза
1$:             cmp     @#177662, #3    ; да - КТ?
                bne     2$              ; нет
                ; да, пауза
                tst     @#177714        ; да, а джойстик  нажат?
                bne     3$              ; да - конец паузы
                br      1$              ; ждём, пока не будет нажато что-нибудь другое

2$:             cmp     @#177662, #21   ; нажато СУ - Q?
                beq     4$              ; да
3$:             return                  ; нет - выход
; ───────────────────────────────────────────────────────────────────────────
; Су-Q - спрятать игру
; Су-F - вернуть игру

4$:             mov     #130, @#177664
                mov     #60000, R1
                mov     #4000, R2

5$:             clr     (R1)+
                sob     R2, 5$
                mov     #60200, R1
                mov     #BasText, R2
                clr     R5              ; масштаба нет
                mov     #300, ChColorMask
                call    DrawText        ; Вход: R1 - адрес экрана
                                        ;       R2 - адрес текста
                mov     #61400, R3
                mov     #40, R0

6$:             mov     #140003, 100(R3)
                mov     #-1, (R3)+
                sob     R0, 6$
                add     #46, R1
                call    DrawText        ; Вход: R1 - адрес экрана
                                        ;       R2 - адрес текста
                mov     #62100, R1
                call    DrawText        ; Вход: R1 - адрес экрана
                                        ;       R2 - адрес текста
                mov     #63300, R1
                call    DrawText        ; Вход: R1 - адрес экрана
                                        ;       R2 - адрес текста
                mov     #64500, R1
                call    DrawText        ; Вход: R1 - адрес экрана
                                        ;       R2 - адрес текста
                mov     #65700, R1
                call    DrawText        ; Вход: R1 - адрес экрана
                                        ;       R2 - адрес текста
                sub     #100, R1
                mov     #12, R2

7$:             com     (R1)
                add     #100, R1
                sob     R2, 7$

8$:             bit     @#177716, #100  ; ждём нажатия Су-F
                bne     8$
                cmp     @#177662, #6
                bne     8$
; Восстановление границ рабочей области экрана
RestoreScreen:  mov     #57576, R1
                mov     #101, R2

1$:             mov     #36, R3
                mov     (R1)+, 176(R1)
                mov     (R1)+, 176(R1)

2$:             clr     (R1)+
                sob     R3, 2$
                sob     R2, 1$
                call    RestoreWall   ; Восстановление стены, если есть
                cmpb    #252, @#56202   ; и восстановление сплошной области слева от стены
                                        ; если стена есть
                bne     5$
                mov     #57502, R1
                mov     #110, R2

3$:             tstb    (R1)
                bne     4$
                movb    #252, (R1)
                inc     R1
                br      3$
; ───────────────────────────────────────────────────────────────────────────

4$:             bis     #77, R1
                add     #3, R1
                sob     R2, 3$

5$:             mov     #1030, @#177664
                return
; End of function CheckPause_Hide


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

; Вход: R1 - адрес экрана
;       R2 - адрес текста

DrawText:       clr     R0
                bisb    (R2)+, R0
                beq     2$
                mov     R2, -(SP)
                asl     R0
                mov     R0, R3
                asl     R0
                asl     R0
                add     R3, R0
                add     #112037, R0
                mov     #11, R2

1$:             movb    (R0)+, R3
                call    DrawLineChar    ; Вывод одной строки символа
                                        ; Вход: R3 - значение байта линии символа
                                        ;       R1 - адрес экрана
                                        ;       R5 - масштаб, 0 - нет
                sob     R2, 1$
                mov     (SP)+, R2
                sub     #1076, R1
                br      DrawText
; ───────────────────────────────────────────────────────────────────────────

2$:             return
; End of function DrawText


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

; Вход: R5 - указатель в массиве Enemys + 2
;       R3 - высота объекта в строках * 100
;       R0 - количество проверяемых элементов в массиве

CheckCollision: mov     (R5)+, R4       ; это адрес экрана объекта
                beq     2cc$       ; 0 - нету, нечего проверять
; End of function CheckCollision


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

; Вход: R5 - указатель в массиве Enemys + 4
;       R3 - высота объекта в строках * 100
;       R0 - количество проверяемых элементов в массиве
;       R4 - адрес экрана проверяемого объекта

CheckCollisionP:mov     R4, R2          ; адрес экрана объекта
                bic     #177700, R4     ; получим горизонтальное смещение
                cmp     #41, R4         ; если правее ГГ
                blt     2cc$            ; то не встретились
                add     (R5), R4        ; прибавим текущую видимую ширину объекта
                cmp     #40, R4         ; если левее ГГ
                bgt     2cc$            ; то не встретились
                mov     ScrAddrGG, R1   ; адрес вывода спрайта ГГ
                add     #400, R1        ; нижняя граница ГГ
                cmp     R1, R2          ; если выше ГГ
                bgt     2cc$            ; то не встретились
                sub     R3, R2          ; верхняя граница объекта
                cmp     #67000, R1      ; ГГ присел
                blt     1$              ; да - попали в него
                add     #4000, R1       ; если прыжок или ходьба - то это нижняя граница ГГ
                cmp     R1, R2          ; пересеклись?
                blt     2cc$            ; нет - всё ок

1$:             ;tst     (SP)+           ; ### это для честной игры
                br      2cc$            ; ### это для бессмертия
                jmp     DecreaseLives$ ; уменьшаем жизни
; ───────────────────────────────────────────────────────────────────────────

2cc$:           add     #EnemysItemSize-2, R5 ; к следующему элементу массива
                sob     R0, CheckCollision ; и так все проверяемые элементы
                return
; End of function CheckCollisionP


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

; Восстановление стены, если есть

RestoreWall:    mov     WallScrAddr, R1 ; адрес экрана стены
                beq     3ret$
                mov     #3, R5
                mov     #WallSpr, R0

1$:             dec     R1
                mov     R1, R4
                bit     #76, R1
                beq     3ret$
                mov     #WallSprSize, R2

2$:             movb    (R0)+, (R4)
                add     #100, R4
                sob     R2, 2$
                add     #60, R0
                sob     R5, 1$

3ret$:          return
; End of function RestoreWall


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

; Стереть с экрана номер текущего этапа, если время пришло
; и Вкл/выкл звук

sub_31616:      tst     StgDrawDelay  ; Время вывода на экран номера текущего этапа
                beq     3$
                dec     StgDrawDelay  ; Время вывода на экран номера текущего этапа
                bne     3$
                mov     #62233, R1
                mov     #16, R2

1$:             mov     #14, R3

2$:             clrb    (R1)+
                sob     R3, 2$
                add     #64, R1
                sob     R2, 1$

3$:             ;jmp     SwitchSound   ; Вкл/выкл звука
; End of function sub_31616


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

; Вкл/выкл звука

SwitchSound:    mov     #SoundSub, R1
                mov     @#177662, R0    ; Код нажатого символа
                cmp     #14, R0         ; это СБР?
                bne     1$              ; нет
                mov     #400, R3        ; да - выключим звук
                mov     #2, R2
                call    @(R1)+          ; Вход: R2 - длительность звука БИП
                                        ;       R3 - частота звука
                mov     #NoSound, -(R1) ; меняем адрес п/п звука
0$:             return
; ───────────────────────────────────────────────────────────────────────────

1$:             cmp     #1, R0          ; это ПОВТ?
                bne     2ss$            ; нет
                cmp     #NoSound, (R1)  ; да, звук был выключен?
                bne     0$              ; нет, работал
                mov     #300, R3        ; включим звук
                mov     #4, R2
                call    @SndSubAddr$+2

SndSubAddr$:    mov     #102062, (R1)   ; Вход: R2 - длительность звука БИП
                                        ;       R3 - частота звука
                return
; End of function SwitchSound

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

2ss$:           bit     @#177716, #100  ; клавиша нажата?
                bne     9$              ; нет
                tst     (PC)+           ; да, а клавишу уже нажимали?
CtrlKeyPressFlag:.word 0                ; Флаг нажатия управляющих клавиш 0 и 1
                                        ; Чтобы многократной обработки нажатия не происходило
                bne     3$              ; да - выход
                com     CtrlKeyPressFlag ; нет - отметим, что нажали
                mov     #Score, R1
                cmp     #'1, R0         ; это "1"?
                bne     7$              ; нет
; да - увеличиваем жизнь на 1 за счёт очков
                mov     #Lives, R0
                cmp     (R0), #8.       ; жизней и так дохрена?
                bgt     9$              ; да, игнорируем
                tst     (R1)+           ; очки есть?
                bne     5$              ; да, много
                cmpb    #2, (R1)        ; нет, а хотя бы 2000 есть?
                bgt     9$              ; нету, тогда значит нет

5$:             call    Minus1kScores   ; Минус 1000 очков
                call    Minus1kScores   ; Минус 1000 очков
                add     LivesIncDec, (R0) ; увеличиваем число жизней
                mov     (R0), R0        ; количество жизней
                mov     #43015, R1
                br      6$
; ───────────────────────────────────────────────────────────────────────────

7$:             cmp     #'0, R0         ; это "0"?
                bne     9$              ; нет
; да - покупаем бомбы за счёт очков
                mov     #Bombs, R0
                cmp     (R0), #8.       ; если уже и так много бомб
                bgt     9$              ; то игнорируем
                tst     (R1)+           ; очки есть?
                bne     8$              ; да, много
                tstb    (R1)            ; нет, а хотя бы тысяча?
                beq     9$              ; тоже нет, значит нет

8$:             call    Minus1kScores   ; Минус 1000 очков
                inc     (R0)
                mov     (R0), R0
                mov     #44447, R1
6$:             movb    SegmDigits(R0), R0
                call    DrawSegmDigit   ; Вывод на экран цифры из сегментов
                                        ; Вход: R0 - код цифры (набор сегментов)
                jmp     DrawScore       ; Вывод счёта
; ───────────────────────────────────────────────────────────────────────────

9$:             clr     CtrlKeyPressFlag ; сбросим флаг
3$:             return
; END OF FUNCTION CHUNK FOR sub_31616

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

; Минус 1000 очков

Minus1kScores:  mov     #Score+3, R1

1$:             decb    -(R1)
                bpl     2$
                movb    #9., (R1)
                br      1$
; ───────────────────────────────────────────────────────────────────────────

2$:             return
; End of function Minus1kScores



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

; Прорисовка поверхности
; И отображение текущего этапа

ShowCurrStage:  call    DrawGround$4    ; Выключение анимации приседания
                                        ; Очистка рабочей области экрана
                                        ; Прорисовка поверхности
                                        ; Очистка буферов динамических элементов
                mov     (PC)+, (PC)+    ; инициализируем таймер отображения номера этапа на экране
                .word 70
StgDrawDelay:   .word 0                 ; Время вывода на экран номера текущего этапа

                mov     #62233, R1      ; и отображаем
; End of function ShowCurrStage


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

; Вывод текущего этапа "Этап n"

sub_31554:      mov     #240, R4
                mov     #1, R5          ; масштаб х2
                mov     #StrStage, R2   ; адрес зашифрованной строки
                clr     R0
                call    DrawString      ; Вывод строки
                                        ; Вход: R1 - адрес экрана
                                        ;       R2 - адрес строки
                                        ;       R0 - начальное значение аккумулятора кодов расшифрованных символов
                                        ;       R5 - масштаб по вертикали
PrintStage:     mov     (PC)+, R0
Stage:          .word 1                 ; Текущий этап

                jmp     DrawChar        ; Вывод символа
                                        ; Вход: R0 - код символа
                                        ;       R1 - адрес экрана
                                        ;       R4 - маска цвета символа
                                        ;       R5 - масштаб, 0 - нет
; End of function sub_31554


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

; Проверка на границы этапа
; Запрет двигаться назад, и проверка на конец этапа

CheckStageBounds:
                cmp     #61, Progress   ; если прогресс > 61
                blt     MaxProgress     ; переход
                tst     HorizMovOffset  ; иначе, движение есть?
                bpl     MaxProgress     ; влево - переход
                clr     HorizMovOffset  ; а вправо - запретим

MaxProgress:    cmp     #0, Progress    ; до конца этапа дошли?
                bgt     1$              ; нет - выход
                ; да - формируем конец этапа
                mov     #GameTopStack, SP
                jmp     EndStage

1$:             return
; End of function CheckStageBounds


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

; Сюда попадаем при окончании этапа

EndStage:       add     #100, Progress
                call    DrawGround      ; Очистка рабочей области экрана
                                        ; Прорисовка поверхности
                                        ; Очистка буферов динамических элементов
                mov     #TextEndStage, R2
                mov     #62220, R1
                mov     #1, R5
                clr     R0
                mov     #100, R4
                call    DrawString      ; Вывод строки
                                        ; Вход: R1 - адрес экрана
                                        ;       R2 - адрес строки
                                        ;       R0 - начальное значение аккумулятора кодов расшифрованных символов
                                        ;       R5 - масштаб по вертикали
                call    PrintStage      ; Вывод символа
                cmp     R0, #6          ; сейчас прошли 6-й этап?
                beq     7EndGame$       ; да - конец игры
                mov     #64427, R1      ; иначе - выводим
                clr     R0
                call    DrawString      ; Вывод строки
                                        ; Вход: R1 - адрес экрана
                                        ;       R2 - адрес строки
                                        ;       R0 - начальное значение аккумулятора кодов расшифрованных символов
                                        ;       R5 - масштаб по вертикали
                cmp     Stage, #1       ; Текущий этап
                beq     1$
                add     #5, R2

1$:             call    DrawString      ; Вывод строки
                                        ; Вход: R1 - адрес экрана
                                        ;       R2 - адрес строки
                                        ;       R0 - начальное значение аккумулятора кодов расшифрованных символов
                                        ;       R5 - масштаб по вертикали
                mov     #StolbDrawTbl, R1 ; CurrentStageData ; подготавливаем данные для следующего этапа
                mov     #<StageSizeW*6>, R2 ; общий размер массива данных всех этапов, 220 * 6

2$:             mov     StageSize(R1), (R1)+  ; сдвигаем данные этапов влево, в смысле, следующий на место предыдущего
                sob     R2, 2$
                ; и после этого увеличиваем номер этапа

3$:             inc     Stage           ; Увеличиваем текущий этап
                mov     #SndParam5, R4
                call    PlaySound
                call    Pranyk
                mov     #Score+2, R5
                call    AddScore$       ; + 10000 к счёту
                mov     #SndParam6, R4
                call    PlaySound
                jmp     ContinueGame$   ; переход на следующий уровень

7EndGame$:      call    Pranyk
                jmp     GameFinish$
; End of function EndStage

Pranyk:
4$:             bit     #100, @#177716  ; ждём, пока отпустят клавишу или джойстик
                beq     4$
                tst     @#177714
                bne     4$

                sob     R0, .
                sob     R0, .

5$:             bit     #100, @#177716
                beq     6$
                tst     @#177714
                beq     5$

6$:             return


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


PlaySound:      mov     (R4)+, R5

1$:             mov     (R4)+, R3
                beq     2$
                mov     R5, R2
                call    @SoundSub       ; Вход: R2 - длительность звука БИП
                                        ;       R3 - частота звука
                br      1$
; ───────────────────────────────────────────────────────────────────────────

2$:             return
; End of function PlaySound




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

; Вывод названия и этапа

sub_32710:      mov     #27, R5
; берётся кусок экрана с названием из игровой панели
; и красиво выводится
                mov     #61527, R1

1$:             mov     R1, R4
                mov     #43054, R0

2$:             mov     #22, R2

3$:             movb    (R0)+, (R4)
                bicb    #125, (R4)+
                sob     R2, 3$
                add     #56, R4
                add     #56, R0
                cmp     #45300, R0
                bge     4$
                sub     #100, R0

4$:             cmp     #61600, R4
                bge     2$
                sub     #100, R1
                mov     R1, -(SP)
                mov     R5, -(SP)
                clr     0Scale$
                mov     #27, R3
                mov     #1, R5
                mov     #61526, R0
                mov     #62726, R1

5$:             mov     R5, R4

6$:             mov     #12, R2

7$:             mov     (R0)+, (R1)+
                sob     R2, 7$
                add     #54, R1
                sub     #24, R0
                sob     R4, 6$
                tst     (PC)+
0Scale$:        .word 0
                bne     8$
                mov     #7, 0Scale$
                inc     R5

8$:             dec     0Scale$
                sub     #100, R0
                sob     R3, 5$
                mov     (SP)+, R5
                mov     (SP)+, R1
                sob     R5, 1$
                mov     #64006, R1      ; адрес экрана
                call    sub_31554       ; Вывод текущего этапа "Этап n"
                clr     R0
                mov     #Text2, R2
                mov     #64060, R1
                call    DrawString      ; Вывод строки
                                        ; Вход: R1 - адрес экрана
                                        ;       R2 - адрес строки
                                        ;       R0 - начальное значение аккумулятора кодов расшифрованных символов
                                        ;       R5 - масштаб по вертикали
                return
; End of function sub_32710


; ───────────────────────────────────────────────────────────────────────────
SndParam:       .word 10
                .word 1000
                .word 100
                .word 1000
                .word 300
                .word 1000
                .word 500
                .word 0
SndParam2:      .word 10
                .word 1000
                .word 400
                .word 600
                .word 500
                .word 200
                .word 600
                .word 0
SndParam3:      .word 4
                .word 600
                .word 2000
                .word 3000
                .word 0
                .word 6
                .word 2000
                .word 1400
                .word 1000
                .word 0
SndParam4:      .word 6
                .word 30
                .word 60
                .word 30
                .word 0
SndParam5:      .word 20
                .word 400
                .word 200
                .word 300
                .word 400
                .word 1000
                .word 1400
                .word 0
SndParam6:      .word 10
                .word 400
                .word 200
                .word 100
                .word 40
                .word 0

; ───────────────────────────────────────────────────────────────────────────
; Зашифрованный текст.
; каждый следующий код - разница от предыдущего
; да ещё и все +1
Text2:          .asciz  "SOUND"<12><262>
                .asciz  <201>"ON"
                .asciz  "OFF"
; ───────────────────────────────────────────────────────────────────────────
StrStage:       .asciz  "ЭТАП "
; ───────────────────────────────────────────────────────────────────────────
TextEndStage:   .asciz "ВЫ ПРОШЛИ ЭТАП "
                .asciz "КОД: "
                .asciz "7316"
                .asciz "4891"
; ───────────────────────────────────────────────────────────────────────────
; Текст для задания управления
Text3:          .asciz "ВЫБОР УПРАВЛЕНИЯ"<12><12><12><12><234>"ЛЕВО"
                .asciz <12><233>"ПРАВО"
                .asciz <12><233>"ВВЕРХ"
                .asciz <12><234>"ВНИЗ"
                .asciz <12><233>"ОГОНЬ"
                .asciz <12><233>"ВЗРЫВ"

; ───────────────────────────────────────────────────────────────────────────
; текст бейсика при скрытии игры
BasText:        .asciz "CAGLRCCC.R"
                .asciz "ЛАТ"
                .asciz "Ok"
                .asciz "AUTO 260"
                .asciz "260 CLS"
                .asciz "270 "
BasTextEnd:
.SCRIPT "Text Encode"
    mov #BasText, R1
2$: movb (R1), R0
    beq 1$
    bpl 3$
    sub #40, R0
3$: sub #20, R0
1$: movb R0, (R1)+
    cmp R1, #BasTextEnd
    blo 2$
.ENDS
                .even
; ───────────────────────────────────────────────────────────────────────────
BlowSpr1:       .word ^B0000000000110000
                .word ^B1100110000000000
                .word ^B0000001100000011
                .word ^B0000001100111100
                .word ^B1111110011000000
                .word ^B0011001111110000
                .word ^B0000111111000011
                .word ^B1100110011110000
                .word ^B0011001100000000
                .word ^B0000001100001100
                .word ^B0011000011000011
                .word ^B0000000000000000
                .word ^B0011000000110000

BlowSpr2:       .word ^B0000000000000000
                .word ^B0000000000000000
                .word ^B0000001100110000
                .word ^B0000000011000011
                .word ^B1100111100111100
                .word ^B0011110011110011
                .word ^B0000111100111100
                .word ^B0011110011110000
                .word ^B1100001100000011
                .word ^B0000000011000000
                .word ^B0000000000000000
                .word ^B0000000000000000
                .word ^B0000000000000000

BlowSpr3:       .word ^B0000000000000000
                .word ^B0000000000000000
                .word ^B0000000000000000
                .word ^B0000000000000000
                .word ^B0011000011001100
                .word ^B0000001111110000
                .word ^B0000001111111100
                .word ^B0000110011000000
                .word ^B0000000000000000
                .word ^B0000000000000000
                .word ^B0000000000000000
                .word ^B0000000000000000
                .word ^B0000000000000000
BlowSprEnd:
BlowSprSize = BlowSpr2 - BlowSpr1

; ───────────────────────────────────────────────────────────────────────────
WormParticleSpr:.byte 1, 5              ; ширина, высота
                .byte ^B01000100
                .byte ^B01010100
                .byte ^B00010000
                .byte ^B01010100
                .byte ^B01000100
                .byte  0
; ───────────────────────────────────────────────────────────────────────────
TrtlParticleSpr:.byte 1, 5
                .byte ^B00010100
                .byte ^B01010101
                .byte ^B01010101
                .byte ^B01010101
                .byte ^B00010100
                .byte 0
; ───────────────────────────────────────────────────────────────────────────
SnakParticleSpr:.byte 1, 4
                .byte ^B00111100
                .byte ^B11001111
                .byte ^B11001111
                .byte ^B11111100
FrogParticleSpr:.byte 2, 6
                .word ^B0000000011111100
                .word ^B0000001111111111
                .word ^B0000111111111111
                .word ^B0011110000001111
                .word ^B0011111100001111
                .word ^B0000111111111100
; ───────────────────────────────────────────────────────────────────────────
; осколки от мухи при её подбитии
FlyParticle:    .byte 2, 12
                .word ^B000010101000000
                .word ^B001010101010000
                .word ^B001000101010000
                .word ^B001010000010100
                .word ^B100010101000101
                .word ^B101010101000101
                .word ^B001010101010100
                .word ^B101010001010100
                .word ^B001010100010000
                .word ^B000010100000000
; ───────────────────────────────────────────────────────────────────────────
GGParticleSpr:  .byte 2, 6
                .word ^B1100000000000000
                .word ^B1100000000000000
                .word ^B0011000000001111
                .word ^B0011000011111100
                .word ^B0000111111000000
                .word ^B1111110000000000
; ───────────────────────────────────────────────────────────────────────────
SporeSpr:       .byte 1, 5
                .byte ^B00111100
                .byte ^B11111111
                .byte ^B11111111
                .byte ^B11111111
                .byte ^B00111100
                .byte ^B00000000
; ───────────────────────────────────────────────────────────────────────────
NullSpr:        .byte 1, 1
; ───────────────────────────────────────────────────────────────────────────
LavaBallSpr:    .word ^B0000000111000000
                .word ^B0011011101110100
                .word ^B0001110111011100
                .word ^B0111011101110111
                .word ^B1101110111011101
                .word ^B0111011101110111
                .word ^B0001110111011100
                .word ^B0011011101110100
                .word ^B0000000111000000
; ───────────────────────────────────────────────────────────────────────────
; Это спрайты
; Формат такой.
; .byte ширина в столбцах
; {.byte высота столбца
;   {.byte данные}высота
; }ширина
WormSpr1:       .byte 6
                .byte 4
                .byte 160, 334, 164, 320
                .byte 7
                .byte 167, 335, 167, 335, 167, 334, 100
                .byte 7
                .byte 3, 334, 167, 335, 167, 335, 67
                .byte 7
                .byte 164, 335, 367, 375, 67, 301, 300
                .byte 8.
                .byte 377, 377, 377, 300, 303, 3, 77, 317
                .byte 8.
                .byte 17, 60, 77, 77, 0, 0, 17, 3
wormSpr2:       .byte 5
                .byte 5
                .byte 320, 164, 334, 160, 300
                .byte 10.
                .byte 35, 167, 35, 67, 35, 67, 35, 164, 334, 160
                .byte 10.
                .byte 360, 364, 375, 367, 75, 307, 315, 67, 15, 3
                .byte 8.
                .byte 377, 377, 377, 300, 303, 3, 77, 317
                .byte 8.
                .byte 17, 60, 77, 77, 0, 0, 17, 3
                .byte 0
; ───────────────────────────────────────────────────────────────────────────
TurtleSpr1:     .byte 6
                .byte 17.
                .byte 0, 0, 0, 0, 0, 0, 0, 300, 60, 60, 360, 300, 0, 0
                .byte 0, 360, 300
                .byte 17.
                .byte 0, 0, 0, 0, 374, 74, 360, 77, 360, 360, 377, 377
                .byte 3, 300, 303, 374, 363
                .byte 16.
                .byte 314, 377, 77, 317, 374, 3, 124, 123, 114, 103, 14
                .byte 3, 14, 0, 3, 3
                .byte 12.
                .byte 14, 317, 3, 124, 24, 125, 21, 105, 104, 5, 121, 124
                .byte 11.
                .byte 60, 374, 374, 361, 361, 4, 125, 121, 121, 25, 4
                .byte 7
                .byte 63, 377, 63, 14, 3, 0, 1
                .byte 0
TurtleSpr2:     .byte 5
                .byte 17.
                .byte 0, 0, 0, 0, 300, 300, 0, 360, 374, 3, 377, 374, 60
                .byte 0, 60, 317, 74
                .byte 17.
                .byte 63, 377, 74, 360, 317, 63, 117, 63, 317, 77, 317
                .byte 77, 300, 14, 74, 77, 17
                .byte 12.
                .byte 3, 317, 17, 114, 117, 20, 25, 125, 104, 124, 20
                .byte 100
                .byte 12.
                .byte 60, 363, 300, 25, 21, 105, 121, 24, 24, 120, 105
                .byte 5
                .byte 10.
                .byte 63, 377, 363, 317, 377, 0, 25, 5, 5, 1
; ───────────────────────────────────────────────────────────────────────────
FlySprL2R1:     .byte 6
                .byte 18.
                .byte 300, 20, 160, 300, 0, 360, 374, 374, 374, 314, 314
                .byte 60, 300, 0, 0, 100, 0, 100
                .byte 21.
                .byte 1, 314, 307, 315, 3, 360, 374, 374, 374, 314, 314
                .byte 74, 363, 0, 21, 104, 21, 104, 21, 104, 20
                .byte 21.
                .byte 3, 303, 303, 300, 300, 317, 77, 77, 77, 77, 77, 17
                .byte 103, 24, 121, 4, 21, 4, 21, 4, 1
                .byte 17.
                .byte 0, 300, 303, 3, 343, 263, 354, 273, 356, 273, 16
                .byte 20, 104, 21, 104, 20, 100
                .byte 19.
                .byte 0, 300, 303, 300, 302, 313, 362, 74, 302, 273, 0
                .byte 21, 104, 21, 104, 21, 104, 21, 104
                .byte 18.
                .byte 0, 0, 3, 3, 3, 0, 0, 3, 2, 3, 2, 0, 0, 1, 4, 1, 4
                .byte 1
                .byte 0
FlySprL2R2:     .byte 6
                .byte 16.
                .byte 160, 4, 334, 160, 300, 60, 374, 374, 374, 314, 314
                .byte 60, 300, 0, 0, 100
                .byte 18.
                .byte 0, 303, 301, 307, 1, 360, 374, 374, 374, 314, 314
                .byte 74, 363, 0, 21, 104, 21, 104
                .byte 17.
                .byte 3, 303, 303, 300, 300, 317, 77, 77, 77, 77, 77, 17
                .byte 103, 24, 121, 4, 1
                .byte 16.
                .byte 0, 300, 303, 3, 263, 343, 270, 356, 273, 356, 273
                .byte 56, 100, 21, 100, 25
                .byte 15.
                .byte 0, 300, 303, 300, 303, 316, 363, 74, 203, 356, 273
                .byte 0, 104, 21, 104
                .byte 14.
                .byte 0, 0, 3, 3, 3, 0, 0, 2, 3, 2, 3, 0, 4, 21
                .byte 0
; ───────────────────────────────────────────────────────────────────────────
FlySprR2L1:     .byte 6
                .byte 18.
                .byte 0, 0, 300, 300, 300, 0, 0, 200, 300, 200, 300, 0
                .byte 0, 100, 20, 100, 20, 100
                .byte 19.
                .byte 0, 3, 303, 3, 303, 263, 317, 74, 302, 273, 0, 104
                .byte 21, 104, 21, 104, 21, 104, 21
                .byte 17.
                .byte 0, 3, 303, 300, 316, 313, 56, 273, 356, 273, 340
                .byte 4, 21, 104, 21, 4, 1
                .byte 21.
                .byte 300, 303, 303, 3, 3, 363, 374, 374, 374, 374, 374
                .byte 360, 301, 24, 105, 20, 104, 20, 104, 20, 100
                .byte 21.
                .byte 100, 63, 323, 163, 300, 17, 77, 77, 77, 63, 63, 74
                .byte 317, 0, 104, 21, 104, 21, 104, 21, 4
                .byte 18.
                .byte 3, 4, 15, 3, 0, 17, 77, 77, 77, 63, 63, 14, 3, 0
                .byte 0, 1, 0, 1
                .byte 0
FlySprR2L2:     .byte 6
                .byte 14.
                .byte 0, 0, 300, 300, 300, 0, 0, 200, 300, 200, 300, 0
                .byte 20, 104
                .byte 15.
                .byte 0, 3, 303, 3, 303, 263, 317, 74, 302, 273, 356, 0
                .byte 21, 104, 21
                .byte 16.
                .byte 0, 3, 303, 300, 316, 313, 56, 273, 356, 273, 356
                .byte 270, 1, 104, 1, 124
                .byte 17.
                .byte 300, 303, 303, 3, 3, 363, 374, 374, 374, 374, 374
                .byte 360, 301, 24, 105, 20, 100
                .byte 18.
                .byte 0, 303, 103, 323, 100, 17, 77, 77, 77, 63, 63, 74
                .byte 317, 0, 104, 21, 104, 21
                .byte 16.
                .byte 15, 20, 67, 15, 3, 14, 77, 77, 77, 63, 63, 14, 3
                .byte 0, 0, 1
                .byte 3
; ───────────────────────────────────────────────────────────────────────────
FrogSpr1:       .byte 5
                .byte 22.
                .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 360, 300, 300, 74, 360
                .byte 360, 300, 300, 20, 120, 120, 0, 300
                .byte 22.
                .byte 0, 0, 0, 0, 200, 340, 60, 40, 60, 3, 77, 300, 0
                .byte 377, 377, 17, 123, 104, 124, 24, 300, 363
                .byte 21.
                .byte 0, 0, 270, 300, 54, 10, 60, 40, 60, 10, 316, 273
                .byte 357, 277, 357, 77, 54, 1, 0, 3, 3
                .byte 17.
                .byte 0, 273, 300, 56, 260, 40, 70, 216, 313, 200, 16
                .byte 73, 356, 273, 356, 273, 356
                .byte 17.
                .byte 0, 73, 356, 260, 54, 13, 56, 73, 356, 273, 356, 273
                .byte 356, 73, 56, 13, 2
                .byte 0
FrogSpr2:       .byte 5
                .byte 16.
                .byte 0, 300, 0, 0, 0, 300, 74, 360, 360, 300, 300, 20
                .byte 120, 120, 0, 300
                .byte 16.
                .byte 260, 302, 3, 10, 0, 377, 300, 377, 377, 17, 123
                .byte 104, 124, 24, 300, 363
                .byte 15.
                .byte 354, 0, 2, 14, 40, 270, 357, 277, 357, 77, 54, 1
                .byte 0, 3, 3
                .byte 12.
                .byte 356, 200, 356, 70, 354, 263, 316, 73, 356, 273, 356
                .byte 260
                .byte 12.
                .byte 16, 73, 356, 60, 16, 73, 356, 270, 356, 273, 56
                .byte 3
                .byte 0
; ───────────────────────────────────────────────────────────────────────────
SnakeSpr1:      .byte 4
                .byte 21.
                .byte 104, 21, 104, 121, 124, 100, 0, 100, 20, 100, 120
                .byte 100, 100, 0, 0, 360, 374, 377, 74, 300, 300
                .byte 22.
                .byte 104, 121, 125, 125, 25, 101, 104, 124, 25, 1, 1
                .byte 5, 5, 25, 377, 77, 377, 300, 3, 3, 77, 17
                .byte 22.
                .byte 124, 125, 25, 125, 125, 124, 25, 1, 0, 0, 0, 0, 0
                .byte 0, 377, 374, 377, 300, 3, 3, 77, 17
                .byte 17.
                .byte 25, 125, 125, 24, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                .byte 3, 3
                .byte 77
SnakeSpr2:      .byte 6
                .byte 5
                .byte 100, 20, 100, 20, 100
                .byte 6
                .byte 104, 21, 124, 125, 125, 124
                .byte 18.
                .byte 104, 125, 125, 124, 120, 124, 120, 125, 24, 25, 120
                .byte 124, 120, 100, 0, 300, 360, 300
                .byte 21.
                .byte 125, 125, 125, 124, 121, 1, 0, 0, 0, 0, 0, 1, 305
                .byte 361, 77, 377, 17, 63, 74, 374, 360
                .byte 21.
                .byte 1, 5, 5, 1, 0, 0, 0, 0, 0, 0, 0, 377, 0, 0, 0, 377
                .byte 14, 60, 60, 363, 360
                .byte 20.
                .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 14, 74, 77
                .byte 14, 0, 0, 3
; ───────────────────────────────────────────────────────────────────────────
HolmSpr:        .byte 7
                .byte 6
                .byte 242, 252, 242, 210
                .byte 40, 200
                .byte 9.
                .byte 242, 52, 252, 252
                .byte 252, 250, 242, 210
                .byte 240
                .byte 11.
                .byte 242, 252, 212, 250
                .byte 252, 252, 252, 252
                .byte 250, 212, 240
                .byte 12.
                .byte 242, 252, 252, 252
                .byte 212, 252, 210, 252
                .byte 212, 252, 210, 252
                .byte 11.
                .byte 242, 252, 50, 212
                .byte 50, 212, 42, 210
                .byte 42, 10, 2
                .byte 7
                .byte 242, 212, 42, 210
                .byte 42, 10, 2
                .byte 3
                .byte 242, 210, 42
                .byte 252
; ───────────────────────────────────────────────────────────────────────────
StolbSpr:       .byte 4
                .byte 10.
                .byte 212, 250, 212, 242
                .byte 250, 50, 210, 240
                .byte 40, 200
                .byte 32.
                .byte 242, 252, 212, 52
                .byte 252, 252, 252, 252
                .byte 212, 242, 50, 202
                .byte 52, 252, 250, 252
                .byte 242, 252, 250, 252
                .byte 242, 252, 250, 252
                .byte 252, 242, 250, 250
                .byte 240, 50, 240, 200
                .byte 32.
                .byte 52, 242, 212, 242
                .byte 252, 212, 250, 212
                .byte 42, 210, 52, 202
                .byte 50, 212, 252, 212
                .byte 52, 212, 242, 212
                .byte 42, 212, 242, 210
                .byte 42, 210, 52, 42
                .byte 10, 42, 10, 2
                .byte 10.
                .byte 252, 42, 252, 210
                .byte 42, 10, 42, 10
                .byte 12, 2
                .byte  242
; ───────────────────────────────────────────────────────────────────────────
VulkanSpr:      .byte 5
                .byte 8.
                .byte 252, 242, 252, 242, 250, 210, 240, 200
                .byte 21.
                .byte 252, 252, 252, 252, 210, 252, 210, 242, 10, 242
                .byte 250, 252, 242, 252, 250, 212, 210, 42, 2, 50, 200
                .byte 20.
                .byte 252, 252, 242, 212, 210, 242, 242, 250, 212, 242
                .byte 52, 202, 52, 252, 252, 42, 212, 2, 200, 242
                .byte 21.
                .byte 52, 252, 212, 242, 252, 212, 250, 212, 42, 210, 52
                .byte 202, 50, 212, 250, 212, 242, 50, 200, 50, 2
                .byte 10.
                .byte 252, 42, 252, 210, 42, 10, 42, 10, 12, 2
; ───────────────────────────────────────────────────────────────────────────
; Массив сжатых спрайтов анимации ходьбы человечка
; размер одного спрайта - 100. байтов
PackedSprMovAnmSize = 100.
; их тут 4 штуки
PackedSprMovAnm:.byte 0, 0, 0, 340, 3
                .byte 200, 101, 0, 4, 12
                .byte 40, 240, 0, 42, 4
                .byte 40, 74, 0, 52, 1
                .byte 300, 77, 0, 330, 3
                .byte 100, 43, 200, 347, 1
                .byte 360, 300, 101, 337, 56
                .byte 346, 163, 346, 376, 157
                .byte 237, 377, 366, 165, 47
                .byte 317, 210, 140, 374, 157
                .byte 336, 177, 354, 371, 327
                .byte 274, 63, 205, 303, 140
                .byte 140, 63, 0, 357, 1
                .byte 160, 53, 0, 164, 3
                .byte 0, 67, 0, 150, 3
                .byte 200, 27, 0, 360, 0
                .byte 100, 27, 0, 52, 141
                .byte 20, 45, 11, 121, 214
                .byte 220, 150, 4, 11, 53
                .byte 240, 20, 1, 26, 16
                .byte 0, 76, 0, 30, 4
                .byte 100, 240, 0, 2, 12
                .byte 40, 102, 0, 302, 3
                .byte 240, 22, 0, 374, 3
                .byte 200, 75, 0, 60, 2
                .byte 100, 36, 0, 27, 0
                .byte 366, 336, 361, 336, 56
                .byte 317, 363, 362, 376, 57
                .byte 255, 177, 142, 166, 33
                .byte 332, 110, 340, 375, 27
                .byte 54, 77, 203, 366, 73
                .byte 170, 223, 1, 303, 0
                .byte 200, 61, 0, 370, 1
                .byte 200, 53, 0, 174, 7
                .byte 300, 367, 0, 150, 37
                .byte 200, 267, 1, 160, 34
                .byte 0, 211, 0, 210, 6
                .byte 200, 24, 0, 110, 2
                .byte 200, 52, 0, 10, 1
                .byte 0, 41, 0, 340, 3
                .byte 0, 0, 0, 340, 3
                .byte 200, 101, 0, 4, 12
                .byte 40, 240, 0, 42, 4
                .byte 40, 74, 0, 52, 1
                .byte 300, 77, 0, 330, 3
                .byte 100, 43, 0, 347, 1
                .byte 370, 100, 0, 337, 16
                .byte 344, 163, 140, 376, 17
                .byte 116, 377, 340, 355, 16
                .byte 236, 21, 340, 340, 6
                .byte 366, 57, 300, 317, 2
                .byte 30, 121, 0, 344, 10
                .byte 300, 261, 1, 370, 31
                .byte 200, 253, 0, 174, 3
                .byte 300, 67, 0, 174, 7
                .byte 100, 167, 0, 170, 2
                .byte 300, 63, 6, 52, 127
                .byte 20, 361, 204, 10, 42
                .byte 104, 40, 102, 10, 24
                .byte 10, 301, 0, 37, 0
                .byte 0, 76, 0, 30, 4
                .byte 100, 240, 0, 2, 12
                .byte 40, 102, 0, 302, 3
                .byte 240, 22, 0, 374, 3
                .byte 200, 75, 0, 60, 2
                .byte 100, 36, 0, 27, 0
                .byte 366, 336, 361, 336, 56
                .byte 317, 363, 362, 376, 57
                .byte 255, 177, 142, 166, 33
                .byte 332, 110, 340, 375, 27
                .byte 54, 77, 203, 366, 73
                .byte 170, 223, 1, 303, 0
                .byte 340, 53, 0, 176, 0
                .byte 300, 17, 0, 140, 0
                .byte 200, 13, 0, 244, 0
                .byte 40, 5, 0, 111, 0
                .byte 20, 3, 0, 103, 0
                .byte 300, 7, 0, 62, 0
                .byte 40, 14, 0, 16, 1
                .byte 0, 37, 0, 0, 0
PackedSprMovAnmEnd:
; ───────────────────────────────────────────────────────────────────────────
JumpRight:      .byte 30                ; высота в строках
                .byte 6                 ; ширина в байтах, каждый бит спрайта удваивается
                .byte 0, 0, 174         ; прыжок вправо, присяд.
                .byte 0, 0, 203
                .byte 0, 260, 100
                .byte 0, 147, 100
                .byte 340, 117, 204
                .byte 370, 135, 170
                .byte 70, 36, 45
                .byte 160, 74, 177
                .byte 0, 275, 76
                .byte 300, 233, 35
                .byte 340, 147, 1
                .byte 320, 377, 0
                .byte 250, 167, 0
                .byte 34, 3, 0
                .byte 376, 30, 0
                .byte 376, 63, 0
                .byte 234, 67, 0
                .byte 340, 67, 0
                .byte 310, 33, 0
                .byte 204, 21, 0
                .byte 302, 10, 0
                .byte 62, 61, 0
                .byte 104, 106, 0
                .byte 70, 70, 0
                .byte 50
                .byte 6
                .byte 0, 0, 104         ; прыжок вправо, полёт
                .byte 0, 0, 42
                .byte 0, 0, 156
                .byte 0, 0, 144
                .byte 0, 0, 144
                .byte 0, 0, 64
                .byte 0, 0, 43
                .byte 0, 300, 64
                .byte 0, 40, 70
                .byte 0, 40, 74
                .byte 0, 220, 36
                .byte 0, 120, 37
                .byte 0, 220, 13
                .byte 0, 200, 7
                .byte 0, 320, 7
                .byte 0, 330, 3
                .byte 0, 274, 1
                .byte 0, 176, 0
                .byte 0, 376, 1
                .byte 0, 357, 1
                .byte 0, 357, 0
                .byte 200, 37, 0
                .byte 200, 77, 0
                .byte 100, 37, 0
                .byte 240, 6, 0
                .byte 140, 3, 0
                .byte 360, 0, 0
                .byte 360, 3, 0
                .byte 340, 5, 0
                .byte 340, 4, 0
                .byte 320, 4, 0
                .byte 174, 2, 0
                .byte 162, 3, 0
                .byte 61, 1, 0
                .byte 311, 0, 0
                .byte 45, 0, 0
                .byte 45, 0, 0
                .byte 51, 0, 0
                .byte 25, 0, 0
                .byte 2, 0, 0
                .byte 50
                .byte 6
                .byte 0, 0, 0           ; прыжок вправо, приземление
                .byte 0, 0, 72
                .byte 0, 0, 175
                .byte 0, 0, 173
                .byte 0, 0, 173
                .byte 0, 0, 70
                .byte 0, 76, 35
                .byte 0, 101, 35
                .byte 0, 201, 16
                .byte 200, 62, 17
                .byte 200, 330, 7
                .byte 200, 364, 3
                .byte 0, 371, 1
                .byte 0, 276, 0
                .byte 0, 177, 0
                .byte 300, 76, 0
                .byte 340, 136, 0
                .byte 360, 106, 0
                .byte 360, 71, 0
                .byte 370, 37, 0
                .byte 170, 7, 0
                .byte 374, 0, 0
                .byte 374, 3, 0
                .byte 375, 1, 0
                .byte 173, 0, 0
                .byte 207, 37, 0
                .byte 37, 74, 0
                .byte 357, 173, 0
                .byte 377, 167, 0
                .byte 376, 67, 0
                .byte 314, 31, 0
                .byte 340, 21, 0
                .byte 360, 10, 0
                .byte 110, 4, 0
                .byte 210, 30, 0
                .byte 304, 41, 0
                .byte 62, 176, 0
                .byte 102, 0, 0
                .byte 214, 0, 0
                .byte 160, 0, 0
; ───────────────────────────────────────────────────────────────────────────
CrouchRight:    .byte 40
                .byte 10
                .byte 0, 370, 0, 0      ; присяд для выстрела вправо
                .byte 0, 6, 1, 0
                .byte 0, 201, 2, 0
                .byte 200, 200, 242, 30
                .byte 200, 10, 161, 147
                .byte 200, 362, 310, 136
                .byte 0, 113, 50, 2
                .byte 200, 374, 340, 0
                .byte 300, 373, 360, 0
                .byte 340, 43, 170, 0
                .byte 340, 335, 37, 0
                .byte 360, 376, 7, 0
                .byte 360, 36, 3, 0
                .byte 370, 301, 0, 0
                .byte 370, 7, 0, 0
                .byte 370, 3, 0, 0
                .byte 364, 0, 0, 0
                .byte 14, 77, 0, 0
                .byte 76, 170, 0, 0
                .byte 336, 367, 0, 0
                .byte 376, 357, 0, 0
                .byte 374, 157, 0, 0
                .byte 230, 63, 0, 0
                .byte 300, 43, 0, 0
                .byte 340, 21, 0, 0
                .byte 220, 10, 0, 0
                .byte 20, 61, 0, 0
                .byte 210, 103, 0, 0
                .byte 144, 374, 0, 0
                .byte 204, 0, 0, 0
                .byte 30, 1, 0, 0
                .byte 340, 0, 0, 0
; ───────────────────────────────────────────────────────────────────────────
; три набора по 8 байтов,
; спрайты колышущейся воды (вверх ногами)
WaterWaveSpr:   .byte ^B00010101
                .byte ^B00010101
                .byte ^B00000100
                .byte ^B00000100
                .byte ^B00000000
                .byte ^B00000000
                .byte ^B00000000
                .byte ^B00000000

                .byte ^B01000101
                .byte ^B00000101
                .byte ^B00000001
                .byte ^B00000001
                .byte ^B00000000
                .byte ^B00000000
                .byte ^B00000000
                .byte ^B00000000

                .byte ^B01010101
                .byte ^B01010100
                .byte ^B01010000
                .byte ^B01010000
                .byte ^B01000000
                .byte ^B01000000
                .byte ^B00000000
                .byte ^B00000000
WaterWaveSprEnd:
; ───────────────────────────────────────────────────────────────────────────
; Массив данных 116 * 3
; это спрайты вертикальной стены
WallSprSize = 116
WallSpr:        .byte 3, 3, 17
                .byte 63, 17, 63
                .byte 317, 77, 316
                .byte 77, 314, 63
                .byte 317, 63, 14
                .byte 63, 14, 3
                .byte 17, 3, 14
                .byte 3, 3, 0
                .byte 0, 3, 3
                .byte 0, 0, 0
                .byte 0, 0, 0
                .byte 0, 0, 0
                .byte 0, 0, 3
                .byte 0, 2, 14
                .byte 3, 14, 63
                .byte 14, 42, 314
                .byte 42, 210, 62
                .byte 10, 42, 14
                .byte 2, 10, 3
                .byte 0, 0, 0
                .byte 0, 0, 0
                .byte 0, 0, 2
                .byte 10, 2, 12
                .byte 2, 10, 42
                .byte 10, 42, 42
                .byte 10, 42, 210
                .byte 42, 210, 42
                .byte 212, 42, 212
                .byte 50, 212, 42
                .byte 10, 42, 10
                .byte 12, 10, 2
                .byte 0, 0, 0
                .byte 0, 0, 0
                .byte 2, 0, 2
                .byte 0, 0, 0
                .byte 0, 0, 0
                .byte 0, 0, 242
                .byte 210, 212, 242
                .byte 250, 212, 252
                .byte 210, 52, 210
                .byte 42, 210, 42
                .byte 210, 0, 210
                .byte 377, 76, 354
                .byte 72, 216, 70
                .byte 376, 53, 354
                .byte 312, 356, 273
                .byte 342, 73, 356
                .byte 362, 273, 76
                .byte 363, 72, 263
                .byte 76, 362, 213
                .byte 370, 77, 56
                .byte 314, 76, 314
                .byte 56, 317, 76
                .byte 14, 77, 16
                .byte 54, 316, 77
                .byte 362, 73, 354
                .byte 272, 356, 270
                .byte 352, 54, 212
                .byte 352, 262, 53
                .byte 312, 256, 210
                .byte 52, 216, 52
                .byte 210, 42, 12
                .byte 12, 50, 12
                .byte 50, 212, 52
                .byte 212, 210, 52
                .byte 252, 212, 252
                .byte 210, 252, 52
                .byte 242, 252, 250
                .byte 212, 252, 252
                .byte 212, 52, 252
                .byte 252, 252, 42
                .byte 252, 42, 252
                .byte 212, 252, 210
                .byte 52, 12, 52
                .byte 10, 52, 212
                .byte 42, 252, 42
                .byte 212, 52, 212
                .byte 42, 10, 52
                .byte 12, 250, 52
                .byte 242, 252, 52
                .byte 252, 52, 240
                .byte 212, 252, 210
                .byte 252, 210, 42
                .byte 252, 10, 242
                .byte 252, 262, 252
                .byte 312, 252, 352
                .byte 252, 253, 252
                .byte 242, 52, 252
                .byte 252, 52, 272
                .byte 252, 242, 52
                .byte 272, 252, 252
                .byte 212, 272, 252
                .byte 252, 250, 312
                .byte 252, 352, 242
                .byte 352, 52, 356
                .byte 252, 252, 312
                .byte 252, 356, 252
                .byte 212, 252, 252
                .byte 50, 252, 252
                .byte 252, 212, 252
                .byte 252, 212, 252
                .byte 250, 252, 212
                .byte 252, 52, 252
                .byte 242, 252, 52
                .byte 252, 242, 252
                .byte 252, 52, 252
                .byte 242, 252, 252
                .byte 252, 52, 252
                .byte 252, 252, 242
                .byte 252, 252, 252
                .byte 252, 250, 252
                .byte 252, 52, 252
                .byte 252, 252, 212
                .byte 252, 252, 252
                .byte 50, 252, 252
                .byte 252, 212, 252
                .byte 252, 252, 252
                .byte 212, 252, 252
                .byte 52, 252, 252
                .byte 242, 252, 252
                .byte 252, 252, 250
                .byte 252, 252, 52
                .byte 252, 252, 252
                .byte 202, 252, 212
                .byte 252, 242, 252
                .byte 52, 212, 252
; тоже что-то со стеной связанное
byte_13470:     .byte 52
                .byte 252
                .byte 250
                .byte 42
                .byte 210
                .byte 42
                .byte 200
                .byte 42
                .byte 200
                .byte 42
                .byte 0
                .byte 200
                .byte 10
                .byte 200
                .byte 0
                .byte 10
                .byte 0
                .byte 0
                .byte 2
                .byte 2
                .byte 12
                .byte 12
                .byte 10
                .byte 52
                .byte 50
                .byte 42
                .byte 52
                .byte 240
                .byte 250
                .byte 240
                .byte 240
                .byte 202
; ───────────────────────────────────────────────────────────────────────────
PlanetSpr:      .byte 0, 0, 314, 14, 0, 0 ; размеры 6х30
                .byte 0, 300, 63, 63, 3, 0
                .byte 0, 360, 317, 314, 14, 0
                .byte 0, 374, 377, 63, 63, 0
                .byte 0, 377, 377, 317, 314, 0
                .byte 0, 377, 377, 77, 63, 0
                .byte 300, 377, 377, 377, 314, 0
                .byte 300, 377, 377, 77, 63, 3
                .byte 300, 377, 377, 377, 314, 0
                .byte 364, 377, 377, 377, 63, 23
                .byte 365, 377, 377, 377, 314, 134
                .byte 365, 377, 377, 377, 63, 123
                .byte 125, 377, 377, 377, 317, 125
                .byte 124, 125, 375, 177, 125, 25
                .byte 120, 125, 125, 125, 125, 5
                .byte 300, 125, 125, 125, 125, 3
                .byte 300, 377, 127, 325, 317, 0
                .byte 300, 377, 377, 377, 63, 3
                .byte 0, 377, 377, 377, 314, 0
                .byte 0, 377, 377, 377, 363, 0
                .byte 0, 374, 377, 377, 74, 0
                .byte 0, 360, 377, 77, 17, 0
                .byte 0, 300, 377, 377, 3, 0
                .byte 0, 0, 374, 77, 0, 0
; ───────────────────────────────────────────────────────────────────────────
SoundSub:       .word 102062            ; Вход: R2 - длительность звука БИП
                                        ;       R3 - частота звука

LivesIncDec:    .word 1                 ; Значение, на которое уменьшается или увеличивается число жизней
RNDAccum:       .word 0
; ───────────────────────────────────────────────────────────────────────────
CurBlowSpr:     .word 0                 ; адрес текущего спрайта взрыва, 0 - нет
CurBlowScrAddr: .word 0                 ; Текущий адрес экрана взрыва, если взрыв
Bombs:          .word 0                 ; Количество бомб
Lives:          .word 0                 ; Количество жизней
Progress:       .word 0                 ; Текущий прогресс

FlyL2RScrAddr:  .word 0                 ; временный адрес экрана мухи
FlyR2LScrAddr:  .word 0                 ; временный адрес экрана мухи

CurWaterWaveSpr:.word 0                 ; текущий адрес спрайта колышущейся воды
WallScrAddr:    .word 0                 ; адрес экрана стены
VulkanAddr:     .word 0                 ; адрес экрана вулкана

StarMask:       .word 20                ; маски звёзд
CurStarMask:    .word 20

ScrAddrGG:      .word 0                 ; адрес вывода спрайта ГГ
HorizMovOffset: .word 0                 ; горизонтальное смещение: 1 - при движении влево
                                        ;                         -1 - при движении вправо
                                        ;                          0 - стоим на месте
MoveDir:        .word 0                 ; Флаг направления движения
                                        ; >0 - идём влево
                                        ; <0 - идём вправо
MovAnimGGPtr:   .word 0                 ; Адрес в массиве сжатых спрайтов разных анимаций
JumpFlag:       .word 0                 ; Флаг прыжка
word_25032:     .word 0                 ; переменные разных фаз прыжка
word_25034:     .word 0                 ;
word_25036:     .word 0                 ;
CrouchShootFlag:.word 0                 ; Флаг приседания, >0 - просто присесть, <0 - ещё и стрелять
BombBlowFlag:   .word 0                 ; Флаг взрыва бомбы
VertGGOffset:   .word 0                 ; смещение ГГ по вертикали, -400 - присел, 400 - прыжок
; эти параметры должны следовать друг за другом вместе
StolbParam:     .word 0, 0, 0
HolmParam:      .word 0, 0, 0
VulkanParam:    .word 0, 0, 0
; ───────────────────────────────────────────────────────────────────────────
; смещения разлёта осколков
ParticleOffset: .word -300
                .word -77
                .word 2
                .word 101
                .word 300
                .word 77
                .word -2
                .word -101
ParticleOffsetEnd:
; ───────────────────────────────────────────────────────────────────────────
; Каждый байт - данные, повторяющиеся в линию
GroundData:     .byte 242
                .byte 212
                .byte 212
                .byte 250
                .byte 252
                .byte 210
                .byte 252
                .byte 210
                .byte 42
                .byte 210
                .byte 42
                .byte 210
                .byte 0
                .byte 210
                .byte 0
                .byte 210
; ───────────────────────────────────────────────────────────────────────────
ClrScrEx2Data:  .word 177400
                .word 37700
                .word 7760
                .word 1774
                .word 377
                .word 140077
                .word 170017
                .word 176003
; ───────────────────────────────────────────────────────────────────────────
StarAddrTblSize = 12.
StarAddrTbl:    .word 60060
                .word 66020
                .word 62000
                .word 62204
                .word 63036
                .word 65066
                .word 64015
                .word 62457
                .word 64427
                .word 66573
                .word 57010
                .word 65046
; ───────────────────────────────────────────────────────────────────────────
; массив кодов сегментов для вывода цифровых цифр
; каждый бит означает 1 сегмент, 1 - светится, 0 - не светится
SegmDigits:     .byte ^B01111101        ; 0
                .byte ^B01010000        ; 1
                .byte ^B01001111        ; 2
                .byte ^B01010111        ; 3
                .byte ^B01110010        ; 4
                .byte ^B00110111        ; 5
                .byte ^B00111111        ; 6
                .byte ^B01010001        ; 7
                .byte ^B01111111        ; 8
                .byte ^B01110111        ; 9
; ───────────────────────────────────────────────────────────────────────────
; Высота символа - 6 строк
Font:           .byte 0                 ; пробел
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0                 ; ! (кто хочет, пусть дорисовывает недостающие символы)
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte ^B00000000        ; "
                .byte ^B01101100
                .byte ^B01101100
                .byte ^B01001000
                .byte ^B00000000
                .byte ^B00000000
                .byte 0                 ; #
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0                 ; $
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0                 ; %
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0                 ; &
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0                 ; '
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0                 ; (
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0                 ; )
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0                 ; *
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte ^B00010000        ; +
                .byte ^B00011000
                .byte ^B01111110
                .byte ^B00011000
                .byte ^B00011000
                .byte ^B00000000
                .byte ^B00000000        ; ,
                .byte ^B00000000
                .byte ^B00000000
                .byte ^B00011000
                .byte ^B00011000
                .byte ^B00010000
                .byte ^B00000000        ; -
                .byte ^B00000000
                .byte ^B01111110
                .byte ^B00011110
                .byte ^B00000000
                .byte ^B00000000
                .byte ^B00000000        ; .
                .byte ^B00000000
                .byte ^B00000000
                .byte ^B00000000
                .byte ^B00011000
                .byte ^B00011000
                .byte 0                 ; /
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte ^B00111100        ; 0
                .byte ^B01100010
                .byte ^B01010010
                .byte ^B01001011
                .byte ^B01000111
                .byte ^B00111110
                .byte ^B00010000        ; 1
                .byte ^B00010000
                .byte ^B00010000
                .byte ^B00011000
                .byte ^B00011000
                .byte ^B00011000
                .byte ^B00111110        ; 2
                .byte ^B01000001
                .byte ^B00111000
                .byte ^B00001110
                .byte ^B01100011
                .byte ^B01111111
                .byte ^B00111110        ; 3
                .byte ^B01000000
                .byte ^B00111110
                .byte ^B01100000
                .byte ^B01100000
                .byte ^B00111111
                .byte ^B01000010        ; 4
                .byte ^B01000010
                .byte ^B01100011
                .byte ^B01111111
                .byte ^B01100000
                .byte ^B01100000
                .byte ^B01111110        ; 5
                .byte ^B00000001
                .byte ^B00111111
                .byte ^B01100000
                .byte ^B01100001
                .byte ^B01111111
                .byte ^B00111100        ; 6
                .byte ^B00000010
                .byte ^B00111111
                .byte ^B01100001
                .byte ^B01100001
                .byte ^B00111110
                .byte ^B01111111        ; 7
                .byte ^B01100000
                .byte ^B00110000
                .byte ^B00011000
                .byte ^B00011000
                .byte ^B00011000
                .byte ^B00011100        ; 8
                .byte ^B00110010
                .byte ^B00111110
                .byte ^B01100001
                .byte ^B01100001
                .byte ^B00111110
                .byte ^B00111110        ; 9
                .byte ^B01000001
                .byte ^B01000001
                .byte ^B01111110
                .byte ^B01100000
                .byte ^B01100000
                .byte ^B00011000        ; :
                .byte ^B00011000
                .byte ^B00000000
                .byte ^B00011000
                .byte ^B00011000
                .byte ^B00000000
                .byte 0                 ; ;
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0                 ; <
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte ^B00000000        ; =
                .byte ^B01111100
                .byte ^B00000000
                .byte ^B01111100
                .byte ^B00011100
                .byte ^B00000000
                .byte 0                 ; >
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte ^B01111110        ; ?
                .byte ^B01000010
                .byte ^B01000000
                .byte ^B01111000
                .byte ^B00000000
                .byte ^B00011000
                .byte ^B00000000        ; @
                .byte ^B00000000
                .byte ^B00000000
                .byte ^B00000000
                .byte ^B00000000
                .byte ^B00000000
                .byte ^B00111000        ; А
                .byte ^B01001100
                .byte ^B01000110
                .byte ^B01111111
                .byte ^B01100011
                .byte ^B01100011
                .byte ^B00001110        ; В
                .byte ^B00010010
                .byte ^B00111110
                .byte ^B01000011
                .byte ^B01100011
                .byte ^B00111111
                .byte ^B00111100        ; С
                .byte ^B01100010
                .byte ^B00000011
                .byte ^B00000011
                .byte ^B01100011
                .byte ^B00111110
                .byte ^B00111111        ; D
                .byte ^B01000010
                .byte ^B01000010
                .byte ^B01100011
                .byte ^B01100011
                .byte ^B00111111
                .byte ^B01111110        ; Е
                .byte ^B00000010
                .byte ^B00111111
                .byte ^B00000011
                .byte ^B00000011
                .byte ^B00111111
                .byte ^B01111110        ; F
                .byte ^B00000010
                .byte ^B00111111
                .byte ^B00000011
                .byte ^B00000011
                .byte ^B00000011
                .byte ^B00111100        ; G
                .byte ^B00000010
                .byte ^B01110010
                .byte ^B01000011
                .byte ^B01100011
                .byte ^B00111110
                .byte ^B01000010        ; Н
                .byte ^B01000010
                .byte ^B01100011
                .byte ^B01111111
                .byte ^B01100011
                .byte ^B01100011
                .byte ^B00110000        ; I
                .byte ^B00010000
                .byte ^B00010000
                .byte ^B00011000
                .byte ^B00011000
                .byte ^B00011000
                .byte ^B00100000        ; J
                .byte ^B00100000
                .byte ^B01100000
                .byte ^B01100011
                .byte ^B01100011
                .byte ^B00111110
                .byte ^B00110010        ; К
                .byte ^B00011010
                .byte ^B00001111
                .byte ^B00011011
                .byte ^B00110011
                .byte ^B01100011
                .byte ^B00000010        ; L
                .byte ^B00000010
                .byte ^B00000011
                .byte ^B01000011
                .byte ^B01100011
                .byte ^B01111111
                .byte ^B01000010        ; М
                .byte ^B01100010
                .byte ^B01110111
                .byte ^B01101011
                .byte ^B01101011
                .byte ^B01100011
                .byte ^B01000010        ; N
                .byte ^B01000010
                .byte ^B01000111
                .byte ^B01001011
                .byte ^B01110011
                .byte ^B01100011
                .byte ^B00111100        ; О
                .byte ^B01000010
                .byte ^B01000011
                .byte ^B01100011
                .byte ^B01100011
                .byte ^B00111110
                .byte ^B00111110        ; Р
                .byte ^B01000010
                .byte ^B01100011
                .byte ^B00111111
                .byte ^B00000011
                .byte ^B00000011
                .byte ^B00111100        ; Q
                .byte ^B01000010
                .byte ^B01000011
                .byte ^B01110011
                .byte ^B00110011
                .byte ^B01101110
                .byte ^B00111100        ; R
                .byte ^B01000010
                .byte ^B01100010
                .byte ^B00111111
                .byte ^B00110011
                .byte ^B01100011
                .byte ^B01111100        ; S
                .byte ^B00000110
                .byte ^B00111100
                .byte ^B01000000
                .byte ^B01100011
                .byte ^B00111111
                .byte ^B01111111        ; Т
                .byte ^B01001001
                .byte ^B00001000
                .byte ^B00001100
                .byte ^B00001100
                .byte ^B00001100
                .byte ^B01000010        ; U
                .byte ^B01000010
                .byte ^B01100011
                .byte ^B01100011
                .byte ^B01100010
                .byte ^B00111100
                .byte ^B01000010        ; V
                .byte ^B01000011
                .byte ^B01100011
                .byte ^B00110110
                .byte ^B00110100
                .byte ^B00011000
                .byte ^B00111100        ; W
                .byte ^B01010010
                .byte ^B01010010
                .byte ^B01011011
                .byte ^B01011011
                .byte ^B01011011
                .byte ^B01100011        ; Х
                .byte ^B00110110
                .byte ^B00011100
                .byte ^B00011100
                .byte ^B00110110
                .byte ^B01100011
                .byte ^B01100010        ; Y
                .byte ^B01100011
                .byte ^B00110011
                .byte ^B00001100
                .byte ^B00001100
                .byte ^B00001100
                .byte ^B01111111        ; Z
                .byte ^B01100001
                .byte ^B00111000
                .byte ^B00001110
                .byte ^B01000011
                .byte ^B01111111
                .byte 0                 ; [
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0                 ; \
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0                 ; ]
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0                 ; ^
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0                 ; _
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte 0
                .byte ^B00110010        ; Ю
                .byte ^B01001010
                .byte ^B01001011
                .byte ^B01101111
                .byte ^B01101011
                .byte ^B00110011
                .byte ^B00111000        ; А
                .byte ^B01001100
                .byte ^B01000110
                .byte ^B01111111
                .byte ^B01100011
                .byte ^B01100011
                .byte ^B01111110        ; Б
                .byte ^B00000010
                .byte ^B00111111
                .byte ^B01100001
                .byte ^B01100001
                .byte ^B00111111
                .byte ^B00100010        ; Ц
                .byte ^B00100010
                .byte ^B00110011
                .byte ^B00110011
                .byte ^B01110011
                .byte ^B01011110
                .byte ^B00011000        ; Д
                .byte ^B00100100
                .byte ^B00100110
                .byte ^B00100110
                .byte ^B00100110
                .byte ^B01111111
                .byte ^B01111110        ; Е
                .byte ^B00000010
                .byte ^B00111111
                .byte ^B00000011
                .byte ^B00000011
                .byte ^B00111111
                .byte ^B00111110        ; Ф
                .byte ^B01001001
                .byte ^B01001001
                .byte ^B01001101
                .byte ^B00111110
                .byte ^B00001100
                .byte ^B01111110        ; Г
                .byte ^B01100010
                .byte ^B00000011
                .byte ^B00000011
                .byte ^B00000011
                .byte ^B00000011
                .byte ^B01100011        ; Х
                .byte ^B00110110
                .byte ^B00011100
                .byte ^B00011100
                .byte ^B00110110
                .byte ^B01100011
                .byte ^B01000010        ; И
                .byte ^B01100010
                .byte ^B01110011
                .byte ^B01101011
                .byte ^B01100111
                .byte ^B01100011
                .byte ^B01011010        ; Й
                .byte ^B01100010
                .byte ^B01110011
                .byte ^B01101011
                .byte ^B01100111
                .byte ^B01100011
                .byte ^B00110010        ; К
                .byte ^B00011010
                .byte ^B00001111
                .byte ^B00011011
                .byte ^B00110011
                .byte ^B01100011
                .byte ^B00111000        ; Л
                .byte ^B01000100
                .byte ^B01000010
                .byte ^B01100011
                .byte ^B01100011
                .byte ^B01100011
                .byte ^B01000010        ; М
                .byte ^B01100010
                .byte ^B01110111
                .byte ^B01101011
                .byte ^B01101011
                .byte ^B01100011
                .byte ^B01000010        ; Н
                .byte ^B01000010
                .byte ^B01100011
                .byte ^B01111111
                .byte ^B01100011
                .byte ^B01100011
                .byte ^B00111100        ; О
                .byte ^B01000010
                .byte ^B01000011
                .byte ^B01100011
                .byte ^B01100011
                .byte ^B00111110
                .byte ^B00111100        ; П
                .byte ^B01000010
                .byte ^B01000010
                .byte ^B01100011
                .byte ^B01100011
                .byte ^B01100011
                .byte ^B01111110        ; Я
                .byte ^B01000011
                .byte ^B01100011
                .byte ^B01111110
                .byte ^B01100100
                .byte ^B01100011
                .byte ^B00111110        ; Р
                .byte ^B01000010
                .byte ^B01100011
                .byte ^B00111111
                .byte ^B00000011
                .byte ^B00000011
                .byte ^B00111100        ; С
                .byte ^B01100010
                .byte ^B00000011
                .byte ^B00000011
                .byte ^B01100011
                .byte ^B00111110
                .byte ^B01111111        ; Т
                .byte ^B01001001
                .byte ^B00001000
                .byte ^B00001100
                .byte ^B00001100
                .byte ^B00001100
                .byte ^B01100010        ; у
                .byte ^B01100011
                .byte ^B01100110
                .byte ^B00111100
                .byte ^B00011000
                .byte ^B00001110
                .byte ^B01001010        ; Ж
                .byte ^B01101010
                .byte ^B00111110
                .byte ^B01101101
                .byte ^B01101101
                .byte ^B01101101
                .byte ^B00001110        ; В
                .byte ^B00010010
                .byte ^B00111110
                .byte ^B01000011
                .byte ^B01100011
                .byte ^B00111111
                .byte ^B00000010        ; Ь
                .byte ^B00000010
                .byte ^B00111111
                .byte ^B01000011
                .byte ^B01100011
                .byte ^B00111110
                .byte ^B01000010        ; Ы
                .byte ^B01000010
                .byte ^B01101111
                .byte ^B01110001
                .byte ^B01111001
                .byte ^B01101111
                .byte ^B00111110        ; 3
                .byte ^B01000000
                .byte ^B00111110
                .byte ^B01100000
                .byte ^B01100001
                .byte ^B00111110
                .byte ^B01010010        ; Ш
                .byte ^B01010010
                .byte ^B01011011
                .byte ^B01011011
                .byte ^B01011011
                .byte ^B00111110
                .byte ^B00011110        ; Э
                .byte ^B00100000
                .byte ^B01111000
                .byte ^B01100000
                .byte ^B00110000
                .byte ^B00011111
                .byte ^B00100010        ; Щ
                .byte ^B00101010
                .byte ^B00101011
                .byte ^B00101011
                .byte ^B01101011
                .byte ^B01011110
                .byte ^B01000010        ; Ч
                .byte ^B01000010
                .byte ^B01100011
                .byte ^B01111111
                .byte ^B01100000
                .byte ^B01100000
                .byte ^B00000111        ; Ъ
                .byte ^B00000100
                .byte ^B00111100
                .byte ^B01000110
                .byte ^B01100110
                .byte ^B00111110
; ───────────────────────────────────────────────────────────────────────────
KbdTab:         .byte 10                ; влево
                .byte 31                ; вправо
                .byte 32                ; вверх
                .byte 33                ; вниз
                .byte 40                ; взрыв
                .byte 0

JoyTab:         .word 2                 ; влево
                .word 1                 ; вправо
                .word 4                 ; вверх
                .word 10                ; вниз
                .word 40                ; выстрел
                .word 20                ; взрыв
; ───────────────────────────────────────────────────────────────────────────
; Счёт 6 байтов, последний байт - бит 7 признак конца байтов счёта
Score:          .byte 0, 0, 0, 0, 0, 200
; ───────────────────────────────────────────────────────────────────────────
; Три элемента по 2 слова
; формат:
; .word адрес экрана
; .word смещение на экране
SporesParamTblSize = 3
SporesParamItemSize = 4
SporesParamTbl: .blkb SporesParamTblSize * SporesParamItemSize

; ───────────────────────────────────────────────────────────────────────────
; таблица разлёта осколков при попадании в объект
; размер элемента - 24 байта (10. слов)
; формат:
; .word адрес спрайта осколка
; .byte время жизни
; .byte текущее смещение в таблице смещений
; {.word адрес }10 - 8 адресов осколков
ParticlesTblItemSize = 24
ParticlesTblSize = 9.
ParticlesTbl:   .blkb   ParticlesTblSize * ParticlesTblItemSize
ParticlesTblEnd:
; ───────────────────────────────────────────────────────────────────────────
; массив параметров живности
; размер 10 байтов
; формат:
; .word смещение от правого края экрана
; .word текущий адрес экрана
; .word текущая видимая ширина
; .word текущий адрес спрайта с видимого столбца
EnemysItemSize = 10
EnemysSize = 10
Enemys:
E.Worms:        .blkb   EnemysItemSize  ; 0
E.Turtles:      .blkb   EnemysItemSize  ; 10
E.Snakes:       .blkb   EnemysItemSize  ; 20
                .blkb   EnemysItemSize  ; 30
E.Frogs:        .blkb   EnemysItemSize  ; 40
                .blkb   EnemysItemSize  ; 50
E.FlyL2R:       .blkb   EnemysItemSize  ; 60
E.FlyR2L:       .blkb   EnemysItemSize  ; 70

; массив из двух слов, адреса комков извержения вулкана
LavaBallArrSize = 2
LavaBallArr:    .blkw LavaBallArrSize   ; массив комков извержения вулкана


CurrentStageData:
; Массив данных текущего этапа, размер 440 байтов
; сейчас заполнен данными первого этапа
StageSize = Stage2Data - Stage1Data
StageSizeW = StageSize / 2
Stage1Data:
; Таблица параметров, когда рисовать столб (16. слов)
StolbDrawTblSize = 16.
StolbDrawTbl:   .word 21
                .word 374
                .word 714
                .word 505
                .word 1113
                .word 1413
                .word 2315
                .word 2065
                .word 2470
                .word 3016
                .word 4055
                .word 3467
                .word 4605
                .word 5056
                .word 5350
                .word 5774
; Таблица параметров, когда рисовать холм (16. слов)
HolmDrawTblSize = 16.
HolmDrawTbl:    .word 306
                .word 1034
                .word 475
                .word 1341
                .word 1472
                .word 1627
                .word 2046
                .word 2164
                .word 2425
                .word 3006
                .word 4273
                .word 3607
                .word 3731
                .word 4733
                .word 6416
                .word 5563
; Таблица параметров, определяющих, когда рисовать воду (100 слов)
WaterDrawTblSize = 64.
WaterDrawTbl:   .word 100021
                .word 26
                .word 100073
                .word 400
                .word 100415
                .word 522
                .word 100560
                .word 1154
                .word 101176
                .word 1204
                .word 101227
                .word 1235
                .word 101260
                .word 1350
                .word 101413
                .word 1534
                .word 101551
                .word 1556
                .word 101571
                .word 1600
                .word 101610
                .word 1751
                .word 101765
                .word 1772
                .word 102037
                .word 2132
                .word 102153
                .word 2241
                .word 102265
                .word 2271
                .word 2321
                .word 102315
                .word 102345
                .word 2351
                .word 102375
                .word 2401
                .word 102424
                .word 3232
                .word 103246
                .word 4155
                .word 104177
                .word 4211
                .word 104233
                .word 4245
                .word 104267
                .word 5077
                .word 105145
                .word 5275
                .word 105343
                .word 5473
                .word 105540
                .word 5630
                .word 105656
                .word 5662
                .word 105710
                .word 5714
                .word 105742
                .word 5746
                .word 105774
                .word 6000
                .word 106026
                .word 6032
                .word 106060
                .word 6534
; Таблица параметров, определяющих, когда рисовать вулкан (16. слов)
VulkanDrawTblSize = 16.
VulkanDrawTbl:  .word 637
                .word 1464
                .word 2125
                .word 3420
                .word 3660
                .word 3540
                .word 4004
                .word 4125
                .word 4424
                .word 5573
                .word 6131
                .word 1572
                .word 6341
                .word 6464
                .word 0
                .word 0
; Таблица параметров, определяющих, когда рисовать вертикальную стену
; 32. слова
WallDrawTblSize = 32.
WallDrawTbl:    .word 123
                .word 100227
                .word 730
                .word 101034
                .word 1644
                .word 101750
                .word 2474
                .word 102600
                .word 2577
                .word 102703
                .word 2702
                .word 103006
                .word 3022
                .word 103126
                .word 3125
                .word 103231
                .word 3254
                .word 103360
                .word 4302
                .word 104406
                .word 4747
                .word 105053
                .word 5156
                .word 105262
                .word 5354
                .word 105460
                .word 4473
                .word 104577
                .word 4621
                .word 104725
                .word 6203
                .word 106307
; данные второго этапа
Stage2Data:     .word 205, 372, 605, 1211, 2053, 3003, 3435, 3722
                .word 4070, 4412, 4616, 5142, 5431, 6071, 6142, 6740
                .word 45, 507, 720, 1064, 1326, 1454, 1612, 2066
                .word 2426, 2553, 3612, 4263, 4707, 5232, 5464, 6175
                .word 100021, 252, 100320, 324, 100372, 376, 100444, 744
                .word 101012, 1125, 101173, 1257, 101325, 1746, 102014, 2133
                .word 102156, 2162, 102207, 3327, 103375, 3475, 103523, 3530
                .word 103556, 3563, 103611, 4042, 104070, 4074, 104122, 4126
                .word 104154, 4526, 104560, 4564, 104616, 4622, 104654, 4740
                .word 104757, 4766, 105006, 5210, 105231, 5263, 105311, 5316
                .word 105344, 5350, 105376, 5403, 105431, 5435, 105463, 5474
                .word 105522, 6114, 106142, 6146, 106174, 6205, 106233, 6745
                .word 530, 1055, 1400, 1534, 1671, 2060, 2240, 3261
                .word 3427, 3660, 3764, 4220, 4334, 4456, 4760, 5202
                .word 74, 100200, 614, 100720, 2313, 102417, 2446, 102552
                .word 2561, 102665, 2677, 103003, 3014, 103120, 3117, 103223
                .word 5033, 105137, 5532, 105636, 5650, 105754, 5766, 106072
                .word 6277, 106403, 6402, 106506, 6505, 106611, 6610, 106714
; данные третьего этапа
Stage3Data:     .word 240, 421, 1162, 2303, 2541, 2651, 2770, 3115
                .word 4077, 4265, 4551, 4712, 2164, 3715, 5047, 5164
                .word 200, 16, 454, 572, 722, 1301, 1505, 1732
                .word 1616, 2045, 5437, 2415, 4317, 3326, 3752, 4201
                .word 100065, 100015, 26, 254, 100302, 306, 100334, 340
                .word 100366, 373, 100421, 425, 100453, 464, 100512, 1322
                .word 101350, 1355, 101403, 1450, 101462, 1554, 101567, 1665
                .word 101701, 2002, 102017, 2113, 102131, 2232, 102251, 2346
                .word 102366, 2467, 102510, 2605, 102627, 3001, 103027, 3033
                .word 103061, 3067, 103115, 3121, 103147, 3155, 103203, 3345
                .word 103373, 3500, 103526, 3635, 103663, 3774, 104022, 4133
                .word 104161, 4361, 104407, 4523, 104551, 4555, 104603, 6326
                .word 134, 545, 1442, 1546, 4444, 1774, 2105, 2224
                .word 2340, 2461, 2577, 4643, 3564, 3427, 4060, 4230
                .word 615, 100721, 734, 101040, 1053, 101157, 1172, 101276
                .word 2663, 102767, 3213, 103317, 4734, 105040, 5060, 105164
                .word 5175, 105301, 5502, 105606, 5300, 105404, 5605, 105711
                .word 5710, 106014, 6013, 106117, 6116, 106222, 6221, 106325
; данные четвёртого этапа
Stage4Data:     .word 324, 543, 1035, 1165, 1512, 675, 4041, 2071
                .word 2302, 2506, 3121, 3337, 4267, 4556, 5070, 5561
                .word 215, 346, 467, 2221, 760, 1334, 1463, 1625
                .word 2535, 3016, 3241, 3544, 4132, 4532, 4341, 5010
                .word 100076, 33, 100013, 243, 100310, 377, 100425, 431
                .word 100457, 731, 100756, 772, 101017, 1245, 101273, 1304
                .word 101322, 1550, 101567, 2010, 102036, 2043, 102071, 2075
                .word 102123, 2646, 102674, 2702, 102730, 3725, 103753, 3757
                .word 104005, 4013, 104041, 4045, 104073, 4101, 104127, 4312
                .word 104340, 4351, 104377, 4642, 104670, 4676, 104724, 3453
                .word 103463, 3701, 103706, 5340, 105366, 5373, 105421, 5602
                .word 105630, 5640, 105666, 5700, 105726, 6061, 106107, 6504
                .word 521, 1213, 1571, 2155, 2262, 2462, 2573, 2760
                .word 3065, 3277, 3403, 3510, 4567, 4751, 5055, 5267
                .word 111, 100215, 571, 100675, 1042, 101146, 1345, 101451
                .word 1661, 101765, 2331, 102435, 3135, 103241, 3566, 103672
                .word 4150, 104254, 4426, 104532, 5127, 105233, 5441, 105545
                .word 5743, 106047, 6120, 106224, 6241, 106345, 6344, 106450
; данные пятого этапа
Stage5Data:     .word 233, 56, 1050, 1162, 1277, 1534, 2200, 2706
                .word 3740, 4151, 4326, 4501, 4727, 5043, 5152, 5610
                .word 245, 107, 416, 562, 1114, 1375, 1511, 1632
                .word 2047, 2416, 2667, 3717, 4024, 4347, 4461, 5262
                .word 100021, 271, 100317, 326, 100354, 602, 100630, 1344
                .word 101360, 1541, 101567, 1576, 101624, 2074, 102107, 2113
                .word 102124, 2130, 102137, 2143, 102174, 3054, 103102, 3111
                .word 103137, 3146, 103174, 3202, 103230, 3326, 103354, 3463
                .word 103511, 3520, 103546, 3554, 103602, 5512, 105521, 5525
                .word 105534, 5540, 105547, 5553, 105562, 5566, 105575, 5601
                .word 105610, 5614, 105623, 5627, 105636, 5642, 105651, 5655
                .word 105664, 6004, 106013, 6017, 106045, 6051, 106116, 6122
                .word 403, 660, 1336, 2241, 2452, 2661, 3256, 3411
                .word 3766, 4305, 4664, 4771, 5105, 5216, 5334, 5725
                .word 127, 100233, 456, 100562, 730, 101034, 1173, 101277
                .word 1405, 101511, 1640, 101744, 1743, 102047, 5405, 105511
                .word 2312, 102416, 2520, 102624, 2734, 103040, 3610, 103714
                .word 4035, 104141, 4154, 104260, 4355, 104461, 4532, 104636
; данные шестого этапа
Stage6Data:     .word 571, 2157, 2415, 2670, 1047, 1450, 3116, 3467
                .word 3722, 4076, 4440, 4625, 4756, 5065, 5171, 5302
                .word 111, 621, 1625, 1741, 2053, 2276, 2540, 3337
                .word 4004, 4144, 4261, 4377, 4511, 4715, 5022, 5130
                .word 100021, 53, 100073, 731, 100757, 764, 101012, 1020
                .word 101047, 1053, 101101, 1106, 101134, 1342, 101370, 1374
                .word 101422, 101450, 1454, 101502, 1506, 101534, 1426, 3141
                .word 103167, 3204, 103232, 3273, 103305, 3314, 103326, 3363
                .word 103411, 3424, 103452, 3515, 103530, 3537, 103552, 3614
                .word 103642, 3655, 103703, 3742, 103757, 3766, 104003, 4047
                .word 104075, 4110, 104136, 4200, 104217, 4226, 104245, 4412
                .word 104440, 4444, 104472, 4640, 104666, 4672, 104714, 6361
                .word 160, 373, 661, 1162, 1564, 2001, 2112, 2231
                .word 2347, 2466, 2615, 2737, 3306, 3531, 3760, 4220
                .word 243, 100347, 450, 100554, 1235, 101341, 1635, 101741
                .word 3012, 103116, 4273, 104377, 4521, 104625, 5176, 105302
                .word 5306, 105412, 5411, 105515, 5514, 105620, 5617, 105723
                .word 5722, 106026, 6025, 106131, 6130, 106234, 6233, 106337


; ───────────────────────────────────────────────────────────────────────────
; Конец игры.
; Послеигровые действия

GameFinish$:    add     #TT4$Final$-Entry$, Vector4
                br      2fin$
; ───────────────────────────────────────────────────────────────────────────

TT4$Final$:     add     #4, SP
                xor     R0, R0
                mov     (R0), R0

1$:             xor     R0, (SP)+
                bne     1$
                mov     R0, -(SP)

2fin$:          mov     #137, MorphJMP1$
                call    ClrScrEx        ; Очистка экрана рабочей области с эффектами
                mov     #FinalTextData1, R2

jmp_33440:      movb    (R2)+, R5       ; количество переводов строки, если 0, то выход из цикла после вывода строки
                movb    (R2)+, R4       ; маска цвета
                mov     (R2)+, R1       ; адрес экрана
                clr     R0              ; аккумулятор
                call    DrawString      ; Вывод строки
                                        ; Вход: R1 - адрес экрана
                                        ;       R2 - адрес строки
                                        ;       R0 - начальное значение аккумулятора кодов расшифрованных символов
                                        ;       R5 - масштаб по вертикали
                mov     R2, -(SP)
                mov     R5, -(SP)
                mov     #SndParam3, R4
                call    PlaySound

4$:             bit     #100, @#177716
                bne     4$
                call    PlaySound
                call    ClrScrEx        ; Очистка экрана рабочей области с эффектами
                mov     (SP)+, R5
                mov     (SP)+, R2
                dec     R5
                beq     jmp_33440

MorphJMP1$:     br      MorphJMP1BR$    ; сюда пишется 401 и 137
                .word   SpShStartAnim   ; Анимация взлёта космического корабля
; ───────────────────────────────────────────────────────────────────────────
MorphJMP1BR$:   sub     #TT4$Final$-Entry$, Vector4
                jmp     Entry2$
; ───────────────────────────────────────────────────────────────────────────


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

; Анимация взлёта космического корабля

SpShStartAnim:  mov     #-2, fin_SprOffs
                mov     #-42, fin_SprOffs2
                mov     #65330, fin_ScrAddr
                mov     #57004, R1
                call    DrawPlanetSprA  ; Рисуем планету
                                        ; Вход: R1 - адрес экрана
                call    DrawFloor       ; Прорисовка земной поверхности
                call    sub_37020
                clr     fin_offs+2
                call    DrawSpaceShip
                mov     #210, 2fin_AnimDurat$

1$:             dec     (PC)+
2fin_AnimDurat$:.word 0
                beq     2$
                call    sub_36630
                br      1$
; ───────────────────────────────────────────────────────────────────────────

2$:             mov     #100, fin_offs+2
                mov     #200, 4fin_AnimDurat$

3$:             dec     (PC)+
4fin_AnimDurat$:.word 0
                beq     5$
                call    sub_36630
                br      3$
; ───────────────────────────────────────────────────────────────────────────

5$:             call    ClrScrEx        ; Очистка экрана рабочей области с эффектами
                mov     #70036, R1
                call    DrawPlanetSprA  ; Рисуем планету
                                        ; Вход: R1 - адрес экрана
                clr     R0
                sob     R0, .
                sob     R0, .
                mov     #20, R3

6$:             mov     #63636, R1
                mov     R3, -(SP)
                mov     #4, R2

7$:             mov     R1, -(SP)
                call    sub_37376
                mov     R2, -(SP)
                mov     #3, R2
                mov     #4, R3
                call    @SoundSub       ; Вход: R2 - длительность звука БИП
                                        ;       R3 - частота звука
                mov     (SP)+, R2
                mov     (SP)+, R1
                sub     #400, R1
                sob     R2, 7$
                mov     (SP)+, R3
                sob     R3, 6$
                call    ClrScrEx        ; Очистка экрана рабочей области с эффектами
                mov     (PC)+, @(PC)+
                        br . + <MorphJMP1BR$-MorphJMP1$>
                        .word MorphJMP1$
                mov     #FinalTextData2, R2
                jmp     jmp_33440
; End of function SpShStartAnim


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


sub_36630:      sub     fin_offs+2, fin_ScrAddr
                mov     (PC)+, R1
fin_ScrAddr:    .word 0

                mov     R1, R2
                sub     #56530, R2
                bpl     1$
                sub     R2, R1

1$:             mov     #51, R2

fin2$:          mov     #15, R3

fin_offs:       mov     100(R1), (R1)+
                sob     R3, fin_offs
                add     #46, R1
                sob     R2, fin2$
                mov     fin_ScrAddr, R1
                add     #2225, R1
                mov     (PC)+, R0
off_36712:      .word   SpShFlame1
                cmp     #SpShFlame2, R0
                beq     5$
                mov     #SpShFlame1, R0

5$:             mov     #15, R2

6$:             mov     #5, R3
                cmp     #56500, R1
                bmi     7$
                add     R3, R1
                add     R3, R0
                br      8$
; ───────────────────────────────────────────────────────────────────────────

7$:             movb    (R0)+, (R1)+
                sob     R3, 7$

8$:             add     #73, R1
                sob     R2, 6$
                tst     (PC)+
9Delay$:        .word 0

                bne     10$
                mov     #6, 9Delay$
                mov     R0, off_36712

10$:            dec     9Delay$
                mov     #SndParam4, R4
                call    PlaySound
; End of function sub_36630


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


sub_37020:      mov     #73702, R1
                mov     fin_SprOffs, R5
                mov     #HolmSpr, R0
                call    sub_10          ; Вычисление ширины остатка видимого спрайта при
                                        ; захождении за левую границу экрана
                                        ; а при движении вправо - коррекция адреса экрана
                                        ; Вход: R5 - смещение на экране
                                        ;       R0 - адрес спрайта
                                        ;       R1 - адрес экрана
                                        ; Выход: R2 - видимый остаток
                                        ;       C=0 - R2 валидно, С=1 - объект полностью за границей экрана
                bcc     1$
                clr     fin_SprOffs
                br      3$
; ───────────────────────────────────────────────────────────────────────────

1$:             mov     #HolmParam, R4
                mov     R2, R5
                call    DrawGroundSprite ; Вывод спрайта
                                        ; Вход: R1 - адрес экрана снизу
                                        ;       R0 - адрес спрайта
                                        ;       R2 - ширина спрайта
                                        ;       R5 - сколько столбцов рисовать
                                        ;       R4 - блок параметров из 3-х слов
                dec     (PC)+
fin_SprOffs:    .word 0

3$:             mov     #73702, R1
                mov     fin_SprOffs2, R5
                mov     #HolmSpr, R0
                call    sub_10          ; Вычисление ширины остатка видимого спрайта при
                                        ; захождении за левую границу экрана
                                        ; а при движении вправо - коррекция адреса экрана
                                        ; Вход: R5 - смещение на экране
                                        ;       R0 - адрес спрайта
                                        ;       R1 - адрес экрана
                                        ; Выход: R2 - видимый остаток
                                        ;       C=0 - R2 валидно, С=1 - объект полностью за границей экрана
                bcs     4$
                mov     #StolbParam, R4
                mov     R2, R5
                dec     fin_SprOffs2
                jmp     DrawGroundSprite ; Вывод спрайта
                                        ; Вход: R1 - адрес экрана снизу
                                        ;       R0 - адрес спрайта
                                        ;       R2 - ширина спрайта
                                        ;       R5 - сколько столбцов рисовать
                                        ;       R4 - блок параметров из 3-х слов
; ───────────────────────────────────────────────────────────────────────────

4$:             clr     (PC)+
fin_SprOffs2:   .word 0
                return
; End of function sub_37020


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


DrawSpaceShip:  mov     #SpaceShipSpr, R0
                mov     #65330, R1
                mov     #50, R2

1$:             mov     R1, -(SP)
                movb    (R0)+, R3
                add     R3, R1
                movb    (R0)+, R3

2$:             movb    (R0)+, R4
                beq     6$
                mov     #10, R5
                br      4$
; ───────────────────────────────────────────────────────────────────────────

3$:             asl     (R1)
                asl     (R1)

4$:             aslb    R4
                bcc     5$
                bis     #3, (R1)

5$:             sob     R5, 3$

6$:             tst     (R1)+
                sob     R3, 2$
                mov     (SP)+, R1
                add     #100, R1
                sob     R2, 1$
                return
; End of function DrawSpaceShip


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

; Спецэффект с развеиванием дымком планеты

sub_37376:      mov     #14, R5

1$:             mov     #16, R4

2$:             mov     R5, R3

3$:             mov     #word_37452, R0
                add     R4, R0
                mov     (R0), R0
                add     R1, R0
                cmp     #56700, R1
                bpl     4$
                movb    (R0), (R1)

4$:             mov     R0, R1
                sob     R3, 3$
                sub     #2, R4
                bpl     2$
                sob     R5, 1$
                clrb    (R1)
                return
; End of function sub_37376

; ───────────────────────────────────────────────────────────────────────────
word_37452:     .word 77
                .word 300
                .word 101
                .word 1
                .word -77
                .word -200
                .word -101
                .word -1
; ───────────────────────────────────────────────────────────────────────────
; спрайт космического корабля, как-то запакованный
SpaceShipSpr:   .byte 16, 6, 32, 0, 0, 0, 0, 174
                .byte 16, 6, 65, 0, 0, 0, 300, 117
                .byte 14, 7, 200, 152, 0, 337, 336, 177
                .byte 67, 14, 7, 360, 145, 300, 6, 0
                .byte 300, 72, 12, 10, 300, 33, 152, 260
                .byte 371, 370, 77, 163, 12, 10, 60, 4
                .byte 44, 154, 354, 361, 237, 300, 12, 10
                .byte 207, 10, 250, 0, 176, 343, 341, 1
                .byte 10, 10, 300, 16, 20, 270, 75, 305
                .byte 7, 324, 10, 10, 60, 30, 40, 60
                .byte 173, 213, 255, 152, 10, 10, 210, 61
                .byte 144, 160, 7, 5, 117, 75, 10, 10
                .byte 104, 142, 110, 66, 370, 2, 257, 36
                .byte 6, 11, 340, 17, 300, 310, 60, 40
                .byte 74, 115, 7, 4, 12, 200, 5, 34
                .byte 200, 305, 337, 307, 173, 257, 1, 4
                .byte 11, 300, 257, 72, 240, 143, 40, 237
                .byte 60, 117, 4, 11, 100, 176, 165, 230
                .byte 233, 377, 76, 217, 55, 4, 11, 40
                .byte 374, 353, 0, 153, 366, 175, 312, 7
                .byte 4, 11, 20, 371, 377, 177, 63, 354
                .byte 173, 156, 3, 4, 11, 210, 162, 277
                .byte 143, 33, 331, 367, 314, 1, 6, 10
                .byte 344, 162, 277, 214, 262, 357, 114, 13
                .byte 4, 11, 376, 3, 4, 5, 107, 145
                .byte 377, 314, 5, 2, 12, 177, 374, 227
                .byte 377, 372, 1, 300, 10, 56, 13, 0
                .byte 13, 300, 374, 374, 203, 276, 14, 356
                .byte 117, 372, 214, 14, 0, 13, 340, 373
                .byte 71, 230, 377, 362, 335, 107, 325, 106
                .byte 7, 0, 12, 230, 367, 323, 237, 377
                .byte 210, 273, 127, 52, 244, 0, 13, 174
                .byte 357, 123, 253, 347, 4, 167, 17, 0
                .byte 146, 3, 0, 13, 362, 336, 307, 237
                .byte 172, 2, 356, 346, 377, 105, 16, 0
                .byte 13, 341, 335, 347, 257, 73, 201, 300
                .byte 32, 0, 100, 3, 0, 13, 241, 50
                .byte 122, 5, 110, 301, 335, 254, 252, 152
                .byte 15, 0, 13, 377, 377, 363, 307, 57
                .byte 1, 102, 123, 125, 125, 10, 6, 7
                .byte 370, 37, 202, 256, 354, 253, 52, 12
                .byte 5, 174, 327, 230, 177, 125, 16, 3
                .byte 147, 376, 252, 16, 4, 230, 371, 177
                .byte 1, 16, 4, 140, 346, 377, 3, 16
                .byte 4, 200, 235, 377, 7, 22, 2, 377
                .byte 17, 20, 3, 134, 16, 30, 20, 3
                .byte 272, 374, 67, 20, 2, 167, 3, 20
                .byte 3, 372, 374, 77
; два спрайта 5х15
SpShFlame1:     .byte 0, 0, 0, 360, 300
                .byte 17, 0, 300, 0, 0
                .byte 63, 0, 74, 60, 0
                .byte 317, 303, 63, 0, 3
                .byte 360, 300, 14, 363, 0
                .byte 77, 363, 63, 14, 0
                .byte 0, 14, 374, 60, 60
                .byte 17, 63, 17, 303, 300
                .byte 314, 314, 63, 0, 0
                .byte 17, 3, 3, 74, 14
                .byte 3, 60, 0, 14, 0
                .byte 60, 300, 60, 0, 300
                .byte 0, 0, 0, 0, 0
SpShFlame2:     .byte 77, 300, 3, 74, 0
                .byte 374, 17, 74, 300, 0
                .byte 317, 63, 360, 17, 77
                .byte 360, 374, 17, 363, 303
                .byte 374, 300, 17, 14, 74
                .byte 77, 0, 374, 63, 314
                .byte 377, 17, 300, 314, 0
                .byte 314, 360, 3, 3, 0
                .byte 3, 17, 74, 14, 60
                .byte 360, 17, 14, 0, 300
                .byte 314, 360, 0, 60, 3
                .byte 0, 74, 60, 14, 0
                .byte 0, 3, 14, 0, 0
; ───────────────────────────────────────────────────────────────────────────
; тут текст подогнан так, чтобы .word  попадал на чётные ячейки
FinalTextData1: .byte 1
                .byte 320
                .word 62106
                .ascii "АВТОРСКИЕ ПРАВА НА ПЕРЕВАЛ"<12>
                .ascii <225>"ПРИНАДЛЕЖАТ"<12>
                .ascii <206>"БОРТНИКУ БОРИСУ БОРИСОВИЧУ"<12>
                .asciz <226>"Г. МОСКВА."
                .byte 1
                .byte 200
                .word 60110
                .ascii "Я РАД ПРИВЕТСТВОВАТЬ ВАС"<12>
                .ascii <216>"В КОНЦЕ ЭТОЙ ИГРЫ,"<12>
                .ascii <213>"ОТНОСЯЩЕЙСЯ К РАЗРЯДУ"<12>
                .ascii <205>"ТРУДНЕЙШИХ, И ОБЕЩАЮ ВПРЕДЬ"<12>
                .ascii <211>"НЕ ДЕЛАТЬ ТАКОЙ ЕРУНДЫ,"<12>
                .asciz <224>"КАК ПЕРЕВАЛ."
                .byte 1
                .byte 300
                .word 62006
                .ascii "СЛЕДУЮЩАЯ ИГРА"<212>"JUMPKEY"<12>
                .ascii <204>"БУДЕТ НА БОЛЕЕ МОЩНОМ УРОВНЕ."<12><12>
                .asciz <207>"КОД ЕЕ ЗАПУСКА: 16503497."
                .byte 1
                .byte 100
                .word 57120
                .ascii "ПРЕДЫДУЩИЕ ИГРЫ:"<12><12>
                .ascii <205>"GAME 1"<205>"-"<205>"BALLY"<204>'"DIDAY"'<12>
                .ascii <205>"GAME 2"<205>"-"<205>'SECOND "FLASSE"'<12>
                .ascii <205>"GAME 3"<205>"-"<205>'PLANET "SLIRIS"'<12>
                .ascii <205>"GAME 4"<205>"-"<205>'RUNING "TOORUN"'<12>
                .asciz <205>"GAME 5"<205>"-"<205>"SUPERMAN 1."
                .byte 1
                .byte 200
                .word 57111
                .ascii "НАЗВАНИЯ СЛЕДУЮЩИХ ИГР:"<12><12>
                .ascii <205>"JUMPKEY"<224>"JUMPKEY 2"<12>
                .ascii <205>"JUMPKEY 3"<220>"JUMPKEY 4"<12>
                .ascii <205>"FREDDY HARDEST"<206>"FREDDY 2"<12>
                .ascii <205>"FREDDY 3"<222>"TOWER"<12>
                .asciz <205>"RENEGADE"<222>"CRAZYCROSS."
                .byte 1
                .byte 300
                .word 61011
                .ascii "ПРАВО ИЗМЕНЕНИЯ ПОРЯДКА"<12>
                .ascii <214>"И НАЗВАНИЙ ИГР АВТОР"<12>
                .ascii <215>"ОСТАВЛЯЕТ ЗА СОБОЙ."<12><12>
                .asciz <214>"СЛЕДИТЕ ЗА РЕКЛАМОЙ."
                .byte 7
                .byte 320
                .word 62027
                .asciz "ВЗЛЕТАТЬ?"
; ───────────────────────────────────────────────────────────────────────────
FinalTextData2: .byte 1
                .byte 200
                .word 57111
                .ascii "А ТЕПЕРЬ, НЕ ОТКЛАДЫВАЯ,"<12>
                .ascii <204>"ПРИШЛИТЕ КОД ЗАПУСКА JUMPKEY"<12>
                .ascii <221>"117465 Г.МОСКВА"<12>
                .ascii <210>"УЛ. ТЕПЛЫЙ СТАН, 9-7-88,"<12>
                .ascii <232>"БОРИСУ"<12>
                .ascii <221>"ЕСЛИ ВЫ ПЕРВЫЙ,"<12>
                .asciz <232>"ТО..."
                .byte 7
                .byte 300
                .word 62035
                .asciz "END"
                .even
; ───────────────────────────────────────────────────────────────────────────
; Этот участок используется как временный буфер данных
; размер буфера минимум 200 байтов, в реальности - 400 байтов
TmpBuff:        ; загружаем заставку
                mov     #GameTopStack, SP
                mov     #PICBPM, R1
                mov     @#52, W1
                mov     @#264, W2
                mov     @#266, W3
                mov     @#300, W4
                call    @#120002
                ; восстанавливаем испорченные ячейки
                mov     (PC)+, @(PC)+
W1:             .word 0, 52
                mov     (PC)+, @(PC)+
W2:             .word 0, 264
                mov     (PC)+, @(PC)+
W3:             .word 0, 266
                mov     (PC)+, @(PC)+
W4:             .word 0, 300
                br      1GoNext$
; ───────────────────────────────────────────────────────────────────────────

TT4$1$:         add     #4, SP
1GoNext$:       mov     #SndParam, R4
                call    PlaySound

1$:             bit     #100, @#177716
                bne     1$
; подготовительные действия, из заставки частично делаем
; игровой экран
                mov     #55520, R1
                mov     #4, R2

2$:             clr     (R1)+
                clr     (R1)+
                add     #74, R1
                sob     R2, 2$
                mov     #-1, (R1)+
                mov     #-1, (R1)+
                mov     #65601, R1
                mov     #33, R2

3$:             movb    #377, (R1)+
                add     #77, R1
                sob     R2, 3$
                add     #Entry$-TT4$1$, Vector4
                halt    ; переход на Entry$ - запуск программы
; ───────────────────────────────────────────────────────────────────────────
PICBPM:         .word   3
                .word   40000,0
                .asciz  "PEREVAL.PIC"
                .even
.org TmpBuff+400
; ───────────────────────────────────────────────────────────────────────────
                .blkw 19.
GameTopStack:   .word 14747             ; Вершина стека в игре

; ===========================================================================
; это уже не относится к игре. это переносчик игры на своё место
MVGMC:          mov     PC, R3
                clr     R0
                .addr   R1, GMCBGN
                mov     R1, R2
                add     #TmpBuff-GMCBGN, R2
                sub     R1, R2
1$:             mov     (R1)+, (R0)+
                cmp     R1, R3
                blo     1$
                jmp     (R2)

                .END
