# Программирование Спринтера

## Оглавление:

- Экран и палитра
- Шрифты
- Память
- Файлы
- Звук
- ISA-8 слоты
- Summary
- More information
- Акселератор компьютера Sprinter
- Прерывания
- IDE контроллер
- FDD контроллер
- Клавиатура
- Коды ошибок DSS

###  Экран и палитра

Функции для работы с экраном:

Сейчас DOS поддерживает четыре режима экрана.

Два текстовых:

    40x32 символов c 16 цветами (режим 02h);
    80x32 символов c 16 цветами (режим 03h);

и два графических:

    320x256 точек с 256 цветами (режим 81h);
    640x256 точек с 16 цветами (режим 82h);

Основным режимом является текстовый режим 80x32 (03h), если
ваша программа работает в другом режиме, то вам следует перед 
переключением режима получить номер текущего режима функцией 
51h GETVMOD и сохранить его, а перед завершением программы 
восстановить его.

Например:

```asm
    LD C,51h        ;получить режим экрана
    RST 10h
    LD C,A          ;поместить номер режима экрана в регистр C
    PUSH BC         ;и сохранить на стеке (B - страница, C - режим)
    ...
    ... ;ваша программа
    ...
    POP BC          ;взять со стека режим экрана
    LD A,C          ;поместить номер режима экрана в регистр A
    LD C,50h        ;установить режим экрана
    RST 10h
    LD C,41h        ;завершить программу.
    RST 10h
```

DSS имеет функции вывода на текстовый экран символов и символьных
строк. Для графических режимов требуются собственные процедуры 
вывода на экран. Например, при завершении программы вы можете 
выдать строку на текстовый экран:

```asm
    LD HL,STRING    ;указатель на строку символов
    LD C,5Ch        ;вывод строки символов
    RST 10h

STRING  DB "Thank you for using my program..."    ;текстовая строка
        DB 13,10        ;символы возврата каретки и перевода строки
        DB 0            ;символ конца строки
```

Для вывода на графический экран, вам необходимо подключить 
видео память в одно из трех окон памяти 04000h-07FFFh, 
08000h-0BFFFh, 0C000h-0FFFFh. Это осуществляется выводом 
значения 50h в соответствующий порт 0A2h, 0C2h или 0E2h в
зависимости от окна памяти. При подключении обратите 
внимание на то, чтобы стек вашей программы не попадал в 
это адресное пространство.

Например, если вам нужно поставить точку на экране, то 
подпрограмма для режима 81h будет выглядеть так:

```asm
; HL - горизонтальная координата
; DE - вертикальная координата

    IN A,(0E2h)         ;считать из порта номер страницы подключенной в
                        ;третье окно памяти
    LD C,A              ;запомнить в регистре C
    LD A,50h            ;страница видео памяти
    OUT (0E2h),A        ;подключение видео памяти
    LD A,E              ;поместить вертикальную координату в регистр A.
    OUT (89h),A         ;выдать в порт
    LD DE,0C000h        ;адрес начала третьего окна памяти
    ADD HL,DE           ;получить адрес точки (адрес начала окна +
                        ;горизонтальная координата)
    LD A,255            ;цвет выводимой точки (от 0 до 255)
    LD (HL),A           ;вывод точки на экран
    LD A,C              ;вспомнить номер страницы памяти
    OUT (0E2h)          ;подключить страницу памяти вместо страницы видео
                        ;памяти
```

Перед выводом точек следует установить необходимые цвета в
палитре. Различные режимы вывода на экран задаются номером 
видео страницы от 50h до 5Fh. Подробнее о режимах вывода вы 
можете прочитать в описании архитектуры компьютера.

**50h (80) SETVMOD (Выбор режима экрана)**

    входные данные:
      A - режим экрана
        02h - текстовый 40x32x16 цветов
        03h - текстовый 80x32x16 цветов
        81h - графический 320x256x256 цветов
        82h - графический 640x256x16 цветов
      B - страница экрана 0/1
      C - 50h
    выходные данные:
      A - код ошибки, если CF=1

Функция устанавливает режим экрана. Седьмой бит режима экрана 
установлен для графических режимов и сброшен для текстовых. 
Существуют два текстовых режима и два графических.

**51h (81) GETVMOD (Получить текущий режим экрана)**

    входные данные:
      C - 51h
    выходные данные:
      A - текущий режим экрана
      B - страница экрана 0/1

Функция возвращает текущий режим экрана и номер страницы экрана.


Q: 
Здравствуйте. А как с палитрами??? Как загрузить произвольную
палитру (отдельный цвет). Желательно с исходником.
Почему системная палитра выглядит по разному в эмуляторе и реальном
Спринтере.

