;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 current drive and offset mov word [.pointer], bx mov dl, byte [drive] mov byte [.drive], dl ;Change the drive if needed ;Check for a drive specification cmp byte [si + 0x1], ":" jne .start ;Check which drive to change to cmp byte [si], "a" je .cha cmp byte [si], "A" je .cha cmp byte [si], "b" je .chb cmp byte [si], "B" je .chb cmp byte [si], "c" je .chc cmp byte [si], "C" je .chc cmp byte [si], "d" je .chd cmp byte [si], "D" je .chd ;Set the carry flag and print an error message stc mov si, .driverrormsg mov ah, 0x2 int 0x21 jmp .done ;Change .cha: mov dl, 0x0 mov byte [.drive], dl jmp .drivechanged .chb: mov dl, 0x1 mov byte [.drive], dl jmp .drivechanged .chc: mov dl, 0x2 mov byte [.drive], dl jmp .drivechanged .chd: mov dl, 0x3 mov byte [.drive], dl .drivechanged: add si, 0x2 .start: ;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 file 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 .error: pop ax stc mov si, .filerrormsg mov ah, 0x2 int 0x21 jmp .done ;Find and load the file .load: pop ax ;Load the disk description table ;Set the source mov dl, [.drive] mov ch, 0x0 mov dh, 0x0 mov cl, 0x1 ;Set the destination mov si, buffer mov bx, si ;Set the size mov al, 0x1 ;Load mov ah, 0x2 int 0x13 ;Set the carry flag and print an error message jnc .storevalues mov si, .diskerrormsg mov ah, 0x2 int 0x21 jmp .done ;Store the disk values used for the rest of the call .storevalues: mov ax, word [buffer + 0xb] mov word [.sectorsize], ax mov al, byte [buffer + 0xd] mov byte [.clustersize], al mov ax, word [buffer + 0xe] mov word [.bootsectors], ax mov al, byte [buffer + 0x10] mov byte [.fats], al mov ax, word [buffer + 0x11] mov word [.rootentries], ax mov ax, word [buffer + 0x16] mov word [.sectorsperfat], ax mov ax, word [buffer + 0x18] mov word [.sectorspertrack], ax mov ax, word [buffer + 0x1a] mov word [.sides], 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, .filerrormsg 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 ;Set the destination mov bx, word [.pointer] ;Load a sector mov ch, 0x0 mov cl, byte [.clustersize] .loadsector: push cx call .calcsource ;Set the size push ax mov al, 0x1 ;Load mov ah, 0x2 int 0x13 pop ax ;Set the next sector add ax, 0x1 add bx, word [.sectorsize] pop cx loop .loadsector ;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 .drive db 0x0 .sectorsize dw 0x0 ;bytes .clustersize db 0x0 ;sectors .bootsectors dw 0x0 .fats db 0x0 .rootentries dw 0x0 .sectorsperfat dw 0x0 .sectorspertrack dw 0x0 .sides dw 0x0 .file times 0xb db 0x20 .cluster dw 0x0 .pointer dw 0x0 .driverrormsg db "Drive not found", 0x0 .diskerrormsg db "Disk not found", 0x0 .filerrormsg db "File not found", 0x0 ;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 ;Decrease 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 [.drive] ret