; XONIX
; компилить xonix.asm в xonix.obj, fx.asm в fx.obj
; линковать:
; xonix.obj + figure.fnt (font) + voice.bin (oood) + fx.obj +
; markx.pck (markx)
; в скобках - имя метки массива


KEYCOD          = 104
PALREG          = 106       ; копия по записи в 177662
PUSHA           = 154512
SCRADT          = 50410
GRTOUP          = 2000.     ; порог для текущего счёта, для перехода на следующий уровень

OWERDT          = 372       ; здесь хранится код для перезаписи файла (АНДОС/МКДОС)
OWERWR          = OWERDT+2  ; здесь хранится адрес ячейки, куда помещается код для перезаписи (АНДОС/МКДОС)
SCREEN          = OWERDT+4  ; здесь хранится адрес ячейки перехвата сообщений об ошибках (АНДОС/МКДОС)

GameClass       = 400       ;w
GameSpeed       = 402       ;w скорость игры
TotalScore      = 404       ;w общий счёт
CurrentScore    = 406       ;w текущий счёт
GameNum         = 410       ;w номер игры
LiveTime        = 412       ;w время жизни
LivesNum        = 414       ;w число попыток
L3610           = 416       ;w адрес начала хвоста (откуда вышел на захват территории)
Tmp$1           = 420       ;w временная ячейка для хранения разных переменных
HiOutMask       = 422       ;w битовая маска для вывода строки больших символов
TicksToOneSec   = 424       ;b счётчик прерываний 50Гц, чтобы насчитать 1 секунду
TAKT            = 425       ;b счётчик тиков таймера для часов.
DLITSN          = 426       ;b длительность звучания звуков AY
NOBEEP          = 427       ;b флаг что не надо звучать сэмплами
CountToBlkBall  = 430       ;b счётчик до появления очередного чёрного шарика
BlkBallSpeed    = 431       ;b скорость движения чёрных шариков
WhiteBalls      = 432       ;b число белых шаров
BlackBalls      = 433       ;b число чёрных шаров




TOPSTK:         jmp     BEGIN
                .asciz  " XONIX by (c) GID "
                .even
NAMRES:         .asciz  "xonix   .res"
                .even

MSGTOP:         .asciz  "Таблица рекордов"
                .even
; таблица рекордов
RECORD:         .word   0
TOPTAB:         .word   0       ;1
                .byte   40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 0, 0
                .word   0       ;2
                .byte   40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 0, 0
                .word   0       ;3
                .byte   40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 0, 0
                .word   0       ;4
                .byte   40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 0, 0
                .word   0       ;5
                .byte   40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 0, 0
                .word   0       ;6
                .byte   40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 0, 0
                .word   0       ;7
                .byte   40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 0, 0
                .word   0       ;8
                .byte   40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 0, 0
                .word   0       ;9
                .byte   40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 0, 0
LASTP:          .word   0       ;10
                .byte   40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 0, 0
ENDTAB:

MINSEC:         .byte   0, 0, 0, 0, 0, 0
;                       │  │  │  │  │  └ единицы секунд
;                       │  │  │  │  └─── десятки секунд
;                       │  │  │  └────── единицы минут
;                       │  │  └───────── десятки минут
;                       │  └──────────── единицы часов
;                       └─────────────── десятки часов

RNDVL1:         .word   110165  ; для RANDOM чтоб высчитывать направление
                                ; движения шаров
RNDVL2:         .word   23137   ; ещё для высчитывания направления
                                ; движения чёрных шаров

KRDMYS:         .word   0       ; координата моего шарика
                .word   0       ; направление моего шарика (не используется)
                ; тут координаты чёрных шариков max=4.
BLKBK1:         .word   0       ; координата 1
BLKDIR:         .word   0       ; направление 1
BLKBK2:         .word   0       ; 2
                .word   0
BLKBK3:         .word   0       ; 3
                .word   0
BLKBK4:         .word   0       ; 4
                .word   0
                ; тут координаты белых шариков max=16.
WHTBK1:         .word   56647   ; коорд1
WHTDIR:         .word   -501    ; напр1
                .word   72535   ; 2
                .word   501
                .word   54261   ; 3
                .word   -501
                .word   60506   ; 4
                .word   -477
                .word   47232   ; 5
                .word   -477
                .word   62421   ; 6
                .word   -501
                .word   53525   ; 7
                .word   -477
                .word   51134   ; 8
                .word   501
                .word   71312   ; 9
                .word   -477
                .word   72024   ; 10
                .word   -501
                .word   52372   ; 11
                .word   -501
                .word   63171   ; 12
                .word   477
                .word   54225   ; 13
                .word   -501
                .word   61207   ; 14
                .word   -501
                .word   46565   ; 15
                .word   477
                .word   46567   ; 16
                .word   -477

; стартовые координаты чёрных шариков, константы
StartCoordBkS:  .word   75140, 74440, 75137, 74437
; константы просмотра пространства вокруг точки: вверху, справа, снизу, слева
SearchView:     .word   -500, 501, 477, -501
; направления движения шариков: вправо-вниз, влево-вниз, вправо-вверх, влево-вверх
DIRECT:         .word   501, 477, -477, -501

FUCK:           .asciz  "При игре с вечной жизнью, результат не считается."

StrGame:        .asciz  "Игра:"
StrLives:       .asciz  "Попыток:"
StrTime:        .asciz  "Время:"
StrCurrScore:   .asciz  "Текущий счет:"
StrTotalScore:  .asciz  "Общий счет:"
XONIX:          .asciz  "XONIX"
StrBonusGame:   .asciz  "Призовая игра"
StrYrScore:     .asciz  "Ваш результат: "
StrYrName:      .asciz  "Введите ваше имя"
StrAnyKey:      .asciz  "Нажмите любую клавишу"

StrInfinite:    .asciz  "0 - Вечная жизнь, "
StrNormalGame:  .asciz  "1 - Нормальная игра."
StrSetSpeed:    .asciz  "Установите скорость игры (0..9)"
                .even

VEC60:          mov     R0, -(SP)
                mov     @#177662, R0
                cmpb    #16, R0
                beq     1$
                cmpb    #17, R0
                beq     1$
                cmpb    #100, R0
                bhi     3$
                bisb    (PC)+, R0
RUSLAT:         .word   0
3$:             movb    R0, @#KEYCOD
                mov     (SP)+, R0
                rti

1$:             movb    RLRG-16(R0), RUSLAT
                br      3$
RLRG:           .byte   200, 0

INKEY:          clr     R0
                bisb    @#KEYCOD, R0
                clrb    @#KEYCOD
                return
; ждать нажатия клавиши
KEYWAI:         mov     #3, R3
0$:             inc     RNDVL1
                cmp     @#177662, #40
                beq     1$
                call    ISKEY
                beq     1$
                sob     R3, 0$
                inc     RNDVL2
                br      KEYWAI
1$:             return

ISKEY:          bit     @#177716, #100
                return

; ввод кода с клавиатуры
EMT6:           tst     @#177662
1$:             call    ISKEY
                beq     1$
0$:             call    ISKEY
                bne     0$
                mov     @#177662, R0
                return

; остановка часов и выход
HLT4:           call    T100DS
                call    SHUTUP
                mov     (PC)+, @(PC)+
OLDV10:         .word   0, 10
                mov     (PC)+, @(PC)+
OLDV4:          .word   0, 4
                jmp     @#100000



BEGIN:          mov     #TOPSTK, SP
                call    START

L1000:          mov     @#177710, RAN
                mov     #20, @#177706
                mov     #34, @#177712
                movb    #1, @#TAKT      ; ┐это инициализация часов
                mov     #MINSEC, R0     ; │
                clr     (R0)+           ; │
                clr     (R0)+           ; │
                clr     (R0)+           ; │
                mov     #TRP100, @#100  ; │
                mov     #340, @#102     ; │
                call    T100EN          ; ┘
                mov     #34, @#177712

                call    FIELD           ; ┐
                mov     #55032, R1      ; │заставка
                mov     #XONIX, R0      ; │
                call    HIOUT           ; ┘
                movb    #1, @#WhiteBalls ; начинаем с одного белого шарика
                movb    #2, @#BlkBallSpeed

