gcc -o $@ $^
endif
-pcomm.com: ../../lib/crt/crt0.o cbreak.o cd.o crlf.o date.o del.o dir.o erase.o exit.o history.o mkdir.o pcomm.o time.o touch.o type.o vector.o writedec.o writehex.o writestr.o xmalloc.o xstrcpy.o ../../lib/crt/libc.a
+pcomm.com: ../../lib/crt/crt0.o cbreak.o cd.o crlf.o date.o del.o dir.o erase.o exit.o history.o mkdir.o pcomm.o rmdir.o time.o touch.o type.o vector.o writedec.o writehex.o writestr.o xmalloc.o xstrcpy.o ../../lib/crt/libc.a
../../utils/binutils/slink --oformat msdos -o $@ $^
%.o: %.asm
genver.exe: genver.c
gcc -o $@ $^
-pcomm.com: ../../lib/crt/crt0.o cbreak.o cd.o crlf.o date.o del.o dir.o erase.o exit.o history.o mkdir.o pcomm.o time.o touch.o type.o vector.o writedec.o writehex.o writestr.o xmalloc.o xstrcpy.o ../../lib/crt/libc.a
+pcomm.com: ../../lib/crt/crt0.o cbreak.o cd.o crlf.o date.o del.o dir.o erase.o exit.o history.o mkdir.o pcomm.o rmdir.o time.o touch.o type.o vector.o writedec.o writehex.o writestr.o xmalloc.o xstrcpy.o ../../lib/crt/libc.a
../../utils/binutils/slink --oformat msdos -o $@ $^
%.o: %.asm
mov ah, HEX (41)
mov dx, bx
int HEX (21)
- jnc _handler_del.deleted
+ jnc _handler_del.close
cmp ax, 2
jne _handler_del.check3
call _writestr
call _crlf
- jmp _handler_del.cleanup
+ jmp _handler_del.next
-_handler_del.deleted:
+_handler_del.close:
pop bx
+ mov bx, ax
+
+ mov ah, HEX (3E)
+ int HEX (21)
+
jmp _handler_del.next
_handler_del.cleanup:
db "EXIT Exit the current shell if it's not the last instance.", HEX (0D), HEX (0A)
db "MKDIR Create a new directory.", HEX (0D), HEX (0A)
db "REBOOT Reboots the machine.", HEX (0D), HEX (0A)
+ db "RMDIR Delete an empty directory.", HEX (0D), HEX (0A)
db "TIME Displays the system time.", HEX (0D), HEX (0A)
db "TOUCH Create a new file if it doesn't already exist.", HEX (0D), HEX (0A)
db "TYPE Displays the contents of a text file.", HEX (0D), HEX (0A)
dw 0
dw _handler_reboot
+ dw hash_rmdir
+ dw 0
+ dw _handler_rmdir
+
dw hash_time
dw 0
dw _handler_time
--- /dev/null
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; @file type.asm
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;******************************************************************************
+; @function _handler_rmdir
+;******************************************************************************
+global _handler_rmdir
+_handler_rmdir:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 4
+
+ push ax
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ mov word ptr [bp - 4], 0
+ mov word ptr [bp - 2], 0
+
+ cmp byte ptr [bx], 0
+ jne _handler_rmdir.ok
+
+ mov bx, offset _err_invalid
+ call _writestr
+
+ jmp _handler_rmdir.done
+
+_handler_rmdir.ok:
+
+ push bx
+
+ call _strlen
+ add sp, 2
+
+ mov di, offset _cmdline
+ mov si, bx
+
+ mov cx, ax
+ rep movsb
+
+ xor al, al
+ stosb
+
+ mov bx, offset _cmdline
+
+_handler_rmdir.store_arg:
+
+ cmp byte ptr [bx], 0
+ je _handler_rmdir.next
+
+ mov si, bx
+ push si
+
+ mov ax, offset _vec_files
+ push ax
+
+ call _vec_push
+ add sp, 4
+
+_handler_rmdir.check:
+
+ mov ax, ' '
+ push ax
+
+ mov si, bx
+ push si
+
+ call _strchr
+ add sp, 4
+
+ and ax, ax
+ jz _handler_rmdir.next
+
+ mov bx, ax
+ mov byte ptr [bx], 0
+
+ inc bx
+
+_handler_rmdir.skip:
+
+ cmp byte ptr [bx], 0
+ je _handler_rmdir.next
+
+ cmp byte ptr [bx], ' '
+ ja _handler_rmdir.store_arg
+
+ inc bx
+ jmp _handler_rmdir.skip
+
+_handler_rmdir.next:
+
+ mov ax, word ptr [bp - 4]
+ inc ax
+
+ cmp ax, cs:[_vec_files + 4]
+ ja _handler_rmdir.cleanup
+
+ mov word ptr [bp - 4], ax
+ dec ax
+
+ xor dx, dx
+
+ mov cx, 2
+ mul cx
+
+ mov bx, ax
+ push es
+
+ mov ax, cs:[_vec_files + 0]
+ mov es, ax
+
+ mov ax, es:[bx]
+ mov bx, ax
+
+ pop es
+
+_handler_rmdir.delete:
+
+ mov ah, HEX (3A)
+ mov dx, bx
+ int HEX (21)
+ jnc _handler_rmdir.next
+
+ mov cx, bx
+
+ cmp ax, 3
+ jne _handler_rmdir.check3
+
+ mov bx, offset _err_failed
+ jmp _handler_rmdir.error
+
+_handler_rmdir.check3:
+
+ cmp ax, 16
+ jne _handler_rmdir.unhandled
+
+ mov bx, offset _err_current
+ jmp _handler_rmdir.error
+
+_handler_rmdir.unhandled:
+
+ mov bx, offset _err_unhandled
+
+_handler_rmdir.error:
+
+ cmp ax, 3
+ jne _handler_rmdir.error2
+
+ xchg bx, cx
+ call _writestr
+
+ xchg bx, cx
+
+_handler_rmdir.error2:
+
+ call _writestr
+
+ cmp ax, 16
+ jne _handler_rmdir.next
+
+ mov bx, cx
+
+ call _writestr
+ call _crlf
+
+ jmp _handler_rmdir.next
+
+_handler_rmdir.cleanup:
+
+ mov ax, cs:[_vec_files + 0]
+ push ax
+
+ call _free
+ add sp, 2
+
+ mov ax, cs
+ mov es, ax
+
+ mov di, offset _vec_files
+ xor al, al
+
+ mov cx, 6
+ rep stosb
+
+_handler_rmdir.done:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+
+ add sp, 4
+ pop bp
+
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_vec_files: db 6 dup (0)
+_cmdline: db 256 dup (0)
+
+_err_invalid: db "Invalid number of parameters", HEX (0D), HEX (0A), HEX (00)
+
+_err_failed: db " is either an invalid directory, not a directory or is not empty", HEX (0D), HEX (0A), HEX (00)
+_err_current: db "Attempt to remove current directory: ", HEX (00)
+
+_err_unhandled: db "Unhandled error code", HEX (0D), HEX (0A), HEX (00)
for f in *.lst; do if [ -f $$f ]; then rm -rf $$f; fi; done
if [ -f kernel.sys ]; then rm -rf kernel.sys; fi
-kernel.sys: bootstrap.o crlf.o disk.o divide.o error.o fat.o file.o find.o int21.o int23.o invalid.o kernel.o kmalloc.o krealloc.o make.o mangle.o mem.o prog.o query.o search.o vector.o walk.o writechr.o writedec.o writehex.o writestr.o ../lib/crt/libc.a
+kernel.sys: bootstrap.o crlf.o disk.o divide.o error.o fat.o file.o find.o get.o int21.o int23.o invalid.o kernel.o kmalloc.o krealloc.o make.o mangle.o mem.o prog.o query.o search.o vector.o walk.o writechr.o writedec.o writehex.o writestr.o ../lib/crt/libc.a
../utils/binutils/slink --oformat binary -o $@ $^
%.o: %.asm
for %%f in (*.lst) do ( if exist %%f ( del /q %%f ) )
if exist kernel.sys ( del /q kernel.sys )
-kernel.sys: bootstrap.o crlf.o disk.o divide.o error.o fat.o file.o find.o int21.o int23.o invalid.o kernel.o kmalloc.o krealloc.o make.o mangle.o mem.o prog.o query.o search.o vector.o walk.o writechr.o writedec.o writehex.o writestr.o ../lib/crt/libc.a
+kernel.sys: bootstrap.o crlf.o disk.o divide.o error.o fat.o file.o find.o get.o int21.o int23.o invalid.o kernel.o kmalloc.o krealloc.o make.o mangle.o mem.o prog.o query.o search.o vector.o walk.o writechr.o writedec.o writehex.o writestr.o ../lib/crt/libc.a
../utils/binutils/slink --oformat binary -o $@ $^
%.o: %.asm
;; Calculate the sector shift.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
xor cx, cx
+
xchg ax, cx
+ inc cx
_secshift:
--- /dev/null
+;******************************************************************************
+; @file search.asm
+;******************************************************************************
+%ifndef HEX
+% define HEX(y) 0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Include our fat.inc file for our BPB offsets.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%include "fat.inc"
+
+;******************************************************************************
+; @function _get_files
+;******************************************************************************
+global _get_files
+_get_files:
+
+ push bp
+
+ mov bp, sp
+ sub sp, 34
+
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ mov word ptr [bp - 32], 0
+
+ mov word ptr [bp - 20], 0
+ mov word ptr [bp - 16], 0
+
+ mov bx, ax
+ or bx, dx
+
+ and bx, bx
+ jnz _get_files.not_root
+
+ mov ax, cs:[_root_start]
+ mov dx, cs:[_root_start + 2]
+
+_get_files.got_root:
+
+ mov word ptr [bp - 30], 1
+ mov word ptr [bp - 24], 1
+
+ mov word ptr [bp - 28], ax
+ mov word ptr [bp - 26], dx
+
+ mov ax, 32
+ xor dx, dx
+
+ mov cx, cs:[_root_entries]
+ mul cx
+
+ mov cx, cs:[_bytes_per_sector]
+ div cx
+
+ xchg cx, ax
+ dec cx
+
+ xor dx, dx
+ mov word ptr [bp - 22], cx
+
+ mov ax, word ptr [bp - 28]
+ mov dx, word ptr [bp - 26]
+
+ mov word ptr [bp - 6], ax
+ mov word ptr [bp - 4], dx
+
+ jmp _get_files.read
+
+_get_files.not_root:
+
+ mov word ptr [bp - 30], 0
+ mov word ptr [bp - 24], 1
+
+ mov word ptr [bp - 28], ax
+ mov word ptr [bp - 26], dx
+
+ call cs:[_convert_cluster]
+ jc _get_files.done
+
+ mov word ptr [bp - 6], ax
+ mov word ptr [bp - 4], dx
+
+ xor ch, ch
+ mov cl, cs:[_sectors_per_cluster]
+
+ mov word ptr [bp - 34], cx
+ dec word ptr [bp - 34]
+
+_get_files.read:
+
+ mov bx, cs:[_disk_scratch]
+ mov es, bx
+ xor bx, bx
+
+ mov ax, word ptr [bp - 6]
+ mov dx, word ptr [bp - 4]
+
+ mov cx, word ptr [bp - 24]
+ call _read_sectors
+
+ mov ax, cs:[_bytes_per_sector]
+ xor dx, dx
+
+ mov cx, 32
+ div cx
+ xchg cx, ax
+
+ xor di, di
+
+_get_files.search:
+
+ cmp byte ptr es:[di], 0
+ je _get_files.advance
+
+ cmp byte ptr es:[di], HEX (E5)
+ je _get_files.advance
+
+ inc word ptr [bp - 32]
+
+_get_files.advance:
+
+ add di, 32
+ loop _get_files.search
+
+ cmp word ptr [bp - 30], 1
+ jne _get_files.check
+
+ mov ax, word ptr [bp - 22]
+
+ and ax, ax
+ jz _get_files.done
+
+ dec ax
+ mov word ptr [bp - 22], ax
+
+ mov ax, word ptr [bp - 6]
+ mov dx, word ptr [bp - 4]
+
+ add ax, word ptr [bp - 24]
+ adc dx, 0
+
+ mov word ptr [bp - 6], ax
+ mov word ptr [bp - 4], dx
+
+ jmp _get_files.read
+
+_get_files.check:
+
+ mov ax, word ptr [bp - 34]
+
+ and ax, ax
+ jz _get_files.next_clust
+
+ dec ax
+ mov word ptr [bp - 34], ax
+
+ mov ax, word ptr [bp - 6]
+ mov dx, word ptr [bp - 4]
+
+ add ax, word ptr [bp - 24]
+ adc dx, 0
+
+ mov word ptr [bp - 6], ax
+ mov word ptr [bp - 4], dx
+
+ jmp _get_files.read
+
+_get_files.next_clust:
+
+ mov ax, word ptr [bp - 28]
+ mov dx, word ptr [bp - 26]
+
+ call cs:[_next_cluster]
+ jmp _get_files.not_root
+
+_get_files.done:
+
+ mov ax, word ptr [bp - 32]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore registers.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Clean up the stack and restore the base pointer.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ add sp, 34
+ pop bp
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Return to caller.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ret
db HEX (39)
dw _int21_39
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Delete Directory (rmdir).
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ db HEX (3A)
+ dw _int21_3A
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Set Current Directory.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
jmp iretc
+;******************************************************************************
+; @function _int21_3A
+; @brief Delete Directory (rmdir)
+;
+; @in DS:DX -> Pointer to ASCIIZ path name.
+;******************************************************************************
+_int21_3A:
+
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push es
+ push ds
+
+ mov si, dx
+
+ call _get_disk_info
+ jc _int21_3A.error_path
+
+ mov di, si
+
+ call _walk_path
+ jc _int21_3A.error_path
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Mangle the file name and search for it in the file system.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ call _mangle_dos_name
+ jc _int21_3A.error_path
+
+ call _search_dos_dir
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; If the carry flag was set then the entry doesn't exists.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jc _int21_3A.error_path
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Transfer the offset in ax to the si register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov si, ax
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Check if the entry is a directory.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov cl, cs:[si + 8]
+
+ test cl, HEX (10)
+ jz _int21_3A.error_path
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Check the starting cluster is the root cluster.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[si + 0]
+ mov dx, cs:[si + 2]
+
+ cmp dx, cs:[_root_cluster + 2]
+ ja _int21_3A.get_files
+
+ cmp dx, cs:[_root_cluster + 2]
+ jne _int21_3A.error_path
+
+ cmp ax, cs:[_root_cluster]
+ jbe _int21_3A.error_path
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Check if the starting cluster is the current cluster.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ cmp dx, cs:[_curr_cluster + 2]
+ ja _int21_3A.get_files
+
+ cmp dx, cs:[_curr_cluster + 2]
+ jne _int21_3A.curr_dir
+
+ cmp ax, cs:[_curr_cluster]
+ je _int21_3A.curr_dir
+
+_int21_3A.get_files:
+
+ call _get_files
+
+ cmp ax, 2
+ jb _int21_3A.error_path
+
+ sub ax, 2
+
+ and ax, ax
+ jnz _int21_3A.error_path
+
+_int21_3A.remove:
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Get the starting cluster again.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[si + 0]
+ mov dx, cs:[si + 2]
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the si register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; We'll use the cx register as a counter.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor cx, cx
+
+_int21_3A.clear:
+
+ push ax
+ push dx
+
+ call cs:[_next_cluster]
+ jc _int21_3A.clear_final
+
+ mov si, ax
+ mov di, dx
+
+ pop dx
+ pop ax
+
+ push bx
+ push cx
+
+ xor bx, bx
+ xor cx, cx
+
+ call cs:[_update_cluster]
+
+ pop cx
+ pop bx
+
+ inc cx
+
+ mov ax, si
+ mov dx, si
+
+ jmp _int21_3A.clear
+
+_int21_3A.clear_final:
+
+ inc cx
+
+ pop dx
+ pop ax
+
+ push bx
+ push cx
+
+ xor bx, bx
+ xor cx, cx
+
+ call cs:[_update_cluster]
+ pop cx
+ pop bx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the si register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Preserve the count.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ push cx
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Update the entry on disk.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[si + 10]
+ mov dx, cs:[si + 12]
+
+ mov cx, cs:[si + 14]
+ mov di, cs:[si + 16]
+
+ push es
+ push bx
+ push ax
+ push dx
+ push cx
+
+ mov bx, cs:[_disk_scratch]
+ mov es, bx
+
+ xor bx, bx
+ call _read_sectors
+
+ mov byte ptr es:[di + 0], HEX (E5)
+ pop cx
+ pop dx
+ pop ax
+
+ xor bx, bx
+ call _write_sectors
+
+ pop bx
+ pop es
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Restore the value in the cx register.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ pop si
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Check if we have an info sector.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ mov ax, cs:[_info_sector]
+
+ and ax, ax
+ jz _int21_41.done
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Update the free clusters.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ xor dx, dx
+
+ add ax, cs:[_hidden_sectors]
+ adc dx, cs:[_hidden_sectors + 2]
+
+ mov bx, cs:[_disk_scratch]
+ mov es, bx
+ xor bx, bx
+
+ mov cx, 1
+ call _read_sectors
+
+ mov di, HEX (01E0)
+
+ mov ax, es:[di + 8]
+ mov dx, es:[di + 10]
+
+ add ax, si
+ adc dx, 0
+
+ mov es:[di + 8], ax
+ mov es:[di + 10], dx
+
+ mov ax, cs:[_info_sector]
+ xor dx, dx
+
+ add ax, cs:[_hidden_sectors]
+ adc dx, cs:[_hidden_sectors + 2]
+
+ mov cx, 1
+ call _write_sectors
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; Jump to done.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ jmp _int21_3A.done
+
+_int21_3A.error_path:
+
+ mov ax, 3
+ jmp _int21_3A.error
+
+_int21_3A.curr_dir:
+
+ mov ax, 16
+
+_int21_3A.error:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ stc
+ jmp iretc
+
+_int21_3A.done:
+
+ pop ds
+ pop es
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+
+ xor ax, ax
+ clc
+
+ jmp iretc
+
;******************************************************************************
; @function _int21_3B
; @brief Set Current Directory