;это мой тетрис
;по моему не хватает блока заставки и вообще, код ужасен
;зачем-то сделано, чтоб на БК10 нельзя было работать
;чего я хотел, уже не помню

VAR1    =100        ;ширина экрана в байтах
WIDTH   =10.        ;ширина стакана
HEIGHT  =20.        ;высота стакана
ADRSTK  =40400      ;адрес верхнего левого угла стакана
ADRPDS  =51754      ;адрес вывода подсказки
ADRMNU  =61352      ;базовый адрес меню
ADRWN   =67421      ;адрес вывода окошка 'ввода имени'
ADRWN2  =62020      ;адрес вывода окошка 'чтение/запись'
ADRWN3  =62023      ;адрес вывода окошка 'выход?(д/н)'
SPRHI   =14         ;высота спрайта в строках
SPRHEI  =1400       ;высота спрайта в байтах
SPRWID  =3          ;ширина спрайта в байтах
TONXLV  =10.        ;количество сгоревших линий до следующего уровня

TOPSTK:         jmp     BEGIN

MSGTOP:         .asciz  "Таблица рекордов"
                .even
;таблица рекордов
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:
;начало области сохранения игры
;стакан
STAKAN:
LINE1:          .blkb   12.     ;WIDTH+2
LINE2:          .blkb   12.     ; первый и последний байты - стенки стакана
LINE3:          .blkb   12.
LINE4:          .blkb   12.
LINE5:          .blkb   12.
LINE6:          .blkb   12.
LINE7:          .blkb   12.
LINE8:          .blkb   12.
LINE9:          .blkb   12.
LINE10:         .blkb   12.
LINE11:         .blkb   12.
LINE12:         .blkb   12.
LINE13:         .blkb   12.
LINE14:         .blkb   12.
LINE15:         .blkb   12.
LINE16:         .blkb   12.
LINE17:         .blkb   12.
LINE18:         .blkb   12.
LINE19:         .blkb   12.
LINE20:         .blkb   12.
DNOSTK:         .blkb   12.

;переменные конфигурации
FLSND:          .byte   0       ; флаг звука
FLPODS:         .byte   0       ; флаг подсказки
FLCOLF:         .byte   0       ; флаг цветных линий
;просто переменные
KEYCOD:         .byte   0       ; код клавиши
LEVEL:          .byte   0       ; текущий уровень
TEKFIG:         .byte   0       ; номер текущей фигуры (0..6)
NXTFIG:         .byte   0       ; номер следующей фигуры (0..6)
TEKFCL:         .byte   0       ; цвет текущей фигуры (1..6)
NXTFCL:         .byte   0       ; цвет следующей фигуры (1..6)
L16720:         .byte   0       ; Какой-то штраф. если !=0, то от начисляемых очков вычитается 5
                                ; не используется, или я где-то пропустил функционал

YKSTK:          .byte   0       ; Y координата фигуры в стакане
XKSTK:          .byte   0       ; X координата фигуры в стакане
PRYK:           .byte   0       ; предыдущая координата Y, при прорисовке фигуры при перемещении
PRXK:           .byte   0       ; предыдущая координата X
YTKSTK:         .byte   0       ; временная координата X в стакане, для прорисовки
XTKSTK:         .byte   0       ; временная координата X в стакане, для прорисовки
PRHIF:          .byte   0       ; флаг истинности значений PRYK, PRXK, заодно и высота видимой части фигуры
POZPOW:         .byte   0       ; номер позиции фигуры при повороте 0..3
                .even

LINLEV:         .word   0       ; число сгоревших линий до повышения уровня
CHECK:          .word   0       ; текущий счёт
LINES:          .word   0       ; общий счётчик сгоревших линий
DELAY:          .word   0       ; задержка между перемещениями фигуры на одну линию вниз
DELAY2:         .word   0       ; задержка между горизонтальными перемещениями фигуры, коснувшейся дна
DELAY3:         .word   0       ; время, когда фигура ещё не застыла и её можно двигать горизонтально
L16710:         .word   0       ; счётчик штрафных очков, накапливается а потом вычитается от счёта за фигуру
L16712:         .word   0       ; штраф 1 за движение фигуры по стакану. т.е. чем больше она сама падает,
                                ; тем меньше очков будет начислено
L16714:         .word   0       ; штраф 2 за горизонтальное движение фигуры по дну стакана или застывшим фигурам
L16722:         .word   0
C716:           .word   0       ; регистр 177716 магнитофона по записи
PALREG:         .word   0       ; регистр 177662 по записи
ENDVAR:
;конец области сохранения игры

NAMRES:         .asciz  "P?tetris.res" ;имена должны начинаться с чётного адреса
                .even
NAMSVD:         .asciz  "P?tetris.svd"
MSGERR:         .asciz  "Нужен БК0011(М)!"<12>
MSGER2:         .asciz  "Нужен ANDOS v3.1 или MKDOS v3.15"<12>
                .even

;чтение/запись сохранения игры
IOSVD:          jsr     R5, PUSHA
                mov     #320, R2
                mov     R2, R1
                mov     R0, (R2)+
                mov     R2, R0
                mov     #STAKAN, (R0)+
                mov     #ENDVAR-STAKAN, (R0)+
                mov     #NAMSVD, R2
                br      0$
;чтение таблицы рекордов
LOADTB:         jsr     R5, PUSHA
                mov     #3, R2
                br      1$
;запись таблицы рекордов
SAVETB:         jsr     R5, PUSHA
                mov     #2, R2
1$:             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$
                emt     36
                return

BEGIN:          mov     #TOPSTK, SP
                call    INISET
                bvs     1$
                bcc     2$
                mov     #MSGER2, R1
                br      3$

1$:             mov     #MSGERR, R1
3$:             clr     R2
                emt     20
                halt

2$:             call    LOADTB      ;читаем таблицу рекордов
                ;тут надо какую-нибудь заставку или ещё что-нибудь
                ; какой-нибудь прессанукей

                call    INPUT       ;ждём нажатия какой-нибудь клавиши
NEWV4:          mov     #TOPSTK, SP
                clr     R0
                mtps    R0          ;сбрасываем приоритет
                clrb    LEVEL       ;выставляем начальный уровень
                call    GAME        ;игра
                call    NM2TAB      ;записать в таблицу рекордов
                br      NEWV4       ;и играть заново



;начальные установки
INISET:         cmpb    #300, @#177717  ;это БК11?
                bne     1$              ;если нет
                cmp     @#120170, #100000+310.   ;это ANDOS v3.1 или выше?
                bhis    3$              ;нет
                cmp     @#120004, #100000+315.   ;это MKDOS v3.15 или выше
                blo     2$
                mov     #100256, @#120074 ;запретим вывод на экран сообщений в mkdose
                mov     #"?:, R0
                br      4$

3$:             mov     #100256, @#120146 ;запретим вывод на экран сообщений в андосе
                mov     #"P?, R0
