            PAGE        63,132      ; printer format
            
name        _800        ; 800 Rel II  Ver 1.80

                        ; WARNING: this program must be assembled, linked
                        ; and converted to .COM .

code        segment
assume      cs:code     

org         0h
new_base    db          11 dup (?)  ; room for base table


org         80h
prmlen      db          ?           ; Length of command line parameters
prm         db          7fh dup (?) ; Command line


org         100h        ; .COM format

res_sh_par equ 10   ; resident shift in paragraphs
res_sh_byt equ res_sh_par*16 ; resident shift in bytes

start_resident:

begin:      jmp         init        ; jmp to initialization


oldint13    dd          ?        ; old int 13 (disk)

dosver      dw          ?
pspseg      dw          ?

                        ; table of format-gap and media-state.
                        ; sectors,
                        ; format-gap and media-state for double_den,
                        ; high_den, micro, micro144.
                        ; 0=format not supported.

low80       equ         54h           ; media_state for 80 track low density
low80co     equ         57h           ; media_state compatibility mode

sct_cyl     dw          2a0ah         ;  360K drive: 43 Tracks, 10 sectors
            dw          5411h         ; 1200K drive: 85 Tracks, 17 sectors
            dw          540ah         ;  720K drive: 85 Tracks, 10 sectors
            dw          5414h         ; 1440K drive: 85 Tracks, 20 sectors

state_gap   db          09h,50h,93h,50h,74h,50h,97h,50h,97h ; 360K
            db          0ah,2ah,93h,2ah,74h,2ah,97h,2ah,97h ; 400K
            db          0fh,00h,00h,54h,15h,00h,00h,6ch,17h ;1200K
            db          11h,00h,00h,1eh,15h,00h,00h,6ch,17h ;1360K
            db          12h,00h,00h,00h,00h,00h,00h,6ch,17h ;1440K
            db          14h,00h,00h,00h,00h,00h,00h,29h,17h ;1600K
            db          00h ; end of table


base_tbl    db          0dfh,002h,025h,002h,009h,01bh,0ffh,050h,0f6h,00fh,008h
                        ; 720K base table
                        
base_length equ         size new_base

my_boot     label       byte       ; 800KB 5¬" boot sector changes
            jmp         $+3        ; system ID overwritten.
            nop                    ; reset double step bit
            and         byte ptr cs:[490h],11011111b
            db          0ebh       ; jmp (to boot program).
my_boot_len equ         $-offset my_boot

drive       db          0,0         ; drive types
chgav       db          0,0         ; change line available flag

nodrive     equ         0           ; no drive
double_den  equ         1           ; 360K drive
high_den    equ         2           ; 1.2M drive
micro       equ         3           ; 3« inch 720K drive
micro144    equ         4           ; 3« inch 1.44M drive

drive_sel   equ         byte ptr ds:[43Fh] ; Drive Select Status
media_ctl   equ         byte ptr ds:[48Bh]; Last Data & Step Rate
media_state equ         byte ptr ds:[490h+si] ; (data rate, double step, etc)
DRS_port    equ         3f7h ; Data Rate Select

bps_300     equ         01000000b   ; 300bps data rate (only 5¬ low-density)

ST2         equ         byte ptr ds:[444h]      ; ST2: controller status
wrongcyl    equ         00010000b               ; Wrong cylinder bit

media_known equ         00010000b            ; media type already established

base_point  equ         ds:[1eh*4]  ; pointer to base table.
lastsct     equ         es:[bx+4]   ;last sector in base_table

double_step equ         00100000b   ; double step bit

on          equ         1
off         equ         0
inv_cmd     equ         2           ; invalid prm on command line.
cmd         db          1           ; 1 when 800 is active.

PAGE

oldint13p   proc                    ; call old int 13 handler
            pushf
            cli
            call        oldint13
            ret
oldint13p   endp

reset       proc
            pushf
            push        ax

            mov         ah,0        ; reset disk

            call        oldint13p

            pop         ax
            popf
            ret
reset       endp




