Implemented mkdir
authorRobert Pengelly <robertapengelly@hotmail.com>
Mon, 5 Aug 2024 09:40:46 +0000 (10:40 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Mon, 5 Aug 2024 09:40:46 +0000 (10:40 +0100)
19 files changed:
build/chimaera.img
build/chimaera.vhd
src/Makefile.unix
src/Makefile.w32
src/apps/hello/hello.asm
src/apps/pcomm/Makefile.unix
src/apps/pcomm/Makefile.w32
src/apps/pcomm/dir.asm
src/apps/pcomm/mkdir.asm [new file with mode: 0644]
src/apps/pcomm/pcomm.asm
src/apps/pcomm/type.asm
src/kernel/Makefile.unix
src/kernel/Makefile.w32
src/kernel/disk.asm
src/kernel/fat.asm
src/kernel/file.asm
src/kernel/int21.asm
src/kernel/make.asm [new file with mode: 0644]
src/kernel/walk.asm

index b02386d1b16436c8ed65d88b01c5ee59dfad7d54..c8767c1233d093e2b062d5037a6c062af85f2813 100644 (file)
Binary files a/build/chimaera.img and b/build/chimaera.img differ
index 98393defcda3850b26f73fddcf38e0bdd68b54e7..38de4898930509ab5fe0f056527f9fb315daf253 100644 (file)
Binary files a/build/chimaera.vhd and b/build/chimaera.vhd differ
index 2f65ea2018560a2e52c8e94cb92113515ae8c497..5fc771150c6c1b36474d16a0b8ccf0a64798fc6e 100644 (file)
@@ -34,9 +34,12 @@ chimaera.img: all
 chimaera.vhd: all
        if [ -f $@ ]; then rm -rf $@; fi
 
+#      utils/parted/parted --arca --boot boot/mbr/dosmbr.bin mkpart 128,06,17,65535 $@
+#      utils/dosfstools/mkdosfs --arca --boot boot/freeldr/bootsect/fat16.bin --offset 17 --sectors 65535 -F 16 -n "CHIMAERA OS" $@
+
        utils/parted/parted --arca --boot boot/mbr/dosmbr.bin mkpart 128,11,17,66623 $@
        utils/dosfstools/mkdosfs --arca --boot boot/freeldr/bootsect/fat32_chs.bin --offset 17 --sectors 66623 -F 32 -n "CHIMAERA OS" $@
-
+       
        utils/dosfstools/mmd --arca --offset 17 -i $@ boot boot/freeldr
 
        utils/dosfstools/mcopy --arca --offset 17 -i $@ $(SRCDIR)/boot/freeldr/freeldr.cfg ::/boot/freeldr/
index ce995b5ca1970bda37fe3c8f556485b14650a348..9b4bec3531a8f844d54c37e9410c7d25fd36b47d 100644 (file)
@@ -33,7 +33,7 @@ chimaera.img: all
 chimaera.vhd: all
        if exist $@ ( del /q $@ )
 
-       utils/parted/parted --arca --boot boot/mbr/dosmbr.bin mkpart 128,11,17,65535 $@
+       utils/parted/parted --arca --boot boot/mbr/dosmbr.bin mkpart 128,06,17,65535 $@
        utils/dosfstools/mkdosfs --arca --boot boot/freeldr/bootsect/fat16.bin --offset 17 --sectors 65535 -F 16 -n "CHIMAERA OS" $@
 
        utils/dosfstools/mmd --arca --offset 17 -i $@ boot boot/freeldr
index f477f8e6695331f3c186ded324af258c24cd468d..cea0de6be7d19ada0f7c3db991da5ee4d0978df0 100644 (file)
@@ -16,20 +16,41 @@ _main:
     call    _writestr
     call    _crlf
     
-    mov     ah,     HEX (08)
+;    mov     ah,     HEX (08)
+;    int     HEX (21)
+;    
+;    call    _writehex
+;    call    _crlf
+;    
+;    mov     ah,     HEX (07)
+;    int     HEX (21)
+;    
+;    call    _writehex
+;    call    _crlf
+;    
+;    xor     ax,     ax
+;    int     HEX (16)
+    
+    mov     ah,     HEX (39)
+    mov     dx,     offset _dir_non_exist
     int     HEX (21)
     
     call    _writehex
     call    _crlf
     
-    mov     ah,     HEX (07)
+    mov     ah,     HEX (39)
+    mov     dx,     offset _dir_exist
     int     HEX (21)
     
     call    _writehex
     call    _crlf
     
-    xor     ax,     ax
-    int     HEX (16)
+    mov     ah,     HEX (39)
+    mov     dx,     offset _dir_file
+    int     HEX (21)
+    
+    call    _writehex
+    call    _crlf
     
     xor     ax,     ax
     ret
@@ -38,3 +59,7 @@ _main:
 ;; Data area.
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 msg_hello:                      db      "Hello, world!",        HEX (0D),   HEX (0A),   HEX (00)
+
+_dir_non_exist:                 db      "abc\\123",             HEX (00)
+_dir_exist:                     db      "temp",                 HEX (00)
+_dir_file:                      db      "hello.com",            HEX (00)
index ddb3cc13d0971e8aa3a968563313a0bb6a74e89b..7edf7ba199d0765ffa128c69f126347b77ae5ddf 100644 (file)
@@ -46,7 +46,7 @@ genver: genver.c
        gcc -o $@ $^
 endif
 
-pcomm.com: ../../lib/crt/crt0.o cbreak.o cd.o crlf.o date.o dir.o erase.o exit.o history.o pcomm.o time.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 dir.o erase.o exit.o history.o mkdir.o pcomm.o time.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
index 176b539941e0ed62afe574e8c5c5d124c7629213..4a11f17c0364edc236d92c268ba393d59cc722a1 100644 (file)
@@ -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 dir.o erase.o exit.o history.o pcomm.o time.o type.o vector.o writedec.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 dir.o erase.o exit.o history.o mkdir.o pcomm.o time.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
index 2e4a9d5c96ca0653494c500d2ff1a10b282957e3..8a86bf59dace3b350461bcac50e23e81df7656b0 100644 (file)
@@ -72,7 +72,7 @@ _handler_dir.got_path:
     
     mov     bx,     offset _cmdline
 
-_handler_dir.store_file:
+_handler_dir.store_arg:
 
     cmp     byte ptr [bx],      0
     je      _handler_dir.check2
@@ -111,7 +111,7 @@ _handler_dir.skip:
     je      _handler_dir.check2
     
     cmp     byte ptr [bx],      ' '
-    ja      _handler_dir.store_file
+    ja      _handler_dir.store_arg
     
     inc     bx
     jmp     _handler_dir.skip
diff --git a/src/apps/pcomm/mkdir.asm b/src/apps/pcomm/mkdir.asm
new file mode 100644 (file)
index 0000000..416d917
--- /dev/null
@@ -0,0 +1,189 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; @file            mkdir.asm
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%ifndef     HEX
+% define        HEX(y)                  0x##y
+%endif
+
+;******************************************************************************
+; @function         _handler_mkdir
+;******************************************************************************
+global      _handler_mkdir
+_handler_mkdir:
+
+    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_mkdir.ok
+    
+    mov     bx,     offset _err_invalid
+    call    _writestr
+    
+    jmp     _handler_mkdir.done
+
+_handler_mkdir.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_mkdir.store_arg:
+
+    cmp     byte ptr [bx],      0
+    je      _handler_mkdir.next
+    
+    mov     si,     bx
+    push    si
+    
+    mov     ax,     offset _vec_files
+    push    ax
+    
+    call    _vec_push
+    add     sp,     4
+
+_handler_mkdir.check:
+
+    mov     ax,     ' '
+    push    ax
+    
+    mov     si,     bx
+    push    si
+    
+    call    _strchr
+    add     sp,     4
+    
+    and     ax,     ax
+    jz      _handler_mkdir.next
+    
+    mov     bx,     ax
+    mov     byte ptr [bx],      0
+    
+    inc     bx
+
+_handler_mkdir.skip:
+
+    cmp     byte ptr [bx],      0
+    je      _handler_mkdir.next
+    
+    cmp     byte ptr [bx],      ' '
+    ja      _handler_mkdir.store_arg
+    
+    inc     bx
+    jmp     _handler_mkdir.skip
+
+_handler_mkdir.next:
+
+    mov     ax,     word ptr [bp - 4]
+    inc     ax
+    
+    cmp     ax,     cs:[_vec_files + 4]
+    ja      _handler_mkdir.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_mkdir.open:
+
+    mov     ah,     HEX (39)
+    mov     dx,     bx
+    int     HEX (21)
+    jnc     _handler_mkdir.next
+    
+_handler_mkdir.error:
+
+    push    bx
+    
+    mov     bx,     offset _err_failed
+    call    _writestr
+    
+    pop     bx
+    
+    call    _writestr
+    call    _crlf
+    
+    jmp     _handler_mkdir.next
+
+_handler_mkdir.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_mkdir.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      "Unable to create directory - ",    HEX (00)
index 703de21e7836fcb84a807e56b20eab71010027c2..e2aea7b094baa91d07c0f6841b2ce3e985f3696d 100644 (file)
@@ -253,6 +253,31 @@ _main:
     call    _strlen
     add     sp,     2
     
+    add     bx,     ax
+
+.L54:
+
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; If there was no string then we skip the following code.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    and     ax,     ax
+    jz      .L55
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; If the last character is not an asterisk then we have the
+    ;; right length.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    cmp     byte ptr [bx - 1],      '*'
+    jne     .L55
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; Otherwise, decrement ax by one as our command line doesn't
+    ;; have the asterisk character.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    dec     ax
+
+.L55:
+
     mov     bx,     ax
     jmp     .L41
 
@@ -1048,6 +1073,7 @@ _handler_help.msg:
     db      "DIR        Displays a list of files and subdirectories in a directory.",       HEX (0D),   HEX (0A)
     db      "ECHO       Specifies the text to display to the screen.",                      HEX (0D),   HEX (0A)
     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      "TIME       Displays the system time.",                                         HEX (0D),   HEX (0A)
     db      "TYPE       Displays the contents of a text file.",                             HEX (0D),   HEX (0A)
@@ -1267,6 +1293,10 @@ _cmd_table:
     dw      0
     dw      _handler_help
     
+    dw      hash_mkdir
+    dw      0
+    dw      _handler_mkdir
+    
     dw      hash_reboot
     dw      0
     dw      _handler_reboot
index 4d504cf51058c2160457d83d5e6d3bfb03897ba1..da8d569a84d66b61076722996eded3d291eee185 100644 (file)
@@ -54,7 +54,7 @@ _handler_type.ok:
     
     mov     bx,     offset _cmdline
 
-_handler_type.store_file:
+_handler_type.store_arg:
 
     cmp     byte ptr [bx],      0
     je      _handler_type.next
@@ -93,7 +93,7 @@ _handler_type.skip:
     je      _handler_type.next
     
     cmp     byte ptr [bx],      ' '
-    ja      _handler_type.store_file
+    ja      _handler_type.store_arg
     
     inc     bx
     jmp     _handler_type.skip
@@ -177,12 +177,6 @@ _handler_type.file_open:
 
 _handler_type.clear_and_read:
 
-    mov     di,     offset _buffer
-    xor     al,     al
-    
-    mov     cx,     256
-    rep     stosb
-    
     mov     ah,     HEX (3F)
     mov     cx,     255
     mov     dx,     offset _buffer
@@ -192,15 +186,13 @@ _handler_type.clear_and_read:
     and     ax,     ax
     jz      _handler_type.close
     
-    mov     si,     offset _buffer
+    mov     si,     dx
+    mov     cx,     ax
 
 _handler_type.print_loop:
 
     lodsb
     
-    and     al,     al
-    jz      _handler_type.clear_and_read
-    
     cmp     al,     HEX (0A)
     jne     _handler_type.char_ok
     
@@ -218,7 +210,12 @@ _handler_type.char_ok:
     mov     dl,     al
     int     HEX (21)
     
-    jmp     _handler_type.print_loop
+    dec     cx
+    jnz     _handler_type.print_loop
+
+_handler_type.read_done:
+
+    jmp     _handler_type.clear_and_read
 
 _handler_type.close:
 
index 8be5e8a26316d13a5954e7290e5fae564056e76e..ec98783bd772917d925b42b96c7cc295f6fe9c2f 100644 (file)
@@ -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 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 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
index d444a134fe8b6c9df7aa84d672031065c047edcc..202bd392b16cc8e7b228db605b4f5cdfc7d0e93d 100644 (file)
@@ -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 int21.o int23.o invalid.o kernel.o kmalloc.o krealloc.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 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
index 64fba99bd552e5e44942ab4a2d5975ea9c202ae0..ded082d50458258a5a8fa3cc2ddb5606caf3d64b 100644 (file)
@@ -139,7 +139,7 @@ _get_partition_info:
     ;; Set the base pointer to the stack pointer and reserve some space.
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
     mov     bp,     sp
-    sub     sp,     24
+    sub     sp,     26
     
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
     ;; Preserve registers.
@@ -167,6 +167,7 @@ _get_partition_info:
     mov     word ptr [bp - 20],     0
     mov     word ptr [bp - 22],     0
     mov     word ptr [bp - 24],     0
+    mov     word ptr [bp - 26],     0
     
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
     ;; MBR partitions start at offset 0x01BE and are 16 bytes in length.
@@ -259,6 +260,9 @@ _get_partition_info:
     cmp     byte ptr es:[bx + 1],       HEX (58)
     jne     .L12
     
+    mov     ax,     es:[bx + 48]
+    mov     word ptr [bp - 26],     ax
+    
     mov     ax,     es:[bx + 44]
     mov     dx,     es:[bx + 46]
     
@@ -484,6 +488,9 @@ _get_partition_info:
     mov     ax,     word ptr [bp - 20]
     stosw
     
+    mov     ax,     word ptr [bp - 26]
+    stosw
+    
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
     ;; Get drive parameters.
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -533,14 +540,14 @@ _get_partition_info:
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
     ;; Clear the carry flag.
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-    add     sp,     24
+    add     sp,     26
     clc
     
     jmp     .L20
 
 .L22:
 
-    add     sp,     24
+    add     sp,     26
     stc
 
 .L20:
@@ -952,6 +959,221 @@ _read_sectors.done:
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
     ret
 
+;******************************************************************************
+; @function         _write_sectors
+;******************************************************************************
+global      _write_sectors
+_write_sectors:
+
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; Preserve the registers that will get clobbered.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    push    bx
+    push    cx
+    push    si
+    push    di
+    push    es
+
+_write_sectors.next:
+
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; The di regsiter will be our retry counter.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    mov     di,     HEX (0005)
+
+_write_sectors.retry:
+
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; Preserve the ax, cx and dx registers.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    push    ax
+    push    cx
+    push    dx
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; If disk extensions aren't avaiable then we need to use CHS.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    cmp     word ptr cs:[_edd_available],       1
+    jb      _write_sectors.chs
+
+_write_sectors.lba:
+
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; We'll create the LBA write on the stack.  8086 doesn't allow pushing
+    ;; values directly so we'll use si.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    xor     si,     si
+    push    si
+    push    si
+    
+    push    dx
+    push    ax
+    push    es
+    push    bx
+    
+    mov     si,     1
+    push    si
+    
+    mov     si,     16
+    push    si
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; The dl register needs to be set to the drive number before we alter
+    ;; the data segment.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    mov     dl,     cs:[_drive_no]
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; We need to set si to sp as the LBA write requires ds:si.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    mov     si,     sp
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; Preserve the data segment.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    push    ds
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; Preserve the ax and dx registers.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    push    ax
+    push    dx
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; Initialize the data segment to the stack segment.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    push    ss
+    pop     ds
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; write the sector into memory.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    mov     ah,     HEX (43)
+    stc
+    int     HEX (13)
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; Restore the ax and dx registers.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    pop     dx
+    pop     ax
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; Restore the data segment.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    pop     ds
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; Cleanup the stack.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    add     sp,     16
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; If there was no carry the we successfully write the sector.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    jnc     _write_sectors.success
+
+_write_sectors.chs:
+
+    div     word ptr cs:[_sectors_per_track]
+            ; ax = LBA / SPT
+            ; dx = LBA # SPT        = sector - 1
+    
+    mov     cx,     dx
+    inc     cx
+            ; cx = sector no.
+    
+    xor     dx,     dx
+    div     word ptr cs:[_heads_per_cylinder]
+            ; ax = (LBA / SPT) / HPC = cylinder
+            ; dx = (LBA / SPT) # HPC = head
+    
+    mov     ch,     al
+            ; ch = LSB 0...7 of cylinder no.
+    ror     ah
+    ror     ah
+    or      cl,     ah
+            ; cl = MSB 8...9 of cylinder no. + sector no.
+    mov     dh,     dl
+            ; dh = head no.
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; write the sector into es:bx.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    mov     ax,     HEX (0301)
+    mov     dl,     cs:[_drive_no]
+    stc
+    int     HEX (13)
+    jnc     _write_sectors.success
+
+_write_sectors.failure:
+
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; Reset the disk.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    xor     ah,     ah
+    mov     dl,     cs:[_drive_no]
+    int     HEX (13)
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; Restore the ax, cx and dx registers.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    pop     dx
+    pop     cx
+    pop     ax
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; Decrement the loop counter and retry if greater than zero.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    dec     di
+    jnz     _write_sectors.retry
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; Invoke the BIOS.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    int     HEX (18)
+
+_write_sectors.success:
+
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; Add the bytes per sector to bx to get the next offset to write in to.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    add     bx,     cs:[_bytes_per_sector]
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; Restore the ax, cx and dx registers.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    pop     dx
+    pop     cx
+    pop     ax
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; Advance to the next sector.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    add     ax,     1
+    adc     dx,     0
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; Loop until cx is zero.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    loop    _write_sectors.next
+
+_write_sectors.done:
+
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; Restore the registers that got clobbered.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    pop     es
+    pop     di
+    pop     si
+    pop     cx
+    pop     bx
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; Return to caller.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ret
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Data area.
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
index 7053b0c55545e509b3c9a892d239a4cd715a95d3..4703318766883bd5b4ca79e40418423b0af90e16 100644 (file)
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 %include    "fat.inc"
 
+;******************************************************************************
+; @function         _calculate_total
+;******************************************************************************
+_calculate_total:
+
+    push    cx
+    push    si
+    
+    mov     ax,     cs:[_total_sectors16]
+    xor     dx,     dx
+    
+    and     ax,     ax
+    jnz     _calculate_total.have_secs
+    
+    mov     ax,     cs:[_total_sectors32]
+    mov     dx,     cs:[_total_sectors32 + 2]
+
+_calculate_total.have_secs:
+
+    sub     ax,     cs:[_data_start]
+    sbb     dx,     cs:[_data_start + 2]
+    
+    xor     ch,     ch
+    mov     cl,     cs:[_sectors_per_cluster]
+    
+    xor     si,     si
+    push    si
+    
+    push    si
+    push    cx
+    push    dx
+    push    ax
+    
+    call    _udivmodsi4
+    add     sp,     10
+
+_calculate_total.done:
+
+    pop     si
+    pop     cx
+    ret
+
+
 ;******************************************************************************
 ; @function         _convert_cluster12
 ;******************************************************************************
@@ -110,9 +153,448 @@ _convert_cluster32.c3:
     
     add     dx,     cx
     
-    add     ax,     cs:[_data_start]
-    adc     dx,     cs:[_data_start + 2]
+    add     ax,     cs:[_data_start]
+    adc     dx,     cs:[_data_start + 2]
+    
+    ret
+
+;******************************************************************************
+; @function         _find_free12
+;******************************************************************************
+global      _find_free12
+_find_free12:
+
+    push    bp
+    
+    mov     bp,     sp
+    sub     sp,     2
+    
+    push    bx
+    push    cx
+    push    si
+    push    di
+    push    es
+    
+    mov     ax,     cs:[_fat_seg]
+    mov     es,     ax
+    
+    call    _calculate_total
+    
+    mov     si,     ax
+    mov     di,     dx
+    
+    mov     ax,     2
+    xor     dx,     dx
+
+_find_free12.loop:
+
+    mov     bx,     si
+    or      bx,     cx
+    
+    and     bx,     bx
+    jz      _find_free12.error
+    
+    push    ax
+    push    dx
+    push    si
+    push    cx
+    
+    mov     si,     ax
+    
+    mov     ax,     3
+    mul     si
+    
+    shr     ax
+    pushf
+    
+    mov     cx,     cs:[_bytes_per_sector]
+    shl     cx
+    
+    xor     dx,     dx
+    div     cx
+    
+    push    dx
+    xchg    si,     ax
+    
+    mov     ax,     cs:[_fat_start]
+    mov     dx,     cs:[_fat_start + 2]
+    
+    add     ax,     si
+    adc     dx,     0
+    
+    xor     bx,     bx
+    
+    cmp     ax,     cs:[_fat_sector]
+    jne     _find_free12.read
+    
+    cmp     dx,     cs:[_fat_sector + 2]
+    je      _find_free12.check
+
+_find_free12.read:
+
+    mov     cs:[_fat_sector],       ax
+    mov     cs:[_fat_sector + 2],       dx
+    
+    mov     cx,     2
+    call    _read_sectors
+
+_find_free12.check:
+
+    pop     si
+    popf
+    pop     cx
+    
+    push    ds
+    mov     ax,     es
+    mov     ds,     ax
+    mov     ax,     [si]
+    pop     ds
+    jnc     _find_free12.even_cluster
+    
+    mov     cl,     4
+    shr     ax,     cl
+
+_find_free12.even_cluster:
+
+    and     ax,     HEX (0FFF)
+    
+    xor     dx,     dx
+    pop     si
+    
+    mov     bx,     ax
+    or      bx,     dx
+    
+    and     bx,     bx
+    jnz     _find_free12.next
+    
+    pop     dx
+    pop     ax
+    
+    jmp     _find_free12.done
+
+_find_free12.next:
+
+    pop     dx
+    pop     ax
+    
+    add     ax,     1
+    adc     dx,     0
+    
+    sub     si,     1
+    sbb     di,     0
+    
+    jmp     _find_free12.loop
+
+_find_free12.error:
+
+    pop     es
+    pop     di
+    pop     si
+    pop     cx
+    pop     bx
+    
+    add     sp,     2
+    pop     bp
+    
+    stc
+    ret
+
+_find_free12.done:
+
+    pop     es
+    pop     di
+    pop     si
+    pop     cx
+    pop     bx
+    
+    add     sp,     2
+    pop     bp
+    
+    clc
+    ret
+
+;******************************************************************************
+; @function         _find_free16
+;******************************************************************************
+global      _find_free16
+_find_free16:
+
+    push    bp
+    
+    mov     bp,     sp
+    sub     sp,     2
+    
+    push    bx
+    push    cx
+    push    si
+    push    di
+    push    es
+    
+    mov     ax,     cs:[_fat_seg]
+    mov     es,     ax
+    
+    call    _calculate_total
+    
+    mov     si,     ax
+    mov     di,     dx
+    
+    mov     ax,     2
+    xor     dx,     dx
+
+_find_free16.loop:
+
+    mov     bx,     si
+    or      bx,     cx
+    
+    and     bx,     bx
+    jz      _find_free16.error
+    
+    push    ax
+    push    dx
+    push    si
+    push    cx
+    
+    shl     ax
+    pushf
+    
+    mov     cx,     cs:[_bytes_per_sector]
+    shl     cx
+    
+    xor     dx,     dx
+    div     cx
+    
+    push    dx
+    xchg    si,     ax
+    
+    mov     ax,     cs:[_fat_start]
+    mov     dx,     cs:[_fat_start + 2]
+    
+    add     ax,     si
+    adc     dx,     0
+    
+    xor     bx,     bx
+    
+    cmp     ax,     cs:[_fat_sector]
+    jne     _find_free16.read
+    
+    cmp     dx,     cs:[_fat_sector + 2]
+    je      _find_free16.check
+
+_find_free16.read:
+
+    mov     cs:[_fat_sector],       ax
+    mov     cs:[_fat_sector + 2],       dx
+    
+    mov     cx,     2
+    call    _read_sectors
+
+_find_free16.check:
+
+    pop     si
+    popf
+    pop     cx
+    
+    mov     ax,     cs:[_fat_seg]
+    jnc     _find_free16.first64
+    
+    add     ax,     HEX (1000)
+
+_find_free16.first64:
+
+    push    ds
+    mov     ds,     ax
+    mov     ax,     [si]
+    pop     ds
+    
+    xor     dx,     dx
+    pop     si
+    
+    mov     bx,     ax
+    or      bx,     dx
+    
+    and     bx,     bx
+    jnz     _find_free16.next
+    
+    pop     dx
+    pop     ax
+    
+    jmp     _find_free16.done
+
+_find_free16.next:
+
+    pop     dx
+    pop     ax
+    
+    add     ax,     1
+    adc     dx,     0
+    
+    sub     si,     1
+    sbb     di,     0
+    
+    jmp     _find_free16.loop
+
+_find_free16.error:
+
+    pop     es
+    pop     di
+    pop     si
+    pop     cx
+    pop     bx
+    
+    add     sp,     2
+    pop     bp
+    
+    stc
+    ret
+
+_find_free16.done:
+
+    pop     es
+    pop     di
+    pop     si
+    pop     cx
+    pop     bx
+    
+    add     sp,     2
+    pop     bp
+    
+    clc
+    ret
+
+;******************************************************************************
+; @function         _find_free32
+;******************************************************************************
+global      _find_free32
+_find_free32:
+
+    push    bp
+    
+    mov     bp,     sp
+    sub     sp,     2
+    
+    push    bx
+    push    cx
+    push    si
+    push    di
+    push    es
+    
+    mov     ax,     cs:[_fat_seg]
+    mov     es,     ax
+    
+    call    _calculate_total
+    
+    mov     si,     ax
+    mov     di,     dx
+    
+    mov     ax,     2
+    xor     dx,     dx
+
+_find_free32.loop:
+
+    mov     bx,     si
+    or      bx,     cx
+    
+    and     bx,     bx
+    jz      _find_free32.error
+    
+    push    ax
+    push    dx
+    push    di
+    push    cx
+    
+    mov     di,     ax
+    
+    and     di,     cs:[_fat_secmask]
+    mov     cx,     cs:[_fat_secshift]
+
+_find_free32.cn_loop:
+
+    shr     dx
+    rcr     ax
+    loop    _find_free32.cn_loop
+    
+    shl     di
+    shl     di
+    mov     word ptr [bp - 2],      di
+    
+    pop     cx
+
+    add     ax,     cs:[_fat_start]
+    adc     dx,     cs:[_fat_start + 2]
+    
+    xor     bx,     bx
+    
+    cmp     ax,     cs:[_fat_sector]
+    jne     _find_free32.read
+    
+    cmp     dx,     cs:[_fat_sector + 2]
+    je      _find_free32.check
+
+_find_free32.read:
+
+    mov     cs:[_fat_sector],       ax
+    mov     cs:[_fat_sector + 2],       dx
+    
+    mov     cx,     2
+    call    _read_sectors
+
+_find_free32.check:
+
+    mov     ax,     es:[di]
+    mov     dx,     es:[di + 2]
+    
+    pop     di
+    
+    mov     bx,     ax
+    or      bx,     dx
+    
+    and     bx,     bx
+    jnz     _find_free32.next
+    
+    pop     dx
+    pop     ax
+    
+    jmp     _find_free32.done
+
+_find_free32.next:
+
+    pop     dx
+    pop     ax
+    
+    add     ax,     1
+    adc     dx,     0
+    
+    sub     si,     1
+    sbb     di,     0
+    
+    jmp     _find_free32.loop
+
+_find_free32.error:
+
+    pop     es
+    pop     di
+    pop     si
+    pop     cx
+    pop     bx
+    
+    add     sp,     2
+    pop     bp
+    
+    stc
+    ret
+
+_find_free32.done:
+
+    pop     es
+    pop     di
+    pop     si
+    pop     cx
+    pop     bx
+    
+    add     sp,     2
+    pop     bp
     
+    clc
     ret
 
 ;******************************************************************************
@@ -195,9 +677,15 @@ _getfattype.fat12:
     mov     ax,     offset _convert_cluster12
     mov     cs:[_convert_cluster],      ax
     
+    mov     ax,     offset _find_free12
+    mov     cs:[_find_free],    ax
+    
     mov     ax,     offset _nextcluster_fat12
     mov     cs:[_next_cluster],         ax
     
+    mov     ax,     offset _update_cluster12
+    mov     cs:[_update_cluster],       ax
+    
     jmp     short   _getfattype.done
 
 _getfattype.fat16:
@@ -205,8 +693,14 @@ _getfattype.fat16:
     mov     ax,     offset _convert_cluster16
     mov     cs:[_convert_cluster],      ax
     
+    mov     ax,     offset _find_free16
+    mov     cs:[_find_free],    ax
+    
     mov     ax,     offset _nextcluster_fat16
     mov     cs:[_next_cluster],         ax
+    
+    mov     ax,     offset _update_cluster16
+    mov     cs:[_update_cluster],       ax
 
 _getfattype.done:
 
@@ -479,6 +973,309 @@ _nextcluster_fat32.no_carry:
     clc
     ret
 
+;******************************************************************************
+; @function         _update_cluster12
+;******************************************************************************
+global      _update_cluster12
+_update_cluster12:
+
+    push    ax
+    push    bx
+    push    cx
+    push    dx
+    push    si
+    push    di
+    push    es
+    
+    mov     si,     ax
+    mov     di,     cx
+    
+    mov     ax,     3
+    mul     si
+    shr     ax
+    
+    push    cx
+    pushf
+    
+    mov     cx,     cs:[_bytes_per_sector]
+    shl     cx
+    
+    xor     dx,     dx
+    div     cx
+    
+    push    dx
+    xchg    si,     ax
+
+_update_cluster12.read:
+
+    mov     bx,     cs:[_fat_seg]
+    mov     es,     bx
+    xor     bx,     bx
+    
+    mov     ax,     cs:[_fat_start]
+    mov     dx,     cs:[_fat_start + 2]
+    
+    add     ax,     si
+    adc     dx,     0
+    
+    push    ax
+    push    dx
+    
+    mov     cx,     2
+    call    _read_sectors
+    
+    pop     dx
+    pop     ax
+    
+    and     di,     HEX (0FFF)
+    
+    pop     si
+    popf
+    pop     cx
+    
+    push    ax
+    push    dx
+    
+    mov     cx,     es:[si]
+    jnc     _update_cluster12.even
+    
+    shl     di
+    shl     di
+    shl     di
+    shl     di
+    mov     ax,     di
+    
+    and     cl,     HEX (0F)
+    or      al,     cl
+    
+    jmp     _update_cluster12.update
+
+_update_cluster12.even:
+    
+    mov     ax,     di
+    
+    and     ch,     HEX (F0)
+    or      ah,     ch
+
+_update_cluster12.update:
+
+    mov     es:[si],        ax
+    pop     dx
+    pop     ax
+    
+    mov     cx,     cs:[_sectors_per_fat]
+    call    _write_sectors
+    
+    mov     cx,     cs:[_sectors_per_fat]
+    call    _write_sectors
+
+_update_cluster12.done:
+
+    pop     es
+    pop     di
+    pop     si
+    pop     dx
+    pop     cx
+    pop     bx
+    pop     ax
+    ret
+
+;******************************************************************************
+; @function         _update_cluster16
+;******************************************************************************
+global      _update_cluster16
+_update_cluster16:
+
+    push    ax
+    push    bx
+    push    cx
+    push    dx
+    push    si
+    push    di
+    push    es
+    
+    mov     di,     cx
+    shl     ax
+    
+    push    cx
+    pushf
+    
+    mov     cx,     cs:[_bytes_per_sector]
+    shl     cx
+    
+    xor     dx,     dx
+    div     cx
+    
+    push    dx
+    xchg    si,     ax
+
+_update_cluster16.read:
+
+    mov     bx,     cs:[_fat_seg]
+    mov     es,     bx
+    xor     bx,     bx
+    
+    mov     ax,     cs:[_fat_start]
+    mov     dx,     cs:[_fat_start + 2]
+    
+    add     ax,     si
+    adc     dx,     0
+    
+    push    ax
+    push    dx
+    
+    mov     cx,     2
+    call    _read_sectors
+    
+    pop     dx
+    pop     ax
+    pop     si
+    popf
+    pop     cx
+    
+    push    ax
+    push    dx
+    
+    mov     ax,     es
+    jnc     _update_cluster16.first64
+    
+    add     ax,     HEX (1000)
+
+_update_cluster16.first64:
+
+    push    ds
+    mov     ds,     ax
+    mov     [si],       di
+    pop     ds
+    
+    mov     cx,     2
+    
+    cmp     cs:[_sectors_per_fat],      cx
+    jae     _update_cluster16.update
+    
+    mov     cx,     1
+
+_update_cluster16.update:
+
+    pop     dx
+    pop     ax
+    
+    push    ax
+    push    dx
+    call    _write_sectors
+    
+    pop     dx
+    pop     ax
+    
+    add     ax,     cs:[_sectors_per_fat]
+    adc     dx,     0
+    
+    call    _write_sectors
+
+_update_cluster16.done:
+
+    pop     es
+    pop     di
+    pop     si
+    pop     dx
+    pop     cx
+    pop     bx
+    pop     ax
+    ret
+
+;******************************************************************************
+; @function         _update_cluster32
+;******************************************************************************
+global      _update_cluster32
+_update_cluster32:
+
+    push    ax
+    push    bx
+    push    cx
+    push    dx
+    push    si
+    push    di
+    push    es
+    
+    push    bx
+    push    cx
+    
+    mov     di,     ax
+    
+    and     di,     cs:[_fat_secmask]
+    mov     cx,     cs:[_fat_secshift]
+
+_update_cluster32.cn_loop:
+
+    shr     dx
+    rcr     ax
+    loop    _update_cluster32.cn_loop
+    
+    pop     cx
+    pop     si
+    
+    shl     di
+    shl     di
+    
+    add     ax,     cs:[_fat_start]
+    adc     dx,     cs:[_fat_start + 2]
+    
+    push    ax
+    push    dx
+    push    cx
+    
+    mov     bx,     cs:[_fat_seg]
+    mov     es,     bx
+    xor     bx,     bx
+    
+    mov     cx,     1
+    call    _read_sectors
+    
+    and     si,     HEX (0FFF)
+    pop     cx
+    
+    mov     es:[di],    cx
+    mov     es:[di + 2],    si
+
+_update_cluster32.update:
+
+    pop     dx
+    pop     ax
+    
+    mov     si,     ax
+    mov     di,     dx
+    
+    mov     cx,     1
+    call    _write_sectors
+    
+    mov     ax,     cs:[_data_start]
+    mov     dx,     cs:[_data_start + 2]
+    
+    sub     ax,     cs:[_fat_start]
+    sbb     dx,     cs:[_fat_start + 2]
+    
+    xor     ch,     ch
+    mov     cl,     cs:[_number_of_fats]
+    
+    div     cx
+    
+    add     ax,     si
+    adc     dx,     di
+    
+    mov     cx,     1
+    call    _write_sectors
+
+_update_cluster32.done:
+
+    pop     es
+    pop     di
+    pop     si
+    pop     dx
+    pop     cx
+    pop     bx
+    pop     ax
+    ret
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Data area.
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -488,9 +1285,15 @@ _fat_bpb:                       db      25      dup (0)
 global      _convert_cluster
 _convert_cluster:               dw      HEX (0000)
 
+global      _find_free
+_find_free:                     dw      HEX (0000)
+
 global      _next_cluster
 _next_cluster:                  dw      HEX (0000)
 
+global      _update_cluster
+_update_cluster:                dw      HEX (0000)
+
 global      _fat_seg
 _fat_seg:                       dw      HEX (0000)
 
@@ -500,6 +1303,9 @@ _fat_secmask:                   dw      HEX (0000)
 global      _fat_secshift
 _fat_secshift:                  dw      HEX (0000)
 
+global      _info_sector
+_info_sector:                   dw      HEX (0000)
+
 global      _curr_cluster
 _curr_cluster:
 
index f728c1794a09f0320e3065bb43d2a117a3682481..ac140241386ce64c12753c3a63093e74beacfa2c 100644 (file)
@@ -77,7 +77,7 @@ _read_cluster.read:
     xor     ch,     ch
     mov     cl,     es:[si + 6]
     
-    mov     bx,     es:[si + 68]
+    mov     bx,     es:[si + 70]
     mov     es,     bx
     xor     bx,     bx
     
@@ -127,8 +127,8 @@ _getc:
 
 _getc.is_eof:
 
-    mov     ax,     es:[si + 64]
-    mov     dx,     es:[si + 66]
+    mov     ax,     es:[si + 66]
+    mov     dx,     es:[si + 68]
     
     mov     cx,     ax
     
@@ -137,27 +137,27 @@ _getc.is_eof:
 
 _getc.check:
 
-    cmp     dx,     es:[si + 62]
+    cmp     dx,     es:[si + 64]
     ja      _getc.check2
     
-    cmp     dx,     es:[si + 62]
+    cmp     dx,     es:[si + 64]
     jne     _getc.done
     
-    cmp     ax,     es:[si + 60]
+    cmp     ax,     es:[si + 62]
     jbe     _getc.done
 
 _getc.check2:
 
-    mov     ax,     es:[si + 60]
-    mov     dx,     es:[si + 62]
+    mov     ax,     es:[si + 62]
+    mov     dx,     es:[si + 64]
     
     mov     cx,     es:[si + 50]
     div     cx
     
-    cmp     word ptr es:[si + 52],      0
+    cmp     word ptr es:[si + 54],      0
     je      _getc.check_offset
     
-    mov     word ptr es:[si + 52],      0
+    mov     word ptr es:[si + 54],      0
     jmp     short   _getc.read
 
 _getc.check_offset:
@@ -167,31 +167,29 @@ _getc.check_offset:
 
 _getc.read:
 
-    mov     bx,     es:[si + 56]
-    mov     cx,     es:[si + 58]
+    mov     bx,     es:[si + 58]
+    mov     cx,     es:[si + 60]
     call    _read_cluster
 
 _getc.loaded:
 
     push    es
     
-    mov     bx,     es:[si + 68]
+    mov     bx,     es:[si + 70]
     mov     es,     bx
     mov     bx,     dx
     mov     al,     es:[bx]
     
     mov     bx,     ds
     mov     es,     bx
-    stosb
-    
-    mov     bx,     es
-    mov     ds,     bx
     
+    stosb
     pop     es
+    
     inc     word ptr [bp - 2]
     
-    add     word ptr es:[si + 60],      1
-    adc     word ptr es:[si + 62],      0
+    add     word ptr es:[si + 62],      1
+    adc     word ptr es:[si + 64],      0
 
 _getc.done:
 
@@ -714,6 +712,9 @@ _open_file.got_handle:
     mov     ax,     cs:[_clustsize]
     stosw
     
+    mov     ax,     cs:[_info_sector]
+    stosw
+    
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
     ;; Store the value 1 as the first word to indicate that we need
     ;; to be read
@@ -905,7 +906,7 @@ _read_file:
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
     ;; Make sure we're not write-only.
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-    cmp     word ptr es:[si + 54],  1
+    cmp     word ptr es:[si + 56],  1
     je      _read_file.error
     
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -915,6 +916,9 @@ _read_file:
 
 _read_file.loop:
 
+    and     cx,     cx
+    jz      _read_file.done
+    
     call    _getc
     jc      _read_file.error
     
@@ -922,7 +926,9 @@ _read_file.loop:
     jz      _read_file.done
     
     inc     word ptr [bp - 2]
-    loop    _read_file.loop
+    
+    dec     cx
+    jnz     _read_file.loop
 
 _read_file.done:
 
@@ -1077,25 +1083,25 @@ _seek_file.beginning:
 
     xor     ax,     ax
     
-    mov     es:[si + 60],       ax
     mov     es:[si + 62],       ax
+    mov     es:[si + 64],       ax
     
     jmp     short   _seek_file.offset
 
 _seek_file.end:
 
-    mov     ax,     es:[si + 64]
-    mov     es:[si + 60],   ax
-    
     mov     ax,     es:[si + 66]
     mov     es:[si + 62],   ax
+    
+    mov     ax,     es:[si + 68]
+    mov     es:[si + 64],   ax
 
 _seek_file.offset:
 
-    mov     ax,     es:[si + 60]
+    mov     ax,     es:[si + 62]
     add     ax,     cx
     
-    mov     di,     es:[si + 62]
+    mov     di,     es:[si + 64]
     adc     di,     dx
     
     cmp     di,     0
@@ -1106,15 +1112,15 @@ _seek_file.offset:
 
 _seek_file.ptr_ok:
 
-    mov     es:[si + 60],   ax
-    mov     es:[si + 62],   di
+    mov     es:[si + 62],   ax
+    mov     es:[si + 64],   di
 
 _seek_file.done:
 
     mov     word ptr es:[si + 52],      1
     
-    mov     ax,     es:[si + 60]
-    mov     dx,     es:[si + 62]
+    mov     ax,     es:[si + 62]
+    mov     dx,     es:[si + 64]
     clc
     
     pop     di
index 91407018a05a3ae7a788b7a476b45f8288d5023b..cb56f0420d330815b02326634c3092aae9f909c3 100644 (file)
@@ -5,6 +5,11 @@
 % define        HEX(y)                  0x##y
 %endif
 
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Includes.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%include    "fat.inc"
+
 ;******************************************************************************
 ; @function          _bcd2int
 ;******************************************************************************
@@ -293,6 +298,9 @@ _get_disk_info.copy:
     lodsw
     mov     cs:[_clustsize],    ax
     
+    lodsw
+    mov     cs:[_info_sector],      ax
+    
     pop     ds
     pop     si
     
@@ -312,8 +320,14 @@ _get_disk_info.fat32:
     mov     ax,     offset _convert_cluster32
     mov     cs:[_convert_cluster],      ax
     
+    mov     ax,     offset _find_free32
+    mov     cs:[_find_free],    ax
+    
     mov     ax,     offset _nextcluster_fat32
     mov     cs:[_next_cluster],         ax
+    
+    mov     ax,     offset _update_cluster32
+    mov     cs:[_update_cluster],       ax
 
 _get_disk_info.done:
 
@@ -810,6 +824,12 @@ _int21_dispatch.list:
     db      HEX (30)
     dw      _int21_30
     
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; Create Directory (mkdir).
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    db      HEX (39)
+    dw      _int21_39
+    
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
     ;; Set Current Directory.
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -1636,6 +1656,109 @@ _int21_30:
     
     iret
 
+;******************************************************************************
+; @function         _int21_39
+; @brief            Create Directory (mkdir)
+;
+; @in               DS:DX -> Pointer to ASCIIZ path name.
+;******************************************************************************
+_int21_39:
+
+    push    bx
+    push    cx
+    push    dx
+    push    si
+    push    di
+    push    es
+    push    ds
+    
+    mov     si,     dx
+    
+    call    _get_disk_info
+    jc      _int21_39.error_path
+    
+    mov     di,     si
+    
+    call    _walk_path
+    jc      _int21_39.error_path
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; Preserve registers.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    push    ax
+    push    dx
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; Mangle the file name and search for it in the file system.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    call    _mangle_dos_name
+    jc      _int21_39.name_error
+    
+    call    _search_dos_dir
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; Restore registers.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    pop     dx
+    pop     ax
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; If the carry flag wasn't set then the entry already exists.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    jnc     _int21_39.error_exists
+    
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    ;; If we get here then the path is okay and the entry doesn't exist
+    ;; so lets try and create it.
+    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    mov     cx,     HEX (10)
+    
+    call    _make_dos_entry
+    jc      _int21_39.error
+    
+    jmp     _int21_39.done
+
+_int21_39.name_error:
+
+    pop     dx
+    pop     ax
+
+_int21_39.error_exists:
+
+    mov     ax,     5
+
+_int21_39.error_path:
+
+    mov     ax,     3
+
+_int21_39.error:
+
+    pop     ds
+    pop     es
+    pop     di
+    pop     si
+    pop     dx
+    pop     cx
+    pop     bx
+    
+    stc
+    jmp     iretc
+
+_int21_39.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
@@ -1793,6 +1916,9 @@ _int21_3B.copy:
     lodsw
     mov     cs:[_clustsize],    ax
     
+    lodsw
+    mov     cs:[_info_sector],      ax
+    
     pop     ds
     pop     si
     pop     es
@@ -1813,8 +1939,14 @@ _int21_3B.fat32:
     mov     ax,     offset _convert_cluster32
     mov     cs:[_convert_cluster],      ax
     
+    mov     ax,     offset _find_free32
+    mov     cs:[_find_free],    ax
+    
     mov     ax,     offset _nextcluster_fat32
     mov     cs:[_next_cluster],         ax
+    
+    mov     ax,     offset _update_cluster32
+    mov     cs:[_update_cluster],       ax
 
 _int21_3B.get_path:
 
@@ -1939,12 +2071,20 @@ _int21_3B.check_prev:
 
 _int21_3B.get_prev:
 
-    mov     byte ptr es:[di - 1],   0
+    cmp     di,     offset _int21_3B.path
+    je      _int21_3B.no_slash2
+    
+    cmp     byte ptr es:[di - 1],   '\\'
+    jne     _int21_3B.no_slash2
     
+    mov     byte ptr es:[di - 1],   0
+
+_int21_3B.no_slash2:
+
     push    si
     push    ds
     
-    mov     ax,     es
+    mov     ax,     cs
     mov     ds,     ax
     
     mov     ax,     '\\'
@@ -1959,10 +2099,20 @@ _int21_3B.get_prev:
     pop     ds
     pop     si
     
+    and     ax,     ax
+    jnz     _int21_3B.got_index
+    
+    mov     di,     offset _int21_3B.path
+    jmp     _int21_3B.zero
+
+_int21_3B.got_index:
+
     mov     di,     ax
     inc     di
+
+_int21_3B.zero:
+
     mov     byte ptr es:[di],   0
-    
     jmp     _int21_3B.loop
 
 _int21_3B.char_ok:
@@ -2255,6 +2405,7 @@ _int21_3F.copy:
     push    si
     push    ds
     push    ax
+    push    cx
     
     mov     ds,     ax
     xor     si,     si
@@ -2308,6 +2459,9 @@ _int21_3F.copy:
     lodsw
     mov     cs:[_clustsize],    ax
     
+    lodsw
+    mov     cs:[_info_sector],      ax
+    
     mov     bx,     cs:[_root_cluster]
     mov     cx,     cs:[_root_cluster + 2]
     
@@ -2324,11 +2478,18 @@ _int21_3F.fat32:
     mov     ax,     offset _convert_cluster32
     mov     cs:[_convert_cluster],      ax
     
+    mov     ax,     offset _find_free32
+    mov     cs:[_find_free],    ax
+    
     mov     ax,     offset _nextcluster_fat32
     mov     cs:[_next_cluster],         ax
+    
+    mov     ax,     offset _update_cluster32
+    mov     cs:[_update_cluster],       ax
 
 _int21_3F.read:
 
+    pop     cx
     pop     ax
     pop     ds
     pop     si
@@ -2698,12 +2859,12 @@ _int21_4C.check_file:
     mov     ds,     di
     xor     di,     di
     
-    mov     ax,     [di + 70]
+    mov     ax,     [di + 72]
     
     cmp     ax,     dx
     jne     _int21_4C.next_file
     
-    mov     ax,     [di + 68]
+    mov     ax,     [di + 70]
     push    es
     
     mov     es,     ax
@@ -3215,6 +3376,9 @@ _int21_4F.copy:
     lodsw
     mov     cs:[_clustsize],    ax
     
+    lodsw
+    mov     cs:[_info_sector],      ax
+    
     pop     di
     pop     si
     pop     ds
@@ -3236,8 +3400,14 @@ _int21_4F.fat32:
     mov     ax,     offset _convert_cluster32
     mov     cs:[_convert_cluster],      ax
     
+    mov     ax,     offset _find_free32
+    mov     cs:[_find_free],    ax
+    
     mov     ax,     offset _nextcluster_fat32
     mov     cs:[_next_cluster],         ax
+    
+    mov     ax,     offset _update_cluster32
+    mov     cs:[_update_cluster],       ax
 
 _int21_4F.find:
 
diff --git a/src/kernel/make.asm b/src/kernel/make.asm
new file mode 100644 (file)
index 0000000..741438f
--- /dev/null
@@ -0,0 +1,482 @@
+;******************************************************************************
+; @file             make.asm
+;******************************************************************************
+%ifndef     HEX
+% define        HEX(y)                  0x##y
+%endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Include our fat.inc file for our BPB offsets.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+%include    "fat.inc"
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; @function        _generate_timestamp
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_generate_timestamp:
+
+    push    si
+    push    cx
+    push    dx
+    
+    mov     ah,     HEX (2C)
+    int     HEX (21)
+    
+    xor     ah,     ah
+    mov     al,     dh
+    shr     ax
+    mov     si,     ax
+    
+    push    cx
+    xor     ah,     ah
+    mov     al,     cl
+    mov     cl,     5
+    shl     ax,     cl
+    pop     cx
+    add     si,     ax
+    
+    push    cx
+    xor     ah,     ah
+    mov     al,     ch
+    mov     cl,     11
+    shl     ax,     cl
+    pop     cx
+    add     si,     ax
+
+_generate_timestamp.done:
+
+    mov     ax,     si
+    
+    pop     dx
+    pop     cx
+    pop     si
+    ret
+    
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; @function        _generate_datestamp
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_generate_datestamp:
+
+    push    si
+    push    cx
+    push    dx
+    
+    mov     ah,     HEX (2A)
+    int     HEX (21)
+    
+    xor     ah,     ah
+    mov     al,     dl
+    mov     si,     ax
+    
+    push    cx
+    xor     ah,     ah
+    mov     al,     dh
+    mov     cl,     5
+    shl     ax,     cl
+    pop     cx
+    add     si,     ax
+    
+    push    cx
+    mov     ax,     cx
+    sub     ax,     1980
+    mov     cl,     9
+    shl     ax,     cl
+    pop     cx
+    add     si,     ax
+
+_generate_datestamp.done:
+
+    mov     ax,     si
+    
+    pop     dx
+    pop     cx
+    pop     si
+    ret
+
+
+;******************************************************************************
+; @function         _make_dos_entry
+;******************************************************************************
+global      _make_dos_entry
+_make_dos_entry:
+
+    push    bp
+    
+    mov     bp,     sp
+    sub     sp,     48
+    
+    push    bx
+    push    cx
+    push    dx
+    push    si
+    push    di
+    push    es
+    push    ds
+    
+    mov     word ptr [bp - 48],     ax
+    mov     word ptr [bp - 46],     dx
+    
+    mov     word ptr [bp - 36],     cx
+    mov     word ptr [bp - 32],     bx
+    
+    mov     word ptr [bp - 20],     0
+    mov     word ptr [bp - 16],     0
+    
+    mov     bx,     ax
+    or      bx,     dx
+    
+    and     bx,     bx
+    jnz     _make_dos_entry.not_root
+    
+    mov     ax,     cs:[_root_start]
+    mov     dx,     cs:[_root_start + 2]
+
+_make_dos_entry.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     _make_dos_entry.read
+
+_make_dos_entry.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      _make_dos_entry.error
+    
+    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]
+
+_make_dos_entry.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
+
+_make_dos_entry.make:
+
+    cmp     byte ptr es:[di],       0
+    je      _make_dos_entry.found_free
+    
+    cmp     byte ptr es:[di],       HEX (E5)
+    je      _make_dos_entry.found_free
+
+_make_dos_entry.advance:
+
+    add     di,     32
+    loop    _make_dos_entry.make
+    
+    cmp     word ptr [bp - 30],     1
+    jne     _make_dos_entry.check
+    
+    mov     ax,     word ptr [bp - 22]
+    
+    and     ax,     ax
+    jz      _make_dos_entry.error
+    
+    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     _make_dos_entry.read
+
+_make_dos_entry.check:
+
+    mov     ax,     word ptr [bp - 34]
+    
+    and     ax,     ax
+    jz      _make_dos_entry.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     _make_dos_entry.read
+
+_make_dos_entry.next_clust:
+
+    mov     ax,     word ptr [bp - 28]
+    mov     dx,     word ptr [bp - 26]
+    
+    call    cs:[_next_cluster]
+    jmp     _make_dos_entry.not_root
+
+_make_dos_entry.found_free:
+
+    call    cs:[_find_free]
+    jc      _make_dos_entry.error
+
+_make_dos_entry.got_clust:
+
+    mov     word ptr [bp - 38],     ax
+    mov     word ptr [bp - 40],     dx
+    
+    call    _generate_datestamp
+    mov     word ptr [bp - 42],     ax
+    
+    call    _generate_timestamp
+    mov     word ptr [bp - 44],     ax
+    
+    push    si
+    push    ds
+    
+    mov     si,     cs
+    mov     ds,     si
+    
+    mov     si,     word ptr [bp - 32]
+    
+    mov     cx,     11
+    rep     movsb
+    
+    pop     ds
+    pop     si
+    
+    mov     ax,     word ptr [bp - 36]
+    stosb
+    
+    xor     ax,     ax
+    stosw
+    
+    mov     ax,     word ptr [bp - 44]
+    stosw
+    
+    mov     ax,     word ptr [bp - 42]
+    stosw
+    
+    mov     ax,     word ptr [bp - 42]
+    stosw
+    
+    mov     ax,     word ptr [bp - 40]
+    stosw
+    
+    mov     ax,     word ptr [bp - 44]
+    stosw
+    
+    mov     ax,     word ptr [bp - 42]
+    stosw
+    
+    mov     ax,     word ptr [bp - 38]
+    stosw
+    
+    xor     ax,     ax
+    stosw
+    stosw
+    
+    mov     ax,     word ptr [bp - 6]
+    mov     dx,     word ptr [bp - 4]
+    
+    mov     cx,     word ptr [bp - 24]
+    call    _write_sectors
+    
+    mov     ax,     word ptr [bp - 38]
+    mov     dx,     word ptr [bp - 40]
+    
+    mov     bx,     HEX (FFFF)
+    mov     cx,     HEX (FFF8)
+    
+    call    cs:[_update_cluster]
+    
+    mov     ax,     cs:[_disk_scratch]
+    mov     es,     ax
+    
+    xor     al,     al
+    xor     di,     di
+    
+    mov     cx,     cs:[_clustsize]
+    rep     stosb
+    
+    xor     di,     di
+    
+    mov     al,     '.'
+    stosb
+    
+    mov     al,     ' '
+    
+    mov     cx,     10
+    rep     stosb
+    
+    mov     al,     HEX (10)
+    stosb
+    
+    xor     ax,     ax
+    stosw
+    
+    mov     ax,     word ptr [bp - 44]
+    stosw
+    
+    mov     ax,     word ptr [bp - 42]
+    stosw
+    
+    mov     ax,     word ptr [bp - 42]
+    stosw
+    
+    mov     ax,     word ptr [bp - 40]
+    stosw
+    
+    mov     ax,     word ptr [bp - 44]
+    stosw
+    
+    mov     ax,     word ptr [bp - 42]
+    stosw
+    
+    mov     ax,     word ptr [bp - 38]
+    stosw
+    
+    xor     ax,     ax
+    stosw
+    stosw
+    
+    mov     al,     '.'
+    
+    mov     cx,     2
+    rep     stosb
+    
+    mov     al,     ' '
+    
+    mov     cx,     9
+    rep     stosb
+    
+    mov     al,     HEX (10)
+    stosb
+    
+    xor     ax,     ax
+    stosw
+    
+    mov     ax,     word ptr [bp - 44]
+    stosw
+    
+    mov     ax,     word ptr [bp - 42]
+    stosw
+    
+    mov     ax,     word ptr [bp - 42]
+    stosw
+    
+    mov     ax,     word ptr [bp - 46]
+    stosw
+    
+    mov     ax,     word ptr [bp - 44]
+    stosw
+    
+    mov     ax,     word ptr [bp - 42]
+    stosw
+    
+    mov     ax,     word ptr [bp - 48]
+    stosw
+    
+    xor     ax,     ax
+    stosw
+    stosw
+    
+    mov     ax,     word ptr [bp - 38]
+    mov     dx,     word ptr [bp - 40]
+    call    cs:[_convert_cluster]
+    
+    xor     ch,     ch
+    mov     cl,     cs:[_sectors_per_cluster]
+    
+    xor     bx,     bx
+    call    _write_sectors
+    
+    jmp     _make_dos_entry.done
+
+_make_dos_entry.error:
+
+    pop     ds
+    pop     es
+    pop     di
+    pop     si
+    pop     dx
+    pop     cx
+    pop     bx
+    
+    add     sp,     48
+    pop     bp
+    
+    mov     ax,     5
+    stc
+    
+    ret
+
+_make_dos_entry.done:
+
+    pop     ds
+    pop     es
+    pop     di
+    pop     si
+    pop     dx
+    pop     cx
+    pop     bx
+    
+    add     sp,     48
+    pop     bp
+    
+    xor     ax,     ax
+    clc
+    
+    ret
index 98c1c4d9db32e01120364f90d6ed9aa33b3bb4c1..7fd3a2513fe9ac9853414268a0c40a50c8f08ebb 100644 (file)
@@ -70,6 +70,56 @@ _walk_path.end_path:
     call    _mangle_dos_name
     jc      _walk_path.not_found
     