4$:             mov     R0, NAMRES      ;для автоматической перезаписи файла
                mov     R0, NAMSVD      ;у андоса и мкдоса разные префиксы
                mov     #200, C716      ;это копия выходного порта 177716
                call    SETVEC          ;установим вектора

                clrb    FLSND           ;выключим звук
                clrb    FLPODS          ;выключим подсказку
                clrb    FLCOLF          ;выключим признак цветных фигур
                mov     #40000, PALREG  ;зададим палитру 0 по умолчанию

RANDOM:         clr     @#177706        ;инициализируем таймер
RNDM2:          mov     #20, @#177712   ;для получения псевдослучайных чисел
                tst     (PC)+           ;выход с ok
1$:             sev                     ;бит V если БК10
                return
2$:             sec                     ;бит C если не ANDOS v3.1
                return

SETVEC:         mov     #200, @#62
                mov     #VEC60, @#60
                mov     @#62, @#276
                mov     @#60, @#274
                clrb    KEYCOD
                mov     #NEWV4, @#4
                return

VEC60:          mov     R0, -(SP)
                movb    @#177662, R0
                cmpb    #17, R0
                beq     1$
                cmpb    #16, R0
                bne     2$
1$:             movb    RCODE-16(R0), RUSLAT
                br      0$

2$:             cmpb    R0, #100
                blo     3$
                bisb    (PC)+, R0
RUSLAT:         .word   0
3$:             movb    R0, KEYCOD
0:              mov     (SP)+, R0
                rti
RCODE:          .byte   200, 0

CLS:            mov     #40000, R0
0$:             clr     (R0)+
                tst     R0
                bpl     0$
                return

GAME:           call    SETCNS          ;начальная установка параметров
                clrb    L16720
                call    CLRSTK          ;очищаем стакан
                call    SCREEN          ;перерисовываем экран
                mov     #300, R0
                mov     #1000, R1
                call    SOUND           ;звук начала игры
                clrb    KEYCOD          ;сбрасываем код нажатой клавиши

                call    GETFIG          ;получим номер фигуры
                movb    R0, NXTFIG      ;это будет следующая фигура
                call    GETCLF          ;получим номер цвета
                movb    R0, NXTFCL      ;это будет цвет следующей фигуры
                ;игровой цикл
0LOOP$:         call    GETFIG          ;получим номер фигуры
                movb    NXTFIG, TEKFIG  ;следующая фигура становится текущей
                movb    R0, NXTFIG      ;а это будет следующей

                call    GETCLF          ;получим номер цвета
                movb    NXTFCL, TEKFCL  ;следующий цвет станет текущим
                movb    R0, NXTFCL      ;а это будет следующий
                tstb    FLPODS          ;подсказку выводить?
                beq     1$              ;нет
                call    OUTPDS          ;да - выведем
1$:             clrb    POZPOW          ;начальная позиция поворота
                movb    #4, XKSTK       ;начальная координата X
                clrb    YKSTK           ;начальная координата Y

                clrb    PRHIF           ;флаг истинности значений PRYK, PRXK
                clr     L16710
                clr     L16722

                call    VERFRE          ;проверим, помещается ли фигура в начальном положении
                bcs     0END$           ;нет - стакан полон, конец игры
2$:             call    OUTFIG          ;выводим фигуру

                mov     DELAY, R5
                clr     R4
3$:             call    CNTRLK          ;обработка нажатий клавиатуры
                                        ;выход: R0 - признак перемещения фигуры,
                                        ;0 - не переместилась, не 0 - переместилась
                bcs     7$              ;сбросили фигуру вниз?
                tst     R0              ;фигура переместилась?
                beq     4$              ;нет
                mov     DELAY3, R4      ;да, тогда будет значение задержки 3
4$:             tst     R4              ;задержки нету? т.е. фигура не перемещалась
                beq     5$              ;нет
                dec     R4              ;есть - сосчитаем
5$:             sob     R5, 3$          ;и пока есть задержка 1
                                        ;крутимся в цикле обработки клавиш
                ;кончилась задержка 1
                incb    YKSTK           ;фигура сдвинулась на 1 вниз
                mov     #10, R0
                mov     #2, R1
                call    SOUND           ;звук движения фигуры
                call    VERFRE          ;проверим, помещается ли туда
                bcc     6$              ;да, помещается
                tst     R4              ;не помещается, а что задержка 3?
                beq     7$              ;кончилась
                mov     DELAY2, R5      ;нет ещё, тогда вместо задержки 1 будет задержка 2
                clr     R4              ;задержки 2 нет
                add     L16714, L16710  ;начисляем очки
                br      8$              ;

6$:             add     L16712, L16710  ;начисляем очки
                clr     L16722          ;фигура пока не застыла
                br      2$              ;и идём выводить фигуру

7$:             clr     R5              ; задержка 3 кончилась, тогда и задержки 2 нет
                tst     L16722          ; фигура застыла?
                bne     9$              ; да
                mov     DELAY2, R5      ; даём шанс
                inc     L16722          ; двигать горизонтально
8$:             decb    YKSTK           ;в общем, пока фигура не упала ещё
                br      3$              ;снова идём обрабатывать клавиатуру
                ;тут как я подозреваю, даётся возможность двигать фигуру горизонтально
                ;вдоль уже уложенных фигур.

9$:             call    CalcScore       ;начисляем очки в счёт
                movb    YKSTK, R0       ;делаем звук упавшей фигуры
                asl     R0
                mov     #100, R1
                call    SOUND
                call    LINCHK
                br      0LOOP$
;game over
0END$:          return

SCREEN:         call    SWSCR0          ; отображаем экран 0
                mov     #76000, @#177716 ; в это время чистим экран 1
                call    CLS
                call    SWSCR1          ; отображаем экран 1
                mov     #16000, @#177716 ; в это время чистим экран 0
                call    CLS
                call    PANEL           ; п/п вывода панели
                call    OUTSCR          ; выводим всю информацию
                movb    FLSND, R0       ; флаг звука
                mov     #2, R1
                call    INSM            ; выделение пункта меню
                                        ; вход:  R0 - значение флага
                                        ;        R1 - номер пункта 1..6
                inc     R1
                movb    FLPODS, R0      ; флаг подсказки
                call    INSM            ; выделение пункта меню
                                        ; вход:  R0 - значение флага
                                        ;        R1 - номер пункта 1..6
                jmp     SWSCR0          ; отображаем экран 0

OUTSCR:         call    OUTSTK          ; рисуем стакан
                call    OUTLEV          ; вывод класса
                call    OUTLIN          ; вывод числа строк
;вывод счета
OUTCHK:         mov     #47262, R1
                mov     CHECK, R0
                br      0OUT
;вывод класса
OUTLEV:         mov     #44666, R1
                movb    LEVEL, R0
                mov     R2, -(SP)
                mov     #3, R2
                br      1OUT
;вывод числа строк
OUTLIN:         mov     #46062, R1
                mov     LINES, R0
0OUT:           mov     R2, -(SP)
                mov     #5, R2
1OUT:           call    OUT10           ;десятичный вывод числа на экран
                                        ;вход:  R0 - число
                                        ;       R1 - адрес экрана
                                        ;       R2 - число выводимых символов
                mov     (SP)+, R2
                return