test300     proc
            push        ax                 ; test 300Kbs (360KB in 1.2MB)
            mov         al,media_state     ;             (720KB in 1.2MB)
            and         al,11000000b       ;             (800KB in 1.2MB)
            cmp         al,bps_300
            pop         ax
            ret
test300     endp


setCTR      proc
            push        ax
            push        bx
            push        dx

            mov         bl,media_ctl
            mov         al,media_state ; media_state.tr_rate=>media_ctl.LASTRATE
            rol         al,1
            rcl         bl,1
            rol         al,1
            rcl         bl,1
            ror         bl,1
            ror         bl,1
            mov         media_ctl,bl
            and         al,11b
            mov         dx,DRS_port  ; set Controller Transfer Rate
            out         dx,al

            pop         dx
            pop         bx
            pop         ax
            ret
setCTR      endp


setESDI     proc                         ; input  CH=Cylinders CL=sectors
            push        ax               ; output ES:DI base table
            push        bx
            push        dx

            mov         al,drive[si]
            cbw
            cmp         al,double_den
            jb          exitCY
            cmp         al,micro144
            ja          exitCY

            cmp         ch,84       ; max 85 tracks.
            ja          exitCY

            xor         bx,bx
foloop:     mov         dl,state_gap[bx] ; look for format in table
            or          dl,dl
            jz          exitCY

            cmp         dl,cl       ; format found
            jae         fofound

            add         bx,09h      ; loop.
            jmp         foloop

fofound:    push        di
            mov         di,ax
            shl         di,1
            mov         dx,word ptr state_gap[bx+di-1]   ; load dl=gap
            pop         di
            or          dx,dx                            ;      dh=media state
            je          exitCY

set_st_gap: cmp         ch,42       ; if tracks>43 ...
            jbe         fook

            cmp         al,high_den
            ja          fook

            jb          exitCY      ; ... and drive=360K then not supported.

            cmp         dh,74h      ; ... and drive=1.2M and low-density then
            jne         fook

core2:      mov         dh,low80    ; set single step.

fook:       mov         media_state,dh  ; set media state
                                        ; set BASE TABLE
            mov         base_tbl[4],cl  ; set EOT
            mov         base_tbl[7],dl  ; set format gap

            push        cs   ; move 1.6M,1.44M,1.36M,800K,400K,720K base table
            pop         es   ; on new_base

            push        cx
            push        si

            mov         di,offset new_base+res_sh_byt
            mov         si,offset base_tbl
            mov         cx,base_length

            push        ds
            push        cs
            pop         ds
            cld
            rep         movsb
            pop         ds

            pop         si
            pop         cx

            mov         di,offset new_base+res_sh_byt ;ES:DI points to base table.

exitNC:     clc
            jmp         short exitESDI
exitCY:     stc                   ; format not supported.
exitESDI:   pop         dx
            pop         bx
            pop         ax
            ret

setESDI     endp

PAGE

newint13    proc
            sti                     ; new int 13h handler
            cmp         ah,18h
            jne         chkon
            cmp         cx,0fedch   ; answer to installation request
            jne         chkon
            push        cs
            pop         es          ; ES:=CS
            mov         ax,0ba98h
            stc
            retf        2

chkon:      cmp         cmd,off
            je          oldi
            cmp         ah,1
            jbe         oldi
            cmp         dl,1        ; do oldint if Hard-disk request
            jbe         continue
oldi:       cli
            jmp         oldint13

continue:   push        ds
            push        si

            xor         si,si       ; set DS to seg 0000h
            mov         ds,si

            mov         si,dx       ; save drive number
            and         si,00000001b 

            cmp         ah,5
            jae         chkbootwr

            push        es          ; read/write/verify
            push        bx
            push        dx
            les         bx,base_point
            mov         dl,cl
            add         dl,al
            dec         dl
            cmp         dl,lastsct
            jbe         donoth
            mov         dh,1bh
            mov         lastsct,dx   ; allows 1.6MB read/write/verify