NewGame:        clr     @#TotalScore
                clr     @#CurrentScore
                clr     @#GameNum
                mov     StartCoordBkS+6, BLKBK1  ; расставляем чёрные шарики
                mov     StartCoordBkS  , BLKBK2
                mov     StartCoordBkS+2, BLKBK3
                mov     StartCoordBkS+4, BLKBK4

ContinueGame:   call    KEYWAI
                call    FIELD
                inc     @#GameNum       ; ┐выведем текущий номер игры
                call    OUTIGR          ; ┘

                mov     #76622, R1      ; выводим строки:
                mov     #StrCurrScore, R2
                call    PUTS            ; "текущий счёт"
                mov     #76601, R1      ;
                mov     #StrTotalScore, R2
                call    PUTS            ; "общий счёт"
                mov     #40032, R1      ;
                mov     #StrTime, R2    ;
                call    PUTS            ; "время"

                movb    @#WhiteBalls, R1 ; число белых шариков
                mov     #WHTDIR, R2     ; ┐зададим направления
                mov     RNDVL1, R3      ; │движения белых шариков
                call    RANDOM          ; ┘
                mov     #4, R1          ; ┐зададим направления
                mov     #BLKDIR, R2     ; │движения чёрных шариков
                mov     RNDVL2, R3      ; │
                call    RANDOM          ; ┘

                mov     #42237, R1      ; зададим координаты моего
                mov     R1, KRDMYS      ; шарика
                movb    Spr7, R0        ; и выведем его на экран
                call    FIGURS          ; вывод спрайта
                                        ; вход: R0 - мл.байт - код спрайта (его первый байт)
                                        ;       R1 - адрес вывода спрайта
                                        ; портит R2
                clr     @#L3610
                clrb    @#BlackBalls    ; пока чёрных шариков нету
                movb    #1., @#CountToBlkBall
                movb    #2, @#DLITSN

                call    OUTCHK          ; выведем текущий счёт
                call    OUTTCK          ; выведем общий счёт
                call    OUTTIM          ; выведем время жизни

                mov     #10., R1
                sub     @#GameClass, R1
                asl     R1              ; * 20.
                asl     R1
                mov     R1, R0
                asl     R1
                asl     R1
                add     R0, R1
                                                ; ┐установим число попыток
                cmp     @#GameNum, #1           ; │
                beq     1$                      ; │
                cmp     @#LivesNum, #2          ; │
                bge     2$                      ; │
                mov     #2, R1                  ; │
1$:             mov     R1, @#LivesNum          ; ┘
2$:             call    OUTPOP                  ; и выведем его

                call    OUTWHS                  ; выведем белые шарики
ContinueAfterDeath:
                clr     @#LiveTime
                clrb    @#TicksToOneSec
; это игровой цикл
                mov     @#GameSpeed, @#177706   ; установка таймера
1$:             mov     #34, @#177712           ;
                call    OUTBLS                  ; вывод чёрного шарика, если время пришло
                call    SOUND                   ; звук
                call    MOVBLS                  ; перемещение чёрных шариков
                call    MOVWHS                  ; перемещение белых шариков
                call    MOVING                  ; перемещение моего шарика
2$:             tstb    @#177712                ; ждём таймер
                bpl     2$                      ;
                br      1$                      ; и так, пока цикл не прервётся


; вывод текущего счёта
OUTCHK:         mov     #76637, R1
                mov     @#CurrentScore, R2
                jmp     OUT10

OUTTCK:         mov     #76614, R1              ; ┐выведем общий счёт
OUTTC2:         mov     @#TotalScore, R2        ; │
                jmp     OUT10                   ; ┘
; вывод числа попыток
OUTPOP:         mov     #40014, R1
                mov     #StrLives, R2
                call    PUTS
                mov     @#LivesNum, R2
                jmp     OUT10

; вывод номера игры
OUTIGR:         mov     #40001, R1
                mov     #StrGame, R2
                call    PUTS
                mov     @#GameNum, R2
                jmp     OUT10

; вывод времени жизни
OUTTIM:         mov     #40040, R1
                mov     @#LiveTime, R2
                jmp     OUT10

; вывод спрайта
; вход: R0 - мл.байт - код спрайта (его первый байт)
;       R1 - адрес вывода спрайта
; портит R2
FIGURS:         mov     R0, -(SP)
; у спрайтов 0..3 бит 4 == 0, и биты 1,0 - порядковый номер
; у спрайтов 4..7 бит 4 == 1, и биты 1,0 - порядковый номер
                mov     R0, R2
                bic     #177774, R2     ; оставляем мл два бита, там порядковый номер спрайта
                bic     #177767, R0     ; выделяем бит 4
                asr     R0              ; сдвигаем его в бит 3
                bis     R0, R2          ; получаем порядковый номер спрайта 0..7
                mov     R2, R0          ; умножаем
                asl     R0              ;
                asl     R0              ;
                add     R2, R0          ; на 5
                add     #SPRTAB, R0
                movb    (R0)+, (R1)
                movb    (R0)+, 100(R1)
                movb    (R0)+, 200(R1)
                movb    (R0)+, 300(R1)
                movb    (R0)+, 400(R1)
                mov     (SP)+, R0
                return

SPRTAB:
                        ;00000000
                        ;00000000
                        ;00000000
                        ;00000000
                        ;00000000
Spr0:           .byte   000, 000, 000, 000, 000 ; 0 пустое пространство
                        ;10100101
                        ;00000000
                        ;10000001
                        ;00000000
                        ;10100101
Spr1:           .byte   245, 000, 201, 000, 245 ; 1 чёрный шарик
                        ;01100110
                        ;10011001
                        ;00100100
                        ;10011001
                        ;01100110
Spr2:           .byte   146, 231, 044, 231, 146 ; 2 захваченная территория
                        ;11100111
                        ;11111111
                        ;01111110
                        ;11111111
                        ;11100111
Spr3:           .byte   347, 377, 176, 377, 347 ; 3 мой шарик в пустом пространстве
                        ;00011000
                        ;01100110
                        ;11000011
                        ;01100110
                        ;00011000
Spr4:           .byte   030, 146, 303, 146, 030 ; 4 белый шарик
                        ;10011001
                        ;00000000
                        ;10000001
                        ;00000000
                        ;10011001
Spr5:           .byte   231, 000, 201, 000, 231 ; 5 наружная стена
                        ;01001010
                        ;10000001
                        ;00000000
                        ;10000001
                        ;01010010
Spr6:           .byte   112, 201, 000, 201, 122 ; 6 свой хвост
                        ;11111111
                        ;11111111
                        ;11111111
                        ;11111111
                        ;11111111
Spr7:           .byte   377, 377, 377, 377, 377 ; 7 мой шарик на захваченной территории

                .even

;нарисование игрового поля
FIELD:          movb    Spr5, R0                ; рисуем наружную стену
                mov     #41500, UPPER
                mov     #75600, LOWER
                mov     #00, LEFTB
                mov     #77, RIGHTB
                call    FILL$

                movb    Spr2, R0                ; рисуем захваченную территорию
                mov     #42200, UPPER
                mov     #75100, LOWER
                mov     #01, LEFTB
                mov     #76, RIGHTB
                call    FILL$

                movb    #0, R0                  ; рисуем пустое пространство
                mov     #43400, UPPER
                mov     #73700, LOWER
                mov     #03, LEFTB
                mov     #74, RIGHTB
                call    FILL$
                return

;вход:  UPPER верхняя граница
;       LOWER нижняя граница
;       LEFTB левая граница
;       RIGHTB правая граница
;       R0  фигура заполнения
FILL$:          mov     #SPRTAB, R2     ; находим нужный спрайт по его первому байту
12$:            cmpb    (R2), R0
                beq     11$
                add     #5, R2
                br      12$

11$:            mov     R2, FIG         ; найденный адрес запоминаем
                call    SETS            ; подключаем буфер
                mov     #100000, R4     ; адрес буфера
                mov     R4, R5
                call    RAND2           ; выход: R1 - случайное число
                bic     #177770, R1
                inc     R1
                mov     R1, R3          ; получим число 1..8.
