Немига 303 ROM disasm

Материал из Emuverse
Версия от 10:46, 5 мая 2020; Nzeemin (обсуждение | вклад) (Новая страница: «{{Emuverse}} Источник: https://github.com/nzeemin/nemigabtl/blob/master/docs/nemiga-303.lst <pre> ; Дизассемблированное ПЗУ комп…»)
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)
Этот документ создан для Emuverse и распространяется на условиях лицензии CC-BY-SA-3.0.

Источник: https://github.com/nzeemin/nemigabtl/blob/master/docs/nemiga-303.lst

; Дизассемблированное ПЗУ компьютера НЕМИГА ПК 588 версия 3.03
;

000204: DW				; REV    Рабочий регистр
000206: DW				; VFORM
000210: DW				; BRIGHT
000212: DW				; XNEW
000214: DW				; YNEW
000216: DW				; XOLD
000220: DW				; YOLD

; ==== Начало ПЗУ ====
160000:	DW	177570			; ??
160002:	DW	160210, 000341		; Вектор прерывания сигнала/команды HALT
160006: DW	162010, 000340		; Вектор прерывания начального пуска
160012: DW	161126, 000340		; Вектор прерывания??
160016: JMP     @#163512		; MODE3
160022: JMP    	@#163532		; SYSLIN -- Вывод в служебную строку
160026: JMP    	@#163734		; TT.OUT
160032: JMP    	@#163740		; SYSOUT
160036: JMP    	@#162342		; PRINT
160042: JMP    	@#165344		; DRAW   -- Нарисовать линию, сохранив XOLD,YOLD
160046: JMP    	@#165336		; QDRAW     то же для QUASIC
160052: JMP    	@#165340		; FDRAW     то же для FORTRAN
160056: JMP    	@#165374		; LINE   -- Нарисовать линию
160062: JMP    	@#165366		; QLINE     то же для QUASIC
160066: JMP    	@#165370		; FLINE     то же для FORTRAN
160072: JMP    	@#165604		; POINT  -- Нарисовать точку
160076: JMP    	@#165576		; QPOINT    то же для QUASIC
160102: JMP    	@#165600		; FPOINT    то же для FORTRAN
160106: JMP    	@#165670		; RPOINT -- Читать яркость точки
160112: JMP    	@#165660		; QRPOIN    то же для QUASIC
160116: JMP    	@#165662		; FRPOIN    то же для FORTRAN
160122: JMP    	@#162304		; DUMP -- напечатать восьмеричное число R3
160126: JMP	@177754			; SOUND

; ==== Обработчики прерываний ========================================================

; Обработка канального сигнала СБРОС
160142: MOV	#000357, @#000206	; 239. -> VFORM
160150: CLR	@#177560		; Сброс состояния клавиатуры
160154: MOV	#000200, @#177564	; Устанавливаем состояние терминала
160162: CLR	@#177770
160166: BIC	#177541, @#177766	; Оставляем только флаги #136
160174: MOV	(SP)+, R0
160176: JMP	@#161060		; Завершаем обработку прерывания HALT
;
; Обработка нажатия СТОП?? кнопки ОСТ??
160202: MOV	(SP)+, R0		; Восстанавливаем R0
160204: JMP	@#161126		; Переходим к сохранению регистров и пульту
;
; Обработчик прерывания по сигналу/команде HALT
160210: CMP	#056311, @#177776	; Проверка, настроена ли память режима HALT
160216: BEQ	160224			; Да, настроена
160220: JMP	@#162010		; Нет => выход на процедуру холодного старта
160224: MOV	R0, -(SP)		; Сохраняем R0 чтобы не испортить
160226: BIS	#000200, @#177564	; Устанавливаем состояние терминала
160234: BIT	#176000, @#170006	; Проверка регистра фиксации HALT
160242: BMI	160142			; Канальный сигнал СБРОС? => переходим
160244: BEQ	160202			; 6 ст битов пусты - кнопка ОСТ?? => переходим
160246: BIT	#004000, @#170006	; Сигнал Н4? -- адаптер локальной сети
160254: BEQ	160262			; Нет
160256: CALL	@000104			; ??
160262: BIT	#040000, @#170006	; Сигнал Н1? -- обращение к 177566
160270: BEQ	160302			; Нет
160272: MOV	@#177566, R0		; Регистр данных терминала
160276: CALL	@#163740		; SYSOUT Вывод символа R0 на экран
160302: BIT	#020000, @#170006	; Сигнал Н2? -- обращение к 177562
160310: BEQ	160334			; Нет
160312: MOVB	@#177767, R0		; Провека буферной ячейки??
160316: BEQ	160326			; Буфер пуст
160320:	CLRB	@#177767		; Очищаем буфер
160324:	BR	160520
160326: BIC	#177677, @#177560	; Чистим ~0100 в рег.статуса клавиатуры - есть клавиша
160334: MOV	@#170006, R0
160340: BIT	#002000, R0		; Пришёл байт с клавиатуры?
160344: BEQ	160600			; Нет
160346: BIC	#177400, R0		; Оставляем байт поступивший с клавиатуры
160352: BEQ	160202			; Символ 00 -- СТОП?
; Звук нажатия клавиши
160354: MOV	R1, -(SP)
160356: MOV	R2, -(SP)
160360: TSTB	@#177761		; Флаг блокировки вызова SOUND
160364: BNE	160402			; <> 0 => не вызывать повторно
160366: CALL	@#160126		; SOUND
160372: BR	160402
160374: DW	160376			; Адрес мелодии
160376: DB	011, 214, 001, 000	; Мелодия - звук длиной 1/50 сек
160402: MOV	#177766, R1
160406: MOV	#000100, R2
160412: TSTB	(R1)
160414: BPL	160514
160416: BITB   	#000300, R0
160422: BEQ    	160472
160424: BPL    	160454
160426: BIT    	R2, R0
160430: BEQ    	160514
160432: BIC    	#177600, R0
160436: BITB   	R2, (R1)+
160440: BNE    	160514
160442: MOVB   	R0, (R1)
160444: MOV    	#000016, R0
160450: BISB   	R2, -(R1)
160452: BR     	160514
160454: BITB   	R2, (R1)+
160456: BEQ    	160514
160460: MOVB   	R0, (R1)
160462: MOV    	#000017, R0
160466: BICB   	R2, -(R1)
160470: BR     	160514
160472: CMPB   	R0, #000040
160476: BHIS   	160514
160500: MOVB   	161066(R0), @#177767	; Нажатая клавиша -> в буферную ячейку
160506: BEQ    	160514
160510: MOV    	#000033, R0
;
160514: MOV	(SP)+, R2
160516: MOV	(SP)+, R1
160520: MOV	R0, @#177562		; Записываем символ в рег.данных клавиатуры
160524: MOV	(SP)+, R0
160526: BIS	#000200, @#177560	; Состояние клавиатуры -- сброс бита готовности
160534: BIT	#000100, @#177560	; Состояние клавиатуры -- разрешено прерывание?
160542: BEQ	161060			; нет => Завершаем обработку прерывания HALT
160544: BISB   	#000001, @#177766
160552: TSTB   	000002(SP)
160556: BMI    	161060
160560: BICB   	#000001, @#177766
160566: MOV    	@#000062, -(SP)		; Кладём в стек вызов
160572: MOV    	@#000060, -(SP)		; прерывания по вектору 60
160576: BR     	161060
;
160600: MOV	(SP)+, R0		; Восстанавливаем R0
160602: BIT	#010000, @#170006	; Сигнал Н3?
160610: BEQ	161060			; Нет => Завершаем обработку прерывания HALT
; Обработка сигнала Н3 - кадровый синхроимпульс, 50 Гц
160612: MOV	R4, -(SP)		; Сохраняем R4
160614: TSTB	@#177761		; Флаг блокировки SOUND
160620: BPL	160746			; bit7=0 - блокировано => переходим
160622: MOV	@#177752, R4		; Берём адрес продолжения мелодии
160626: INCB	@#177760		; Увеличиваем счётчик длительности ноты
160632: CMPB	@#177760, 177777(R4)	; Сравниваем с длительностью ноты
160640: BLO	160746			; пока не кончилась => переходим
160642: TSTB	(R4)			; 200 ?
160644: BMI	160742			; да => переходим
160646: BITB	#000037, (R4)		; Есть ещё нота мелодии?
160652: BNE	160736			; да => переходим
160654: BICB	#000200, @#177761	; Снимаем флаг блокировки SOUND
; Обработка флагов завершения мелодии
160662: BITB	#000040, (R4)		; 040 и 140 ?
160666: BNE	160712			; да => переходим
160670: TSTB	(R4)			; 000 ? (никаких действий по окончании мелодии)
160672: BEQ	160746			; да => переходим
160674: MOV    	@#177750, @#160710	; Копируем адрес начала мелодии??
160702: CALL   	@#160126		; SOUND
160706: BR     	160746			; переходим к работе с курсором
160710: DW	000000
; Окончание мелодии байтом 040 либо 140
160712: BITB   	#000100, (R4)+		; байт 140?
160716: BNE    	160732			; да => переход
160720: MOV    	(SP)+, R4
160722: CLRB   	@#170006		; Разрешаем системные прерывания
; Переход на прерывание по вектору 110
160726: MOV    	@#000110, PC
; Окончание мелодии байтом 140
160732: CLRB   	(R4)			; Очистка байта после конца мелодии
160734: BR     	160746			; переходим к работе с курсором
;
160736: MOVB   	(R4)+, @#170030		; Октава и громкость
160742: CALL   	@#162560		; Обработка продолжения мелодии
; Мигание курсора
160746: DECB	@#177756		; Уменьшаем счётчик мигания
160752: BPL	161020			; значение >= 0 ? => переходим
160754: MOVB	#000007, @#177756	; Новое значение счётчика
160762: COMB	@#177757		; Инвертировать состояние курсора при мигании
160766: MOV	@#177772, R4		; Смещение курсора
160772: BMI	161020
160774: TSTB	@#177771		; Состояние курсора??
161000: BMI	161020
161002: ADD	#143105, R4		; + косвенный адрес, начало 25-й строки экрана
161006: BPL	161020			; Если за экраном => переходим
161010: MOV	R4, @#177572		; Устанавливаем косвенный адрес
161014: COM	@#177570		; Инвертирование восьми пикселей курсора
161020: MOV	(SP)+, R4		; Восстанавливаем R4
161022: TSTB	000002(SP)
161026: BMI	161060			; ?? => Завершаем обработку прерывания HALT
161030: BITB   	#000001, @#177766
161036: BNE    	160560
161040: BIT    	#000100, @#177564	; Разрешено прерывание в рег.состояния терминала?
161046: BEQ    	161060			; нет => переходим
161050: MOV    	@#000066, -(SP)		; Кладём в стек вызов
161054: MOV    	@#000064, -(SP)		; прерывания по вектору 64
; Завершение обработки прерывания HALT
161060: CLRB	@#170006		; Разрешаем системные прерывания
161064: RTI	
; Таблица байт
161066:

; Обработка прерывания?? Сохранение регистров и переход к пульту
161126: MOV	(SP)+, @#177736		; Сохраняем PC
161132: MOV	(SP)+, @#177740		; Сохраняем PSW
161136: MOV	SP, @#177734		; Сохраняем SP
161142: MOV	#177734, SP		; Сохраняем остальные регистры
161146: MOV	R5, -(SP)		; -> 177732
161150: MOV	R4, -(SP)		; -> 177730
161152: MOV	R3, -(SP)		; -> 177726
161154: MOV	R2, -(SP)		; -> 177724
161156: MOV	R1, -(SP)		; -> 177722
161160: MOV	R0, -(SP)		; -> 177720 -- начало блока регистров
161162: MOV	@#000004, -(SP)
161166: MOV	@#000006, -(SP)
161172: MOV	@#177766, -(SP)
161176: CLR	@#177766
161202: MOV	#000340, @#000006	; PSW для прерывания
161210: MOV	#161406, @#000004	; Адрес прерывания??
161216: MOV	#000060, @#170010
161224: BR	161406			; Переход к пультовому терминалу
;
; ==== Программа пультового терминала ================================================
;
; Просмотр ячеек памяти -- переход к следующему слову
161226: INC	R2
161230: INC	R2
; Команда '/' - просмотр ячеек памяти
161232: MOV	#162764, R5		; Строка
161236: CALL	@#162342		; Вывод строки, адрес в R5
161242: MOV	R2, R3			; Печатаем адрес
161244: CALL	@#162304		; Вывод R3 как 8-ричного числа
161250: MOV	(R2), R3		; Печатаем значение
161252: CALL	@#162304		; Вывод R3 как 8-ричного числа
161256: CALL	@#162356		; Получаем команду с клавиатуры
161262: TST	R1
161264: BEQ	161270
161266:	MOV	R5, (R2)		; Заносим новое значение
161270: CMPB	#000012, R0		; Нажали ПС?
161274: BEQ	161226			; Да, переходим к следующему слову памяти
161276: CMPB	#000015, R0		; Нажали ВВОД?
161302: BEQ	161406			; Да, возвращамся в пульт
161304: CMPB	#000136, R0		; Нажали '^' ?
161310: BNE	161516			; Нет -- выводим признак ошибки и в пульт
161312: DEC	R2			; Переходим к предыдущему слову памяти
161314: DEC	R2
161316: BR	161232
;
; Команда 'G' - продолжение выполнения программы
161320: MOV	(SP)+, @#177766
161324: TST	R1			; Параметр задан?
161326: BEQ	161342			; Нет => восстановление регистров и возврат
161330: CLR	@#177740
161334: MOV	R5, @#177736		; Адрес запуска
161340: RESET	
; Восстановление всех регистров, возврат из прерывания
161342: MOV	(SP)+, @#000006
161346: MOV	(SP)+, @#000004
161352: MOV	(SP)+, R0
161354: MOV	(SP)+, R1
161356: MOV	(SP)+, R2
161360: MOV	(SP)+, R3
161362: MOV	(SP)+, R4
161364: MOV	(SP)+, R5
161366: MOV	(SP), SP
161370: MOV	@#177740, -(SP)		; PSW
161374: MOV	@#177736, -(SP)		; PC
161400: RTI	
;
; Вывод символа и переход к пульту
161402: CALL	@#163734		; TT.OUT Вывод символа
; Вывод приглашения пульта и ожидание команды
161406: MOV	#162752, R5		; Строка "Пульт>"
161412: MOV	#177712, SP
161416: MOV	#000340, @#000006	; PSW для прерывания
161424: MOV	#161516, @#000004	; Адрес прерывания??
161432: CALL	@#162342		; PRINT Вывод строки, адрес в R5
161436: CALL	@#162356		; Получаем команду с клавиатуры
161442: MOV	R5, R2
161444: CMPB	#000057, R0		; Символ '/' - просмотр ячеек памяти
161450: BEQ	161232
161452: CMPB	#000123, R0		; Символ 'S' - вывод регистров ЦП
161456: BEQ	161524
161460: CMPB	#000107, R0		; Символ 'G' - выполнение программы
161464: BEQ	161320
161466: CMPB	#000104, R0		; Символ 'D' - загрузка с диска MD
161472: BEQ	161764
161474: CMPB	#000130, R0		; Символ 'X' - загрузка с диска DX
161500: BEQ	161646
161502: CMPB	#000116, R0		; Символ 'N' - загрузка с сети
161506: BEQ	162010			; Переход на программу холодного старта
161510: CMPB	#000014, R0		; Нажат УПР + L - очистка экрана
161514: BEQ	161402			; Вывод символа 014 и возврат к пульту
; Вывод знака вопроса (ошибка выполнения команды) и возврат в пультовый режим
161516: MOV	#162751, R5		; Строка " ?"
161522: BR	161412
;
; Команда 'S' -- вывод на экран регистров процессора
161524: MOV	#000011, R2		; 9 регистров
161530: MOV	#161556, R5		; Строка с названиями регистров
161534: CALL	@#162342		; Вывод строки
161540: MOV	#177720, R4		; Адрес блока сохранённых регистров
161544: MOV	(R4)+, R3
161546: CALL	@#162304		; Вывод R3 как 8-ричного числа
161552: SOB	R2, 161544
161554: BR	161406			; Возврат в пульт
161556: DB	...			; Строка с названиями регистров ЦП

