;!TODO код дико костыльный и будет переделан вместе с процедурой INITDVC ReScanDRV: .NUMBER_OF_SUBTABLES EQU 2 ;количество таблиц второго уровня (LOGDRV, RMDRIVE) ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; 0. запоминаем бут-диск ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; LD A,B LD (.old_letter),A ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; 1. копируем в буфер таблицы DEVICE, LOGDRV, RAMDTBL ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; LD HL,DEVICE LD DE,OLD_TABLES.DEVICE LD BC,OLD_TABLES.DEVICE - DEVICE LDIR ; LD A,.NUMBER_OF_SUBTABLES LD (Fill_if_Exists.tbl),A ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; 2. вызываем инициализацию драйвов ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; CALL INITDVC_RET_DRIVE LD (DRV_PAGE.LDRIVE),A ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; 3. сравниваем записи старых таблиц с новыми: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; LD HL,OLD_TABLES.DEVICE LD B,DSS_MAX_DRIVES_AMOUNT .tbl_scanNew_mainLoop: PUSH BC PUSH HL ; получаем номер процедуры для этой буквы диска LD A,(HL) ; CP #FF JR Z,.nextN ; LD B,A INC HL LD A,(HL) INC HL LD H,(HL) LD L,A ; [ищем что за драйв] EX DE,HL ; FDD? LD HL,FDDRIVE AND A SBC HL,DE JR Z,.nextN ; пропуск FDD драйвов ; HDD? LD HL,HDDRIVE AND A SBC HL,DE ; HDD! Сверка по таблице LOGDRV JP Z,SCAN_TABLES.HARD_DRV ; RD? LD HL,RMDRIVE AND A SBC HL,DE ; RAM Drive! Сверка по таблице RAMDTBL JP Z,SCAN_TABLES.RAM_DRV ; CD/DVD? ;LD HL,CDDRIVE ;AND A ;SUB HL,DE ; CD/DVD! ; JR Z,SCAN_TABLES.CD_ROM ; следующий виток .nextN: POP HL .nextN2: INC HL INC HL INC HL POP BC DJNZ .tbl_scanNew_mainLoop ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; 4. сравниваем запись новых таблиц со старыми ; а. если драйв только в новой: ; а1) втыкаем его в первую свободную запись в DEVICE (или ставим после последнего драйва) ; ; ВХОД: IX - OLD_TABLES.DEVICE ; HL - OLD_TABLES.DEVICE.End ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; INC HL LD (OLD_TABLES_CURRENT),HL EXX LD HL,OLD_TABLES.LOGDRV - LOGDRV LD B,DSS_MAX_DRIVES_AMOUNT EXX ; находим в старой DEVICE первую свободную ячейку (проверяем с конца в начало) LD IX,OLD_TABLES.DEVICE + OLD_TABLES.DEVICE.Size - OLD_TABLES.DEVICE.TBL_Entry LD IY,LOGDRV LD DE,-OLD_TABLES.DEVICE.TBL_Entry ; двигаемся по таблице назад LD B,DSS_MAX_DRIVES_AMOUNT ; .loop1: LD A,#FF CP (IX+0) JR NZ,.loop2_start ADD IX,DE DJNZ .loop1 .loop1_exit: LD A,C ; закончили считать переменную LDRIVE LD (DRV_PAGE.LDRIVE),A ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; 5. проверяем, не грохнулся ли бут-диск. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; .old_letter+1: LD A,0 _CALC_DEVICE_ENTRY OLD_TABLES.DEVICE LD A,(HL) INC A JP Z,ERROR_BOOTDRV_DIES ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ; 6. заменяем новые таблицы на модифицированные старые ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; LD HL,OLD_TABLES.DEVICE LD DE,DEVICE LD BC,OLD_TABLES.DEVICE - DEVICE LDIR ; ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ;7. выход ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; LD A,(DRV_PAGE.LDRIVE) RET ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; ;-----------------------[] .loop2_start: LD C,B ; начинаем считать переменную LDRIVE LD A,DSS_MAX_DRIVES_AMOUNT SUB B ; сколько шагов вперёд по таблице осталось LD B,A ; .loop2: LD DE,DEVICE.TBL_Entry ; теперь двигаемся по таблице вперёд ADD IX,DE ; тут указатель показывает на первую свободную ячейку после блока с данными драйвов PUSH IX PUSH BC CALL Fill_if_Exists POP BC POP IX ; NC: ; DE = адрес процедуры обработчика таблицы ; A = логический номер устройства в таблице обработчика ; ; CF - нет больше новых записей JR C,.loop1_exit LD (IX+0),A LD (IX+1),E LD (IX+2),D ; INC C ; добавили драйв ; DJNZ .loop2 JR .loop1_exit ;-----------------------[] ;-----------------------[] Fill_if_Exists: .tbl+1: LD B,ReScanDRV.NUMBER_OF_SUBTABLES DJNZ 1F ; B=1, RAMDTBL LD A,RAMDTBL.TBL_Entry LD IY,RAMDTBL CALL .RUN LD DE,RMDRIVE RET NC LD A,(.tbl) DEC A ;!!!!! может быть переполнение LD (.tbl),A RET ; 1: DJNZ 1F ; B=2, LOGDRV LD A,LOGDRV.TBL_Entry LD IY,LOGDRV CALL .RUN LD DE,HDDRIVE RET NC ; переходим на другую таблицу - RAMDTBL LD A,(.tbl) DEC A ;!!!!! может быть переполнение LD (.tbl),A LD HL,OLD_TABLES.RAMDTBL LD (OLD_TABLES_CURRENT),HL EXX LD B,MAX_RAMDRIVES EXX JR Fill_if_Exists ; 1: SCF ; unknown table number RET ; .RUN: EXX ; LD D,0 LD E,A PUSH DE ; LD A,#FE ; Так поиск закончится либо на номере драйва, либо по концу таблицы PUSH BC CALL Find_Record.loop1 ; ищет в новой таблице новую запись POP BC JR NC,1F ; POP DE EXX RET ; 1: PUSH IY ; сохраняем текущий адрес новой таблицы ; LD IY,(OLD_TABLES_CURRENT) ; LD A,#FF ; Так поиск закончится либо на пустой записи, либо по концу таблицы LD C,D ; номер записи в таблице. D=0 PUSH BC CALL Find_Record.loop2 LD A,C POP BC JR NC,1F ; POP DE POP DE EXX RET ; 1: EX (SP),IY ; переключение со старой на новую таблицу PUSH IY EXX ; перекидываем запись из новой в старую POP HL POP DE POP BC LDIR LD (IY),#FF ; грохаем только что перекинутую запись из новой таблицы AND A RET OLD_TABLES_CURRENT: WORD 0 ;-----------------------[] ;-----------------------[] ; ВХОД: A - Маска для сравнения ; DE - Длина одной записи ; IY - Адрес данных в таблице ; ВЫХОД: NC: ; IY - начало подходящей записи ; C - номер новой записи в старой таблице ; CF - Не найдено, таблица закончилась Find_Record: .loop1: CP (IY) RET NC ADD IY,DE INC C DJNZ .loop1 ; таблицу прошерстили SCF RET .loop2: CP (IY) RET Z ADD IY,DE INC C DJNZ .loop2 ; таблицу прошерстили SCF RET ;-----------------------[] ;-----------------------[] ERROR_BOOTDRV_DIES: DI LD E,1 LD BC,BIOS.LP_OPEN_S.TXT_80x32_Default RST ToBIOS ; LD HL,#2050 LD DE,0 LD BC,256*COLORS.CGA.PAPER.BLUE + BIOS.LP_CLS_WIN RST ToBIOS ; LD A,1 OUT (RGMOD),A ; set scr-2 ; LD HL,.ERROR_MSG LD DE,#A000 LD BC,.ERROR_MSG.size LD A,C LDIR ; LD DE,16*256 + (80-.ERROR_MSG.size)/2 ;X=0, Y=16 LD C,BIOS.LP_SET_PLACE RST ToBIOS ; LD HL,#A000 LD DE,0*256 + COLORS.CGA.FLASH + COLORS.CGA.PAPER.BLUE + COLORS.CGA.INC.WHITE LD B,A LD C,BIOS.LP_PRINT_LINE3 RST ToBIOS ; .loop: DI HALT JR .loop ; .ERROR_MSG: DZ "Kernel panic! Boot disk lost. Press Ctrl+Alt+Del or RESET." .ERROR_MSG.size EQU $-.ERROR_MSG ;-----------------------[] ;-----------------------[] ; НЕ ГРОХАТЬ HL! ; а. если драйв есть в новой и старой, то затираем в новой ; таблице совпавший драйв ; б. если драйв есть только в старой, то: ; б1) грохаем файловые манипуляторы с его номером MODULE SCAN_TABLES ; вход: B - лог.номер драйва, DE RAM_DRV: ; Получаем номер рамдиска в OLD_TABLES.RAMDTBL LD A,B LD BC,OLD_TABLES.RAMDTBL CALL GET_RAMDRV_NUM.skip_tbl LD (.cur_drv),BC AND #0F LD C,A ; номер рамдиска ; Ищем в новой такой же номер рамдиска LD B,MAX_RAMDRIVES LD DE,RAMDTBL .loop: LD A,(DE) SUB C JR Z,.found INC DE INC DE DJNZ .loop ; ЗАПИСЬ НЕ НАЙДЕНА ; Достаём положение в OLD_TABLES.DEVICE POP HL ; Достаём шаг общего цикла для получения лог.номера драйва в KILL_FM POP BC PUSH BC ; Грохаем ФМ и запись в OLD_TABLES.DEVICE CALL KILL_FM ; грохаем в старой RAMDTBL этот драйв EX DE,HL .cur_drv+1: LD HL,0 LD (HL),#FF DEC HL LD (HL),#FF EX DE,HL JP ReScanDRV.nextN2 ; .found: DEC A ; затираем в новой таблице совпавший драйв (чтоб легче было парсить оставшееся) LD (DE),A DEC DE LD (DE),A JP ReScanDRV.nextN ;-----[] HARD_DRV: LD L,B LOGDRV_ENTRY_FIND OLD_TABLES.LOGDRV LD IX,LOGDRV LD DE,LOGDRV.TBL_Entry LD B,DSS_MAX_DRIVES_AMOUNT ; .loop: LD A,(IY+LOGDRV.PHISICAL_DRV_NUMBER) ;CP #FF ;JR Z,.skip CP (IX+LOGDRV.PHISICAL_DRV_NUMBER) JR NZ,.skip ; LD A,(IY+LOGDRV.SECTOR_OFFSET) CP (IX+LOGDRV.SECTOR_OFFSET) JR NZ,.skip LD A,(IY+LOGDRV.SECTOR_OFFSET+1) CP (IX+LOGDRV.SECTOR_OFFSET+1) JR NZ,.skip LD A,(IY+LOGDRV.SECTOR_OFFSET+2) CP (IX+LOGDRV.SECTOR_OFFSET+2) JR NZ,.skip LD A,(IY+LOGDRV.SECTOR_OFFSET+3) CP (IX+LOGDRV.SECTOR_OFFSET+3) JR Z,.found ; .skip: ADD IX,DE DJNZ .loop ; ЗАПИСЬ НЕ НАЙДЕНА ; Грохаем старую запись в OLD_TABLES.LOGDRV LD A,#FF LD (IY+LOGDRV.PHISICAL_DRV_NUMBER),A ; Достаём положение в OLD_TABLES.DEVICE POP HL ; Достаём шаг общего цикла для получения лог.номера драйва в KILL_FM POP BC PUSH BC ; Грохаем ФМ и запись в OLD_TABLES.DEVICE CALL KILL_FM ; JP ReScanDRV.nextN2 ; .found: ; затираем в новой таблице совпавший драйв (чтоб легче было парсить оставшееся) LD (IX+LOGDRV.PHISICAL_DRV_NUMBER),#FF JP ReScanDRV.nextN ; ; CD_ROM: ; JP ReScanDRV.nextN ;-----[] ; ВХОД: HL - текущая запись в таблице DEVICE ; B - шаг общего цикла KILL_FM: ; LD A,DSS_MAX_DRIVES_AMOUNT SUB B LD C,A ; втыкаем страницу ядра с таблицей файловых манипуляторов PUSH BC LD A,(PORTAL.out_DRV.RETBANK) LD B,A LD C,SLOT3 IN A,(SLOT3) OUT (C),B POP BC PUSH AF ; Шерстим манипуляторы на наличие в них грохнутого драйва LD IY,CORE_BUFFERS.FM_BUF - CORE_BUFFERS.FM_BUF.Size + #C000 LD B,FMCOUNT LD DE,CORE_BUFFERS.FM_BUF.Size .loop_fm: ADD IY,DE LD A,(IY+_sFM.DRIVE) CP C JR NZ,.skip XOR A LD (IY+_sFM.NAME),A ; грохаем манипулятор .skip: DJNZ .loop_fm ; POP AF OUT (SLOT3),A ; ; грохаем в OLD_TABLES.DEVICE убитый драйв LD (HL),#FF ; RET ENDMODULE ;-----------------------[] /* [DRIVE TABLES] .Size == DEVICE.Size + LOGDRV.Size + RAMDTBL.Size == 78+1 + 416 + 32 == 526 ; логический номер устройства + адрес обработчика. ; Порядковый номер * 3 = буква диска + "A" DEVICE EQU $ .TBL_Entry EQU 3 .End EQU 1 + $ + DSS_MAX_DRIVES_AMOUNT * .TBL_Entry ; для стоп-байта #FF .Size EQU .End - $ ;+00 BYTE MASTER/SLAVE PHISICAL DRIVE NUMBER #80/#81/... ;+01 LONG SECTOR OFFSET ;+05 LONG SIZE IN SECTORS ;+09 LONG Volume Serial Number in HEX ; [ ] ;!TODO ;+13 WORD FREE ;+15 BYTE FREE ; Логический номер раздела. ;Номер группы = логический номер раздела HDD из DEVICE LOGDRV EQU DEVICE + DEVICE.Size .TBL_Entry EQU 16 .Size EQU DSS_MAX_DRIVES_AMOUNT * .TBL_Entry ; ТАБЛИЦА СООТВЕТСТВИЯ МЕЖДУ ФИЗИЧЕСКИМ НОМЕРОМ РАМДИСКА И ЕГО RAM-DISK ID ; Log Number: DB RAM_DRIVE_NUMBER, RAM_DRIVE_ID RAMDTBL EQU $ + DEVICE.Size + LOGDRV.Size .TBL_Entry EQU 2 .Size EQU .TBL_Entry * MAX_RAMDRIVES */