10$:            call    ININ            ; формируем случайный адрес в заданных пределах
                mov     R1, (R5)+
                sob     R3, 10$

L2:             cmp     R4, R5          ; адреса кончились?
                bhis    0$              ; да - выходим
                mov     #SearchView, R3 ; направления просмотра пространства вокруг точки
                mov     (R4)+, R1       ; берём очередной адрес

L1:             mov     R1, R0
                bic     #177700, R0     ; смещение в строке текущей точки
                add     (R3)+, R1       ; адрес точки которую проверим
                mov     R1, R2
                bic     #177700, R2     ; смещение в строке проверяемой точки (x)
                sub     R2, R0          ; граничные условия
                beq     4$
                cmp     #77, R0         ; пропускаем
                beq     3$
                cmp     #-77, R0
                beq     3$

4$:             mov     R1, R0          ; адрес точки которую проверим
                bic     R2, R0          ; (y)
                cmp     (PC)+, R0       ; проверим, чтобы в пределы входило
UPPER:          .word   0
                bhi     3$
                cmp     (PC)+, R0
LOWER:          .word   0
                blo     3$
                cmp     (PC)+, R2
LEFTB:          .word   0
                bhi     3$
                cmp     (PC)+, R2
RIGHTB:         .word   0
                blo     3$

                mov     (PC)+, R0       ; если входит - рисуем на этом месте спрайт
FIG:            .word   0
                cmpb    (R0), (R1)      ; если на этом месте уже фигура
                beq     3$              ; пропускаем
                mov     R1, (R5)+       ; иначе адрес запомним
                movb    (R0)+, (R1)     ; а фигуру рисуем
                movb    (R0)+, 100(R1)
                movb    (R0)+, 200(R1)
                movb    (R0)+, 300(R1)
                movb    (R0)+, 400(R1)
3$:             cmp     #SearchView+10, R3
                bhi     L1
                br      L2

0$:             jmp     SETN

;выход: R1 - откорректированный адрес
ININ:           call    RAND2           ; выход: R1 - случайное число
                mov     R1, R2
                clrb    R2
                bic     R2, R1          ; тут младший байт случайного числа
                swab    R2              ; тут старший байт случайного числа
                bic     #300, R2        ; x = 0..77
                mov     R2, -(SP)
                bic     #300, R1        ; y = 0..77
                cmp     R1, #60
                blos    01$
                mov     #60, R1         ; y = 0..60
01$:            ;умножим на 5
                mov     R1, R2
                asl     R2
                asl     R2
                add     R2, R1
                ;умножим на 100
                swab    R1
                ror     R1
                asr     R1              ; y *= 0500
                add     UPPER, R1       ; прибавим верхнюю границу
                mov     (SP)+, R2
0$:             cmp     R1, UPPER       ; и корректируем, если координаты выходят за пределы
                bhis    1$
                add     #100, R1
                br      0$

1$:             cmp     R1, LOWER
                blos    2$
                sub     #100, R1
                br      1$

2$:             cmp     R2, LEFTB
                bhis    3$
                inc     R2
                br      2$

3$:             cmp     R2, RIGHTB
                blos    4$
                dec     R2
                br      3$

4$:             bis     R2, R1          ;формируем адрес
                return


;вывод большими буквами
;вход:  R0 - адрес строки
;       R1 - адрес вывода
HIOUT:          mov     R1, -(SP)       ; сперва сформируем строку в буфере
                call    SETS
                mov     #100000, R1
                mov     R1, -(SP)
                clr     -(SP)
00$:            clr     R3
                bisb    (R0)+, R3
                beq     2$
                inc     (SP)
                mov     #FONT-500, R2
                tstb    R3
                bpl     1$
                sub     #500, R2
1$:             asl     R3
                add     R3, R2
                asl     R3
                asl     R3
                add     R3, R2
                mov     R0, -(SP)
                mov     #12, R3
3$:             movb    (R2)+, R5
                mov     #10, R4
0$:             asr     R5
                ror     R0
                asr     R0
                sob     R4, 0$
                mov     R0, (R1)
                mov     R0, 100(R1)
                add     #200, R1
                sob     R3, 3$
                sub     #2376, R1
                mov     (SP)+, R0
                br      00$

2$:             mov     (SP)+, R0       ; количество символов в строке
                mov     (SP)+, R4       ; а потом красиво выведем
                mov     (SP)+, R1
                asl     R0
                beq     4$
                mov     #177774, @#HiOutMask
                mov     #10, -(SP)
8$:             mov     R1, -(SP)
                mov     R4, -(SP)
                mov     @#HiOutMask, R2
                mov     #4, -(SP)
7$:             mov     #5, R3
6$:             mov     R0, -(SP)
5$:             movb    (R4)+, R5
                bicb    R2, R5
                movb    R5, (R1)+
                sob     R0, 5$
                mov     (SP)+, R0
                sub     R0, R1
                sub     R0, R4
                add     #400, R1
                add     #400, R4
                sob     R3, 6$
                mov     #3000, R3
                sob     R3, .
                sub     #2300, R4
                sub     #2300, R1
                sec
                ror     R2
                asr     R2
                dec     (SP)
                bne     7$
                clr     (SP)+
                asl     @#HiOutMask
                asl     @#HiOutMask
                mov     (SP)+, R4
                mov     (SP)+, R1
                dec     (SP)
                bne     8$
                clr     (SP)+
4$:
SETN:           mov     #16000, @#177716
                return
SETS:           mov     #17400, @#177716
                return

; выбор случайного направления движения
; Вход: R1 - количество шариков
;       R2 - адрес таблицы параметров шариков
;       R3 - случайное число
RANDOM:         mov     #3, R4
                bic     R3, R4
                ror     R3
                ror     R3
                asl     R4
                mov     DIRECT(R4), (R2)
                cmp     (R2)+, (R2)+ ; R2+=4 и элемент внесения случайности в бит С
                sob     R1, RANDOM
                return

; вывод на экран белых шариков
; по их текущим координатам
OUTWHS:         movb    @#WhiteBalls, R4 ; количество белых шариков
                movb    Spr4, R0        ; белый шарик
4$:             mov     R4, R1          ; номер * 4
                asl     R1
                asl     R1
                mov     WHTBK1-4(R1), R1 ; координата текущего шарика
                call    FIGURS          ; вывод спрайта
                                        ; вход: R0 - мл.байт - код спрайта (его первый байт)
                                        ;       R1 - адрес вывода спрайта
                                        ; портит R2
                sob     R4, 4$
                return

;вывод чёрного шарика, если время пришло
OUTBLS:         cmpb    @#TicksToOneSec, #50. ; прошла секунда?
                blt     5422$           ; нет ещё, выходим
                clrb    @#TicksToOneSec ; прошла, обнуляем счётчик
                inc     @#LiveTime      ; прожили ещё одну секунду
                call    OUTTIM          ; вывод времени жизни
                decb    @#CountToBlkBall ; считаем секунды
                bgt     5422$           ; пока меньше минуты, выходим
                movb    #60., @#CountToBlkBall ; прошла минута, инициализируем счётчик
                incb    @#BlackBalls    ; увеличиваем количество чёрных шариков
                movb    @#BlackBalls, R4 ; берём количество
                asl     R4
                asl     R4
                add     #BLKBK1-4, R4
                mov     (R4), R1        ; получим адрес в таблице
5342$:          cmpb    Spr2, (R1)      ; по этому адресу захваченная территория?
                beq     5354$           ; да, всё нормально
                inc     R1              ; движемся вправо
                br      5342$           ; до тех пор, пока не попадём на неё

5354$:          movb    Spr1, R0        ; выводим чёрный шарик
                call    FIGURS          ; вывод спрайта
                                        ; вход: R0 - мл.байт - код спрайта (его первый байт)
                                        ;       R1 - адрес вывода спрайта
                                        ; портит R2
                cmpb    @#BlackBalls, #5 ; если чёрных шаров стало >=5
                bge     DeathBlack      ; то мой шарик убит
                mov     R1, (R4)        ; иначе сохраним адрес в таблице
                movb    #6, @#DLITSN    ; звук появления нового чёрного шарика
                call    SOUND
