c71e249a4e
First substantive commit: the entire Sprinter C compiler tree on top of
the bare README+gitignore initial commit.
What's in here:
bin/sprinter-cc — driver script invoking SDCC + linker + mkexe
libc/ — Sprinter-specific libc layer over ESTEX/BIOS
(conio, gfx, io, mem, stdio + headers)
runtime/ — crt0 variants (default/small/banked/minimal)
+ heap + bank trampolines
toolchain/ — mkexe (SprintEXE packer, C + tests)
examples/ — 30 demo programs (gfx, file I/O, env, time, …)
lib/Makefile — builds the libc archive (sprinter.lib)
docs/ — converted Sprinter manuals + asm reference samples
third_party/ — solid-c reference compiler dump + sdcc setup script
release_docs/ — packaging / release notes
gitignore overhaul:
• Drop dangerous blanket patterns: *.asm (would hide docs/samples/*.asm)
and *.exe (case-insensitive match was hiding third_party/solid-c/*.EXE
on macOS APFS). Replaced with examples/*/*.{asm,exe,…} and lib/*.lib.
• Restore tracking of toolchain/mkexe/tests/{one,big}.bin — those are
INPUT fixtures, not build outputs.
• Collapse the duplicated SDCC/C/Sdcc sections into one section per
concern (build outputs / vendored / OS-junk).
• Add .sprinter-cc-*/, build/ (catches lib/build/ too), .claude/.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1387 lines
83 KiB
Plaintext
Executable File
1387 lines
83 KiB
Plaintext
Executable File
; 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 ;
|
||
;
|
||
;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░;
|
||
;██████████████████████████████████████████████████████████████████████████████████████████████████████████████; |