A:
Пример из исходников Антона Енина (

```asm
;[]=======================================================================[]
; palette from Flex Navigator
CustomPalette:
            db 0x00, 0x00, 0x00, 0x00 ; Black 00
            db 0x00, 0x00, 0xFF, 0x00 ; B.Red 01
            db 0x00, 0x80, 0x00, 0x00 ; Green 02
            db 0x00, 0xFF, 0xFF, 0x00 ; B.Yellow 03
            db 0x80, 0x00, 0x00, 0x00 ; Blue 04
            db 0xFF, 0xFF, 0x00, 0x00 ; Invert bg 05
            db 0x80, 0x00, 0x00, 0x00 ; Invert fg 06
            db 0x80, 0x80, 0x80, 0x00 ; BlackGray 07
            db 0xC0, 0xC0, 0xC0, 0x00 ; HighGray 08
            db 0x80, 0x00, 0x00, 0x00 ; Panel 09
            db 0xFF, 0xFF, 0x00, 0x00 ; Files 0A
            db 0x00, 0xFF, 0xFF, 0x00 ; Select Files 0B
            db 0x00, 0xFF, 0xFF, 0x00 ; InvSel Files 0C
            db 0xC0, 0xC0, 0xC0, 0x00 ; Reserved 0D
            db 0xFF, 0xFF, 0xFF, 0x00 ; White 0E
            db 0xFF, 0xFF, 0xFF, 0x00 ; White 0F

;[]=======================================================================[]
;[]=======================================================================[]
; set requist video mode 640x256x16
SetVideoMode:

            ld c, 0x51 ; save previos vmode
            rst 0x10
            ld (vmode + 1), a
            ld a, b
            ld (vscrn + 1), a
            sub a
            call CrearVideoRam
            ld bc, 0x0050 ; set 640x256x16
            ld a, 0x82
            rst 0x10
            ld hl, CustomPalette
            ld de, 0x1000
            ld bc, 0xFFA4
            sub a
            rst 0x08 ; load palette
            ret

;[]=======================================================================[]
```

```asm
;Установить 5-й цвет \"средне-зеленым\"
            LD HL,COLOUR
            LD DE,#0105
            LD BC,#FFA4
            XOR A
            RST #08

;                B   G   R
COLOUR      DB #00,#80,#00,#00
            
;Изменить все 256 цветов в палитре
            LD HL,COLOURS
            LD DE,#0000
            LD BC,#FFA4
            XOR A
            RST #08

;Параметры цвета
;                B   G   R
COLOUR      DB #00,#80,#00,#00

;Палитра
COLOURS     DB #00,#00,#00,#00 ;Colour 0
            DB #00,#00,#80,#00 ;Colour 1
            DB #00,#80,#00,#00 ;Colour 2
            DB #00,#80,#80,#00 ;Colour 3
            ...
            DB #FF,#FF,#FF,#00 ;Colour 255
```

Как я понял, сейчас есть проблема с выводом на экран.
Попробую расписать схему видео-вывода на словах.

Режим адресации. Задается номером страницы.
Если номер 5Xh - адресация графическая.
Если номер не 5Xh - адресация спектрумовская, и она включена все время,
даже если в соседней странице включился номер 5Xh.

Спектрумовская адресация, это доступ к видеопамяти на запись в адресах
4000h..5FFFh или в 4000h - 7FFFh, в зависимости от состояния порта
PORT_Y (89h).

    Бит 6 = 1 - отключает вывод в спектрумовское окно памяти.
    Бит 7 = 1 - расширяет спектрумовское окно с 8Kb до 16Kb

    Бит 4..0 - пределяет 8kb банк спектрумовского режима.

Эти банки располагаются "вертикально", т.е. такой банк соответствует
32-м последовательным точкам на графической линии и 256-ти линиям.

Сначала я чаще всего использовал окно 4000h..7FFFh для работы с
графикой, поэтому получилось так, что графическая адресация перекрывала
спектрумовскую при включении в порт A2h значения 5Xh, а выше 8000h
использовалось программой, потом, когда стали использовать для вывода на
экран страницу 0C000h, получилось так, что в странице 4000h оставалась
открыта видеопамять со спектрумовской адресацией, а порт 89h
используется и там и там, но с разным назначением.

Т.е. после открытия страницы 0C000h для графики остается открытой и
спектрумовский способ адресации видеопамяти в странице 4000h..7FFFh.
P.S. Надеюсь, что не запутал все окончательно...

###  Шрифты

#### *Несколько наборов шрифтов одновременно*

Вот ответ, полученный от Ivan Mak.

=== Cut ===

Через Bios:

    IX - 32-хбайтовый описатель окна

(искать в описании, здесь только только самое важное)

    (IX+4) - режим знакоместа
        bit4=1 - text_mode
        bit5=0 - 16, bit5=1 - 8 точек в знакоместе (80/40 символов)
        bit7..6,3..0 - номер знакогенератора

исключение: bit7..6=B"11" - бордер

...

Он же (IX+4) - номер используемого знакогенератора в 
этом окне, он же регистр B в функциях B4,B5
Функция B0 открытие окна использует описатель, в котором указан
знакогенератор, открытый для всех символов данного окна. Он может
быть перебит прямой записью в видео-память или фунцией B5, 
которая пишет символ со знакогенератором. При использовании 
функции B0 четвертый бит регистра E определяет, какая страница 
режима будет использоваться. Для работы с двумя страницами надо 
открывать окно два раза со значениями 0 и 1 в 4-м бите рег.E

---

**0B4h (180) WIN_GET_SYM Взять символ с экрана**

    Значение регистров на входе:
      C=0B4h
      A - идентификатор окна (д.б. 0)
      DE - положение символа в окне:
        D - вертикаль, E - горизонталь
    Значение регистров на выходе:
      NC - нормальное завершение
      L - символ, 
      H - атрибут,
      B - знакогенератор
      CF - ошибка неверный идентификатор окна

**0B5h (181) WIN_PUT_SYM Положить символ на экран**

    Значение регистров на входе:
      C=0B5h
      A - идентификатор окна
      DE - положение символа в окне:
        D - вертикаль, E - горизонталь
      L - символ, 
      H - атрибут символа
      B - знакогенератор
    Значение регистров на выходе:
      NC - нормальное завершение
      CF - ошибка неверный идентификатор окна

**0B6h (182) WIN_SET_ZG Установка знакогенератора**

    Значение регистров на входе:
    C=0B6h
      A - системный номер знакогенератора
      DE - указатель на 2Kb данных знакогенератора
    Значение регистров на выходе:
      NC - нормальное завершение
      CF - ошибка (старая версия, нет функции)

**0B8h (184) WIN_GET_ZG Получение знакогенератора**

    Значение регистров на входе:
      C=0B8h
      DE - адрес, куда будет загружено 2kb знакогенератора
    Значение регистров на выходе:
      NC - нормальное завершение
      CF - ошибка (старая версия, нет функции)

Функция копирует имеющийся знакогенератор из ПЗУ

---

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

    Bytes:
    byte0 - знакогенератор/режим то же, что в (IX+4)
    byte1 - символ
    byte2 - атрибут
    byte3 - reserved (заполнить нулями)

    Port_Y - номер линии засылаемый в порт 89h
        линия 1+S S=0..79 - номер символа в строке для экрана 0
        линия 128+S S=0..79 - номер символа в строке для экрана 1
        (S=0 - выводит символ слева)

    Adress: в линии 768+N*4 - N - номер строки экрана 0..31.
    Адрес одинаков для обоих экранов.
    (N=0 выводит символ сверху)

    В режиме 40 символов, номера строк через один: 1,3,5\...79

    Экраны переключаются нулевым битом порта 0C9h

---

Текстовый экран устроен на удивление просто: в области описания 
экрана в текстовом режиме на один символ отводится 4 байта (номер
знакогенератора, код символа, атрибут и один неиспользуемый байт),
причем надо обратить внимание на то, что в этом режиме экран "повернут
на бок". Что-бы вывести символ на экран, надо в Port_Y (0x89) записать
128+номер символа в строке (от 0 до 79), затем к адресу начала экранной
страницы прибавить 768 (для первого экрана), после чего мы получим адрес
байта, в котором хранится номер знакогенератора для вывода символа
(поменяйте его, если это необходимо), увеличиваем адрес на один и туда
записываем уже код самого символа, а в следующий байт - атрибут этого
символа. Что-бы перейти на следующую строку текстового экрана, надо
прибавить к адресу начала экранной страницы число 4*номер строки.
Используя акселератор (команду копирования вертикальной линии) можно
очень быстро выводить текст строки на экран.

Остается только добавить что прямой доступ к области описания экрана не
рекомендован разработчиками, т.к. есть веротяность потери совместимости
со следующими моделями, где символы могут описываться подругому. Но если
вам необходима большая скорость вывода на экран в текстовом режиме и вы
готовы после выпуска программы вносить в неё изменения для обеспечения
совместимости со следующими моделями, либо выложить исходники программы,
что-бы желающие могли их исправить при необходимости, то, мне кажется
можно использовать прямой доступ.

###  Память

В конфигурации спринтер по #0000...#3FFF, при работе ДСС находится 
сама ДСС с её Резетами, то есть чтобы использывать когда сюда 
подставленна страница пользователя резеты не доступны!.

Это так в нижних 16K находится DSS / BIOS в остальных 48К
приложение, но с определенными особенностями. Стек не должен быть 
выше #BFFF при вызове DSS и ниже #8000 при вызове некоторых 
функций BIOS.

В следующих версиях DSS планируется снятие ряда ограничений на стек
и расположения данных при вызове ее функций.

Q: Теперь адресса #4000..#7FFF, #8000..#BFFF, #C000..#FFFF, когда ДСС
передаёт управление эти программам, какие банки там нахадятся по
умолчанию?

A: В зависимости от адреса загрузки и размера приложения DSS выделяет
необходимое число страниц памяти. Так при размере меньше 16К будет
выделена одна страница, при размере больше 16К - две, и т.д. В окна с
"неиспользуемым" адресном пространством будет подключатся
специальная страница #FF. Если приложению требуется памяти больше чем
зарезервировано в exe-файле, оно должно выделить себе дополнительный
блок памяти самостоятельно.


Q: Теперь память можно челкать по портам #7FFD,1FFD или нет?
И если да, то как типа in #&7FFD,(номер страницы).

Напрямую память можно счелкать через 4 порта памяти:

    #82 - #0000-#3FFFF
    #A2 - #4000-#7FFFF
    #C2 - #8000-#BFFFF
    #E2 - #C000-#FFFFF

Записывая физический номер страницы в порт. Список номеров 
физических страниц для выделенного блока памяти можно получить 
через BIOS.

Q: Также хотеловсь бы увидет пример по использывани ф-ии 
38х Setwin!

A: SETWIN работает с логичискими страницами.

**38h (56) SETWIN (Подключение страницы памяти)**

    входные данные:
      A - идентификатор блока памяти
      B - номер страницы в блоке (0,1,2\...)
      H - биты 6 и 7 задают номер окна, в которое будет подключена страница
      C - 38h
    выходные данные:
      A - номер страницы, если CF=0
      A - код ошибки, если CF=1

Функция вычисляет физический номер страницы в блоке памяти и
подключает её в окно адресного пространства в зависимости от 
значения регистра HL. То есть, если HL указывает на адрес в 
пределах от 04000h до 07FFFh, то страница подключается в первое 
окно, от 08000h до 0BFFFh - второе окно, от 0C000h до 0FFFFh - 
третье.

На выходе в регистре A содержится физический номер страницы, 
которая была подключена до выполнения функции. 

```asm
; Выделить блок памяти 32К и подключить его страницы в #8000 и #C000 окна:
;

    LD C,#3D        ;GETMEM
    LD B,2          ;BLOCK 32K
    RST #10         ;SYSTEM CALL
    JR C,ERROR      ;MEMORY ALLOCATION ERROR
    LD (MEMHND),A   ;SAVE MEMORY HANDLE
    ;
    LD HL,#8000     ;FRAME ADDRESS
    LD C,#38        ;SETMEM
    LD B,0          ;FIRST MEMORY PAGE
    LD A,(MEMHND)   ;MEMORY HANDLE
    RST #10         ;SYSTEM CALL
    JR C,ERROR      ;MEMORY ALLOCATION ERROR
    ;
    LD HL,#C000     ;FRAME ADDRESS
    LD C,#38        ;SETMEM
    LD B,1          ;SECOND MEMORY PAGE
    LD A,(MEMHND)   ;MEMORY HANDLE
    RST #10         ;SYSTEM CALL
    JR C,ERROR      ;MEMORY ALLOCATION ERROR
    ;
```


Q:
Во! Пасибо большое? А еслищёлкать портами то есть возможномть что
программа будет совместима с будущей версией ПЗУ/АЛТЕРЫ/ДСС/ПЛАТЫ?

A:
Да, в любом случае будет возможность запуска программ в той
конфигурации для которой она была написана. Что-то вроде режима
совместимости. Но если для программы не критично работа напрямую
через порты, лучше пользоваться SETWIN как более универсальный.

> Так при размере меньше 16К будет выделена одна страница, при
> размере больше 16К - две, и т.д. В окна с "неиспользуемым" адресном
> пространством будет подключатся специальная страница #FF.

Q: 
Какие физические номера этих страниц к приме 1,2,3,,,256!

A:
Это можно узнать через функцию BIOS, эти номера будут разными в
зависимости от того сколько памяти было выделено другим приложениям.

Q:
Денис а такой вариант выделения памяти будет работать?

```asm
START
ORG #4000
    NOP
ORG #8000
    NOP
ORG #C000
    NOP
```

Дальше нужный орг и прога!

A:
Да, если конечно будет записан код от #4000 до конца программы, а не
от последнего ORG, как это делают некоторые ассемблеры.
Еще одно замечание, для DSS1.xx exe-файлы могут начинаться с #4100,
но после запуска можно использовать память с #4000.


Q:
В документации по спринтеру, есть такая фраза:
#82 - PAGE0 - страница ОЗУ, подключаемая вместо ПЗУ через порт #1FFD.
Что-бы это значило?

```asm
    ld a, номер_подключаемой_страницы
    out (#82),a
    ld a, _что?_
    out (#1ffd),a
```

A:

```asm
    LD A,1          ;RAM #0000-#3FFF
    LD BC,#1FFD
    OUT (C),A
    ;
    LD A,0          ;ROM #0000-#3FFF
    LD BC,#1FFD
    OUT (C),A
```

Fast-RAM включается подобно КЭШ-памяти в 'Пентагоне\'.
Включение/выключение происходит с помощью кода:

```asm
    DI
    IN A,(#FB)  ; включить Fast-RAM - 16к в 0-е окно
                ; (в адреса #0000..#3FFF)
    ... ; your programm
    IN A,(#7B)  ; выключить Fast-RAM
    EI
```    

Если надо использовать прерывания, программа должна установить
свой обработчик в адрес #0038.
Следует иметь в виду, что Fast-RAM может быть использована другими
программами, т.е. при запуске некоего процесса через DSS содержание
Fast-RAM может не сохраниться.

Перед вызовом функций DSS и BIOS Fast-RAM надо отключать.

###  Файлы

Q:
И ещё вопрос по функции 16h подскажите плз намера атрибутов в
частномти можно ли узнать размер файла этой функцией?

Размер файла можно узнать с помощью функции 15h.

A:

**15h (21) MOVE_FP (Перемещение указателя в файле)**

    входные данные:
      A - файловый манипулятор
      HL:IX - смещение указателя в файле
      B - способ перемещения
        B=0 от начала файла
        B=1 от текущего значения указателя
        B=2 от конца файла
      C - 15h
    выходные данные:
      A - код ошибки, если CF=1
      HL:IX - новое значение указателя
        HL:IX интерпретируется как 32-битное число. Если число меньше 65536,
        регистр HL содержит 0. Возможны следующие способы перемещения указателя:
        B=0 Смещение считается от начала файла, если HL:IX=0, указатель
          устанавливается на начало файла.
        B=1 Смещение считается от текущего значения указателя.
        B=2 Смещение считается от конца файла, если HL:IX=0, после перемещения
          HL:IX получится длина файла в байтах.

Атрибуты файла:

Каждый бит байта атрибутов задаёт определённый атрибут файла.
Атрибуты файлов можно изменять специальной функцией ДОС.

    бит 0 - Только для чтения
    бит 1 - Скрытый
    бит 2 - Системный
    бит 3 - Метка тома
    бит 4 - Каталог
    бит 5 - Архивный
    бит 6 - Не используется
    бит 7 - Не используется

- Атрибут "только для чтения". При значении 1 из файла можно читать,
но в него нельзя писать и его нельзя стереть.
- Атрибут "скрытый". При значении 1 файл невиден для обычных операций
ДОС.
- Атрибут "системный". Указывает, что файл является системным.
- Атрибут "метка тома". В старых версиях MS-DOS использовался для
задания метки диска.
- Атрибут "каталог". При значении 1 идентифицирует файл как каталог,
подчинённый данному каталогу или элементы "." и "..".
- Атрибут "архивный". Этот бит устанавливается при операциях записи в
файл.
Его могут использовать утилиты создающие архивные копии для сохранения
изменённых файлов.

###  Звук

Звук через COVOX-Blaster (COVOX с буферным ОЗУ)

CBL=COVOX-Blaster

Порт управления: 004Eh (**16-bit port!!!**, писать только 
через OUT (c),reg)

```asm
; bit 7 - COVOX-Blaster on (если 0 то обычный режим COVOX)
; bit 6 - STEREO-mode on
; bit 5 - 16bit-mode on
; bit 4 - Interrupt on - включение прерываний
; bits 3..0 - частота
;
; 0 16khz -- mono/stereo -- это старые режимы -- не использовать!
; 1 22khz -- mono/stereo -- это старые режимы -- не использовать!
; 2 reserved
; 3 reserved
; 4 reserved
; 5 reserved
; 6 reserved
; 7 reserved
;
; 8 7.8125 KHz -- mono/stereo 8/16 bit
; 9 10.9375 KHz -- mono/stereo 8/16 bit
; A 15.625 KHz -- mono/stereo 8/16 bit
; B 21.875 KHz -- mono/stereo 8/16 bit
; C 31.25 KHz -- mono/stereo 8/16 bit
; D 43.75 KHz -- mono/stereo 8/16 bit
; E 54.6875 KHz -- mono/stereo 8/16 bit
; F 109.375 KHz -- mono/stereo 8/16 bit
```

Порт 0FEh - биты запроса прерываний от CBL

    bit 7 - запрос данных для CBL
    bit 5 - синхронизация экрана (кадровый импульс, 4мс длиной, 20мс период)

Запись данных в COVOX-Blaster производится с помощью акселератора,
записью в страницу ОЗУ 0FDh (просто записать блок 128/256 байт с
адреса 0C000h) или через порт 4Fh командами OTIR блок записываемых 
данных по запросу. Для 8 бит режима - 128 байт; для 16 бит - 256 байт

Самый простой пример:

```asm
Test:
    LD BC,04Eh
    LD A,8Bh            ; включить 8 бит 22khz mono
    OUT (C),A           ; - CBL - включен!
    INC C
    LD HL,Sample
    OTIR                ; загрузить все 256 байт
    RET

Sample:
    DB 80h,81,82h,...   ; (256 отсчетов звука с нулем на уровне 80h)
```

Должен пищать одну ноту (если в Sample записать синус, то должно
чисто звучать).

Запрос данных в бите 7 порта FE появляется для каждых 128 байт (256
в режиме 16 бит). Его следует проверять, если его не оказалось, то
прерывание экранное, а не от CBL.

При выставленных прерываниях от CBL, стоит использовать режим IM 2,
иначе, будет часто вызываться DOS-овая процедура прерываний и могут
появиться тормоза на высоких частотах.

В режиме 8 бит сэмплы должны иметь уровень нуля на 80h, 16 бит 
сэмплы - уровень нуля - 0000h 
Stereo-сэмплы - должны иметь чередующиеся отсчеты левого и правого
канала.

```asm
mono_8bit:

    DB 80h,81h,7Fh....

mono_16bit:
    DW 0,1000,-1000...

stereo_8bit:
    DB 80h,80h,81h,80h,7Fh,80h... 
    ; здесь один канал играет, второй молчит

stereo_16bit:
    DW 0,0,1000,0,-1000,0... 
    ; аналогично, один канал играет, второй молчит
```    

(При тестировании 16 бит режима следует помнить, что звук с
амплитудой в единицы почти не слышен)

P.S. Формат данных выбран так, что бы из WAV-файлов данные в CBL
пересылать простой операцией блочной пересылки.

###  ISA-8 слоты

#### Summary

This article describe ISA-8 interaction.

#### More information

If you want to interaction with ISA devices, you have to make following
steps:
1) send 10h value to port 1FFDh(system port);
2) send control byte to port 0E2h(third memory window port);
control byte:
```
    D7...should be 1
    D6...should be 1
    D5...should be 0
    D4...should be 1
    D3...should be 0
    D2...specify number of ISA slot
    D1...specify access mode (0 - ISA memory, 1 - ISA ports)
    D0...should be 0
```
The read/write signals are forming from read/write signals 
memory range 0C000h-0FFFFh. And the address lines A13...A0 
has taken from processor data-BUS. The other ISA-signals 
such as RESET, AEN, A19...A14 can be set in port 9FBDh. 
And default value is 00h. 
```
port 9FBDh:
    D7...RESET
    D6...AEN
    D5...A19
    D4...A18
    D3...A17
    D2...A16
    D1...A15
    D0...A14
```