5422$:          return

; смерть от чёрного шарика
; в R1 - координаты нового, 5-го лишнего чёрного шарика
DeathBlack:     clr     @#L3610
                mov     R1, @#Tmp$1     ; текущий адрес лишнего чёрного шарика
                br      0Death1$
; смерть от белого шарика
DeathWhite:     tst     (SP)+           ; мой шарик убит
                clr     @#Tmp$1
0Death1$:       call    OOO             ; предсмертный крик моего шарика
; для вечной игры dec заменяем на tst
FRWRCM:         dec     @#LivesNum      ; уменьшаем попытки
                call    OUTPOP          ; выводим
                mov     #100000, R0
                sob     R0, .
                tst     @#LivesNum      ; попытки кончились?
                beq     5750$           ; да - переход
                clr     @#LiveTime      ; сбросим время жизни
                clrb    @#TicksToOneSec ; тики таймера начнём считать заново
                clrb    @#BlackBalls    ; чёрных шариков нет
                movb    #1., @#CountToBlkBall
                movb    #2, @#DLITSN
                call    L6560           ; шарик на место, а всё что нарисовано - стереть
                call    OUTTIM          ; вывод времени жизни

                movb    Spr2, R0        ; захваченная территория
                mov     @#Tmp$1, R1     ; адрес лишнего чёрного шарика
                beq     5622$           ; 0 - значит не то,
                cmpb    Spr1, (R1)      ; там чёрный шарик?
                bne     5622$           ; нет
                ; да - погасим его
                call    FIGURS          ; вывод спрайта
                                        ; вход: R0 - мл.байт - код спрайта (его первый байт)
                                        ;       R1 - адрес вывода спрайта
                                        ; портит R2
5622$:          mov     #4, R5          ; общее количество чёрных шариков
                mov     #StartCoordBkS, R3
                mov     #BLKBK1, R4
1$:             mov     (R4), R1        ; погасим чёрный шарик
                call    FIGURS          ; вывод спрайта
                                        ; вход: R0 - мл.байт - код спрайта (его первый байт)
                                        ;       R1 - адрес вывода спрайта
                                        ; портит R2
                mov     (R3)+, (R4)+    ; зададим его начальную координату
                tst     (R4)+
                sob     R5, 1$
                jmp     ContinueAfterDeath ; продолжим игру

; кончились попытки
5750$:          cmp     @#CurrentScore, #GRTOUP
                bge     LevelUp
                call    FIELD           ; всё сотрём
; конец игры
ENPIC:          mov     #45432, R1      ; ┐выведем большими буквами
                mov     #XONIX, R0      ; │XONIX
                call    HIOUT           ; ┘

                mov     #70420, R1      ; ┐выведем "результат"
                mov     #StrYrScore, R2 ; │
                call    PUTS            ; │
                call    OUTTC2          ; ┘и общий счёт

                bit     #400, FRWRCM
                beq     0$
                ; это вечная жизнь
                mov     #FUCK, R2
                mov     #52006, R1
                call    PUTS
                br      1$
0$:             ; это не вечная жизнь
                call    STOPOF
                call    INSTAB
                cmpb    R0, #ENDTAB
                bne     0NE
                call    OUTTAB
                mov     #72025, R1
                mov     #StrAnyKey, R2
                call    PUTS
                br      1EX

0NE:            mov     R0, -(SP)
                call    OUTTAB
                mov     #72030, R1
                mov     #StrYrName, R2
                call    PUTS
                mov     (SP)+, R0
                call    GETNME
                call    SAVETB
1$:             mov     #72025, R1
                mov     #StrAnyKey, R2
                call    PUTS
1EX:            call    STOPON

                call    EMT6
                jmp     NewGame              ; начнём сначала

STOPON:         mov     #200, @#177716
                return
STOPOF:         mov     #10200, @#177716
                return

; повышение уровня
LevelUp:        call    FIELD               ; всё сотрём
                mov     @#CurrentScore, R1  ; ┐ выделяем из
                mov     #10., R2            ; │ текущего счёта
                sub     @#GameClass, R2     ; │ количество
                call    MULT                ; │ процентов
                mov     #100., R2           ; │ равное скорости игры 0..9
                call    DIVD                ; ┘ == 10..1%
                mov     R1, R5
                beq     0N
0Y:             inc     @#TotalScore
                call    OUTTCK
                sob     R5, 0Y
0N:
                clr     @#CurrentScore      ; обнулим счёт
                call    OUTCHK
                clr     @#LiveTime          ; ┐обнулим время жизни
                call    OUTTIM              ; ┘

                movb    @#WhiteBalls, R1    ; ┐увеличение белых шариков
                inc     R1                  ; │
                cmp     R1, #17.            ; │а там не конец игры?
                beq     1ENDGM              ; │да - выйдем
                movb    R1, @#WhiteBalls    ; ┘

                mov     #55022, R1          ; ┐выведем большими буквами
                mov     #StrBonusGame, R0   ; │"призовая игра"
                call    HIOUT               ; ┘

                inc     @#LivesNum          ; ┐увеличим число попыток
                cmp     @#LivesNum, #2      ; │
                bge     3$                  ; │
                mov     #2, @#LivesNum      ; ┘
3$:             call    OUTPOP              ; и выведем
                ; инициализируем координаты чёрных шариков
                mov     StartCoordBkS+4, BLKBK1
                mov     StartCoordBkS+2, BLKBK2
                mov     StartCoordBkS+6, BLKBK3
                mov     StartCoordBkS  , BLKBK4
                jmp     ContinueGame        ; продолжим игру

1ENDGM:         call    FIELD
                jmp     ENPIC


;шарик на место, а всё что нарисовано - стереть
L6560:          mov     KRDMYS, R5      ; координаты моего шарика
                cmpb    Spr7, (R5)      ; там мой шарик на захваченной территории?
                beq     0$              ; да,
                cmpb    Spr3, (R5)      ; нет, на пустой?
                beq     1$              ; да,
                ; нет
                clr     @#L3610
                call    SetMyToStart    ; задаём начальные координаты моего шарика
                mov     R5, KRDMYS      ; сохраняем
                mov     R5, R1
                movb    Spr7, R0        ; рисуем
                call    FIGURS          ; вывод спрайта
                                        ; вход: R0 - мл.байт - код спрайта (его первый байт)
                                        ;       R1 - адрес вывода спрайта
                                        ; портит R2
; ищем по всему игровому полю хвост и стираем его
L4610:          mov     #42775, R1
                mov     Spr0, R0
                mov     #50, R4
2$:             add     #406, R1
                mov     #72, R5
3$:             cmpb    Spr6, (R1)      ; свой хвост
                bne     4$
                call    FIGURS          ; вывод спрайта
                                        ; вход: R0 - мл.байт - код спрайта (его первый байт)
                                        ;       R1 - адрес вывода спрайта
                                        ; портит R2
4$:             inc     R1
                sob     R5, 3$
                sob     R4, 2$
                return

0$:             mov     R5, R1
                movb    Spr2, R0        ; захваченная территория
                call    FIGURS          ; вывод спрайта
                                        ; вход: R0 - мл.байт - код спрайта (его первый байт)
                                        ;       R1 - адрес вывода спрайта
                                        ; портит R2
6$:             call    SetMyToStart
                mov     R5, R1
7$:             mov     R1, KRDMYS
                movb    Spr7, R0        ; мой шарик на захваченной территории
                jmp     FIGURS          ; вывод спрайта
                                        ; вход: R0 - мл.байт - код спрайта (его первый байт)
                                        ;       R1 - адрес вывода спрайта
                                        ; портит R2

1$:             mov     R5, R1
                mov     Spr0, R0        ; пустое пространство
                call    FIGURS          ; вывод спрайта
                                        ; вход: R0 - мл.байт - код спрайта (его первый байт)
                                        ;       R1 - адрес вывода спрайта
                                        ; портит R2
                call    L4610           ; ищем по всему игровому полю хвост и стираем его
                cmp     @#L3610, #42700
                bgt     5$
                clr     @#L3610
                br      6$