; Команда 'X' -- загрузка с устройства DX
; (код загрузчика практически повторяет код загрузчика с DX/RX01 из ПЗУ ДВК)
161646: MOV	#100247, R2
161652: CMP	R5, #000001		; номер диска = 1 ?
161656: BLO	161666			; меньше 1 => переходим
161660:	BHI	161516			; больше 1 => показываем признак ошибки, возврат в пульт
161662:	BIS	#000020, R2
161666: MOV	#177170, R1		; Адрес регистра команд/состояния
161672: MOV	#040000, (R1)
161676: BITB	R2, (R1)		; <
161700: BEQ	161676			; / Ожидаем результат или ошибку
161702:	MOV	#000007, R3
161706:	MOV	R1, R0
161710:	MOV	R2, (R0)+
161712:	BR	161720
161714:	MOV    	#000001, (R0)
161720:	ASR    	R3			; 007 -> 003 -> 001 -> 000
161722:	BLO    	161730			; 
161724:	MOV    	(PC)+, (R1)		; 
161726:	MOVB   	(R0), (R3)+		; сохраняем полученный байт
161730:	BIT    	R2, (R1)		; <
161732:	BEQ    	161730			; / Ожидаем результат или ошибку
161734:	BMI    	161676			; 
161736:	BLO    	161714			; повтор
161740:	TSTB   	(R1)
161742:	BMI    	161726
161744:	CLR    	R0
161746:	CMPB   	#000247, R2
161752:	ADC    	R0
161754:	MOV    	#000200, @#177766
161762:	CLR    	PC			; Запуск полученного блока
;
; Команда 'D' -- загрузка с диска
161764: CMP	R5, #000007		; Номер устройства больше 7?
161770: BHI	161516			; Да => показать признак ошибки, возврат в пульт
161772: CALL	@#162774		; Загрузка данных с дисковода
161776: BLO	161516			; Ошибка? => возврат в пульт
162000: MOV	#000200, @#177766
162006: CLR	PC			; Запуск полученного блока
;
; ==== Программа холодного старта ====================================================
;
; Холодный старт при включении питания
162010: MOV	#001000, SP		; Устанавливаем стек
162014: CLR	R0
162016: MOV	#056311, -(R0)		; Сохраняем признак режима HALT -> (177776)
162022: MOV	#166064, -(R0)		; Адрес знакогенератора -> (177774)
162026: MOV	#000010, R1
162032: CLR	-(R0)			; <|
162034: SOB	R1, 162032		;  / Очищаем 010 слов 177754-177773 - переменные??
162036: MOV	#162556, @#177754	; Подставляем в SOUND пустую подпрограмму
162044: MOV	#162064, @#000004
162052: CLR	@#170024		; Сброс второго счётчика??
162056: MOV	#162474, @#177754	; Адрес полноценной программы SOUND
162064: RESET				; Сбрасываемся и переходим в режим USER??
162066: MOV	#000021, R0		; Символ очистки всего экрана
162072: CALL	@#163740		; SYSOUT Вывод символа R0 на экран
162076: CALL	@#163532		; SYSLIN Вывод в служебную строку
162102: BR	162106
162104: DW	162664			; Адрес строки названия машины и версии ПЗУ
162106: MOV	#161126, @#000004	; Адрес прерывания?? - переход в пульт
162114: MOV	#000340, @#000006	; PSW для прерывания
; Попытка загрузки из сети
162122: MOV	#170010, R4		; Адрес регистра состояния локальной сети
162126: MOV	#000014, (R4)		; Настройка состояния сетевого адаптера
162132: MOV	#162723, R5		; Адрес строки "ждите..."
162136: CALL	@#162342		; Вывод строки; после этого R5 = "Ошибка сети ? Пульт>"
162142: MOV	#162274, @#000004	; Адрес прерывания ??
162150: BIT	#100040, (R4)		; Проверяем состояние локальной сети
162154: BMI	162274			; ошибка сети, выходим
162156: BEQ    	162150
162160: TST    	(R4)
162162: MOVB   	#000003, @#170006	; Запрещение прерываний??
162170: MOV    	#000016, (R4)
162174: CALL   	@#162252		; Ожидаем слово из сети
162200: MOV    	000002(R4), R2		; Получили количество слов в блоке
162204: MOV    	R2, R3
162206: ASL    	R3			; Удваиваем -- получаем адрес за концом блока
162210: CMP    	(R3)+, (R3)+		; Сдвигаем R3 ещё на 2 слова вперёд
162212: MOV    	R3, SP			; Новый стек
162214: CLR    	R0			; R0 = 0 -- адрес куда читаем блок
162216: CALL   	@#162252		;<| Ожидаем слово из сети
162222: MOV    	000002(R4), (R0)+	; | Сохраняем полученое слово
162226: SOB    	R2, 162216		; / продолжаем
162230: MOV    	#000020, (R4)
162234: CLR    	-(SP)			; оставляем PSW = 0 для RTI
162236: CLR    	-(SP)			; оставляем PC = 0 для RTI
162240: BIS    	#000200, @#177766
162246: JMP    	@#161060		; разрешение прерываний и RTI
; Подпрограмма -- ожидание слова из сети
162252: MOV    	#037777, R1		; счётчик ожидания
162256: BIT    	#100040, (R4)
162262: BMI    	162274			; ошибка сети, выходим
162264: BEQ    	162272
162266: TST    	(R4)
162270: RETURN 	
162272: SOB    	R1, 162256
162274: MOV	#002060, (R4)
162300: JMP	@#161412		; Выводим "Ошибка сети ? Пульт>" и в пульт
;
; ==== Программы вывода на экран чисел и строк =======================================
;
; Подпрограмма DUMP Вывод слова как 8-ричного числа; R3 = число
162304: MOV	#000006, R1		; Шесть разрядов
162310: CLR	R0
162312: ROL	R3
162314: ROL	R0
162316: ADD	#000060, R0		; '0'
162322: CALL	@#163734		; TT.OUT Вывод символа
162326: CLR	R0
162330: ROL	R3
162332: ROL	R0
162334: ROL	R3
162336: ROL	R0
162340: SOB	R1, 162312
; Подпрограмма PRINT -- Вывод строки на экран; R5 = адрес строки
162342: MOVB	(R5)+, R0		; Очередной символ
162344: BNE	162350			; Не ноль?
162346: RETURN				; Конец строки, выходим
162350: CALL	@#163734		; TT.OUT Вывод символа
162354: BR	162342			; Продолжаем вывод строки
;
; Ввод команды; команда это символ либо 8-ричное число (параметр) и символ
162356: CLR	R1			; Длина параметра пока нулевая
162360: CLR	R5			; Параметр по умолчанию = 0
162362: TSTB	@#177560		; Получен ли символ с клавиатуры?
162366: BPL	162362			; Пока не получен
162370: MOVB	@#177562, R3		; Считываем символ
162374: CMPB	R3, #000177
162400: BNE	162430
162402: DEC	R1
162404: BMI	162356
162406: ASH    	R5, #177775
162412: BIC    	#160000, R5
162416: MOV    	#000134, R0
162422: CALL   	@#163734		; TT.OUT Вывод символа
162426: BR     	162362
162430: MOV	R3, R0
162432: CMPB	R0, #000040		; Это спецсимвол с кодом меньше кода пробела?
162436: BLO	162346			; Да => выходим
162440: CALL	@#163734		; TT.OUT Вывод символа
162444: BIC	#177407, R3
162450: CMP	#000060, R3		; Это цифра?
162454: BNE	162346			; Нет => выходим
162456: BIC	#177770, R0
162462: ASH	R5, #000003
162466: BIS	R0, R5			; Добавляем 8-ричную позицию к числу в R5
162470: INC	R1			; Длина строки увеличилась
162472: BR	162362			; Переходим к ожиданию следующего символа
; 
; Подпрограмма SOUND
162474: MOV	R4, -(SP)		; Сохраняем R4
162476: BICB	#000200, @#177761	; Предотвращаем повторный вызов SOUND: bit7=0
162504: CLR	@#170024		; Сброс таймер 2 (длительности)
162510: MOV	000002(SP), R4		; Откуда вызвали SOUND
162514: MOV	000002(R4), R4		; Получаем адрес мелодии 
162520: TSTB	(R4)
162522: BEQ	162554
162524: MOV	R4, @#177750		; Запоминаем адрес начала мелодии
162530: MOV	#001516, @#170020	; Пишем в регистр состояния таймера
162536: MOVB	(R4)+, @#170030		; Октава и громкость
162542: CALL	@#162560		; Обработка продолжения мелодии
162546: BISB	#000200, @#177761	; Возвращаем флаг блокировки SOUND: bit7=1
162554: MOV	(SP)+, R4		; Восстанавливаем R4
162556: RETURN	
;
162560: MOV	R3, -(SP)		; Сохраняем R3
162562: MOVB	(R4)+, R3
162564: BIC	#177760, R3		; Оставляем нижние 4 бита -- 00..17
162570: ASL	R3			; и умножаем на 2
162572: MOV	162624(R3), @#170022	; Выбираем по R3 слово и пишем в первый счётчик
162600: MOVB	(R4)+, @#170024		; Задаём длительность
162604: CLRB	@#177760		; Очищаем счётчик длительности ноты
162610: MOV	R4, @#177752		; Запоминаем адрес продолжения мелодии
162614: TST	@#170026		; Устанавливаем триггер таймера
162620: MOV	(SP)+, R3		; Восстанавливаем R3
162622: RETURN
; Значения задержки первого таймера для нот
162624: DW	000000, 003570, 003414, 003246, 003110, 002754, 002630, 002510
162644: DW	002374, 002264, 002160, 002061, 001764, 000000, 000000, 000000