;проверка, можно ли вывести фигуру
VERFRE:         jsr     R5, PUSHA
                movb    TEKFIG, R0      ; номер текущей фигуры 0..6
                movb    POZPOW, R1      ; позиция вращения 0..3
                asl     R0
                asl     R0
                add     R1, R0
                asl     R0              ; Nf * 8 + Nr * 2
                mov     FIGIMG(R0), R0  ; битовая карта фигуры
                mov     #4, R5          ; число видимых линий фигуры
                movb    YKSTK, R2       ; Y
                dec     R2              ; y = Y-1 - верхняя линия
3$:             tst     R2              ; y >=0 ?
                bge     0$              ; да. всю фигуру видно на экране
                mov     #4, R4          ; ширина фигуры
2$:             asl     R0              ; смотрим фигуру
                bcs     1$              ; есть клетка в невидимой части, значит фигуру вывести нельзя
                sob     R4, 2$          ; и так всю линию
                inc     R2              ; переходим к следующей линии
                dec     R5              ; уменьшаем число видимых линий
                br      3$

0$:             tst     R5              ; сколько линий видимо?
                beq     4$              ; нисколько, и это не ошибка, просто выход
                asl     R2
                movb    XKSTK, R3       ; X
                dec     R3              ; x = X-1 - левый столбец
8$:             mov     STKLIN(R2), R1  ; адрес линии в стакане
                add     R3, R1          ; адрес клетки в стакане
                mov     #4, R4          ; ширина фигуры - 4 клетки
7$:             asl     R0              ; смотрим бит
                bcs     5$              ; что-то есть - переход
                inc     R1              ; пусто - идём к следующей клетке
                br      6$

5$:             tstb    (R1)+           ; а в стакане там есть что-то?
                bmi     1$              ; стенка или упавшая фигура, значит фигуру вывести нельзя
6$:             sob     R4, 7$          ; и так всю линию
                tst     (R2)+           ; переходим к следующей линии
                sob     R5, 8$          ; и так всю фигуру
4$:             tst     (PC)+           ; ничего не мешает
1$:             sec                     ; что-то мешает
                return

;входной параметр в R0: 0 - стереть, номер фигуры - нарисовать
;и координаты в XTKSTK, YTKSTK
OFS:            bic     #177540, R0     ;чистим  ненужные биты
                mov     R1, -(SP)
                movb    YTKSTK, R1
                swab    R1              ;R1=YTKSTK*400
                bisb    XTKSTK, R1      ;R1=YTKSTK*400+XTKSTK
                mov     R1, -(SP)       ;R1=(YTKSTK*400+XTKSTK)*3=
                asl     R1              ;       =YTKSTK*1400+XTKSTK*3
                add     (SP)+, R1       ;
                add     #ADRSTK+SPRWID, R1 ;высчитаем, где на экране вывести спрайт
                call    OUTSPR
                mov     (SP)+, R1
                return

;прорисовка фигуры на экране
OUTFIG:         jsr     R5, PUSHA
                movb    TEKFIG, R0      ; номер текущей фигуры 0..6
                movb    POZPOW, R1      ; позиция вращения 0..3
                asl     R0
                asl     R0
                add     R1, R0
                asl     R0              ; Nf * 8 + Nr * 2
                mov     FIGIMG(R0), R0  ; битовая карта фигуры
;здесь в массиве стакана формируется фигура
                mov     #4, R5          ; сколько линий фигуры видно
                movb    YKSTK, R2       ; Y
                dec     R2              ; y = Y-1 - верхняя линия
1$:             tst     R2              ; y >=0 ?
                bge     2$              ; да. всю фигуру видно на экране
                inc     R2              ; нет, сдвинемся на линию вниз
                asl     R0
                asl     R0
                asl     R0
                asl     R0
                dec     R5
                br      1$

2$:             mov     R5, -(SP)       ; число отображаемых линий фигуры
                mov     R2, -(SP)       ; начальная координата y фигуры
                movb    XKSTK, R3       ; X
                dec     R3              ; x = X-1 - левый столбец
                mov     R3, -(SP)       ; начальная координата x фигуры
                asl     R2
3$:             mov     STKLIN(R2), R1  ; адрес линии в стакане
                add     R3, R1          ; адрес клетки в стакане
                mov     #4, R4          ; ширина фигуры - 4 клетки
4$:             asl     R0              ; смотрим бит
                bcc     6$              ; пусто - переход
                tstb    (R1)            ; не пусто, а что там было?
                beq     5$              ; пусто
                bisb    #40, (R1)       ; что-то было, бит 5 установим, эту клетку не надо рисовать
                bicb    #100, (R1)      ; бит 6 сбросим, эту клетку не надо стирать
                br      6$

5$:             movb    TEKFCL, (R1)    ; если было пусто, то просто текущий цвет фигуры
6$:             inc     R1              ; переходим к следующей клетке
                sob     R4, 4$          ; и так всю линию
                tst     (R2)+           ; переходим к следующей линии
                sob     R5, 3$          ; и так всю фигуру
;здесь стираются ненужные фрагменты, по предыдущим координатам
                movb    PRHIF, R5       ; флаг истинности предыдущих координат, заодно и высота видимой части фигуры
                beq     10$             ; прошлая фигура не видна была, значит стирать нечего
                movb    PRYK, R2        ; предыдущая координата Y
                movb    PRXK, R3        ; предыдущая координата X
                movb    R2, YTKSTK      ; рабочая координата Y
                asl     R2
7$:             mov     STKLIN(R2), R1  ; адрес линии в стакане
                add     R3, R1          ; адрес клетки в стакане
                mov     #4, R4          ; ширина фигуры - 4 клетки
                movb    R3, XTKSTK      ; рабочая координата X
8$:             bitb    #100, (R1)      ; бит 6 есть?
                beq     9$              ; нету - переход
                clr     R0              ; есть, значит
                call    OFS             ; сотрём клетку
                clrb    (R1)            ; и в массиве изменения сделаем
9$:             inc     R1              ; переходим к следующей клетке
                incb    XTKSTK          ; корректируем рабочую координату
                sob     R4, 8$          ; и так всю линию
                tst     (R2)+           ; переходим к следующей линии
                incb    YTKSTK          ; корректируем рабочую координату
                cmpb    YTKSTK, #HEIGHT ; проверим, не вышли ли за пределы стакана
                bge     10$             ; вышли - прервать цикл
                sob     R5, 7$          ; и так всю фигуру
;здесь прорисовываются недостающие
10$:            mov     (SP)+, R3       ; начальная координата x фигуры
                movb    R3, PRXK        ; в следующий раз они станет предыдущей
                mov     (SP)+, R2       ; начальная координата y фигуры
                movb    R2, PRYK        ; в следующий раз они станет предыдущей
                mov     (SP)+, R5       ; число отображаемых линий фигуры
                movb    R5, PRHIF       ; флаг истинности предыдущих координат, заодно и высота видимой части фигуры
                beq     16$             ; если 0 - то фигура не видима, и рисовать её не надо
                movb    R2, YTKSTK      ; рабочая координата Y
                asl     R2
11$:            mov     STKLIN(R2), R1  ; адрес линии в стакане
                add     R3, R1          ; адрес клетки в стакане
                mov     #4, R4          ; ширина фигуры - 4 клетки
                movb    R3, XTKSTK      ; рабочая координата X
