Учимся читать и писать!
«640K ought to be enough for anybody...»
Итак, объём стандартной дискеты — 640Кб. Объём sd card — гораздо выше.
Как использовать SD в своих программах?
Речь пойдёт о драйвере, который повсеместно используется на zx evo — в Wild Commander.
Этот драйвер написан Koshi, и позволяет проводить основные операции с файлами и папками на sd card:
— создавать
— удалять
— переименовывать
— проверять на наличие
— переходить по директориям
— читать сектор
— записывать сектор
Для начала, давайте подключим модуль.
Его требования следующие:
1. Фиксированное размещение в памяти:
— драйвер должен лежать в странице #0f;
— включение и вызов драйвера происходит из PAGE0, драйвер работает с адреса #0, эта память должна быть RAM
2. Инициализация драйвера при старте
— необходимо вызвать инит драйвера, инит устройства и проверить выдачу ошибок.
3. Во время работы драйвер использует DMA. Это позволяет производить файловые операции с максимально доступной нам скорость.
Любая DMA транзакция во время работы драйвера:
— при записи может привести к проблемам с данными на карте, и как результат — её инициализация;
— при чтении — прочитает неизвестно что.
Для начала — необходимо перенести определения вызовов драйвера в свой исходный код. По представленной ссылке (в кодировке 866) показан пример работы с драйвером + определения адресов вызовов его функций, которые нам и нужны.
Инициализация драйвера:
после успешного выполнения инициализации вы уже находитесь в корневой папке.
Давайте зайдём в папку wc в корне диска. Для этого нам необходим дескриптор (описатель) папки.
Первый байт — признак папки, далее — имя, заканчивающееся 0.
Чтение файла
В текущей (активной) папке есть файл с настройками — wc.ini, который охота заполучить в память.
опять нужен дескриптор файла, производим его поиск, и потом — чтение:
Читаем его:
Всё, содержимое первых 512 байт файла — находится в паге download_page с адреса 0.
С чтением уже понятнее. Теперь стоит разобраться с записью.
Создание папки производится следующим образом.
для начала — мы должны находится в активной директории. это может быть корневая, переход в неё производим вызовом SETROOT;
либо же с помошью подпрограммы set_folder из примеров выше — переходим в нужную.
здесь нужно отметить, что для создаваемой папки нужно только её имя с терминатором «0» в конце.
Создание файла так же просто:
здесь нужно отметить, что дескриптор создаваемого файла гораздо шире чем в предидущих случаях.
Он содержит признак файла, его длину в 32 бита, имя и терминатор. Размер файла может быть больше 640кб ;)
пример указания длины файла:
в данном случае можно заметить, что с начала мы записываем младшие 16 бит длины, далее — последующие 16 бит.
Подпрограмма создания файлов может возвращать следующие ошибки:
Запись данных производится вызовом подпрограммы SAVE512, которой необходимо передать страницу в С, адрес с данными в HL, и количество блоков по 512 байт для сохранения.
Для расчёта количества блоков по текущей длине я использую следующую подпрограмму Коши:
Люблю такой код, поиграйте с ним :)
На входе: длина в виде DE,HL
на выходе: длина в блоках, в DE,HL.
Подпрограмма применима в случаях, когда вы собираетесь писать файл больше 128кб.
итак, запись небольшого блока:
Запись больше 256 блоков:
Удаление файла
Указываем дескриптор, вызываем функцию:
Блин, хорошо, базовый наборчик есть. Можно и попробовать. Но!
Для этого ваш запускаемый spg-файл необходимо сохранить либо на реальную карту, либо записать в образ диска эмулятора.
Бегать с картой долго, да и — можно запороть своими попытками. Поэтому — пишем в образ эмулятора.
Для тестов и отладки я рекомендую использовать великолепную прогу от Robus, которая позволяет записывать в образ диска эмулятора необходимые вам файлы. К достоинствам robimg.exe следует отнести то, что писать она может даже в открытый сейчас образ, чего не умеет ни один знакомый мне менеджер образов, и работает из командной строки.
Пример использования этого «инжектора» вы можете увидеть здесь. Создаётся папка с нужными именем, в которую копируются все необходимые файлы, и после этого она впрыскивается с заменой в нужную директорию на лету.
Великолепный инструмент, который очень облегчил задачу отладки.
Рекомендую иметь копию образа карты (wc.img) для эмулятора, потому что… ;)
Ссылки:
github.com / ZiFi — драйвер, доки
WildCommander sources
SD driver sources
Итак, объём стандартной дискеты — 640Кб. Объём sd card — гораздо выше.
Как использовать SD в своих программах?
Речь пойдёт о драйвере, который повсеместно используется на zx evo — в Wild Commander.
Этот драйвер написан Koshi, и позволяет проводить основные операции с файлами и папками на sd card:
— создавать
— удалять
— переименовывать
— проверять на наличие
— переходить по директориям
— читать сектор
— записывать сектор
В первую очередь я хочу поблагодарить Koshi за реализацию настолько сложной задачи как изучение, кодинг и отладка драйвера;
и во вторых — за предоставление модуля драйвера для использования в составе Zifi.
Итак, базовое руководство по файловым операциям с использованием драйвера sd card.
Для начала, давайте подключим модуль.
Его требования следующие:
1. Фиксированное размещение в памяти:
— драйвер должен лежать в странице #0f;
— включение и вызов драйвера происходит из PAGE0, драйвер работает с адреса #0, эта память должна быть RAM
2. Инициализация драйвера при старте
— необходимо вызвать инит драйвера, инит устройства и проверить выдачу ошибок.
3. Во время работы драйвер использует DMA. Это позволяет производить файловые операции с максимально доступной нам скорость.
Любая DMA транзакция во время работы драйвера:
— при записи может привести к проблемам с данными на карте, и как результат — её инициализация;
— при чтении — прочитает неизвестно что.
Для начала — необходимо перенести определения вызовов драйвера в свой исходный код. По представленной ссылке (в кодировке 866) показан пример работы с драйвером + определения адресов вызовов его функций, которые нам и нужны.
Базовые операции с sd card:
Инициализация драйвера:
sd_driver_page equ #0f
sd_init ld a,sd_driver_page
call set_page0
CALL DOS_SWP ; DEPACK Driver
CALL DEV_INI ; инициализация карты
JP NZ,ER0 ; обработка ошибки карты "SD Card NOT ready!"
CALL HDD
JP NZ,ER1 ; ошибка FAT32 NOT FOUND
CALL SETROOT ; установка и переход в корень диска: SET ROOT DIR
jp sd_exit ; возвращаем нужную пагу и другие полезные действия при выходе
set_page0 ld bc,PAGE0
out (c),a
ret
после успешного выполнения инициализации вы уже находитесь в корневой папке.
Функции чтения
Переход по папкамДавайте зайдём в папку wc в корне диска. Для этого нам необходим дескриптор (описатель) папки.
Первый байт — признак папки, далее — имя, заканчивающееся 0.
set_folder LD HL,DIR
CALL FENTRY ; поиск папки
JP Z,not_found ; папка где ты!?
CALL SETDIR ; установка найденного каталога как активного для файловых операций
ret
DIR DB #10
DB "wc",0
Koshi: FENTRY ищет файлы/каталоги и выдает длину оных в ответ, плюс позиционирует на них.
Выход этой функции:
Z — entry not found
NZ — [DE,HL] — file length
Чтение файла
В текущей (активной) папке есть файл с настройками — wc.ini, который охота заполучить в память.
опять нужен дескриптор файла, производим его поиск, и потом — чтение:
Читаем его:
LD HL,FILE_INI
CALL FENTRY
JP Z,ini_not_found
LD C,download_page ; страница для загрузки
LD HL,#0000 ; адрес загрузки
LD B,1 ; размер файла в блоках (1 блок = 512 байт)
CALL LOAD512
FILE_INI DB #00; 0 - file, 1 - DIR
DB "wc.ini",0
Всё, содержимое первых 512 байт файла — находится в паге download_page с адреса 0.
С чтением уже понятнее. Теперь стоит разобраться с записью.
Операции записи
Сюда входит — создание папки, файла, запись в файл.Создание папки производится следующим образом.
для начала — мы должны находится в активной директории. это может быть корневая, переход в неё производим вызовом SETROOT;
либо же с помошью подпрограммы set_folder из примеров выше — переходим в нужную.
LD HL,DIR_new
CALL MKDIR
ret
DIR_new DB "zxpron",0
здесь нужно отметить, что для создаваемой папки нужно только её имя с терминатором «0» в конце.
Создание файла так же просто:
LD HL,FILE
CALL MKFILE
JP NZ,error_create_new_file ;File Creation Failed
ret
FILE DB #00; flag
DW #0000,#0000;length
FILE_NAME ds 16
db 0
здесь нужно отметить, что дескриптор создаваемого файла гораздо шире чем в предидущих случаях.
Он содержит признак файла, его длину в 32 бита, имя и терминатор. Размер файла может быть больше 640кб ;)
i: HL - flag(1),ln(4),name(1-255),0
пример указания длины файла:
DW #1000,#0000 ;length - 4kb
в данном случае можно заметить, что с начала мы записываем младшие 16 бит длины, далее — последующие 16 бит.
Подпрограмма создания файлов может возвращать следующие ошибки:
Koshi: если файло есть, то NZ получаем, и смотрим в A код ошибке
если 3 — то имя уже занято
o: NZ — ERROR (NO ENOUGHT SPACE)
A: 1 — ln not valid
2 — index fatality
3 — ln already exists
255 — unknown error
Z — SUCCESS
Запись данных производится вызовом подпрограммы SAVE512, которой необходимо передать страницу в С, адрес с данными в HL, и количество блоков по 512 байт для сохранения.
Описание параметров:
i: CHL - Addres
B - lenght
o: CHL - New Value
A - EndOfChain (#0F)
Для расчёта количества блоков по текущей длине я использую следующую подпрограмму Коши:
DEL512 ;i:[DE,HL]/512
LD A,L,L,H,H,E,E,D,D,0
LD BC,1:OR A:CALL NZ,ADD4B
LD A,2
DELITX2 ;i:[DE,HL]/A
; A - Power of Two
; o:[DE,HL]
CP 2:RET C
LD C,0
SRL A
L33T SRL D:RR E,H,L,C
SRL A:JR NC,L33T
LD A,C:OR A:RET Z
LD BC,1:CALL ADD4B
RET
ADD4B ADD HL,BC:RET NC:INC DE
RET
Люблю такой код, поиграйте с ним :)
На входе: длина в виде DE,HL
на выходе: длина в блоках, в DE,HL.
Подпрограмма применима в случаях, когда вы собираетесь писать файл больше 128кб.
итак, запись небольшого блока:
;Save data into new file <128kb:
save_64 ld b,len
ld c,page
ld hl,adress
call SAVE512
Запись больше 256 блоков:
Koshi: просто пишешь до посинения пока цепочка не кончиццо
када цепочки конец — что сейв512, что лоад512 выдадут в А=#0F
Удаление файла
Указываем дескриптор, вызываем функцию:
ld hl,delete_file
call DELFL
параметры DELFL:
i: HL - flag(1),name(1-255),0
o: Z - NOT FOUND
NZ - FILE DELETED
Блин, хорошо, базовый наборчик есть. Можно и попробовать. Но!
Как тестить?
Естественно что функции работы с sd необходимо проверять на sd.Для этого ваш запускаемый spg-файл необходимо сохранить либо на реальную карту, либо записать в образ диска эмулятора.
Бегать с картой долго, да и — можно запороть своими попытками. Поэтому — пишем в образ эмулятора.
Для тестов и отладки я рекомендую использовать великолепную прогу от Robus, которая позволяет записывать в образ диска эмулятора необходимые вам файлы. К достоинствам robimg.exe следует отнести то, что писать она может даже в открытый сейчас образ, чего не умеет ни один знакомый мне менеджер образов, и работает из командной строки.
Пример использования этого «инжектора» вы можете увидеть здесь. Создаётся папка с нужными именем, в которую копируются все необходимые файлы, и после этого она впрыскивается с заменой в нужную директорию на лету.
Великолепный инструмент, который очень облегчил задачу отладки.
Рекомендую иметь копию образа карты (wc.img) для эмулятора, потому что… ;)
Ссылки:
github.com / ZiFi — драйвер, доки
WildCommander sources
SD driver sources
3 комментария
Но всетаки, для пользователей, конкретно в примерах это лучше прописать. имхо.
ps: Пример отображения содержимого SD-карты начиная с корня… как более развернутое изложения примеров..)