```asm

ISA_DIR     EQU 9FBDh
SC_PORT     EQU 1FFDh
PAGE3       EQU 0E2h

SAVE_PAGE   DB 0        ;variable for previous status of third memory port

RESET_ISA:              ; reset ISA device
    LD C, ISA_DIR
    LD A,0C0h
    OUT (C),A
    CALL Pause_10ms
    LD A,0
    OUT (C),A
    RET

Pause_10ms:
    LD HL,10000

Loop:
    DEC HL
    LD A,H
    XOR L
    JR NZ,Loop
    RET

OPEN_ISA_PORTS:         ; open access to ISA
    LD BC,SC_PORT
    LD A,10h
    OUT (C),A
    IN A,(PAGE3)        ; read value from memory port
    LD (SAVE_PAGE),A    ; save previous status of memory port
    LD A,0D2h           ; control byte for (first (upper) ISA slot)
    OUT (PAGE3), A      ; opening ISA port address space
    LD C,ISA_DIR
    LD A,0              ; high ISA addresses RESET and AEN signals.
    OUT (C),A
    RET

CLOSE_ISA_PORTS:        ; close access to ISA
    LD A,(SAVE_PAGE)
    OUT (PAGE3),A       ; restore value of memory port
    LD BC,SC_PORT
    LD A,0
    OUT (C),A           ;
    RET

WRITE_ISA_PORT:
    LD HL,ADRESS_PORT+0C000h    ; ISA port address + 0C000h offset 3 memory page
    LD A,DATA_OUT               ; data for writing
    LD (HL),A                   ; write data to port which pointered HL
    RET

READ_ISA_PORT:
    LD HL, ADRESS_PORT+0C000h   ; ISA port address + 0C000h offset 3 memory page
    LD A,(HL)                   ; read data from port which pointered HL
    RET

```

