Перейти к содержимому

Библиотеки для Sprinter

Набор библиотек на ассемблере Z80 для компьютера Sprinter. Они закрывают самые трудоёмкие части прикладного программирования — графику, вывод текста и пользовательский интерфейс, — чтобы приложение не программировало видеоконтроллер, страницы VRAM и палитру напрямую.

Библиотека Видеорежим Назначение
GFX320 #81 — 320×256, 256 цветов 2D-графика: примитивы, тайлы, палитра, двойная буферизация, fade
GFX640 #82 — 640×256, 16 цветов то же для режима высокого разрешения
AFNT320 #81 — 320×256, 256 цветов быстрый вывод текста аппаратным акселератором
AFNT640 640×256, 16 цветов быстрый вывод текста аппаратным акселератором
WIN320 #81 — 320×256, 256 цветов оконный интерфейс: панели, кнопки, поля ввода, списки
MENU320 #81 (поверх WIN320) строка меню с выпадающими списками

Все библиотеки, кроме MENU320, распространяются в виде DLL — одного готового файла (GFX320.DLL, WIN320.DLL и т. д.), который кладётся рядом с программой. MENU320 — исключение: это модуль, который линкуется прямо в приложение и работает поверх WIN320.

DLL загружает менеджер библиотек libman. Это небольшой модуль, который включается в приложение; он умеет найти файл DLL (сначала в каталоге EXE), распаковать его, разместить в памяти и диспетчеризовать вызовы функций по номерам.

Здесь важно понимать организацию памяти Sprinter: адресное пространство Z80 (64 КБ) разбито на четыре окна по 16 КБ — WIN0 (#0000), WIN1 (#4000), WIN2 (#8000) и WIN3 (#C000). В любое окно можно подключить любую страницу физической памяти, в том числе видеопамять. DLL целиком живёт в одном окне; рекомендуемая раскладка — библиотека в WIN3, а код, данные и стек приложения в WIN0–WIN2.

Загрузка и вызов выглядят одинаково для всех библиотек:

ld hl,dll_name ; "GFX320.DLL",0 — ASCIIZ-имя файла
ld a,3 ; окно для DLL (WIN3)
call LIBMAN.l_load
jp c,load_error ; CF=1 — не загрузилась (причина в l_reason)
ld (handle),hl ; HL — хэндл загруженной библиотеки
ld hl,(handle)
ld b,GFX_CLEAR ; номер функции — константа из .inc-файла
ld a,0 ; аргументы функции: A, DE, IX, IY
ld e,GFX_TARGET_FRONT
call LIBMAN.l_call
jp c,dispatch_error ; CF=1 — ошибка самого libman
or a
jp nz,gfx_error ; A≠0 — код ошибки библиотеки

Что здесь происходит:

  • l_load получает имя файла в HL и номер окна в A, а возвращает хэндл — по нему библиотека потом вызывается и выгружается (l_free);
  • l_call получает хэндл в HL и номер функции в B; до самой функции доходят только регистры A, DE, IX, IY (HL и BC заняты диспетчером). Крупные структуры передаются указателем, обычно в DE;
  • результат приходит двумя уровнями: флаг CF — ошибка диспетчера libman (например, кривой хэндл), а регистр A — статус самой функции: 0 — успех, иначе код ошибки (#10..#17 у GFX, #20..#28 у WIN320).

Номера функций и коды ошибок не нужно помнить — каждая библиотека поставляется с include-файлом констант для sjasmplus (gfx320.inc, win320.inc, …), а GFX и WIN320 дополнительно имеют готовые биндинги для C (SDCC) и Turbo Pascal.

  • Видеорежим включает приложение. Библиотеки не переключают режим сами: перед рисованием вызовите DSS SETVMOD с нужным номером режима.
  • Не печатайте через консоль DSS в графическом режиме. Текстовый экран и знакогенератор лежат в той же видеопамяти, поэтому обычный текстовый вывод портит картинку. Ждите клавишу «молча» (DSS #30), а печатайте после возврата в текстовый режим.
  • Библиотеки нереентерабельны. Нельзя вызывать их из обработчика прерываний; из ISR обычно только взводят флаг, а рисуют в главном цикле.
  • После любой операции библиотеки восстанавливают подключённые страницы памяти и состояние прерываний — приложению не нужно ничего чинить за ними.