; This is the DOS 2.0 ELECTRONIC DISK from the example in the DOS 2.0
; manual. It is now set for 180K of space. Look for the ======> 2 locations
; to change the size.
;
; To include the drive into your system, edit a file called CONFIG.SYS. It
; does not exist on the system supplied by IBM. Create a new file, and type
; in   DEVICE=VDISK.COM
;  and save the file  (must be standard ASCII fornat!).
; make sure you copy VDISK.COM to your boot disk.
; When you boot, the number of disk drives will be determined from the
; switch setting and the ELECTRONIC DISK will be made the next drive letter.
;
; For example, if you have two floppies, the RAM DISK will be Drive C.
;
;
; Assemble this will MASM and link with LINK pgm.
; You must then use the EXE2BIN command,  type   EXE2BIN VDISK VDISK
; after that, you must rename the new file  RENAME VDISK.BIN VDISK.COM
;
cseg    segment para public 'code'
status  macro   state,err,rc
        ifidn   <state>,<done>
        or      es:word ptr srh_sta_fld[bx],0100h
        endif
        ifidn   <state>,<busy>
        or      es:word ptr srh_sta_fld[bx],0200h
        endif
        ifidn   <err>,<error>
        or      es:word ptr srh_sta_fld[bx],1000h
        endif
        ifnb    <rc>
        or      es:word ptr srh_sta_fld[bx],rc
        endif
        endm
;
;
;
srh     equ     0
srh_len equ     13
srh_len_fld     equ     srh
srh_ucd_fld     equ     srh+1
srh_ccd_fld     equ     srh+2
srh_sta_fld     equ     srh+3
srh_res_fld     equ     srh+5
;
md      equ     srh+srh_len
md_len  equ     1
dta     equ     md+md_len
dta_len equ     4
count   equ     dta+dta_len
count_len       equ     2
ssn     equ     count+count_len
ssn_len equ     2
;
ret_byte        equ     md+md_len
;
bpba_ptr        equ     dta+dta_len
bpda_ptr_len    equ     4
;
units   equ     srh+srh_len
units_len       equ     1
br_addr_0       equ     units+units_len
br_addr_1       equ     br_addr_0+2
br_addr_len     equ     4
bpb_ptr_off     equ     br_addr_0+br_addr_len
bpb_ptr_seg     equ     bpb_ptr_off+2
;
vdsk    proc    far
        assume  cs:cseg,es:cseg,ds:cseg
begin:
start   equ     $
;
next_dev        dd      -1
attribute       dw      2000h
strategy        dw      dev_strategy
interrupt       dw      dev_int
dev_name        db      1
        db      7 dup(?)
;
rh_off  dw      ?
rh_seg  dw      ?;
bpb     equ     $
        dw      512
        db      2
        dw      1
        db      2
        dw      112
        dw      720
        db      0fdh
        dw      2
;
bpb_ptr dw      bpb
;
; current virtual disk information
;
total   dw      ?
verify  db      0
start_sec       dw      0
vdisk_ptr       dw      0
user_dta        dd      ?
boot_rec        equ     $
        db      3 dup(0)
        db      'IBM  2.0'
        dw      512
        db      2
        dw      1
        db      2
        dw      112
        dw      720
        db      0fdh
        dw      2
;
;
funtab  label   byte
        dw      init
        dw      media_check
        dw      build_bpb
        dw      ioctl_in
        dw      input
        dw      nd_input
        dw      in_stat
        dw      in_flush
        dw      output
        dw      out_verify
        dw      out_stat
        dw      out_flush
        dw      ioctl_out
;
;
in_save proc    near
        mov     ax,es:word ptr dta[bx]
        mov     cs:user_dta,ax
        mov     ax,es:word ptr dta+2[bx]
        mov     cs:user_dta+2,ax
        mov     ax,es:word ptr count[bx]
        xor     ah,ah
        mov     cs:total,ax
        ret
in_save endp
;
calc_addr       proc    near
        mov     ax,cs:start_sec
        mov     cx,20h
        mul     cx
        mov     dx,cs:vdisk_ptr
        add     dx,ax
        mov     ds,dx
        xor     si,si
        mov     ax,cs:total
        mov     cx,512
        mul     cx
        or      ax,ax
        jnz     move_it
        mov     ax,0ffffh
move_it:
        xchg    cx,ax
        ret
calc_addr       endp
;
sector_read proc near
        call    calc_addr
        mov     es,cs:user_dta+2
        mov     di,cs:user_dta
;
        mov     ax,di
        add     ax,cx
        jnc     read_copy
        mov     ax,0ffffh
        sub     ax,di
        mov     cx,ax