When you work with ISA, the access to third memory page are disabled. If
you want to address ISA-memory more than 3FFFh, you should specify high
bits in port 9FBDh.

###  Акселератор компьютера Sprinter.

Акселератор предназначен для ускорения операций по пересылке блоков
данных в ОЗУ и видео-ОЗУ.

Акселератор позволяет:

- быстро заполнять горизонтальную или вертикальную линию длиной до 256
точек одним цветом (в режиме 640x256 - одинарную/двойную горизонтальную
линию длиной до 512 точек)
- быстро копировать горизонтальную или вертикальную линию длиной до 256
точек (в режиме 640x256 - горизонтальную линию до 512 точек)
- проводить быстрые операции AND, OR, XOR с блоками памяти.

**Акселератор не может работать с блоками данных ПЗУ и Быстрого-ОЗУ.**

ОЗУ акселератора является частью внутреннего ОЗУ ППЛМ.
Операции по пересылке данных производятся путем записи блока данных в
это внутреннее ОЗУ, а затем копировании его в нужное место ОЗУ из ОЗУ
акселератора.
Блок данных, записываемый в ОЗУ акселератора может иметь различную
длинну из диапазона 1..256 байт.
После одной записи копирование может производиться несколько раз и,
таким образом, можно производить заполнение экрана текстурами.
Для заполнения экрана одним цветом используется другой режим
акселератора. В нем вместо копируемого блока данных из внутреннего ОЗУ
производится запись данных с шины процессора, которые в этот момент не
изменяются.