;
; ==== Подпрограммы работы с дисководом MD ===========================================
;
; Чтение с дисковода для загрузки; R5 = номер устройства
162774: CALL	@#163512		; MODE3
163000: MOV	#000001, R4
163004: MOV	R5, -(SP)		; Запоминаем номер устройства
163006: ASR	R5			; Получаем номер привода
163010: BHIS	163016
163012: ADD	#000004, R5
163016: MOV	R5, @#004002
163022: MOV	#000400, -(SP)
163026: CLR	-(SP)
163030: MOV	R4, -(SP)		; Сохраняем R4
163032: MOV	#000006, R1		; Повторять 6 раз
163036: MOV	#000070, R0		;<| Команда -- мотор и ШАГ ВПЕРЁД
163042: CALL	@#163342		; | Готовимся и запускаем команду
163046: SOB	R1, 163036		; / Повтор цикла
163050: MOV	#000030, R0		; Команда -- мотор и ШАГ НАЗАД
163054: CALL	@#163342		; Готовимся и запускаем команду
163060: CLR	@#177106		; Сбрасываем таймер
163064: BIT	R4, @#177106		; Ждём
163070: BNE	163064
163072: BIT	#000010, (R5)		; TR00 ?
163076: BNE	163050			; Нет => повторяем команду ШАГ НАЗАД
163100: CLR	@#177106		;<| Сбрасываем таймер
163104: BIT	R4, (R5)		; | Сброшен RELOAD ?
163106: BEQ	163116			; | Да -- переходим к чтению секторов
163110: SOB	R2, 163100		; / Ждём
163112: JMP	@#163332
; Мы на 0-й дорожке, читаем первый сектор
163116: MOVB	R4, R0			; Количество секторов = 1
163120: MOV	#004004, R3		; Адрес буфера для чтения
163124: CALL	@#163402		; Прочитать сектора
163130: CLR	@#004000
163134: MOV	@#004000, R0
163140: MOVB	004016(R0), R0		; Первый байт -- кол-во секторов на 0-й дорожке
163144: MOV	#004140, R3		; Куда читать дорожку
163150: CALL	@#163402		; Прочитать сектора
163154: CLR	R1
163156: MOV	#004016, R5
163162: MOV	#000120, R4
163166: MOVB	(R5)+, R2
163170: MOV	R1, R0
163172: ADD	R2, R1
163174: CMP	R1, (SP)
163176: BHI	163206
163200: SOB    	R4, 163166
163202: JMP    	@#163332
;
163206: MOV	(SP), R3
163210: SUB	R0, R3
163212: SUB	#000120, R4
163216: ADD	@#004000, R4
163222: BEQ	163256
163224: MOV    	#000030, R0
163230: SUB    	R4, @#004000
163234: TST    	R4
163236: BPL    	163246
163240: MOV    	#000070, R0
163244: NEG    	R4
163246: CALL   	@#163342
163252: SOB    	R4, 163246
163254: BR     	163134
;
163256: INC	R3
163260: MOV	#003750, R5
163264: ADD	#000202, R5
163270: SOB	R3, 163264
163272: MOV	#000100, R4
163276: MOV	(SP)+, R3
163300: MOV	(SP)+, R2
163302: MOV	(R5)+, (R2)+
163304: DEC	(SP)
163306: BEQ	163322
163310: SOB	R4, 163302
163312: INC	R3
163314: MOV	R2, -(SP)
163316: MOV	R3, -(SP)
163320: BR	163154
163322: TST	(SP)+
163324: MOV	(SP)+, R0
163326: BR	163340
;
163330: TST	(SP)+
163332: MOV	(SP)+, (SP)+
163334: MOV	(SP)+, (SP)+
163336: SEC	
163340: RETURN
;
; Подготовка и запуск операции; R0 = операция
163342: MOV	#177106, R5		; Адрес регистра таймера дисковода
163346: MOV	#000006, R2		; 3 мс * 6 = 18 мс
163352: CLR	(R5)			; Стартуем таймер
163354: BIT	#000001, (R5)		; Таймер досчитал?
163360: BNE	163354			; Нет
163362: SOB	R2, 163352		; Продолжаем ждать
163364: BIS	@#004002, R0
163370: MOV	R0, -(R5)		; Задаём режим
163372: TST	-(R5)			; Заполняем флаги из регистра данных
163374: MOV	#000001, -(R5)		; Запуск операции
163400: RETURN				; Теперь R5 = адрес регистра состояния
;
; Чтение секторов; R0 = кол-во секторов, R3 = адрес куда читать
163402: MOV	R3, R1
163404: MOV	R0, -(SP)		; Запомним кол-во секторов
163406: MOV	#000012, R4		; 10 -- размер заголовка дорожки
163412: ADD	#000202, R4		; 130 -- размер сектора
163416: SOB	R0, 163412		; Умножим 130 на кол-во секторов
163420: MOV	#000010, R0		; Команда -- включить мотор и читать
163424: CALL	@#163342		; Организуем запуск команды
163430: MOV	#177102, R2		; Адрес регистра данных дисковода
163434: TSTB	(R5)			; Готов прочитанный байт?
163436: BPL	163434			; Пока нет -- TR не установлен
163440: MOVB	(R2), (R1)+		; Читаем очередной байт
163442: SOB	R4, 163434		; Переходим к следующему
163444: MOV	(R5), R0		; Запомним состояние
163446: CLR	(R5)			; Окончание операции чтения
163450: MOV	(SP)+, R4		; Вспомним кол-во секторов
163452: INC	R4
163454: BIT	#000141, R0		; RELOAD или OP-FAILED или LOST-DATA ?
163460: BNE	163330			; Да -- завершаемся с ошибкой
163462: MOV	#000010, R0		; 8 -- длина заголовка
163466: CLR	R2			; Начинаем считать контрольную сумму
163470: MOVB	(R3)+, R1		; Очередной байт
163472: ADD	R1, R2			; Добавляем к сумме
163474: SOB	R0, 163470
163476: MOV	#000200, R0		; 128 -- длина сектора
163502: CMP	R2, (R3)+		; Сумма совпала?
163504: BNE	163330			; Нет -- завершаемся с ошибкой
163506: SOB	R4, 163466		; Продолжаем подсчёт сумм секторов
163510: RETURN	
;
; Подпрограмма MODE3: Вызов подпрограммы с запретом системных прерываний
163512: MOVB	#000003, @#170006	; Запрещение прерываний
163520: CALL	@(SP)+			; Выполняем как п/п то что после CALL @#163512
163522: MOVB	#000000, @#170006	; Разрешение прерываний
163530: RETURN	
;
; Подпрограмма SYSLIN: Вывод в служебную строку
163532: CALL	@#163512		; MODE3
163536: MOV	R0, -(SP)
163540: MOV	R1, -(SP)
163542: MOV	#177772, R0		; Адрес переменной - место курсора
163546: MOV	(R0), -(SP)
163550: MOV	-(R0), -(SP)
163552: MOV	000012(SP), R1
163556: CMP	(R0)+, (R1)+
163560: MOV	(R1), R1
163562: MOVB	(R1)+, (R0)+
163564: CLRB	(R0)+
163566: ADD	#176000, -(R0)
163572: CLR	-(R0)
163574: BIS	#000010, -(R0)
163600: CMP	@#177772, #176062
163606: BGE	163622
163610: MOVB	(R1)+, R0		; Получаем следующий символ
163612: BEQ	163622			; 0?
163614: CALL	@#163740		; SYSOUT Вывод символа на экран
163620: BR	163600
163622: MOV	#177766, R0
163626: BIC	#000010, (R0)+
163632: MOV	(SP)+, (R0)+
163634: MOV	(SP)+, (R0)+
163636: MOV	(SP)+, R1
163640: MOV	(SP)+, R0
163642: RETURN	
;
163644: MOV    	#177772, R4
163650: SUB    	#000040, R2
163654: BPL    	163660
163656: CLR    	R2
163660: DECB   	@#177770
163664: BEQ    	163714
163666: MOV    	#000027, R5
163672: CMP    	R2, R5
163674: BHI    	163700
163676: MOV    	R2, R5
163700: MUL    	R5, #001200
163704: BIC    	#177700, (R4)
163710: BIS    	R5, (R4)
163712: BR     	164306
163714: MOV    	#000061, R5
163720: CMP    	R2, R5
163722: BHI    	163726
163724: MOV    	R2, R5
163726: BIC    	#000077, (R4)
163732: BR     	163710
;
; ==== Программа вывода символов на экран ============================================
;
; TT.OUT Вывод символа на экран; мл.байт R0 = символ
163734: CALL	@#163512		; MODE3
; SYSOUT Вход -- вывод символа
; Стандартная подпрограмма вывода символа
163740: MOV	R0, -(SP)
163742: MOV	R1, -(SP)
163744: MOV	R2, -(SP)
163746: MOV	R3, -(SP)
163750: MOV	R4, -(SP)
163752: MOV	R5, -(SP)
163754: CALL	@#165176		; Убрать курсор если он виден
163760: MOV	000012(SP), R2
163764: BIC	#177400, R2		; Оставляем только младший байт
163770: MOV	#177770, R5
163774: TSTB	(R5)
163776: BPL	164032
164000: CLRB	(R5)
164002: CMP	R2, #000131
164006: BEQ	164302
164010: CMP	R2, #000113
164014: BHI	164306
164016: SUB	#000100, R2
164022: BMI	164306
164024: MOVB	165306(R2), R4
164030: BR	164266
164032: BNE	163644
164034: MOVB	@#177766, R4
164040: BPL	164072
164042: CLR	@#177762		; | Маска фона для символа
164046: CLR	@#177764		; | Маска гашения символа перед выводом
164052: ROLB	R2
164054: CLC	
164056: BPL	164070
164060: BITB	#000040, R4
164064: BEQ	164070
164070: RORB	R2
164072: CMP	R2, #000040
164076: BLO	164230
164100: CMP	#166064, @#177774	; Знакогенератор стандартный?
164106: BNE	164130
164110: ROLB	R2
164112: BPL	164120
164114: BIC	#000100, R2
164120: BHIS	164126
164122: BIS	#000100, R2
164126: ASR	R2
164130: ADD	#142005, R3		; Начало основной части экрана
164134: SUB	#000040, R2		; Символ минус 32.
164140: ASL	R2			; Дальше умножаем на 10.
164142: MOV	R2, R5			;
164144: ASL	R2			;
164146: ASL	R2			;
164150: ADD	R5, R2			; Получили смещение в знакогенераторе
164152: ADD	@#177774, R2		; Знакогенератор
164156: MOV	#000012, R4		; Высота 10. пикселей
164162: MOVB	(R2), R5		;<| Берём строку символа
164164: SWAB	R5			; | Переносим в старший байт
164166: CLRB	R5			; |
164170: BISB	(R2), R5		; | Копируем в младший байт
164172: INC	R2			; |
164174: BIC	@#177764, R5		; | Маска гашения символа перед выводом
164200: MOV	@#177762, R0		; | Маска фона
164204: XOR	R0, R5			; |
164206: MOV	R3, 000002(R1)		; | Устанавливаем косвенный адрес
164212: MOV	R5, (R1)		; | Пишем в видеопамять
164214: ADD	#000100, R3		; | К следующей пиксел-строке
164220: SOB	R4, 164162		; /
164222: MOV	#177572, R0		; Регистр косвенного адреса
164226: BR	164424			; Переходим к следующей позиции вывода
; Обработка символов с кодом меньше #040
164230: MOV	#165322, R5
164234: BITB	#000010, R4
164240: BNE	164252
164242: CMP	(R5)+, (R5)+
164244: TSTB	R4
164246: BMI	164252
164250: CMP	(R5)+, (R5)+
164252: MOV	(R5)+, R4
164254: MOV	(R5), R5
164256: ASHC	R4, R2
164260: BPL	164546
164262: MOVB	165246(R2), R4		; По коду символа получаем смещение из таблицы
164266: BIC	#177400, R4		; смещение не больше 377
164272: ASL	R4			; смещение умножить на 2
164274: MOV	#177770, R5		; Размер экрана в байтах, начиная от начала ГЗУ
164300: ADD	R4, PC			; Переходим по 164302 + 2 * смещение из таблицы 165246
; +000 -- символ 20 либо ESC+131 -- прямая адресация курсора;
; следующие два байта строки: N строки+40, N позиции+40
164302: MOVB   	#000002, (R5)
164306: BR     	164546
; +003 -- символ 36 -- очистка служебной строки
164310: MOV    	#140000, R2		; Косвенный адрес начала экрана
164314: MOV    	#002000, R3		; Сколько слов чистить
164320: MOV    	R2, (R0)
164322: CLR    	(R1)
164324: INC    	R2
164326: SOB    	R3, 164320
164330: BR     	164546
; +014 -- символ 27 -- переход из режима "Немига" в VT-52
164332: BIC    	#000400, (R5)
164336: BIS    	#000200, -(R5)
164342: BR     	164546
;
164344: BIT	#000200, 177776(R5)
164352: BNE	164366
; +025 -- VT-52 символ ESC+106 -- вкл/откл звук подтверждения нажатия клавиши
164354:

164366: DECB	(R5)
164370: BR	164546
; +034 -- символ 06
164372: CLR	(R5)
164374: TST	-(R5)
164376: CLR	-(R5)
164400: CLR	-(R5)
164402: BR	164546
; +041 -- символы 02..05
164404: COMB	177760(R2)
164410: BR	164546
; +044 -- символ 30 -- погасить/включить курсор
164412: MOV    	#000200, R2
; +046 -- символ 01 -- включить/выключить сдвиг экрана
164416: SWAB   	R2
164420: XOR    	R2, (R5)
164422: BR     	164546
;
; Переход к следующей позиции вывода
164424: MOV	#177772, R5		; Текущая позиция курсора
164430: INC	(R5)			; Следующая позиция		
164432: MOV	(R5), R3
164434: MOV	R3, R4
164436: BIC	#177700, R4		; Позиция в пределах строки
164442: CMP	R4, #000062		; Больше 50 ?
164446: BLO	164546			; Меньше => завершаем процедуру
164450: BIC	#000077, R3		; Возвращаемся к началу строки
164454: MOV	R3, (R5)		; Сохраняем новое место курсора
164456: ADD	#001200, R3		; Добавляем 10 пиксел-строк
164462: CMP	R3, #034700		; Дошли до конца экрана?
164466: BLO	164554			; Нет => завершаем процедуру
164470: BIC	#177700, R3
164474: BITB	#000001, @#177771	; Состояние курсора??
164502: BNE	164554
; Скроллинг экрана
164504: MOV	#142005, R2		; Косвенный адрес куда копировать
164510: MOV	#143205, R3		; Косвенный адрес откуда копировать
164514: MOV	R3, (R0)		; Заносим адрес откуда
164516: MOV	(R1), R4		; Берём слово
164520: MOV	R2, (R0)		; Заносим адрес куда
164522: MOV	R4, (R1)		; Пишем слово
164524: INC	R2			; Переходим к след адресу куда
164526: INC	R3			; К след адресу откуда
164530: BNE	164514			; Экран не кончился? => повторяем
164532: BR	165074
; +115 -- символ 10 -- Backspace
164534: BIC    	#177700, R3
164540: BEQ    	165104
164542: DEC    	@#177772		; новое смещение курсора левее на 1
164546: BR     	165104
; +123 -- символ 15 -- возврат каретки
164550: BIC	#000077, R3		; На начало строки
164554: MOV	R3, @#177772		; Сохраняем позицию курсора
164560: BR     	165104
; +130 -- символ 11 -- горизонтальная табуляция с шагом 8
164562: MOV    	R3, R4
164564: BIC    	#177700, R4
164570: CMP    	R4, #000057
164574: BHIS   	165104
164576: ADD	#000010, R3
164602: BIC	#000007, R3
164606: BR	164554
; +??? -- символ VT-52 16 -- переход на русский регистр
164610: BIS    	#000040, -(R5)
164614: BR     	165104
; +??? -- символ VT-52 17 -- переход на латинский регистр
164616: BIC    	#000040, -(R5)
164622: BR     	165104
; +151 -- символ VT-52 ESC+100 -- переход в режим "Немига"
164624: BIC    	#177600, -(R5)
164630: BR     	165104