5$:             mov     @#L3610, R1
                cmpb    Spr2, (R1)      ; захваченная территория
                beq     7$
                br      6$

; установка моего шарика в начальную точку
; с учётом того, что там может быть чёрный шарик
SetMyToStart:   mov     #42237, R5          ; начальные координаты моего шарика
                cmpb    Spr2, (R5)          ; если там пусто (захваченная территория)
                beq     4$                  ; да - выйдем
                add     #500, R5            ; посмотрим, что под ним
                cmpb    Spr2, (R5)          ; пусто ?
                beq     4$                  ; да - выходим
                inc     R5                  ; что справа-внизу
                cmpb    Spr2, (R5)          ; пусто ?
                beq     4$                  ; да - выходим
                sub     #500, R5            ; а справа?
2$:             cmpb    Spr2, (R5)          ; пусто ?
                beq     4$                  ; да - выходим
                inc     R5                  ; нет - будем двигаться вправо, пока не станет пусто
                br      2$                  ; предполагается, что очень скоро станет.

4$:             return

SOUND:          tstb    @#DLITSN
                beq     0$
                mov     #177714, R1
                mov     #366, (R1)          ; регистр 11 - амплитуда канала B
                movb    #357, (R1)          ; значение 20 - волпак
                mov     #362, (R1)          ; регистр 15
                movb    #377, (R1)          ; значение 0
                decb    @#DLITSN
0$:             return

;перемещение чёрных шариков
MOVBLS:         decb    @#BlkBallSpeed      ; пора двигать?
                bmi     2$                  ; да
                return
2$:             movb    #2, @#BlkBallSpeed  ; возвращаем значение
                movb    @#BlackBalls, R3    ; сколько у нас чёрных шариков?
                beq     0$                  ; 0 - нечего двигать
1$:             mov     R3, R4
                asl     R4
                asl     R4
                add     #BLKBK1-4, R4
                call    BlacksCheck
                sob     R3, 1$
0$:             return

BlacksCheck:    mov     (R4)+, R5       ; адрес очередного чёрного шарика
                mov     #1, R0          ; смещение по горизонтали
                bit     #2, (R4)        ; куда движемся? бит 1 установлен у перемещения
                                        ; влево-вниз и влево-вверх
                beq     0$              ; 0 - вправо,
                neg     R0              ; !0 - влево
0$:             mov     #500, R1        ; смещение по вертикали
                tst     (R4)            ; куда движемся? >0 - вниз, <0 - вверх
                bpl     1$
                neg     R1              ; вверх
1$:             movb    Spr2, R2
                add     R0, R5          ; посмотрим, что по направлению движения по горизонтали
                cmpb    (R5), R2        ; захваченная территория?
                bne     2$              ; нет
                sub     R0, R5          ; вернём как было
                add     R1, R5          ; теперь посмотрим, что по направлению движения по вертикали
                cmpb    (R5), R2        ; захваченная территория?
                beq     3$              ; да
                neg     R1              ; нет - шарик меняет направление
                br      4$

3$:             add     R0, R5          ; теперь проверим, что там по ходу движения
                cmpb    (R5), R2        ; захваченная территория?
                beq     5$              ; да - продолжим движение
                neg     R1              ; нет - шарик меняет направление

2$:             neg     R0              ; шарик меняет направление
4$:             cmpb    Spr1, (R5)      ; столкнулся с чёрным шариком?
                bne     00$             ; нет
                .word   213             ; да - звук чёрный:чёрный
                br      01$
; если чёрный шарик наткнётся на мой, когда он без движения,
; то столкновение не считается
00$:            .word   211             ; звук чёрный:стена
01$:            add     R0, R1
                mov     R1, (R4)        ; сохраним новое направление
                return                  ; и выходим

                ; вокруг вообще чисто, продолжаем движение, направление не меняется
5$:             mov     -(R4), R1       ; старый адрес чёрного шарика
                mov     R5, (R4)        ; новый адрес сохраним в таблице
                movb    R2, R0          ; стираем его на старом месте
                call    FIGURS          ; вывод спрайта
                                        ; вход: R0 - мл.байт - код спрайта (его первый байт)
                                        ;       R1 - адрес вывода спрайта
                                        ; портит R2
                mov     R5, R1
                movb    Spr1, R0        ; и выводим на новом
                jmp     FIGURS          ; вывод спрайта
                                        ; вход: R0 - мл.байт - код спрайта (его первый байт)
                                        ;       R1 - адрес вывода спрайта
                                        ; портит R2


;перемещение белых шариков
MOVWHS:         movb    @#WhiteBalls, R3 ; количество белых шариков
1$:             mov     R3, R4
                asl     R4
                asl     R4
                add     #WHTBK1-4, R4   ; адрес параметров шарика
                call    WhitesCheck     ; проверка на помехи движению шарика
                bcc     0$              ; всё в порядке
                .word   214             ; конец моему шарику
                jmp     DeathWhite

0$:             sob     R3, 1$
                return

WhitesCheck:    mov     (R4)+, R5       ; адрес очередного белого шарика
                mov     #1, R0          ; смещение по горизонтали
                bit     #2, (R4)        ; куда движемся? бит 1 установлен у перемещения
                                        ; влево-вниз и влево-вверх
                beq     1$              ; 0 - вправо,
                neg     R0              ; !0 - влево
1$:             mov     #500, R1        ; смещение по вертикали
                tst     (R4)            ; куда движемся? >0 - вниз, <0 - вверх
                bpl     2$
                neg     R1              ; вверх
2$:             add     R0, R5          ; посмотрим, что слева/справа
                cmpb    Spr3, (R5)      ; наткнулся на мой шарик
                beq     0Collision$     ; конец моему шарику
                cmpb    Spr6, (R5)      ; наткнулся на мой хвост
                beq     0Collision$     ; конец моему шарику
                tstb    (R5)            ; там пусто
                bne     0Reflect$

0X_ok$:         sub     R0, R5          ; теперь посмотрим, что там сверху/снизу
                add     R1, R5
                cmpb    Spr3, (R5)      ; наткнулся на мой шарик
                beq     0Collision$     ; конец моему шарику
                cmpb    Spr6, (R5)      ; наткнулся на мой хвост
                beq     0Collision$     ; конец моему шарику
                tstb    (R5)            ; там пусто
                bne     3$
                ; по бокам чисто
0Y_ok$:         add     R0, R5          ; теперь проверим, что там по ходу движения
                cmpb    Spr3, (R5)      ; наткнулся на мой шарик
                beq     0Collision$     ; конец моему шарику
                cmpb    Spr6, (R5)      ; наткнулся на мой хвост
                beq     0Collision$     ; конец моему шарику
                tstb    (R5)            ; там пусто
                bne     7$
                ; вокруг вообще чисто, продолжаем движение
9$:             mov     -(R4), R1       ; старый адрес белого шарика
                mov     R5, (R4)        ; новый адрес
                movb    Spr0, R0        ; стираем его на прежнем месте
                call    FIGURS          ; вывод спрайта
                                        ; вход: R0 - мл.байт - код спрайта (его первый байт)
                                        ;       R1 - адрес вывода спрайта
                                        ; портит R2
                mov     R5, R1
                movb    Spr4, R0        ; рисуем на новом месте
                call    FIGURS          ; вывод спрайта
                                        ; вход: R0 - мл.байт - код спрайта (его первый байт)
                                        ;       R1 - адрес вывода спрайта
                                        ; портит R2
                br      0ExitOK$        ; и выходим

3$:             neg     R1              ; белый шарик меняет направление по вертикали
                br      4$
7$:             neg     R1              ; белый шарик меняет направление по вертикали
0Reflect$:      neg     R0              ; белый шарик меняет направление по горизонтали
4$:             cmpb    Spr4, (R5)      ; наткнулся на другой белый шарик
                bne     5$
                .word   212             ; звук белый:белый
                br      6$