12$:            cmpb    TEKFCL, (R1)    ; в клетке только текущий цвет?
                bne     13$             ; нет
                movb    (R1), R0        ; да - значит надо просто нарисовать новую клетку
                call    OFS
                br      14$             ; и пойдём фиксировать клетку

13$:            bitb    #40, (R1)       ; бит 5 есть?
                beq     15$             ; нету, значит ничего делать не надо
                bicb    #40, (R1)       ; есть, значит там уже была клетка и тоже ничего делать не надо
14$:            bisb    #100, (R1)      ; зафиксируем клетку, она там уже по настоящему
15$:            inc     R1              ; переходим к следующей клетке
                incb    XTKSTK          ; корректируем рабочую координату
                sob     R4, 12$         ; и так всю линию
                tst     (R2)+           ; переходим к следующей линии
                incb    YTKSTK          ; корректируем рабочую координату
                sob     R5, 11$         ; и так всю фигуру
16$:            return

LINCHK:         jsr     R5, PUSHA
;тут фиксируется упавшая фигура
                movb    PRYK, R2
                movb    PRHIF, R5
                movb    PRXK, R3
                movb    R2, YTKSTK
                asl     R2
1$:             mov     STKLIN(R2), R1
                add     R3, R1
                mov     #4, R4
                movb    R3, XTKSTK
2$:             bitb    #100, (R1)+     ;клетка зафиксирована?
                beq     3$              ;нет
                movb    TEKFCL, -(R1)   ;да - сделаем из неё упавшую клетку
                bisb    #200, (R1)      ;текущего цвета
                movb    (R1)+, R0
                call    OFS             ;и нарисуем
3$:             incb    XTKSTK
                sob     R4, 2$
                tst     (R2)+
                incb    YTKSTK
                cmpb    YTKSTK, #HEIGHT
                bge     4$
                sob     R5, 1$
;тут удаляются полные строки
4$:             movb    PRHIF, R5
                movb    PRYK, R2
                movb    R2, YTKSTK
                asl     R2
                mov     #-1, -(SP)
5$:             mov     STKLIN(R2), R1

                movb    (R1)+, R0       ;берём цвет первой клетки линии
                bpl     9$              ;если не упавшая клетка - то линия не полная
                mov     #WIDTH-1, R4    ;ширина линии - 1
6$:             tstb    (R1)            ;текущая клетка упавшая?
                bpl     9$              ;нет
                tstb    FLCOLF          ;цветные линии включены?
                beq     7$              ;нет - значит сравнение на совпадение цвета игнорируем
                cmpb    (R1), R0        ;требуем совпадения цвета клеток по всей линии
                ;вариант с проверкой на цвет - извращение, просто нереально собрать полную линию
                ;из фигур одного цвета
                bne     9$
7$:             inc     R1
                sob     R4, 6$
                ;да, есть полная линия
                mov     R2, -(SP)       ;индекс линии сохраним в стеке
                call    L5224           ;увеличим счёт сгоревших линий
;сотрём линию на экране и в памяти
                mov     #WIDTH, R4
                clrb    XTKSTK
                mov     STKLIN(R2), R1
8$:             clr     R0
                call    OFS
                clrb    (R1)+
                incb    XTKSTK
                sob     R4, 8$
9$:             tst     (R2)+
                incb    YTKSTK
                cmpb    YTKSTK, #HEIGHT
                bge     10$
                sob     R5, 5$
;теперь в массиве пометим что прорисовать заново, что стереть
10$:            tst     (SP)            ;линии в стеке сохраняли?
                bmi     24$             ;нет
                mov     (SP)+, R0       ;да - достанем
                mov     R0, R2
11$:            dec     R2
                dec     R2              ;а это линия над удалённой
                bmi     16$             ;если такой не бывает, то пойдём дальше
                cmp     R2, (SP)        ;а если бывает, проверим, она тоже удалена?
                bgt     12$             ;нет
                tst     (SP)+           ;да - и её посчитаем
                br      11$             ;пойдём искать линию над удалёнными линиями

12$:            mov     STKLIN(R2), R3  ;адрес линии, с которой опускаются клетки
                mov     STKLIN(R0), R1  ;адрес линии, куда опускаются клетки
                mov     #WIDTH, R4
13$:            movb    (R3)+, (R1)     ;есть упавшая клетка? заодно и цвет скопируем, если есть
                bmi     14$             ;да
                bicb    #300, (R1)      ;нет
                bisb    #40, (R1)+      ;пометим, что тут должно быть пусто
                br      15$

14$:            bicb    #240, (R1)      ;да
                bisb    #100, (R1)+     ;пометим, что тут должна быть клетка
15$:            sob     R4, 13$
                dec     R0              ;подымемся на линию выше
                dec     R0
                br      11$
;кончились опускающиеся линии, или дошли до верха стакана
16$:            tst     R0              ;стакан кончился?
                bmi     19$             ;да - идём рисовать
                mov     STKLIN(R0), R1  ;почистим пространство стакана
                mov     #WIDTH, R4      ;над упавшими линиями
17$:            tstb    (R1)+
                beq     18$
                bicb    #300, -(R1)
                bisb    #40, (R1)+
18$:            sob     R4, 17$
                dec     R0
                dec     R0
                br      16$
;а тут прорисуем
19$:            clr     R2
                clrb    YTKSTK
20$:            mov     STKLIN(R2), R1
                mov     #WIDTH, R4
                clrb    XTKSTK
21$:            bitb    #40, (R1)       ;клетка помечена как пустая?
                beq     22$             ;нет
                clr     R0              ;да - стираем
                call    OFS
                clrb    (R1)+
                br      23$

22$:            bitb    #100, (R1)+     ;помечена как прорисовываемая?
                beq     23$             ;нет
                bisb    #200, -(R1)     ;да - пометим как упавшую
                bicb    #140, (R1)      ;удалим все флаги
                movb    (R1)+, R0
                call    OFS
23$:            incb    XTKSTK
                sob     R4, 21$
                tst     (R2)+
                incb    YTKSTK
                cmpb    YTKSTK, #HEIGHT
                blt     20$

24$:            clr     (SP)+
                return
;обработка нажатий клавиатуры
;выход: R0 - признак перемещения фигуры, 0 - не переместилась, !0 - переместилась
CNTRLK:         mov     R1, -(SP)
                mov     R5, -(SP)
                call    INKEY           ; получим код нажатой клавиши. если есть
                tst     R0              ; на клавишу нажимали?
                beq     1$              ; нет, выходим
                mov     #KEYS, R1       ; поиск кода в массиве
2$:             tstb    (R1)            ; кончились?
                beq     1$              ; да, выходим, нажали не то, что нам надо
                cmpb    (R1)+, R0       ; проверяем
                bne     2$              ; не то
                sub     #KEYS+1, R1     ; нашли
                ;делаем звук нажатой клавиши
                mov     R1, -(SP)
                mov     #100, R0
                mov     #4, R1
                call    SOUND
                mov     (SP)+, R1
                mov     R1, R0
                inc     R1
                asl     R0
                clr     R5
                ;входные параметры: R1 - порядковый номер кода клавиши в меню
                ;R5 - 0, на выходе если R5 не 0 - фигура переместилась
                call    @CTRSUB(R0)
                ;выходные параметры: R5 - признак перемещения фигуры
                ;C = 1, если сбросили фигуру вниз
                mov     R5, R0
                br      0$