read_copy:
rep     movsb
        ret
sector_read endp
;
sector_write proc near
        call    calc_addr
        push    ds
        pop     es
        mov     di,si
        mov     ds,cs:user_dta+2
        mov     si,cs:user_dta
;
;
        mov     ax,si
        add     ax,cx
        jnc     write_copy
        mov     ax,0ffffh
        sub     ax,si
        mov     cx,ax
write_copy:
rep     movsb
        ret
sector_write endp
;
dev_strategy:
        mov     cs:rh_seg,es
        mov     cs:rh_off,bx
        ret
;
;
;
dev_int:
        cld
        push    ds
        push    es
        push    ax
        push    bx
        push    cx
        push    dx
        push    di
        push    si
;
;
        mov     al,es:[bx]+2
        rol     al,1
        lea     di,funtab
        xor     ah,ah
        add     di,ax
        jmp     word ptr[di]
;
;
init:
        push    cs
        pop     dx
        lea     ax,cs:vdisk
        mov     cl,4
        ror     ax,cl
        add     dx,ax
        mov     cs:vdisk_ptr,dx
        mov     ax,2d00h
        add     dx,ax
        mov     es:word ptr br_addr_0[bx],0
        mov     es:br_addr_1[bx],dx
        mov     es:byte ptr units[bx],1
        lea     dx,bpb_ptr
        mov     es:bpb_ptr_off[bx],dx
        mov     es:bpb_ptr_seg[bx],cs
        mov     es,cs:vdisk_ptr
        xor     di,di
        lea     si,boot_rec
        mov     cx,24
rep     movsb
        mov     cs:word ptr start_sec,1
        mov     cs:word ptr total,2
        call    calc_addr
        push    ds
        pop     es
        mov     di,si
        xor     al,al
rep     stosb
        mov     ds:byte ptr [si],0fch
        mov     ds:byte ptr 1[si],0ffh
        mov     ds:byte ptr 2[si],0ffh
        push    ds
        push    si
        mov     cs:word ptr start_sec,3
        mov     cs:word ptr total,2
        call    calc_addr
        push    ds
        pop     es
        mov     di,si
        pop     si
        pop     ds
rep     movsb
        mov     cs:word ptr start_sec,5
        mov     cs:word ptr total,4
        call    calc_addr
        xor     al,al
        push    ds
        pop     es
        xor     di,di
rep     stosb
        mov     es,cs:rh_seg
        mov     bx,cs:rh_off
        status  done,moerror,0
        jmp     exit
;
;
media_check:
        mov     es:byte ptr ret_byte[bx],1
        status  done,moerror,0
        jmp     exit
;
;
;
build_bpb:
        push    es
        push    bx
        mov     cs:word ptr start_sec,0
        mov     cs:word ptr total,1
        call    calc_addr
        push    cs
        pop     es
        lea     di,bpb
        add     si,11
        mov     cx,13
rep     movsb
        pop     bx
        pop     es
        lea     dx,bpb
        mov     es:bpba_ptr[bx],dx
        mov     es:bpba_ptr+2[bx],cs
        mov     es:dta[bx],dx
        mov     es:dta+2[bx],cs
        status  done,moerror,0
        jmp     exit
;
;
ioctl_in:
ioctl_out:
nd_input:
in_stat:
in_flush:
out_stat:
out_flush:
;
input:
        call    in_save
        mov     ax,es:word ptr ssn[bx]
        mov     cs:start_sec,ax
        mov     ax,es:word ptr count[bx]
        mov     cs:total,ax
        call    sector_read
        mov     bx,cs:rh_off
        mov     es,cs:rh_seg
        status  done,moerror,0
        jmp     exit
;
;
output:
        call    in_save
        mov     ax,es:word ptr ssn[bx]
        mov     cs:start_sec,ax
        mov     ax,es:word ptr count[bx]
        mov     cs:total,ax
        call    sector_write
        mov     bx,cs:rh_off
        mov     es,cs:rh_seg
        cmp     cs:byte ptr verify,0
        jz      no_verify
        mov     cs:byte ptr verify,0
        jmp     input
no_verify:
        status  done,moerror,0
        jmp     exit
out_verify:
        mov     cs:byte ptr verify,1
        jmp     output
;
;
exit:
        pop     si
        pop     di
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        pop     es
        pop     ds
        ret
e_q_p:
 if ($-start) mod 16
 org ($-start)+16-(($-start) mod 16)
 endif
vdisk   equ     $
vdsk    endp
cseg    ends
        end     begin