Управление акселератором производится непосредственно из программы.
Для этого изпользуются команды процессора, которые, фактически, являются
операциями типа NOP.

```asm
LD B,B - выключить акселетарор.
LD D,D - включить акселератор в режим приема байта размера блока
         далее следует команда типа LD A,dat, где dat и будет новым
         размером блока. Если размер блока был установлен ранее,
         его можно не устанавливать.
LD C,C - Операция Fill - заполнение одним байтом. Последующая
         команда типа LD (HL),A приведет к заполнению указанного
         ранее количества байт значением A
LD E,E - Операция Fill для графического экрана - заполнение
         вертикальных линий.
LD H,H - rezerved
LD L,L - копирование блока. Последующая команда типа LD A,(HL)
         приведет к заполнению ОЗУ акселератора данными из адреса (HL),
         а команда типа LD (DE),A приведет к перезаписи данных из ОЗУ
         акселератора в ОЗУ или видео-ОЗУ.
LD A,A - копирование блока для графического экрана подобна команде
         LD L,L, но работает с вертикальными линиями экрана.
```

Пример использования акселератора:

```asm
    ; Считаем, что экранная страница уже открыта по адресу #C000
    LD HL,#C040     ; адрес начала линии первого экрана
    LD DE,#C180     ; адрес начала линии второго экрана
    LD BC,#140      ; длина экрана по горизонтали
    DI              ; запретить прерывания для работы с акселератором
    LD D,D          ; включить акселератор на установку размера блока
    LD A,0          ; установить размер блока - 256 байт
    LD A,A          ; установить акселератор на копирование
                    ; вертикальных линий.
    LDIR            ; копировать
    LD B,B          ; выключить акселератор
    EI              ; включить прерывания
```