1$:             clr     R0
0$:             mov     (SP)+, R5
                mov     (SP)+, R1
                return
;бросить фигуру вниз
MVDOWN:         incb    YKSTK           ;увеличиваем Y координату
                call    VERFRE          ;проверим, помещается ли там фигура
                bcs     00$             ;нет, хватит
                call    OUTFIG          ;выведем фигуру
                br      MVDOWN          ;и повторим
;фигуру влево
MVLEFT:         decb    XKSTK           ;уменьшаем Х координату
                call    VERFRE          ;проверим, помещается ли там фигура
                bcc     22$             ;да, все в норме
                incb    XKSTK           ;нет - вернём координату как было
                br      5022$
;фигуру вправо
MVRIGH:         incb    XKSTK           ;увеличиваем Х координату
                call    VERFRE          ;проверим, помещается ли там фигура
                bcc     22$             ;да, все в норме
                decb    XKSTK           ;нет - вернём координату как было
                br      5022$
;поворот фигуры
MVTURN:         movb    POZPOW, R1      ;позицию поворота сохраним
                incb    POZPOW          ;изменим позицию
                bicb    #374, POZPOW    ;возможно всего 4 варианта
                call    VERFRE          ;проверим, помещается ли фигура в таком положении
                bcc     22$             ;нет
                movb    R1, POZPOW      ;вернём позицию поворота как было
                br      5022$

22$:            call    OUTFIG          ;выведем фигуру на новой позиции
                inc     R5              ;флаг перемещения фигуры
5022$:          clc
00$:            return

;меню чтения/записи сохранения
GT1:            call    SETINS
                mov     R1, -(SP)
                call    STOPOF
                call    OUTWN2
2$:             call    INPUT
                cmpb    #3, R0      ;КТ - отмена
                beq     3$
                cmpb    #'^, R0     ;Ч - чтение сохранения
                bne     0$
                mov     #3, R0
                call    IOSVD
                call    OUTWN2
                call    OUTSCR
                br      400$

0$:             cmpb    #'Z, R0     ;З - запись сохранения
                bne     2$
                mov     #2, R0
                call    IOSVD
3$:             call    OUTWN2
                br      400$
;меню показа таблицы рекордов
GT2:            call    SETINS
                call    GETTAB
                br      215$
;меню выхода
GT3:            call    SETINS
                mov     R1, -(SP)
                call    STOPOF
                call    OUTWN3
2$:             call    INPUT
                cmpb    #3, R0
                beq     3$
                cmpb    #'N, R0
                beq     3$
                cmpb    #'D, R0
                bne     2$
                call    OUTWN3
                call    STOPON
                mov     #16000, @#177716
                mov     #42000, @#177662
                jmp     @#100000

3$:             call    OUTWN3
400$:           call    STOPON
                mov     (SP)+, R1
                br      215$

;меню паузы
PAUSE$:         call    SETINS
1$:             call    INKEY
                cmpb    PAUKEY, R0
                bne     1$
215$:           clr     R5
                clr     R0
                br      204$

;меню вкл./выкл. звука
SNDTRG:         comb    FLSND
                movb    FLSND, R0
                br      204$

;меню подсказки
SWHINT:         mov     R5, -(SP)
                mov     R4, -(SP)
                mov     R2, -(SP)
                mov     R1, -(SP)        ;сперва очистим место
                mov     #ADRPDS, R2
                mov     #7, R0
                mov     #4, R5
2$:             mov     R2, R1
                mov     #4, R4
1$:             call    OUTSPR
                add     #SPRWID, R1
                sob     R4, 1$
                add     #SPRHEI, R2
                sob     R5, 2$
                mov     (SP)+, R1
                mov     (SP)+, R2
                mov     (SP)+, R4
                mov     (SP)+, R5
                comb    FLPODS          ;подсказку выводить?
                beq     3$              ;нет
                call    OUTPDS          ;да - выведем
3$:             movb    FLPODS, R0
204$:           call    INSM            ;выделение пункта меню
                                        ;вход:  R0 - значение флага
                                        ;       R1 - номер пункта 1..6
                clc
                return

;меню ускорить
SPEDUP:         mov     R0, -(SP)
                mov     R1, -(SP)
                cmpb    LEVEL, #11      ;ускорять то есть куда?
                bge     0ND$            ;нет, и так уже максимум
                clr     LINLEV          ;досрочно заставим перейти на новый уровень
                br      0UL$

;увеличение числа сгоревших линий
L5224:          mov     R0, -(SP)
                mov     R1, -(SP)
                mov     R2, R0
                add     #20, R0
                asl     R0
                mov     #600, R1
                call    SOUND           ;озвучим сгоревшую линию
                inc     LINES           ;увеличиваем счётчик линий
                call    OUTLIN          ;выводим на экран
                cmpb    LEVEL, #11      ;уровень максимальный?
                bge     0ND$            ;да - нафиг
                dec     LINLEV          ;нет - уменьшаем счётчик до повышения уровня
                bne     0ND$            ;не 0, - не пора повышать уровень
0UL$:           incb    LEVEL           ;повышаем уровень
                call    OUTLEV          ;выведем на экран
                mov     #30, R0
                mov     #4000, R1
                call    SOUND           ;озвучим повышение уровня
                call    SetDelays       ;зададим задержки
                add     #TONXLV, LINLEV ;через TONXLV линий новое повышение уровня
0ND$:           mov     (SP)+, R1
                mov     (SP)+, R0
                clc     ;нужно при выходе из обработки команды меню SPEDUP
                return

;начальная установка параметров
SETCNS:         mov     R1, -(SP)
                mov     R0, -(SP)
                mov     #2, L16712
                mov     #1, L16714
                clr     CHECK           ; очищаем текущий счёт
                clr     LINES           ; очищаем общее число линий
                call    SetDelays
                clr     R1
                movb    LEVEL, R0
                beq     2$              ; если начинаем игру не с нуля
1$:             add     #TONXLV, R1     ; то следующее повышение уровня
                sob     R0, 1$          ; будет ещё не скоро.
2$:             add     #6, R1          ; первое повышение уровня через 6 линий
                mov     R1, LINLEV      ; линий до повышения уровня
                mov     (SP)+, R0
                mov     (SP)+, R1
                return
;установка значений задержек на данном уровне
SetDelays:      movb    LEVEL, R0       ; текущий уровень
                asl     R0
                mov     DLYTAB(R0), R0  ; задержка на текущем уровне
                mov     R0, DELAY
                asr     R0
                mov     R0, DELAY2
                cmp     R0, DLYLIM      ;если вторая задержка меньше заданного предела
                bge     1$
                mov     DLYLIM, DELAY2  ;то исправим ситуацию
1$:             mov     DELAY2, DELAY3
                return