donoth:     pop         dx
            pop         bx
            pop         es


            cmp         drive[si],high_den   ; 1.2MB drive
            jne         chkbootwr
            test        media_state,media_known  ; media unknown
            jnz         chkbootwr
                                             ; establish media
            call        test300              ; low density in 1.2MB
            jne         establ
            mov         media_state,61h      ; 360/1.2 not established

establ:     push        ax
            push        cx

            mov         ax,0401h    ; verify command on trk 0 to make
            mov         cx,0001h    ; disk type established.
            call        oldint13p

            jnc         twc

            pop         cx          ; can't establish media.
            pop         si
            jmp         short intexit

twc:        call        test300     ; low density in 1.2MB drive
            jne         popchkboot

            mov         ax,0401h    ; verify track 1 to know
            mov         ch,01h      ; if double step needed.

            call        oldint13p

            test        ST2,wrongcyl ; if wrong cyl then single step needed
            call        reset

            je          popchkboot
core1:      mov         media_state,low80

popchkboot: pop         cx
            pop         ax

chkbootwr:  cmp         ah,3
            jne         chk08
            cmp         cx,0001h    ; writing boot sector ?
            jne         oldint
            cmp         dh,0
            jne         oldint
            call        test300 ; double density in 1.2M drive
            jne         oldint
            test        media_state,double_step ; 80 track
            jnz         oldint
            cmp         byte ptr es:[bx+1],01h ; is boot OK for 5¬ 800K ?
            je          oldint

            push        di          ; change boot sector before writing
            push        si
            push        cx
            mov         cl,es:[bx+1]
            sub         cl,9
            mov         es:[bx+my_boot_len],cl
            mov         di,bx
            mov         si,offset my_boot
            mov         cx,my_boot_len

            push        ds
            push        cs
            pop         ds
            cld
            rep         movsb
            pop         ds

            pop         cx
            pop         si
            pop         di
            
oldint:     call        oldint13p   ; call old int 13h handler

intexit :   pop         si
            pop         ds
            retf        2            


chk08:      cmp         ah,08h      ; get drive parameters
            jne         chk18

            mov         bl,drive[si]  ; drive type
            mov         dh,01       ; 2 heads

            push        bx
            xor         bh,bh
            dec         bl
            shl         bl,1
            mov         cx,sct_cyl[bx] ; CL=sectors CH=tracks
            pop         bx

            call        setESDI
            jc          oldint

            mov         dl,2        ; 2 drives
            cmp         drive[1],0
            jne         ok2
            dec         dl

ok2:        clc
            xor         ah,ah
            jmp         intexit

chk18:      cmp         ah,18h      ; set media type for format ?
            jne         oldint

            push        ax

            cmp         chgav[si],1 ; change line available ?
            jne         exitcl

            mov         ah,16h
            call        oldint13p   ; change line active ?
            jnc         exitcl

            push        cx
            push        dx
            mov         ax,0401h
            mov         cx,0001h    ; reset change line
            mov         dh,0
            call        oldint13p
            cmp         ah,80h      ; exit on drive not ready error
            pop         dx
            pop         cx
            call        reset
            jne         exitcl
            stc
            pop         si          ; to compensate PUSH AX
            jmp         short intexit

exitcl:     pop         ax

            call        setESDI
            jc          oldint

            cmp         word ptr chgav,0
            je          noCTR

            call        setCTR

noCTR:      clc
            jmp         intexit
newint13    endp


oldint21    dd          ?

ID_1        dw          02d0h       ; 360K drive
            dw          0960h       ; 1.2M drive
            dw          05a0h       ; 720K drive
ID_4        dw          0b40h       ; 1.44M drive

Searchlen   equ         (offset ID_4 - offset ID_1 + 2) / 2

f44_chgs    db          00h         ; device type
            db          2bh         ; 43 tracks (360K drive)
            db          01h         ; sectors/cluster
            dw          0070h       ; root entries
            dw          035ch       ; total sectors
            db          0f0h        ; media type
            db          03h         ; sectors/FAT
            db          0ah         ; sectors/track

