;Load a file named in SI as a string ending in a null to the offset BX and set AL to 0x0 if the load was succesful and 0x1 if there was an error. loadf: ;Store the initial registers in the stack push ax push bx push cx push dx push si push di ;Store the offset mov word [.pointer], bx ;Set DI at .file and initialise it with spaces mov di, .file mov cx, 0xb mov al, 0x20 rep stosb sub di, 0xb ;Convert .file into FAT formatting ;Initialise the length counter for the main part of the name mov bl, 0x8 ;Convert the main part of the file name .nameloop: ;Load a character lodsb ;Check for a period cmp al, 0x2e je .initext ;Check for everything else and convert to upper case call .checkconv jmp .nameloop ;Convert the extension .initext: ;Set DI and initialise the length counter for the extension mov bl, 0x3 mov di, .file+0x8 .extloop: ;Load a character lodsb ;Check for a period push ax cmp al, 0x2e je .error pop ax ;Check for everything else and convert to upper case call .checkconv jmp .extloop ;Set the carry flag and print an error message if the file name is invalid .error: pop ax stc mov si, .errormsg mov ah, 0x2 int 0x21 jmp .done ;Find and load the file .load: pop ax ;Load the root ;Set the source mov ah, 0x0 mov al, [.fats] mul word [.sectorsperfat] add ax, [.bootsectors] push ax call .calcsource ;Set the destination mov si, buffer mov bx, si ;Set the size push dx mov ax, [.rootentries] mov dx, 0x20 mul dx mov dx, 0x0 div word [.sectorsize] pop dx push ax ;Load mov ah, 0x2 int 0x13 ;Search the root for the file entry ;Set DI to the root mov di, buffer ;Initialise the search loop mov cx, word [.rootentries] mov ax, 0x0 .search: ;Store CX in the stack push cx ;Check for the file entry mov si, .file mov cx, 0xb rep cmpsb je .loadentry ;Set DI to the next entry add ax, 0x20 mov di, buffer add di, ax ;Load CX from the stack pop cx loop .search ;Set the carry flag and print an error message if the file is not found stc mov si, .errormsg mov ah, 0x2 int 0x21 jmp .clearstack ;Load the file entry .loadentry: ;Load CX from the stack pop cx ;Store the first cluster mov ax, word [es:di+0xf] mov word [.cluster], ax ;Set the source mov ax, 0x1 call .calcsource ;Set the destination mov di, buffer mov bx, di ;Set the size mov ax, [.sectorsperfat] ;Load mov ah, 0x2 int 0x13 ;Load the file ;Load a cluster .loadcluster: ;Set the source pop cx pop bx mov ax, word [.cluster] sub ax, 0x2 mul byte [.clustersize] add ax, bx add ax, cx push bx push cx call .calcsource ;Set the destination mov bx, word [.pointer] ;Set the size ;mov al, 0x1 mov al, [.clustersize] ;Load mov ah, 0x2 int 0x13 ;Calculate the next cluster mov ax, [.cluster] mov dx, 0x0 mov bx, 0x3 mul bx mov bx, 0x2 div bx mov si, buffer add si, ax mov ax, word [ds:si] or dx, dx jz .even shr ax, 1 shr ax, 1 shr ax, 1 shr ax, 1 jmp .contcalc .even: and ax, 0xfff .contcalc: mov word [.cluster], ax cmp ax, 0xff8 jge .clearcarry mov ax, [.sectorsize] mul word [.clustersize] add word [.pointer], ax jmp .loadcluster ;Clear the carry flag if the load was succesful .clearcarry: clc ;Clear the stack .clearstack: pop cx pop bx .done: ;Load the initial registers from the stack pop di pop si pop dx pop cx pop bx pop ax ;Set AL to 0x1 if there was an error and to 0x0 otherwise and return jc .setal mov al, 0x0 iret .setal: mov al, 0x1 iret ;Data .file times 0xb db 0x20 .errormsg db "File not found", 0x0 .cluster dw 0x0 .pointer dw 0x0 ;These are temporary until i write something to load them from the disk itself .bootdrive db 0x0 .sectorsize dw 0x200 ;bytes .clustersize db 0x2 ;sectors .bootsectors dw 0x1 .fats db 0x2 .rootentries dw 0x70 .sectorsperfat dw 0x2 .sectorspertrack dw 0x9 .sides dw 0x2 ;Check the file name and convert to upper case .checkconv: ;Check for the string end cmp al, 0x0 je .load ;Check for the length limit cmp bl, 0x0 je .error ;Check for invalid characters cmp al, 0x22 je .error cmp al, 0x2a jl .contcheck1 cmp al, 0x2c jg .contcheck1 jmp .error .contcheck1: cmp al, 0x2f je .error cmp al, 0x3a jl .contcheck2 cmp al, 0x3f jg .contcheck2 jmp .error .contcheck2: cmp al, 0x5b jl .contcheck3 cmp al, 0x5d jg .contcheck3 jmp .error .contcheck3: cmp al, 0x7c je .error ;Check for lower case cmp al, 0x61 jl .storech cmp al, 0x7a jg .storech ;Convert lower to upper case sub al, 0x20 .storech: ;Store the character stosb ;Increase the counter dec bl ret ;Calculate the source arguments for loading data from the disk .calcsource: push ax push bx mov bx, ax mov dx, 0x0 div word [.sectorspertrack] add dl, 0x1 mov cl, dl mov ax, bx mov dx, 0x0 div word [.sectorspertrack] mov dx, 0x0 div word [.sides] mov dh, dl mov ch, al pop bx pop ax mov dl, byte [.bootdrive] ret