;добавка к счёту
CalcScore:      mov     R0, -(SP)
                movb    LEVEL, R0       ; уровень
                movb    CHKADD(R0), R0  ; сколько очков даётся на уровне
                asr     L16710          ; штраф
                sub     L16710, R0      ; вычитаем штрафные очки
                bmi     1$              ; <0 - нечего начислять
                tstb    L16720          ; что?
                beq     2$              ; а ничего
                clrb    L16720          ; иначе
                sub     #5, R0          ; отнимаем ещё 5 очков
                bmi     1$              ; <0 - нечего начислять
2$:             add     R0, CHECK       ; начисляем очки
                call    OUTCHK          ; и выводим
1$:             mov     (SP)+, R0
                return

;вывод подсказки
OUTPDS:         jsr     R5, PUSHA
                movb    NXTFIG, R0       ;номер следующей фигуры
                asl     R0
                asl     R0
                asl     R0
                mov     FIGIMG(R0), R2
                mov     #ADRPDS, R3
                mov     #4, R5
3$:             mov     R3, R1
                mov     #4, R4
1$:             mov     #7, R0
                asl     R2
                bcc     0$
                movb    NXTFCL, R0       ;цвет следующей фигуры
0$:             call    OUTSPR
                add     #SPRWID, R1
                sob     R4, 1$
                add     #SPRHEI, R3
                sob     R5, 3$
                return

;вход:  R1 - тон
;       R2 - длительность
SOUND:          mov     R2, -(SP)
                mov     R3, -(SP)
                mov     R4, -(SP)
                mov     R1, -(SP)
                clr     R4              ;если звука нет, то звучать не будем
                tstb    FLSND           ;звук есть?
                beq     0$              ;нет
                mov     #140, R4        ;есть - будем звучать
0$:             mov     #10, R3
1$:             xor     R4, C716
                call    OUTPRT
                mov     R0, R2
4$:             cmp     #340, #340      ; задержка
                dec     R1
                bne     5$
                dec     R3
                beq     6$
                mov     (SP), R1
5$:             sob     R2, 4$
                br      1$

6$:             bic     R4, C716
                call    OUTPRT
3$:             mov     (SP)+, R1
                mov     (SP)+, R4
                mov     (SP)+, R3
                mov     (SP)+, R2
                return

INKEY:          clr     R0
                bisb    KEYCOD, R0
                clrb    KEYCOD
                return

INPUT:          call    INKEY
                tstb    R0
                beq     INPUT
                bicb    #177640, R0
                return

PUSHA:          mov     R4, -(SP)
                mov     R3, -(SP)
                mov     R2, -(SP)
                mov     R1, -(SP)
                mov     R0, -(SP)
                call    (R5)
                mov     (SP)+, R0
                mov     (SP)+, R1
                mov     (SP)+, R2
                mov     (SP)+, R3
                mov     (SP)+, R4
                mov     (SP)+, R5
                return
;получение цвета фигуры
;выход: R0 - цвет фигуры 1..6
GETCLF:         call    GETFIG
                tst     R0
                beq     GETCLF
                return
;получение номера фигуры
;выход: R0 - номер фигуры 0..6
GETFIG:         mov     #70, R0
                call    RND
                asr     R0
                asr     R0
                asr     R0
                cmp     #6, R0
                blo     GETFIG
                return
;вход:  R0 - верхняя граница
;выход: R0 - RND
RND:            mov     R2, -(SP)
                mov     R1, -(SP)
                mov     R0, -(SP)
                swab    (PC)+
RAN:            .word   153252
                incb    RAN
                rolb    RAN+1
                sub     @#177710, RAN
                mov     RAN, R0
RAN0:           add     #0, @#177706
                call    RNDM2
                bic     #140001, R0
                add     100000(R0), RAN0+2
                mov     (SP)+, R1
                mov     #100000, R2
1$:             cmp     R0, R1
                blos    0$
                bic     R2, R0
                asr     R2
                br      1$
0$:             mov     (SP)+, R1
                mov     (SP)+, R2
                return

;очистка стакана в памяти
CLRSTK:         mov     #STKLIN, R3     ; таблица адресов линий стакана
                mov     #HEIGHT, R2     ; высота стакана
1$:             mov     (R3)+, R0       ; очередной адрес
                dec     R0              ; левую стенку тоже считаем
                movb    #200, (R0)+     ; это левая стенка
                mov     #WIDTH, R1
0$:             clrb    (R0)+           ; внутри стакана пусто
                sob     R1, 0$
                movb    #200, (R0)+     ; это правая стенка
                sob     R2, 1$
                mov     (R3)+, R0       ; дно стакана
                dec     R0
                mov     #WIDTH+2, R1
2$:             movb    #200, (R0)+     ; целиком стенка
                sob     R1, 2$
                return

;вывод стакана по образу в памяти на экран
OUTSTK:         mov     #ADRSTK, R3     ; адрес верхнего левого угла стакана
                mov     #STKLIN, R4     ; адрес массива адресов линий стакана
                mov     #HEIGHT+1, R2   ; высота стакана + дно
1$:             mov     R3, R1          ; адрес экрана текущей линии
                mov     (R4)+, R5       ; адрес текущей линии
                dec     R5              ; стенку тоже выводить
                mov     R4, -(SP)
                mov     #WIDTH+2, R4    ; ширина стакана + стенки
0$:             movb    (R5)+, R0       ; очередной кубик
                bic     #177540, R0     ; чистим лишние биты
                call    OUTSPR          ; выводим спрайт кубика
                                        ; вход: R0 - номер спрайта
                                        ;       R1 - адрес экрана
                add     #SPRWID, R1     ; адрес вывода следующего кубика
                sob     R4, 0$          ; и так всю линию
                mov     (SP)+, R4
                add     #SPRHEI, R3     ; адрес следующей строки экрана
                sob     R2, 1$          ; и так весь стакан
                return

;вход:  R0 - номер спрайта
;       R1 - адрес экрана
;есть такие спрайты:
;0 - пустота в стакане
;200 - стенка стакана
;1 - красный кубик
;201- упавший красный кубик
;2 - зелёный кубик
;202- упавший зелёный кубик
;3 - синий кубик
;203- упавший синий кубик
;4 - жёлтый кубик
;204- упавший жёлтый кубик
;5 - фиолетовый кубик
;205- упавший фиолетовый кубик
;6 - голубой кубик
;206- упавший голубой кубик
;7 - спрайт чёрного цвета

OUTSPR:         mov     R2, -(SP)
                mov     R1, -(SP)
                mov     R0, -(SP)
                bic     #177400, R0
                aslb    R0              ;делаем из кодов спрайтов
                adc     R0              ;порядковый номер от 0 до 16
                asl     R0              ;затем умножаем на 44
                asl     R0
                mov     R0, R2
                asl     R2
                asl     R2
                asl     R2
                add     R0, R2
                add     #SPRITE, R2
                mov     #SPRHI, R0
0$:             movb    (R2)+, (R1)+
                movb    (R2)+, (R1)+
                movb    (R2)+, (R1)+
                add     #VAR1-SPRWID, R1
                sob     R0, 0$
                mov     (SP)+, R0
                mov     (SP)+, R1
                mov     (SP)+, R2
                return