entrylen    equ         $-offset f44_chgs

            db          01h
            db          55h         ; 85 tracks (1.2M drive)
            db          01h
            dw          00e0h
            dw          0b4ah
            db          0f0h
            db          09h
            db          11h

            db          07h
            db          55h         ; (720K drive)
            db          01h
            dw          00e0h
            dw          06a4h
            db          0f0h
            db          05h
            db          0ah

            db          07h
            db          55h         ; (1.44M drive)
            db          01h
            dw          00e0h
            dw          0d48h
            db          0f0h
            db          0ah
            db          14h
                                    ; Alternate tables: for prgs<>diskcopy
IDA_1       dw          035ch       ; 360K drive
            dw          0b4ah       ; 1.2M drive
            dw          06a4h       ; 720K drive
IDA_4       dw          0d48h       ; 1.44M drive

f44_achgs   db          00h
            db          28h         ; 40 tracks (360K drive)
dos4_1:     db          02h
            dw          0070h
            dw          02d0h       ; total sectors
            db          0fdh        ; media type
dos4_2:     db          02h         ; sectors/FAT
            db          09h         ; sectors/track

            db          01h
            db          50h         ; 80 tracks (1.2M drive)
            db          01h
            dw          00e0h
            dw          0960h
            db          0f9h
            db          07h
            db          0fh

            db          02h
            db          50h         ; (720K drive)
dos4_3:     db          02h
            dw          0070h
            dw          05a0h
            db          0f9h
dos4_4:     db          03h
            db          09h

            db          07h
            db          50h         ; (1.44M drive)
            db          01h
            dw          00e0h
            dw          0b40h
            db          0f0h
            db          09h
            db          12h



fname1      db          'DISKCOPY'
fname1len   equ         $-offset fname1
fname2      db          'DISKCOMP'
fname2len   equ         $-offset fname2
fname3      db          'FORMAT'
fname3len   equ         $-offset fname3

newint21    proc
            sti
            cmp         ax,440dh    ; IOctl get default device parameters
            jne         jmpoldint21
            cmp         cx,0860h
            jne         jmpoldint21
            xchg        bx,dx
            test        byte ptr ds:[bx],1  ; BPB from disk or default ?
            xchg        dx,bx
            jz          dochgs

jmpoldint21:cli
            jmp         oldint21     ; from disk

dochgs:     pushf                    ; from default
            cli
            call        oldint21

            pushf
            push        es
            push        ax
            push        bx
            push        cx
            push        si
            push        di
            push        dx
            push        ds

            cmp         cmd,on
            je          donew21
            jmp         exitsrc

donew21:    mov         ah,62h      ; get PSP address of current process
            pushf
            cli
            call        oldint21

            mov         ds,bx
            mov         pspseg,bx
            mov         ds,ds:[2ch] ; get environment address
            mov         si,0ffffh
loopen:     inc         si
            cmp         word ptr ds:[si],0000h  ; find end of environment
            jne         loopen

            add         si,3
loopname:   inc         si
            cmp         byte ptr ds:[si],00h    ; find end of full filename.
            jne         loopname

loopfname:  dec         si
            and         byte ptr ds:[si],11011111b ; lower to uppercase
            cmp         byte ptr ds:[si],'\'    ; find begin of filename.
            jne         loopfname
            inc         si
            push        cs
            pop         es

            mov         dx,si

            mov         di,offset fname1        ; Is Diskcopy running ?
            mov         cx,fname1len

            cld
            repe        cmpsb
            je          exitsrc

            mov         si,dx
            mov         di,offset fname2        ; Is Diskcomp running ?
            mov         cx,fname2len

            repe        cmpsb
            je          exitsrc

            cmp         dosver, 0500h           ; DOS 5+ ?
            jb          exitsrc

            mov         si,dx
            mov         di,offset fname3        ; Is Format running ?
            mov         cx,fname3len

            repe        cmpsb
            jne         exitsrc

            mov         ds,pspseg               ; look for /T on cmd-line

            mov         di,0        ; look for '/'
            mov         si,0
            mov         cl,ds:[80h] ; prmlen
