;LAST UPDATE: 08.06.2013 savelij
include macros.a80
include sdcomand.a80
include ports_ngs.a80
include global_vars.a80
;КОЛИЧЕСТВО СЕКТОРОВ В КЛАСТЕРЕ В ПЕРЕМЕННОЙ BYTSSEC
;КОНЕЦ ЦЕПОЧКИ НОМЕРОВ СТАРШИЙ БАЙТ 32 БИТНОГО ЧИСЛА = 0XFF
;ДЛЯ НГС РЕЖИМА УЧИТЫВАТЬ ПОЛОЖЕНИЕ СТЕКА, АДРЕС РАБОТЫ КОДА И ПОЛОЖЕНИЕ ПЕРЕМЕННЫХ
NGS EQU 1 ;0-КОМПИЛЯЦИЯ ДЛЯ ZSD, 1-КОМПИЛЯЦИЯ ДЛЯ NEOGS
CONV_NUMSEC EQU 1 ;0-СОХРАНЯТЬ НОМЕР КЛАСТЕРА, 1-СОХРАНЯТЬ НОМЕР СЕКТОРА
;СТАРТОВАЯ СТРАНИЦА ДЛЯ СПИСКА КЛАСТЕРОВ, ПО ЗАПОЛНЕНИЮ НОМЕР СТРАНИЦЫ ДЕКРЕМЕНТИТСЯ
IF NGS=1
NUM_PAGE EQU 0X7F ;СТАРТОВАЯ СТРАНИЦА УКЛАДКИ КЛАСТЕРОВ/СЕКТОРОВ
BUFF_SEC EQU 0X5000 ;АДРЕС БУФЕРОВ И ПЕРЕМЕННЫХ
ADR_LOADING EQU 0X8000 ;АДРЕС УКЛАДКИ НОМЕРОВ КЛАСТЕРОВ/СЕКТОРОВ
ADR_EXEC EQU 0X6000 ;АДРЕС ИСПОЛНЕНИЯ КОДА
ELSE
NUM_PAGE EQU 7 ;СТАРТОВАЯ СТРАНИЦА УКЛАДКИ КЛАСТЕРОВ/СЕКТОРОВ
BUFF_SEC EQU 0X8000 ;АДРЕС БУФЕРОВ И ПЕРЕМЕННЫХ
ADR_LOADING EQU 0XC000 ;АДРЕС УКЛАДКИ НОМЕРОВ КЛАСТЕРОВ/СЕКТОРОВ
ADR_EXEC EQU 0X6000 ;АДРЕС ИСПОЛНЕНИЯ КОДА
ENDIF
ORG ADR_EXEC ;-> ЗАМЕНИТЬ НА ЛЮБОЙ УДОБНЫЙ
DI
LD HL,F_PATH ;АДРЕС ПИТИ И ИМЕНИ ФАЙЛА ДЛЯ ПОИСКА
LD A,NUM_PAGE ;НОМЕР СТРАНИЦЫ КУДА СКЛАДЫВАТЬ НОМЕРА КЛАСТЕРОВ/СЕКТОРОВ
CALL READ_CLS
JR $
;ПУТЬ ДО ФАЙЛА, ТОЛЬКО В ВЕРХНЕМ РЕГИСТРЕ ИБО ПОИСК ВЕДЕТСЯ ПО КОРОТКОМУ ИМЕНИ ВИДА 8.3
F_PATH IF NGS=0
DB "DEMO/ANAMORIG.UDI",0
ELSE
DB "MP3/MIC-RO~1.MP3",0
ENDIF
;МОЖНО УКАЗАТЬ ПУТЬ В ВИДЕ "DIR/DIR/FILE.EXT" 0 В КОНЦЕ СТРОКИ ОБЯЗАТЕЛЕН
;---------------------------------
;ГРУЗИЛКА ФАЙЛА ПО УКАЗАННОМУ ПУТИ
BUF512 EQU BUFF_SEC ;200 БУФЕР СЕКТОРА
TDIRCLS EQU BUF512+0X0200 ;400 БУФЕР КЛАСТЕРОВ ROOT ДИРЕКТОРИИ
CAL_FAT EQU TDIRCLS+0X0400 ;1 КАЛИБР FAT
BYTSSEC EQU CAL_FAT+1 ;1 КОЛИЧЕСТВО СЕКТОРОВ В КЛАСТЕРЕ
ROOTCLS EQU BYTSSEC+1 ;4 КЛАСТЕР НАЧАЛА ROOT ДИРЕКТОРИИ
ROOTSEC EQU ROOTCLS+4 ;2 РАЗМЕР В СЕКТОРАХ ROOT ДИРЕКТОРИИ
SEC_FAT EQU ROOTSEC+2 ;4 КОЛИЧЕСТВО СЕКТОРОВ ОДНОЙ FAT
RSVDSEC EQU SEC_FAT+4 ;2 РАЗМЕР РЕЗЕРВНОЙ ОБЛАСТИ
STARTRZ EQU RSVDSEC+2 ;4 НАЧАЛО ДИСКА/РАЗДЕЛА
FRSTDAT EQU STARTRZ+4 ;4 АДРЕС ПЕРВОГО СЕКТОРА ДАННЫХ ОТ BPB
SEC_DSC EQU FRSTDAT+4 ;4 КОЛИЧЕСТВО СЕКТОРОВ НА ДИСКЕ/РАЗДЕЛЕ
CLS_DSC EQU SEC_DSC+4 ;4 КОЛИЧЕСТВО КЛАСТЕРОВ НА ДИСКЕ/РАЗДЕЛЕ
FATSTR EQU CLS_DSC+4 ;4 НАЧАЛО ПЕРВОЙ FAT ТАБЛИЦЫ
ADRPATH EQU FATSTR+4 ;2 АДРЕС ТЕКСТА ПУТИ ФАЙЛА
STATUS EQU ADRPATH+2 ;1 СТАТУС ПОСЛЕ ВЫЗОВА LOAD_SD
OLD_SP EQU STATUS+1 ;2 СТЕК ДЛЯ ВЫХОДА
FB_EXT EQU OLD_SP+2 ;B БУФЕР 8.3 ДЛЯ ПОИСКА ИМЕНИ
LVL_DIR EQU FB_EXT+0X0B ;1 НОМЕР УРОВНЯ ДИРЕКТОРИИ
LSTLOAD EQU LVL_DIR+1 ;4 НОМЕР СЕКТОРА ЗАГРУЖЕННОГО В БУФЕР
;SD КАРТА НЕ НАЙДЕНА
ZAW003 LD A,0XEE
WR_STAT LD SP,(OLD_SP)
LD (STATUS),A
IF NGS=1
RET
ELSE
CS__LOW PUSH AF
LD A,1
OUT (P_CONF),A
POP AF
RET
CS_HIGH PUSH AF
LD A,3
OUT (P_CONF),A
XOR A
OUT (P_DATA),A
POP AF
RET
ENDIF
;ЧТЕНИЕ СПИСКА КЛАСТЕРОВ ФАЙЛА
;НА ВХОДЕ:A-СТРАНИЦА НАЧАЛА ЗАГРУЗКИ
;HL-АДРЕС ТЕКСТОВОЙ СТРОКИ
;ПУТИ К ФАЙЛУ ВМЕСТЕ С ИМЕНЕМ И РАСШИРЕНИЕМ ФАЙЛА. ПУТЬ ПОЛНОСТЬЮ ОТ ROOT
;НА ВЫХОДЕ: A=
;0X00-OK
;0XAA-ФАЙЛ НЕ НАЙДЕН
;0XDD-FAT НЕ ОБНАРУЖЕН
;0XEE-SD КАРТА НЕ ОБНАРУЖЕНА
READ_CLS LD IYL,A;LY,A ;СОХРАНИЛИ НОМЕР СТРАНИЦЫ КУДА ГРУЗИТЬ
LD (ADRPATH),HL ;СОХРАНИЛИ АДРЕС СТРОКИ ПУТИ
LD (OLD_SP),SP ;СОХРАНИЛИ СТЕК
LD A,0XFF
LD (LSTLOAD+3),A ;ПРИНУДИТЕЛЬНАЯ ЗАГРУЗКА СЕКТОРА БЕЗ ПРОВЕРКИ НАЛИЧИЯ В БУФЕРЕ
IF NGS=1
LD A,1
OUT (GSCFG0),A ;ОТКЛЮЧИЛИ ПЗУ, ВСЕ СТРАНИЦА ОЗУ
LD A,%10011011
OUT (SCTRL),A ;СКОНФИГУРИЛИ НГС С CS=1 ДЛЯ SD КАРТЫ
ELSE
CALL CS_HIGH
ENDIF
LD B,0X10
LD A,0XFF
IF NGS=1
OUT (SD_SEND),A ;ПИШЕМ 0X10 БАЙТ 0XFF В ПОРТ КАРТОЧКИ
ELSE
OUT (P_DATA),A
ENDIF
DJNZ $-4
XOR A ;256 ПОПЫТОК НАЙТИ SD КАРТУ
EX AF,AF'
IF NGS=1
LD A,1
OUT (SCTRL),A ;ВЫБРАЛИ SD КАРТУ CS=0
ENDIF
ZAW001 LD HL,CMD00
CALL OUTCOM ;ПЕРЕВОДИМ КАРТОЧКУ В РЕЖИМ SPI КОМАНДОЙ 0
CALL IN_OOUT ;ЖДЕМ ОТВЕТА
EX AF,AF'
DEC A
JR Z,ZAW003 ;ЖДЕМ ПО СЧЕПТЧИКУ 256 РАЗ
EX AF,AF'
DEC A
JR NZ,ZAW001 ;ЖДЕМ ПОКА КАРТА ОТВЕТИТ БАЙТОМ 1
LD BC,SD_RSTR
LD HL,CMD08
CALL OUTCOM ;ОПРЕДЕЛЯЕМ СПЕЦИФИКАЦИЮ КАРТЫ
CALL IN_OOUT ;В "A" ОТВЕТ КАРТЫ R1
IN H,(C)
NOP
IN H,(C)
NOP
IN H,(C)
NOP
IN H,(C) ;ПРОЧИТАЛИ ОСТАЛЬНЫЕ БАЙТЫ В НИКУДА
BIT 2,A ;ЕСЛИ ОШИБКА, ТО
LD HL,0 ;КАРТА СПЕЦИФИКАЦИИ 1.0
JR NZ,ZAW006 ;ИНАЧЕ
LD H,0X40 ;КАРТА СПЕЦИФИКАЦИИ 2.0
ZAW006 LD A,CMD_55
CALL OUT_COM ;ЗАПУСКАЕМ ВНУТРЕННЮЮ ИНИЦИАЛИЗАЦИЮ КАРТЫ
CALL IN_OOUT
IF NGS=1
LD BC,SD_SEND
ELSE
LD BC,P_DATA
ENDIF
LD A,ACMD_41
OUT (C),A
LD A,H
OUT (C),A
XOR A
OUT (C),A
NOP
OUT (C),A
NOP
OUT (C),A
DEC A
OUT (C),A
CALL IN_OOUT
AND A
JR NZ,ZAW006 ;ЖДЕМ ПОКА КАРТЫ ПЕРЕЙДЕТ В РЕЖИМ ГОТОВНОСТИ
ZAW004 LD A,CMD_59
CALL OUT_COM ;ПРИНУДИТЕЛЬНО ОТКЛЮЧАЕМ CRC16
CALL IN_OOUT
AND A
JR NZ,ZAW004
ZAW005 LD HL,CMD16
CALL OUTCOM ;ПРИНУДИТЕЛЬНЫЙ РАЗМЕР СЕКТОРА 512 БАЙТ
CALL IN_OOUT
AND A
JR NZ,ZAW005
;ИНИЦИАЛИЗАЦИЯ ПЕРЕМЕННЫХ FAT
WC_FAT LD DE,0
LD B,D
LD C,E
CALL LOADLST ;ЧИТАЕМ СЕКТОР 0 КАРТОЧКИ
PUSH HL
POP IX
LD DE,0X01BE
ADD HL,DE ;ПЕРЕХОДИМ НА СМЕЩЕНИЕ ДЛЯЧ ПРОВЕРОК
LD A,(HL) ;ПРОВЕРЯМ ЧТОБЫ БЫЛ 0, КАРТОЧКИ НЕ МОГУТ БЫТЬ ЗАГРУЗОЧНЫМИ
AND A
JR NZ,RDFAT05 ;ЕСЛИ НЕ 0, ПРОВЕРИТЬ ДРУГОЕ
LD DE,4
ADD HL,DE ;ПЕРЕХОДИМ К ПРОВЕРКЕ ТИПА РАЗДЕЛА
LD A,(HL)
LD B,0
CP 1 ;FAT12?
JR Z,RDFAT06
LD B,2
CP 0X0B ;FAT32?
JR Z,RDFAT06
CP 0X0C ;FAT32?
JR Z,RDFAT06
LD B,1
CP 6 ;FAT16?
JR Z,RDFAT06
CP 4 ;FAT16?
JR Z,RDFAT06
CP 0X0E ;FAT16?
JR NZ,RDFAT05
RDFAT06 LD A,B ;БЕРЕМ ИЗ "B" ТИП РАЗДЕЛА
LD (CAL_FAT),A ;СОХРАНИЛИ
ADD HL,DE
CALL LOADZP ;БЕРЕМ НОМЕР СЕКТОРА НАЧАЛА ОСНОВНОГО РАЗДЕЛА
JR RDFAT00 ;ПЕРЕХОДИМ К ИНИЦИАЛИЗАЦИИ ПЕРЕМЕННЫХ ДЛЯ РАБОТЫ С ФАТОМ
;MBR НЕ ОБНАРУЖЕН, ПРОВЕРЯЕМ СЕКТОР 0 КАРТЫ КАК ОПИСАТЕЛЬ
RDFAT05 LD C,(IX+0X0D) ;C=КОЛИЧЕСТВО СЕКТОРОВ В КЛАСТЕРЕ
XOR A
LD E,A
LD B,8
RR C
ADC A,0
DJNZ $-4 ;КОЛИЧЕСТВО СЕКТОРОВ В КЛАСТЕРЕ ДОЛЖНО БЫТЬ СТЕПЕНЬЮ 2
DEC A
JR NZ,$+3 ;ПРОВЕРИЛИ КОЛИЧЕСТВО БИТ
INC E ;+1, ЕСТЬ ТАКОЕ
LD A,(IX+0X0E)
OR (IX+0X0F)
JR Z,$+3 ;КОЛИЧЕСТВО ЗАРЕЗЕРВИРОВАННЫХ СЕКТОРОВ ДОЛЖНО БЫТЬ >0
INC E ;+1, ЕСТЬ ТАКОЕ
LD A,(IX+0X13)
OR (IX+0X14)
JR NZ,$+3 ;КОЛИЧЕСТВО СЕКТОРОВ НА РАЗДЕЛЕ ДЛЯ ФАТ16?
INC E
LD A,(IX+0X20)
OR (IX+0X21)
OR (IX+0X22)
OR (IX+0X23)
JR NZ,$+3 ;КОЛИЧЕСТВО СЕКТОРОВ НА РАЗДЕЛЕ ДЛЯ ФАТ32?
INC E ;ОДНО ИЗ НИХ ДОЛЖНО БЫТЬ =0, ДРУГОЕ >0
LD A,(IX+0X15)
AND 0XF0
CP 0XF0
JR NZ,$+3 ;СТАРШИЕ БИТЫ ДОЛЖНЫ БЫТЬ В 1
INC E
LD A,E
CP 4 ;УСЛОВИЯ СОВПАЛИ?
LD A,0XDD ;FAT НЕ НАЙДЕН
JP NZ,WR_STAT
LD A,0XFF
LD (CAL_FAT),A ;ТИП ФАТ ПОКА НЕ ОПРЕДЕЛЕН
LD DE,0
LD B,D
LD C,E
RDFAT00 LD (STARTRZ),DE
LD (STARTRZ+2),BC ;ПОЛОЖИЛИ НОМЕР СТАРТОВОГО СЕКТОРА РАЗДЕЛА
CALL LOADLST ;ЗАГРУЗИЛИ ЕГО
LD HL,0
LD DE,(BUF512+0X16) ;BPB_FATSZ16
LD A,D
OR E
JR NZ,RDFAT01 ;ЕСЛИ НЕ FAT12/16 (BPB_FATSZ16=0)
LD DE,(BUF512+0X24)
LD HL,(BUF512+0X26) ;BPB_FATSZ32
;ТО БЕРЕМ ИЗ СМЕЩЕНИЯ +36
RDFAT01 LD (SEC_FAT+2),HL
LD (SEC_FAT),DE ;ЧИСЛО СЕКТОРОВ НА FAT-ТАБЛИЦУ
LD HL,0
LD DE,(BUF512+0X13) ;BPB_TOTSEC16
LD A,D
OR E
JR NZ,RDFAT02 ;ЕСЛИ НЕ FAT12/16 (BPB_TOTSEC16=0)
LD DE,(BUF512+0X20)
LD HL,(BUF512+0X22) ;BPB_TOTSEC32
;ТО БЕРЕМ ИЗ СМЕЩЕНИЯ +32
RDFAT02 LD (SEC_DSC+2),HL
LD (SEC_DSC),DE ;К-ВО СЕКТОРОВ НА ДИСКЕ/РАЗДЕЛЕ
;ВЫЧИСЛЯЕМ ROOTDIRSECTORS
LD BC,(BUF512+0X0B) ;BPB_BYTSPERSEC
LD DE,(BUF512+0X11) ;BPB_ROOTENTCNT
LD HL,0
LD A,D
OR E
JR Z,RDFAT03
LD B,H
LD C,L
LD A,0X10
CALL BCDE_A
EX DE,HL
;ЭТО РЕАЛИЗОВАНА ФОРМУЛА
;ROOTDIRSECTORS=((BPB_ROOTENTCNT*32)+(BPB_BYTSPERSEC-1))/BPB_BYTSPERSEC
;В HL=ROOTDIRSECTORS. ЕСЛИ FAT32, ТО HL=0 ВСЕГДА
RDFAT03 PUSH HL ;ROOTDIRSECTORS
LD (ROOTSEC),HL
LD A,(BUF512+0X10)
LD DE,(SEC_FAT)
LD HL,(SEC_FAT+2)
DEC A
EX DE,HL
ADD HL,HL
EX DE,HL
ADC HL,HL
DEC A
JR NZ,$-6
POP BC ;ПОЛНЫЙ РАЗМЕР FAT-ОБЛАСТИ В СЕКТОРАХ
CALL HLDEPBC ;ПРИБАВИЛИ ROOTDIRSECTORS
LD BC,(BUF512+0X0E) ;BPB_RSVDSECCNT
LD (RSVDSEC),BC
CALL HLDEPBC ;ПРИБАВИЛИ BPB_RESVDSECCNT
LD (FRSTDAT),DE
LD (FRSTDAT+2),HL ;ПОЛОЖИЛИ НОМЕР ПЕРВОГО СЕКТОРА ДАННЫХ
LD B,H
LD C,L
LD HL,SEC_DSC ;BCDE+32-ое ЧИСЛО ПО АДРЕСУ HL
CALL BCDEHLM ;ВЫЧЛИ ИЗ ПОЛНОГО К-ВА СЕКТОРОВ РАЗДЕЛА
LD A,(BUF512+0X0D)
LD (BYTSSEC),A
CALL BCDE_A ;РАЗДЕЛИЛИ НА К-ВО СЕКТОРОВ В КЛАСТЕРЕ
LD (CLS_DSC),DE
LD (CLS_DSC+2),BC ;ПОЛОЖИЛИ КОЛ-ВО КЛАСТЕРОВ НА РАЗДЕЛЕ
LD A,(CAL_FAT)
CP 0XFF
JR NZ,RDFAT04
;ОПРЕДЕЛЕНИЕ ТИПА FAT ПРИ ОТСУСТВИИ MBR
LD DE,(SEC_FAT-1)
LD BC,(SEC_FAT+1)
LD E,0 ;BCDE=КОЛИЧЕСТВО СЕКТОРОВ *0X100
PUSH BC
PUSH DE ;СОХРАНИЛИ
SRL B
RR C
RR D
RR E ;BCDE=КОЛИЧЕСТВО СЕКТОРОВ *0X80
LD HL,CLS_DSC ;КОЛИЧЕСТВО КЛАСТЕРОВ НА FAT
PUSH HL ;СОХРАНИЛИ
CALL HLBCDEM ;КОЛИЧЕСТВО КЛАСТЕРОВ-(КОЛИЧЕСТВО СЕКТОРОВ*0X80)
LD A,E
AND 0X80 ;КОЛИЧЕСТВО МЕНЕЕ 128 КЛАСТЕРОВ В СЕКТОРЕ ДЛЯ FAT32
OR D
OR C
OR B
LD A,2
POP HL
POP DE
POP BC
JR Z,RDFAT04 ;FAT32 ЕСЛИ ФЛАГ Z=0
CALL HLBCDEM ;КОЛИЧЕСТВО КЛАСТЕРОВ-(КОЛИЧЕСТВО СЕКТОРОВ*0X100)
LD A,D
OR C
OR B
LD A,1
JR Z,RDFAT04 ;FAT16 ЕСЛИ ФЛАГ Z=0
XOR A ;ИНАЧЕ FAT12
;ДЛЯ FAT12/16 ВЫЧИСЛЯЕМ АДРЕС ПЕРВОГО СЕКТОРА ДИРЕКТОРИИ
;ДЛЯ FAT32 БЕРЕМ ПО СМЕЩЕМИЮ +44, НА ВЫХОДЕ BCDE-СЕКТОР ROOTDIR
RDFAT04 LD (CAL_FAT),A ;УТОЧНИЛИ ТИП ФАТА
EX AF,AF'
LD DE,(RSVDSEC)
LD BC,0
LD HL,STARTRZ
CALL BCDEHLP
LD (FATSTR),DE
LD (FATSTR+2),BC ;ВЫЧИСЛИЛИ И ПОЛОЖИЛИ НОМЕР СЕКТОРА НАЧАЛА FAT-TАБЛИЦ
EX AF,AF'
AND A
LD DE,0
LD B,D
LD C,E
JR Z,FSRROO2 ;FAT12-NONE
DEC A
JR Z,FSRROO2 ;FAT16
LD DE,(BUF512+0X2C)
LD BC,(BUF512+0X2E) ;FAT32
FSRROO2 LD (ROOTCLS),DE
LD (ROOTCLS+2),BC ;ПОЛОЖИЛИ НОМЕР КЛАСТЕР ROOT ДИРЕКТОРИИ
XOR A
LD (LVL_DIR),A ;НАЧИНАЕМ С ROOT ДИРЕКТОРИИ
LD HL,(ADRPATH) ;ВЕРНУЛИ АДРЕС СТРОКИ ПУТИ ДО ФАЙЛА
FINDFL1 PUSH BC
PUSH DE ;СОХРАНИЛИ НОМЕР КЛАСТЕРА
CALL FNDBUF ;РАСПАКОВКА ЧАСТИ ТЕКСТОВОЙ СТРОКИ ДЛЯ СОЗДАНИЯ МАСКИ ПОИСКА
POP DE
POP BC ;ВОССТАНОВИЛИ НОМЕР КЛАСТЕРА
PUSH HL ;СОХРАНИЛИ ТЕКУЩИЙ АДРЕС ТЕКСТОВОЙ СТРОКИ
LD HL,TDIRCLS ;АДРЕС ТАБЛИЦЫ КЛАСТЕРОВ ТЕКУЩЕЙ ДИРЕКТОРИИ
LD A,D
OR E
OR B
OR C
CALL SAVEZP ;СОХРАНИЛИ В ТАБЛИЦУ НОМЕР ТЕКУЩЕГО КЛАСТЕРА
JR Z,LASTCLS ;ЕСЛИ НОМЕР КЛАСТЕРА 0, ТО ЭТО ROOT ДИРА (ДЛЯ ФАТ12/16)
NEXTCLS PUSH HL
CALL RDFATZP ;ЧИТАЕМ СЛЕДУЩИЙ НОМЕР КЛАСТЕРА ИЗ ЦЕПОЧКИ ДИРЕКТОРИИ
CALL LST_CLS ;ПРОВЕРЯЕМ НА КОНЕЦ ЦЕПОЧКИ
POP HL
JR C,LASTCLS
CALL SAVEZP ;ЕСЛИ НЕ ПОСЛЕДНИЙ СОХРАНЯЕМ В ТАБЛИЦУ
JR NEXTCLS ;СЛЕДУЮЩИЙ НОМЕР КЛАСТЕРА
LASTCLS LD BC,0XFFFF
CALL SAVEZP ;КЛАДЕМ МАРКЕР КОНЦА ЦЕПОЧКИ
EXX
LD HL,LVL_DIR
LD A,(HL) ;ТЕКУЩИЙ УРОВЕНЬ ДИРЕКТОРИИ
INC (HL) ;СЛЕДУЮЩИЙ УРОВЕНЬ ДИРЕКТОРИИ
AND A
LD BC,0 ;КОЛИЧЕСТВО ЗАПИСЕЙ ROOT ДИРЕКТОРИИ
JR NZ,LASTCLS1
LD A,(CAL_FAT)
CP 2
JR NC,LASTCLS1
LD HL,(ROOTSEC) ;УЖЕ НЕ ROOT ДИРЕКТОРИЯ
ADD HL,HL
ADD HL,HL
ADD HL,HL
ADD HL,HL
ADD HL,HL
LD B,H
LD C,L
LASTCLS1 EXX
FINDFL INC BC ;ИЩЕМ ПО ЗАДАННОЙ МАСКЕ НАЧИНАЯ С 0
CALL RDDIRSC ;ГРУЗИМ ПО НОМЕРУ ОПИСАТЕЛЯ СЕКТОР ДИРЕКТОРИИ
LD A,C
AND 0X0F ;В СЕКТОРЕ МАКСИМУМ 16 ОПИСАТЕЛЕЙ
LD E,A
LD D,0
EX DE,HL
ADD HL,HL
ADD HL,HL
ADD HL,HL
ADD HL,HL
ADD HL,HL
ADD HL,DE ;ПОЛУЧИЛИ АДРЕС НУЖНОГО ОПИСАТЕЛЯ
EXX
DEC BC
LD A,B
OR C ;ПРОВЕРКА НА ОКОНЧАНИЕ ROOT ДИРЕКТОРИИ
EXX
LD A,0XAA
JP Z,WR_STAT
LD A,(HL) ;ПРОВЕРЯЕМ ПЕРВЫЙ БАЙТ ИМЕНИ ОПИСАТЕЛЯ
AND A
LD A,0XAA ;ЕСЛИ БАЙТ =0, ТО
JP Z,WR_STAT ;ПЕРЕХОД ПО ОШИБКЕ = ФАЙЛ НЕ НАЙДЕН
PUSH HL
PUSH BC
CALL COMPARE ;СРАВНИВАЕМ С ЗАДАННОЙ МАСКОЙ
POP BC
POP DE
PUSH DE
POP IX ;СОДЕРЖИМОЕ IX=АДРЕС ОПИСАТЕЛЯ
JR NZ,FINDFL ;НЕ СОВПАДАЕТ, ПЕРЕХОДИМ К СЛЕДУЮЩЕМУ ОПИСАТЕЛЮ
CALL RD_CLAS ;ЗАБИРАЕМ НОМЕР КЛАСТЕРА ИЗ НАЙДЕННОГО ОПИСАТЕЛЯ
EX (SP),HL ;ВОССТАНОВИЛИ ТЕКУЩИЙ АДРЕС В СТРОКЕ ПУТИ ДО ФАЙЛА
INC SP
INC SP ;МАСКИРОВКА НА СТЕКЕ АДРЕСА РАЗМЕРА В БАЙТАХ ТЕКУЩЕГО ФАЙЛА
LD A,(HL)
AND A ;ТЕКСТОВАЯ СТРОКА КОНЧИЛАСЬ?
JR NZ,FINDFL1 ;ЕСЛИ НЕТ, ТО ИЩЕМ ДАЛЬШЕ
LD A,(IX+0X0B) ;ПРОВЕРЯЕМ ЭТО ДИРА ИЛИ ФАЙЛ?
AND 0X10
LD A,0XAA ;ЕСЛИ ДИРА, ТО ОШИБКА
JP NZ,WR_STAT ;ТЕКСТОВАЯ СТРОКА ДОЛЖНА УКАЗЫВАТЬ НА ФАЙЛ
FINDFL2 LD A,IYL
DEC IYL
IF NGS=1
OUT (MPAG),A ;ВКЛЮЧАЕМ ЗАДАННУЮ СТРАНИЦУ ДЛЯ ЗАГРУЗКИ
ELSE
CALL PAGE_7FFD
ENDIF
LD HL,ADR_LOADING
FINDFL3 IF CONV_NUMSEC=1
PUSH BC
PUSH DE
PUSH HL
CALL REALSEC ;КОНВЕРСИЯ НОМЕРА КЛАСТЕРА В НОМЕР СЕКТОРА
POP HL
CALL SAVEZP ;УКЛАДКА В БУФЕР НОМЕРА СЕКТОРА
POP DE
POP BC
ELSE
CALL SAVEZP ;УКЛАДКА В БУФЕР НОМЕРА КЛАСТЕРА
ENDIF
LD A,H
AND A
JR Z,FINDFL2 ;ПРОВЕРКА НА КОНЕЦ ПАМЯТИ
PUSH HL
CALL RDFATZP
CALL LST_CLS
POP HL
JR NC,FINDFL3
XOR A
LD B,0XFF
JP SAVEZP ;КОНЕЦ ЦЕПОЧКИ СТАРШИЙ БАЙТ НОМЕРА = FF
SAVEZP LD (HL),E
INC HL
LD (HL),D
INC HL
LD (HL),C
INC HL
LD (HL),B
INC HL
RET
LOADZP LD E,(HL)
INC HL
LD D,(HL)
INC HL
LD C,(HL)
INC HL
LD B,(HL)
INC HL
RET
;ЧТЕНИЕ СЕКТОРА DIR ПО НОМЕРУ BC
RDDIRSC PUSH BC
LD D,B
LD E,C
LD BC,0
LD A,0X10
CALL BCDE_A
LD A,E
PUSH AF
LD A,(BYTSSEC)
PUSH AF
CALL BCDE_A
LD HL,TDIRCLS
EX DE,HL
ADD HL,HL
ADD HL,HL
ADD HL,DE
CALL LOADZP
CALL REALSEC
POP AF
DEC A
LD L,A
POP AF
AND L
LD L,A
LD H,0
ADD HL,DE
EX DE,HL
LD HL,0
ADC HL,BC
LD B,H
LD C,L
CALL LOADLST
POP BC
RET
;ПРОВЕРКА НА ПОСЛЕДНИЙ КЛАСТЕР В ЦЕПОЧКЕ
LST_CLS LD A,(CAL_FAT) ;ЗАВИСИТ ОТ РАЗРЯДНОСТИ ФАТА
AND A
JR NZ,LST_CL1
LD HL,0X0FF7 ;ПРОВЕРКА ДЛЯ ФАТ12
SBC HL,DE
RET
LST_CL1 DEC A
JR NZ,LST_CL2
LST_CL3 LD HL,0XFFF7 ;ПРОВЕРКАМ ДЛЯ ФАТ16 И МЛАДШИХ БИТ ФАТ32
SBC HL,DE
RET
LST_CL2 LD HL,0X0FFF ;ПРОВЕРКА ДЛЯ СТАРШИХ БИТ ФАТ32
SBC HL,BC
RET NZ
JR LST_CL3
;ЧТЕНИЕ СЛЕДУЮЩЕГО НОМЕРА КЛАСТЕРА В ЦЕПОЧКЕ
RDFATZP LD A,(CAL_FAT) ;ЧТЕНИЕ ЗАВИСИТ ОТ РАЗРАДНОСТИ ФАТА
AND A
JR Z,RDFATS0 ;ПЕРЕХОД ВПЕРЕД ДЛЯ ФАТ12
DEC A
JR Z,RDFATS1 ;ПЕРЕХОД ВПЕРЕД ДЛЯ ФАТ16
EX DE,HL ;ЗДЕСЬ ЧТЕНИЕ ДЛЯ ФАТ32
ADD HL,HL
EX DE,HL
LD HL,0
ADC HL,BC
ADC HL,BC ;УМНОЖИЛИ НОМЕР КЛАСТЕРА НА 2
LD A,E
LD E,D
LD D,L
LD C,H
LD B,0 ;РАЗДЕЛИЛИ НОМЕР КЛАСТЕРА НА 256
CALL RDFATS2 ;ЧИТАЕМ МЛАДШИЕ 16 БИТ ИСПОЛЬЗУЯ ЧТЕНИЕ ДЛЯ ФАТ16
INC HL
LD C,(HL)
INC HL
LD B,(HL) ;ПРОЧИТАЛИ ПОСЛЕДУЮЩИЕ СТАРШИЕ 16 БИТ
RET
;ЧТЕНИЕ 16 БИТНОГО НОМЕРА КЛАСТЕРА ИЗ ЦЕПОЧКИ ДЛЯ ФАТ16
RDFATS1 LD BC,0
LD A,E
LD E,D
LD D,C ;РАЗДЕЛИЛИ НОМЕР КЛАСТЕРА НА 256, СТАРШИЕ 16 БИТ =0
RDFATS2 PUSH AF ;ОБЩЕЕ ЧТЕНИЕ 16 БИТНОГО НОМЕРА КЛАСТЕРА ДЛЯ ФАТ16/32
PUSH BC
LD HL,FATSTR
CALL BCDEHLP ;ПРИБАВИЛИ СМЕЩЕНИЕ ОТ НАЧАЛА ФАТ ТАБЛИЦЫ
CALL LOADLST ;ЗАГРУЗИЛИ ВЫЧИСЛЕННЫЙ НОМЕР СЕКТОРА
POP BC
POP AF
LD E,A
LD D,0
ADD HL,DE
ADD HL,DE ;ВЫЧИСЛИЛИ СМЕЩЕНИЕ ДО НУЖНОГО НОМЕРА В ЗАГРУЖЕННОМ СЕКТОРЕ
LD E,(HL)
INC HL
LD D,(HL) ;ПОЛУЧИЛИ 16 БИТ НОМЕРА КЛАСТЕРА
RET
;ЧТЕНИЕ 12 БИТНОГО НОМЕРА КЛАСТЕРА ИЗ ЦЕПОЧКИ ДЛЯ ФАТ12
RDFATS0 LD H,D
LD L,E
ADD HL,HL
ADD HL,DE ;HL=HL*3
SRL H
RR L ;HL=HL/2 - В ИТОГЕ УМНОЖИЛИ НОМЕР КЛАСТЕРА НА 1,5
LD A,E ;A-НАМ ИНТЕРЕСЕН ТОЛЬКО БИТ НОМЕР СТАРОГО НОМЕРА КЛАСТЕРА
LD E,H
LD D,0
LD B,D
LD C,D ;РАЗДЕЛИЛИ НОМЕР КЛАСТЕРА НА 256
SRL E
PUSH AF
PUSH HL
LD HL,FATSTR
CALL BCDEHLP ;ПРИБАВИЛИ СМЕЩЕНИЕ ОТ НАЧАЛА ФАТ ТАБЛИЦЫ
CALL LOADLST ;ЗАГРУЗИЛИ ВЫВЧИСЛЕННЫЙ СЕКТОР
POP BC
LD A,B
AND 1
LD B,A ;BC=СМЕЩЕНИЕ В ЗАГРУЖЕННОМ СЕКТОРЕ
ADD HL,BC ;HL=АДРЕС ОТКУДА ЧИТАТЬ БАЙТЫ НОМЕРА КЛАСТЕРА
LD B,(HL) ;ПРОЧИТАЛИ МЛАДШУЮ ЧАСТЬ НОМЕРА КЛАСТЕРА
INC HL ;АДРЕС СЛЕДУЮЩЕГО БАЙТА
LD A,H
CP HIGH (BUF512)+2 ;ПРОВЕРКА НА ПЕРЕХОД ГРАНИЦЫ ЗАГРУЖЕННОГО СЕКТОРА
JR NZ,RDFATS4
PUSH BC ;ВЫХОД ЗА ПРЕДЕЛЫ ТЕКУЩЕГО ЗАГРУЖЕННОГО СЕКТОРА
LD BC,0
INC DE
CALL LOADLST ;ЗАГРУЖАЕМ СЛЕДУЮЩИЙ СЕКТОР ФАТ ТАБЛИЦЫ
POP BC
RDFATS4 POP AF
LD D,(HL) ;ЧИТАЕМ СТАРШИЕ БИТЫ НОМЕРА КЛАСТЕРА
LD E,B ;ТЕПЕРЬ DE=НОМЕР СЛЕДУЮЩЕГО КЛАСТЕРА В ЦЕПОЧКЕ
LD BC,0
RRA ;ПРОВЕРЯЕМ БИТ 0 СТАРОГО НОМЕРА КЛАСТЕРА
JR NC,RDFATS3
SRL D ;СДВИГАЕМ НОМЕР ПРОЧИТАННОГО НОМЕРА КЛАСТЕРА В МЛАДШИЕ 12 БИТ
RR E
SRL D
RR E
SRL D
RR E
SRL D
RR E
RDFATS3 LD A,D
AND 0X0F
LD D,A ;СБРОСИЛИ НЕЗНАЧАЩИЕ СТАРШИЕ 4 БИТА У ПОЛУЧЕННОГО НОМЕРА КЛАСТЕРА
RET
;ВЫЧИСЛЕНИЕ РЕАЛЬНОГО СЕКТОРА
;НА ВХОДЕ BCDE=НОМЕР КЛАСТЕРА FAT
;НА ВЫХОДЕ BCDE=НОМЕР РЕАЛЬНОГО СЕКТОРА
REALSEC LD A,B
OR C
OR D
OR E
JR NZ,REALSE1 ;BCDE=0?
LD HL,SEC_FAT ;ЭТО ROOT ДИРЕКТОРИЯ У ФАТ12/16
LD DE,(FATSTR) ;МЕСТОПОЛОЖЕНИЕ ROOT ДИРЫ СРАЗУ ПОСЛЕ ФАТ ТАБЛИЦЫ
LD BC,(FATSTR+2)
PUSH HL
CALL BCDEHLP ;ПРИБАВИЛИ К НАЧАЛУ ФАТ ТАБЛИЦЫ ЕЕ РАЗМЕР
POP HL
JP BCDEHLP ;ПРИБАВИЛИ ЕЩЕ РАЗ И ПОЛУЧИЛИ НОМЕР СЕКТОРА НАЧАЛА ROOT ДИРЫ
REALSE1 LD HL,0XFFFE
EX DE,HL
ADD HL,DE
EX DE,HL
INC HL
ADC HL,BC ;HLDE=НОМЕР КЛАСТЕРА-2
LD A,(BYTSSEC) ;НУЖНО УМНОЖИТЬ НА РАЗМЕР КЛАСТЕРА
JR REALSE2
REALSE3 SLA E
RL D
RL L
RL H
REALSE2 RRCA
JR NC,REALSE3 ;УМНОЖИЛИ НА РАЗМЕР КЛАСТЕРА
LD B,H
LD C,L
LD HL,STARTRZ
CALL BCDEHLP ;ПРИБАВИЛИ СМЕЩЕНИЕ ОТ НАЧАЛА ДИСКА
LD HL,FRSTDAT
JP BCDEHLP ;ПРИБАВИЛИ СМЕЩЕНИЕ ОТ НАЧАЛА РАЗДЕЛА
;BCDE=BCDE/512
BCDE200 LD E,D
LD D,C
LD C,B
LD B,0
LD A,2
JR BCDE_A
;BCDE>>A=BCDE
BCDE_A1 SRL B
RR C
RR D
RR E
BCDE_A RRCA
JR NC,BCDE_A1
RET
;(ADR)-BCDE=BCDE
BCDEHLM LD A,(HL)
INC HL
SUB E
LD E,A
LD A,(HL)
INC HL
SBC A,D
LD D,A
LD A,(HL)
INC HL
SBC A,C
LD C,A
LD A,(HL)
SBC A,B
LD B,A
RET
;(ADR)+BCDE=BCDE
BCDEHLP LD A,(HL)
INC HL
ADD A,E
LD E,A
LD A,(HL)
INC HL
ADC A,D
LD D,A
LD A,(HL)
INC HL
ADC A,C
LD C,A
LD A,(HL)
ADC A,B
LD B,A
RET
;HLDE+BC=HLDE
HLDEPBC EX DE,HL
ADD HL,BC
EX DE,HL
LD BC,0
ADC HL,BC
RET
;BCDE-(ADR)=BCDE
HLBCDEM LD A,E
SUB (HL)
INC HL
LD E,A
LD A,D
SBC A,(HL)
INC HL
LD D,A
LD A,C
SBC A,(HL)
INC HL
LD C,A
LD A,B
SBC A,(HL)
LD B,A
RET
;ГРУЗИЛКА ОДНОГО СЕКТОРА
LOADLST CALL CPNUMSC ;ПРОВЕРКА НОМЕРА СЕКТОРА ЗАГРУЖЕННОГО В БУФЕР
JR NZ,LOADLST1
LD HL,BUF512 ;В БУФЕРЕ УЖЕ ЗАГРУЖЕН УКАЗАННЫЙ СЕКТОР
RET
LOADLST1 LD (LSTLOAD+2),BC
LD (LSTLOAD),DE ;СОХРАНИЛИ НОМЕР СЕКТОРА ЗАГРУЖАЕМОГО В БУФЕР
LD HL,BUF512 ;АДРЕС БУФЕРА СЕКТОРА
LD A,1 ;ГРУЗИТЬ 1 СЕКТОР
PUSH HL
CALL RDMULTI ;ЗАГРУЗИЛИ СЕКТОР
POP HL ;НА ВЫХОДЕ HL=АДРЕС НАЧАЛА БУФЕРА ЗАГРУЖЕННОГО СЕКТОРА
RET
;ПРОВЕРКА НА УЖЕ ЗАГРУЖЕННЫЙ СЕКТОР
CPNUMSC LD HL,LSTLOAD
LD A,(HL)
INC HL
CP E
RET NZ
LD A,(HL)
INC HL
CP D
RET NZ
LD A,(HL)
INC HL
CP C
RET NZ
LD A,(HL)
CP B
RET
;ПОДАЧА КОМАНДЫ В SD КАРТУ БЕЗ ПАРАМЕТРОВ
OUTCOM PUSH BC
IF NGS=1
LD BC,0X0600+SD_SEND ;ВЫДАТЬ В ПОРТ 6 БАЙТ
ELSE
LD BC,0X600+P_DATA
ENDIF
OTIR
POP BC
RET
;ВЫДАЧА В ПОРТ SD КАРТЫ КОМАНДЫ С ПАРАМЕТРОМ 0
OUT_COM PUSH BC
IF NGS=1
LD BC,SD_SEND
ELSE
CALL CS__LOW
LD BC,P_DATA
ENDIF
OUT (C),A ;ОТПРАВИЛИ КОД КОМАНДЫ
XOR A
OUT (C),A ;БИТЫ 31-24 ПАРАМЕТРА
NOP
OUT (C),A ;БИТЫ 23-16 ПАРАМЕТРА
NOP
OUT (C),A ;БИТЫ 15-8 ПАРАМЕТРА
NOP
OUT (C),A ;БИТЫ 7-0 ПАРАМЕТРА
DEC A
OUT (C),A ;БЕЗ CRC16
POP BC
RET
SECM200 PUSH HL
PUSH BC
LD A,CMD_58
CALL OUT_COM
CALL IN_OOUT
IF NGS=1
LD BC,SD_RSTR
ELSE
LD BC,P_DATA
ENDIF
IN H,(C)
NOP
IN A,(C)
NOP
IN A,(C)
NOP
IN A,(C)
BIT 6,H
POP HL
JR NZ,SECN200
EX DE,HL
ADD HL,HL
EX DE,HL
ADC HL,HL
LD H,L
LD L,D
LD D,E
LD E,0
SECN200 LD A,CMD_18
IF NGS=1
LD C,SD_SEND
ELSE
LD C,P_DATA
ENDIF
OUT (C),A
NOP
OUT (C),H
NOP
OUT (C),L
NOP
OUT (C),D
NOP
OUT (C),E
LD A,0XFF
OUT (C),A
POP HL
RET
IN_OOUT EXX
LD DE,0X20FF
IN_WAIT IF NGS=1
IN A,(SD_RSTR)
ELSE
IN A,(P_DATA)
ENDIF
CP E
JR NZ,IN_EXIT
IN_NEXT DEC D
JR NZ,IN_WAIT
IN_EXIT EXX
RET
CMD00 DB 0X40,0X00,0X00,0X00,0X00,0X95;GO_IDLE_STATE
CMD08 DB 0X48,0X00,0X00,0X01,0XAA,0X87;SEND_IF_COND
CMD16 DB 0X50,0X00,0X00,0X02,0X00,0XFF;SET_BLOCKEN
;МНОГО СЕКТОРНОЕ ЧТЕНИЕ С SD КАРТЫ
RDMULTI EX AF,AF'
CALL SECM200
EX AF,AF'
IF NGS=1
LD BC,SD_RSTR
ELSE
LD BC,P_DATA
ENDIF
RDMULT1 EX AF,AF'
CALL IN_OOUT
CP 0XFE
JR NZ,$-5
INIR
NOP
INIR
NOP
IN A,(C)
NOP
IN A,(C)
EX AF,AF'
DEC A
JR NZ,RDMULT1
LD A,CMD_12
CALL OUT_COM
CALL IN_OOUT
INC A
JR NZ,$-4
RET
;ВЫБОРКА НОМЕРА КЛАСТЕРА ИЗ ФАЙЛОВОГО ОПИСАТЕЛЯ
RD_CLAS EX DE,HL
LD DE,0X14 ;СТАРШИЕ 16 БИТ ЧИТАЕМ ИЗ СМЕЩЕНИЯ +20
ADD HL,DE
LD C,(HL)
INC HL
LD B,(HL)
LD E,5 ;МЛАДШИЕ 16 БИТ ЧИТАЕМ ИЗ СМЕЩЕНИЯ +26
ADD HL,DE
LD E,(HL)
INC HL
LD D,(HL)
INC HL
RET
PAGE_7FFD PUSH BC
LD BC,CONF_128
OR 0X10
OUT (C),A
POP BC
RET
;ПРОВЕРКА ПО МАСКЕ
COMPARE LD DE,FB_EXT
LD B,0X0B
LD A,(DE)
CP (HL)
RET NZ
INC HL
INC DE
DJNZ $-5
RET
;РАСПАКОВЩИК ПУТИ К ФАЙЛУ
FNDBUF LD BC,0X0802
LD DE,FB_EXT
FNDBUF4 LD A,(HL)
INC HL
CP "."
JR Z,FNDBUF2
CP "/"
JR Z,FNDBUF5
LD (DE),A
INC DE
DJNZ FNDBUF4
LD A,(HL)
AND A
RET Z
INC HL
JR FNDBUF3
FNDBUF5 LD A,C
AND A
RET Z
FNDBUF2 LD A,B
AND A
JR Z,FNDBUF3
LD A," "
LD (DE),A
INC DE
DJNZ $-2
FNDBUF3 LD B,3
DEC C
DEC HL
LD A,(HL)
CP "/"
JR Z,FNDBUF4
INC HL
JR FNDBUF4