; Sprinter.

; Функции BIOS.

; Вызов функций производится через вход в TR-DOS #3D13. Номер команды
; задается в регистре C. Установленный на выходе флаг C означает завершение
; работы функции с ошибкой.
; При работе части функций биоса необходимо что бы стек находился в
; области #8000..#BFFF, так как они используют для своей работы переключение
; страниц PAGE1 и PAGE3. Для устранения каких либо неприятностей связанных со
; стеком его следует всегда устанавливать в этот диапазон при вызове функций
; биоса Спринтера.

; Вызов функций биос так же может быть осуществлен через вход по
; RST #18 при подключенном системном ПЗУ, а так же через RST 8 при
; подключенном ОЗУ в нулевой банке путем установки на адрес RST 8 небольшой
; программы, переключающейся в ПЗУ биоса

; Для подключения системного ПЗУ можно воспользоваться такой
; последовательностью команд:
        DI
        LD A,0
        OUT (#7C),A
; после этого в 0-м адресе будет включена ПЗУ биоса
; и программа может вызывать функции через RST #18,
; просто заменяя этим вызовом вызов CALL #3D13
; * Обычные функции TR-DOS в этот момент недоступны

; Чтобы вернуться к обычному ПЗУ следует выполнить программу:
        LD A,0
        OUT (#3C),A

; Вызов из ОЗУ осуществляется через RST 8. При этом на адресе 8 должна
; располагаться такая программа:
        PUSH AF
        LD A,0
        OUT (#7C),A    ; в этом месте вместо ОЗУ подключится ПЗУ биоса и
                        ; программа уйдет в него.
        POP AF          ; На эту команду происходит возврат при таком
                        ; вызове биоса.
        RET
; Оптимизация кода в этом месте недопустима. Вместо LD A,0 можно установить
; две команды XOR A и DI
; Далее вызов функций осуществляется аналогично RST #18, но следует помнить,
; что адресное пстранство 0000..#3FFF во время работы биоса занято ПЗУ и в нем
; не могут располагаться данные для работы функций.

; Вызов новых функций через #3D13 автоматически отключает прерывания.
; После исполнения функции программа должна включить их при необходимости.
; Если необходимо что бы прерывания были включены все время, следует
; использовать режим IM 2, с таблицей, стеком и обработчиком расположенным в
; области #8000..#BFFF и пользоваться вызовом через RST #18 или RST 8
; В этом случае прерывания в биосе не отключаются.

; В ближайшее время в описание биоса будут добавлены функции работы с FDD и
; CD-ROM
; * В данный момент они имеются, но предполагается их серьезная переделка.
; Некоторые функции зарезервированы для дальнейшего развития. Так же не
; описана часть графических функций, так как они в данный момент подвергаются
; серьезным переделкам.

;==============================================================================
;               1. Работа с памятью.
;==============================================================================
EMM:
.GetMemSize:    ; определение объемов ОЗУ
 LD C,#C0       ; функция номер #C0
 RST ToBIOS     ; HL - общий объем памяти в страницах по 16kb
                ; BC - объем свободной памяти в страницах по 16kb
;

.InitMem:       ; инициализация распределения памяти
                ; стирается вся информация о выделенных ранее блоках
                ; ОЗУ. Устанавливаются как занятые блоки с
                ; системной информацией, а так же первые 256kb ОЗУ	;!FIXIT
 LD C,#C1       ; номер функции
 RST ToBIOS     ; выходных параметров нет
;

.GetMem:        ; выделение блока ОЗУ
 LD B,num_pages ; запрашиваемое число страниц ОЗУ
 LD C,#C2       ; номер функции
 RST ToBIOS     ; NC -> А - идентификатор блока
                ; CF -> A=1 - нет памяти
;

.FreeMem:       ; освободить блок ОЗУ
 LD A,id_blk    ; идентификатор блока
 LD C,#C3       ; номер функции
 RST ToBIOS     ; NC - нормальное завершение
                ; CF - неверный идентификатор блока
                ; правильность идентификатора отслеживается не всегда
;

.GetMemPage:    ; получить физический номер страницы из блока
 LD A,id_blk    ; идентификатор блока
 LD B,page      ; логическая страница в блоке
 LD C,#C4       ; номер функции
 RST ToBIOS     ; NC -> А - физический номер страницы
                ; CF -> А=0 - нет такого блока, A=FF - конец блока
;

.GetMemBlkPages:; получить список физических страниц блока
 LD A,id_blk    ; идентификатор блока
 LD HL,bufer    ; буфер длиной 256 байт для размещения списка
                ; буфер должен быть длиной на единицу больше числа
                ; страниц в блоке
 LD C,#C5       ; номер функции
 RST ToBIOS     ; NC -> HL - тот же буфер, B - число страниц в блоке,
                ; данные по адресу HL - список физических страниц по
                ; порядку. Список заканчивается байтом FF
                ; CF -> неверный идентификатор блока. Старая
                ; информация в буфере может быть затерта
;

.GetBanksPorts: ; Получение адресов портов окон
 LD A,win_num   ; номер окна проецирования 0,1,2 или 3
 LD C,#C6       ; номер функции
 RST ToBIOS     ; NC -> C - 8-мибитный адрес порта, B - номер
                ; подключенной в данный момент страницы ОЗУ
                ; CF -> ошибка номера окна
; Функция фактически не используется в данный момент. Адреса портов окон
; не изменялись с самого начала разработки компьютера и, надеюсь, не будут
; меняться. Для соблюдения приличий программисту следует хотя бы один раз
; вызвать эти функции и сравнить адреса портов с теми, что используются в
; программе и, если они не совпадают, выдать соответствующее предупреждение.
; В данный момент эти порты таковы: PAGE0=#82, PAGE1=#A2, PAGE2=#C2, PAGE3=#E2
;

.GetMemPageNext:; получить следующую страницу блока по предыдущему
 LD A,page      ; физическая страница блока
 LD C,#C7       ; номер функции
 RST ToBIOS     ; NC -> A - следующая физическая страница блока
                ;       A=FF - индицирует конец блока
                ; CF -> ошибка номера страницы
; Информация о распределении памяти хранится в виде RAM Allocation Table,
; похожей на дисковый FAT. Поэтому нахождение физического номера следующей
; страницы по предыдущему физическому номеру происходит значительно быстрее,
; чем поиск по увеличенному на единицу логическому номеру.
;

.MergeMemBlocks:; слияние блоков
 LD A,id_blk1   ; блок номер 1
 LD B,id_blk2   ; блок номер 2
 LD C,#9E       ; номер функции
 RST ToBIOS     ; NC -> A - блок результата
                ; CF -> ошибка, неверный номер блока
;

.DivMemBlocks   ; разделение блока
 LD A,id_blk1   ; блок
 LD B,len_blk   ; новая длина блока
 LD C,#9D       ; номер функции
 RST ToBIOS     ; NC -> A - блок результата, B - блок остатка
                ; CF -> ошибка, неверный номер блока
;

;==============================================================================
;               2. Работа с блоками как с RAM-Disk-ами
;==============================================================================

.GetMemRMD:     ; Получить блок памяти N bytes для RAM-Disk'а
 LD A,ram_disk  ; номер RAM-Disk-а 0..15
 LD B,ram_blocks; число необходимых блоков
 LD C,#92       ; номер функции
 RST ToBIOS     ; NC -> L, A - КЛЮЧ RAM-Disk'а
                ; CF -> ошибка,
                ;  A - код ошибки: 1 - нет памяти
                ;                  2 - RAM-Disk занят
;

.FreeMemRMD:    ; Освободить блок памяти для RAM-Disk'а
 LD A,ram_disk  ; номер RAM-Disk'а 0..15
 LD C,#93       ; номер функции
 RST ToBIOS     ; NC - нормальное завершение
                ; CF - ошибка, А=0 - нет такого блока, A=2 - ошибка цепочки
;

.GetMemPageRMD: ; Получить физический номер страницы RAM-Disk'а
 LD A,ram_disk  ; номер RAM-Disk'а 0..15
 LD B,page      ; логическая страница RAM-Disk'а
 LD C,#94       ; номер функции
 RST ToBIOS     ; NC -> А - физический номер страницы
                ; CF -> А=0 - нет такого блока, A=FF - конец блока
;

.CheckInit:     ; Если обнаружен первый старт, то инициализация всей памяти, системных переменных
 LD C,#97       ; номер функции
 RST ToBIOS     ; 
;

RAMD_CALC_PAGE: ; Вычисление страницы и адреса в RAM-Disk по абсолютному номеру сектора
 LD A,ram_disk  ; номер RAM-Disk'а 0..15
 LD DE,sector   ; абсолютный номер сектора
 LD C,#98       ; номер функции
 RST ToBIOS     ; A - страница, HL - адрес в странице
;

.FullInit:      ; инициализация всей памяти, системных переменных
 LD C,#9F       ; номер функции
 RST ToBIOS     ; 
;

BLK_RD_WR:      ; чтение/запись из/в блок(а) памяти секторами
                ; по 256 байт (в случае с ROM диском можно по 512)
 LD HL,bufer    ; адрес буфера данных
 LD DE,sector   ; абсолютный номер сектора (считать по 256b сектор)
 LD B,sec_num   ; число секторов
 LD A,id_blk    ; идентификатор блока (для rom disk размер сектора: 1 - 256b, 2 - 512 b)
 LD A',command  ; команда 0 - чтение, #FF - запись, #46 чтение из ROM-Disk
 LD C,#C8       ; номер функции
 RST ToBIOS     ; NC -> нормальное завершение
                ; CF -> ошибка идентификатора
;

BLK_TO_RAMD:    ; назначить блок памяти RAM-Disk-у
                ; любой блок памяти может содержать данные
                ; RAM-Disk-а в формате TR-DOS для подключения этих
                ; данных в качестве диска и служит эта функция
 LD A,ram_disk  ; номер RAM-Disk-а 0..15 - соответствует
                ; RAM-Disk-ам от e: до t:
 LD B,id_blk    ; идентификатор блока
 LD C,#C9       ; номер функции
 RST ToBIOS     ; NC -> нормальное завершение
                ; CF -> ошибка: неверный номер RAM-Disk-а или RAM-Disk занят
;

RAMD_CLEAR:     ; освободить RAM-Disk
                ; освобождение RAM-Disk-а не есть освобождение
                ; блока ОЗУ. Это просто отключение блока ОЗУ от
                ; RAM-Disk-а
 LD A,ram_disk  ; номер RAM-Disk-а - 0..15
 LD C,#CA       ; номер функции
 RST ToBIOS     ; NC -> нормальное завершение, B - идентификатор
                ; блока отключенного от RAM-Disk-а
                ; CF -> ошибка: неверный номер RAM-Disk-а или
                ; RAM-Disk был свободен
;

GET_RAMD_ST:    ; получение идентификатора блока, назначенного на
                ; RAM-Disk
 LD A,ram_disk  ; номер RAM-Disk-а 0..15
 LD C,#CE       ; номер функции
 RST ToBIOS     ; NC -> A - идентификатор блока.
                ;       A=0 - блок не назначен.
                ; CF -> ошибка номера RAM-Disk-а
;

GET_RAMD_NUM:   ; получить номер RAM-Disk-а (0..15) по его block id
 LD A,id_blk    ; идентификатор блока
 LD C,#9B       ; номер функции
 RST ToBIOS     ; NC -> A - номер RAM-Disk-а (0..15).
                ; CF -> ошибка в идентификаторе блока или биос ниже 2.55
;
; [x] 4/11/23
SWAP_RAM_DRIVES:; поменять местами ID RAM драйвов (ZX/Sp)
 LD B,func	; 0 - swap to Sp, #FF - swap to ZX, #FE - no swap, only get info
 LD C,#9C	; номер функции
 RST ToBIOS     ; A - current RAM Drives set
;==============================================================================
;               3. Управление назначением на дисководы
;==============================================================================

; Каждый из 4-х дисководов TR-DOS может быть переназначен для работы
; с RAM-Disk-ами, винчестером и реальными дисководами.
SET_DISK_REDIR:	; установить на текущий драйв переназначение (старая функция для TR-DOS!)
 LD E,drv_type  ; физический тип и номер устройства
 LD C,#99	;
 RST ToBIOS	; NC -> нормальние завершение.
;

GET_DISK_REDIR: ; получить тип назначения на текущий драйв (старая функция для TR-DOS!)
 LD C,#9A	; номер функции
 RST ToBIOS     ; NC -> нормальние завершение. A - тип назначения
                ; A=0..3 - назначен реальный дисковод A:, B:, C:, D:
                ; A=4..19 - назначен RAM-Disk, A = ram_disk + 4
                ; A=#40..#4F - назначен винчестер (#40+hdd_drive)
;

RAMD_TO_DRV:    ; назначение RAM-Disk на дисковод.
 LD A,ram_disk  ; номер RAM-Disk-а
 LD B,drive     ; номер дисковода 0..3 - соответствует дисководам
                ; A:, B:, C:, D:
 LD C,#CB       ; номер функции
 RST ToBIOS     ; NC -> нормальние завершение
                ; CF -> ошибка: неверный номер драйва или рамдиска
;

FDD_TO_DRV:     ; назначение реального дисковода
 LD А,disk_drive; номер физического дисковода 0..3
 LD B,drive     ; номер драйва 0..3
                ; Номер физического дисковода и номер драйва должны
                ; совпадать, так как компьютер не имеет
                ; электрической схемы переключения дисководов на
                ; разные буквы. В будущих версиях железа, возможно,
                ; это появится.
 LD C,#CC       ; номер функции
 RST ToBIOS     ; NC -> нормальние завершение
                ; CF -> ошибка: неверный номер драйва или дисковода
;

HDD_TO_DRV:     ; назначение винчестера на дисковод
 LD A,hdd_drive ; Номер винчестера.
                ; различных разделов и master/slave
 LD B,drive     ; номер драйва 0..3
 LD C,#CD       ; номер функции
 RST ToBIOS     ; NC -> нормальние завершение
                ; CF -> ошибка: неверный номер драйва или винчестера
;

GET_DRV_ST:     ; получить тип назначения на драйв      ; !TODO проверить
 LD A,drive     ; номер драйва 0..3
 LD C,#CF       ; номер функции
 RST ToBIOS     ; NC -> нормальние завершение. A - тип назначения
                ; A=0..3 - назначен реальный дисковод A:, B:, C:, D:
                ; A=4..19 - назначен RAM-Disk, A = ram_disk + 4
                ; A=#40..#4F - назначен винчестер (#40+hdd_drive)
                ; CF -> ошибка номера драйва
;

;==============================================================================
;               4. Функции управления железом и определение версии.
;==============================================================================

;!TODO
FN_SEND_BYTE
 LD C,#E8
 RST ToBIOS
;
;!TODO
FN_RESEIVE_B
 LD C,#E9
 RST ToBIOS
;
;!TODO
FN_KBD_OUT  
 LD C,#EA
 RST ToBIOS
;

FN_CRIPT
 LD B,func	; 1: HL - ROM_NUMBER part1
;		      A - ROM_NUMBER part2
;		     BC - BoardID start
;		     DE - BoardID end
;		[x] 28/01/2024
;		; 2: HL - адрес буфера для названия чипа (текст). максимум 5 байтов, заканчиваются нулём
 LD HL,buff	;   CF = 0:
;		;     A: 0 - K30, 1 - K50, остальное в резерве на будущее
;		;    DE: версия битстрима
 LD C,#ED
 RST ToBIOS
;

RST_CONF.AY8910:; переключение в конфигурацию Spectrum. AY8910
 LD C,#EE	; номер функции
 RST ToBIOS	; NC -> нормальное завершение
		; CF -> функция не исполнена, фатальная ошибка
		; машину следует перезапустить по RESET
;

FN_VERSION:     ; выдача информации о версии биоса и железа
 LD HL,bufer    ; буфер, куда будет помещена ASCIIZ строка с
                ; названием и номером версии, конец строки отмечен
                ; нулем.
 LD C,#EF       ; номер функции
 RST ToBIOS     ; NC -> HL - тот же буфер с записанной строкой:
		;	   "название прошивки | Sprinter | версия_конфы"
		;	 A - число полей строки в буфере HL
                ;       DE - версия биоса
                ;       BC - версия железа (;!TODO тут выдаётся CONFIG_BYTE)
                ;         BC=#FFFF - not identifyed
                ;         BC=#FFFE - Sprinter-1
                ;         BC=#FFFD - Sprinter-2
                ;         BC=#FFFC - Spectrum + AY8910
                ;         BC=#FFFB - Game-1
                ;         BC=#FFFA - Video-1
                ;         BC=#FFF9 - DooM
		;	  BC=#FEFF - Sprinter 2000
                ;         Иные значения BC - новые прошивки
                ;       версия железа выдается только
                ;       в биосах версий 1.16 и выше
                ; CF -> ошибка. Очень старая версия, не имеющая
                ; данной функции
;!!!!! Старая версия выдавала:
;		; L - первые 4 бита - биты порта All_Mode.
;		; 	в FN есть такой код:
;
	; LD	A,%0000'1101	; нужные биты для порта All_Mode
	; AND	L
	; SUB	%0000'1101
	; JR	Z,InitVM1
	; IN	A,(SCREEN_SWITCH)
	; PUSH	AF
	; LD	C,BIOS.RST_CONF.SP97_2
	; RST	ToBIOS
	; SUB	A
	; OUT	(BORDER),A
	; POP	AF
	; OUT	(SCREEN_SWITCH),A
;


;!FIXIT
RST_CONF.SP97_1:; переключение в конфигурацию Sprinter-1. SPRINTER_1
 LD C,#F0       ; номер функции
 RST ToBIOS     ; NC -> нормальное завершение
                ; CF -> функция не исполнена, фатальная ошибка
                ; машину следует перезапустить по RESET
;

;!FIXIT
RST_CONF.SP97_2:; переключение в конфигурацию Sprinter-2. SPRINTER_2
 LD C,#F1       ; номер функции
 RST ToBIOS     ; NC -> нормальное завершение
                ; CF -> функция не исполнена, фатальная ошибка
                ; машину следует перезапустить по RESET
;

RST_CONF.CUSTOM:; переключение конфигурации пользователя. SPRINTER_ALL
 LD A,page_cnf  ; страница с файлом прошивки для ПЛМ EPF10K10
                ; страница не может иметь номер больше 127
                ; Файл прошивки, естественно должен быть уже
                ; загружен в эту страницу
 LD B,ramblk	; [x] при A = #FE перезаливка конфы с возвратом. B указывает на RAM Block ID с битстримом для загрузки, если B=0, то загрузка из ROM 
		; [x] при A = #FD происходит реинит. Аксель включается и тд... можно напихать туда ещё что-нибудь
		; [x] при A = #FC софт-ресет с возвратом
		; [x] при A = #FB установка перехватчика софт-ресета, DE - адрес процедуры
		; [x] при A = #FA установка перехватчика хард-ресета, DE - адрес процедуры, B - RAM_BLK_ID с конфой, либо 0, если из пзу
 LD C,#F3       ; номер функции
 RST ToBIOS     ; NC -> нормальние завершение
                ; CF -> функция не исполнена, фатальная ошибка
                ; машину следует перезапустить по RESET
;

;		; [x] free zx pages 
GOTO_SPEC:	; Вход в режим спектрума
; Вход:	D: 0 - BASIC 128, 1 - BASIC 48, 2 - TR-DOS 128,
; 	   3 - EXPANSION. C закрытыми 128-ми портами:
; 	   4 - TR-DOS, 5 - BASIC 48
;	E: значение для SYS_PORT/CNF_PORT
;	L: Block_ID.vROM
;	H: Block_ID.vRAM
;	B: Port All Mode
;A [1..0]: 1 - int scorp, 2 - int pent, 3 - int ZX 
;   A'[2]: 0 - set default palette, 1 - don't change palette
;   A'[7]: 0 - 320, 1 - 312 строк
 LD C,#FB
 RST ToBIOS
;

REINIT:         ; [x] Сброс, перезагрузка, рестарт, очистка памяти с восстановлением ZX pages	; [ ] free zx pages!
 LD B,res_type  ; 1 - рестарт, 2 - soft reset, 3 - hard reset. 4 - clear RAM except zx pages
 LD C,#FD       ; номер функции
 RST ToBIOS     ; CF -> функция не исполнена, возможные причины:
                ;       - некорректное значение res_type
                ;       - одна из ZX страниц занята (при res_type=4),
                ;         тогда под zx отдастся только часть страниц
                ;       - старая версия BIOS
;

;[x]
FN_SYNC:        ; установка синхронизации, очистка режима экрана, установка задержек
                ; функция может быть отнесена и к группе функций
                ; вывода на экран, так как полностью очищает
                ; страницы режима экрана. На всем экране остается
                ; только бордюр
 LD A,sync_mode ; режим синхронизации
                ; Reg A bit7 = 0 - режим очистки экрана и установки INT:
                ;       A = 0:  режим по умолчанию - используется для очистки
                ;               страниц режима (отключения вывода всех окон)
                ;       A = 1:  режим Scorpion - 312 строк в экране,
                ;               положение INT-а, как в Scorpion-256
                ;       A = 2:  режим Pentagon - 320 строк в экране,
                ;               положение INT-a как в Pentagon-128
                ;       A = 3:  режим Spectrum
                ;               положение INT-a как в оригинальном ZX Spectrum
                ;       A = 4:  установка INT из настроек пользователя в CMOS
                ;       A = 5:  установка INT из таблицы пользователя
		;		указатель в IX, данные в SLOT1..2
                ;
                ; Reg A bit7 = 1 - режим установки вертикальной синхронизации и/или wait:
                ; bit1,bit0:
                ;       %00	- синхра выставляется из системной переменной
                ;       %01	- синхра выставляется из CMOS
                ;       %10	- синхра 320 lines 49 Hz
                ;       %11	- синхра 312 lines 50 Hz
                ; bit2:
                ;       %0	- игнорировать bit1..bit0
                ;       %1	- не игнорировать bit1..bit0
                ; bit3:
                ;       %0	- no waits (port all_mode bit2 set)
                ;       %1	- original waits (port all_mode bit2 res)
                ; bit4:
                ;       %0	- игнорировать bit3
                ;       %1	- не игнорировать bit3
                ; bit5,bit6 - reserved					;!TODO use for HOLD port?
                ;
 LD C,#F2       ; Номер функции
 RST ToBIOS     ; NC -> нормальное завершение
                ; CF -> неверный номер режима синхронизации
; изменение режима синхронизации может привести к временному сбою
; синхронизации монитора.

; !TODO подробное описание
DCP_CONFIG:     ; [x] функция управления дешифратором портов.
                ;A  - если ноль, то вызов функции переинициализации портов PORTS_INIT
                ;HL - адрес
                ;DE - маска - 0 изменяемые биты, 1 неизменяемые
                ;B  - порт
                ;C  - #F4      номер функции
; Функция позволяет открывать/закрывать дополнительные порты компьютера.
;

; Функции SET_PORTS и READ_PORTS позволяют иметь доступ
; к любым портам компьютера независимо от того, открыты они или нет.
; С помощью этих функций возможно прочитать содержимое портов 1FFD и
; 7FFD, например, а так же установить нужные значения в закрытые системные
; порты. Порты User-а позволят эмулировать некоторые устройства,
; отсутствующие в Спринтере, а так же могут дать особый способ
; передачи данных между программами, минуя ОЗУ.

;
SET_PORTS:      ; глобальная установка портов.
 LD A,port_num  ; внутренний номер порта
                ; F0..FF - страницы Scorpion 0..15, подключаемые в
                ; адрес #C000, страница именно та, которая
                ; подключена в данный момент через 7FFD,1FFD
                ; E0=EXPANSION, Е1=TR-DOS, E2=BASIC-128, E3=BASIC-48
                ; E4=EXPANSION',Е5=TR-DOS',E6=BASIC-128',E7=BASIC-48'
                ; E8=RAM0, E9=RAM1, EA=RAM2, EB=SYS0, EC=CASH
                ; ED,EE - reserv, EF=SYS1
                ; C0=COPY_1FFD, C1=COPY_7FFD, C2=COPY_BRD, C3-reserv
                ; C4-reserv, C5=COPY_V_MODE, C6=COPY_SYS, C7-reserv
                ; C8..CF - альтернативный набор для C0..C7
                ; D0..DF-reserv - доп. страницы для Pentagon-512
                ; 80..BF-user_ports!
                ; 00..7F-внешние порты, использовать не рекомендуется
 LD B,port_data ; данные, записываемые во внутренний порт
 LD C,#F8       ; номер функции
 RST ToBIOS     ; B - предыдущее содержание порта
;

; [x] 26/01/2024 добавлена.
READ_PORTS:     ; глобальное чтение портов
 LD A,port_num  ; внутренний номер порта
 LD C,#F9       ; номер функции
 RST ToBIOS     ; B - содержание порта
;

; [x] 26/01/2024 процедура дублирует функционал SET_PORTS. Убрана.
;WRITE_PORTS:    ; глобальная запись портов
; LD A,port_num  ; внутренний номер порта
; LD B,data_port ; записываемые данные
; LD C,#FA       ; номер функции
; RST ToBIOS     ;
;;;


CMOS_RD:        ; читать из регистра CMOS
 LD D,cmos_reg  ; номер регистра CMOS
 LD C,#F6       ; номер функции
 RST ToBIOS     ; NC - часы есть
                ; CF - часов нет
                ; A  - значение ячейки
;

CMOS_WR:        ; писать в регистр CMOS
 LD D,cmos_reg  ; номер регистра CMOS
 LD A,Value     ; значение
 LD C,#F7       ; номер функции
 RST ToBIOS     ; NC - часы есть
                ; CF - часов нет
; Функции CMOS_RD,CMOS_WR работают всегда. Если в машине нет микросхемы CMOS,
; она эмулируется. Наличие микросхемы определяется функцией CMOS_TEST.
;

CMOS_TEST:      ; проверить наличие CMOS
 LD C,#F5       ; номер функции
 RST ToBIOS     ; NC - часы есть
                ; CF - часов нет
;

FN_TURBO:       ; функция управления турбо режимом и плотностью ВГ93
 LD A,turbo_mode; режим турбо:     2 - off,  3 - on
                ; плотность ВГ93: 18 - 720, 19 - 1440
 LD C,#8F       ; номер функции
 RST ToBIOS     ; NC -> исполнение
                ; CF -> неверный режим турбо
; * переключение режима турбо может не произойти, если прошивка не
; поддерживает это переключение. При этом ошибки не происходит.
;

;==============================================================================
;               5. Функции печати и управления режимом экрана.
;==============================================================================

;!TODO Графические функции
;-----------------------;
;PIC_FN0                ; #A0  ОТКРЫТИЕ ОКНА
;PIC_FN1                ; #A1  ВЫВЕСТИ ТОЧКУ
;PIC_FN2                ; #A2  ВЫВОД ЛИНИИ COPY
;PIC_FN3                ; #A3  ВЫВОД ЛИНИИ FILL
;PIC_FN4                ; #A4  ВЫВОД ПАЛИТРЫ	;!FIXIT установка палитры
;PIC_FN5                ; #A5  УСТАНОВКА SCREEN_SWITCH
;PIC_FN6                ; #A6  A - page_pal, E - номер палитры, B - тип палитры
;PIC_FN7                ; #A7  Рисование линии одного цвета
;PIC_FN8                ; #A8  Рисование разноцветной линии 
;-----------------------;

WIN_OPEN:               ; функция открытия окна.
 LD IX,win_descriptor   ; описатель окна
                        ;  IX           - 32-хбайтовый описатель окна
                        ;  (IX+0)       - горизонтальный размер окна в знакоместах
                        ;  (IX+1)       - вертикальный размер в знакоместах
                        ;  (IX+2)       - положение окна по горизонтали на экране
                        ;  (IX+3)       - положение окна по вертикали на экране
                        ;  (IX+4)       - режим знакоместа
                        ;                       bit4=1 - text_mode  bit4=0 - graf_mode
                        ;                       bit5=0 - 16, bit5=1 - 8 точек в знакоместе
                        ;                  graf_mode
                        ;                       bit7..6 - номер палитры
			;			bit3..0 - не существенны
                        ;                  text_mode
			;			bit7..6,3..0 - номер знакогенератора
                        ;                       исключение: bit7..6=B"11" -> бордер
                        ;  (IX+5)       - дополнительный режим знакоместа
                        ;                       bit0=1 - указывает на включение спектрумовской
                        ;                       адресации экрана
                        ;  (IX+6)       - положение по X в поле графики (по знакоместам)
                        ;  (IX+7)       - положение по Y в поле графики (по знакоместам)
                        ;                       разъяснения о положении в поле графики - ниже
                        ;  (IX+8..31)   - зарезервировано (переменные окна)
 LD E,win_flag          ; флаги окна:
                        ;       бит 0   - указывает какую страницу режима включать
                        ;                 после исполнения функции. bit0=0 - экран 0, bit0=1 - экран 1
                        ;       бит 4   - указывает на какой странице режима
                        ;                 открывать окно. bit4=1 - экран 0, bit4=0 - экран 1
 ;LD HL,win_place	; HL - место на экране по знакоместам (копия в IX+2,3),
                        ;      в новых версиях биоса значение HL не существенно    
 LD C,#B0               ; номер функции
 RST ToBIOS             ; NC -> A - номер окна
                        ; CF -> ошибка слишком много окон
 LD (id_win),A          ; сохранить идентификатор окна

; * При открытии окна описатель копируется в системную страницу ОЗУ и
; программа может не сохранять его.
; ** В данный момент идентификатор окна всегда равен 0

; Видео-ОЗУ Спринтера можно представить как одно сплошное поле графики
; размером 1024 точки по горизонтали на 256 точек по вертикали
; Положение в поле графики показывает где будет находиться в этом поле
; верхний левый угол окна. Положение исчисляется в знакоместах. Т.е.
; Если указано положение по X - 2, по Y - 6, это означает, что верхний угол
; окна будет расположен по координатам X=16, Y=48 в поле графики видео-ОЗУ
; Таким образом, если, например, открыть два окна в разных местах, но с
; одинаковыми координатами в поле графики, на экране окажутся два
; идентичных окна, данные в которые будут попадать одновременно.

; Знакогенераторы текстовых режимов так же располагаются в видео-ОЗУ и
; имеют конкретные адреса в поле графики. При необходимости иметь на экране
; как графическое, так и текстовое изображение надо следить, что бы
; данные графических окон не попадали в поле графики, где расположены
; знакогенераторы

; При использовании какого либо знакогенератора, он занимает часть поля
; графики по координатам
; (координаты в знакоместах, т.е. в значениях байта IX+6 описателя окна)
; X = (8 * ( bit3..0 режима ))..(8 * ( bit3..0 режима ) + 7)
; По Y занимаются все положения.
; Таким образом, при использовании нескольких знакогенераторов сначала
; следует использовать знакогенераторы с номерами меняющимися в Bit7..6,
; так как они попадают в одни и те же координаты поля графики

; При открытии графических окон следует помнить, что в этот момент
; информация текстового экрана находящаяся в этом месте будет утеряна.
; При открытии текстового окна изменяется информация только в поле графики
; знакогенератора соответствующему этому текствовому экрану. Если эта
; информация и информация графического окна не пересекались, то при
; повторном открытии графического экрана, на нем автоматически
; восстановится графическая картинка
;

WIN_CLOSE:      ; закрытие окна
 LD A,(id_win)  ; идентификатор окна (пока должен быть 0)
 LD C,#B1       ; номер функции
 RST ToBIOS     ; NC -> успешное завершение
                ; CF -> ошибка - неверный идентификатор
                ; Окно с номером 0 никогда не закрывается и попытка
                ; закрытия приводит к ошибке


LP_OPEN_S:      ; Открытие стандартных окон.
 LD E,win_flag  ; флаги окна
                ; bit 0 определяет страницу режима, которая будет
                ; открыта после исполнения функции
 LD B,win_type  ; тип открываемого окна:
                ;       0 - спектрумовское окно 32x24
                ;       1 - текстовое окно 64x24
		;	2 - текстовое окно 40x32
                ;       3 - текстовое окно 80x32
                ;       4 - спектрумовское окно, HL - положение окна
                ;       5 - текстовое окно 64x24, HL - положение окна
		;	6 - текстовое окно 40x32, HL - положение окна
                ;       7 - текстовое окно 80x32, HL - положение окна
                ;       8 - графическое окно 0, HL - положение окна
                ;       9 - графическое окно 1, HL - положение окна
 LD HL,win_place; положение окна для 4..9 типов
 LD C,#80       ; номер функции
 RST ToBIOS     ; выполнить функцию
; ** Функция старая, использовать не рекомендуется.

; Далее, в функциях запоминания, восстановления, перемещения и стирания
; подразумеваются локальные окна в смысле "окно в окне". Идентификатор окна
; относится к глобальному окну, отнисительно которого адресуются локальные
;

WIN_COPY:       ; копирование данных текстового окна в память
                ; запоминание окна
 LD A,(id_win)  ; идентификатор глобального окна (пока должен быть 0)
 LD H,ver_size  ; HL - размер локального окна вертикаль/горизонталь
 LD L,hor_size  ; размер в символах
 LD D,ver_place ; DE - положение локального окна в глобальном окне
 LD E,hor_place ; положение по горизонтали в символах
 LD IX,bufer    ; адрес буфера для запоминания данных локального окна. (для режиима 80x32)
 LD B,bufer_page; страница буфера данных окна (только SLOT3 или SLOT2)
		; адрес буфера указывается для окна #C000
                ; если адрес указан с #8000, номер страницы буфера
                ; не действителен
 LD C,#B2       ; номер функции
 RST ToBIOS     ; NC -> нормальное завершение
                ; CF -> ошибка - неверный идентификатор окна
; при работе этой функции через RST #18 или RST 8, обязательна установка
; DI, так как функция пользуется стеком для ускорения своей работы.
;

WIN_RESTORE:    ; копирование данных из памяти в текстовое окно
                ; восстановление окна
 LD A,(id_win)  ; идентификатор глобального окна (пока должен быть 0)
 LD H,ver_size  ; HL - размер локального окна вертикаль/горизонталь
 LD L,hor_size  ; размер в символах
 LD D,ver_place ; DE - положение локального окна
 LD E,hor_place ; положение по горизонтали в символах
 LD IX,bufer    ; адрес буфера данных для локального окна
 LD B,bufer_page; страница буфера данных окна (только SLOT3 или SLOT2)
		; адрес буфера указывается для окна #C000
                ; если адрес указан с #8000, номер страницы буфера
                ; не действителен.
 LD C,#B3       ; номер функции
 RST ToBIOS     ; NC -> нормальное завершение
                ; CF -> ошибка - неверный идентификатор окна
; при работе этой функции через RST #18 или RST 8, обязательна установка
; DI, так как функция пользуется стеком для ускорения работы.

; Данные для функций WIN_COPY_WIN и WIN_RESTORE_WIN имеют одинаковую
; структуру В данный момент эта структура похожа на структуру текстового
; экрана IBM, т.е. данные идут в формате  sym1,atr1,sym2,atr2,.. сплошным
; массивом. Сначала данные для первой строки, затем сразу для второй и т.д.

WIN_GET_SYM:    ; взять символ с экрана
 LD A,(id_win)  ; идентификатор окна (пока должен быть 0)
 LD DE,place    ; положение символа: D - вертикаль, E - горизонталь
 LD C,#B4       ; номер функции
 RST ToBIOS     ; NC -> нормальное завершение
                ; L - символ, H - атрибут, B - знакогенератор
                ; CF -> ошибка неверный идентификатор окна
;

WIN_PUT_SYM:    ; положить символ на экран
 LD A,(id_win)  ; идентификатор окна (пока должен быть 0)
 LD DE,place    ; положение символа: D - вертикаль, E - горизонталь
 LD B,sym_zg    ; знакогенератор
 LD L,symbol    ; символ
 LD H,atribute  ; атрибут символа
 LD C,#B5       ; номер функции
 RST ToBIOS     ; NC -> нормальное завершение
                ; CF -> ошибка неверный идентификатор окна
;

;
WIN_GET_ZG:     ; получить знакогенератор
 LD DE,zg_buff  ; указатель на 2Kb буфер для знакогенератора
 LD C,#B8        ; номер функции
 RST ToBIOS     ; NC -> завершение
;

;
WIN_SET_ZG:     ; установка знакогенератора
 LD A,sym_zg    ; системный номер знакогенератора
 LD DE,zg_form  ; указатель на 2Kb данных знакогенератора
                ; Данные знакогенератора должны располагаться в таком виде, в каком они
                ; выглядели бы как набор символов на спектрумовском экране при переносе 2Kb
                ; LDIR-om в адрес #4000
                ; * В будущем возможно изменение этого расположения на обычное
 LD C,#B6       ; номер функции
 RST ToBIOS     ; NC -> завершение
                ; CF -> ошибка (старая версия, нет функции)
;

WIN_MOVE:       ; перемещение окна (Внимание! использует как буфер страницу #FF)
 LD A,(id_win)  ; идентификатор глобального окна (пока должен быть 0)
 LD H,ver_size  ; HL - размер локального окна вертикаль/горизонталь
 LD L,hor_size  ; размер в символах
 LD D,ver_place ; DE - положение локального окна
 LD E,hor_place ; положение по горизонтали в символах
 LD IX,new_place; новое положение локального окна
 LD C,#B7       ; номер функции
 RST ToBIOS     ; NC -> нормальное завершение
                ; CF -> ошибка - неверный идентификатор окна
; при работе этой функции через RST #18 или RST 8, обязательна установка
; DI, так как функция пользуется стеком для ускорения работы.

; Даллее следуют функции печати для работы с _текущим_ глобальным окном.
; В данный момент текущим всегда является последнее открытое окно
; На графическом экране функция не работает
;

LP_PRINT_ALL:   ; печать символов с атрибутом
 LD A,symbol    ; символ
 LD E,atribute  ; атрибут
 LD B,num_sym   ; число выводимых символов
 LD C,#81       ; номер функции
 RST ToBIOS     ; на экран выводится строка из B одинаковых
                ; символов
                ; регистры HL,IX - сохраняются
;

LP_PRINT_SYM:   ; Вывод символов на экран с текущего
                ; знакоместа без атрибута
 LD A,symbol    ; символ
 LD B,num_sym   ; число выводимых символов
 LD C,#82       ; номер функции
 RST ToBIOS     ; на экран выводится строка из B одинаковых символов
                ; атрибут остается тот, который был на экране
                ; регистры HL,IX - сохраняются
;

LP_PRINT_ATR:   ; печать атрибутов
 LD E,atribute  ; атрибут
 LD B,num_sym   ; число выводимых символов
 LD C,#83       ; номер функции
 RST ToBIOS     ; на экран выводится строка из B одинаковых
                ; атрибутов. Символы не меняются.
                ; регистры HL,IX - сохраняются
;

LP_SET_PLACE:   ; Установка текущего знакоместа в окне
 LD E,hor_place ; номер символа по горизонтали
 LD D,ver_place ; номер символа по вертикали
                ; ** Превышение границ приводит не к ошибке, а к
                ; переустановке сначала, за вычетом полного
                ; размера окна
 LD C,#84       ; номер функции
 RST ToBIOS     ; позиция печати устанавливается в соответстии с
                ; регистром DE
		; портятся только альтернативные регистры и те,
		; что как параметры на входе

LP_PRINT_LINE:  ; Вывод строки символов на экран с текущего
                ; знакоместа
 LD HL,line_adr ; адрес строки. Должен быть между #4000 и #BFFF
 LD E,atribute  ; атрибут, с которым будет выведена строка
 LD B,num_sym   ; длина выводимой строки
 LD C,#85       ; номер функции
 RST ToBIOS     ; "исполнение желаний"
;

LP_PRINT_LINE2: ; Вывод строки символов на экран с текущего
                ; знакоместа без атрибутов
 LD HL,line_adr ; адрес строки. Должен быть между #4000 и #BFFF
 LD B,num_sym   ; длина выводимой строки
 LD C,#86       ; номер функции
 RST ToBIOS     ; строка будет выведена без изменения атрибутов в
                ; месте печати
;

LP_PRINT_LINE3: ; Вывод строки символов длиной B на экран с текущего
                ; знакоместа до разделителя D. После разделителя
                ; выводятся пробелы что бы вывести B символов.
 LD HL,line_adr ; адрес строки. Должен быть между #4000 и #BFFF
 LD E,atribute  ; атрибут, с которым будет выведена строка
 LD D,delimiter ; разделитель
 LD B,num_sym   ; длина выводимой строки
 LD C,#87       ; номер функции
 RST ToBIOS     ; символы из (HL) выводятся на экран, пока не
                ; встретится символ равный D, далее печатаются
                ; пробелы, как дополнение строки до B символов
;

LP_PRINT_LINE4: ; Вывод строки символов длиной B на экран с текущего
                ; знакоместа до разделителя D. После разделителя
                ; выводятся пробелы что бы вывести B символов.
		; Без атрибутов.
 LD HL,line_adr ; адрес строки. Должен быть между #4000 и #BFFF
 LD D,delimiter ; разделитель
 LD B,num_sym   ; длина выводимой строки
 LD C,#88       ; номер функции
 RST ToBIOS     ; символы из (HL) выводятся на экран, пока не
                ; встретится символ равный D, далее печатаются
                ; пробелы, как дополнение строки до B символов
                ; атрибуты не изменяются
;

LP_CLS_WIN:     ; очистка экрана
 LD DE,place    ; положение локального окна (глобальное = текущее)
 LD H,ver_size  ; HL - размер локального окна вертикаль/горизонталь
 LD L,hor_size  ;      размер в символах
 LD B,atribute  ; атрибут очистки
 LD C,#89       ; номер фунции
 RST ToBIOS     ; выполнение. Произворится выводом пробелов с
                ; заданным атрибутом
;

LP_SCROLL_UD:   ; Скроллинг части глобального окна вверх/вниз
 LD B,scrollType; тип скроллинга 1 - вверх/ 2 - вниз
 LD D,beg_line  ; начальная строка скроллинга
 LD E,num_lines ; число скроллируемых строк
 LD C,#8A       ; номер функции
 RST ToBIOS     ; выполнение. Скроллируются полные строки
                ; глобального окна
;

LP_PRINT_LINE5: ; Вывод строки символов на экран с текущего
                ; знакоместа до разделителя после разделителя
                ; вывод останавливается
 LD HL,line_adr ; адрес строки. Должен быть между #4000 и #BFFF
 LD D,stop_symb ; символ конца строки
 LD E,atribute  ; атрибут, с которым будет выведена строка
 LD B,num_sym   ; максимальная длина выводимой строки
 LD C,#8B       ; номер функции
 RST ToBIOS     ; символы из (HL) выводятся на экран, пока не
                ; встретится символ равный D или количество
                ; символов не превысило B. Далее происходит
                ; возврат
;

LP_PRINT_LINE6: ; Вывод строки символов на экран с текущего
                ; знакоместа до разделителя после разделителя
                ; вывод останавливается, без атрибутов
 LD HL,line_adr ; адрес строки. Должен быть между #4000 и #BFFF
 LD D,stop_symb ; символ конца строки
 LD B,num_sym   ; максимальная длина выводимой строки
 LD C,#8C       ; номер функции
 RST ToBIOS     ; символы из (HL) выводятся на экран, пока не
                ; встретится символ равный D или количество
                ; символов не превысило B. Далее происходит
                ; возврат. Атрибуты не выводятся
                ;
                ; HL -> адрес следующий после конца строки
;

LP_CLS_WIN2:    ; очистка экрана, указанием символа заполнения
 LD DE,place    ; положение локального окна (глобальное = текущее)
 LD H,ver_size  ; HL - размер локального окна вертикаль/горизонталь
 LD L,hor_size  ;      размер в символах
 LD A,symbol    ; символ очистки
 LD B,atribute  ; атрибут очистки
 LD C,#8D       ; номер фунции
 RST ToBIOS     ; Выполнение. Произворится выводом пробелов с
                ; заданным атрибутом и символом
;

LP_GET_PLACE:   ; получить текущее положение вывода на экран
                ; в глобальном окне
 LD C,#8E       ; номер функции
 RST ToBIOS     ; в регистр DE будут положены координаты,
                ; в которых будет напечатан следующий символ
                ; D - вертикаль, E - горизонталь
;

LP_PR_LINE_DIR	;!TODO недоделана. Печать "в консоль" строки до
		; разделителя с автоскроллом и с учётом управляющих
		; символов: BELL, Backspace, TAB, CR, LF, FF, VT.
 LD DE,place	; положение символа в окне
 LD HL,text	; строка для печати. должна находиться в банках 1..2
 LD B,delimiter ; разделитель 
 LD C,#E0       ; номер фунции
 RST ToBIOS     ; Выполнение.
;..............................................................................
;       Графические функции
;       координаты считаются от верхнего левого угла экрана
;..............................................................................


PIC_POINT:      ; установить точку
 LD DE,Y_coord  ; координата по вертикали
 LD HL,X_coord  ; координата по горизонтали
 LD A,(id_win)  ; идентификатор граф. окна (пока должен быть 0)
 LD B,color     ; цвет точки
 LD C,#A1       ; номер функции
 RST ToBIOS     ; поставить точку

; В действительности ставить точки на экране с помощью функции биоса,
; слишком медленно. Для этого лучше пользоваться прямым выводом данных
; на графический экран. Устройство экрана и способы прямого вывода
; графических данных описаны в файле архитектуры Спринтера.
;


PIC_SET_PAL:    ; установка палитры
 LD HL,pal_data ; данные палитры:
                ; список цветов по четыре байта B,G,R,Y
 LD E,beg_color ; начальный цвет
 LD D,num_colors; количество устанавливаемых цветов
 LD B,pal_mask  ; маска при установке палитры. Для нормального
                ; режима должнa быть FF
 LD A,page_pal  ; номер палитры (0..15, 8..15 резервные)
 LD C,#A4       ; номер функции
 RST ToBIOS     ; установка палитры
; данные палитры должны представлять собой список приблизительно такого вида:
 DB blue1,green1,red1,0
 DB blue2,green2,red2,0
;.....................
 DB blueN,greenN,redN,0

; N = num_colors. Значение num_colors равное 0 соответствует 256-ти цветам
; при записи в видео-ОЗУ все данные предварительно проходят функцию AND со
; значением pal_mask

; Страницы палитры 0..3 соответствуют графическим режимам. Для вывода в
; соответствующей палитре нужно задать соответствующее значение bit7..6 в
; байте режима знакоместа

; Страницы 4..7 соответствуют текстовому режиму и режиму "Спектрум"
; В странице 4 задается цвет paper для каждого атрибута. В странице 5
; задается цвет ink для каждого атрибута.
; В странице 6 задается цвет paper, которым он будет моргать в режиме flash
; В странице 7 задается цвет ink, которым он будет моргать в режиме flash
; Таким образом, для каждого из 256-ти атрибутов задается четыре цвета
; если цвета 4,5 совпадают с цветами 6,7 то режим flash оказывается
; отключенным. Для его включения в спектрумовском режиме надо поменять
; местами цвета 6 и 7. Если надо включить flash в режим IBM-CGA, следует
; установить цвета 6 и 7 одинаковыми и равными цвету 4
; по сути режим flash всегда включен и на экране постоянно меняются цвета
; paper с 4-го на 6-й, а цвета ink с 5 на 7-й. Если эти пары цветов для
; атрибута знакоместа устанавливаются одинаковыми, то flash в этом месте
; не виден.
; Используя подобное задание цветов текстового режима можно легко добиться
; совместимости по цветам как со Спектрумом, так и с IBM
;

;[x] новое?
PIC_GET_PAL:    ; получение установленной палитры
 LD HL,pal_data ; буфер для палитры:
                ; список цветов по четыре байта B,G,R,Y
 LD E,beg_color ; начальный цвет
 LD D,num_colors; количество цветов
 LD A,page_pal  ; #80 + номер палитры (0..15, 8..15 резервные)
 LD C,#A4       ; номер функции (такой же как и для PIC_SET_PAL)
 RST ToBIOS     ; получение палитры
;

SET_PAL_INIT:   ; установка внутренней палитры.
 LD A,PAL_PAGE  ; страница палитры (для графической)
 LD E,PAL_N     ; номер палитры (для графической)
 LD B,type	; 3 - установка CGA палитры
                ; 2 - установка спектрумовской палитры
                ; 1 - установка графической палитры
 LD C,#A6       ; номер функции
 RST ToBIOS     ; установка палитры
;==============================================================================

; Функции работы с винчестером разделяются на две группы:
;  1.	 функции с номeрами #4x работают в более простом режиме и
; 	используются в TR-DOS. Эти функции находят только один
; 	винчестер и работают только с его первым разделом. Если есть
; 	master, то функции используют его, если master-а нет, то
; 	определяется slave, если нет ни того ни другого, выдается ошибка.
; 	 Функцию подготовки #43 не требуется исполнять перед
; 	операциями #44, #45 и #46!
; 	 При исполнении функции 43h производится вся подготовка к
; 	операциям чтения/записи вычисление цилиндров/головок/секторов и
; 	занесение их в регистры винчестера далее программа может сама
; 	только подать команду читать/писать и самостоятельно производить
; 	считывание/запись данных в винчестер. Команда удобна для работы
; 	программ в реальном времени, когда необходимо кроме
; 	чтения/записи данных производить какие либо иные действия.
; 	 Страница буфера для функций #44..#46 имеет значение только при
; 	попадании адресов чтения/записи в диапазон #C000..#FFFF. Кроме
; 	того, при попадании межсекторного промежутка на адрес 0 при
; 	наличии несчитанных/незаписанных секторов, производится
; 	автоматическое переключение страницы ОЗУ по RAM Allocation Table
; 	и продолжение чтения/записи с адреса #C000, что позволяет
; 	непрерывно писать/читать до 128kb прямо в выделенный блок ОЗУ.

;  2.	 Функции с номерами #5x более сложны, используются в Estex и
; 	работают с обоими винчестерами, со всеми разделами, а так же с
; 	дисководами, RAM-Disk-ами и CD-ROM-ами.
; 	 В этих функциях в регистре A обычно задается номер и тип
; 	устройства:
; 		бит 0..3 - номер устройства
; 		бит 4..7 - тип устройства:
; 		           0 - дисковод
; 		           6 - ram-disk
; 		           8 - HDD
; 		           C - CD-ROM
; 		остальные номера резервные
; 	А так же задаются страшая часть номера сектора в регисте HL,
; 	младшая часть номера сектора в регистре IX. Обратить внимание,
; 	на другой порядок расположения абсолютного номера сектора в 
; 	регистрах HL и IX по сравнению с фунциями #4x!

;==============================================================================
;               6. Работа с винчестером и дисками MS-DOS. Функции 4x
;==============================================================================

; [x] 27/01/2024 адаптирована для корректной работы с FN_HDD_PART
HDD_INIT:       ; инициализация винчестера. Портит значение PORT_Y
 LD C,#40       ; номер функции
 RST ToBIOS     ; NC -> нормальное завершение
                ; CF -> винчестер не найден
;

; !FIXIT пока работает только с одним каналом (по-старому)
HDD_RECAL:      ; рекалибровка винчестера
 LD C,#41       ; номер функции
; * Функция зарезервирована для дальнейшего использования ; !TODO
;
; [x] 28/01/2024 работает со всеми каналами IDE и Master/Slave
HDD_TEST_IDE:   ; Тест наличия интерфейса IDE
 LD C,#42       ; номер функции
 RST ToBIOS     ; NC -> нормальние завершение
                ;   в регистре B информация о наличии устройств
                ;   bit0=1 - есть устройство "Primary master"
                ;   bit1=1 - есть устройство "Primary slave"
                ;   bit2=1 - есть устройство "Secondary slave"
                ;   bit3=1 - есть устройство "Secondary slave"
                ; CF -> ошибка, аппаратная неисправность
;

HDD_PREPARE:    ; подготовка винчестера к операции чтения/записи
 LD A,bufer_page; страница буфера, если адрес в окне #C000
 LD IX,sec_high ; абсолютный номер сектора старшая часть
 LD DE,sec_low  ; абсолютный номер сектора младшая часть
 LD HL,bufer_adr; адрес буфера данных
 LD B,sec_num   ; число секторов
 LD C,#43       ; номер функции
 RST ToBIOS     ; При исполнении производится вся подготовка к
                ; операциям чтения/записи вычисление
                ; цилиндров/головок/секторов и занесение их в регистры винчестера
                ; далее программа может сама только подать команду читать/писать и
                ; самостоятельно производить считывание/запись данных в винчестер.
                ; Команда удобна для работы программ в реальном времени, когда необходимо
                ; кроме чтения/записи данных производить какие либо иные действия.
                ; На выходе в окне 3 стоит страница из A если H >= #С0.
                ; Остаётся только начать читать с портов HDD
;

; [x] 27/01/2024 теперь работает с любым разделом HDD
HDD_READ_BPB:   ; читать BPB. Портит значение PORT_Y
 LD C,#44       ; номер функции
 LD HL,bufer_adr; адрес буфера для BPB
 LD A,bufer_page; страница буфера, если адрес в окне #C000
 RST ToBIOS     ; NC -> нормальное завершение
                ; CF -> ошибка
;

HDD_READ:       ; читать сектора с винчестера. Портит значение PORT_Y
 LD A,bufer_page; страница буфера, если адрес в окне #C000
 		; в A может быть BlockID, тогда будет читаться далее
		; в следующие страницы с адреса #C000
 LD IX,sec_high ; абсолютный номер сектора старшая часть
 LD DE,sec_low  ; абсолютный номер сектора младшая часть
 LD HL,bufer_adr; адрес буфера данных
 LD B,sec_num   ; число читаемых секторов
 LD C,#45       ; номер команды
 RST ToBIOS     ; NC -> нормальное завершение
                ; CF -> ошибка

; ** При попадании межсекторного промежутка на адрес 0
; производится автоматическое переключение страницы ОЗУ по
; RAM Allocation Table.
;

HDD_WRITE:      ; писать сектора на винчестер
 LD A,bufer_page; страница буфера, если адрес в окне #C000
 LD HL,bufer_adr; адрес буфера данных
 LD B,sec_num   ; число записываемых секторов
 LD DE,sec_low  ; абсолютный номер сектора младшая часть
 LD IX,sec_high ; абсолютный номер сектора старшая часть
 LD C,#46       ; номер команды
 RST ToBIOS     ; NC -> нормальное завершение
                ; CF -> ошибка

; ** При попадании межсекторного промежутка на адрес 0
; производится автоматическое переключение страницы ОЗУ по RAM
; Allocation Table.
;

; !FIXIT использовать в HDD_TO_DRV
; [x] 07/01/2024
HDD_PART:	; настройка канала IDE, master/slave, раздела HDD. Портит значение PORT_Y
 LD A,hdd_part	; bit0 - master/slave, bit1: Primary/Secondary, bit2..3: использующийся раздел в MBR
 LD C,#47
 RST ToBIOS 
; 

HDD_READ_NEXT:	; Читать следующий сектор (только LBA!). Портит значение PORT_Y
 LD A,bufer_page; страница буфера, если адрес в окне #C000 
 LD B,sec_num   ; число читаемых секторов
 LD HL,bufer_adr; адрес буфера данных
 LD DE,add_par	; прибавляется к номеру предыдущего прочитанного сектора
 LD C,#48       ; номер команды
 RST ToBIOS     ; NC -> нормальное завершение
                ; CF -> ошибка
;
;==============================================================================
;               7. Работа с винчестером и дисками MS-DOS. Функции 5x
;==============================================================================

; !TODO
 LD C,#50        ; зарезервирована
;

DRV_RESET:      ; Сброс контроллера и настройка на диск
 LD A,drv_type  ; бит 0..3 - номер устройства
                ; бит 4..7 - тип устройства
                ;     0 - дисковод
                ;     6 - ram-disk
                ;     8 - HDD
                ;     C - CD-ROM
                ; остальные номера резервные
 LD C,#51       ;
 RST ToBIOS     ; NC - нормальное завершение
                ; CF - нет диска или нет устройства
;

DRV_READ_LONG:  ; чтение с устройства
 LD A,drv_type  ; бит 0..3 - номер устройства
                ; бит 4..7 - тип устройства
                ;     0 - дисковод
                ;     6 - ram-disk
                ;     8 - HDD
                ;     C - CD-ROM
 EX AF,AF'      ;
  LD A,Mem_BLK  ; страница, куда читать если буфер в SLOT3
 EX AF,AF'      ;
 LD HL,sec_h    ; старшая часть номера сектора
 LD IX,sec_l    ; младшая часть номера сектора
 LD B,n_sec     ; количество секторов
 LD DE,bufer_adr; адрес буфер для чтения
 LD C,#52       ;
 RST ToBIOS     ; NC - нормальное завершение
                ; CF - ошибка чтения или нет устройства
;

; !TODO расписать
DRV_WRITE_LONG:
 LD C,#53        ; Long write
;

DRV_VERIFY:     ; проверка секторов
 LD A,drv_type  ; бит 0..3 - номер устройства
                ; бит 4..7 - тип устройства
                ;     0 - дисковод
                ;     6 - ram-disk      ; !FIXIT
                ;     8 - HDD
                ;     C - CD-ROM
 LD HL,sec_h    ; страшая часть номера сектора
 LD IX,sec_l    ; младшая часть номера сектора
 LD B,n_sec     ; количество секторов
 LD C,#54       ;
 RST ToBIOS     ; NC - нормальное завершение
                ; CF - проверка с ошибкой или нет устройства
;

DRV_READ:       ; чтение с устройства
 LD A,drv_type  ; бит 0..3 - номер устройства
                ; бит 4..7 - тип устройства
                ;     0 - дисковод
                ;     6 - ram-disk
                ;     8 - HDD
                ;     C - CD-ROM
 LD HL,sec_h    ; старшая часть номера сектора
 LD IX,sec_l    ; младшая часть номера сектора
 LD B,n_sec     ; количество секторов
 LD DE,bufer_adr; адрес буфер для чтения
 LD C,#55       ;
 RST ToBIOS     ; NC - нормальное завершение
                ; CF - ошибка чтения или нет устройства
;

DRV_WRITE:      ; запись на устройства
 LD A,drv_type  ; бит 0..3 - номер устройства
                ; бит 4..7 - тип устройства
                ;     0 - дисковод
                ;     6 - ram-disk
                ;     8 - HDD
                ;     C - CD-ROM
 LD HL,sec_h    ; страшая часть номера сектора
 LD IX,sec_l    ; младшая часть номера сектора
 LD B,n_sec     ; количество секторов
 LD DE,bufer_adr; адрес буфер для записи
 LD C,#56       ;
 RST ToBIOS     ; NC - нормальное завершение
                ; CF - ошибка записи или нет устройства
;

DRV_DETECT:     ; определение параметров устройства
 LD A,drv_type  ; бит 0..3 - номер устройства
                ; бит 4..7 - тип устройства
                ;     0 - дисковод
                ;     6 - ram-disk
                ;     8 - HDD
                ;     C - CD-ROM
 LD C,#57       ;
 RST ToBIOS     ; NC - нормальное завершение
                ; A  - для FDD bit7: 720/1.44
		;      для HDD и CD: drive type
                ; CF - нет устройства или нет носителя
;

DRV_GET_PAR:    ; получить параметры носителя
 LD A,drv_type  ; бит 0..3 - номер устройства
                ; бит 4..7 - тип устройства
                ;     0 - дисковод
                ;     6 - ram-disk
                ;     8 - HDD
                ;     C - CD-ROM
 LD C,#58       ;
 RST ToBIOS     ; NC - нормальное завершение
                ;     L  - число секторов (на целиндр)
                ;     H  - число головок
                ;     DE - количество цилиндров
                ;     IX - размер сектора в байтах
                ;     B  - доп. параметры:
                ;           FDD: бит7 - тип 720/1.44
                ;           HDD: бит0 - канал IDE 0/1
                ;                бит6 - CHS/LBA
                ;           RMD: ramdrive block id	; [x]
		;
                ; если в HL,DE все FF - устройства нет
                ; CF - нет устройства
;

DRV_SET_PAR:    ; установить параметры носителя
 LD A,drv_type  ; бит 0..3 - номер устройства
                ; бит 4..7 - тип устройства
                ;     0 - дисковод
                ;     6 - ram-disk
                ;     8 - HDD
                ;     C - CD-ROM
 LD L,n_secs    ;    L  - число секторов (на целиндр)
 LD H,n_heads   ;    H  - число головок
 LD DE,n_cyls   ;    DE - количество цилиндров
 LD IX,sec_size ;    IX - размер сектора в байтах
 LD B,ext_par   ;    B  - доп. параметры
                ;         для дискет бит7 - тип 720/1.44
 LD C,#59       ;
 RST ToBIOS     ; NC - нормальное завершение
;

DRV_VERSION:    ; получить версию драйвера дисковой подсистемы
 LD C,#5A       ;
 RST ToBIOS     ; CF - старая версия BIOS
                ; NC - нормальное завершение
                ;      DE - номер версии. 
;

; !TODO
 LD C,#5B	; зарезервирована
;

; !TODO
 LD C,#5C	; зарезервирована
;

; !TODO
 LD C,#5D	; зарезервирована
;

DRV_EXTENDED:	; расширенный набор подфункций, может отличаться для разных устройств
 LD B,sub_func	; номер подфункции
 LD C,#5E	; зарезервирована
 RST ToBIOS     ; NC - нормальное завершение
; Подфункции:
; 		Для CD-ROM:
;			0 - Eject
;			1 - Close tray
;

DRV_LIST:	; !TODO добавить описание и поддержку RAM DRIVE в этой функции
 LD C,#5F       ;
 RST ToBIOS     ; 
;
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░;
;██████████████████████████████████████████████████████████████████████████████████████████████████████████████;