From: Robert Pengelly Date: Tue, 6 Aug 2024 16:02:27 +0000 (+0100) Subject: Implemented int 21h/AH=3A X-Git-Url: https://git.candlhat.org/?a=commitdiff_plain;h=95bdbe46d7fa6d93f8d5ca6d6e56ad811cce028a;p=chimaera.git Implemented int 21h/AH=3A --- diff --git a/build/chimaera.img b/build/chimaera.img index f77702e..23b8a08 100644 Binary files a/build/chimaera.img and b/build/chimaera.img differ diff --git a/build/chimaera.vhd b/build/chimaera.vhd index 768d5a4..e6582f5 100644 Binary files a/build/chimaera.vhd and b/build/chimaera.vhd differ diff --git a/src/apps/pcomm/Makefile.unix b/src/apps/pcomm/Makefile.unix index b256c62..bdad935 100644 --- a/src/apps/pcomm/Makefile.unix +++ b/src/apps/pcomm/Makefile.unix @@ -46,7 +46,7 @@ genver: genver.c 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 diff --git a/src/apps/pcomm/Makefile.w32 b/src/apps/pcomm/Makefile.w32 index ddfdcfc..7f03f20 100644 --- a/src/apps/pcomm/Makefile.w32 +++ b/src/apps/pcomm/Makefile.w32 @@ -30,7 +30,7 @@ genhash.exe: genhash.c 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 diff --git a/src/apps/pcomm/del.asm b/src/apps/pcomm/del.asm index 154872a..d9c086e 100644 --- a/src/apps/pcomm/del.asm +++ b/src/apps/pcomm/del.asm @@ -132,7 +132,7 @@ _handler_del.delete: 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 @@ -168,11 +168,16 @@ _handler_del.error: 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: diff --git a/src/apps/pcomm/pcomm.asm b/src/apps/pcomm/pcomm.asm index 755fc5f..22a54ef 100644 --- a/src/apps/pcomm/pcomm.asm +++ b/src/apps/pcomm/pcomm.asm @@ -1076,6 +1076,7 @@ _handler_help.msg: 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) @@ -1307,6 +1308,10 @@ _cmd_table: dw 0 dw _handler_reboot + dw hash_rmdir + dw 0 + dw _handler_rmdir + dw hash_time dw 0 dw _handler_time diff --git a/src/apps/pcomm/rmdir.asm b/src/apps/pcomm/rmdir.asm new file mode 100644 index 0000000..bc06adc --- /dev/null +++ b/src/apps/pcomm/rmdir.asm @@ -0,0 +1,223 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; @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) diff --git a/src/kernel/Makefile.unix b/src/kernel/Makefile.unix index ec98783..b8922e9 100644 --- a/src/kernel/Makefile.unix +++ b/src/kernel/Makefile.unix @@ -13,7 +13,7 @@ clean: 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 diff --git a/src/kernel/Makefile.w32 b/src/kernel/Makefile.w32 index 202bd39..d867896 100644 --- a/src/kernel/Makefile.w32 +++ b/src/kernel/Makefile.w32 @@ -13,7 +13,7 @@ clean: 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 diff --git a/src/kernel/bootstrap.asm b/src/kernel/bootstrap.asm index 28231f0..3dad07f 100644 --- a/src/kernel/bootstrap.asm +++ b/src/kernel/bootstrap.asm @@ -303,7 +303,9 @@ _calc_offsets: ;; Calculate the sector shift. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; xor cx, cx + xchg ax, cx + inc cx _secshift: diff --git a/src/kernel/get.asm b/src/kernel/get.asm new file mode 100644 index 0000000..9b84031 --- /dev/null +++ b/src/kernel/get.asm @@ -0,0 +1,208 @@ +;****************************************************************************** +; @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 diff --git a/src/kernel/int21.asm b/src/kernel/int21.asm index 6f189c3..8a0b2ae 100644 --- a/src/kernel/int21.asm +++ b/src/kernel/int21.asm @@ -830,6 +830,12 @@ _int21_dispatch.list: db HEX (39) dw _int21_39 + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Delete Directory (rmdir). + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + db HEX (3A) + dw _int21_3A + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Set Current Directory. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -1764,6 +1770,296 @@ _int21_39.done: 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