5$:             .word   210             ; звук белый:стена
6$:             add     R0, R1
                mov     R1, (R4)        ; сохраним новое направление

0ExitOK$:       tst     (PC)+
0Collision$:    sec
                return

;перемещение моего шарика
MOVING:         bit     @#177716, #100
                bne     0$
                mov     KRDMYS, R1
                mov     R1, R5
                mov     @#177662, R2
                cmp     #32, R2         ; ↑
                beq     0GoUp
                cmp     #31, R2         ; →
                beq     0GoRight
                cmp     #33, R2         ; ↓
                beq     0GoDown
                cmp     #10, R2         ; ←
                beq     0GoLeft
                ; нажато что-нибудь другое - игнорировать
0$:             return

0GoUp:          sub     #500, R5
                br      1$

0GoRight:       inc     R5
                br      1$

0GoDown:        add     #500, R5
                br      1$

0GoLeft:        dec     R5              ; вычисляем новый адрес
1$:             ; проверим, что на том месте, куда надо переместиться
                cmpb    Spr7, (R1)      ; движемся по захваченной территории?
                bne     0Attack
                ; да - проверим на близость чёрного шарика
                movb    Spr1, R2
                cmpb    -500(R1), R2    ; сверху
                beq     0MeetToBlack
                cmpb    1(R1), R2       ; справа
                beq     0MeetToBlack
                cmpb    500(R1), R2     ; снизу
                beq     0MeetToBlack
                cmpb    -1(R1), R2      ; слева
                beq     0MeetToBlack
                ; мой шарик движется по захваченной территории
                cmpb    Spr1, (R5)      ; встретились с чёрным шариком?
                beq     0MeetToBlack
                cmpb    Spr2, (R5)      ; там пусто?
                beq     0SafeMove
                cmpb    Spr4, (R5)      ; встретился с белым шариком?
                beq     0MeetToWhite    ; да, непруха
                                        ; это когда вылетаешь с захваченной области на пустое
                                        ; пространство, а там - сразу белый шарик
                tstb    (R5)            ; пусто?
                beq     0UnsafeMove     ; вылетел на захват территории
                return

0MeetToBlack:   .word   214             ; звук от встречи с чёрным шариком
                jmp     DeathBlack

0MeetToWhite:   mov     R1, @#L3610     ; начало хвоста
0MeetToWhite$S: .word   214             ; звук от встречи с белым или чёрным шариком
0SelfDead:      jmp     DeathWhite

                ; движется по захваченному пространству
0SafeMove:      movb    Spr2, R0        ; на старом месте нарисуем захваченное пространство (сотрём свой шарик)
                call    FIGURS          ; вывод спрайта
                                        ; вход: R0 - мл.байт - код спрайта (его первый байт)
                                        ;       R1 - адрес вывода спрайта
                                        ; портит R2
                movb    Spr7, R0        ; на новом месте нарисуем свой шарик
                br      0FIG
                ; захватывает территорию
0Catching:      movb    Spr6, R0        ; рисуем хвост на старом месте
                br      0FIGSS
                ; движение по пустому пространству
0UnsafeMove:    mov     R1, @#L3610     ; сохраним координату начала захвата территории
                movb    Spr2, R0        ; на старом месте нарисуем захваченное пространство (сотрём свой шарик)
0FIGSS:         call    FIGURS          ; вывод спрайта
                                        ; вход: R0 - мл.байт - код спрайта (его первый байт)
                                        ;       R1 - адрес вывода спрайта
                                        ; портит R2
                movb    Spr3, R0        ; на новом месте нарисуем свой шарик в пустом пространстве
0FIG:           mov     R5, KRDMYS      ; сохраним новую координату
                mov     R5, R1
                jmp     FIGURS          ; вывод спрайта
                                        ; вход: R0 - мл.байт - код спрайта (его первый байт)
                                        ;       R1 - адрес вывода спрайта
                                        ; портит R2

; мой шарик движется по пустому пространству и захватывает территорию
0Attack:        cmpb    Spr1, (R5)      ; встретились с чёрным шариком?
                beq     0MeetToBlack    ; да, непруха
                                        ; это когда залетаешь на захваченную территорию из пустого
                                        ; пространства, а там - сразу чёрный шарик
                tstb    (R5)            ; пусто?
                beq     0Catching
                cmpb    Spr4, (R5)      ; встретился с белым шариком?
                beq     0MeetToWhite$S
                cmpb    Spr6, (R5)      ; наткнулся на свой хвост
                beq     0SelfDead
                cmpb    Spr2, (R5)      ; достиг захваченной территории
                beq     0SuccessCatch
                return

                ;успешно захватил кусок территории
0SuccessCatch:  cmp     R5, @#L3610     ; если тут же вернулся туда, откуда вышел
                beq     0SelfDead       ; то умер
                mov     R5, KRDMYS
                movb    Spr6, R0        ; на старом месте нарисуем хвост
                call    FIGURS          ; вывод спрайта
                                        ; вход: R0 - мл.байт - код спрайта (его первый байт)
                                        ;       R1 - адрес вывода спрайта
                                        ; портит R2
                mov     R5, R1
                movb    Spr7, R0        ; на новом месте нарисуем свой шарик в захваченном пространстве
                call    FIGURS          ; вывод спрайта
                                        ; вход: R0 - мл.байт - код спрайта (его первый байт)
                                        ;       R1 - адрес вывода спрайта
                                        ; портит R2
                mov     #42775, R1
                movb    Spr2, R0
                mov     #50, R4         ; по всему игровому полю ищем
4$:             add     #406, R1        ; спрайты хвоста
                mov     #72, R5         ; и заменяем их на спрайты захваченной территории
3$:             cmpb    Spr6, (R1)
                bne     2$
                call    FIGURS          ; вывод спрайта
                                        ; вход: R0 - мл.байт - код спрайта (его первый байт)
                                        ;       R1 - адрес вывода спрайта
                                        ; портит R2
                inc     @#TotalScore    ; и увеличиваем счёт на их количество
                inc     @#CurrentScore
2$:             inc     R1
                sob     R5, 3$
                sob     R4, 4$
; начинаем заполнение захваченного пространства
                movb    @#WhiteBalls, R3
                call    SETS
                mov     #100000, R4
                mov     R4, R5
                mov     #WHTBK1, R1     ; сохраним координаты белых шаров
5$:             mov     (R1)+, (R5)+    ; от них начнём поиск
                tst     (R1)+
                sob     R3, 5$
                mov     #1, R2          ; код, которым заполняется пустое пространство
                                        ; в котором есть белые шарики
6$:             cmp     R4, R5          ; конец массива?
                bge     9$              ; да -выходим
                mov     #SearchView, R3
                mov     (R4)+, R1       ; очередной адрес
7$:             add     (R3)+, R1       ; следующая координата
                tstb    (R1)            ; там пусто?
                bne     8$              ; нет
                movb    R2, (R1)        ; да - пометим
                mov     R1, (R5)+       ; координату сохраним
8$:             cmp     R3, #SearchView+10
                blo     7$
                br      6$

9$:             call    SETN
                mov     #42775, R1      ; теперь по всему игровому полю
                movb    Spr2, R0        ; ищем пустые помеченные клетки
                mov     #50, R4         ; и заменяем их на захваченную территорию
10$:            add     #406, R1
                mov     #72, R5
11$:            tstb    (R1)            ; там пусто?
                bne     12$             ; нет
                ; если пусто - то это теперь захваченная территория
                call    FIGURS          ; вывод спрайта
                                        ; вход: R0 - мл.байт - код спрайта (его первый байт)
                                        ;       R1 - адрес вывода спрайта
                                        ; портит R2
                inc     @#TotalScore
                inc     @#CurrentScore
                br      13$

12$:            cmpb    (R1), #1        ; там спец код?
                bne     13$             ; нет, там какая-то фигура
                clrb    (R1)            ; да - очищаем
13$:            inc     R1
                sob     R5, 11$
                sob     R4, 10$
; всё, закончили
                call    OUTCHK
                call    OUTTCK
                cmp     @#CurrentScore, #GRTOUP ; уровень повышать пора?
                blt     14$             ; нет ещё
                clr     (SP)+
                jmp     LevelUp         ; да - повышаем