Эта часть программы произведет копирование всего содержимого первого
экрана на другой. Время исполения составляет примерно 26 милисекунд.
Дополнительные функции акселератора (AND, OR, XOR) работают таким же
образом.
Для выполнения логических функций используются команды XOR (HL); OR
(HL); AND (HL).

Пример кодирования блока в 256 байт.
```asm
    LD HL,ADRES_1
    LD DE,XOR_DAT
    DI
    LD D,D
    LD A,0          ; число байт, которые надо закодировать
    LD L,L
    LD A,(DE)       ; взять блок данных в ОЗУ акселератора
    XOR (HL)        ; произвести операцию XOR с данными акселератора
    LD (HL),A       ; запомнить в ОЗУ результат операции
    LD B,B
EI
```

Скорость работы акселератора ограничивается только физической
скоростью работы основного ОЗУ. Определить примерное время работы
команды с акселератором можно по такой формуле:

Время работы = время работы команды без акселератора + время работы акселератора

Время работы акселератора = число пересылаемых байт /7 микросекунд
Во время работы акселератора необходимо отключать прерывания, так как в
этот момент изменяется система команд процессора и программа на
прерывании не сможет работать корректно.

###  Прерывания

Кадровые и клавиатурные прерывания приходят с вектором 0FFh, отличать по
биту приема байта в порте клавиатуры, не пришел, значит экран. Возможно,
конечно, совпадение но это исключительно редкий случай.

