; LAST UPDATE: 07.07.2021 savelij
include ../../macros.a80
include ../../define.a80
include ../../global_vars.a80
include ../../ports_ngs.a80
include ../../sdcomand.a80
include ../../ports_ide.a80
include ../../nums_devices.a80
DRV_VAR EQU 0X4000
ORG DRV_VAR+0X200
INIT_VAR $
include ../../fat_vars.a80
ORG DRV_VAR+0X300
BUF_512_ EQU DRV_VAR ;200 БУФЕР СЕКТОРА
NUM_DEVICE EQU DRV_VAR+0X2FF ;1 НОМЕР УСТРОЙСТВА ДЛЯ ЗАПУСКА КОДА
MAS_SLA EQU NUM_DEVICE-1 ;1 МАСКА ДЛЯ MASTER/SLAVE
LOADSCS1 EQU MAS_SLA-2 ;2 АДРЕС ВЫЗЫВАЕМОГО ДРАЙВЕРА
LENGHT EQU LOADSCS1-2 ;2 ДЛИНА ФАЙЛА В БАЙТАХ
;[ТОЧКА ВХОДА]
;НА ВХОДЕ: A-НОМЕР ВЫБРАННОГО УСТРОЙСТВА
; BCDE-НОМЕР КЛАСТЕРА ЗАПУСКАЕМОГО ФАЙЛА
DI
LD A,(NUM_DEVICE)
CP _SD_SDZ
LD HL,READ_SD ;ДРАЙВЕР SD ZC КАРТЫ
JR Z,SETLOADER
CP _SD_SDG
LD HL,READNGS ;ДРАЙВЕР SD NGS КАРТЫ
JR Z,SETLOADER
CP _HDD_NEMO_MASTER
LD HL,RD_HDDN ;ДРАЙВЕР HDD NEMO
JR Z,SETLOADER
CP _HDD_SMUC_MASTER
LD HL,RD_HDDS ;ДРАЙВЕР HDD SMUC
JR Z,SETLOADER
CP _HDD_DIVIDE_MASTER
LD HL,RD_HDDD ;ДРАЙВЕР HDD DIVIDE
JR Z,SETLOADER
LD HL,RD_HDDP ;ДРАЙВЕР HDD PROFI
SETLOADER LD (LOADSCS1),HL ;УСТАНОВИЛИ АДРЕС ЧИТАЛКИ СЕКТОРОВ
LD A,(MAS_SLA)
AND A
LD A,0XE0
JR Z,SETMASL
LD A,0XF0
SETMASL LD (MAS_SLA),A
LD BC,(FILE_SRC+0X14)
LD (AFILCLS+2),BC
LD DE,(FILE_SRC+0X1A)
LD (AFILCLS),DE
LD A,(FILE_SRC+9)
CP "P"
JP Z,RUNSPG2 ;ПЕРЕХОД НА ЗАПУСК SPG ФАЙЛА
CP "N"
JP Z,RUNSNA ;ПЕРЕХОД НА ЗАПУСК SNA ФАЙЛА
CALL REALSEC ;ПРЕОБРАЗОВАЛИ В НОМЕР СЕКТОРА
CALL LOADLST ;ЗАГРУЗИЛИ В БУФЕР
EXX
LD HL,(BUF_512_+9)
LD (0X5D45),HL ;АДРЕС СТАРТА КОДА
LD HL,(BUF_512_+0X0B)
LD (LENGHT),HL ;УСТАНОВКА ДЛИНЫ ФАЙЛА В БАЙТАХ
LD DE,0X11
ADD HL,DE ;ПРОПУСК HOBETA ЗАГОЛОВКА
LD A,L
AND A
JR Z,READ01 ;ЕСЛИ МЛАДШИЙ БАЙТ НЕ 0
INC H ;СТАРШИЙ +1
READ01 LD A,H
SRL A ;ДЕЛИМ НА 2 ИБО НА ФАТЕ СЕКТОР 512 БАЙТ
ADC A,0 ;УЧИТЫВАЕМ ЧЕТ/НЕЧЕТ
DEC A ;ПЕРВЫЙ СЕКТОР ЗАГРУЖЕН, ГРУЗИТЬ НА 1 МЕНЬШЕ
EXX
JP Z,LDIRBUF ;ЕСЛИ СЕКТОР 1 ПЕРЕНОС И ЗАПУСК
DEC A
LD IXL,A ;ЗАПОМНИЛИ КОЛИЧЕСТВО СЕКТОРОВ-1
JP Z,READ08 ; если файл влез в 2 сектора
EXX
CALL LD_ONES ;ПЕРЕНОС ОСТАТКОВ ПЕРВОГО СЕКТОРА
PUSH DE ;АДРЕС КУДА ДАЛЕЕ ГРУЗИТЬ
EXX
LD HL,1 ;ОДИН СЕКТОР УЖЕ ЗАГРУЖЕН
ADD HL,DE ;ДАЛЕЕ ГРУЗИТЬ СО СЛЕДУЮЩЕГО СЕКТОРА
EX DE,HL
JR NC,READ04
INC BC ;BCDE=BCDE+1
READ04 POP HL ;В HL АДРЕС ДЛЯ ПРОДОЛЖЕНИЯ ЗАГРУЗКИ
LD IY,(SecPerClus) ;LY=КОЛ-ВО СЕКТОРОВ В КЛАСТЕРЕ
LD A,IXL
CP IYL ;СЕКТОРОВ ОСТАЛОСЬ МЕНЬШЕ ЧЕМ В КЛАСТЕРЕ
JR C,READ02 ;ПЕРЕХОД НА ДОЗАГРУЗКУ ОСТАТКА СЕКТОРОВ
INC IXL
LD A,IYL
CP 2
JR C,READ07
DEC A
JR READ05
READ07 PUSH HL
LD DE,(AFILCLS)
LD BC,(AFILCLS + 2)
CALL RDFATZP ;ПОЛУЧИТЬ НОМЕР СЛЕДУЮЩЕГО КЛАСТЕРА
LD (AFILCLS),DE
LD (AFILCLS + 2),BC
CALL LST_CLS ;ПРОВЕРКА НА ОКОНЧАНИЕ FAT ЦЕПОЧКИ
POP HL
JR C,RUNLOAD ;ЕСЛИ КЛАСТЕРА ЗАКОНЧИЛИСЬ, ТО ЗАПУСК ЗАГРУЖЕННОГО
PUSH HL
CALL REALSEC ;ПРЕОБРАЗОВАНИЕ НОМЕРА КЛАСТЕРА В НОМЕР СЕКТОРА
POP HL
LD A,IXL ;СКОЛЬКО СЕКТОРОВ ОСТАЛОСЬ ЗАГРУЗИТЬ
CP IYL ;СРАВНИВАЕМ С РАЗМЕРОМ КЛАСТЕРА
JR C,READ02 ;ЕСЛИ ОСТАЛОСЬ ЗАГРУЗИТЬ СЕКТОРОВ МЕНЬШЕ ЧЕМ В КЛАСТЕРЕ, ТО ДОЗАГРУЖАЕМ ОСТАТОК
LD A,IYL ;СКОЛЬКО СЕКТОРОВ ЗАГРУЖАТЬ
READ05 CALL LOADSCS ;ЗАГРУЗКА СЕКТОРОВ
LD A,IXL ;СКОЛЬКО СЕКТОРОВ ВСЕГО ЗАГРУЖАТЬ
SUB IYL ;МИНУС СКОЛЬКО СЕКТОРОВ ТОЛЬКО ЧТО ЗАГРУЗИЛИ
JR Z,RUNLOAD ;СЕКТОРА КОНЧИЛИСЬ, ПЕРЕХОДИМ НА ЗАПУСК
LD IXL,A ;СКОЛЬКО СЕКТОРОВ ОСТАЛОСЬ ЗАГРУЗИТЬ
JR READ07 ;ПРОДОЛЖАЕМ ЗАГРУЗКУ
; размер кода в Hobeta менее 2 секторов
; копируем хвост первого сектора и догружаем из второго с переносом
READ08 EXX
CALL LD_ONES
PUSH DE
EXX
POP HL
LD IXL,1
JR READ03
;ЗАГРУЗКА КОЛИЧЕСТВА СЕКТОРОВ, ЕСЛИ ОСТАЛОСЬ МЕНЕЕ РАЗМЕРА КЛАСТЕРА
READ02 AND A
JR Z,READ03
CALL LOADSCS
READ03 PUSH HL
LD A,IXL
LD L,A
LD H,0
ADD HL,DE
EX DE,HL
JR NC,READ06
INC BC
READ06 CALL LOADLST
LD BC,(LENGHT)
EX DE,HL
LD HL,0X11
ADD HL,BC
LD B,H
LD C,L
EX DE,HL
POP DE
LD A,B
AND 1
LD B,A
OR C
JR Z,RUNLOAD
LDIR
;[ЗАПУСК ЗАГРУЖЕННОГО]
RUNLOAD LD HL,0X2758
EXX
LD IY,0X5C3A
EI
JP 0X1B7D ;ЗАПУСК ПЕРЕНЕСЕННОЙ БЕЙСИК ПРОГИ
LDIRBUF LD HL,0X200-0X11
LD DE,(BUF_512_+0X0B)
AND A
SBC HL,DE
JR NC,LDIRBUF1
CALL LD_ONES
JP RUNLOAD
LDIRBUF1 LD HL,BUF_512_+0X11
LD DE,(BUF_512_+9)
LD BC,(BUF_512_+0X0B)
LDIR
JP RUNLOAD
;[ПЕРЕНОС КУСКА ИЗ УЖЕ ЗАГРУЖЕННОГО СЕКТОРА, ЕСЛИ ФАЙЛ=501 БАЙТ И МЕНЕЕ]
LD_ONES LD HL,BUF_512_+0X11
LD DE,(BUF_512_+9)
LD BC,0X200-0X11
LDIR
RET
;[ЗАГРУЗИТЬ СЕКТОРА С ВЫБРАННОГО УСТРОЙСТВА]
LOADSCS PUSH HL
LD HL,(LOADSCS1)
EX (SP),HL
RET
; чтение файла
; BCDE - номер кластера откуда грузить
; IXL - размер кластера
; IXH - временные переменные
; IYL - количество секторов для загрузки
; IYH - смещение в кластере
LD_FILE PUSH BC ;СТАРШИЕ 16 БИТ НОМЕРА КЛАСТЕРА
PUSH DE ;МЛАДШИЕ 16 БИТ НОМЕРА КЛАСТЕРА
PUSH HL ;СОХРАНИЛИ АДРЕС ЗАГРУЗКИ
CALL REALSEC ;ПЕРЕВЕЛИ НОМЕР КЛАСТЕРА В НОМЕР СЕКТОРА
LD IX,(SecPerClus)
LD A,IYH ;СМЕЩЕНИЕ В КЛАСТЕРЕ
LD L,A
LD H,0
ADD HL,DE
EX DE,HL
JR NC,LDFILE1
INC BC ;BCDE=НОМЕР СЕКТОРА ОТКУДА ГРУЗИТЬ
LDFILE1 LD A,IYL ;КОЛИЧЕСТВО СЕКТОРОВ ДЛЯ ЗАГРУЗКИ
CP IXL ;РАЗМЕР КЛАСТЕРА
JP C,LDFILE2
LD A,IXL ;РАЗМЕР КЛАСТЕРА
LDFILE2 ADD A,IYH ;СМЕЩЕНИЕ В КЛАСТЕРЕ
CP IXL ;РАЗМЕР КЛАСТЕРА
LD A,IYL ;КОЛИЧЕСТВО СЕКТОРОВ ДЛЯ ЗАГРУЗКИ
JP C,LDFILE5
LD A,IXL ;РАЗМЕР КЛАСТЕРА
SUB IYH ;СМЕЩЕНИЕ В КЛАСТЕРЕ
LDFILE5 LD IXH,A ;TEMP VAR, СКОЛЬКО СЕКТОРОВ СЕЙЧАС ГРУЗИМ
POP HL ;ВОССТАНОВИЛИ АДРЕС ЗАГРУЗКИ
CALL LOADSCS ;ЗАГРУЗИЛИ СЕКТОРА
POP DE
POP BC ;ВОССТАНОВИЛИ НОМЕР КЛАСТЕРА
LD A,IYH ;СМЕЩЕНИЕ В КЛАСТЕРЕ
ADD A,IXH ;TEMP VAR
CP IXL ;РАЗМЕР КЛАСТЕРА
JP C,LDFILE3
SUB IXL ;РАЗМЕР КЛАСТЕРА
LDFILE3 LD IYH,A ;СМЕЩЕНИЕ В КЛАСТЕРЕ
JP C,LDFILE4
PUSH HL ;СОХРАНИЛИ АДРЕС ЗАГРУЗКИ
CALL RDFATZP ;ПРОЧИТАЛИ НОМЕР СЛЕДУЮЩЕГО КЛАСТЕРА
CALL LST_CLS ;ПРОВЕРИЛИ, А МОЖЕТ ЭТО ПОСЛЕДНИЙ КЛАСТЕР?
POP HL ;ВОССТАНОВИЛИ АДРЕС ЗАГРУЗКИ
RET C ;ЕСЛИ ПОСЛЕДНИЙ, ВЫХОДИМ
LDFILE4 LD A,IYL ;КОЛИЧЕСТВО СЕКТОРОВ ДЛЯ ЗАГРУЗКИ
SUB IXH ;TEMP VAR
RET Z
LD IYL,A ;КОЛИЧЕСТВО СЕКТОРОВ ДЛЯ ЗАГРУЗКИ
JP NZ,LD_FILE
RET
;[ПРОВЕРКА НОМЕРА КЛАСТЕРА]
LST_CLS LD A,(FATType)
AND A
JR NZ,LST_CL1
LD HL,0X0FF7
SBC HL,DE
RET
LST_CL1 DEC A
JR NZ,LST_CL2
LD HL,0XFFF7
SBC HL,DE
RET
LST_CL2 LD HL,0X0FFF
SBC HL,BC
RET NZ
LD HL,0XFFF7
SBC HL,DE
RET
;[ЧТЕНИЕ СЛЕДУЮЩЕГО КЛАСТЕРА]
RDFATZP LD A,(FATType)
AND A
JR Z,RDFATS0
DEC A
JR Z,RDFATS1
EX DE,HL
ADD HL,HL
EX DE,HL
LD HL,0
ADC HL,BC
ADD HL,BC ; HLDE = BCDE * 2
LD A,E
LD E,D
LD D,L
LD C,H
LD B,0
CALL RDFATS2
INC HL
LD C,(HL)
INC HL
LD B,(HL)
RET
RDFATS1 LD BC,0
LD A,E
LD E,D
LD D,C
RDFATS2 PUSH AF
PUSH BC
LD HL,NumSecFAT1
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)
RET
RDFATS0 LD H,D
LD L,E
ADD HL,HL
ADD HL,DE
SRL H
RR L
LD A,E
LD E,H
LD D,0
LD B,D
LD C,D
SRL E
PUSH AF
PUSH HL
LD DE,(NumSecFAT1)
LD BC,(NumSecFAT1 + 2)
CALL LOADLST
POP BC
LD A,B
AND 1
LD B,A
ADD HL,BC
LD B,(HL)
INC HL
LD A,H
CP HIGH (BUF_512)+2
JR NZ,RDFATS4
PUSH BC
LD BC,0
INC DE
CALL LOADLST
POP BC
RDFATS4 POP AF
LD D,(HL)
LD E,B
LD BC,0
RRA
JR NC,RDFATS3
REPT 4
SRL D
RR E
ENDM
RDFATS3 LD A,D
AND 0X0F
LD D,A
RET
;[ПРЕОБРАЗОВАНИЕ НОМЕРА КЛАСТЕРА]
;ВЫЧИСЛЕНИЕ РЕАЛЬНОГО СЕКТОРА
;НА ВХОДЕ BCDE=НОМЕР FAT
;НА ВЫХОДЕ BCDE=АДРЕС СЕКТОРА
REALSEC LD A,B
OR C
OR D
OR E
JR NZ,REALSE1
LD DE,(NumSecRootDir)
LD BC,(NumSecRootDir + 2)
RET
REALSE1 LD HL,0XFFFE
EX DE,HL
ADD HL,DE
EX DE,HL
INC HL
ADC HL,BC ;НОМЕР КЛАСТЕРА-2
LD A,(SecPerClus)
JR REALSE2
REALSE3 SLA E
RL D
RL L
RL H
REALSE2 RRCA
JR NC,REALSE3 ;УМНОЖИЛИ НА РАЗМЕР КЛАСТЕРА
LD B,H
LD C,L
LD HL,FirstSecData
JP BCDEHLP ;ПРИБАВИЛИ СМЕЩЕНИЕ ОТ НАЧАЛА РАЗДЕЛА
;[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
;[ЗАГРУЗКА СЕКТОРА В БУФЕР]
LOADLST LD HL,BUF_512_
PUSH HL
LD A,1
CALL LOADSCS
POP HL
RET
;[INCLUDES]
include drivers/drv_zc.a80
include drivers/drv_neogs.a80
include drivers/drv_nemo.a80
include drivers/drv_smuc.a80
include drivers/drv_divide.a80
include drivers/drv_profi.a80
include spg2_run.a80
include sna_run.a80