;вывод символа
;вход:  R0 - код
;       R1 - адрес экрана
PUTCH:          jsr     R5, PUSHA
                bic     #177400, R0
                bitb    #140, R0
                beq     01$
                bitb    #200, R0
                beq     02$
                sub     #100, R0
02$:            sub     #40, R0
                asl     R0
                mov     R0, R2
                asl     R0
                asl     R0
                add     R2, R0
                add     #FONT, R0
                mov     #12, R2
03$:            movb    (R0)+, R3
                mov     #10, R4
04$:            asrb    R3
                ror     R5
                asr     R5
                sob     R4, 04$
                mov     R5, (R1)
                add     #100, R1
                sob     R2, 03$
01$:            return
;вывод ASCIZ строки
;вход:  R0 - адрес строки
;       R1 - адрес экрана
OUTS:           mov     R0, -(SP)
                mov     R2, -(SP)
                mov     R0, R2
1$:             movb    (R2)+, R0
                beq     0$
                call    PUTCH
                tst     (R1)+
                br      1$
0$:             mov     (SP)+, R2
                mov     (SP)+, R0
                return

CONST:          .word   10000., 1000., 100., 10., 1
;десятичный вывод числа на экран
;вход:  R0 - число
;       R1 - адрес экрана
;       R2 - число выводимых символов
OUT10:          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
                bne     0$
                cmp     #1, R4
                bne     1$
0$:             inc     R5
                add     #'0, R0
                call    PUTCH
                tst     (R1)+
                dec     (SP)
1$:             sob     R4, 4$
                mov     R1, 6(SP)
                sub     #5, R5
                neg     R5
                beq     5$
                mov     #40, R0
6$:             call    PUTCH
                tst     (R1)+
                dec     (SP)
                blt     5$
                sob     R5, 6$
5$:             clr     (SP)+
                return

SETINS:         movb    (PC), R0
;выделение пункта меню
;вход:  R0 - значение флага
;       R1 - номер пункта 1..6
INSM:           jsr     R5, PUSHA
                clr     R2
1$:             dec     R1
                beq     0$
                add     #1200, R2
                br      1$

0$:             add     #ADRMNU, R2
                mov     #12, R3
5$:             mov     #11, R1
                tstb    R0              ; флаг задействован?
                bne     2$              ; да - переход
3$:             bic     #52525, (R2)+   ; развыделим
                sob     R1, 3$
                br      4$

2$:             mov     (R2), R4        ; выделим
                clc
                ror     R4
                bis     R4, (R2)+
                sob     R1, 2$
4$:             add     #100-22, R2
                sob     R3, 5$
                return

;работа с таблицей рекордов
;вот это вызывается при нажатии пункта меню
GETTAB:         jsr     R5, PUSHA
                call    OUTTAB
                br      100$
;вот это в конце заносит или не заносит имя в таблицу
NM2TAB:         call    STOPOF          ;запретим кнопку стоп
                call    INSTAB          ;попробуем вставить имя
                cmp     R0, #ENDTAB     ;не вставилось?
                beq     1EXIT           ;то и нечего делать
                mov     R0, -(SP)
                call    OUTTAB          ;выведем таблицу рекордов
                mov     (SP)+, R0
                call    GETNME          ;спросим имя
                call    OUTREC          ;выведем новое имя
                call    SAVETB          ;сохраним таблицу
100$:           bit     #100, @#177716
                beq     100$
1$:             bit     #100, @#177716
                bne     1$
                mov     #16000, @#177716
                call    SWSCR0          ; отобразить экран 0
