;--------------------------------------------------------------- ;Rev Date Name Decription ;--------------------------------------------------------------- ;R04 25-03-2023 BAO ; !FIXIT ;R03 23-01-2000 DNS OPTIMIZE NEW BOOTING PROCEDURE ;R02 08-01-2000 DNS NEW BOOTING PROCEDURE ;R01 25-05-1998 DNS Console printing ;R00 09-11-1998 DNS Color printing start message ; Install CGA palette ; +------------------------------+ ; + System Bootstrap + ; + Initial revision 09 Nov 1998 + ; +------------------------------+ ; BIOS 3.06 загружает один сектор загрузчика и передаёт ему управление. DEFINE ORIGINAL_DSS 0 DEFINE UNIVERSAL_BOOT 1 DISP #8000 OUTPUT 'build/DSSloader.bin' ;ADRIVE EQU #00 ;CDRIVE EQU #02 DRIVE: _mSYSID DI LD (DRIVE),A ;[ ] 17.12.2023 загрузка с активного раздела, а не с первого XOR A LD (DRIVE+1),A ; LD C,BIOS.DRV_VERSION RST ToBIOS_18 ; LD HL,FAIL PUSH HL ; LD HL,MESSAGES.INCORR RET C ; goto FAIL LD A,(DRIVE) BIT 7,A JP Z,GOOD_DRIVE EX DE,HL LD DE,2*256 + 21 ;!HARDCODE если версия ниже 2.21, то ошибка SBC HL,DE LD HL,MESSAGES.INCORR RET C ; goto FAIL JP GOOD_DRIVE //////////////////////////////////////////////////////////////////////// FAIL: CALL MESSAGE .NULL: LD HL,MESSAGES.FAILURE CALL MESSAGE DI HALT JR $ ; ; ; DOSMESS: CALL FMESAGE ; LD C,Dss.PChars ; RST ToDSS ; RET ; ; ; FMESAGE: LD HL,MSG0 ; LD BC,MSGE-MSG0 ; INC A ; EX AF,AF' ; XOR A ; EX AF,AF' ; .NEXTMSG: EX AF,AF' ; CPIR ; RET PO ; RET NZ ; EX AF,AF' ; DEC A ; JR NZ,.NEXTMSG ; RET ; ; MESSAGE: ;CALL FMESAGE ;R01 Start XOR A OUT (SYS_PORT.ON),A .loop: LD A,(HL) ;R01 INC HL OR A RET Z CALL PRINTX JR .loop ; PRINTX: CP "\r" ; JR Z,.CR_ CP "\n" ; JR Z,.LF_ LD BC,1*256 + BIOS.LP_PRINT_SYM RST ToBIOS_18 RET ; .CR_: LD C,BIOS.LP_GET_PLACE RST ToBIOS_18 LD E,0 LD C,BIOS.LP_SET_PLACE RST ToBIOS_18 RET ; .LF_: LD C,BIOS.LP_GET_PLACE RST ToBIOS_18 LD A,#1F CP D JR NZ,.LF2 PUSH DE PUSH HL LD DE,#0020 LD BC,1*256 + BIOS.LP_SCROLL_UD RST ToBIOS_18 LD DE,#1F00 LD C,BIOS.LP_SET_PLACE RST ToBIOS_18 LD A," " LD BC,#50 + BIOS.LP_PRINT_SYM RST ToBIOS_18 POP HL POP DE DEC D .LF2: INC D LD C,BIOS.LP_SET_PLACE RST ToBIOS_18 RET ;R01 ;R01 End ; FAILURE EQU 0 ; INCORR EQU 1 ; ERRPART EQU 2 ; ERRIBPB EQU 3 ; NO_SYS EQU 4 ; NOSHELL EQU 5 ; STARTDO EQU 6 ;a BIOS version that is incompatible with this version of DOS MESSAGES:; 0 10 20 30 40 50 60 70 80 .FAILURE: DB "\r\nFatal error! Press RESET to restart.\r\n",0 .INCORR: DB "\r\nUnsupported BIOS version! Update BIOS to run this version of DSS.\r\n",0 .ERRPART: DB "\r\nUnknown partition table.",0 .ERRIBPB: DB "\r\nInvalid BOOT sector.",0 .NO_SYS: DB "\r\nCan't open file SYSTEM.DOS...",0 .NOSHELL: DB "\r\nCan't open file SYSTEM.EXE...",0 .STARTDO: DB "\r\nStarting DSS... \r\n\n",0 ; SHELL_NAME: DB '\SYSTEM.EXE /P',0 ROOT: DB 'X:\',0 CORE_NAME: DB "SYSTEM DOS" .Size EQU $-CORE_NAME FATMSG: DB "FAT" //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// ASSERT $<#8200, "Error!!! BIOS LOADING ONLY FIRST #200 BYTES" //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// GOOD_DRIVE: LD DE,#8200 ;!HARDCODE LD HL,0 LD IX,2 LD BC,2*256 + BIOS.DRV_READ ;!HARDCODE дозагрузка ещё двух секторов загрузчика LD A,(DRIVE) RST ToBIOS_18 JP C,FAIL.NULL ; ; CONTINUE ;!TEST 26/03/2024 ;LD SP,#C000 ; LD HL,0 LD (DISKL),HL LD (DISKH),HL ; LD BC,1*256 + BIOS.GetMem RST ToBIOS_18 ;GET PAGE FOR DOS LD (BANKDOS),A ; OUT (SLOT0),A ; CALL GET_BPB ;READ BPB LD HL,MESSAGES.ERRIBPB RET C ; goto FAIL CALL GETROOT LD HL,MESSAGES.NO_SYS RET C ; goto FAIL ; [ ] загрузка system.dos больше #4000 байтов LD HL,(FSIZE1) LD A,H OR L JR NZ,.set_size LD DE,(FSIZE0) LD HL,#4000 SBC HL,DE JR NC,.set_no_size .set_size: LD A,#FF .set_no_size: LD (BIG_CORE),A OR A PUSH AF ; загрузка LD HL,(FCLUSTR) LD DE,#C000 CALL LOAD_CORE ; [ ] загрузка system.dos больше #4000 байтов EX AF,AF' POP AF JR Z,.no_big_core EX AF,AF' JR C,.no_big_core ; IN A,(SLOT1) LD (BANKDOS),A LD A,SUBLOAD_SIZE LD (LOAD_CORE.max_sectors),A LD (BIG_CORE),A ; теперь это счётчик оставшихся секторов ; LD A,(BOOT_BUFFER + BOOT_SECTOR.SectorsPerCluster) CP #20 + 1 ; !HARDCODE кол-во загружаемых секторов JP NC,INC_SECTOR_NUM CALL R_F_FAT ; next cluster in chain EX DE,HL LD DE,#C000 CALL NC,LOAD_CORE .no_big_core: ; RUN_CORE: DI XOR A OUT (SYS_PORT.OFF),A ; LD A,#10 LD BC,#7FFD OUT (C),A ; LD A,1 LD B,#1F ;1FFD OUT (C),A ; ; LD A,(BANKDOS) ; OUT (SLOT0),A ;DOS LOADED ;IF UNIVERSAL_BOOT ;[ ] 17.12.2023 загрузка с активного раздела, а не с первого LD A,(DRIVE+1) ; номер раздела LD L,A ; LD A,(DRIVE) ; номер устройства LD C,Dss.Version RST ToDSS JP C,FAIL.NULL ; LD HL,MESSAGES.STARTDO CALL MESSAGE ; XOR A OUT (SYS_PORT.OFF),A ; LD A,(DRIVE) LD BC,Dss.BootDSK.Set RST ToDSS ; LD BC,Dss.BootDSK.Get ;ELSE ; IF ORIGINAL_DSS ; LD C,Dss.Version ; RST ToDSS ; ELSE ; LD A,(DRIVE) ; LD C,Dss.Version ; RST ToDSS ; JP C,FAIL.NULL ; LD C,Dss.BootDSK ; ENDIF ; ; LD HL,MESSAGES.STARTDO ; CALL MESSAGE ; IF ORIGINAL_DSS ; LD A,(DRIVE) ; LD BC,Dss.BootDSK.Set ; RST ToDSS ; LD BС,Dss.BootDSK.Get ; ENDIF ;ENDIF ; RST ToDSS ; ADD A,"A" ; LD HL,ROOT LD (HL),A LD C,Dss.ChDir RST ToDSS ; LD HL,SHELL_NAME LD BC,Dss.Exec RST ToDSS .NoShell: JP NC,FAIL.NULL LD HL,MESSAGES.NOSHELL CP DSS_Error.sys.UNEXPECTED_APP_TRMN JP NZ,FAIL JP FAIL.NULL ; .NoShell: LD HL,MESSAGES.NOSHELL ; JP C,FAIL ; LD HL,MESSAGES.FAILURE ; JP FAIL ; XFAIL: CALL DOSMESS ; .fail: LD HL,MESSAGES.FAILURE ; CALL DOSMESS ; DI ; HALT ; .halt: JR .halt ; ; INC_SECTOR_NUM: PUSH DE CALL NSECTOR LD DE,#20 ;!HARDCODE количество прочитанных секторов ADD IX,DE JR NC,.no_inc INC HL .no_inc: ; POP DE LD BC,RUN_CORE PUSH BC PUSH HL JP LOAD_CORE.subload ; CALL .set_stack ; JP RUN_CORE ; .set_stack: PUSH HL ; JP LOAD_CORE.subload ; ; PART_TB: PUSH BC LD HL,(BOOT_BUFFER + BOOT_SECTOR.MBR_SIGNATURE) LD DE,#AA55 ;AND A ; CF = 0 SBC HL,DE SCF RET NZ LD IX,BOOT_BUFFER + BOOT_SECTOR.PARTITION_TABLE LD B, +(_sMBR_PARTITION_TABLE / _sMBR_PARTITION_RECORD) ; .part_loop: LD A,(IX + _sMBR_PARTITION_RECORD.FS_ID) ; ЕСЛИ добавится поддержка ещё одного типа ФС, то поменять 1 на 2 ; 1 CP PartitionSysTypes.FAT16_LBA JR Z,YEPDOS CP PartitionSysTypes.FAT16 JR Z,YEPDOS CP PartitionSysTypes.FAT16_32Mb JR Z,YEPDOS CP PartitionSysTypes.FAT12 JR Z,YEPDOS CP PartitionSysTypes.FAT32 JR Z,YEPDOS CP PartitionSysTypes.FAT32_LBA JR Z,YEPDOS ; ; 2 ;EXX ;LD HL,SUPPORTED_PARTITIONS ;LD BC,SUPPORTED_PARTITIONS.Size ;CPIR ;EXX ;JR Z,YEPDOS ; .next: LD DE,_sMBR_PARTITION_RECORD ADD IX,DE DJNZ .part_loop ; LD HL,MESSAGES.ERRPART JP FAIL ; 2 ; SUPPORTED_PARTITIONS: ; ;.Empty DB #00 ; .FAT12 DB #01 ; .FAT16_32Mb DB #04 ; ;.Extended DB #05 ; .FAT16 DB #06 ; ;.HPFS_NTFS DB #07 ; .FAT32 DB #0B ; .FAT32_LBA DB #0C ; .FAT16_LBA DB #0E ; ;.Win_Ext_LBA DB #0F ; ;.Linux_swap DB #82 ; ;.Linux DB #83 ; ;.Linux_extended DB #85 ; .Size EQU $-SUPPORTED_PARTITIONS ; YEPDOS: ;[ ] 17.12.2023 загрузка с активного раздела, а не с первого LD A,#80 CP (IX+0) JR NZ,PART_TB.next LD A,4 ;!HARDCODE счетчик записей партиций в MBR SUB B PUSH AF ; номер загрузочного раздела ; LD E,(IX+08) LD D,(IX+09) LD L,(IX+10) LD H,(IX+11) PUSH DE POP IX LD (DISKL),IX LD (DISKH),HL LD A,(DRIVE) LD DE,BOOT_BUFFER LD BC,1*256 + BIOS.DRV_READ RST ToBIOS_18 ;[ ] 17.12.2023 загрузка с активного раздела, а не с первого POP AF POP BC LD L,A ; номер загрузочного раздела LD A,C ;LD A,C ; RET ; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ;/* GET_BPB: LD IX,#0000 LD HL,#0000 LD DE,BOOT_BUFFER LD BC,1*256 + BIOS.DRV_READ LD A,(DRIVE) RST ToBIOS_18 RET C LD A,(DRIVE) LD B,A AND #F0 LD C,A CP #80 JR NZ,.NX1 CALL PART_TB ;HDD RET C ;[ ] 17.12.2023 загрузка с активного раздела, а не с первого LD (DRIVE+1),HL ; .NX1: CP #00 JR NZ,.NX2 ; ; SET_PRM if FDD PUSH BC LD A,B LD C,BIOS.DRV_GET_PAR RST ToBIOS_18 LD A,(BOOT_BUFFER + BOOT_SECTOR.SectorsPerTrack) LD L,A POP AF ;PUSH AF LD C,BIOS.DRV_SET_PAR RST ToBIOS_18 ;POP BC ;LD A,C ; нахера? ;RET .NX2: LD HL,(BOOT_BUFFER + BOOT_SECTOR.MBR_SIGNATURE) LD DE,#AA55 AND A SBC HL,DE SCF RET NZ ; LD IY,BOOT_BUFFER ;Analysing Block Parametr BIOS LD A,(IY+_sBOOT_SECTOR_PARAMS.DRIVE_TYPE) CP #F0 RET C LD HL,0 ;calc. first sector FAT LD (FatBuffer.RootDirFirstSector_H),HL ; LD E,(IY+_sBOOT_SECTOR_PARAMS.RESERVED_SECTORS) ;Reserve sec LD D,(IY+_sBOOT_SECTOR_PARAMS.RESERVED_SECTORS+1) ADD HL,DE LD (FatBuffer.FAT1_SEC_L),HL ;first sector FAT LD E,(IY+_sBOOT_SECTOR_PARAMS.SectorsPerFAT16) ;sectors in FAT LD D,(IY+_sBOOT_SECTOR_PARAMS.SectorsPerFAT16+1) LD A,(BOOT_BUFFER + BOOT_SECTOR.Number_of_FATs) ;amount FATs .C_DATA1: ADD HL,DE DEC A JR NZ,.C_DATA1 LD (FatBuffer.RootDirFirstSector_L),HL ;first sector DIR EX DE,HL LD L,(IY+_sBOOT_SECTOR_PARAMS.FilesInRootDIR) ;Number file handel LD H,(IY+_sBOOT_SECTOR_PARAMS.FilesInRootDIR+1) ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL LD A,H SRL A LD (FatBuffer.DirSizeInSectors),A ;Sectors per dir LD L,A LD H,0 ADD HL,DE LD (FatBuffer.FirstDataSector_L),HL ;First sector data ; LD C,(IY+_sBOOT_SECTOR_PARAMS.BytesPerSector) ;Size sector LD B,(IY+_sBOOT_SECTOR_PARAMS.BytesPerSector+1) LD HL,0 LD A,(BOOT_BUFFER + BOOT_SECTOR.SectorsPerCluster) .NEXTAD3: ADD HL,BC ;calc. cluster size DEC A JR NZ,.NEXTAD3 LD (FatBuffer.BytesPerCluster),HL LD HL,BOOT_BUFFER + BOOT_SECTOR.ID_FAT LD DE,FATMSG LD B,3 .R_BPBL1: LD A,(DE) CP (HL) JP NZ,.IBMDOS_ INC HL INC DE DJNZ .R_BPBL1 .FID: LD A,(HL) INC HL CP " " JR Z,.FID CP "1" SCF RET NZ LD A,(HL) CP "6" ; FAT16 ;LD HL,#FFFF JR Z,.BPB_FAT CP "2" ; FAT12 SCF RET NZ ;LD HL,#0FFF .BPB_FAT: LD (FatBuffer.FAT_TYPE),A ;LD (FatBuffer.END_CHAIN_CLUSTER_L),HL ; LD IX,(DISKL) LD HL,(DISKH) LD DE,(FatBuffer.FAT1_SEC_L) LD BC,#0000 ADD IX,DE ADC HL,BC ;HL:IX LD DE,FAT_SECTORS_BUFFER LD BC,3*256 + BIOS.DRV_READ LD A,(DRIVE) RST ToBIOS_18 RET C LD HL,0 LD (FatBuffer.CacheBlock),HL XOR A RET ; .IBMDOS_ LD A,(IY+_sBOOT_SECTOR_PARAMS.DRIVE_TYPE) CP #F0 RET C CP #F8 LD A,"6" LD HL,#FFFF JR Z,.BPB_FAT LD A,"2" LD HL,#0FFF JR .BPB_FAT ;*/ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* GET_BPB: LD IX,#0000 LD HL,#0000 LD DE,BOOT_BUFFER LD BC,1*256 + BIOS.DRV_READ LD A,(DRIVE) RST ToBIOS_18 RET C LD A,(DRIVE) LD B,A AND #F0 LD C,A CP #80 JR NZ,.NX1 CALL PART_TB ;HDD RET C ;[ ] 17.12.2023 загрузка с активного раздела, а не с первого LD (DRIVE+1),HL ; .NX1: CP #00 JR NZ,.NX2 ; ; SET_PRM if FDD PUSH BC LD A,B LD C,BIOS.DRV_GET_PAR RST ToBIOS_18 LD A,(BOOT_BUFFER + BOOT_SECTOR.SectorsPerTrack) LD L,A POP AF ;PUSH AF LD C,BIOS.DRV_SET_PAR RST ToBIOS_18 ;POP BC ;LD A,C ; нахера? ;RET .NX2: LD HL,(BOOT_BUFFER + BOOT_SECTOR.MBR_SIGNATURE) LD DE,#AA55 AND A SBC HL,DE SCF RET NZ ; ;RD_BPB: ; CALL READ_BPB ; JP C,DOS_X_Error.Not_ready ; ; ; LD DE,#AA55 ; сигнатура ;R05 ; LD HL,(BOOT_BUFFER + BOOT_SECTOR.MBR_SIGNATURE) ;R08 ;R07 ; ;R05 ; AND A ; SBC HL,DE ; JP NZ,DOS_X_Error.UnknownBPB ; ; ;R08 ; [x] fat32 ; LD HL,BOOT_BUFFER ; LD DE,CORE_BUFFERS.BootSector ; LD BC,_sBOOT_SECTOR_PARAMS_FAT32 ; size ; LDIR ; LD A,(BOOT_BUFFER + BOOT_SECTOR.DRIVE_TYPE) CP #F0 RET C ; ; LD HL,(BOOT_BUFFER + BOOT_SECTOR.BytesPerSector) ; LD (FatBuffer.BytesPerSector),HL ; LD A,(BOOT_BUFFER + BOOT_SECTOR.SectorsPerCluster) ; LD (FatBuffer.SectorsPerCluster),A ; calc. first sector FAT LD HL,(BOOT_BUFFER + BOOT_SECTOR.RESERVED_SECTORS) LD (FatBuffer.FAT1_SEC_L),HL ; low word first sector FAT #1 ;LD (FatBuffer.FAT2_SEC_L),HL ; low word first sector FAT #2 ; fat32 XOR A LD B,A LD C,A LD (FatBuffer.FAT1_SEC_H),BC ; high word first sector FAT #1 ; fat32 ; LD (FatBuffer.FAT2_SEC_H),BC ; high word first sector FAT #1 ; fat32 LD (FatBuffer.SectorsPerFAT_H),A ; fat32 ; ; LD DE,(BOOT_BUFFER + BOOT_SECTOR.SectorsPerFAT16) LD A,E OR D JR NZ,.skip_high ; LD BC,(BOOT_BUFFER + BOOT_SECTOR.SectorsPerFAT32 + 2) LD A,C LD (FatBuffer.SectorsPerFAT_H),A LD DE,(BOOT_BUFFER + BOOT_SECTOR.SectorsPerFAT32) .skip_high: LD (FatBuffer.SectorsPerFAT_L),DE LD A,(BOOT_BUFFER + BOOT_SECTOR.Number_of_FATs) ; amount FATs LD (FatBuffer.Number_Of_FATs),A CP 1 JR Z,.one_FAT DEC A ADD HL,DE LD (FatBuffer.FAT2_SEC_L),HL JR NC,.no_inc_BC INC BC .no_inc_BC: LD (FatBuffer.FAT2_SEC_H),BC .one_FAT: ;C_DATA1 .loop1: ADD HL,DE JR NC,.loop1_1 INC BC .loop1_1: DEC A JR NZ,.loop1 ; LD (FatBuffer.RootDirFirstSector_L),HL ; first sector DIR ;LD BC,(FatBuffer.BytesPerSector) LD BC,(BOOT_BUFFER + BOOT_SECTOR.BytesPerSector) LD A,B AND A ; RL C RLA RL C RLA RL C RLA ; LD C,A LD B,0 ; BC - File handels in sectors ;;;; IF COMPILE_UNUSED_CODE LD (FatBuffer.FilesPerSector),A ENDIF ; EX DE,HL LD HL,(BOOT_BUFFER + BOOT_SECTOR.FilesInRootDIR) ; 0 for fat32 ; fat32 LD A,H OR L JR Z,.skip_loop2 ; DEC HL XOR A ;NEXTAD2 .loop2: INC A RET C SBC HL,BC JR NC,.loop2 ; .skip_loop2: EX DE,HL LD C,A ; A - sectors in DIR LD B,0 LD (FatBuffer.DirSizeInSectors),A ADD HL,BC ; Start DATA area LD (FatBuffer.FirstDataSector_L),HL ; B = 0 ; ;LD HL,(FatBuffer.BytesPerSector) LD HL,(BOOT_BUFFER + BOOT_SECTOR.BytesPerSector) ;LD A,(FatBuffer.SectorsPerCluster) LD A,(BOOT_BUFFER + BOOT_SECTOR.SectorsPerCluster) ;!TODO FATcacheSize ; calc. cluster size XOR 1 JR Z,.loop3.end RRA .loop3: ADD HL,HL RRA JP NC,.loop3 .loop3.end: ; LD (FatBuffer.BytesPerCluster),HL ; fat32 LD HL,(BOOT_BUFFER + BOOT_SECTOR.SectorsPerDrive) LD DE,(FatBuffer.FirstDataSector_L) LD A,H OR L JP NZ,.HDDSMAL ; LD HL,(BOOT_BUFFER + BOOT_SECTOR.BPB_BIG_TOTAL_SECTORS_L) LD BC,(BOOT_BUFFER + BOOT_SECTOR.BPB_BIG_TOTAL_SECTORS_H) PUSH BC ; Total Sectors high PUSH HL ; Total Sectors low AND A SBC HL,DE JP NC,.HDDBIG DEC BC JP .HDDBIG ; .HDDSMAL: ; CF = 0 LD BC,0 PUSH BC ; Total Sectors high PUSH HL ; Total Sectors low SBC HL,DE ; .HDDBIG: CALL SectorToCluster ; LD A,(FatBuffer.SectorsPerCluster) ; SCF ; .loop7: RRA ; JR C,.loop7_exit ; RR B ; RR C ; RR H ; RR L ; JP .loop7 ; .loop7_exit: INC HL LD (FatBuffer.MaxClusterLow),HL LD A,L OR H JR NZ,.no_inc_bc INC BC .no_inc_bc: LD (FatBuffer.MaxClusterHigh),BC ; XOR A LD H,A LD L,A LD (FatBuffer.CacheBlock),HL LD (FatBuffer.CacheUpdated),A ; A = 0 LD HL,(FatBuffer.SectorsPerFAT_H) LD H,A EX DE,HL LD HL,(FatBuffer.SectorsPerFAT_L) ; DE:HL = SectorsPerFAT ; LD A,(BOOT_BUFFER + BOOT_SECTOR.Number_of_FATs) LD B,A DEC A JR Z,.loop_mul_end ; .Number_of_FATs * .SectorsPerFAT .loop_mul: ADD HL,HL EX DE,HL ADC HL,HL EX DE,HL DJNZ .loop_mul .loop_mul_end: ; .DirSizeInSectors + .Number_of_FATs * .SectorsPerFAT LD B,0 LD A,(FatBuffer.DirSizeInSectors) LD C,A ADD HL,BC JR NC,.no_inc_DE INC DE .no_inc_DE: ; .RESERVED_SECTORS + .DirSizeInSectors + .Number_of_FATs * .SectorsPerFAT LD BC,(BOOT_BUFFER + BOOT_SECTOR.RESERVED_SECTORS) ADD HL,BC JR NC,.no_inc_de INC DE .no_inc_de: ; Total_Sectors - (.RESERVED_SECTORS + .DirSizeInSectors + .Number_of_FATs * .SectorsPerFAT) AND A LD B,D LD C,E POP DE ; Total Sectors low EX DE,HL SBC HL,DE EX (SP),HL ; Total Sectors high SBC HL,BC POP DE ; Total Sectors low ; HL:DE = DataSec ; ;LD A,(FatBuffer.SectorsPerCluster) LD A,(BOOT_BUFFER + BOOT_SECTOR.SectorsPerCluster) ; HL:DE / A => DE:BC, H=0, L - остаток CALL DIV_for_SPC ; выясняем разрядность FAT LD A,D OR E JR NZ,.its_FAT32 ; LD HL,4084 SBC HL,BC JR NC,.its_FAT12 ; LD HL,65525 SBC HL,BC JR C,.its_FAT32 ; ; It's FAT16 LD HL,#FFFF LD A,FAT_TYPE.x16 .set_vars: EXX LD HL,0 LD (FatBuffer.END_CHAIN_CLUSTER_H),HL LD (FatBuffer.RootDirStartCluster_L),HL LD (FatBuffer.RootDirStartCluster_H),HL LD HL,BOOT_BUFFER + BOOT_SECTOR.FAT.LABEL EXX LD DE,(BOOT_BUFFER + BOOT_SECTOR.FAT.SERIAL_NUMBER) LD BC,(BOOT_BUFFER + BOOT_SECTOR.FAT.SERIAL_NUMBER+2) JR .SET_VARS ; .its_FAT12: LD HL,#0FFF LD A,FAT_TYPE.x12 JR .set_vars ; .its_FAT32: LD A,(BOOT_BUFFER + BOOT_SECTOR.MainFATnumber) CP #80 JR C,.mirrored_FATs ;если все копии FAT используются ; используется только одна копия FAT LD HL,(FatBuffer.FAT1_SEC_H) LD DE,(FatBuffer.SectorsPerFAT_H) LD D,0 EXX LD HL,(FatBuffer.FAT1_SEC_L) LD DE,(FatBuffer.SectorsPerFAT_L) AND #0F JR Z,.first_FAT_active LD B,A ; .fat_calc_loop: ADD HL,DE EXX ADC HL,DE EXX DJNZ .fat_calc_loop ; .first_FAT_active: LD (FatBuffer.FAT1_SEC_L),HL LD (FatBuffer.FAT2_SEC_L),HL EXX LD (FatBuffer.FAT1_SEC_H),HL LD (FatBuffer.FAT2_SEC_H),HL ; .mirrored_FATs: ; LD HL,BOOT_BUFFER + BOOT_SECTOR.FAT32.LABEL ; EXX LD HL,(BOOT_BUFFER + BOOT_SECTOR.RootDirStartCluster) LD (FatBuffer.RootDirStartCluster_L),HL LD BC,(BOOT_BUFFER + BOOT_SECTOR.RootDirStartCluster+2) LD (FatBuffer.RootDirStartCluster_H),BC ; CALL CLUSTER_TO_SECTOR LD (FatBuffer.RootDirFirstSector_L),HL LD (FatBuffer.RootDirFirstSector_H),BC ; LD HL,(BOOT_BUFFER + BOOT_SECTOR.FSINFO_Sector) LD (FatBuffer.FSINFO_Sector),HL ; LD A,FAT_TYPE.x32 LD HL,#0FFF LD (FatBuffer.END_CHAIN_CLUSTER_H),HL LD H,L LD DE,(BOOT_BUFFER + BOOT_SECTOR.FAT32.SERIAL_NUMBER) LD BC,(BOOT_BUFFER + BOOT_SECTOR.FAT32.SERIAL_NUMBER+2) ; .SET_VARS: LD (FatBuffer.FAT_TYPE),A LD (FatBuffer.END_CHAIN_CLUSTER_L),HL LD (FatBuffer.BPB_SERIAL_NUMBER),DE LD (FatBuffer.BPB_SERIAL_NUMBER+2),BC EXX LD DE,FatBuffer.BPB_LABEL LD BC,11 ;!HARDCODE LDIR ; SET_PAGE_X FATPAGE PUSH AF LD DE,0 CALL READ_FAT_TABLE POP AF OUT (SLOT3),A ; ; Установить начальный кластер для чтения LD A,(FatBuffer.FAT_TYPE) CP FAT_TYPE.x32 JR Z,.set_FSinfo ; LD HL,#0001 LD (G_CLUST.low),HL DEC L LD (G_CLUST.high),HL ; DEC HL LD (FatBuffer.FREE_CLUSTERS_COUNT_L),HL LD (FatBuffer.FREE_CLUSTERS_COUNT_H),HL XOR A RET ; .set_FSinfo: CALL READ_FSinfo ; !FIXIT проверка на ошибку ; ; проверка одной из сотни сраных сигнатур LD HL,(BOOT_BUFFER + _sFSinfo.DATA_SIGNATURE) LD DE,(BOOT_BUFFER + _sFSinfo.DATA_SIGNATURE + 2) LD BC,#7272 SBC HL,BC JR NZ,.error EX DE,HL LD DE,#6141 SBC HL,DE JR NZ,.error ; FREE_CLUSTERS_COUNT LD BC,(BOOT_BUFFER + _sFSinfo.FREE_CLUSTERS_COUNT) LD DE,(BOOT_BUFFER + _sFSinfo.FREE_CLUSTERS_COUNT+2) ; CF = 0 CALL .check_cluster JR NC,.skip_FFFF ; LD B,#FF LD C,B LD D,B LD E,B ; .skip_FFFF: LD (FatBuffer.FREE_CLUSTERS_COUNT_L),BC LD (FatBuffer.FREE_CLUSTERS_COUNT_H),DE ; ; FIRST_FREE_CLUSTER LD BC,(BOOT_BUFFER + _sFSinfo.FIRST_FREE_CLUSTER) LD DE,(BOOT_BUFFER + _sFSinfo.FIRST_FREE_CLUSTER+2) ; CF = 0 CALL .check_cluster JR C,.error ; LD (G_CLUST.high),DE LD (G_CLUST.low),BC XOR A .error: LD (FatBuffer.UPD_FSINFO),A RET Z ;!TODO FREE_CLUSTERS_COUNT ;LD HL,#FFFF ;LD (FatBuffer.FREE_CLUSTERS_COUNT_L),HL ;LD (FatBuffer.FREE_CLUSTERS_COUNT_H),HL ; XOR A LD H,A LD L,2 LD (G_CLUST.low),HL LD L,H LD (G_CLUST.high),HL RET ; ;!TODO MaxCluster - максимально допустимый или на 1 больше максимально допустимого? .check_cluster: LD HL,(FatBuffer.MaxClusterLow) SBC HL,BC LD HL,(FatBuffer.MaxClusterHigh) SBC HL,DE RET ;;;;;;;; ; --> BC:HL - Sector ; <-- BC:HL - Cluster SectorToCluster: LD A,B AND #0F LD B,A ;LD A,(FatBuffer.SectorsPerCluster) LD A,(BOOT_BUFFER + BOOT_SECTOR.SectorsPerCluster) SCF .loop: RRA RET C RR B RR C RR H RR L JP .loop ; */ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ; поиск system.dos GETROOT: LD HL,(FatBuffer.RootDirFirstSector_H) LD IX,(FatBuffer.RootDirFirstSector_L) LD BC,(DISKL) LD DE,(DISKH) LD A,(FatBuffer.DirSizeInSectors) .NEXTSEC: PUSH AF ADD IX,BC ADC HL,DE ;HL:IX PUSH IX PUSH HL LD BC,1*256 + BIOS.DRV_READ LD DE,DIR LD A,(DRIVE) RST ToBIOS_18 CALL SEARCH POP HL POP IX POP BC RET C RET NZ LD A,B LD DE,0 LD BC,1 DEC A JR NZ,.NEXTSEC SCF RET ; ; SEARCH: LD C,17 ;HANDELS PER SECTOR 512/32 + 1 LD IX, DIR - FAT_DIRECTORY_RECORD .SKIPNAM: LD DE,FAT_DIRECTORY_RECORD ADD IX,DE DEC C RET Z ; LD A,(IX+FAT_DIRECTORY_RECORD.NAME) OR A SCF RET Z ; CP #E5 JR Z,.SKIPNAM ; LD A,(IX+FAT_DIRECTORY_RECORD.ATTRIBUT) AND FAT_ATTR.DIRECTORY JR NZ,.SKIPNAM ; LD DE,CORE_NAME PUSH IX POP HL LD B,CORE_NAME.Size ; .loop: LD A,(DE) CP (HL) JR NZ,.SKIPNAM INC HL INC DE DJNZ .loop ; PUSH IX POP HL LD DE,HANDBUF LD BC,FAT_DIRECTORY_RECORD LDIR ; ZF = 1, CF = 0, A != 0 AND A ; на выходе ZF = CF = 0 RET ; ; HL - CLUSTER ; ; DE - ADDRESS ; ;!TODO сделать тут определение размера SYSTEM.DOS и возможность загрузить больше 1 страницы LOAD_CORE: LD (READMEM),DE .loop: PUSH HL CALL NSECTOR LD DE,(READMEM) LD A,(BOOT_BUFFER + BOOT_SECTOR.SectorsPerCluster) .max_sectors+1: CP #20 JR C,.SMALL_CLUSTER ; .subload: LD A,(.max_sectors) LD B,A LD C,BIOS.DRV_READ_LONG LD A,(BANKDOS) EX AF,AF' LD A,(DRIVE) RST ToBIOS_18 POP HL ;AND A RET ; .SMALL_CLUSTER: LD B,A LD C,BIOS.DRV_READ_LONG LD A,(BANKDOS) EX AF,AF' LD A,(DRIVE) RST ToBIOS_18 ; LD HL,(READMEM) LD DE,(FatBuffer.BytesPerCluster) ADD HL,DE LD (READMEM),HL POP HL CCF RET NC ; [ ] загрузка system.dos больше #4000 байтов LD A,(BIG_CORE) DEC A LD (BIG_CORE),A RET Z ; CALL R_F_FAT RET C EX DE,HL JP .loop ; HL - CLUSTER ; DE - ADDRESS ;!TODO сделать тут определение размера SYSTEM.DOS и возможность загрузить больше 1 страницы ; FLOAD: LD (READMEM),DE ; .LD_FILE: PUSH HL ; system.dos first cluster ; CALL NSECTOR ; Cluster to Sector ; LD DE,(READMEM) ; LD A,(BOOT_BUFFER + BOOT_SECTOR.SectorsPerCluster) ; CP #20 + 1 ; !HARDCODE кол-во загружаемых секторов ; LD C,BIOS.DRV_READ_LONG ; JR C,.SMALL_CLUSTER ; LD A,(BANKDOS) ; EX AF,AF' ; ;LD BC,#20*256 + BIOS.DRV_READ_LONG ; LD B,#20 ; !HARDCODE кол-во загружаемых секторов ; .set_drv: LD A,(DRIVE) ; RST ToBIOS_18 ; JP C,GOOD_DRIVE.NoShell ; POP HL ; ; [ ] загрузка system.dos больше #4000 байтов ; ;AND A ; ;RET ; LD A,(BIG_SHELL) ; OR A ; RET Z ; ; ; XOR A ; LD (BIG_SHELL),A ; PUSH HL ; CALL NSECTOR ; LD DE,#20 ; !HARDCODE кол-во прочитанных секторов ; AND A ; ADD IX,DE ; JR NC,.no_inc_hl ; INC HL ; .no_inc_hl: LD BC,SUBLOAD_SIZE*256 + BIOS.DRV_READ ; !HARDCODE кол-во ДОзагружаемых секторов ; LD DE,#4000 ; JR .set_drv ; ; ; .SMALL_CLUSTER: LD B,A ; LD A,(BANKDOS) ; EX AF,AF' ; LD A,(DRIVE) ; RST ToBIOS_18 ; JP C,GOOD_DRIVE.NoShell ; ; ; LD HL,(READMEM) ; LD DE,(CLU_LEN) ; ADD HL,DE ; LD (READMEM),HL ; ; [ ] загрузка system.dos больше #4000 байтов ; ;POP HL ; ;RET C ; CALL C,.more_than_1 ; POP HL ; RET C ; ; ; CALL R_F_FAT ; next cluster in chain ; RET C ; EX DE,HL ; JP .LD_FILE ; ; [ ] загрузка system.dos больше #4000 байтов ; .more_than_1: LD A,(BIG_SHELL) ; OR A ; SCF ; RET Z ; IN A,(SLOT1) ; LD HL,BANKDOS ; CP (HL) ; CCF ; RET Z ; LD (BANKDOS),A ; LD HL,#C000 ; LD (READMEM),HL ; LD A,(BOOT_BUFFER + BOOT_SECTOR.SectorsPerCluster) ; SUB SUBLOAD_SIZE + 1 ; CCF ; RET NC ; LD A,SUBLOAD_SIZE ; LD (BOOT_BUFFER + BOOT_SECTOR.SectorsPerCluster),A ; AND A ; RET ; ; --> HL - CLUSTER ; <-- HL:IX - SECTOR NSECTOR: LD DE,0 DEC HL DEC HL LD A,(BOOT_BUFFER + BOOT_SECTOR.SectorsPerCluster) XOR 1 JR Z,.skip ; RRA .loop: ADD HL,HL RL E RL D RRA JP NC,.loop ; .skip: EX DE,HL PUSH DE POP IX LD DE,(FatBuffer.FirstDataSector_L) ;first data sector XOR A ADD IX,DE LD D,A LD E,A ADC HL,DE ; LD DE,(DISKL) ADD IX,DE LD DE,(DISKH) ADC HL,DE RET ;----------------- ;!TODO сделать это макросами или инклюдами универсальными. повторяются в досе и ещё где-то ; HL - CLUSTER ; DE - (CLUSTER) R_F_FAT: PUSH HL LD A,(FatBuffer.FAT_TYPE) CP "2" JP Z,.R_F_F12 ; .R_F_F16: LD DE,768 ; DE - CLUSTERS IN CASH XOR A .R_F_00H: INC A ; HL - CLUSTER ; [ ] fat32 тут счётчик в 32 бита нужен или 16, если страницу FF использовать SBC HL,DE JP NC,.R_F_00H ADD HL,DE ADD HL,HL ; HL - FAT OFFSET (FROM CASH) DEC A LD BC,(FatBuffer.CacheBlock) ; A - ELEMENT OF CASH CP C CALL NZ,RE_FAT LD DE,FAT_SECTORS_BUFFER ADD HL,DE LD E,(HL) INC HL LD D,(HL) LD HL,#FFEF ; .exit: XOR A SBC HL,DE POP HL RET ; .R_F_F12 LD D,H LD E,L ADD HL,HL ADD HL,DE RR H RR L PUSH AF EX DE,HL LD HL,(BOOT_BUFFER + BOOT_SECTOR.BytesPerSector) LD B,H LD C,L ADD HL,HL ADD HL,BC EX DE,HL XOR A ; DE - SIZE SECTOR * 3 .R_F_00: INC A ; HL - FAT OFFSET SBC HL,DE JP NC,.R_F_00 ADD HL,DE DEC A LD BC,(FatBuffer.CacheBlock) CP C CALL NZ,RE_FAT LD DE,FAT_SECTORS_BUFFER ADD HL,DE POP AF LD E,(HL) INC HL LD D,(HL) JP C,.R_F_F01 LD A,D AND #0F LD D,A JR .R_F_F02 ; .R_F_F01: LD A,E AND #F0 RR D ; вправо на 4 битa RRA RR D RRA RR D RRA RR D RRA LD E,A ; .R_F_F02: LD HL,#0FEF JR .exit ; XOR A ; SBC HL,DE ; POP HL ; RET ; ; RE_FAT: PUSH HL LD L,A LD H,0 LD (FatBuffer.CacheBlock),HL LD E,L LD D,H ADD HL,HL ADD HL,DE LD IX,0 LD DE,(FatBuffer.FAT1_SEC_L) ADD HL,DE EX DE,HL JR NC,.NOINX INC IX .NOINX: LD HL,(DISKL) ADD HL,DE EX DE,HL LD BC,(DISKH) JR NC,.NOINX2 INC IX .NOINX2: ADD IX,BC PUSH IX PUSH DE POP IX POP HL LD DE,FAT_SECTORS_BUFFER LD BC,3*256 + BIOS.DRV_READ LD A,(DRIVE) RST ToBIOS_18 POP HL RET ; //////////////////////////////////////////////////////////////////////// ; Area for boot sector [512Bytes] ;BOOT _sBOOT_SECTOR_PARAMS = $ BOOT_BUFFER EQU $ DIR EQU BOOT_BUFFER+512 ; FAT_SECTORS_BUFFER EQU DIR+512 VALUE EQU 3*512+FAT_SECTORS_BUFFER ; FatBuffer EQU VALUE .CacheBlock EQU FatBuffer+0 ; FatCache .FAT1_SEC_L EQU FatBuffer+2 ; FAT_FRM MSD_FAT_SEC first sector FAT .RootDirFirstSector_H EQU FatBuffer+4 ; DIR_FRH MSD_CAT_SEC first sector DIR .RootDirFirstSector_L EQU FatBuffer+6 ; DIR_FRL MSD_CAT_SEC first sector DIR .DirSizeInSectors EQU FatBuffer+8 ; DIR_S_S DIR_SEC_SIZE .FirstDataSector_L EQU FatBuffer+9 ; DAT_FRM MSD_DAT_SEC .FAT_TYPE EQU FatBuffer+11; FAT_TYP ; !FIXIT TYPE FAT (#32 - 12bit, #36 - 16bit) .BytesPerCluster EQU FatBuffer+12; CLU_LEN ;.END_CHAIN_CLUSTER_L EQU FatBuffer+14; ENDCLUS ; FatCache EQU VALUE+0 ; .CacheBlock ; FAT_FRM EQU FatCache+2 ; .FAT1_SEC_L MSD_FAT_SEC first sector FAT ; DIR_FRH EQU FatCache+4 ; .RootDirFirstSector_H MSD_CAT_SEC first sector DIR ; DIR_FRL EQU FatCache+6 ; .RootDirFirstSector_L MSD_CAT_SEC first sector DIR ; DIR_S_S EQU FatCache+8 ; .DirSizeInSectors DIR_SEC_SIZE ; DAT_FRM EQU FatCache+9 ; .FirstDataSector_L MSD_DAT_SEC ; FAT_TYP EQU FatCache+11; .FAT_TYPE ; !FIXIT TYPE FAT (#32 - 12bit, #36 - 16bit) ; CLU_LEN EQU FatCache+12; .BytesPerCluster ; ENDCLUS EQU FatCache+14; .END_CHAIN_CLUSTER_L HANDBUF EQU VALUE+16 FCLUSTER32 EQU HANDBUF + FAT_DIRECTORY_RECORD.FIRST_CLUSTER_H ; FTIME EQU HANDBUF + FAT_DIRECTORY_RECORD.TIME ; FDATE EQU HANDBUF + FAT_DIRECTORY_RECORD.DATE FCLUSTR EQU HANDBUF + FAT_DIRECTORY_RECORD.FIRST_CLUSTER_L FSIZE0 EQU HANDBUF + FAT_DIRECTORY_RECORD.F_SIZE FSIZE1 EQU HANDBUF + FAT_DIRECTORY_RECORD.F_SIZE + 2 DISKH EQU VALUE+48 DISKL EQU VALUE+50 READMEM EQU VALUE+52 ;SHEL_FM EQU VALUE+54 BIG_CORE EQU VALUE+54 BANKDOS EQU VALUE+55 ; EQU VALUE+56 ;----------------- ; BLOCK #8600-$-3,0 ; DB 'SPT' ; BIGA EQU (($/256)+1)*256 ; BIGA2 EQU BIGA-$-2 ; DS BIGA2 ; DB "dp" ; E______ ;STACK EQU (($/256)+2)*256 ENT OUTEND ;[]-----------------------------------------------------------[]