; +165 -- символ VT-52 ESC+101 или "Немига" 22 -- вверх 1
164654:

164662: MOV	R3, @#177772	; новое смещение курсора
164666: BR	165104
164670: ADD    	#001200, R3	; на 10. линий вниз
164674: CMP    	R3, #034700	; вышли за нижний край?
164700: BHIS   	165104		; да => тогда ничего не делаем
164702: BR     	164662		; устанавливаем новое смещение курсора и выходим
;
164704: INC    	R3
164706: MOV    	R3, R4
164710: BIC    	#177700, R4
164714: CMP    	R4, #000062
164720: BR     	164700
;
164722: CLR	R3
164724: BR	164662
164726: SUB    	#001200, R3
164732: BPL    	164662
164734: CLR    	R2
164736: MOV    	#176600, R3
164742: MOV    	#034600, R5
164746: DEC    	R3
164750: DEC    	R2
164752: MOV    	R3, (R0)
164754: MOV    	(R1), R4
164756: MOV    	R2, (R0)
164760: MOV    	R4, (R1)
164762: SOB    	R5, 164746
164764: MOV    	#001200, R5
164770: INC    	R3
164772: MOV    	R3, (R0)
164774: CLR    	(R1)
164776: SOB    	R5, 164770
165000: BR     	165104
; +240 -- символ 007 -- BELL
165002: BITB   	#000100, @#177761	; Проверяем байт блокировки SOUND
165010: BNE    	165104
165012: CALL   	@#160126		; SOUND
165016: BR     	165104			; к завершению обработки символа
165020: DR	165022			; адрес мелодии
165022: DB	001, 205, 017, 000
; +252 -- символ "Немига" 13, VT-52 ESC+113 -- очистить строку от позиции курсора
165026: CALL   	@#165126
165032: BR     	165104
; +255 -- символ "Немига "37, VT-52 ESC+112 -- очистка экрана от позиции курсора
165034: CALL	@#165126
165040: BIC	#000077, R3
165044: MOV	R3, R2
165046: ADD	#142005, R2		; Начало основной части экрана
165052: BPL	165104
165054: BR	165074
; +266 -- символ 21 -- очистка всего экрана, включая служебную строку
165056: MOV	#140000, R2		; Косвенный адрес начала экрана
165062: BR	165070
; +271 -- символ 14 -- перевод формата, очистка экрана, служебная строка сохраняется
165064: MOV	#142000, R2		; Начало экрана после служебной строки
165070: CLR	@#177772		; Курсор будет в начале экрана
165074: MOV	R2, (R0)		;<| Косвенный адрес
165076: CLR	(R1)			; | Очищаем слово
165100: INC	R2			; | Увеличиваем адрес
165102: BNE	165074			; / дошли до конца ? нет => повторяем
; +301 -- символ 00, ESC+105, ESC+107 -- неиспользуемый код символа
; Завершение обработки символа
165104: CALL	@#165176		; Восстановление курсора
165110: MOV	(SP)+, R5
165112: MOV	(SP)+, R4
165114: MOV	(SP)+, R3
165116: MOV	(SP)+, R2
165120: MOV	(SP)+, R1
165122: MOV	(SP)+, R0
165124: RETURN	
; Очистка строки от текущей позиции до конца строки
165126: MOV	#000012, R5		; 10. итераций
165132: MOV	R3, R2
165134: MOV	#000062, R4		; 50. позиций в строке
165140: BIC	#177700, R2
165144: SUB	R2, R4
165146: BLE	165166
165150: MOV	R3, R2
165152: ADD	#142005, R2		; Начало основной части экрана
165156: MOV	R2, (R0)
165160: CLR	(R1)
165162: INC	R2
165164: SOB	R4, 165156
165166: ADD	#000100, R3
165172: SOB	R5, 165132
165174: RETURN	
;
; Подпрограмма стирания/восстановления курсора
165176: MOV	#177570, R1		; Регистр данных косвенного доступа к памяти
165202: MOV	#177572, R0		; Регистр косвенного адреса
165206: MOV	@#177772, R3		; Место курсора от начала ГЗУ
165212: BMI	165244
165214: TSTB	@#177771		; Состояние курсора??
165220: BMI	165244
165222: TSTB	@#177757		; Состояние курсора при мигании
165226: BPL	165244			; не виден => не нужно убирать
165230: MOV	R3, R4
165232: ADD	#143105, R4		; + косвенный адрес 25-й строки экрана
165236: BPL	165244
165240: MOV	R4, (R0)		; Устанавливаем косвенный адрес
165242: COM	(R1)			; Инвертируем восемь пикселей -- курсор
165244: RETURN	
; Таблица смещений переходов для обработки спецсимволов
165246: DB	301, 046, 041, 041, 041, 041, 034, 240	; 00..07
165256: DB	115, 130, 066, 252, 271, 123, 143, 146	; 10..17
165266: DB	000, 266, 165, 154, 156, 210, 173, 014	; 20..27
165276: DB	044, 201, 115, 021, 212, 066, 003, 255	; 30..37
; Таблица смещений переходов для обработки символов ESC + 100..113
165306: DB	151, 165, 173, 201, 115, 301, 025, 301	; 100..107
165316: DB	210, 212, 255, 252