slhlopp:    mov         bl,ds:[81h+si]
            cmp         bl,'/'
            jne         proxcf
            inc         si
            dec         cl
            mov         bx,word ptr ds:[81h+si]
            or          bx,2020h    ; upper_case to lower_case
            cmp         bx,':t'
            je          exitsrc

proxcf:     inc         si
            dec         cl
            jg          slhlopp
            cmp         cl, 1   ;  reset Z flag

exitsrc:    pop         ds

            pop         bx
            push        dx

            mov         ax,word ptr ds:[bx][0fh]  ; look for media type
                                                  ; (total sectors).
            mov         cx,searchlen              
            push        cs
            pop         es

            mov         dx,offset f44_achgs
            jne         contchgs

            mov         dx,offset f44_chgs

contchgs:   mov         si,offset ID_1
            mov         di,si
            cld
            repne       scasw
            je          chgs

            mov         cx,searchlen
            mov         si,offset IDA_1
            mov         di,si
            repne       scasw
            jne         exit21

chgs:       sub         di,si
            dec         di
            dec         di

            shr         di,1
            mov         ax,di
            mov         cl,entrylen
            mul         cl
            mov         di,ax

            add         di,dx

            mov         al,es:[di]              ; device type.
            mov         ds:[bx][01h],al

            mov         al,es:[di][1]              ; change device parameter
            mov         ds:[bx][04h],al         ; table: tracks,

            mov         al,es:[di][2]
            mov         ds:[bx][09h],al

            mov         ax,es:[di][3]
            mov         ds:[bx][0dh],ax

            mov         ax,es:[di][5]
            mov         ds:[bx][0fh],ax         ; total sectors,

            mov         ax,es:[di][7]
            mov         ds:[bx][11h],ax         ; media type & sectors/FAT,

            mov         al,es:[di][9]
            mov         ds:[bx][14h],al         ; sectors/track.

exit21:     pop         dx
            pop         di
            pop         si
            pop         cx
            pop         bx
            pop         ax
            pop         es
            popf

            retf        2


newint21    endp


end_resident:           

resident_length         equ         end_resident - start_resident
resident_par            equ         (resident_length+100h-res_sh_byt-1)/16+1

PAGE

assume      ds:code,ss:code         ; initialized by DOS (.COM)

inst_msg    db          10
db ' ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿',13,10
db ' ³  800 II    Diskette BIOS Enhancer     Version 1.80         July 14th 1991  ³',13,10
db ' ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´',13,10
db ' ³  Copyright (c) 1991         Alberto Pasquale          All rights reserved  ³',13,10
db ' ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´',13,10
refmsg:
db ' ³  Drive A:                             800 now O                            ³',13,10
db ' ³  Drive B:                             800h for help.                       ³',13,10
db ' ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ',13,10,'$'
        
inv_cmd_msg db          10
db ' ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿',13,10
refmsg2:
db ' ³  WARNING:                                                                  ³',13,10
db ' ³                                                                            ³',13,10
db ' ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ',13,10,7,7,'$'

invcmdmsg   db 'Invalid command^'
invcmdmsglen            equ         $-offset invcmdmsg

linelongmsg db 'Command line too long !'
linelongmsglen          equ         $-offset linelongmsg

inv_dos_msg db          10
db ' ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿',13,10
db ' ³  WARNING:  800 II requires DOS 3.30 or later for full performance !!!      ³',13,10
db ' ³            Some DOS commands may malfunction.                              ³',13,10
db ' ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ',13,10,7,7,'$'



drivetypemsg dw         offset notinstmsg
            dw          offset doubdenmsg
            dw          offset highdenmsg
            dw          offset micro72msg
            dw          offset micro14msg
            dw          offset invdrivmsg

notinstmsg  db          ' Not Installed. '
doubdenmsg  db          '  360KB (5¬").  '
highdenmsg  db          '  1.2MB (5¬").  '
micro72msg  db          '  720KB (3«").  '
micro14msg  db          ' 1.44MB (3«").  '
invdrivmsg  db          ' Unknown type.  '
drivemsglen equ         $-offset invdrivmsg

