esxDOS для самых маленьких. Чтение и запись файлов

Введение


Официальной информации по API esxDOS в принципе не существует, а русскоязычной информации и неофициальной я не нашел.

Система же уже достаточно активно заняла свои позиции(как в виде фирмвари для divMMC/divIDE), так и как часть многих компьютеров(Карабас, ZXUno, Reverse, Spectrum Next и многие другие).

API хорошо работает и с IM2(можно подгружать файлы под музыку), работает почти на всем, что можно и достаточно легко в освоении.

В этой статье я опишу минимальное необходимое для жизни API, которое позволит создавать вам приложения под эту систему.


Что ж начнем!


Вся работа с esxDOS на уровне API очень похожа на работу с POSIX API и идет через RST 8.

Вызов выглядит примерное так:


    <устанавливаем значения регистров>
    RST 8
    db <Номер вызова>


Если же при выполнении нашей операции произошла ошибка — будет установлен флаг C(а код ошибки будет записан в системные переменные бейсика, но в 90% случаем нам достаточно просто знать, что случилась ошибка).

Попробуем считать файл

Для этого нам нужны будут следующие методы API: fopen, fread, fclose и getsetdrv(получение либо установка текущего устройства).

Пока что выглядит знакомо для любого человека, что писал под современные компьютеры.

Константы для вызова этих методов будут следующие:


ESX_GETSETDRV = #89
ESX_FOPEN = #9A
ESX_FCLOSE = #9B
ESX_FREAD = #9D


А так же для метода fopen необходимо будет указать режим работы с файлом(режимы могут объединяться через ИЛИ):


FMODE_READ = #01    ; Чтение
FMODE_WRITE = #06   ; Запись, будет ошибка, если файла нет
FMODE_CREATE = #0E  ; Создание файла, если уже существовал - будет перезаписан


Метод API fopen принимает следующие параметры:
  • A — текущее устройство
  • B — Режим(чтение/запись/создание)
  • IX — указатель на строчку именем файла(заканчивается 0), можно указывать как просто имя файла, так и с путем(в т.ч. относительным)

Номер открытого файла будет в регистре А — его нужно будет запомнить для дальнейшей работы.

Для получения текущего устройства необходимо вызвать метод getsetdrv, указав ему в качестве параметра в регистре А — нуль.

Я не люблю передавать параметры функциям через IX, поэтому в своей обертке я принимаю имя файла в HL.

И так файл мы можем открыть следующим кодом:


; Returns: 
;  A - current drive
getDefaultDrive:
    ld a, 0 : rst #8
    defb ESX_GETSETDRV
    ret

; Opens file on default drive
; B - File mode
; HL - File name
; Returns:
;  A - file stream id
fopen:
    push bc : push hl 
    call getDefaultDrive
    pop ix : pop bc
    rst #8
    defb ESX_FOPEN
    ret


После открытия нам необходимо высвободить ресурсы(у divMMC и divIDE своя память и если бросить файл открытым — то он будет жрать внутренний дескриптор, поможет только выключение/включение компьютера).

Закрыть файл еще проще — нужно просто передать в регистр A его номер и вызвать ESX_FCLOSE:


; A - file stream id
fclose:
    rst #8
    defb ESX_FCLOSE
    ret


Отлично, файл открыли, файл закрыли, но хотелось бы его все таки считать :-) или хотя бы его часть.

И в чем счастье? А в том, что esxDOS позволяет считать хоть один байт, хоть десять, хоть… #ffff — было бы куда читать.

Указываем сколько мы хотим считать в байтах и передаем это значение в регистр BC, в IX указатель на память, а в А — файловый дескриптор, но в моем случае это будет выглядеть вот так:


; A - file stream id
; BC - length
; HL - buffer
; Returns
;  BC - length(how much was actually read) 
fread:
    push hl : pop ix
    rst #8
    defb ESX_FREAD
    ret


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

И что ж? Небольшой практикум — считаем образ экрана с флэшки:


start:
    ld c, #fe : ld a, 0 : out (c), a

    ld hl, filename : ld b, FMODE_READ : call fopen : jr c, onError
    push af 
    ld hl, #4000 : ld bc, #ffff : call fread
    pop af
    call fclose
    ret

onError:
    ld c, #fe
    ld a, 3 
    out (c), a
    jr $

filename    db "/out.scr", 0    


Если файла нет — вывалимся в onError, если есть — получим картинку на экране.

Что ж, сохраним на диск что-нибудь

Для этого нам понадобятся следующие методы API:


ESX_FSYNC = #9C
ESX_FWRITE = #9E


fsync нужен для того, чтобы «уж точно записать на диск»(он принудительно сливает буфер на диск).

У fsync есть только один параметр — номер файла(регистр А).

А интерфейс fwrite — аналогичен fread, только работает наоборот.

Я использую такие обертки:


; A - file stream id
; BC - length
; HL - buffer
; Returns:
;   BC - actually written bytes
fwrite:
    push hl : pop ix
    rst #8
    defb ESX_FWRITE
    ret
    
; A - file stream id
fsync:
    rst #8
    defb ESX_FSYNC
    ret


Для примера сделаем дампалку нижних 16к(там будет esxDOS, возможно, со страницами ОЗУ).


    ld c, #fe : ld a, 0 : out (c), a

    ld hl, filename : ld b, FMODE_CREATE : call fopen : jr c, onError
    push af 
    ld hl, #0000 : ld bc, #4000 : call fwrite
    pop af : push af 
    call fsync
    pop af
    call fclose
    ret

onError:
    ld c, #fe
    ld a, 3 
    out (c), a
    jr $

filename    db "l16.bin", 0    


Что ж самый минимум описан, если будут желающие — продолжу статьи по esxDOS(например, получение каталога или атрибутов файлов, работа со смещениями в файлах)

UPD


Есть несколько мелочей, которые стоит прояснить.

Читать и писать можно много много раз — поточная работа — это основа работы с esxDOS(т.е. можно читать в область экрана из файла каждый раз по целому экрану, могу к следующей статье написать проигрывалку видео для спектрума).

Номер файла — это номер записи во внутренней таблице файловых дескрипторах esxDOS. Точное количество одновременно открытых файлов я не знаю — но оно достаточное, чтобы не особо париться по этому поводу, однако, если постоянно файлы открывать и не закрывать, то они кончатся(таблица хранится во внутренней памяти divMMC/divIDE), поможет выключение/включение компьютера(или полный перезапуск divIDE/divMMC).

И еще раз напомню — чтение и запись считаются побайтово(т.е. если вам нужно записать 3 байта — вы пишите 3 байта, если 100 — то 100).

И да, раз эта тема интересна — то будет еще одна статья. В коментариях предложите — получение каталога или работа со смещениями в файле.

0 комментариев

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.