14$:            return

TRP100:         mov     R5, -(SP)
                mov     R4, -(SP)
                mov     R3, -(SP)
                mov     R2, -(SP)
                mov     R1, -(SP)
                mov     R0, -(SP)
                call    TIMER
                incb    @#TicksToOneSec     ; счётчик тиков
                tstb    @#NOBEEP
                bne     0$
                call    BEEPER
0$:             mov     (SP)+, R0
                mov     (SP)+, R1
                mov     (SP)+, R2
                mov     (SP)+, R3
                mov     (SP)+, R4
                mov     (SP)+, R5
                rti
;часы
TIMER:          mov     #40070, R0
                decb    @#TAKT
                beq     2$                  ; 0 - время пришло
                cmpb    @#TAKT, #24.        ; прошло пол секунды?
                beq     0$                  ; да - отметим
                mov     (SP)+, PC

2$:             movb    #48., @#TAKT        ; инициализируем счётчик
                ;и идём выводить время
4:              call    ADDSEC              ; +1 секунда
                mov     #MINSEC, R1
                mov     #100, R4
                call    CLKL
                inc     R0
                call    CLKL
                inc     R0
                call    CLKL
                sub     #10, R0
0$:             mov     #10, R1             ; мигающее двоеточие
                xor     R1, 302(R0)
                xor     R1, 602(R0)
                mov     (SP)+, PC

CLKL:           mov     PC, -(SP)
                movb    (R1)+, R3           ; цифра
                asl     R3
                mov     R3, R2
                asl     R3
                asl     R3
                add     R2, R3
                add     #FONT+240, R3
                mov     #5, R2
0$:             movb    (R3)+, (R0)
                add     R4, R0
                movb    (R3)+, (R0)
                add     R4, R0
                sob     R2, 0$
                sub     #1177, R0
                mov     (SP)+, PC

ADDSEC:         mov     #MINSEC+6, R1
                mov     #10., R4
                incb    -(R1)       ;единицы секунд
                cmpb    (R1), R4
                blo     0EXIT
                clrb    (R1)
                incb    -(R1)       ;десятки секунд
                cmpb    (R1), #6
                blo     0EXIT
                clrb    (R1)
                incb    -(R1)       ;единицы минут
                cmpb    (R1), R4
                blo     0EXIT
                clrb    (R1)
                incb    -(R1)       ;десятки минут
                cmpb    (R1), #6
                blo     0EXIT
                clrb    (R1)
                incb    -(R1)       ;единицы часов
                cmp     (R1), (PC)+
                .byte   2, 4
                bne     0$
                clr     (R1)
                mov     (SP)+, PC

0$:             cmpb    (R1), R4
                blo     0EXIT
                clrb    (R1)
                incb    -(R1)       ;десятки часов
0EXIT:          mov     (SP)+, PC

;десятичный вывод числа на экран.
;вход:  R2 - число
;       R1 - адрес экрана
OUT10:          mov     R5, -(SP)
                mov     R4, -(SP)
                mov     R3, -(SP)
                mov     R0, -(SP)
                mov     #CONST, R3
                clr     R5
                clr     -(SP)
4$:             mov     (R3)+, R4
                beq     10$
                clr     R0
2$:             sub     R4, R2
                bcs     3$
                inc     R0
                br      2$

3$:             add     R4, R2
                bis     R0, R5
                bne     0$
                cmp     #1, R4
                bne     4$
0$:             add     #'0, R0
                call    PUTCH
                inc     (SP)
                br      4$

10$:            mov     #5, R5
                sub     (SP)+, R5
                beq     02$
                mov     #40, R0
01$:            call    PUTCH
                sob     R5, 01$
02$:            mov     (SP)+, R0
                mov     (SP)+, R3
                mov     (SP)+, R4
                mov     (SP)+, R5
                return
CONST:          .word   10000., 1000., 100., 10., 1, 0

;вход:  R1 - адрес экрана
;       R2 - адрес строки
PUTS:           mov     R0, -(SP)
1$:             movb    (R2)+, R0
                beq     0$
                call    PUTCH
                br      1$

0$:             mov     (SP)+, R0
                return

;вход:  R0 - код
;       R1 - адрес
PUTCH:          mov     R0, -(SP)
                mov     R2, -(SP)
                mov     #FONT-500+1, R2
                bic     #177400, R0
                tstb    R0
                bpl     0$
                sub     #500, R2
0$:             asl     R0
                add     R0, R2
                asl     R0
                asl     R0
                add     R0, R2
                mov     #4, R0
1$:             movb    (R2)+, (R1)
                movb    (R2)+, 100(R1)
                add     #200, R1
                sob     R0, 1$
                sub     #777, R1
                mov     (SP)+, R2
                mov     (SP)+, R0
                return

; генератор как бы случайных чисел
RAND2:          swab    (PC)+
RAN:            .word   0
                incb    RAN+1
MM:             add     #0, RAN
                rolb    RAN
                add     #3337, MM+2
                mov     RAN, R1
                return



;работа с таблицей рекордов

LOADTB:         jsr     R5, @#PUSHA
                mov     #3, R2
                br      401$
;запись таблицы рекордов
SAVETB:         jsr     R5, @#PUSHA
                mov     #2, R2
401$:           mov     #320, R0
                mov     R0, R1
                mov     R2, (R0)+
                mov     #MSGTOP, (R0)+
                mov     #ENDTAB-MSGTOP, (R0)+
                mov     #NAMRES, R2
0$:             movb    (R2)+, (R0)+
                bne     0$
                mov     @SCREEN, -(SP)  ; сохраним содержимое ячейки перехвата сообщений об ошибках
                mov     @OWERWR, -(SP)  ; сохраним прошлый режим перезаписи файлов
                mov     #ARET, @SCREEN  ; блокируем вывод сообщений об ошибках
                mov     @#OWERDT, @OWERWR ; устанавливаем режим перезаписи файлов
                emt     36
                mov     (SP)+, @OWERWR
                mov     (SP)+, @SCREEN
ARET:           return

; раздвижка таблицы
; выход: R0 - адрес заполняемого элемента
;        если R0=ENDTAB, то после этой процедуры выход
INSTAB:         mov     #ENDTAB, R0
                mov     R0, R1
3$:             sub     #16., R1        ; длина записи в таблице

                cmp     @#TotalScore, (R1)
                blos    0EXIT
                mov     R0, R2
                mov     R1, R3
                cmp     #ENDTAB, R0
                beq     0$
                mov     #16., R4
1$:             movb    (R3)+, (R2)+
                sob     R4, 1$
0$:             mov     R1, R3
                mov     @#TotalScore, (R3)+
                mov     #12., R4        ; размер поля имени
2$:             movb    #40, (R3)+
                sob     R4, 2$
                clr     (R3)+
                mov     R1, R0
                cmp     R1, #TOPTAB
                bhi     3$
0EXIT:          return

; вывод таблицы рекордов в окошке
OUTTAB:         ; нарисуем окошко
                mov     #SCRADT, R1     ; адрес верхнего левого угла
                mov     #26, R3         ; ширина окна в словах

                call    WLN1
                call    WLN2
                call    WLN3

                mov     #15, R5
3$:             call    WLN4
                sob     R5, 3$

                mov     #144, R5
7$:             mov     R3, R4
                mov     #001674, (R1)+
6$:             clr     (R1)+
                sob     R4, 6$
                mov     #037300, (R1)+
                add     #20, R1
                sob     R5, 7$

                call    WLN4
                call    WLN3
                call    WLN2
                call    WLN1
                mov     #SCRADT+410, R1
                mov     #MSGTOP, R0
                call    OUTS

; вывод списка
OUTREC:         mov     #SCRADT+2004, R2 ; адрес экрана
                mov     #TOPTAB, R3
                mov     #10., R4
                clr     R5

0$:             inc     R5
                mov     R2, R1
                mov     R2, -(SP)
                mov     #5, R2
                mov     R5, R0
                cmp     #1, R4
                bne     1$
                tst     -(R1)