compmsg     db          '(Compatibility mode)'
compmsglen  equ         $-offset compmsg

compat1     equ         byte ptr offset core1+4 ; locations to be changed
compat2     equ         byte ptr offset core2+1 ; in compatibility mode.

inst_flag   db          0           ; 1 if 800 already installed
ke_flag     db          0           ; 1 if /ke switch used

set21       db          on
ocmd        db          ?


wrdos       proc
            mov         ah,9        ; writes string by DOS
            int         21h
            ret
wrdos       endp

readcmd     proc                    ; read parameter on command line
            cmp         prmlen,0
            ja          contrd
            ret
contrd:
            mov         di,0        ; look for '/'
            mov         si,0
            mov         cl,prmlen
slhloop:    mov         bl,prm[si]
            cmp         bl,'/'
            je          chkcmd
            cmp         bl,' '
            je          proxch
invalid:    mov         al,es:cmd
            mov         cs:ocmd,al
            mov         es:cmd,inv_cmd
                                    ; show invalid command line parameter
            push        es

            push        cs
            pop         es

            cmp         prmlen,59
            ja          linelong

            lea         di,offset refmsg2+18+81+1-invcmdmsglen[si]
            mov         si,offset invcmdmsg
            mov         cx,invcmdmsglen
            cld
            rep         movsb

            mov         si,offset prm
            mov         di,offset refmsg2+18

            xor         ch,ch
            mov         cl,prmlen
            cld
            rep         movsb

            jmp         short exitinv

linelong:   mov         si,offset linelongmsg   ; show line too long msg
            mov         di,offset refmsg2+19
            mov         cx,linelongmsglen
            cld
            rep         movsb

exitinv:    pop         es
            mov         dx,offset inv_cmd_msg
            call        wrdos
            ret

proxch:     inc         si
            dec         cl
            jnz         slhloop
            ret

chkcmd:     cmp         cl,2
            jb          invalid
            inc         si
            dec         cl
            mov         bx,word ptr prm[si]
            or          bx,2020h    ; upper_case to lower_case

            cmp         bl,'0'                  ;/0
            jne         chk36
            cmp         di,1
            ja          invalid
            mov         es:drive[di],nodrive
            inc         di
            cmp         cl,2
            jb          proxch
            cmp         bx,'00'
            jne         proxch
            jmp         indec

chk36:      cmp         cl,2
            jb          jinvalid
            cmp         bx,'63'                 ;/36
            jne         chk12
            cmp         di,1
            ja          jinvalid
            mov         es:drive[di],double_den
            inc         di
            jmp         indec

chk12:      cmp         bx,'21'                 ;/12
            jne         chk72
            cmp         di,1
            ja          jinvalid
            mov         es:drive[di],high_den
            inc         di
            jmp         indec

chk72:      cmp         bx,'27'                 ;/72
            jne         chk14
            cmp         di,1
            ja          jinvalid
            mov         es:drive[di],micro
            inc         di
            jmp         indec

chk14:      cmp         bx,'41'                 ;/14
            jne         chkco
            cmp         di,1
            jbe         set14
jinvalid:   jmp         invalid
set14:      mov         es:drive[di],micro144
            inc         di
            jmp         short indec

chkco:      cmp         bx,'oc'                 ;/CO
            jne         chkke
            mov         bl,low80
            cmp         es:compat1,low80co
            je          set_co
            mov         bl,low80co
set_co:     mov         es:compat1,bl
            mov         es:compat2,bl
            jmp         short indec

chkke:      cmp         bx,'ek'                 ;/KE
            jne         chkcmdon
            cmp         inst_flag,1
            jne         setkeflag
            jmp         invalid
setkeflag:  mov         ke_flag,1
            jmp         short indec

chkcmdon:   cmp         bx,'no'                 ;/ON
            jne         chkcmdof
            mov         es:cmd,on
            jmp         short indec