1EXIT:          jmp     STOPON          ;разрешим кнопку стоп

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

                cmp     CHECK, (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     CHECK, (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     #17400, @#177716 ;в окно0-экр.0, в окно1-экр.1
                mov     #40000, R0       ;скопируем экр.0 в экр.1
0$:             mov     (R0)+, 37776(R0)
                tst     R0
                bpl     0$
                mov     #76000, @#177716 ;в окно0 - экр.1
                ;теперь нарисуем окошко
                mov     #50410, R1       ;адрес верхнего левого угла
                mov     #26, R3          ;ширина окна в словах

                call    WLN1
                call    WLN2
                call    WLN3

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

                mov     #100., 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     #51020, R1
                mov     #MSGTOP, R0
                call    OUTS
                call    OUTREC
                jmp     SWSCR1

WLN1:           mov     R3, R4
                tst     (R4)+
1$:             clr     (R1)+
                sob     R4, 1$
                br      001$
WLN2:           mov     R3, R4
                mov     #177774, (R1)+
2$:             mov     #177777, (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     #177777, (R1)+
                sob     R4, 5$
                mov     #037377, (R1)+
001$:           add     #20, R1
                return


;вывод списка таблицы рекордов
OUTREC:         mov     #52414, 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          ;выводим последнюю 10ю позицию?
                bne     1$              ;нет
                tst     -(R1)           ;да - сдвинуть на символ влево, чтоб ровно все было
1$:             ;выведем порядковый номер
                call    OUT10           ;десятичный вывод числа на экран
                                        ;вход:  R0 - число
                                        ;       R1 - адрес экрана
                                        ;       R2 - число выводимых символов
                mov     #'., R0
                call    PUTCH
                cmp     (R1)+, (R1)+     ;отступ
                mov     R3, R0
                tst     (R0)+
                call    OUTS            ;выведем имя
                tst     (R1)+
                mov     (R3), R0        ;выведем счёт
                call    OUT10           ;десятичный вывод числа на экран
                                        ;вход:  R0 - число
                                        ;       R1 - адрес экрана
                                        ;       R2 - число выводимых символов
                mov     (SP)+, R2
                add     #1200, R2       ;на строку вниз
                add     #16., R3        ;к следующей записи
                sob     R4, 0$           ;и так все записи
                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)+    ;да. счётчик букв уменьшим, а длину вводимой строки наоборот - увеличим
                movb    #40, -(R3)      ;удалим последний символ в памяти
                tst     -(R1)           ;и на экране
                mov     #40, R0
                call    PUTCH
                br      0$              ;снова пойдём мигать курсором и ждать нажатия клавиши

0CHR:           bitb    #140, R0        ;если не буква,
                beq     0$              ;не принимать
                tst     R4              ;буква первая?
                bne     1$              ;нет
                ;нарисуем первую букву
                bitb    #200, R0        ;русская?
                bne     4$              ;да
2$:             bicb    #40, R0         ;латинская, очищаем бит - делаем заглавной
                br      3$              ;русская, очищаем бит - делаем строчной

1$:             bitb    #200, R0        ;не первая буква русская?
                bne     2$              ;да
4$:             bisb    #40, R0         ;латинская, устанавливаем бит - делаем строчной
                                        ;русская, устанавливаем бит - делаем заглавной
3$:             movb    R0, (R3)+       ;её в память
                call    PUTCH           ;и на экран
                tst     (R1)+           ;адрес экрана увеличим
                inc     R4              ;счётчик букв увеличим
                sob     R2, 0$          ;и пока лимит не иссяк - продолжим принимать буквы
10$:            return

;получение имени /регистры не сохраняет/
;вход:  R0 - адрес заполняемой записи
GETNME:         tst     (R0)+
                call    OUTWN           ;выведем окошко
                mov     R2, R1
                add     #1301, R1       ;адрес экрана где рисовать
                mov     R1, -(SP)
                mov     #12., R2
                call    EMT10           ;введём имя
                mov     #10., R3        ;┐ сотрём введённое имя
                mov     (SP)+, R4       ;│ в окошке спрайта
1$:             mov     R4, R1          ;│
                mov     #12., R2        ;│
0$:             clr     (R1)+           ;│
                sob     R2, 0$          ;│
                add     #100, R4        ;│
                sob     R3, 1$          ;┘
                ;затем сотрём окошко

;вывод/стирание спрайта-окошка 'ваше имя'
OUTWN:          mov     #WINNME, R1
                mov     #ADRWN, R2
                br      0OUTWN
;вывод/стирание спрайта-окошка 'чтение/запись'
OUTWN2:         mov     #WINSL, R1
                mov     #ADRWN2, R2
                br      0OUTWN
;вывод/стирание спрайта-окошка 'выход?(д/н)'
OUTWN3:         mov     #WINEX, R1
                mov     #ADRWN3, R2
;вывод/стирание спрайта-окошка
0OUTWN:         jsr     R5, PUSHA
                clr     R3
                bisb    (R1)+, R3       ;высота спрайта
                clr     R4
                bisb    (R1)+, R4       ;ширина спрайта в байтах
1$:             mov     R4, R5
0$:             movb    (R1), R0        ;обменяем данные
                movb    (R2), (R1)+     ;на экране и в памяти
                movb    R0, (R2)+
                sob     R5, 0$
                sub     R4, R2
                add     #100, R2
                sob     R3, 1$
                return

; запретим кнопку СТОП
STOPOF:         bis     #10000, C716
                br      OUTPRT
; разрешим кнопку СТОП
STOPON:         bic     #10000, C716
OUTPRT:         mov     C716, @#177716
                return


; отобразить экран 0
SWSCR0:         bic     #100000, PALREG
                br      0$
; отобразить экран 1
SWSCR1:         bis     #100000, PALREG
                br      0$
; включить таймер 50Гц
T100EN:         bic     #40000, PALREG
                br      0$
; выключить таймер 50Гц
T100DS:         bis     #40000, PALREG
0$:             mov     PALREG, @#177662
                return
;область данных
;образы фигур
;каждое слово - карта 4х4 бита положения фигуры
;4 слова - 4 вида поворота фигуры.
                ;фигура 0:      ■■
                ;               ■■
FIGIMG:         .word   003140  ;позиция 1  0000 0110 0110 0000
                .word   003140  ;позиция 2  0000 0110 0110 0000
                .word   003140  ;позиция 3  0000 0110 0110 0000
                .word   003140  ;позиция 4  0000 0110 0110 0000
                ;фигура 1:      ■■■■
                .word   007400  ;позиция 1  0000 1111 0000 0000
                .word   021042  ;позиция 2  0010 0010 0010 0010
                .word   007400  ;позиция 3  0000 1111 0000 0000
                .word   021042  ;позиция 4  0010 0010 0010 0010
                ;фигура 2:      ■■■
                ;                ■
                .word   007100  ;позиция 1  0000 1110 0100 0000
                .word   043100  ;позиция 2  0100 0110 0100 0000
                .word   047000  ;позиция 3  0100 1110 0000 0000
                .word   046100  ;позиция 4  0100 1100 0100 0000
                ;фигура 3:      ■■■
                ;                 ■
                .word   007040  ;позиция 1  0000 1110 0010 0000
                .word   062100  ;позиция 2  0110 0100 0100 0000
                .word   107000  ;позиция 3  1000 1110 0000 0000
                .word   042300  ;позиция 4  0100 0100 1100 0000
                ;фигура 4:      ■■■
                ;               ■
                .word   007200  ;позиция 1  0000 1110 1000 0000
                .word   042140  ;позиция 2  0100 0100 0110 0000
                .word   027000  ;позиция 3  0010 1110 0000 0000
                .word   142100  ;позиция 4  1100 0100 0100 0000
                ;фигура 5:       ■■
                ;               ■■
                .word   003300  ;позиция 1  0000 0110 1100 0000
                .word   106100  ;позиция 2  1000 1100 0100 0000
                .word   003300  ;позиция 3  0000 0110 1100 0000
                .word   106100  ;позиция 4  1000 1100 0100 0000
                ;фигура 6:      ■■
                ;                ■■
                .word   006140  ;позиция 1  0000 1100 0110 0000
                .word   023100  ;позиция 2  0010 0110 0100 0000
                .word   006140  ;позиция 3  0000 1100 0110 0000
                .word   023100  ;позиция 4  0010 0110 0100 0000

;адреса строк стакана
STKLIN:         .word   LINE1+1
                .word   LINE2+1
                .word   LINE3+1
                .word   LINE4+1
                .word   LINE5+1
                .word   LINE6+1
                .word   LINE7+1
                .word   LINE8+1
                .word   LINE9+1
                .word   LINE10+1
                .word   LINE11+1
                .word   LINE12+1
                .word   LINE13+1
                .word   LINE14+1
                .word   LINE15+1
                .word   LINE16+1
                .word   LINE17+1
                .word   LINE18+1
                .word   LINE19+1
                .word   LINE20+1
                .word   DNOSTK+1
                .word   0

DLYLIM:         .word   1100    ;минимальное значение задержки
;задержки на уровнях
DLYTAB:         .word   4000.
                .word   3000.
                .word   2500.
                .word   2000.
                .word   1500.
                .word   1250.
                .word   1000.
                .word   750.
                .word   500.
                .word   375.

CHKADD:         .byte   30, 33, 36, 41, 44, 47, 52, 55, 60, 63
;адреса переходов
CTRSUB:         .word   PAUSE$  ;пауза
                .word   SNDTRG  ;выкл. звук
                .word   SWHINT  ;подсказка
                .word   SPEDUP  ;ускорить
                .word   GT1     ;DISK
                .word   GT2     ;TABLE
                .word   GT3     ;EXIT
                .word   MVLEFT  ;влево
                .word   MVTURN  ;поворот
                .word   MVRIGH  ;вправо
                .word   MVDOWN  ;вниз
;управляющие кнопки
KEYS:
PAUKEY:         .byte   '1      ;пауза
                .byte   '2      ;выкл. звук
                .byte   '3      ;подсказка
                .byte   '4      ;ускорить
                .byte   '5      ;DISK
                .byte   '6      ;TABLE
                .byte   '7      ;EXIT
                .byte   10      ;влево
                .byte   32      ;поворот
                .byte   31      ;вправо
                .byte   33      ;вниз
                .byte   0
                .even

                .end

;FONT:  знакогенератор
;SPRITE:        начало массива спрайтов
;WINNME:        тут будет спрайт окошка ввода имени
;WINSL: тут будет спрайт окошка чтения/записи
;WINEX: тут будет спрайт окошка выхода
;PANEL: п/п вывода панели