От мыши прерывания не приходят. Сделать можно, но сейчас их нет. Кстати
и различие от экранных прерываний **можно** (и, видимо, надо будет в
новой версии) сделать пожестче через прошивку в ПЛМ.

От ISA и других внутренных портов процессора прерывания приходят с
другим вектором (настраивается в портах), поэтому в режиме IM 2 они
легко различаются.

###  IDE контроллер

Доступ к поpтам осуществляется пpи неактивном Beta-Disk интеpфейсе.
Со схемой без поллитpы не pазобpаться, пpивожу поpты как есть:

поpт pегистp накопителя

    ---- блок командных регистров ----
    xx50 0 (data)
    0051 1 (error/feature)
    0052 2 (sector count)
    0053 3 (sector number)
    0054 4 (cylinder low)
    0055 5 (cylinder high)
    4052 6 (device/head)
    4053 7 (status/command)

    ---- блок управляющих регистров ----
    4054 16 (alternate status/control)
    4055 17 ?

Пpи записи в поpт нужно его адpес увеличить на 0x100.

Пpи чтении pегистpа данных пpи a8=0 выpабатывается стpоб чтения и
младшая часть (D0-D7) шины данных накопителя выдаётся на шину
спектpума, а стаpшая сохpаняется в теневом pегистpе. 
Пpи a8=1 читается теневой pегистp (D8-D15).

Пpи записи pегистpа данных когда a8=0 байт сохpаняется в теневом
pегистpе и стpоб записи для накопителя не выpабатывается. Пpи 
записи pегистpа данных когда a8=1 выpабатывается стpоб записи 
для накопителя и байт с шины спектpума выдаётся на D8-D15 шины 
накопителя, на D0-D7 выдаётся содеpжимое теневого pегистpа.

Контроллер имеет общий теневой регистр для записи и чтения.

вот мои раскопки на эту тему от 13.10.2003:

    регистр команд | регистр состояния - 4153h запись, 4053h чтение
    регистр накопителя | головки - 4152h запись, 4052h чтение
    регистр циллиндра (старший байт) - 0155h запись, 0255h чтение
    регистр циллиндра (младший байт) - 0154h запись, 0254h чтение
    регистр данных - 0150h запись, 0050h чтение

Верна информация.
С одним добавлением. Доступ открыт в режиме Sprinter-ZX,
а в режимах Pentagon, Scorpion и т.п. - закрыт!

###  FDD контроллер

    0Fh Command/Status register
    3Fh Track register
    5Fh Sector register
    FFh Drive Control register

In Spectrum configuration the port 0Fh also mapped to 1Fh for TRDOS
compatibility.
But I would recommend to you don\'t use direct port access for it.
A Sprinter have BIOS functions for reading/writing any disk sectors.

for example:

At first, make reset disk and to set required parameters.
```asm
INIT_DISK:
    LD D,n      ; drive number 0-FDD A, 1-FDD B, 80h-HDD C\...
    LD C,#51    ; reset disk
    RST #08     ; BIOS call
    ;
    LD D,n      ; drive number
    LD E,n      ; sectors per track.
    PUSH DE
    LD A,D
    LD C,#58    ; get disk parameters
    RST #08     ; BIOS call
    LD A,H
    POP HL
    PUSH HL
    LD H,A
    POP AF
    LD IX,256   ; sector size
    LD C,#59    ; set disk parameters
    RST #08     ; BIOS call
    RET
```

And next to use BIOS fn. 055h for reading.
```asm
DRV_READ:               ; reading from disk
    LD A,drv_type       ; bit 0..3 - drive number
                        ; bit 4..7 - drive type
                        ; 0 - FDD
                        ; 6 - ram-disk (reserved)
                        ; 8 - HDD
                        ; C - CD-ROM (reserved)
    LD HL,sec_h         ; sector number (high)
    LD IX,sec_l         ; sector number (low)
                        ; (HL:IX - 32bit sector number, like LBA)
    LD B,n_sec          ; sectors count
    LD DE,bufer_adr     ; memory address for reading
    LD C,#55            ;
    RST #08             ; CF=0 - read OK
                        ; CF=1 - read error
```