chkcmdof:   cmp         bx,'fo'                 ;/OFF
            je          setoff
            jmp         invalid
setoff:     cmp         cl,3
            jae         chkf
            jmp         invalid
chkf:       cmp         prm[si+2],'F'
            je          cmof
            cmp         prm[si+2],'f'
            je          cmof
            jmp         invalid
cmof:       inc         si
            dec         cl
            mov         es:cmd,off

indec:      inc         si
            dec         cl
            jmp         proxch
readcmd     endp


show_ins    proc
            mov         si,0

showtype:   mov         dl,es:drive[si]         ; show drive types
            xor         dh,dh
            mov         di,dx
            cmp         di,4
            jbe         typeok
            mov         di,5
typeok:     shl         di,1
            lea         di,drivetypemsg[di]

            push        si
            push        es
            cmp         si,1
            mov         si,[di]
            push        cs
            pop         es
            mov         di,offset refmsg+13
            jne         typecont
            add         di,81
typecont:   mov         cx,drivemsglen
            cld
            rep         movsb
            pop         es
            pop         si

            inc         si
            cmp         si,1
            jbe         showtype

            cmp         es:cmd,off
            je          prgoff                   ; show 800 state
            mov         word ptr refmsg+50,' n'
            mov         byte ptr refmsg+52,'!'
            jmp         showco
prgoff:     mov         word ptr refmsg+50,'ff'
            mov         word ptr refmsg+52,'! '
showco:     cmp         es:compat1,low80
            je          showin

            push        es

            push        cs                      ; copy compatibility msg
            pop         es
            mov         si,offset compmsg
            mov         di,offset refmsg+56
            mov         cx,compmsglen
            cld
            rep         movsb

            pop         es

showin:     mov         dx,offset inst_msg      ; show name msg
            call        wrdos
            ret
show_ins    endp


estmedia    proc
            push        ds            ; make 360K in 1.2M unestablished
            xor         ax,ax
            mov         ds,ax

            mov         si,1
setmedia:   mov         al,media_state
            and         al,11000000b
            cmp         al,bps_300
            jne         try_next
            mov         media_state,61h
try_next:   dec         si
            jz          setmedia

            pop         ds
            ret
estmedia    endp


get_drive   proc
            cmp         bl,0
            ja          enddr       ; valid drive type from service #8
            mov         bl,4
            cmp         cx,4f12h    ; type 4: 1.44M drive
            je          enddr
            dec         bl          
            cmp         cx,4f09h    ; type 3: 720K drive
            je          enddr
            dec         bl
            cmp         cx,4f0fh    ; type 2: 1.2M drive
            je          enddr
            dec         bl
            cmp         cx,2709h    ; type 1: 360K drive
            je          enddr
            dec         bl          ; type 0: not installed
enddr:      ret
get_drive   endp

use1st      proc
            push        es
            mov         ah,08h
            mov         dl,00h
            int         13h
            mov         ah,08h
            mov         dl,01h
            int         13h
            pop         es
            ret
use1st      endp

init:       mov         ah,18h      ; initialization
            mov         dl,8Fh
            mov         cx,0fedch
            int         13h         ; installation check
            cmp         ax,0ba98h   ; if installed then ES=resident segment

            jne         notinsted
            mov         inst_flag,1
            jmp         short rdcmd

notinsted:  mov         ah,15h      ; read DASD type for drive 0
            mov         dl,0
            int         13h
            jc          eseqcs

            push        ax
            push        si
            push        ds
            mov         ax,0        ; Set Last Transfer Rate
            mov         ds,ax
            mov         al, drive_sel
            shr         al,1
            shr         al,1
            shr         al,1
            shr         al,1
            and         ax, 11b
            mov         si, ax
            call        setCTR
            pop         ds
            pop         si
            pop         ax

            cmp         ah,2        ; change line available ?
            jne         chkd1

            mov         chgav[0],1  ; set change line available flag

chkd1:      mov         ah,15h      ; read DASD type for drive 1
            mov         dl,1
            int         13h

            cmp         ah,2        ; change line available ?
            jne         eseqcs

            mov         chgav[1],1  ; set change line available flag

