;целевой ассемблер: BK Turbo8 Cross Assembler

;Доработанный тест контроллеров АльтПро с ДОЗУ 64-512КБ. Версия 4.75F
;Изменения и нововведения в v4.1:
;* Тест памяти определяет только её количество, и корректность байтового доступа.
;* Тест режимов работает и на БК-0010(01), и на БК-0011М, вывод результатов теста режимов сделан более
;  человекопонятным.
;* Определяется тип контроллера по признаку в слове 0167776.
;Изменения и нововведения в v4.3:
;* Изменён тест определения количества памяти.
;* Добавлен тест проверки на битые ячейки памяти.
;Изменения и нововведения в v4.41:
;* Тест режимов перенесён вперёд, перед тестом памяти.
;* Добавлен свой знакогенератор, чтобы не зависеть от мониторов БК10 и БК11.
;* Добавлено определение версии прошивки 555РТ5.
;* v4.41 - попытка исправить ошибки скроллинга.
;Изменения и нововведения в v4.51:
;* Добавлен тест переключения страниц в проблемных режимах.
;* При заполнении экрана информацией выводится сообщение "нажмите любую клавишу" и программа
;  ожидает нажатия любой клавиши, кроме СТОП и управляющих естественно.
;* v4.51 - Иногда, в нештатных случаях могли возникнуть ситуации, когда регистр 177130 на БК-0010
;  накладывался на ПЗУ бейсика и это приводило к неправильной работе теста. Теперь это исправлено,
;  возникающее прерывание по вектору 4 при записи в 177130 теперь игнорируется.
;Изменения и нововведения в v4.72F:
;* Добавлены тесты конструктивных особенностей: доступ к регистрам HDD, тест буфера ОЗУ для HDD,
;  реакция на команду RESET, реакция на биты 2 (код 4) и 3 (код 10)
;* v4.71 - уточнение реакции на биты 2 и 3.
;* v4.72 - ещё одно уточнение реакции на биты 2 и 3.
;Изменения и нововведения в v4.73F:
;* Тест памяти на ошибки немного усложнён.
;Изменения и нововведения в v4.74F:
;* Тест памяти на ошибки изменён. Добавлено длинное тестирование случайными числами, 
;  с целью проверки стабильности, длительность длинного тестирования можно задать свою,
;  а так же совсем отменить. 
;Изменения и нововведения в v4.75F:
;* номера сегментов теперь 0..7, а не 10..17
;* сообщения об ошибках теста режима уточнены
;* тест блокировки битом 2 регистров 177130, 177132 усложнён
;* тест подключения ПЗУ бейсика на БК 10 битом 3 уточнён
;* тест теперь полностью самостоятелен. и не нуждается ни в какой ОС и никаком мониторе.
;  Версия v4.74F всё же требовала в начале монитор БК10.
;* исходник переписан под кросс ассемблер

SYNCW=55000     ;значение синхронизации. Контрольное слово, которое записывается в ячейку
                ;памяти, и ожидается, что при чтении будет именно оно.

OFSF8=400       ;смещение в шрифте
;системные ячейки знакогенератора
SCRCRD=160      ;Абсолютный адрес курсора в ОЗУ экрана
SCRY=156        ;Y координата, для рулонного сдвига
SCRFNT=166      ;адрес начала шрифта
SCRLNC=164      ;счётчик строк

StdMode=400     ;ячейка, где хранится код стандартного режима и признак БК10/11
RAMBGN=402      ;ячейка, где хранится адрес начала ОЗУ для БК10/11
SCR_INI=404
V4BUF=406       ;ячейка, где хранится оригинальное значение вектора 4
CurrentMode = 410
LNGTST=412      ;ячейка, где хранится длительность длинного тестирования
;-------переменные--
TZADDR=420      ;приходится вводить переменную, т.к. хитрый тест режимов проверяет 17 сегмент дважды
TZMODE=422
TRCODE=424
VALUE1=426      ;временная многофункциональная переменная
AltProDev=430   ;флаг детектирования контроллера альтпро 0 - норма, >0 - не обнаружен <0 - неверное ПЗУ
SMKHDD=431      ;флаг наличия регистров HDD
ERCOD=432
ERT31=434

DECBUF=600      ;буфер ввода десятичного числа

Begin:          mov     #100, @#177660      ;запрещаем прерывания от клавиатуры
                mtps    #340
                mov     #4, R4
                mov     (R4), @#V4BUF       ;сохраним текущий вектор 4, потом заменим его
                                            ;своими данными
                mov     #PZP1, (R4)+        ;тест 10/11
                mfps    (R4)
                mov     #177716, R5
                mov     #StdMode, R2
                mov     #60, (R2)           ;код раб.реж.10
                mov     #42400, @#177662    ;белая палитра, тут на 10-ке случается прер. по вектору 4
                mov     #100140, (R2)       ;признак и код раб.реж.11M
                mov     #16000, (R5)        ;страницы ANDOS
PZP1:           clr     R1
                mov     (PC), R0            ;почувствовать клавиатуру на 6 МГц: > 40000 SOB
                mov     #177130, R3