#  Клавиатура


It's possible by DSS function 36h (K_SETUP). Sprinter has two keyboard
layouts (standard and alternative) which can be switched by [CTRL] +
[SPACE]. Each layout includes four keyboard modes. You can reload all
of them.

```asm
        LD HL,LAYOUT
        LD A,0              ;LAYOUT FOR NORMAL MODE
        LD BC,#0036
        RST #10

Esc     EQU     #1B
Bcs     EQU     #08
Tab     EQU     #09
Cps     EQU     #00
Spc     EQU     #20
Ent     EQU     #0D

;Normal mode (without CAPS and SHIFT not pressed)
        DB      "`",Esc,"1","2","3","4","5","6","7","8","9","0","-","=",Bcs
        DB      Tab,"q","w","e","r","t","y","u","i","o","p","[","]"
        DB      Cps,"a","s","d","f","g","h","j","k","l",";","'",Ent
        DB      #00,"z","x","c","v","b","n","m",#2C,".","/",#00,#5C
        DB      #00,#00,Spc,#00,#00
        DB      #00,#00,#00,#00,#00,#00,#00,#00,#00,#00,#00,#00
        DB      #00,#00,#00,"/","*","-","+",Ent,#00
        DB      #00,#00,#00,#00,#00,#00,#00,#00,#00,#00

;SHIFT mode (without CAPS and SHIFT are pressed)
        DB	    "~",Esc,"!","@","#","$","%","^","&","*","(",")","_","+",Bcs
        DB	    Tab,"Q","W","E","R","T","Y","U","I","O","P","{","}"
        DB	    Cps,"A","S","D","F","G","H","J","K","L",":",#22,Ent
        DB	    #00,"Z","X","C","V","B","N","M","<",">","?",#00,"|"
        DB	    #00,#00,Spc,#00,#00
        DB	    #00,#00,#00,#00,#00,#00,#00,#00,#00,#00,#00,#00
        DB	    #00,#00,#00,"/","*","-","+",Ent,#00
        DB	    #00,#00,#00,#00,#00,#00,#00,#00,#00,#00

;CAPS mode (with CAPS and SHIFT not pressed)
        DB	    "`",Esc,"1","2","3","4","5","6","7","8","9","0","-","=",Bcs
        DB	    Tab,"Q","W","E","R","T","Y","U","I","O","P","[","]"
        DB	    Cps,"A","S","D","F","G","H","J","K","L",";","'",Ent
        DB	    #00,"Z","X","C","V","B","N","M",#2C,".","/",#00,#5C
        DB	    #00,#00,Spc,#00,#00
        DB	    #00,#00,#00,#00,#00,#00,#00,#00,#00,#00,#00,#00
        DB	    #00,#00,#00,"/","*","-","+",Ent,#00
        DB	    #00,#00,#00,#00,#00,#00,#00,#00,#00,#00

;CAPS+SHIFT mode (with CAPS and SHIFT are pressed)
        DB	    "~",Esc,"!","@","#","$","%","^","&","*","(",")","_","+",Bcs
        DB	    Tab,"q","w","e","r","t","y","u","i","o","p","{","}"
        DB	    Cps,"a","s","d","f","g","h","j","k","l",":",#22,Ent
        DB	    #00,"z","x","c","v","b","n","m","<",">","?",#00,"|"
        DB	    #00,#00,Spc,#00,#00
        DB	    #00,#00,#00,#00,#00,#00,#00,#00,#00,#00,#00,#00
        DB	    #00,#00,#00,"/","*","-","+",Ent,#00
        DB	    #00,#00,#00,#00,#00,#00,#00,#00,#00,#00
```        
---

Прерывания от клавиатуры выставляют бит 0 в порте 19h, им и отличаются
от прерываний экрана. Конечно, возможны случайные совпадения, когда
прерывание от клавиатуры пришло одновременно с экранным, но это очень
маловероятно. От других устройств прерывание может придти, но так же с
некими признаками в портах (но это только в случае, если программа эти
порты настроила и использует для себя)

###  Коды ошибок DSS

This is a list of DSS error numbers.

    00h (00) - Success
    01h (01) - Invalid function
    02h (02) - Invalid drive number
    03h (03) - File not found
    04h (04) - Path not found
    05h (05) - Invalid handle
    06h (06) - Too many open files
    07h (07) - File exist
    08h (08) - File read only
    09h (09) - Root overflow
    0Ah (10) - No free space
    0Bh (11) - Directory not empty
    0Ch (12) - Attempt to remove current directory
    0Dh (13) - Invalid media
    0Eh (14) - Invalid operation
    0Fh (15) - Directory exist
    10h (16) - Invalid filename
    11h (17) - Invalid EXE-file
    12h (18) - Not supported EXE-file
    13h (19) - Permission denied
    14h (20) - Not ready
    15h (21) - Seek error
    16h (22) - Sector not found
    17h (23) - CRC error
    18h (24) - Write protect
    19h (25) - Read error
    1Ah (26) - Write error
    1Bh (27) - Drive failure
    1Ch (28) - Unknown error : 28
    1Dh (29) - Unknown error : 29
    1Eh (30) - No free memory
    1Fh (31) - Invalid memory block
    20h (32) - Unknown error : 32