eseqcs:     push        cs
            pop         es
rdcmd:      call        readcmd     ; read command line parameters

            cmp         es:cmd,inv_cmd
            jne         cmpins
            mov         al,cs:ocmd
            mov         es:cmd,al
            mov         al,1        ; return code if error on cmd line
            jmp         exit

cmpins:     cmp         inst_flag,1
            je          showins

            cmp         word ptr es:drive,0
            jne         showins

            mov         ah,8        ; set number of tracks of both drives
            xor         dl,dl
            push        es
            int         13h
            pop         es
            jc          cmosread
            call        get_drive
            mov         es:drive[0],bl

            mov         ah,8
            mov         dl,1
            push        es
            int         13h
            pop         es
            call        get_drive
            mov         es:drive[1],bl
            jmp         short showins

cmosread:   push        ds
            mov         ax,0f000h
            mov         ds,ax
            mov         al,ds:[0fffeh]          ; System ID
            pop         ds
            cmp         al,0fdh     ; do not read CMOS-RAM if PC or XT
            jae         read_sw
            cmp         al,0fbh
            jne         readcmos

read_sw:    int         11h         ; get configuration
            test        al,1        ; are there drives ?
            jz          showins

            mov         es:drive[0],1 ; at least 1 drive.

            mov         cl,6
            shr         al,cl
            cmp         al,1        ; are there 2 drives ?
            jb          showins

            mov         es:drive[1],1
            jmp         short showins

readcmos:   mov         al,10h      ; read drive type from CMOS-RAM
            out         70h,al
            jmp         $+2
            jmp         $+2
            jmp         $+2
            in          al,71h

            xor         ah,ah
            mov         cx,4
divdr:      shr         al,1
            rcl         ah,1
            loop        divdr
            
            mov         word ptr es:drive,ax

showins:    call        show_ins

            call        estmedia

            cmp         inst_flag,1
            jne         install

            call        use1st

            mov         al,00h      ; return code

exit:       mov         ah,4ch    ; exit
            int         21h
            
install:    mov         ah,30h      ; check dos version 
            int         21h
            xchg        ah,al
            mov         dosver, ax
            cmp         ax,0400h    ; 4.0
            jb          dos3
            cmp         ax,0500h    ; 5.0
            jae         dos3

            mov         byte ptr dos4_1,1 ; set 360KB/720KB drive defaults
            mov         byte ptr dos4_2,3 ; to 1sct/clust
            mov         byte ptr dos4_3,1
            mov         byte ptr dos4_4,5

dos3:       cmp         ax,031Eh    ; 3.30 or later
            jae         cont_ins

            cmp         ax,0314h    ; 3.20
            jae         wrinvmsg

            mov         cs:set21,off ; disable new INT21

wrinvmsg:   mov         dx,offset inv_dos_msg
            call        wrdos

cont_ins:   cmp         ke_flag,1
            je          saveold13

            mov         es,cs:[2ch] ; release environment
            mov         ah,49h
            int         21h
            
saveold13:  mov         ax,3513h    ; save old INT 13h vector
            int         21h
            mov         word ptr oldint13,bx
            mov         word ptr oldint13+2,es

            mov         ax,3521h    ; save old INT 21h vector
            int         21h
            mov         word ptr oldint21,bx
            mov         word ptr oldint21+2,es

            mov         ax,cs       ; move resident on PSP
            sub         ax,res_sh_par
            mov         es,ax
            push        es
            mov         si,offset start_resident
            mov         di,si
            mov         cx,resident_length
            cld
            rep         movsb
            
            pop         ds
            mov         dx,offset newint13
            mov         ax,2513h    ; steal INT13 vector
            int         21h

            cmp         cs:set21,on
            jne         TSR

            mov         dx,offset newint21
            mov         ax,2521h    ; steal INT21 vector
            int         21h

TSR:        mov         dx,resident_par ; Terminate but Stay Resident
            mov         ax,3100h
            int         21h

code        ends

end         begin