04$:            mov     R4, (R3)            ;R4 == строб 6
                movb    (PC), (R5)          ;звук (#200)
                mov     (R2), (R3)          ;стандартный режим
                mov     R1, (R3)            ;строб 0
                movb    (PC), (R5)          ;звук (#300)
                mov     #Begin, SP
                sob     R0, 04$

; инициализация
Tests:          mov     #DISTRP, @#34
                mfps    @#36
                trap    0                   ;инициализация экрана
                trap    40                  ;включение стандартного режима с учётом типа БК
                call    SetMemTestLen

                mov     #100, @#177660      ;запрещаем прерывания от клавиатуры
                mov     #StrTitle,R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                call    DETECT
                tstb    @#AltProDev
                beq     MemTest1            ;если после детекта найден контроллер альтпро
                bmi     MemTest1            ;если прошивка не правильная, тоже тесты проведём, но мы предупреждали.
                jmp     StopTests           ;иначе тестов памяти делать не будем.
;тесты памяти

;обработка halt для этапа MemTest1
TT4MemTest1:    bis     R3, PageErrors(R5)
;обработка halt для теста режимов
TT4All:         add     #4, (SP)
                rti

;этап1
;1. пробуем все 32 кода страниц независимо от кол-ва памяти, для каждой страницы заполняем массив PageErrors
MemTest1:       mov     #StrPrepare, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                clr     R5                  ;индекс в массиве PageErrors и RamCodTable
                mov     #TT4MemTest1, @#4
                mov     #123456, R4
                br      0TR3$

0TR2$:          tst     (R5)+
0TR3$:          clr     PageErrors(R5)
                mov     @#RAMBGN, R2
                mov     RamCodTable(R5), R1 ;берём очередной код
                beq     MemTest2            ;0 - конец.
                mov     #'.,R0
                trap    16                  ;вывод символа на экран. Вход: R0 - код символа
                mov     R1, R0              ;устанавливаем нужную страницу
                trap    2                   ;включение режима с учётом типа БК, вход: R0 - код режима
                mov     R0, R1              ;сохраним исправленный код с учётом типа БК
                ;проверим, а не подключали ли мы эту страницу ранее
                mov     #1, R3              ;это признак, когда случился halt, 1 - не было чтения
                mov     R2, R0
                ;проверим, а не подключали ли ранее
                cmp     (R0)+, R4           ;если нет чтения, тут будет halt ---+
                beq     1$                  ;                                   |
                nop                         ;                                   |
                inc     R3                  ;2 - не было записи <- сюда --------+
                mov     R4, (R2)+           ;если нет записи, тут будет halt ---+
                br      2$                  ;                                   |
                nop                         ;                                   |
                br      0TR2$               ;<- сюда ---------------------------+
                ;записать в первое слово смогли, теперь проверим остальные
2$:             mov     #17777, R0          ;всю страницу заполним кодом страницы
3$:             mov     R1, (R2)+           ;тут будет halt ----+
                sob     R0, 3$              ;                   |
                br      4$                  ;                   |
                br      0TR2$               ;<- сюда -----------+

4$:             ;сюда попадаем если не было halta ни при чтении, ни при записи во всей странице.
                ;проведём байт тест
                mov     R4, R2
                mov     R2, (R2)            ;допустим, произошёл halt --+
                nop                         ;                           |
                br      8$                  ;                           |
                br      9$                  ;< - сюда ------------------+

8$:             movb    R2, 1(R2)           ;допустим, произошёл halt --+
                nop                         ;                           |
                br      10$                 ;                           |
                br      9$                  ;< - сюда ------------------+

10$:            cmp     #27056, (R2)        ;а здесь halt перейдёт туда ------------+
                beq     0TR2$               ;байт тест удачно пройден               |
                nop                         ;байт тест провален                     |
9$:             bis     #10,PageErrors(R5)  ;признак ошибки байт теста < - сюда ----+
                br      0TR2$

1$:             bis     #100000, PageErrors(R5)  ;признак, что страницу уже подключали
                br      0TR2$

;обработка halt для этапа MemTest2
TT4MemTest2:    bit     (SP)+,(SP)+         ;корректируем стек
                clr     R1                  ;признак случившегося trap to 4
                br      1HLT$
;этап2
;2. подсчитываем доступное кол-во ОЗУ
;   для каждой модели имеется набор ожидаемых кодов страниц.
;   выводим на экран ошибки только из этого набора
MemTest2:       mov     #TT4MemTest2, @#4
                mov     #StrDOZU, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                clr     R5                  ;индекс в массиве PageErrors и RamCodTable
                clr     R1                  ;счётчик доп. ОЗУ
1NEXT$:         mov     RamCodTable(R5), R0 ;берём очередной код
                beq     0END$               ;если коды кончились - выход
                ;выведем кол-во озу
                trap    22                  ;вывод на экран десятичного числа с подавлением ведущих нулей. вход:  R1 - число
                mov     #40,R0
                trap    16                  ;вывод символа на экран. Вход: R0 - код символа
                mov     PageErrors(R5), R4  ;проблемы с этой страницей были?
                bpl     1$
                ;эту страницу уже подключали
                mov     R1, -(SP)
                mov     RamCodTable(R5), R0
                trap    2                   ;включение режима с учётом типа БК, вход: R0 - код режима
                mov     R0, R1
                mov     #StrPageAlrUse1, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                trap    24                  ;вывод восьмеричного 4-х значного числа из R1, без подавления ведущих нулей
                mov     #StrPageAlrUse2, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                mov     @#RAMBGN, R1
                mov     2(R1), R1           ;код страницы, с которой уже подключали.
                                            ;тут и только тут может случиться tpap to 4
                                            ;если он случался на прошлом этапе
1HLT$:          trap    24                  ;вывод восьмеричного 4-х значного числа из R1, без подавления ведущих нулей
                mov     (SP)+, R1
                br      0NEXT$

1$:             bit     #1, R4
                beq     2$
                ;не было чтения
                mov     #StrRead, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                mov     #StrHalt, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
2$:             bit     #2, R4
                beq     7$
                ;не было записи
                mov     #StrWrite, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                mov     #StrHalt, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
7$:             bit     #10, R4
                beq     0NEXT$
                ;не пройден байт-тест
                mov     #StrByteFail, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки

0NEXT$:         mov     #TZ2ERC, R3         ;заносим значение заранее, потому что там bmi сразу после tpap. так экономим слово
                tst     R4
                bne     5$                  ;какие-либо ошибки чтения-записи были?
                mov     #6, R2              ;нет - курсор просто влево.
                trap    14                  ;двигаем курсор на заданное количество раз влево, вход: R2 - количество раз
                br      6$

5$:             trap    20                  ;вывели ещё сообщение об ошибке, значит делаем перевод строки
                bmi     4$                  ;если уже подключали, то не считается
6$:             add     #16., R1            ;увеличим счётчик кб
4$:             tst     (R5)+               ;перемещаемся дальше по таблице
                cmp     R5, EndRamCod       ;для заданной модели контроллера таблица кончилась?
                blo     1NEXT$               ;если нет - продолжим
                ;выведем конечное кол-во ОЗУ
0END$:          trap    22                  ;вывод на экран десятичного числа с подавлением ведущих нулей. вход:  R1 - число

;промежуточные дополнительные тесты
                call    TestHDDRegs         ;тест доступности регистров HDD по чтению/записи
                call    TestHDDRAM          ;тест ОЗУ, выделенного под буфер HDD
                call    TestBit2            ;тест влияния бита 2
                call    TestBit3            ;тест влияния бита 3
                call    TestReset           ;тест влияния команды RESET

;Тут какой-то непонятный феномен. Если TestReset выполняется перед TestBit2, то
;на реальной БК и СМК перестаёт выдавать корректные результаты тест режимов.
;а в эмуляторе всё работает. В чём косяк, где ошибка в эмуляторе пока не выяснено.
;тест режимов
TREZ:           clr     @#VALUE1
                call    MEMTS4              ;заполняем память синхрокодом
                mov     #7, ZN
                trap    40                  ;включение стандартного режима с учётом типа БК
                mov     #TRZINF, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                clr     @#ERCOD
                cmpb    @#167777, #374
                blo     1$                  ;если А16, то не проверять HDD ОЗУ
                cmpb    @#167776, #300
                bhis    1$
                mov     #240, SMKCON        ;для контроллеров SMK там NOP
1$:             mov     #AltProModes, R5
                mov     TZCODS, R4
                mov     #SYNCW, R2
                mov     #TT4All, @#4
                mov     #277, -(SP)         ;8 реж. * 8 банков

Z1:             mov     @#StdMode, R0
                bpl     10$
                ;для БК11М, надо включать стандартный режим,
                trap    4                   ;включение режима без учёта типа БК, вход: R0 - код режима
                mov     #100000, R1         ;чтобы
                mov     #20000, R0          ;чистить верхнее ОЗУ, чтобы гарантированно отличить его от 
12$:            clr     (R1)+               ;ДОЗУ
                sob     R0, 12$             ;это нужно делать каждый раз при смене режима
10$:            movb    (R5), R1            ;выводим код режима.
                trap    24                  ;вывод восьмеричного 4-х значного числа из R1, без подавления ведущих нулей
                mov     #':, R0
                trap    16                  ;вывод символа на экран. Вход: R0 - код символа
                clr     @#VALUE1
                mov     #100172, R3         ;начальный адрес для проверки
Z2:             mov     R3, @#TZADDR
                mov     #1003, ZC           ;BNE 3$ = норм.!!!
                movb    (R5),R0             ;очередной режим
                bne     7$                  ;привязка к коду режима !!!
                tst     @#StdMode
                bmi     7$                  ;если БК11 - не надо никаких привязок
                cmp     R3, #120000
                bhis    7$                  ;ПЗУ мон.БК10 может не отключаться:
                mov     #240, ZC            ;ПЗУ есть = нет: != == halt
7$:             mov     R0, @#TZMODE        ;режим для вывода на экран
                trap    4                   ;включение режима без учёта типа БК, вход: R0 - код режима
                cmp     R3, #177172
                beq     2$
                incb    (SP)
                beq     ZE
2$:             clr     R0                  ;тут накапливается код результата теста
                cmp     R2, (R3)            ;тестируем, есть ли доступ по чтению
ZC:             bne     3$
                beq     4$
                cmp     (R0)+, (R0)+        ;<-halt сюда для cmp
4$:             cmp     (R0)+, (R0)+
                ;здесь R0 == 0, 4, 010 при !=, =, halt
3$:             mov     R3, (R3)            ;тестируем, есть ли доступ по записи
                cmp     R2, (R3)            ;тестируем, работает ли запись как надо
                beq     6$                  ;если запись прошла, но по чтению все равно изначальный вариант
                nop                         ;<-halt сюда для mov
                mov     R2, (R3)            ;<-halt сюда для cmp
                cmp     R2, (R3)
                br      5$
                br      1$                  ;<-halt сюда для mov
5$:             bne     6$                  ;<-halt сюда для cmp - !=
                inc     R0                  ;write
6$:             inc     R0                  ;nowr 
1$:             cmp     R0, #11             ;для HALT-ОЗУ: R0=11->10
                bne     7$                  ;-
                cmpb    (SP), #327          ;это у нас сегмент 177000 в режиме 120?
                bne     7$                  ;нет
                dec     R0                  ;да, для старой версии прошивки подменяем код с ОЗУзч на ПУСТО
7$:             cmpb    (SP), #366          ;а тут смотрим - это сегмент 160000 в режиме 100?
                bne     SMKCON              ;нет
                cmp     R0, #4              ;да, а схема старая?
                bne     SMKCON              ;нет, новая
                tst     (R0)+               ;для старой подменяем код ОЗУзз на ОЗУ
SMKCON:         br      0$
                cmp     R3, #170172
                bne     0$
                cmpb    (SP), #307          ;в режиме 160 в сегменте 170000 везде ПЗУ
                beq     0$                  ;так что нет нужды проверять его дважды.
                sub     #1000, R3           ;вот поэтому то у нас и проверяется 2 раза сегмент 17
                mov     #6, R1              ;в сегменте 170000 в диапазоне 170000-176777 - всегда ОЗУ
                br      3$                  ;должно быть

0$:             movb    (R4)+, R1
3$:             cmpb    R0, R1
                beq     2$
                movb    R0, @#TRCODE        ;то, что есть - в мл.байт
                movb    R1, @#TRCODE+1      ;то, что должно быть - в ст.байт
                call    TRERR
                inc     @#VALUE1
                inc     @#ERCOD
2$:             add     #10000, R3
                bmi     Z2
                inc     R5
                tst     @#VALUE1
                bne     8$
                mov     #TROK, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
8$:             trap    12                  ;перевод строки. выход: R0 - код 12
                dec     (PC)+
ZN:             .word   7                   ;всего 8 режимов
                bpl     Z1
ZE:             tst     @#ERCOD
                beq     11$
                mov     #ERINFO, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
11$:
;тест режимов 2
;проведём тесты переключения между режимами (20 и 100) и (20 и 0)
;по типу синхротеста.
TREZ2:          trap    40                  ;включение стандартного режима с учётом типа БК
                cmpb    @#167777, #374
                blo     MEMTS3              ;если А16, то пропустить тест
                mov     #TRSWPG, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                mov     #TRST31, @#4
                mov     #SWREZ, R4
0$:             mov     R4, -(SP)
                call    MEMTS4              ;заполняем синхротест
                mov     (SP)+, R4
                movb    (R4)+, R0           ;берём первый режим
                tstb    (R4)
                bmi     MEMTS3
                mov     R0, R1              ;включаем
                trap    4                   ;включение режима без учёта типа БК, вход: R0 - код режима
                trap    24                  ;вывод восьмеричного 4-х значного числа из R1, без подавления ведущих нулей
                mov     #"->, R0
                trap    16                  ;вывод символа на экран. Вход: R0 - код символа
                swab    R0
                trap    16                  ;вывод символа на экран. Вход: R0 - код символа
                movb    (R4), R0            ;берём режим, на который переключаемся
                mov     R0, @#TZMODE
                mov     R0, R1              ;включаем
                trap    4                   ;включение режима без учёта типа БК, вход: R0 - код режима
                trap    24                  ;вывод восьмеричного 4-х значного числа из R1, без подавления ведущих нулей
                trap    12                  ;перевод строки. выход: R0 - код 12
                tst     R1
                bne     1$
                mov     #TRSKIP, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                br      0$

1$:             mov     @#RAMBGN, R2
                mov     #20000, R5
                call    SYNCTS              ;синхротест
                trap    12                  ;перевод строки. выход: R0 - код 12
                br      0$
;этап 3
;3. тестируем на сбойность доступное кол-во ОЗУ
;с подробным выводом каждого сбоя в таком виде:
;код - маска адрес:сбойные биты
MEMTS3:         call    MEMTS4
                mov     #TZERRS, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                mov     #MEMTST, R4
                call    MEMSSS
                call    MEMTS4
                mov     #TZEST2, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                mov     #MEMTSU, R4
                call    MEMSSS
                sob     R3,.
                sob     R3,.
                sob     R3,.
                sob     R3,.
;проверка контрольной суммы.
CRCCHK:         trap    40                  ;включение стандартного режима с учётом типа БК
                mov     #4,R4
                mov     #StopTests, (R4)
                mov     #CRCINF, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                trap    6                   ;ввод кода с клавиатуры. выход: R0 - код
                trap    20                  ;вывод следующего asciz
                call    CRC                 ;считаем crc
                mov     R0, R5              ;и преобразуем его в hex-текст
2$:             mov     #4, R1
                clr     R2
1$:             rol     R0
                rol     R2
                sob     R1, 1$
                add     #'0, R2
                cmp     R2, #'0 + 10.
                blo     6$
                add     #'A - '0 - 10., R2
6$:             movb    R2, (R3)+
                sob     R4, 2$
                cmp     -(R3), -(R3)        ;и выведем его на экран
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
3$:             mov     #10., R4
4$:             call    CRC
                cmp     R5, R0
                bne     5$
                sob     R4, 4$
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                tst     -(R3)
                br      3$

5$:             clr     R0
                call    ERRR0
                sob     R0,.
                br      3$


;тест доступности регистров HDD
TestHDDRegs:    trap    40                  ;включение стандартного режима с учётом типа БК
                mov     #StrTHDInfo1, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                tstb    @#SMKHDD
                bne     0OK$
                mov     #StrTHDDError, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                return

0OK$:           mov     #TT4All, @#4
                mov     #HDDRegsTable, R5   ;таблица регистров HDD
                mov     #377, R4
04$:            mov     (R5)+, R1           ;берём регистр
                beq     0EX$                ;закончились - выход
                trap    10                  ;вывод восьмеричного числа из R1, с подавлением ведущих нулей
                mov     #": , R0
                trap    16                  ;вывод символа на экран. Вход: R0 - код символа
                swab    R0
                trap    16                  ;вывод символа на экран. Вход: R0 - код символа
                mov     #StrHDDRegNoWrt, R3
                mov     R4, (R1)            ;если нет записи, тут будет halt ---+
                br      00$                 ;запись есть                        |
                nop                         ;                                   |
                br      01$                 ;записи нет              <-- сюда --+

00$:            tst     (R3)+
01$:            trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                mov     #StrHDDRegNoRead, R3
                cmp     (R1), R4            ;если нет чтения, тут будет halt ---+
                br      02$                 ;чтение есть                        |
                nop                         ;                                   |
                br      03$                 ;чтения нет              <-- сюда --+

02$:            tst     (R3)+
03$:            trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                br      04$

0EX$:           return


;тест ОЗУ, выделенного под буфер HDD
TestHDDRAM:     trap    40                  ;включение стандартного режима с учётом типа БК
                mov     #StrTHDInfo2, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                tstb    @#SMKHDD
                bne     0OK$
                mov     #StrTHDDError, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                return
;подготовим контрольный массив
0OK$:           mov     #30000, R5          ;адрес начала массива
                mov     #3400, R4           ;размер массива в словах
                mov     R5, R1
                mov     R4, R2
                mov     #123456, R0
                mov     #65432, R3
2$:             mov     R0, (R1)+
                xor     R0, R3
                rol     R3
                ror     R0
                adc     R3
                bcc     1$
                swab    R0
1$:             rol     R3
                ror     R0
                adc     R3
                bcc     0$
                swab    R3
0$:             add     R3, R0
                sob     R2, 2$
;посчитаем его CRC
;и заодно скопируем в буфер ОЗУ HDD
                mov     #TT4TestHDDRAM, @#4
                mov     R5, R1
                mov     R4, R2
                mov     #170000,R3
                clr     R0
3$:             mov     (R1), (R3)+
                add     (R1)+, R0
                adc     R0
                sob     R2, 3$
                mov     R0, R5
                mov     #160, R0
                trap    4               ;включение режима без учёта типа БК, вход: R0 - код режима
                sob     R2,.            ;пауза
                trap    40              ;включение стандартного режима с учётом типа БК
                mov     #170000, R1
                mov     R4, R2
                clr     R0
4$:             add     (R1)+, R0
                adc     R0
                sob     R2,4$
                mov     #StrTHROK, R3
                cmp     R0, R5
                beq     5$
                mov     #StrTHRError, R3
                br      5$

TT4TestHDDRAM:  bit     (SP)+,(SP)+
                mov     #StrTHRAMNone,R3
5$:             trap    20  ;вывод строки символов. Вход: R3 - адрес строки
                return

;----------------------------------------------------------------------------
;тест влияния бита 2
;код 4 блокирует регистры по чтению.
TestBit2:       mov     #StrTstBit2Info, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                call    MEMFIL              ;заполним память синхрокодом.
                mov     #TT4TstBit2, @#4
                mov     #AltProModes+1, R5  ;таблица режимов контроллера
                                            ;режим 160 не будем проверять
4$:             movb    (R5)+, R1           ;проверим во всех режимах
                bmi     0$                  ;режимы кончились
                mov     #StrMode, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                trap    24                  ;вывод восьмеричного 4-х значного числа из R1, без подавления ведущих нулей
                mov     #':, R0
                trap    16
                trap    12
                mov     R1, R0
                clr     R4                  ;тут будет формироваться результат теста
                trap    4                   ;включение режима без учёта типа БК, вход: R0 - код режима
                mov     #2, R3
                mov     #177130,R1
                mov     #4,(R1)             ;блокируем регистры по чтению
1$:             mov     (R1)+, R2           ;читаем 177130, если не получится, halt ---+
                br      0next$              ;Что-то прочлось                           |
                br      0Ok$                ;                               <-- сюда --+

0next$:         cmp     R2, #SYNCW          ;если прочёлся синхрокод 
                beq     0Ok$                ;то тоже нормально
                incb    R4
0Ok$:           swab    R4
                sob     R3, 1$              ;дальше прочитаем 177132
                ;теперь в R4 в мл байте - результат чтения 177130, в старшем - 177132
                ;если 0 - то всё в порядке, если !0 - то не в порядке.
                mov     #2,R2
                mov     #177130, R1
3$:             mov     #StrRegister, R3
                trap    20
                trap    26
                mov     #StrBit2TstRes1,R3  ;это неудача
                tstb    R4
                bne     2$
                mov     #StrBit2TstRes2,R3  ;это удача
2$:             trap    20
                swab    R4
                add     #2, R1
                sob     R2, 3$
                br      4$
0$:             return

TT4TstBit2:     add     #2, (SP)
                rti
;В режимах 60, 120, 140, 40, 100, 0 - должен делаться trap to 4
; потому что там ничего нету, и если регистры заблокировать - читаться ничего не должно
;в режиме 20 - должен читаться синхрокод из 3го сегмента. т.к. он накладывается на регистры

;----------------------------------------------------------------------------
TT4TstBit3:     inc     @#VALUE1
                rti
;тест влияния бита 3
;код 10 подключает ПЗУ бейсика на БК10.
TestBit3:       mov     #StrTstBit3Info, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                tst     @#StdMode           ;это БК11
                bpl     0OK$                ;нет - делаем тест
                mov     #StrBit3TstNone, R3 ;да - тест не нужен
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                return

0OK$:           call    MEMFIL
                mov     #VALUE1,R3
                clr     (R3)
                mov     #TT4TstBit3, @#4
                mov     #SYNCW, R4
                mov     #120, R0
                trap    4                   ;включение режима без учёта типа БК, вход: R0 - код режима
                mov     #10, @#177130       ;подключаем бейсик, при этом ПЗУ накладывается на ОЗУ,
                                            ; и чтение-запись туда будет возможно, но читаться должно не то,
                                            ; что записывается
                mov     #120010, R5
                cmp     (R5), R4            ;читается что? синхрокод?
                beq     0$                  ;да, значит наложения нет
                inc     (R3)                ;нет - значит наложение есть
0$:             clr     (R5)                ;очищаем
                tst     (R5)                ;очистилось?
                beq     00$                 ;да - там чисто ОЗУ
                inc     (R3)                ;нет - значит наложение есть
00$:            add     #40000, R5          ;меняем адрес
                cmp     (R5), R4            ;читается что? синхрокод?
                beq     1$                  ;да, значит наложения нет
                inc     (R3)                ;нет - значит наложение есть
1$:             clr     (R5)
                tst     (R5)                ;очистилось?
                beq     10$                 ;да - там чисто ОЗУ
                inc     (R3)                ;нет - значит наложение есть
10$:            ;теперь второй вариант.
                ;в режиме 140 по адресам 120000-160000 ничего нет.
                ;и если бейсик подключается, там должно работать чтение
                mov     #TT4All, @#4
                mov     #140, R0
                trap    4                   ;включение режима без учёта типа БК, вход: R0 - код режима
                mov     #10, @#177130
                mov     #120020, R5
                tst     (R5)
                inc     (R3)                ;чтение произошло
                nop                         ;значит бейсик подключается
                add     #20000,R5           ;если чтения нет, halt сюда
                tst     (R5)
                inc     (R3)
                nop
                cmp     EndRamCod, #C128-RamCodTable
                blo     01$                 ;реакция в норме, должно накладываться
                ;не должно.
                tst     (R3)                ;наложение есть?
                beq     02$                 ;нету
                mov     #StrBitError,R3     ;хреново, наложение происходит, но не должно
                br      05$

02$:            mov     #StrBitOK,R3        ;отлично, нету и не должно быть.
                br      04$

01$:            tst     (R3)                ;наложение есть?
                beq     03$                 ;нету
                mov     #StrBitOK,R3        ;есть, так и скажем
05$:            trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                mov     #StrBit3TstRes1+3, R3   ;Ок. всё в норме.
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                return

03$:            mov     #StrBitError, R3    ;хреново, не работает бит 10
04$:            trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                mov     #StrBit3TstRes1, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                return


;тест влияния команды RESET
TestReset:      mov     #StrTstResetInfo, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
;1. Заполним каждую страницу своим уникальным кодом.
                call    MEMFIL              ;ну, почти всю страницу, одного слова в одном месте достаточно
;2. Включаем стандартный режим
                tst     @#StdMode
                bmi     011$
                mov     #120, R0
                trap    4                   ;включение режима без учёта типа БК, вход: R0 - код режима
                br      010$

011$:           mov     #140, R0
                trap    4                   ;включение режима без учёта типа БК, вход: R0 - код режима
                mov     #16000, @#177716
                mov     #100000, R1
                mov     #20000, R0
10$:            clr     (R1)+
                sob     R0, 10$
010$:
;3. Запоминаем, что было
                call    RDCRD
;4. Делаем ресет
                reset
;5. Смотрим, что стало
                call    RDRES
;Вывод результатов
                mov     #ADDRSS, R5
                mov     #DTAB, R4
                clr     @#VALUE1
12$:            mov     (R5)+, R1
                beq     11$
                mov     #StrAddress, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                trap    26                  ;вывод восьмеричного числа из R1, без подавления ведущих нулей
                cmp     DTAA-DTAB(R4), (R4)+
                bne     13$
                cmp     DTAA-DTAB(R4), (R4)+
                bne     14$
                mov     #TANRM, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                br      12$

14$:            mov     -2(R4), R1
                br      15$

13$:            mov     (R4), R1
15$:            mov     #TAERR, R3
                inc     @#VALUE1
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                trap    10                  ;вывод восьмеричного числа из R1, с подавлением ведущих нулей
                trap    12                  ;перевод строки. выход: R0 - код 12
                br      12$

11$:            mov     #TRRSOK, R3
                tst     @#VALUE1
                beq     16$
                mov     #TRRSER, R3
16$:            trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                mov     #TRRSTL, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                return

RDRES:          mov     #DTAA, R2
                br      0RD$

RDCRD:          mov     #DTAB, R2
0RD$:           mov     #ADDRSS, R1
1$:             mov     (R1)+, R0
                beq     0$
                mov     (R0)+, (R2)+
                mov     (R0)+, (R2)+
                br      1$
0$:             return

MEMFIL:         clr     R5
                mov     #SYNCW, R4
                mov     #TRST30, @#4        ;игнорируем все возможные trap to 4
11$:            mov     @#RAMBGN, R2
                mov     RamCodTable(R5), R0 ;берём очередной код
                beq     10$
                tst     PageErrors(R5)      ;если на странице были ошибки
                bne     12$                 ;то её пропустим
                trap    2                   ;включение режима с учётом типа БК, вход: R0 - код режима
                mov     #123456, (R2)+      ;признак, что страницу обработали
                mov     R0, (R2)+           ;код подключения страницы
                mov     #17776, R1          ;заполняем все 4 сегмента 
13$:            mov     R4, (R2)+           ;синхрокодом
                sob     R1, 13$
12$:            tst     (R5)+
                cmp     R5, EndRamCod
                blo     11$
10$:            return



;--подпрограммы----------------------------------------------------------------

MEMSSS:         mov     #TRST31, @#4
                clr     R1
32NEXT:         mov     RamCodTable(R1), R0 ;берём очередной код
                beq     31END               ;если коды кончились - выход
                tst     PageErrors(R1)      ;эту страницу уже подключали
                bmi     31NEXT              ;да - её не тестируем
                mov     @#RAMBGN, R2
                mov     #20000, R5
                trap    2                   ;включение режима с учётом типа БК, вход: R0 - код режима
                mov     R0, @#TZMODE        ;сохраняем режим, т.к. для вывода на экран нужно включать стандартный режим
4$:             call    IsKeyPress          ;если кнопка нажата, то может она ещё с прошлого раза нажата.
                beq     4$                  ;подождём, пока отпустят.
                call    SYNCTS              ;синхротест
                call    MEMTSS
31NEXT:         tst     (R1)+               ;перемещаемся дальше по таблице
                cmp     R1, EndRamCod       ;для заданной модели контроллера таблица кончилась?
                blo     32NEXT              ;если нет - продолжим
31END:          return

;синхротест
SYNCTS:         call    MTINF2
                mov     R1, -(SP)
                mov     R5, R1
                mov     R2, R3
                mov     #SYNCW, R0          ;синхрокод
                mov     R0, @#ERT31
2$:             call    IsKeyPress
                beq     0SKIP
                clr     @#VALUE1
                cmp     R0, (R3)
                beq     1$
                tst     @#VALUE1            ;если случился halt
                bne     1$                  ;то не надо, уже вывели сообщение об ошибке
                call    EROUT2              ;выведем сообщение, что ошибка синхротеста
1$:             inc     R3
                inc     R3
                sob     R1, 2$
0SKIP:          call    IsKeyPress          ;если кнопка нажата, то может она ещё с прошлого раза нажата.
                beq     0SKIP               ;подождём, пока отпустят.
                mov     (SP)+,R1
                return
        
;если случился halt при тестировании
TRST31:         call    EROUT1
TRST30:         rti                 ;продолжим тесты, как будто ничего не было

MEMTSS:         mov     #2, R3
                clr     R0
1$:             com     R0  ;-1
                call    (R4)
                com     R0  ;0
                call    (R4)
                sob     R3, 1$
                mov     #16., R3
                inc     R0  ;1
2$:             call    (R4)
                asl     R0
                sob     R3, 2$
                tst     (R3)+ ;2
3$:             clr     R0
                call    (R4)
                com     R0  ;-1
                call    (R4)
                sob     R3, 3$
                mov     #16., R3
                dec     R0  ;-2
4$:             call    (R4)
                sec
                rol     R0
                sob     R3, 4$
                tst     (R3)+ ;2, R0 = -1
5$:             call    (R4)
                com     R0
                call    (R4)
                com     R0
                sob     R3, 5$
                mov     #16., R3 ;R0 = -1
6$:             call    (R4)
                clc
                ror     R0
                sob     R3, 6$
                mov     #16., R3 ;R0 = 0
7$:             call    (R4)
                sec
                ror     R0
                sob     R3, 7$
                tst     (R3)+ ;2, R0 = -1
8$:             call    (R4)
                com     R0
                call    (R4)
                com     R0
                sob     R3, 8$
;добавляем длительное тестирование
                mov     @#LNGTST, R3
                beq     10$
9$:             mov     #-1, R0
                call    RANDOM
                call    (R4)
                sob     R3, 9$
10$:            return

MEMTST:         mov     R3, -(SP)
                mov     R4, -(SP)
                trap    32  ;вывод информации о текущем режиме тестирования
                mov     R5, R4
                mov     R2, R3
1$:             call    IsKeyPress
                beq     MSKIP
                clr     @#VALUE1
                clr     @#ERT31
                mov     R0, (R3)
                inc     @#ERT31
                cmp     R0, (R3)
                beq     0$
                ;случилась ошибка. надо вывести на экран
                tst     @#VALUE1
                bne     0$
                call    ERROUT
0$:             inc     R3
                inc     R3
                sob     R4, 1$
                br      0MOUT

MEMTSU:         mov     R3, -(SP)
                mov     R4, -(SP)
                trap    32  ;вывод информации о текущем режиме тестирования
                mov     R5, R4
                mov     R2, R3
                clr     @#ERT31
1$:             call    IsKeyPress
                beq     MSKIP
                mov     R0, (R3)
                inc     R3
                inc     R3
                sob     R4, 1$
                mov     R5, R4
                mov     R2, R3
                inc     @#ERT31
2$:             call    IsKeyPress
                beq     MSKIP
                clr     @#VALUE1
                cmp     R0, (R3)
                beq     0$
                ;случилась ошибка. надо вывести на экран
                tst     @#VALUE1
                bne     0$
                call    ERROUT
0$:             inc     R3
                inc     R3
                sob     R4, 2$
0MOUT:          mov     (SP)+, R4
                mov     (SP)+, R3
                return

MSKIP:          mov     (SP)+, R4
                mov     (SP)+, R3
                tst     (SP)+
                return

ERRR0:          mov     R3, -(SP)
                mov     R1, -(SP)
                mov     R0, -(SP)
                mov     #TERR, R3
                trap    20          ;вывод строки символов. Вход: R3 - адрес строки
                mov     SP, R3
                trap    20          ;вывод строки символов. Вход: R3 - адрес строки
                mov     (SP)+, R0
                mov     (SP)+, R1
                mov     (SP)+, R3
                return

;новый вид вывода сообщений об ошибках
;такого вида Segment-Code(Code) - в скобках то, что должно быть
TRERR:          ;портит R0,R1
                mov     @#TZADDR, R1    ;адрес, из которого получаем номер сегмента по 10000 байт
                swab    R1
                asr     R1
                asr     R1
                asr     R1
                asr     R1
                bic     #177770, R1     ;сегмент
                mov     #26440, R0
                trap    16              ;вывод символа на экран. Вход: R0 - код символа
                trap    10              ;вывод восьмеричного восьмеричного числа из R1, с подавлением ведущих нулей
                swab    R0
                trap    16              ;вывод символа на экран. Вход: R0 - код символа
                mov     @#TRCODE, R1    ;код, то что есть
                mov     R1, -(SP)
                clrb    (SP)            ;ст.байт - то, что должно быть
                bic     (SP), R1        ;мл байт - то, что есть
                trap    10              ;вывод восьмеричного восьмеричного числа из R1, с подавлением ведущих нулей
                mov     #"(), R0
                trap    16              ;вывод символа на экран. Вход: R0 - код символа
                mov     (SP)+, R1       ;код, то что должно быть
                swab    R1
                trap    10              ;вывод восьмеричного числа из R1, с подавлением ведущих нулей
                swab    R0
                trap    16              ;вывод символа на экран. Вход: R0 - код символа
                return

;подготовительный этап перед 3м этапом
;идея в том, чтобы заполнить все страницы памяти определенным кодом,
;чтобы отловить ошибку следующего вида: пишем в одну ячейку памяти,
;а меняются данные в какой-то другой ячейке в другой странице.
MEMTS4:         clr     R5
                mov     #SYNCW, R4
                mov     #TRST30, @#4
11$:            mov     @#RAMBGN, R2
                mov     RamCodTable(R5), R0 ;берём очередной код
                beq     10$
                tst     PageErrors(R5)      ;если на странице были ошибки
                bne     12$                 ;то её пропустим
                trap    2                   ;включение режима с учётом типа БК, вход: R0 - код режима
                mov     #20000, R1
13$:            mov     R4, (R2)+
                sob     R1, 13$
12$:            tst     (R5)+
                cmp     R5, EndRamCod
                blo     11$
10$:            return

;trap 34 - вывод кода текущего режима и текущей маски
MTMIN2:         trap    24      ;вывод восьмеричного 4-х значного числа из R1, без подавления ведущих нулей
                mov     #" -, R0
                trap    16      ;вывод символа на экран. Вход: R0 - код символа
                swab    R0
                trap    16      ;вывод символа на экран. Вход: R0 - код символа
                swab    R0
                trap    16      ;вывод символа на экран. Вход: R0 - код символа
                mov     R5, R1  ;выведем маску
                trap    30      ;вывод числа в бинарном виде, вход - R1 число
                return

;trap 36 - вывод кода текущего режима и слова "синхро"
MTMIN3:         trap    24      ;вывод восьмеричного 4-х значного числа из R1, без подавления ведущих нулей
                mov     #TZSYN1, R3
                trap    20      ;вывод строки символов. Вход: R3 - адрес строки
                return

;trap 32 - вывод инфы о текущем режиме тестирования
MTINFO:         jsr     R5, PUSHA
                mov     R0,R5
                mov     @#TZMODE, R1
                trap    34      ;вывод кода текущего режима и текущей маски
                br      3EROUE

;вывод инфы о синхропоследовательности
MTINF2:         jsr     R5, PUSHA
                mov     @#TZMODE,R1
                trap    36  ;вывод кода текущего режима и слова "синхро"
3EROUE:         mov     #15,R0
                trap    16  ;вывод символа на экран. Вход: R0 - код символа
                return

;вывод сообщения от ошибке синхропоследовательности
;на входе
;r3 - адрес, где случилась ошибка
EROUT2:         jsr     R5, PUSHA
                mov     @#TZMODE, R1
                mov     R3, -(SP)       ;адрес с ошибкой
                trap    36              ;вывод кода текущего режима и слова "синхро"
                mov     (SP), R1        ;выведем адрес, где случилась ошибка
                trap    26              ;вывод восьмеричного числа из R1, без подавления ведущих нулей
                mov     #':, R0
                trap    16              ;вывод символа на экран. Вход: R0 - код символа
                mov     @(SP)+, R1      ;выведем неправильное значение
                trap    26              ;вывод восьмеричного числа из R1, без подавления ведущих нулей
                mov     #TZSYNF, R3
                trap    20              ;вывод строки символов. Вход: R3 - адрес строки
                br      EROUEN
;на входе
;r0 - маска, с которой случилась ошибка
;r3 - адрес, где случилась ошибка
ERROUT:         jsr     R5, PUSHA
                mov     R0, R5          ;что должно быть
                mov     @#TZMODE, R1
                mov     (R3), -(SP)     ;что есть
                mov     R3, -(SP)       ;адрес с ошибкой
                trap    34              ;вывод кода текущего режима и текущей маски
                mov     #" :, R0        ;выведем ' '
                trap    16              ;вывод символа на экран. Вход: R0 - код символа
                mov     (SP)+, R1       ;выведем адрес, где случилась ошибка
                trap    26              ;вывод восьмеричного числа из R1, без подавления ведущих нулей
                swab    R0              ;выведем ':'
                trap    16              ;вывод символа на экран. Вход: R0 - код символа
                mov     (SP)+, R1       ;выведем то, что прочлось
                trap    30              ;вывод числа в бинарном виде, вход - R1 число
                br      EROUEN

;обработка ошибки по halt.
;r3 - адрес, где случилась ошибка
EROUT1:         inc     @#VALUE1        ;признак halt 
                jsr     R5, PUSHA
                mov     R0, R5          ;что должно быть
                mov     @#TZMODE, R1
2$:             mov     R3, -(SP)       ;адрес с ошибкой
                trap    34              ;вывод кода текущего режима и текущей маски
                mov     #" :, R0        ;выведем ' '
                trap    16              ;вывод символа на экран. Вход: R0 - код символа
                mov     (SP)+, R1       ;выведем адрес, где случилась ошибка
                trap    26              ;вывод восьмеричного числа из R1, без подавления ведущих нулей
                swab    R0              ;выведем ':'
                trap    16              ;вывод символа на экран. Вход: R0 - код символа
                mov     #StrWrite, R3
                tst     @#ERT31
                beq     0$
                mov     #StrRead, R3
0$:             trap    20              ;вывод строки символов. Вход: R3 - адрес строки
                mov     #StrHalt, R3
                trap    20              ;вывод строки символов. Вход: R3 - адрес строки
EROUEN:         trap    12              ;перевод строки. выход: R0 - код 12
EROUE2:         return


CRC:            mov     #160000,R1
                mov     #4000,R2
                clr     R0
0$:             add     (R1)+,R0
                adc     R0
                sob     R2,0$
                return

;выход из теста CRC по кнопке стоп
StopTests:      mov     @#V4BUF, @#4
                mov     #Begin, SP
                trap    40                  ;включение стандартного режима с учётом типа БК
                mov     #StrEndTest, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                ;ждём нажатия клавиши
                trap    6                   ;ввод кода с клавиатуры. выход: R0 - код
                halt                        ;выходим

;БК11М - выход в клавиатурный монитор
ZAGR:           call    @#150170
                emt     0
                emt     1
                halt

;rnd генератор.
;вход: R0 - макс.значение
;выход: R0 - результат
RANDOM:         mov     R1,-(SP)
                mov     R2,-(SP)
                call    FRN
                mov     R0,R1
                clr     R2
                mov     RAN,R0
                sec
3A:             bic     R2,R0
                ror     R2
                cmp     R0,R1
                bhi     3A
                mov     (SP)+,R2
                mov     (SP)+,R1
                return
FRN:            swab    (PC)+
RAN:            .word   0
                incb    RAN
                rolb    RAN+1
MM:             add     #0,RAN
                add     #3337,MM+2
                return

;вызов так: jsr R5,pusha, сохраняем все регистры
;но в R5 нельзя передать параметр, чтобы было можно, есть более сложный метод
PUSHA:          mov     R4, -(SP)
                mov     R3, -(SP)
                mov     R2, -(SP)
                mov     R1, -(SP)
                mov     R0, -(SP)
                ;mov    R5, -(SP)           ;это - чтобы и в R5 можно было
                ;mov    14(SP), R5          ;передавать параметры
                ;call   @(SP)+
                call    (R5)
                mov     (SP)+, R0
                mov     (SP)+, R1
                mov     (SP)+, R2
                mov     (SP)+, R3
                mov     (SP)+, R4
                mov     (SP)+, R5
                return

;------------------------------------------------------------------------------
;диспетчер трап
;сохранение регистров на совести подпрограмм
DISTRP:         mov     (SP), -(SP)         ;адрес возврата из трап
                sub     #2, (SP)            ;получим адрес команды трап
                mov     @(SP)+, -(SP)       ;достанем саму команду
                bic     #177401, (SP)       ;номера трапов только чётные, так мы экономим 1 слово
                add     #TRPTBL, (SP)       ;адрес адреса п/п
                mov     @(SP)+, -(SP)       ;получим адрес п/п
                call    @(SP)+              ;выполняем 
                rti
TRPTBL:         .word   Init                ;0
                .word   SetPage             ;2
                .word   VKL                 ;4
                .word   EMT6                ;6
                .word   OctNumOut           ;10
                .word   OutCR               ;12
                .word   CursorToLeft        ;14
                .word   PutChar             ;16
                .word   JIRN                ;20
                .word   DecNumOut           ;22
                .word   OctNumOut$4         ;24
                .word   OctNumOut$6         ;26
                .word   BinNumOut           ;30
                .word   MTINFO              ;32
                .word   MTMIN2              ;34
                .word   MTMIN3              ;36
                .word   VKLSTD              ;40

;trap 0
Init:           mov     #StdMode, R1
                mov     (R1)+, R0           ;параметр для trap 4
                bpl     2$
                mov     #100000, (R1)+      ;адрес начала ОЗУ - 11M
                tst     (R1)+               ;SCR.Init
                mov     #ZAGR, (R1)         ;для выхода в MON 11
                mov     #16000, @#114       ;как в ANDOS
                br      1$

2$:             mov     #120000, (R1)+      ;адрес начала ОЗУ - 10
                tst     (R1)+               ;SCR.Init
                mov     #100274, (R1)       ;для выхода в MON 10
1$:             trap    4                   ;включение режима без учёта типа БК, вход: R0 - код режима
                ;инициализация экрана
ScreenInit:     mov     #40000, R1
                mov     R1, R0
                mov     R1, @#SCRCRD
                clr     @#SCRY              ;Y координата, для рулонного сдвига
                clr     @#SCRLNC            ;счётчик строк
                mov     #1330, @#177664
3$:             clrb    (R1)+
                sob     R0, 3$
                mov     #FONT8, R0          ;собственный знакогенератор
                sub     #OFSF8, R0
                mov     R0, @#SCRFNT
                return


;trap 2 - подключение страниц и включение режима с учётом типа БК
;вход: R0 - код режима
SetPage:        tst     @#StdMode           ;БК11?
                bpl     VKL                 ;нет
                bic     #40, R0             ;да
;trap 4 - включение режима без учёта типа БК
;вход: R0 - код режима
VKL:            mov     R0, @#CurrentMode
VKL0:           mov     @#4, VV4BUF
                mov     #TRST30, @#4        ;прер по вектору 4 просто будем игнорировать.
                mov     R0, @#177716
                mov     #6, @#177130
                mov     R0, @#177130
                mov     #0, @#177130
                clr     @#177716
                mov     VV4BUF, @#4
                return
VV4BUF:         .word   0   ;буфер сохранения вектора 4

;trap 6 - ввод скан кода клавиши с клавиатуры
;выход: R0 - скан код
EMT6:           call    IsKeyPress          ;клавиша нажата?
                bne     EMT6                ;нет, ждём нажатия
1$:             call    IsKeyPress          ;клавиша нажата?
                beq     1$                  ;да, ждём пока отпустят
                movb    @#177662, R0        ;код нажатой клавиши
                return

IsKeyPress:     bit     #100, @#177716
                return

;trap 10 - вывод восьмеричного числа с подавлением ведущих нулей
;вход: R1 - число
OctNumOut:      jsr     R5, PUSHA
                mov     #6, R4              ;максимальное кол-во цифр в числе
                clr     R5                  ;счётчик цифр
0$:             mov     R1, R0
                bic     #177770, R0         ;получим очередную цифру
                add     #'0, R0
                mov     R0, -(SP)           ;в стек её
                inc     R5
                ror     R1                  ;пододвинем следующую, ADD бит С обнуляет, так что можно
                asr     R1
                asr     R1                  ;цифры остались?
                beq     1$                  ;кончились - выход, если число отрицательное, то мы отработает все 6 цифр.
                sob     R4, 0$
1$:             mov     (SP)+, R0
                trap    16                  ;вывод символа на экран. Вход: R0 - код символа
                sob     R5, 1$
                return

;trap 26 - вывод восьмеричного числа, без подавления ведущих нулей
;вход: R1 - число
OctNumOut$6:    jsr     R5,PUSHA
                mov     #6, R4              ;максимальное кол-во цифр в числе
                br      0DGO$
;trap 24 - вывод восьмеричного 4-х значного числа, без подавления ведущих нулей
;вход: R1 - число
OctNumOut$4:    jsr     R5,PUSHA
                mov     #4, R4              ;максимальное кол-во цифр в числе
0DGO$:          mov     R4,R5               ;счётчик цифр
0$:             mov     R1,R0
                bic     #177770,R0          ;получим очередную цифру
                add     #'0,R0
                mov     R0,-(SP)            ;в стек её
                ror     R1                  ;пододвинем следующую, ADD бит С обнуляет, так что можно
                asr     R1
                asr     R1                  ;цифры остались?
                sob     R4,0$
1$:             mov     (SP)+,R0
                trap    16                  ;вывод символа на экран. Вход: R0 - код символа
                sob     R5,1$
                return

;trap 14 - двигаем курсор на заданное количество раз влево,
;R2 - количество раз
CursorToLeft:   mov     #10, R0
7$:             trap    16                  ;вывод символа на экран. Вход: R0 - код символа
                sob     R2, 7$
                return

;trap 12 - перевод строки, портит R0
OutCR:          mov     #12, R0
;trap 16 - вывод символа на экран
;вход: R0 - код символа
PutChar:        jsr     R5, PUSHA
                call    VKLSTP              ;включаем стандартный режим без сохранения его в переменной "текущий режим"
                bic     #177400, R0         ;чистим старший байт
                bitb    #140, R0            ;символ?
                bne     01$                 ;да, переходим
                ;обрабатываем спецсимволы
                mov     @#SCRCRD, R3        ;координаты экрана
                cmp     #15, R0             ;LF?
                bne     23$                 ;нет
                bic     #77, R3             ;возвращаем курсор в начало строки
                br      31$                 ;проверка на сдвиг экрана

23$:            cmp     #12, R0             ;CR?
                bne     21$                 ;нет
                bic     #77, R3             ;возвращаем курсор в начало строки
                br      22$

21$:            cmp     #10, R0             ;курсор влево?
                bne     06$                 ;нет
                bit     #77, R3             ;мы где?
                beq     20$                 ;в начале строки, некуда влево уже
                dec     @#SCRCRD            ;где-то в строке, двигаемся влево.
                br      20$                 ;и выходим

06$:            cmp     #30 ,R0             ;забой
                bne     20$                 ;нет - остальные игнорируем
                bit     #77, R3             ;мы где?
                beq     20$                 ;в начале строки, некуда уже двигаться
                dec     @#SCRCRD            ;где-то в строке, двигаемся влево.
                mov     #10, R2             ;очищаем поле под курсором
                mov     @#SCRCRD, R1
07$:            clrb    (R1)
                add     #100, R1
                bpl     08$
                sub     #40000, R1
08$:            sob     R2, 07$
                br      20$                 ;и выходим

01$:            tstb    R0                  ;что за символ?
                bpl     02$                 ;латинский
                sub     #40, R0             ;русский - корректируем
02$:            asl     R0                  ;умножаем на 8
                ;mov    R0, R2
                asl     R0
                asl     R0
                ;add    R2, R0
                add     @#SCRFNT, R0        ;получаем адрес в шрифте
                mov     #10, R2             ;выводим
                mov     @#SCRCRD, R1
                mov     R1, R3              ;будущий адрес курсора
03$:            movb    (R0)+, (R1)
                add     #100, R1
                bpl     04$
                sub     #40000, R1
04$:            sob     R2, 03$
                ;двигаем адрес вывода
                mov     R3, R1
                mov     #177700, R0
                bic     R0, R1
                com     R0
                cmp     R1, R0              ;дошли до конца строки?
                bhis    10$                 ;да, надо делать перевод строки
                inc     @#SCRCRD            ;нет, просто на следующую позицию вправо
                br      20$

10$:            bic     R0, R3
22$:            inc     @#SCRLNC            ;увеличим счётчик строк
                add     #1000, R3           ;переходим на новую строку (высота символов 8 точек)
                bpl     11$                 ;за экран не вылезли?
                sub     #40000, R3          ;вылезли - корректируем. это новая координата
11$:            mov     R3, R2              ;если делать рулонный сдвиг, то прежде надо будет очистить от старого текста
                cmp     @#SCRY, #37         ;Если мы в самом низу
                bhis    13$                 ;то увеличивать координату больше не надо
                inc     @#SCRY              ;иначе увеличим
                br      31$                 ;проверка на сдвиг экрана

13$:            ;делаем рулонный сдвиг
                mov     @#177664, R0        ;берём значение рулонного регистра
                bic     #177400, R0         ;очищаем старший байт
                mov     #10, R1             ;высота символов 8 точек
15$:            mov     #32., R4            ;в строке 32 слова
14$:            clr     (R2)+
                sob     R4,14$
                tst     R2                  ;за пределы экрана не вылезли?
                bpl     16$                 ;нет
                sub     #40000, R2          ;да, корректируем
16$:            incb    R0                  ;увеличиваем значение рулонного сдвига
                bis     #1000, R0           ;режим полного экрана
                mov     R0, @#177664        ;заносим значение в регистр.
                ;incb @#177664 не работает как надо, потому что обращение к этому регистру
                ;только словное. байтовое не работает.
                ;а inc @#177664 рано или поздно начинает влиять на бит режима РП
                sob     R1, 15$

31$:            mov     R3, @#SCRCRD        ;сохраняем координаты курсора
                cmp     @#SCRLNC, #37       ;экран заполнился строками?
                blt     20$                 ;нет ещё, всё нормально
                mov     #-1, @#SCRLNC       ;да - инициализируем счётчик
                mov     #StrPressAnyKey, R3         ;
                call    JIRN                ;выведем сообщение, "нажмите любую клавишу"
                call    EMT6                ;подождём нажатия клавиши
                call    OutCR               ;перевод строки
20$:
;возвращаем режим, который был подключён до вывода символа
RETVKL:         mov     R0, -(SP)
                mov     @#CurrentMode, R0
                br      00VKL
;включаем стандартный режим без сохранения его в переменной "текущий режим"
VKLSTP:         mov     R0, -(SP)
                mov     @#StdMode, R0
00VKL:          call    VKL0
                mov     (SP)+, R0
                return

;trap 20 - вывод строки символов.
;вход: R3 - адрес строки
JIRN:           mov     R2, -(SP)
                mov     R5, -(SP)
3$:             movb    (R3)+, R0           ;Портит R0
                beq     1$                  ;0 - конец строки
                cmpb    R0, #220            ;200-220 - повтор 1-20, 100 раз
                bgt     4$                  ;если 1..177 или 221..377 переход
                blt     6$                  ;если 200..217 переход
                movb    #277, R0            ;полная строка !!!
6$:             movb    R0, R2              ;счётчик символов
                ;вариант с рекурсией тут мы можем повторять повторения
;                clr     -(SP)
;                movb    (R3)+, (SP)        ;код символа, который будем повторять
;                mov     R3, R5             ;адрес в строке запомним
;5$:             mov     SP, R3             ;строка из одного кода
;                call    JIRN               ;выведем
;                decb    R2                 ;столько раз, сколько надо
;                bmi     5$
;                mov     R5, R3             ;восстановим адрес в строке
;                tst     (SP)+
;                br      3$
                ;вариант без рекурсии
                movb    (R3)+, R0           ;символ, который надо повторять
5$:             call    PutChar
                decb    R2                  ;столько раз, сколько надо
                bmi     5$
                br      3$

4$:             call    PutChar
                br      3$

1$:             mov     (SP)+,R5
                mov     (SP)+,R2
                return

;trap 22 - вывод десятичного числа с подавлением ведущих нулей
;вход:  R1 - число
DecNumOut:      jsr     R5,PUSHA
                clr     R5
                mov     #CONST,R2
6$:             clr     R0
                mov     (R2)+,R4
                beq     2$
1$:             sub     R4,R1
                bcs     0$
                inc     R0
                br      1$

0$:             add     R4,R1
                bis     R0,R5
                bne     4$
                cmp     #1,R4
                beq     4$
                mov     #-20,R0             ;вместо ведущих нулей будем рисовать пробелы.
4$:             add     #'0,R0
                trap    16                  ;вывод символа на экран. Вход: R0 - код символа
                br      6$

2$:             return


;trap 30 - вывод числа в бинарном виде
;вход - R1 число
BinNumOut:         jsr     R5,PUSHA
                mov     #16.,R2
0$:             mov     #30,R0
                asl     R1
                rol     R0
                trap    16                  ;вывод символа на экран. Вход: R0 - код символа
                sob     R2,0$
                return

;trap 40 - включение стандартного режима с учётом типа БК
VKLSTD:         mov     R0, -(SP)
                mov     @#StdMode, R0
                trap    4                   ;включение режима без учёта типа БК, вход: R0 - код режима
                mov     (SP)+, R0
                return


;-------константы--------------------------
ADDRSS:         .word   100000,120000,140000,160000,0
HDDRegsTable:   .word   177740,177742,177744,177746,177750,177752,177754,177756,177741,177743,0
CONST:          .word   10000.,1000.,100.,10.,1,0

TZCODS:         .word   CODS11 ;адрес таблицы кодов ошибок теста режимов
;коды ошибок теста режимов для SMK. по 8 байт на режим
CODS:           .byte   00,00,06,06,06,06,00,00 ;160
                .byte   00,00,06,06,06,06,00,10 ;60
                .byte   06,06,06,06,06,06,06,10 ;120
                .byte   06,06,06,06,06,06,06,04 ;20
                .byte   00,00,10,10,10,10,00,10 ;140
                .byte   00,00,10,10,06,06,06,10 ;40
                .byte   04,06,06,06,06,06,06,11 ;100
                .byte   10,10,10,10,06,06,06,11 ;0

CODS11:         .byte   10,10,06,06,06,06,00,00 ;160
                .byte   10,10,06,06,06,06,00,10 ;60
                .byte   06,06,06,06,06,06,06,10 ;120
                .byte   06,06,06,06,06,06,06,04 ;20
                .byte   02,02,02,02,00,00,00,10 ;140
                .byte   02,02,02,02,06,06,06,10 ;40
                .byte   05,06,06,06,06,06,06,11 ;100
                .byte   02,02,02,02,06,06,06,11 ;0
;для А16
CODA:           .byte   00,00,06,06,06,06,00,00 ;160
                .byte   00,00,06,06,06,06,00,10 ;60
                .byte   06,06,06,06,10,10,00,10 ;120
                .byte   04,06,10,10,10,10,10,10 ;20
                .byte   00,00,10,10,10,10,00,10 ;140
                .byte   00,00,10,10,06,06,06,10 ;40
                .byte   04,06,06,06,10,10,00,10 ;100
                .byte   10,10,10,10,06,06,06,11 ;0

CODA11:         .byte   10,10,06,06,01,01,00,00 ;160
                .byte   10,10,06,06,06,06,00,10 ;60
                .byte   06,06,06,06,00,00,00,10 ;120
                .byte   04,06,10,10,10,10,10,10 ;20
                .byte   02,02,02,02,00,00,00,10 ;140
                .byte   02,02,02,02,06,06,06,10 ;40
                .byte   05,06,06,06,00,00,00,10 ;100
                .byte   02,02,02,02,06,06,06,11 ;0

;таблица режимов контроллера
AltProModes:    .byte   160,60,120,20,140,40,100,0,377

SWREZ:          .byte   120,20,120,100,20,100,0,20,0,377
                .even
;адрес конца таблицы кодов для подключения страниц памяти
EndRamCod:      .word   C512-RamCodTable
;коды для подключения страниц памяти
RamCodTable:    .word   160   ;0     (код 0)
C016:           .word   60
C032:           .word   2160  ;+32Кб (код 2000)
                .word   2060
C064:           .word   164   ;+64Кб (код 4)
                .word   64
                .word   2164  ;+96Кб (код 2004)(64+32)
                .word   2064
C128:           .word   170   ;+128Кб (код 10)
                .word   70
                .word   2170  ;+160Кб (код 2010)(128+32)
                .word   2070
                .word   174   ;+192Кб (код 14)(128+64)
                .word   74
                .word   2174  ;+224Кб (код 2014)(128+64+32)
                .word   2074
; это для 512Кб (вторая половина)
C256:           .word   161   ;+256Кб (код 1)
                .word   61
                .word   2161  ;+288Кб (код 2001)(256+32)
                .word   2061
                .word   165   ;+320Кб (код 5)(256+64)
                .word   65
                .word   2165  ;+352Кб (код 2005)(256+64+32)
                .word   2065
                .word   171   ;+384Кб (код 11)(256+128)
                .word   71
                .word   2171  ;+416Кб (код 2011)(256+128+32)
                .word   2071
                .word   175   ;+448Кб (код 15)(256+128+64)
                .word   75
                .word   2175  ;+480Кб (код 2015)(256+128+64+32)
                .word   2075
C512:           .word   0
;таблица адресов конца таблицы кодов для подключения страниц памяти
TZCTB:          .word   C016-RamCodTable
                .word   C016-RamCodTable
                .word   C016-RamCodTable
                .word   C016-RamCodTable
                .word   C064-RamCodTable
                .word   C128-RamCodTable
                .word   C256-RamCodTable
                .word   C512-RamCodTable
                .word   C064-RamCodTable
                .word   C128-RamCodTable
                .word   C256-RamCodTable
                .word   C512-RamCodTable
;таблица имён контроллеров
NameTable:      .word   NameA16
                .word   NameA16H
                .word   NameA16M
                .word   NameAUNK
                .word   NameA64M
                .word   NameA128M
                .word   NameA256M
                .word   NameA512M
                .word   NameS64
                .word   NameS128
                .word   NameS256
                .word   NameS512

;имена контроллеров
NameA16:        .asciz  "A16"
NameA16H:       .asciz  "A16HDD"
NameA16M:       .asciz  "A16M"
NameAUNK:       .asciz  "Несуществующий"
NameA64M:       .asciz  "A64M"
NameA128M:      .asciz  "A128M"
NameA256M:      .asciz  "A256M"
NameA512M:      .asciz  "A512M"
NameS64:        .asciz  "SMK64"
NameS128:       .asciz  "SMK128"
NameS256:       .asciz  "SMK256"
NameS512:       .asciz  "SMK512"

StrNoAltPro:    .asciz  "Не обнаружен контроллер АльтПро"<12>
StrFound:       .asciz  "Обнаружен контроллер "
StrVersion:     .asciz  " версия прошивки: "
StrVersionRT:   .asciz  "Версия прошивки 555РТ5: "
RTOK:           .asciz  "новая"<12>
RTBAD:          .ascii  "старая, не рекомендуется к использованию"<12>
                .ascii  "из-за неправильных режимов работы, тест будет показывать ошибки"<12>
                .asciz  "синхронизации на БК11М"<12>
RTERR:          .asciz  "повреждена."<12>

StrTitle:       .ascii  <220>/"/
                .ascii  <210>/ Тест контроллера "АльтПро" с ДОЗУ 64-512 Кб/<12>
                .ascii  <220>/"/
                .asciz  <211>" (c) АльтПро 1997, gid 2012-2019, v4.75F"<12>

StrPrepare:     .asciz  "Подготовка"
TERR:           .asciz  <7><7>" Error "
StrDOZU:        .asciz  <12>"ДОЗУ, Кбайт:"
TZ2ERC:         .asciz  <12><213>" "
TZERRS:         .ascii  <12>"Тест памяти на ошибки..."
TZEST1:         .asciz  <12>"Этап 1"<12>
TZEST2:         .asciz  <12>"Этап 2"<12>
StrWrite:       .asciz  "write-"
StrRead:        .asciz  "read-"
StrHalt:        .asciz  "halt "
StrByteFail:    .asciz  "byte-test fail"
StrPageAlrUse1: .asciz  "стр. с кодом "
StrPageAlrUse2: .asciz  " уже подключали с "
TZSYN1:         .asciz  " - синхро           "
TZSYNF:         .asciz  ":ошибка"
TRZINF:         .asciz  <12>"Тест режимов..."<12>
TRSWPG:         .asciz  <12>"Тест переключения страниц..."<12>
TROK:           .asciz  " OK"
TRSKIP:         .asciz  "пропуск."<12>
ERINFO:         .ascii  "Код ошибки: Сегмент-Код(Код). Сегмент -"<12>
                .ascii  "сегмент памяти по 10000 байтов, Код - код ошибки, в скобках"<12>
                .ascii  "ожидаемый код. Расшифровка кодов:"<12>
                .ascii  "6-ОЗУ, 4-ОЗУзз, 0-ПЗУ, 10-пусто, остальные коды:"<12>
                .asciz  "11-ОЗУзч, 5-ОЗУзз на ОЗУ, 1-ОЗУ на ПЗУ, 2-чужое ОЗУ"<12>

CRCINF:         .ascii  <12><202>"* Для запуска непрерывного теста контрольной суммы ПЗУ"<12>
                .ascii  <203>" нажмите любую клавишу. Правильное значение уточните"<12>
                .asciz  <203>" по документации. Прервать тест - СТОП."<12>

                .asciz   <12>"   Код К.С.= "
                .asciz  "1234 "
                .asciz  "."

StrTHDInfo1:    .asciz  <12>"Тест доступности регистров HDD..."<12>
StrTHDInfo2:    .asciz  <12>"Тест буфера ОЗУ HDD..."<12>
StrTHROK:       .asciz  "ОЗУ в норме."<12>
StrTHRError:    .asciz  "Внимание! ОЗУ повредилось!"<12>
StrTHRAMNone:   .asciz  "Внимание! ОЗУ недоступно!"<12>
StrTHDDError:   .asciz  "Это не СМК, пропускаем тест."<12>
StrHDDRegNoWrt: .asciz  "недоступен по записи, "
StrHDDRegNoRead:.asciz  "недоступен по чтению"<12>
StrTstBit2Info: .asciz  <12>"Тест влияния бита 2..."<12>
StrMode:        .asciz  "Режим "
StrRegister:    .asciz  "Регистр "
StrBit2TstRes1: .asciz  " - не блокируется!"<12>
StrBit2TstRes2: .asciz  " - блокируется."<12>



StrBitError:    .asciz  "ОШИБКА! "
StrBitOK:       .asciz  "Норма. "
StrTstBit3Info: .asciz  <12>"Тест влияния бита 3..."<12>
StrBit3TstRes1: .asciz  "не подключается ПЗУ Бейсика."<12>
StrBit3TstNone: .asciz  "На БК11(М) бит 3 влияния не имеет."<12>
StrTstResetInfo:.asciz  <12>"Тест влияния RESET..."<12>
StrAddress:     .asciz  "Адрес: "
TANRM:          .asciz  " - без изменений"<12>
TAERR:          .asciz  " - "
TRRSOK:         .asciz  "Норма. RESET не"
TRRSER:         .asciz  "ОШИБКА. RESET"
TRRSTL:         .asciz  " влияет на режимы."<12>

StrEndTest:     .asciz  <12><202>"* Тестирование окончено !"
StrPressAnyKey: .asciz  <216>" *** Нажмите любую клавишу. ***"
                .even


;тут будут храниться флаги ошибок для каждой страницы
;возможные результаты:
;   0 - всё отлично
;иначе маски:
;   1 - нет записи (halt)
;   2 - нет чтения (halt)
;   10 - провал байт-теста
;   100000 - страницу уже подключали
PageErrors:     .blkw   40

DTAB:           .blkw   10
DTAA:           .blkw   10

;------------------------------------------------------------------------------
; часть кода, нужная только один раз при инициализации

DETECT:         tst     @#StdMode           ;чтобы тест нельзя было запустить
                bpl     20$                 ;повторно
                mov     #140000, R0         ;сделаем переход на 
                br      21$                 ;выход в монитор

20$:            mov     #100000, R0         ;потому что, тест режимов самомодифицирующийся,
21$:            mov     #137, @#Begin       ;и после его прохода код не восстанавливается в
                mov     R0, @#Begin+2       ;исходное состояние

                ;определяем тип контроллера и кол-во памяти по значению в 167776
                clrb    @#AltProDev         ;флаг детектирования контроллера
                clrb    @#SMKHDD            ;флаг наличия регистров HDD
                mov     @#167776, R5        ;в мл. байте версия прошивки
                mov     R5, R4
                clrb    R4                  ;очищаем младший байт
                bic     R4, R5              ;очищаем старший байт
                swab    R4                  ;в мл байте код количества памяти
                cmp     R4,#370             ;это вообще альтпро?
                bhis    1$                  ;да
0$:             mov     #StrNoAltPro, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                incb    @#AltProDev         ;отметим, что контроллер не найден
                return

1$:             bic     #177770, R4         ;определим тип контроллера
                ;коды в ячейке 167777, определяющие тип контроллера
                ;R4=0 : 370 - A16
                ;R4=1 : 371 - A16+контроллера винта с дозу 4кб
                ;R4=2 : 372 - A16M
                ;R4=3 : 373 - не исп-ся
                ;R4=4 : 374 - SMK64 или A64M
                ;R4=5 : 375 - SMK128 или A128M
                ;R4=6 : 376 - SMK256 или A256M
                ;R4=7 : 377 - SMK512 или A512M
                mov     #4, R3
                cmp     R4, R3              ;для а16 нечего делать
                blo     3$                  ;а если smk или a64m, надо определить, что это
                cmpb    R5, #300            ;это A64-A512?
                bhis    3$                  ;да
                comb    @#SMKHDD            ;нет - отметим, что есть регистры HDD
                add     R3, R4              ;и это СМК
3$:             asl     R4                  ;*2
                mov     #StrFound, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                mov     TZCTB(R4), EndRamCod ;зададим адрес конца таблицы кодов для подключения страниц памяти
                mov     NameTable(R4), R3   ;выведем имя контроллера
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                mov     #StrVersion,R3      ;выведем версию, в нечеловекообразном виде
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                mov     R5, R1
                trap    10                  ;вывод восьмеричного числа из R1, с подавлением ведущих нулей
                trap    12                  ;перевод строки. выход: R0 - код 12
                ;вывели всё. теперь надо переходить к тестам

                ;сейчас проверим, это ПЛИС реплика или оригинал?
                mov     #TRST30, @#4        ;прерывание по вектору 4 просто будем игнорировать.
                mov     #7, @#177130        ;вместо кода 6 используем код 7
                                            ;при этом на оригиналах и новоделах СМК-64 всё будет работать как обычно
                                            ; а на ПЛИС реплике - нет, режим не установится.
                                            ; эта особенность найдена при детальном изучении прошивки ПЛИС.
                                            ;там строб установки режима = 0110 = 0х6 (4 бита)
                mov     #160, @#177130      ;включаем стартовый режим
                mov     #0, @#177130
                mov     #160000,R0
                mov     #170000,R1
                clr     R5
                cmp     (R0),(R1)           ;если значения по этим адресам равны
                beq     0SMK64              ;то режим включился и это оригинал
                inc     R5                  ;нет - режим не включился, это ПЛИС реплика
0SMK64:         ;теперь в R5 код контроллера
                ;сейчас проверим какая прошивка, будем просто использовать кусок теста режимов.
                cmp     R4, #10             ;если это не СМК
                blo     15$                 ;то прошивку проверять не надо
                tst     @#StdMode
                bpl     17$
                tst     R5
                bne     31$
                mov     #CODA11, TZCODS     ;таблица кодов для СМК-64(128) на БК11
                br      18$

31$:            mov     #CODS11, TZCODS     ;таблица кодов для СМК-512 на БК11
                br      18$

17$:            mov     #CODS, TZCODS       ;таблица кодов для СМКхх на БК10

18$:            mov     #TT4All, @#4
                mov     #100, R0            ;код режима
                mov     #SYNCW, R2          ;проверочное слово
                mov     #160172, R3         ;адрес для проверки
                clr     R5
                call    DetectOldRT
                cmp     #4, R0
                bne     10$
                inc     R5
10$:            mov     #120, R0
                mov     #177172, R3
                call    DetectOldRT
                cmp     #11, R0
                bne     11$
                inc     R5
11$:            mov     #StrVersionRT, R3
                trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                tst     R5
                bne     12$
                mov     #RTOK,R3
                br      14$

12$:            comb    @#AltProDev         ;отметим, что прошивка неправильная
                cmp     #2,R5
                bne     13$
                mov     #RTBAD,R3
                br      14$

13$:            mov     #RTERR,R3
14$:            trap    20                  ;вывод строки символов. Вход: R3 - адрес строки
                return

15$:            tst     @#StdMode
                bpl     16$
                mov     #CODA11, TZCODS     ;таблица кодов для Ахх на БК11
                return

16$:            mov     #CODA, TZCODS       ;таблица кодов для Ахх на БК10
                return

DetectOldRT:    mov     R0, -(SP)
                mov     #20, R0     ;включаем режим 20, чтобы вписать куда нужно проверочное слово
                trap    4           ;чтобы алгоритм из теста режимов срабатывал стандартно
                mov     R2, -40000(R3)
                mov     (SP)+, R0   ;устанавливаем нужный режим
                trap    4           ;включение режима без учёта типа БК, вход: R0 - код режима
                clr     R0          ;тут накапливается код результата теста
                cmp     R2, (R3)    ;тестируем, есть ли доступ по чтению
                bne     3$
                beq     4$
                cmp     (R0)+, (R0)+ ;<-halt сюда для cmp
4$:             cmp     (R0)+, (R0)+
                ;зесь R0 == 0, 4, 010 при !=, =, halt
3$:             mov     R3, (R3)    ;тестируем, есть ли доступ по записи
                cmp     R2, (R3)    ;тестируем, работает ли запись как надо
                beq     6$          ;если запись прошла, но по чтению все равно изначальный вариант
                nop                 ;<-halt сюда для mov
                mov     R2, (R3)    ;<-halt сюда для cmp
                cmp     R2, (R3)
                br      5$
                br      1$          ;<-halt сюда для mov
5$:             bne     6$          ;<-halt сюда для cmp - !=
                inc     R0          ;write
6$:             inc     R0          ;nowr
1$:             return


SetMemTestLen:  clr     @#177660        ; разрешим прерывания от клавиатуры
                mov     #TZLNTS,R3
                trap    20
                mov     #32.,R1         ;начальное значение по умолчанию 
                mov     R1,@#LNGTST
                call    DECOU$
                mov     #"]:,R0
                trap    16
                swab    R0
                trap    16
                call    DECIN       ;ввод десятичного числа
                bcs     1$
                mov     R1,@#LNGTST
1$:             mov     #12,R0
                trap    16
                return

;выход:  R1 - полученное число.
;переполнение не проверяется, так что сколько влезет в 16 бит, столько и будет
;если бит С - то выходной результат недостоверен и должен игнорироваться
DECIN:          clr     R1          ;счётчик вводимых цифр
                mov     #DECBUF,R2  ;буфер, куда сохранять цифры
2$:             trap    6           ;ввод кода с клавиатуры. выход: R0 - код
                cmpb    #3,R0       ;если нажали КТ - то отмена
                beq     1CANS
                cmpb    #12,R0      ;конец ввода
                beq     10$
                cmpb    #30,R0      ;забой
                bne     1$
                tst     R1          ;что-то вводили?
                beq     2$          ;нет, игнорируем
                trap    16
                dec     R1          ;да, отменим последнюю цифру
                dec     R2
                br      2$

1$:             cmpb    R0,#'0      ;если не цифры
                blo     2$
                cmpb    R0,#'9
                bhi     2$          ;то тоже игнорируем
                cmp     R1,#5       ;больше 5 цифр не вводить
                bge     2$
                trap    16
                sub     #'0,R0      ;получим число
                movb    R0,(R2)+    ;и сохраним его
                inc     R1          ;увеличим счётчик введённые чисел
                br      2$

10$:            tst     R1          ;если нажали enter до ввода числа,
                beq     3$          ;то это означает просто согласие со значением по умолчанию
                ;а иначе интерпретируем введённое число
                mov     #DECBUF,R2
                clr     R3          ;тут накапливается результат
4$:             asl     R3
                mov     R3,R4
                asl     R3
                asl     R3
                add     R4,R3
                movb    (R2)+,R0
                add     R0,R3
                sob     R1,4$
                mov     R3,R1
                br      5$

1CANS:          tst     R1          ;если нажали esc, когда вводили число
                bne     3$          ;то это означает, просто отмену и согласие со значением по умолчанию
5$:             tst     (PC)+       ;а если нажали до ввода числа - значит отказ от теста
3$:             sec
                return
;вывод десятичного числа с подавлением ведущих нулей
;вход:  R1 - число
DECOU$:         jsr     R5, PUSHA
                clr     R5
                mov     #CONST, R2
6$:             clr     R0
                mov     (R2)+, R4
                beq     2$
1$:             sub     R4, R1
                bcs     0$
                inc     R0
                br      1$

0$:             add     R4, R1
                bis     R0, R5
                bne     4$
                cmp     #1, R4
                bne     6$
4$:             add     #'0, R0
                trap    16
                br      6$

2$:             return

TZLNTS:         .asciz  "Задайте длительность длинного теста (0 - без теста) ["
                .even

                .END

; Коды теста режимов
; 0 - ПЗУ (чтение есть, не равно; записи нет)
; 1 - ОЗУ поверх ПЗУ (чтение есть, не равно; запись есть, результат не меняется)
; 2 - чужое ОЗУ (чтение есть, не равно; запись есть, результат меняется)
; 4 - ОЗУ с защитой от записи (чтение есть, равно; записи нет)
; 5 - ОЗУ с защитой от записи, (чтение есть, равно; запись есть, результат не меняется, выдаётся RPLY)
; 6 - ОЗУ (чтение есть, равно; запись есть, равно)
; 10 - пусто (чтения нет; записи нет)
; 11 - ОЗУ с защитой от чтения (чтения нет; запись есть, результат не определён)