+    cmp     dx,     cs:[_root_cluster + 2]
+    jne     _walk_path.search
+    
+    cmp     ax,     cs:[_root_cluster]
+    jne     _walk_path.search
+
+_walk_path.compare_curr:
+
+    push    ax
+    push    ds
+    
+    mov     ax,     cs
+    mov     ds,     ax
+    
+    push    bx
+    
+    mov     ax,     offset _curr_check
+    push    ax
+    
+    call    _strcmp
+    add     sp,     4
+    
+    and     ax,     ax
+    pop     ds
+    pop     ax
+    jz      _walk_path.check
+
+_walk_path.compare_prev:
+
+    push    ax
+    push    ds
+    
+    mov     ax,     cs
+    mov     ds,     ax
+    
+    push    bx
+    
+    mov     ax,     offset _prev_check
+    push    ax
+    
+    call    _strcmp
+    add     sp,     4
+    
+    and     ax,     ax
+    pop     ds
+    pop     ax
+    jz      _walk_path.check
+
+_walk_path.search:
+
     call    _search_dos_dir
     jc      _walk_path.not_found
     
@@ -82,14 +132,27 @@ _walk_path.end_path:
     
     mov     ax,     es:[bx + 0]
     mov     dx,     es:[bx + 2]
-    
     mov     cl,     es:[bx + 8]
+    
+    mov     bx,     ax
+    or      bx,     dx
+    
+    and     bx,     bx
+    jnz     _walk_path.got_clust
+    
+    mov     ax,     cs:[_root_cluster]
+    mov     dx,     cs:[_root_cluster + 2]
+
+_walk_path.got_clust:
+
     pop     es
     pop     bx
     
     test    cl,     HEX (10)
     jz      _walk_path.not_found
-    
+
+_walk_path.check:
+
     cmp     byte ptr [di - 1],      '\\'
     jne     _walk_path.done
     
@@ -108,3 +171,9 @@ _walk_path.done:
     clc
     
     ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data area.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+_curr_check:                    db      ".          ",      HEX (00)
+_prev_check:                    db      "..         ",      HEX (00)