1$:             call    OUT102          ; порядковый номер
                mov     #'., R0
                call    PUTCH2
                cmp     (R1)+, (R1)+
                mov     R3, R0
                tst     (R0)+
                call    OUTS            ; имя
                tst     (R1)+
                mov     (R3), R0
                call    OUT102          ; счёт
                mov     (SP)+, R2
                add     #1200, R2
                add     #16., R3
                sob     R4, 0$
                return

WLN1:           mov     R3, R4
                tst     (R4)+
1$:             clr     (R1)+
                sob     R4, 1$
                br      001$
WLN2:           mov     R3, R4
                mov     #177774, (R1)+
2$:             mov     #-1, (R1)+
                sob     R4, 2$
                mov     #37777, (R1)+
                br      001$
WLN3:           mov     R3, R4
                mov     #125274, (R1)+
4$:             mov     #125252, (R1)+
                sob     R4, 4$
                mov     #037252, (R1)+
                br      001$
WLN4:           mov     R3, R4
                mov     #177674, (R1)+
5$:             mov     #-1, (R1)+
                sob     R4, 5$
                mov     #037377, (R1)+
001$:           add     #16., R1
                return

; приём строки с клавиатуры /регистры не сохраняет/
; вход: R0 - адрес в памяти
;       R1 - адрес экрана
;       R2 - мл. байт длина строки
EMT10:          clr     R4              ; флаг большой буквы
                mov     R0, R3

0$:             mov     #20000, R0
                mov     1100(R1), R5
                mov     #47776, 1100(R1)
6$:             tstb    @#KEYCOD
                bne     5$
                sob     R0, 6$
                mov     R5, 1100(R1)
                mov     #20000, R0
8$:             tstb    @#KEYCOD
                bne     7$
                sob     R0, 8$
                br      0$

5$:             mov     R5, 1100(R1)
7$:             call    INKEY
                cmpb    #12, R0         ; это ввод?
                beq     10$             ; да - переход
                cmpb    #30, R0         ; это забой?
                bne     0CHR$           ; нет, значит буквы?
                ; обрабатываем удаление символа
                tst     R4              ; мы в начале строки?
                beq     0$              ; да - нечено делать
                cmpb    -(R4), (R2)+    ; R4--, R2++
                movb    #40, -(R3)      ; удаляем последний символ
                tst     -(R1)
                mov     #40, R0         ; и стираем с экрана
                call    PUTCH2
                br      0$

0CHR$:          bitb    #140, R0        ; если не буква, не принимать
                beq     0$

                tst     R4              ; мы в начале строки?
                bne     1$              ; нет
                ; нарисуем первую букву заглавной
                tstb    R0
                bmi     4$
2$:             bicb    #40, R0
                br      3$
                ; остальные - маленькими
1$:             tstb    R0
                bmi     2$
4$:             bisb    #40, R0
3$:             movb    R0, (R3)+
                call    PUTCH2
                tst     (R1)+
                inc     R4
                sob     R2, 0$
10$:            return

; получение имени /регистры не сохраняет/
; вход: R0 - адрес заполняемой записи
GETNME:         clr     @#177660
                mov     R0, R1
                tst     (R0)+
                sub     #TOPTAB, R1     ; адрес экрана где рисовать
                asl     R1
                asl     R1
                asl     R1
                mov     R1, R2
                asl     R1
                asl     R1
                add     R2, R1
                add     #SCRADT+2012, R1
                mov     #12., R2
                call    EMT10           ; введём имя
                mov     #100, @#177660
                return

; вывод символа (обычный, шириной 2 байта)
; вход: R0 - код
;       R1 - адрес экрана
PUTCH2:         jsr     R5, @#PUSHA
                bic     #177400, R0     ; оставляем мл.байт
                mov     #FONT-500, R2   ; шрифт
                bitb    #140, R0        ; это печатный символ?
                beq     01$             ; нет - выход
                tstb    R0              ; верхняя половина таблицы?
                bpl     02$             ; нет
                sub     #500, R2        ; да - ещё корректируем
02$:            asl     R0              ; * 10.
                add     R0, R2
                asl     R0
                asl     R0
                add     R0, R2
                mov     #10., R0        ; высота
03$:            movb    (R2)+, R3       ; берём данные
                mov     #8., R4         ; расширяем байт в слово
04$:            asrb    R3
                ror     R5
                asr     R5
                sob     R4, 04$
                mov     R5, (R1)        ; выводим на экран
                add     #100, R1
                sob     R0, 03$         ; и так весь символ
01$:            return

; вывод ASCIZ строки
; вход: R0 - адрес строки
;       R1 - адрес экрана
OUTS:           mov     R0, -(SP)
                mov     R2, -(SP)
                mov     R0, R2
1$:             movb    (R2)+, R0
                beq     0$
                call    PUTCH2
                tst     (R1)+
                br      1$

0$:             mov     (SP)+, R2
                mov     (SP)+, R0
                return

; десятичный вывод числа на экран
; вход: R0 - число
;       R1 - адрес экрана
;       R2 - число выводимых символов
OUT102:         jsr     R5, @#PUSHA
                mov     R2, -(SP)
                mov     R0, R2
                mov     #CONST, R3
                clr     R5              ; счётчик цифр в числе, выведенных на экран
                mov     #5, R4          ; максимальное количество цифр в числе
4$:             clr     R0              ; аккумулятор
2$:             sub     (R3), R2        ; вычисляем очередной разряд
                blo     3$
                inc     R0
                br      2$

3$:             add     (R3)+, R2
                tst     R0              ; есть что-то?
                bne     0$              ; да, выводим
                tst     R5              ; нет, а это первый 0?
                bne     0$              ; нет, просто выводим на экран
                cmp     #1, R4          ; да, а разряд последний?
                bne     1$              ; нет, пропускаем
0$:             inc     R5              ; считаем выведенную цифру
                add     #'0, R0         ; выводим
                call    PUTCH2
                tst     (R1)+           ; двигаем адрес экрана
                dec     (SP)            ; уменьшаем счётчик выводимых символов
1$:             sob     R4, 4$
                mov     R1, 6(SP)       ; адрес экрана будет возвращён
                sub     #5, R5
                neg     R5              ; сколько цифр недовывели?
                beq     5$              ; нисколько, все 5 вывели
                mov     #40, R0         ; забиваем пробелами остаток
6$:             call    PUTCH2
                tst     (R1)+
                dec     (SP)            ; уменьшаем счётчик выводимых символов
                blt     5$              ; если уже < 0, то хватит выводить
                sob     R5, 6$
5$:             clr     (SP)+
                return

; умножение
; вход:  R2 - множитель
;        R1 - множимое
; выход: R0:R1 - результат
MULT:           mov     #16., R5
                mov     R1, R0
                clr     R1
1$:             asl     R1
                rol     R0
                bcc     0$
                add     R2, R1
0$:             sob     R5, 1$
                return

; деление
; вход:  R0:R1 - делимое
;        R2 - делитель
; выход: R1 - целая часть, R0 - остаток
DIVD:           mov     #16., R5
0$:             asl     R1
                rol     R0
                cmp     R0, R2
                blo     1$
                inc     R1
                sub     R2, R0
1$:             sob     R5, 0$
                return

; 4-х битный ковокс через AY
OOO:            incb    @#NOBEEP        ; выключаем звучание сэмплов
                mov     #177714, R1
                mov     #370, (R1)
                clrb    (R1)
                mov     #OOOD, R2       ; массив данных
                mov     #2048., R0      ; размер
                mov     #366, (R1)      ; выбираем регистр
1$:             movb    (R2)+, (R1)     ; посылаем данные
                mov     #11, R3         ; тон
                sob     R3, .
                sob     R0, 1$          ; весь массив
                movb    #377, (R1)      ; и в конце 0, чтобы замолчало
                clrb    @#NOBEEP        ; разрешаем звучание сэмплов
                return

T100EN:         bic     #40000, @#PALREG
                br      0$
T100DS:         bis     #40000, @#PALREG
0$:             mov     @#PALREG, @#177662
                return

                .END