; Точка входа QDRAW -- DRAW для QUASIC
165336: MOV    	(SP), R5
; Точка входа FDRAW -- DRAW для FORTRAN
165340: CALL   	@#166040
; Точка входа DRAW -- нарисовать линию из (XOLD,YOLD) в (XNEW,YNEW)
; После выполнения операции XNEW=XOLD, YNEW=YOLD.
165344: CALL   	@#165374
165350: MOV    	@#000212, @#000216	; XNEW -> XOLD
165356: MOV    	@#000214, @#000220	; YNEW -> YOLD
165364: RETURN 	
; Точка входа QLINE -- LINE для QAUSIC
165366: MOV    	(SP), R5
; Точка входа FLINE -- LINE для FORTRAN
165370: CALL   	@#166040
; Точка входа LINE -- нарисовать линию из (XOLD,YOLD) в (XNEW,YNEW)
165374: MOV    	#000212, R5		; Адрес XNEW
165400: MOV    	(R5)+, R0
165402: MOV    	(R5)+, R1
165404: MOV    	(R5)+, R2
165406: MOV    	(R5)+, R3
165410: CLR    	@#000204		; Очищаем REV
165414: MOV    	#000001, R4
165420: MOV    	R4, R5
165422: SUB    	R2, R0
165424: BPL    	165432
165426: NEG    	R0
165430: NEG    	R5
165432: SUB    	R3, R1
165434: BPL    	165442
165436: NEG    	R1
165440: NEG    	R4
165442: CMP    	R0, R1
165444: BGE    	165474
165446: MOV    	R0, -(SP)
165450: MOV    	R1, R0
165452: MOV    	(SP), R1
165454: MOV    	R4, (SP)
165456: MOV    	R5, R4
165460: MOV    	(SP), R5
165462: MOV    	R2, (SP)
165464: MOV    	R3, R2
165466: MOV    	(SP)+, R3
165470: INC    	@#000204		; Инкремент REV
165474: TST    	R0
165476: BEQ    	165542
165500: ASL    	R1
165502: MOV    	R0, -(SP)
165504: ASL    	(SP)
165506: MOV    	R1, -(SP)
165510: SUB    	R0, (SP)
165512: CALL   	@#165542
165516: TST    	(SP)
165520: BMI    	165530
165522: SUB    	000002(SP), (SP)
165526: ADD    	R4, R3
165530: ADD    	R1, (SP)
165532: ADD    	R5, R2
165534: SOB    	R0, 165512
165536: CMP    	(SP)+, (SP)+
165540: RETURN 	
165542: MOV    	R1, -(SP)		; Сохраняем регистры
165544: MOV    	R2, -(SP)
165546: MOV    	R3, -(SP)
165550: TST    	@#000204		; Проверяем REV
165554: BEQ    	165562
165556: MOV    	R2, R3
165560: MOV    	(SP), R2
165562: CALL   	@#165614		; Выводим точку (R2,R3)
165566: MOV    	(SP)+, R3		; Восстанавливаем регистры
165570: MOV    	(SP)+, R2
165572: MOV    	(SP)+, R1
165574: RETURN 	
;
; Точка входа QPOINT -- POINT для QUASIC
165576: MOV	(SP), R5
; Точка входа FPOINT -- POINT для FORTRAN
165600: CALL	@#166040
; Точка входа POINT -- нарисовать точку
165604: MOV	@#000212, R2		; XNEW
165610: MOV	@#000214, R3		; YNEW
165614: CALL	@#163512		; MODE3
165620: CALL	@#165746		; Находим точку на экране
165624: BLO	165656
165626: TST	(R1)+
165630: MOV	@#000210, R2		; BRIGHT
165634: ASR	R2
165636: BLO	165646
165640: BIC	R3, @#177570		; Пишем в экран
165644: BR	165652
165646: BIS	R3, @#177570		; Пишем в экран
165652: SWAB	R3
165654: SOB	R1, 165634
165656: RETURN	
;
; Точка входа QRPOIN -- RPOINT для QUASIC
165660: MOV    	(SP), R5
; Точка входа FRPOIN -- RPOINT для FORTRAN
165662: CALL   	@#166040
165666: BR     	165674
; Точка входа RPOINT -- прочитать яркость точки
165670: MOV    	#000210, R4		; Адрес BRIGHT
165674: MOV    	@#000212, R2		; XNEW
165700: MOV    	@#000214, R3		; YNEW
165704: CLR    	(R4)
165706: CALL   	@#163512		; MODE3
165712: CALL   	@#165746		; Находим точку на экране
165716: BLO    	165742
165720: MOV    	#000002, R1
165724: SWAB   	R3
165726: BIT    	R3, @#177570
165732: BEQ    	165736
165734: ADD    	R1, (R4)
165736: SOB    	R1, 165724
165740: RETURN 	
165742: DEC    	(R4)
165744: RETURN 	
; Нахождение точки на экране; устанавливает косвенный адрес, возвращает маску в R3
165746: MOV	R2, R1
165750: CMP	#000637, R2
165754: BLO	166036
165756: ASH	R2, #177775
165762: CMP	(R2)+, (R2)+
165764: CMP	#000377, R3
165770: BLO	166036
165772: CMP	@#000206, R3		; Сравниваем с VFORM
165776: BLO	166036
166000: COMB	R3
166002: SWAB	R3
166004: SEC	
166006: ROR	R3
166010: ASR	R3
166012: BIS	R3, R2
166014: MOV	R2, @#177572		; Устанавливаем косвенный адрес
166020: BIC	#177770, R1
166024: INC	R1
166026: CLR	R3
166030: SEC	
166032: ROR	R3
166034: SOB	R1, 166032
166036: RETURN	
; Подготовка перед вызовом для FORTRAN
166040: MOV	(R5)+, R0
166042: MOV	(R5), R4
166044: BIC	#177770, R0
166050: BEQ	166062
166052: MOV	#000210, R3
166056: MOV	@(R5)+, (R3)+
166060: SOB	R0, 166056
166062: RETURN	
;
; ==== Стандартный знакогенератор ====
166064: DB				; Знакогенератор, 120 символов, 8 байт/символ

; ==== Блок переменных ====
177720: DW			; R0  при останове
177722: DW			; R1  при останове
177724: DW			; R2  при останове
177726: DW			; R3  при останове
177730: DW			; R4  при останове
177732: DW			; R5  при останове
177734: DW			; SP  при останове
177736: DW			; PC  при останове
177740: DW			; PSW при останове
177750: DW			; Адрес начала мелодии
177752:	DW			; Адрес продолжения мелодии
177754: DW			; Адрес подпрограммы SOUND
177756: DB			; Счётчик мигания курсора
177757: DB			; Состояние курсора: 000 - не виден, 377 - виден
177760: DB			; Счётчик длительности ноты
177761: DB			; Байт блокировки вызова SOUND
177762: DW			; FRG    Маска фона для вывода символа
177764: DW			; COL    Маска гашения символа перед выводом
177766: DW			; Какие-то важные флаги??
177770: DW			; SIZE   Размер экрана в байтах, начиная от начала ГЗУ
177772: DW			; CUR    Место курсора от начала ГЗУ
177774: DW			; SYMGEN Адрес знакогенератора
177776: DW			; Значение #056311