GENERCFG.A86
资源名称:drdossrc.zip [点击查看]
上传用户:xiaogehua
上传日期:2007-01-08
资源大小:1183k
文件大小:92k
源码类别:
操作系统开发
开发平台:
Asm
- ; File : $GENERCFG.A86$
- ;
- ; Description :
- ;
- ; Original Author : DIGITAL RESEARCH
- ;
- ; Last Edited By : $CALDERA$
- ;
- ;-----------------------------------------------------------------------;
- ; Copyright Work of Caldera, Inc. All Rights Reserved.
- ;
- ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
- ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
- ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
- ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
- ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
- ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
- ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
- ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
- ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
- ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
- ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
- ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
- ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
- ; CIVIL LIABILITY.
- ;-----------------------------------------------------------------------;
- ;
- ; *** Current Edit History ***
- ; *** End of Current Edit History ***
- ;
- ; $Log$
- ;
- ; GENERCFG.A86 1.51 93/12/02 00:15:06
- ; When auto-sizing DEVICEHIGH requirements use EXE header info if present
- ; GENERCFG.A86 1.49 93/11/29 14:10:29
- ; Add NUMLOCK=ON/OFF support
- ; GENERCFG.A86 1.48 93/11/28 15:32:22
- ; Support HIBUFFERS in UMB's
- ; GENERCFG.A86 1.47 93/11/22 15:45:11
- ; Ignore [COMMON] statements
- ; GENERCFG.A86 1.46 93/11/18 16:20:16
- ; Add primitive multi-master checking
- ; GENERCFG.A86 1.45 93/11/17 20:07:17
- ; change history defaults
- ; GENERCFG.A86 1.44 93/11/16 14:10:21
- ; F5 has precedence over ?
- ; GENERCFG.A86 1.42 93/11/08 17:37:06
- ; Move INSTALLHIGH to before INSTALL, so it's now recognised
- ; GENERCFG.A86 1.41 93/11/04 16:28:08
- ; Cosmetic change - the preload name field now strips off "C:" properly
- ; GENERCFG.A86 1.40 93/11/03 22:52:14
- ; Replace chardev test with one for zero units
- ; GENERCFG.A86 1.39 93/11/03 18:21:16
- ; disable CHARDEV test until it gets fixed
- ; GENERCFG.A86 1.38 93/11/03 17:11:05
- ; Preloaded compression drivers maybe loaded from C: when booting
- ; from a diskette.
- ; GENERCFG.A86 1.37 93/10/29 19:42:51
- ; DOS=UMB turns HIDOS on
- ; GENERCFG.A86 1.36 93/09/28 19:54:52
- ; Support "DEVICE?=" syntax, and "SWITCHES=/N"
- ; GENERCFG.A86 1.35 93/09/02 22:35:16
- ; Add header to system allocations
- ; GENERCFG.A86 1.32 93/08/02 14:46:21
- ; hide preload drives from func_device
- ; support INSTALLHIGH
- ; GENERCFG.A86 1.30 93/07/29 14:47:15
- ; Change SETVER method
- ; GENERCFG.A86 1.28 93/07/20 22:32:07
- ; default upper memory link = FFFF
- ; ENDLOG
- include config.equ
- include i:msdos.equ
- include i:char.def
- include i:reqhdr.equ
- include i:driver.equ
- include i:fdos.equ
- include i:f52data.def ; Function 52 DOS Data Area
- include i:doshndl.def ; DOS Handle Structure Definition
- include i:country.def
- TRUE equ 0FFFFh ; value of TRUE
- FALSE equ 0 ; value of FALSE
- F5KEY equ 3F00h ; keys returned by BIOS
- F8KEY equ 4200h ; in boot_options
- CGROUP group INITCODE, INITDATA, INITENV
- INITCODE CSEG PARA 'INITCODE'
- extrn whitespace:near
- extrn build_cmd_tail:near
- extrn device_init:near
- extrn init_static_request:near
- extrn block_device:near
- extrn device_insert:near
- if not ADDDRV
- extrn nls_hook:near
- extrn nls_unhook:near
- endif
- CONFIG_ERRLVL equ 400h ; special 'CONFIG' error level
- ; config_process returns CF set if an error occurred during command file
- ; processing for ADDDRV.EXE
- Public config_process
- config_process: ; Process CONFIG.SYS
- mov save_sp,sp ; save SP for unstructured GOSUB's
- if ADDDRV
- mov error_flag,0
- else
- mov ax,offset envstart ; env buffer is para aligned
- mov cl,4
- shr ax,cl ; convert offset to paras
- mov cx,ds
- add ax,cx ; segment of env variables
- les bx,drdos_ptr
- mov es:DRDOS_ENVSEG[bx],ax ; tell COMMAND.COM where we are
- push ds ! pop es
- endif
- mov ah,MS_DRV_GET ; check whether we are loading from
- int DOS_INT ; drive C:
- cmp al,2
- je preload_security
- push ds
- mov ah,32h ; get DOS parameter block
- mov dl,3 ; ensure drive C: is valid (no critical
- int DOS_INT ; errors)
- pop ds
- cmp al,0ffh ; skip if the drive is not valid
- je preload_stacker
- mov alt_drive,1 ; drive C: should be used also
- jmp preload_stacker
- preload_security:
- call preload_device ; preload the SECURITY device driver
- preload_stacker:
- mov preload_file,offset stacker_file+2
- call preload_device ; preload STACKER from default drive
- jnc preload_done
- mov preload_file,offset dblspace_file+2
- call preload_device ; STACKER failed, try DBLSPACE from default
- jnc preload_done
- cmp alt_drive,0 ; STACKER and DBLSPACE failed on A:,
- je preload_done ; should we look on drive C:?
- mov preload_file,offset stacker_file
- call preload_device ; preload STACKER from drive C:
- jnc preload_done
- mov preload_file,offset dblspace_file
- call preload_device ; STACKER failed, try DBLSPACE from C:
- preload_done:
- mov ax,(MS_X_OPEN*256)+80h ; Open the configuration file
- mov dx,offset cfg_file ; Try Opening the file DCONFIG.SYS
- int DOS_INT ; if this fails then open CONFIG.SYS
- jnc cfg_20 ; Found DCONFIG.SYS
- if ADDDRV
- mov si,dx
- mov dx,offset err_no_command_file
- xor al,al
- call config_error
- jmps cfg_exit
- else
- mov si,offset cfg_file+1
- mov di,offset cfg_file
- call copy_asciiz ; make DCONFIG.SYS = CONFIG.SYS
- mov ax,(MS_X_OPEN*256)+80h ; Open the configuration file
- int DOS_INT ; CONFIG.SYS
- jc cfg_exit ; Return on error without complaint
- endif
- cfg_20:
- mov bx,ax ; get the CONFIG handle
- mov ah,MS_X_CLOSE ; Close the CONFIG file
- int DOS_INT
- cfg_nextline: ; Read the next command line
- call readline ; If Carry then Terminal Error
- jc cfg_exit ; so Exit
- mov ax,boot_options
- cfg_continue:
- push ax ; save query options
- call scan ; Now Scan the command List
- pop ax ; recover query options
- jc cfg_error ; for a matching command name
- call cfg_query ; prompt to see if we want it
- jc cfg_nextline
- call CFG_FUNC[di] ; Execute the request command
- jmps cfg_nextline ; and loop till the end of the file
- cfg_error:
- mov dx,offset bad_command ; Display a Bad command error msg
- mov al,CR ; and the CR terminated string
- call config_error ; then continue processing
- jmps cfg_nextline ; Carry Returned On Error
- cfg_exit:
- mov sp,save_sp ; get back the real stack
- call preload_complete ; move transcient code to final position
- if ADDDRV
- cmp error_flag,1 ;Set CF if error flag is zero
- cmc ;Set CF if error flag is 1
- endif
- ret
- cfg_query:
- ; On Entry:
- ; AX = boot_options key
- ; SI -> command tail
- ; DI -> CFG_
- ; On Exit:
- ; CY set if we should skip command
- ; SI/DI preserved
- ;
- push si
- push di
- test CFG_FLAGS[di],CF_NOF ; are Function Keys allowed ?
- ; clc ; if not process the command
- jz $+5 ! jmp cfg_query90
- cmp ax,F5KEY ; F5 bypasses CONFIG processing
- stc ; so bypass this line
- je cfg_query90
- test CFG_FLAGS[di],CF_QUERY ; specific QUERY request ?
- jnz cfg_query10
- cmp ax,F8KEY ; should we prompt for everything ?
- clc ; if not process the command
- jne cfg_query90
- cfg_query10:
- push si
- mov si,CFG_NAME[di] ; DS:SI -> command name we matched
- cfg_query20:
- lodsb ; get character
- test al,al ; zero terminated
- jz cfg_query30
- xchg ax,dx ; DL= character
- mov ah,MS_C_WRITE
- int DOS_INT ; output the character
- jmps cfg_query20 ; "DEVICE"
- cfg_query30:
- mov dl,'='
- mov ah,MS_C_WRITE
- int DOS_INT ; "DEVICE="
- pop si ; rest of command line
- cfg_query40:
- lodsb
- cmp al,CR ; is it the end of the line ?
- je cfg_query50 ; no, do another character
- xchg ax,dx ; DL= character
- mov ah,MS_C_WRITE
- int DOS_INT ; output the character
- jmps cfg_query40 ; "DEVICE=FILENAME.SYS"
- cfg_query50:
- mov ah,MS_C_WRITESTR ; Output msg of form " (Y/N) ? "
- mov dx,offset confirm_msg1
- int DOS_INT ; do " ("
- mov ah,MS_C_WRITE
- mov dl,yes_char
- int DOS_INT ; do "Y"
- mov dl,'/'
- int DOS_INT ; do "/"
- mov dl,no_char
- int DOS_INT ; do "N"
- mov ah,MS_C_WRITESTR
- mov dx,offset confirm_msg2
- int DOS_INT ; do ") ? "
- cfg_query60:
- call wait_for_key ; wait until a key is pressed
- mov al,default_query_char ; if we timeout default
- jc cfg_query70
- mov ah,MS_C_RAWIN
- int DOS_INT ; read a char
- test al,al ; is it a function key ?
- jnz cfg_query70
- mov ah,MS_C_RAWIN
- int DOS_INT ; throw away function keys
- jmps cfg_query60
- cfg_query70:
- push ax ; save response
- mov ah,MS_C_WRITE
- mov dl,al
- int DOS_INT ; echo the char
- mov ah,MS_C_WRITESTR
- mov dx,offset confirm_msg3 ; "DEVICE=FILENAME.SYS (Y/N) ?"
- int DOS_INT ; now do CR/LF to tidy up
- pop ax
- call toupper ; make response upper case
- cmp al,yes_char ; is it yes ?
- je cfg_query90
- stc ; return CY set, skip this line
- cfg_query90:
- pop di
- pop si
- ret
- call_preload_entry: ; call the preload device driver back door
- push ds ; all DBLSPACE calls destroy DS register
- callf preload_entry
- pop ds
- ret
- preload_complete: ; CONFIG processing complete
- push ds
- push es
- mov ax,4a11h ; DBLSPACE presence check
- xor bx,bx
- int 2fh
- or ax,ax
- jnz reloc_end
- test dx,8000h ; is relocation already complete (may
- jz reloc_end ; be done by HIDEVICE statement)
- mov bx,0ffffh ; query the size of the transcient
- mov ax,4a11h ; portion
- int 2fh
- mov cx,mem_current ; pull transcient portion down to low
- mov es,cx ; memory
- inc cx
- mov es:DMD_ID,'D' ; control block type is 'D' (device
- mov es:DMD_PSP,cx ; driver), owner is self
- mov es:DMD_LEN,ax
- inc ax ; control block overhead
- add mem_current,ax
- mov di,8 ; copy the name to the control block
- mov si,preload_file ; device filename
- preload_complete10:
- lodsb ; get a character
- cmp al,'' ; have we found the '' yet ?
- jne preload_complete10 ; no, go swallow another character
- movsw ! movsw ! movsw ! movsw ; copy the 8 bytes
- mov ax,es
- inc ax ; segment address of free memory
- mov es,ax
- mov bx,0fffeh ; move transcient portion down
- mov ax,4a11h
- int 2fh
- reloc_end:
- pop es
- pop ds
- ret
- PreloadFixup:
- ;------------
- ; On Entry:
- ; None
- ; On Exit:
- ; None
- ; All regs preserved
- ;
- push es
- push bx
- push ax
- mov al,preload_drv ; get number of preload drives
- les bx,func52_ptr
- sub es:F52_PHYDRV[bx],al
- sub es:F52_LASTDRV[bx],al
- pop ax
- pop bx
- pop es
- ret
- PreloadCleanup:
- ;--------------
- ; On Entry:
- ; None
- ; On Exit:
- ; None
- ;
- ; inform DBLSPACE about each device driver
- push ds
- push es
- xor ax,ax
- xchg al,preload_drv ; get number of preload drives
- les bx,func52_ptr
- add es:F52_PHYDRV[bx],al
- add es:F52_LASTDRV[bx],al
- mov ax,4a11h ; DBLSPACE installation check
- xor bx,bx
- int 2fh
- or ax,ax
- jnz broadcast_exit
- test dx,8000h ; initialisation complete?
- jz broadcast_exit
- mov preload_drv,ch ; save # preload drives
- mov dx,mem_max ; top of available memory
- mov cx,mem_current ; base of available memory
- sub dx,cx
- mov ah,55h ; version number
- mov al,dev_count ; number of new units installed
- mov bx,02h
- callf preload_entry
- broadcast_exit:
- pop es
- pop ds
- ret
- preload_device: ; preload disk compression driver before
- ; processing (D)CONFIG.SYS file
- mov dx,preload_file
- mov cx,mem_current ; next available segment address
- mov es,cx
- inc cx
- mov es:DMD_ID,'D' ; control block type is 'D' (device
- mov es:DMD_PSP,cx ; driver), owner is self
- mov di,8 ; copy the name to the control block
- mov si,dx ; device filename
- preload_device10:
- lodsb ; get a character
- cmp al,'' ; have we found the '' yet ?
- jne preload_device10 ; no, go swallow another character
- movsw ! movsw ! movsw ! movsw ; copy the 8 bytes
- mov ax,es
- inc ax ; segment address of free memory
- mov dev_load_seg,ax ; destination segment for EXEC call
- mov dev_reloc_seg,ax ; relocation factor for .EXE drivers
- push ax
- push ds ! pop es
- mov bx,offset dev_epb ; ES:BX control structure
- mov ax,(MS_X_EXEC * 256)+3
- int DOS_INT
- pop es ; ES:0 -> preload driver
- jnc load_ok
- load_bad:
- jmp preload_exit
- load_ok:
- cmp es:WORD PTR .12h,2e2ch ; preload device signature
- jne load_bad
- mov preload_seg,es ; back door entry to preload driver
- cmp es:word ptr .82h,6 ; is it the old DBLSPACE driver ?
- jne load_new_dblspace
- mov preload_ver,6 ; yes, give it the old version
- load_new_dblspace:
- mov rel_unit,0 ; reset driver relative unit no.
- mov bx,offset request_hdr ; DS:BX static INIT request header
- mov ax,mem_max ; highest segment available to the
- mov ds:RH0_RESIDENT,0 ; driver
- mov ds:RH0_RESIDENT+2,ax
- mov ax,cs
- mov es,ax
- push ds
- call init_static_request ; initialise remaining fields
- mov ax,cs:preload_ver
- callf preload_entry
- pop ds
- jc preload_exit ; INIT function fails if CARRY set
- or ax,ax ; or AX != 0
- jnz preload_exit
- ;; mov ax,ds:RH0_RESIDENT ; end of resident portion (offset)
- ;; add ax,15 ; convert offset to paragraph size
- ;; mov cl,4
- ;; shr ax,cl
- ;; add ax,ds:RH0_RESIDENT+2 ; end of resident portion (segment)
- ;JS we should check that the source and destination do not overlap here!
- mov bx,04h ; find the size of the transient code
- call call_preload_entry
- sub mem_max,ax ; move the top of available memory down
- mov es,mem_max ; ES destination for relocatable code
- dec mem_max ; last free segment address
- mov bx,06h ; call driver to relocate code etc.
- call call_preload_entry
- inc ax
- mov mem_current,ax ; update base of free TPA
- mov es,preload_seg
- xor di,di ; ES:DI -> preload driver
- mov bx,offset request_hdr
- mov al,ds:RH0_NUNITS
- test al,al
- jz preload_char_dev
- add preload_drv,al ; remember how many preloaded drives
- call block_device ; setup the DPBs and other block structures
- preload_char_dev:
- mov cx,mem_current
- mov ax,preload_seg
- sub cx,ax ; CX = length of preload driver
- dec ax
- mov es,ax ; ES:0 -> "DMD" for preload driver
- mov es:DMD_LEN,cx
- inc ax
- mov es,ax
- xor di,di ; ES:DI -> "device" header
- mov ax,0FFFFh
- mov es:[di],ax
- mov es:2[di],ax
- call device_insert ; insert device into chain
- mov dx,mem_max ; top of available memory
- mov cx,mem_current ; base of available memory
- sub dx,cx
- mov ax,5500h ; AH = version, AL = all internal drives
- mov bx,02h ; mount existing container files
- call call_preload_entry
- xor bx,bx ; complete initialisation (hook
- call call_preload_entry ; interrupts etc.)
- preload_exit:
- push cs ! pop es
- ret
- func_hidevice: ; HIDEVICE=filename
- ; Look for /L:r1[,s1][;r2[,s2]] [/S] filename
- ; Look for SIZE=<hexnumber> filename
- mov himem_region,0 ; assume no region supplied
- mov himem_size,0 ; and no size
- mov di,offset region_opt ; check out /L: region option
- call compare
- jc hidevice10
- call parse_region ; get region and size
- jnc hidevice20
- xor si,si ; something wrong, give an error
- mov dx,offset bad_filename
- jmp config_error
- hidevice10:
- mov di,offset size_opt ; check out SIZE= option
- call compare
- jc hidevice20 ; if no SIZE= just try to load it
- call parse_size ; else get supplied value
- hidevice20:
- call whitespace ; we may have a '=' lurking
- hidevice30:
- lodsb ; strip off optional '='
- cmp al,'=' ; before the filename
- je hidevice30
- dec si ; it wasn't a '=' after all
- call whitespace
- mov ax,himem_size ; get size parameter
- cmp ax,6000h ; should we just load low ?
- jae func_device
- push si
- test ax,ax ; have we been given a size ?
- jne hidevice40
- call size_file ; get requirements from file size
- hidevice40:
- call himem_setup ; try and find some hi memory
- pop si
- jc func_device ; if we can't load low
- push si
- call func_device ; now try and install the device
- call himem_cleanup ; clean up our hi memory
- pop si
- jc func_device ; error loading hi, try low
- ret
- func_device: ; DEVICE=filename
- push si
- mov di,offset dev_name ; Copy the Device Filename into a
- mov byte ptr [di],0 ; local buffer and zero terminate
- call copy_file
- pop si ; Restore original SI
- jc device_error
- push es
- push si
- mov es,mem_current ; ES points at structure
- call BuildHeader
- pop si
- push si
- call FindName ; DS:SI -> leafname
- call SetName ; Fill in name info
- pop si
- pop es
- mov ax,mem_current ; Get Current Memory Base
- inc ax ; allow a para for a header
- mov dev_load_seg,ax ; Setup the Load Address and the
- mov dev_reloc_seg,ax ; relocation factor to be applied to
- ; .EXE device drivers
- mov ax,(MS_X_OPEN * 256)+0 ; open file r/o
- mov dx,offset dev_name
- int DOS_INT
- jc device_error
- mov bx,ax ; now find out how big the file is
- mov ax,(MS_X_LSEEK * 256)+2
- xor cx,cx
- xor dx,dx ; by seeking to zero bytes from end
- int DOS_INT
- jc device_error
- xchg ax,cx ; save lo byte of length
- mov ah,MS_X_CLOSE ; close this file
- int DOS_INT
- jc device_error
- mov ax,cx ; DX:AX file length
- or cx,dx ; do we have a zero length file
- jz device_error ; if so stop now
- mov cl,4
- shr ax,cl ; convert file size to para
- mov cl,12
- shl dx,cl ; ignore > 1 MByte portion
- or dx,ax ; dx = file size in para
- inc dx ; one for rounding error
- add dx,mem_current ; top of area needed for the load
- cmp dx,mem_max ; will file fit (really HIDEVICE check)
- jb func_device10 ; no, stop now
- ret
- device_error:
- mov error_level,ax ; save error code
- mov al,0
- mov si,offset dev_name
- mov dx,offset bad_filename
- jmp config_error
- func_device10:
- mov ax,(MS_X_EXEC * 256)+3 ; Use the Load Overlay function to
- mov bx,offset dev_epb ; Read in and Relocate the Device
- mov dx,offset dev_name ; driver
- int DOS_INT ;
- jc device_error
- ; mov dosVersion,ax ; set version number
- push es
- mov ax,mem_current ; Get Current Memory Base
- push ax
- inc ax ; skip the header
- xor di,di ; Address of the first device header
- mov es,ax ; in the device chain
- if ADDDRV
- test es:DH_ATTRIB[di],DA_CHARDEV
- jnz f_dev30 ;Character device driver ?
- ; Can't install block device drivers so output error message and exit.
- pop es
- pop es
- xor al,al
- mov si,offset dev_name
- mov dx,offset err_block_device
- jmp config_error
- f_dev30:
- endif
- call PreloadFixup ; fiddle things for preload
- if DOS5
- call ProtmanFixup ; fiddle int 12 memory for PROTMAN$
- endif
- call device_init ; initialise the device drivers
- if DOS5
- call ProtmanCleanup ; restore int 12 memory after PROTMAN$
- endif
- mov error_level,ax ; save error code
- pop es ; by old EMM386.SYS
- mov ax,mem_current
- mov es:DMD_LEN,ax ; save memory field
- mov ax,es
- inc ax
- sub es:DMD_LEN,ax
- pop es
- call PreloadCleanup ; cleanup after ourselves
- ret
- BuildHeader:
- ;-----------
- ; On Entry:
- ; ES:0 -> header
- ; On Exit:
- ; None
- ;
- xor di,di
- mov al,'D'
- stosb ; ID_FIELD
- mov ax,es
- inc ax
- stosw ; OWNER_FIELD
- xor ax,ax
- stosb ! stosw ! stosw ; zero rest up to name
- ret
- FindName:
- ;--------
- ; On Entry:
- ; DS:SI -> pathname of file
- ; On Exit:
- ; DS:SI -> final leaf name of file
- ; CX = length of leaf name
- ;
- mov cx,si ; remember start of leaf
- FindName10:
- lodsb
- cmp al,' ' ; end of the name ?
- jbe FindName30
- call dbcs_lead ; is it a double byte pair ?
- jne FindName20
- lodsb ; include the second byte
- jmps FindName10
- FindName20:
- cmp al,'' ; is it a seperator ?
- je FindName
- cmp al,'/'
- je FindName
- jmps FindName10
- FindName30:
- xchg cx,si ; SI -> start of leaf name
- sub cx,si
- dec cx ; CX = length
- ret
- SetName:
- ;-------
- ; On Entry:
- ; DS:SI -> leaf name to update
- ; ES = DMD to update
- ; On Exit:
- ; CX/SI preserved
- ;
- push si
- mov di,offset DMD_NAME ; point at the owners name field
- SetName10:
- lodsb
- cmp al,' ' ; end of the name ?
- jbe SetName30
- call dbcs_lead ; is it a double byte pair ?
- jne SetName20
- stosb ; copy 1st byte of pair
- cmp di,(offset DMD_NAME)+DMD_NAME_LEN
- jae SetName30 ; don't overflow if name too long
- movsb ; and the second
- jmps SetName10
- SetName20:
- stosb
- cmp al,'.' ; discard all following '.'
- je SetName30
- cmp di,(offset DMD_NAME)+DMD_NAME_LEN
- jb SetName10 ; don't overflow if name too long
- SetName30:
- dec di
- xor ax,ax
- SetName40:
- stosb ; zero the '.'
- cmp di,(offset DMD_NAME)+DMD_NAME_LEN
- jb SetName40 ; zero the rest of the name
- SetName50:
- pop si
- ret
- if DOS5
- ROS_MEMORY equ .413h ; main memory on KB
- protmanName db 'PROTMAN$'
- protmanAdjust dw 0
- ProtmanFixup:
- ;------------
- ; On Entry:
- ; ES:DI -> device driver header
- ; On Exit:
- ; All regs preserved
- ;
- ; fiddle int 12 memory for PROTMAN$
- ;
- push cx
- push si
- push di
- mov cs:protmanAdjust,0 ; assume it's not protman
- mov si,offset protmanName
- lea di,DH_NAME[di] ; ES:DI -> device driver name
- mov cx,8/2
- repe cmpsw ; does the name match ?
- jne ProtmanFixup10
- mov si,mem_max ; SI = top of memory in para
- push ds
- ; xor cx,cx
- mov ds,cx
- mov cl,10-4
- shr si,cl ; convert para to KBytes
- mov cx,ds:ROS_MEMORY ; CX = existing top of memory
- sub cx,si ; CX = amount to hide
- sub ds:ROS_MEMORY,cx ; hide it
- pop ds
- mov cs:protmanAdjust,cx ; remember how much we hid
- ProtmanFixup10:
- pop di
- pop si
- pop cx
- ret
- ProtmanCleanup:
- ;--------------
- ; On Entry:
- ; None
- ; On Exit:
- ; All regs preserved
- ; restore int 12 memory after PROTMAN$
- ;
- push ds
- push ax
- xor ax,ax
- mov ds,ax
- mov ax,cs:protmanAdjust ; normally zero..
- add ds:ROS_MEMORY,ax
- pop ax
- pop ds
- ret
- endif
- ;
- ; The syntax currently supported is "COUNTRY=NNN,[YYY],[FILENAME]"
- ; where:-
- ; NNN is a valid country code based on
- ; the International Dialing Code
- ;
- ; YYY is the default CODEPAGE
- ;
- ; FILENAME is the location and name of the COUNTRY.SYS
- ; file containing the extended country info.
- ;
- ;
- if not ADDDRV
- func_country: ; COUNTRY=nnn,[yyy],[filename]
- call atoi ; ax = country code
- jc f_ctry50 ; check for error
- mov country_code,ax ; save the Country Code
- call separator ; look for ','
- jc f_ctry20
- call atoi ; Get the Code Page
- jc f_ctry10 ; invalid or non existent code page
- mov code_page,ax ; save default Code Page
- f_ctry10:
- call separator ; look for ','
- jc f_ctry20 ; copy the supplied pathname
- les bx,drdos_ptr ; Get the internal data area
- mov di,es:DRDOS_COUNTRY_FILE[bx]
- ; ES:DI -> pcmode buffer for name
- call copy_file
- push cs ; restore ES
- pop es
- f_ctry20:
- call nls_hook ; install our lang support
- mov bx, country_code ; bx = country code
- mov ah, MS_S_COUNTRY
- mov al, 0FFh ; 16 bit country code
- mov dx, 0FFFFh ; set country code subfunction
- int DOS_INT
- jc f_ctry40 ; check for error
- mov bx, code_page ; bx = code page
- or bx,bx
- jz f_ctry30 ; No Code Page Set leave as 437
- mov ax, MS_X_SETCP ; set codepage subfunction
- int DOS_INT ; to set Current CodePage
- f_ctry30:
- jmp nls_unhook ; remove our lang support
- ; ret
- f_ctry40:
- call nls_unhook ; remove our lang support
- f_ctry50:
- ; Bad or non-existant number in command tail. Display error message.
- xor si,si
- mov dx, offset bad_country
- jmp config_error
- func_shell: ; SHELL=filename
- mov di,offset shell ; Copy the New Command Name
- call copy_file ; into the BIOSINIT buffer
- mov al,0 ! stosb ; Terminate the Environment Correctly
- jc shell_error
- mov di,offset shell_cline+1 ; Now copy the default command
- mov al,' ' ! stosb ; into place
- mov cx,0 ;
- f_sh10:
- lodsb ! stosb ; Copy the next Character
- inc cx ; Increment the count
- cmp al,CR ; Was this the end of string Char
- jnz f_sh10 ; No so Repeat
- mov shell_cline,cl ; Save Command Length
- ret
- shell_error:
- mov al,CR
- mov dx,offset bad_shell
- jmp config_error
- func_lastdrive: ; LASTDRIVE=d:
- call atoi ; are we supplying a decimal number?
- jc f_lastdrive10
- cmp al,32 ; is it in range ?
- jbe f_lastdrive20
- lastdrv_error:
- xor si,si ; Do not display Failing String
- mov dx,offset bad_lastdrive ; and display an error message
- jmp config_error
- f_lastdrive10:
- lodsb ; Get the Option Character
- call toupper ; and convert to Upper Case
- sub al, 'A' ; al should be between 0..25
- jc lastdrv_error
- cmp al, 'Z'-'A'
- ja lastdrv_error
- inc al ; al = number of drives in system
- f_lastdrive20:
- mov last_drv,al ; remember for later
- ret
- func_break: ; BREAK=ON/OFF
- call check_onoff ; Check for ON or OFF
- mov dl,al ; Get value found
- jnc set_break ; and check for error
- xor si,si ; Do not display Failing String
- mov dx, offset bad_break ; Bad or non-existant ON/OFF string
- jmp config_error ; in command tail. Display error message.
- set_break:
- mov ah,MS_S_BREAK ; Set the Default Break Flag
- mov al,01 ; Set Sub-Function
- int DOS_INT ; Execute function and return
- ret
- func_numlock: ; NUMLOCK=ON/OFF
- call check_onoff ; Check for ON or OFF
- jc numlock20
- push ds
- xor bx,bx
- mov ds,bx
- mov bx,417h ; DS:BX -> keyboard control
- or ds:byte ptr [bx],20h ; set numlock bit
- test al,al ; was it numlock on ?
- jnz numlock10 ; if not, better clear the bit
- and ds:byte ptr [bx],not 20h
- numlock10:
- pop ds
- mov ah,MS_C_STAT ; get console status
- int DOS_INT ; (usually int 16 update NUMLOCK state)
- numlock20:
- ret
- func_hibuffers: ; HIBUFFERS=nn[,nn]
- or buffersIn,BUFFERS_IN_HMA
- ; jmp func_buffers
- func_buffers: ; BUFFERS=nn[,nn]
- call atoi ; AX = # of buffers
- jc buffer_error ; check for error
- cmp ax,MIN_NUM_BUFFS ; check if less than minimum
- jae func_buf1
- mov ax,3 ; force to use minimum if less
- func_buf1:
- cmp ax,MAX_NUM_BUFFS ; check if more than maximum
- jbe func_buf2
- mov ax,MAX_NUM_BUFFS ; force to use maximum if more
- func_buf2:
- mov init_buf,al ; update if we want more
- call separator ; look for ','
- jc func_buf4
- call atoi ; Get read-ahead buffer size
- jc buffer_error
- cmp ax,MIN_READ_AHEAD
- jb buffer_error
- cmp ax,MAX_READ_AHEAD
- ja buffer_error
- mov num_read_ahead_buf,al
- func_buf4:
- ret
- buffer_error:
- xor si,si ; Do not display Failing String
- mov dx, offset bad_buffers
- jmp config_error
- func_files: ; FILES=nn
- call atoi ; AX = # of files
- jc files_error ; check for error
- cmp ax,MIN_NUM_FILES ; check if less than minimum
- jae func_fil1
- mov ax,MIN_NUM_FILES ; force to use minimum if less
- func_fil1:
- cmp ax,MAX_NUM_FILES ; check if more than maximum
- jbe func_fil2
- mov ax,MAX_NUM_FILES ; force to use maximum if more
- func_fil2:
- mov num_files,ax ; update the number required
- ret
- files_error:
- xor si,si ; Do not display Failing String
- mov dx, offset bad_files
- jmp config_error
- func_fcbs: ; FCBS=nn
- call atoi ; AX = # of files
- jc fcbs_error ; check for error
- cmp ax,MIN_NUM_FCBS ; check if less than minimum
- jae func_fcb1
- mov ax,MIN_NUM_FCBS ; force to use minimum if less
- func_fcb1:
- cmp ax,MAX_NUM_FCBS ; check if more than maximum
- jbe func_fcb2
- mov ax,MAX_NUM_FCBS ; force to use maximum if more
- func_fcb2:
- mov num_fcbs,ax ; update number of FCB's
- ret
- fcbs_error:
- xor si,si ; Do not display Failing String
- mov dx, offset bad_fcbs
- jmp config_error
- endif ;not ADDDRV
- func_common: ; [COMMON]
- func_remark: ; REM Comment field
- ret
- func_switches: ; SWITCHES=...
- ; /N = disable F5/F8 feature
- ; /W = zap wina20.386 name
- ; /K = disable enhanced keyboard support
- ; /F = skip statup delay
- call whitespace ; skip all spaces
- lodsw ; get '/x'
- cmp al,CR ; check for end-of-line
- je func_switches10
- cmp ah,CR ; check for end-of-line
- je func_switches10
- cmp ax,'N/'
- jne func_switches
- mov boot_options,0 ; disable boot options
- func_switches10:
- ret
- func_stacks: ; STACKS=number,size
- ;-----------
- call atoi ; ax = number of stacks
- jc func_stacks20 ; check for error
- test ax,ax ; special case ? (disabled)
- jz func_stacks10
- cmp ax,MIN_NUM_STACKS ; range check for a sensible value
- jb func_stacks20
- cmp ax,MAX_NUM_STACKS
- ja func_stacks20
- func_stacks10:
- mov num_stacks,ax
- call separator ; look for ','
- jc func_stacks20
- call atoi ; get size of a stack frame
- jc func_stacks20
- cmp ax,MIN_SIZE_STACK ; range check it
- jb func_stacks20
- cmp ax,MAX_SIZE_STACK
- ja func_stacks20
- mov stack_size,ax
- func_stacks20:
- ret
- if not ADDDRV
- func_deblock: ; DEBLOCK=xxxx
- ;------------
- call atohex ; read hex number into DX:AX
- jc func_deblock10
- test dx,dx
- jnz func_deblock10
- mov DeblockSetByUser,TRUE ; the user has supplied a setting
- push ds
- mov ds,bios_seg
- mov DeblockSeg,ax ; save deblocking segment
- pop ds
- func_deblock10:
- ret
- func_fastopen: ; FASTOPEN=nn
- call atoi ; AX = # of files to cache
- jc fopen_error ; check for error
- test ax,ax ; disable fast open?
- jz func_fopen2 ; yes, allow to set to 0000
- cmp ax,MIN_NUM_FOPEN ; check if less than minimum
- jae func_fopen1
- mov ax,MIN_NUM_FOPEN ; force to use minimum if less
- func_fopen1:
- cmp ax,MAX_NUM_FOPEN ; check if more than maximum
- jbe func_fopen2
- mov ax,MAX_NUM_FOPEN ; force to use maximum if more
- func_fopen2:
- mov num_fopen,ax ; update if we want more
- func_fopen3:
- ret
- fopen_error:
- xor si,si ; Do not display Failing String
- mov dx, offset bad_fopen
- jmp config_error
- func_drivparm: ; DRIVPARM = /d:nn [/c] [/f:ff] [h:hh] [/n] [/s:ss] [/t:tt]
- ;-------------
- ; This function specifies the drive parameters for a device
- ; and overrides the defaults assumed by the device driver.
- mov drivp_drv,0FFh ; invalid drive
- call get_switch ; get next switch
- cmp al,'d' ; first option must be /d:dd
- jne drivparm_error
- call get_number ; get numeric parameter
- mov drivp_drv,al
- mov drivp_chg,FALSE
- mov drivp_prm,FALSE
- mov drivp_trk,80 ; assume 80 tracks
- mov bl,drivp_drv ; get drive to set up
- cmp bl,'Z'-'A'
- ja drivparm_error
- inc bl
- mov ioctl_pb,0 ; return defaults
- mov ax,440Dh ; generic IOCTL
- mov cx,0860h ; get device parameters
- mov dx,offset ioctl_func
- int DOS_INT
- jc drivparm_error ; skip if we can't get parameters
- mov drivp_ff,2 ; assume 720K 3.5" drive
- call set_form_factor ; set defaults for form factor
- call get_switch ; get next switch
- cmp al,'c' ; is it /c (change line available)
- jne drivparm1
- mov drivp_chg,TRUE ; disk change line available
- call get_switch ; get next switch
- drivparm1:
- cmp al,'f' ; form factor specification?
- jne drivparm2
- call get_number ; get numeric parameter
- mov drivp_ff,al ; set form factor
- call set_form_factor ; set defaults for form factor
- jmps drivparm_loop ; get more parameters
- drivparm_error:
- xor si,si
- mov dx,offset bad_drivparm
- jmp config_error
- drivparm_loop:
- call get_switch ; get next switch
- drivparm2:
- cmp al,'h' ; specify number of heads
- jne drivparm3
- call get_number ; get numeric parameter
- cmp ax,99
- ja drivparm_error
- mov drivp_heads,ax ; set # of heads
- jmps drivparm_loop
- drivparm3:
- cmp al,'n'
- jne drivparm4
- mov drivp_prm,TRUE ; non-removable media
- jmps drivparm_loop
- drivparm4:
- cmp al,'s'
- jne drivparm5
- call get_number ; get numeric parameter
- cmp ax,63 ; range check sector per track
- ja drivparm_error
- mov drivp_spt,ax ; set # of sectors/track
- jmps drivparm_loop
- drivparm5:
- cmp al,'t'
- jne drivparm_error
- call get_number ; get numeric parameter
- cmp ax,999
- ja drivparm_error
- mov drivp_trk,ax ; set # of sectors/track
- jmps drivparm_loop
- drivparm_done: ; now set drive parameters
- mov bl,drivp_drv
- cmp bl,'Z'-'A'
- ja drivparm_error
- mov ioctl_func,0000$0100b ; normal track layout assumed,
- ; set device BPB for drive
- mov al,drivp_ff ; get form factor
- mov ioctl_type,al
- sub ax,ax ; assume removable, no disk change
- cmp drivp_prm,FALSE
- je drivp_d1
- or ax,1 ; drive is permanent media
- drivp_d1:
- cmp drivp_chg,FALSE
- je drivp_d2
- or ax,2 ; drive supports disk change line
- drivp_d2:
- mov ioctl_attrib,ax ; set drive attributes
- mov ax,drivp_trk ; set # of cylinders
- mov ioctl_tracks,ax
- mov ioctl_mtype,0 ; assume standard type
- mov ax,drivp_spt ; get sectors/track
- mov di,offset ioctl_layout
- push ds ! pop es ; ES:DI -> layout table
- stosw ; set # of sectors
- xchg ax,cx ; CX = # of sectors
- mov ax,1 ; start with sector 1
- drivp_d3:
- stosw ; set next sector #
- inc ax ; move to next sector
- loop drivp_d3 ; repeat for all sectors
- mov ax,drivp_heads
- mul drivp_spt
- mov dx,drivp_trk
- mul dx ; AX/DX = # of sectors/disk
- mov di,offset ioctl_bpb
- mov 8[di],ax ; set sectors per disk
- test dx,dx
- jz drivp_d4
- mov word ptr 8[di],0 ; indicate large partition
- mov 21[di],ax ; set disk size in sectors
- mov 23[di],dx
- drivp_d4:
- mov bl,drivp_drv
- inc bl
- mov ax,440Dh
- mov cx,0840h ; set drive parameters
- mov dx,offset ioctl_func
- int DOS_INT ; tell the BIOS, ignore errors
- ret
- get_switch: ; get next command line switch
- call whitespace ; skip all spaces & tabs
- lodsb ; get next character
- pop dx ; get return address
- cmp al,'/' ; did we get a switch?
- je get_swt9 ; yes, return the character
- jmp drivparm_done
- get_swt9:
- lodsb
- or al,('a' xor 'A') ; return upper-cased character
- jmp dx
- get_number:
- ; entry: SI -> next character (must be ':')
- lodsb ; get next character
- cmp al,':' ; must be colon
- jne get_num_err ; return error if not
- call atoi ; get numeric value
- jc get_num_err ; must be number
- ret ; AX = number
- get_num_err:
- pop dx
- jmp drivparm_error ; reject this command
- set_form_factor:
- mov bl,drivp_ff
- cmp bl,7
- ja set_form9
- mov bh,0
- shl bx,1
- push si ! push es
- mov si,ff_table[bx] ; SI -> default media BPB
- push ds ! pop es
- mov di,offset ioctl_bpb ; ES:DI -> local BPB
- mov cx,21 ; copy initialized portion
- rep movsb
- pop es ! pop si
- ret
- set_form9:
- jmp drivparm_error
- ;
- ; This function modifies the History buffer support provided by
- ; DR DOS the defaults are History OFF, 512 byte buffers,
- ; Insert ON, Search OFF, Matching OFF.
- ;
- func_history: ; HISTORY = ON|OFF[,NNNN[,ON|OFF[,ON|OFF[,ON|OFF]]]]
- ;------------
- mov history_flg,0 ; start with it all off
- call check_onoff ; Check for ON|OFF Switch
- jc f_hist_err
- test al,al ! jz f_hist_exit ; if OFF forget the rest
- or history_flg,RLF_ENHANCED+RLF_INS
- call separator ; look for ','
- jc f_hist_exit ; Buffer Size not Specified
- call atoi ; Get the Buffer Size
- jc f_hist_err ; Invalid on no existant size
- cmp ax,128 ! jb f_hist_err ; Buffer Size to Small
- cmp ax,4096 ! ja f_hist_err ; Buffer Size to Large
- mov history_size,ax ; Save History Buffer Size
- call separator ; look for ','
- jc f_hist_exit ; Insert mode not Specified
- call check_onoff ; Check for ON|OFF Switch
- jc f_hist_err
- test al,al ! jnz func_hist10
- and history_flg,not RLF_INS ; Insert state OFF
- func_hist10:
- call separator ; look for ','
- jc f_hist_exit ; Search mode not Specified
- call check_onoff ; Check for ON|OFF Switch
- jc f_hist_err
- test al,al ! jz func_hist20
- or history_flg,RLF_SEARCH ; Search state ON
- func_hist20:
- call separator ; look for ','
- jc f_hist_exit ; Match mode not Specified
- call check_onoff ; Check for ON|OFF Switch
- jc f_hist_err
- test al,al ! jz func_hist30
- or history_flg,RLF_MATCH ; Match state ON
- func_hist30:
- f_hist_exit:
- ret
- f_hist_err:
- xor si,si ; Do not display Failing String
- mov dx, offset bad_history ; Bad or non-existant ON/OFF string
- jmp config_error ; in command tail. Display error message.
- ;
- ; HIINSTALL filename [Command Line Parameters]
- ;
- ; As INSTALL, but uses high memory if possible
- ;
- func_hiinstall:
- mov ax,5802h
- int DOS_INT ; get upper memory link
- cbw
- push ax ; save upper memory link
- mov ax,5800h
- int DOS_INT ; get alloc strategy
- push ax ; save alloc strategy
- mov ax,5803h
- mov bx,1 ; set upper memory link
- int DOS_INT ; to 1
- mov ax,5801h
- mov bx,80h ; set alloc strategy to lowest-upper
- int DOS_INT ; if available
- call func_install ; try and install it
- mov ax,5801h
- pop bx ; set alloc strategy
- int DOS_INT ; to original value
- mov ax,5803h
- pop bx ; set upper memory link
- int DOS_INT ; to original value
- ret
- ;
- ; INSTALL filename [Command Line Parameters]
- ;
- ; INSTALL will load and execute "FILENAME" with the optional command
- ; line parameters and continue processing the DCONFIG.SYS file when
- ; the application terminates.
- ;
- ; Entry
- ; ds:si -> first character of CR terminated filename and option string.
- ; Exit
- ; none
- ;
- ; WARNING -
- ; This code make certain assumptions about memory layout.
- ; If memory gets fragmented then it all starts falling apart.
- ;
- func_install:
- ;------------
- push ds ! push es
- ;
- ; Shrink the previously allocated memory block to MEM_CURRENT
- ; in preparation of the INSTALL EXEC function.
- ;
- mov es,mem_current_base ; ES: Base Allocated Memory
- mov bx,mem_current ; Get the currently allocated memory
- sub bx,mem_current_base ; and subtract mem_current_base to
- mov ah,MS_M_FREE ; give the number of paragraphs used
- jz func_i10 ; if none, free it all up
- mov ah,MS_M_SETBLOCK ; else modify block accordingly
- func_i10:
- int DOS_INT
- ; Now to protect the CONFIG code in high memory
- mov ah,MS_M_ALLOC ; we now try to find base of TPA
- mov bx,0ffffh ; ASSUME it is the biggest bit
- int 21h ; of free memory about
- mov ah,MS_M_ALLOC ; give it to me please
- int 21h ; ax:0 -> exec memory
- push bx ; we have allocated BX para's
- mov es,ax ; ES -> exec memory
- mov bx,init_dseg ; we want to protect BX:0 and above
- dec bx ; allow for DMD
- sub bx,ax ; we can spare this many paras
- mov ah,MS_M_SETBLOCK ; for the exec so grow the
- int 21h ; block accordingly
- pop ax ; AX = total, BX = amount for install
- sub ax,bx ; AX = amount we just freed
- dec ax ; allow for DMD
- xchg ax,bx ; BX = freed portion (the Init code)
- mov ah,MS_M_ALLOC ; ASSUME an allocation of this size
- int 21h ; will contain SYSDAT/CONFIG
- push ax ; save seg so we can free mem later
- mov ah, MS_M_FREE ; now free up the bit we prepared
- int 21h ; earlier so exec has something
- push ds ! pop es ; to work in
- mov di,offset dev_name ; Copy the filename into a local
- call copy_file ; buffer
- ; Calculate the command line length
- mov di,si ; by scanning the command line for
- mov al,CR ; the terminating CR
- mov cx,128
- repnz scasb
- dec di
- mov ax,di
- sub ax,si
- dec si ; Point to the byte before the
- mov byte ptr [si],al ; command line string and update
- ; the count
- mov ax,offset envstart ; env buffer is para aligned
- mov cl,4
- shr ax,cl ; convert offset to paras
- mov cx,ds
- add ax,cx ; segment of env variables
- mov exec_envseg,ax
- mov exec_lineoff,si
- mov exec_lineseg,ds
- mov exec_fcb1off,0FFFEh ; Force PCMODE to generate
- mov exec_fcb2off,0FFFEh ; correct FCB References
- mov system_ss,ss
- mov system_sp,sp
- mov dx,offset dev_name ; Get ASCIIZ Command
- mov bx,offset exec_envseg ; and Parameter Block Offset
- mov ax,4B00h ; Load and Execute Program with Handle
- int DOS_INT ; EXEC the application
- cli ; Swap back to the original stack
- mov ss,cs:system_ss ; again with interrupts disabled
- mov sp,cs:system_sp
- sti
- mov ah,MS_X_WAIT ; if all went well return the
- jnc func_i20 ; termination code
- mov ah,MS_F_ERROR ; if we had an error from EXEC
- xor bx,bx ; get extended error
- func_i20:
- int DOS_INT ; retrieve error value
- mov cs:error_level,ax ; and save for testing
- pop es ; recover the seg we protected
- mov ah, MS_M_FREE ; so we can free that memory up
- int 21h
- mov ah,MS_M_ALLOC ; try and allocate as much as possible
- mov bx, 0FFFFh ; ASSUME this will cover CONFIG
- int 21h ; bx = No. of paras available
- mov ah, MS_M_ALLOC ; give me bx paras please
- int 21h ; ax:0 -> my memory
- pop es ! pop ds
- mov mem_current_base,ax ; save memory base
- mov mem_current,ax ; for future allocations
- ret
- func_hidos: ; HIDOS ON/OFF
- call check_onoff ; Check for ON or OFF
- jc f_hidos10 ; Return on error
- mov hidos,al ; update hidos flag
- f_hidos10:
- ret
- func_dos: ; DOS=HIGH - relocate BIOS/BDOS/Buffer etc to FFFF
- call separator ; Deblank Command
- mov di,offset high_opt ; es:di -> "HIGH"
- call compare ; do we have an "HIGH"?
- jc func_dos10
- push si
- call func_dos_high ; execute HIGH
- pop si
- jmps func_dos
- func_dos10:
- mov di,offset low_opt ; es:di -> "LOW"
- call compare
- jc func_dos20
- push si
- call func_dos_low ; execute LOW
- pop si
- jmps func_dos
- func_dos20:
- mov di,offset umb_opt ; es:di -> "UMB"
- call compare
- jc func_dos30
- push si
- call func_dos_umb ; execute UMB
- pop si
- jmps func_dos
- func_dos30:
- mov di,offset noumb_opt ; es:di -> "NOUMB"
- call compare
- jc func_dos40
- push si
- call func_dos_noumb ; execute NOUMB
- pop si
- jmps func_dos
- func_dos40:
- ret
- func_dos_high:
- ;-------------
- ; Move DOS into the HMA and allocate buffers etc. high too.
- ;
- mov dos_target_seg,0FFFFh
- mov bios_target_seg,0FFFFh
- mov hidos,TRUE ; update hidos flag to be ON
- or buffersIn,BUFFERS_IN_HMA; buffers at seg FFFF too
- ret
- func_dos_low:
- ;------------
- ; force all allocation to be low
- ;
- mov dos_target_seg,0
- mov bios_target_seg,0
- mov hidos,FALSE ; system allocation from low memory
- mov buffersIn,0 ; buffers from low memory
- ret
- func_dos_umb:
- ;------------
- ; allocate Upper Memory Blocks and link them to the DMD chain
- ;
- mov hidos,TRUE ; update hidos flag to be ON
- call initialise_dmd_upper ; build initial upper memory DMD
- jc func_dos_umb30
- func_dos_umb10:
- call alloc_xms_umb ; allocate XMS upper memory
- jc func_dos_umb20
- call add_dmd_upper ; add to upper memory DMD's
- jmps func_dos_umb10 ; go around again
- func_dos_umb20:
- call remove_last_dmd ; get rid of useless last DMD
- func_dos_umb30:
- mov ax,(MS_M_STRATEGY*256)+3
- mov bx,1 ; link in upper memory region
- int 21h
- ret
- func_dos_noumb:
- ;--------------
- ; Unlink Upper Memory blocks from the DMD chain
- ;
- mov ax,(MS_M_STRATEGY*256)+3
- xor bx,bx ; unlink upper memory region
- int 21h
- ret
- alloc_xms_umb:
- ; On Entry:
- ; None
- ; On Exit:
- ; CY set is no upper memory available
- ; else
- ; BX = para base address
- ; DX = para size
- ;
- ; Try to allocate the largest possible block of XMS memory
- ; so we can link it to the upper memory chain
- ;
- push es
- mov ax,4300h ; check for XMS installation
- int 2fh
- cmp al,80h
- jne alloc_xms10
- mov ax,4310h ; get address of XMS driver
- int 2fh
- mov word ptr xms_driver,bx
- mov word ptr xms_driver+2,es
- mov ah,10h ; allocate upper memory block
- mov dx,0FFFFh ; DX set to find largest block
- callf xms_driver
- cmp dx,3 ; we need at least 3 para's
- jb alloc_xms10 ; before we contruct a DMD
- mov ah,10h ; now allocate largest block
- callf xms_driver
- cmp ax,1 ; did we succeed ?
- je alloc_xms20
- alloc_xms10:
- stc ; return CY set indicating failure
- alloc_xms20:
- pop es
- ret
- xms_driver rd 0
- dw 0,0
- initialise_dmd_upper:
- ; On Entry:
- ; None
- ; On Exit:
- ; CY set if chain already exists
- ; (BX/DX preserved)
- ;
- ; build initial upper memory DMD
- ; we rely on the fact the last para in memory is unused
- ; (but BIOSINIT makes sure that is true)
- ;
- push es
- push bx
- push dx
- if DOS5
- les bx,func52_ptr ; ES:BX -> list of lists
- cmp es:F52_DMD_UPPER[bx],0FFFFh
- else
- les bx,drdos_ptr
- cmp es:DRDOS_DMD_UPPER[bx],0
- les bx,funv52_ptr ; ES:BX -> list of lists
- endif
- stc ; assume error return required
- jne initialise_dmd_upper30 ; bail out if chain already established
- mov es,es:F52_DMDROOT ; ES -> 1st DMD
- initialise_dmd_upper10:
- cmp es:DMD_ID,IDZ ; end of DMD chain ?
- je initialise_dmd_upper20
- cmp es:DMD_ID,IDM ; do we have any more DMD's ?
- stc
- jne initialise_dmd_upper30 ; woops, chain must be bad
- mov ax,es ; better point to it
- inc ax
- add ax,es:DMD_LEN ; AX:0 -> next DMD
- mov es,ax
- jmps initialise_dmd_upper10
- initialise_dmd_upper20:
- mov ax,es
- add ax,es:DMD_LEN ; AX:0 -> will be upper memory chain
- cmp ax,0A000h ; if the DMD chain is already into
- cmc ; upper memory, lets make sure we
- jb initialise_dmd_upper30 ; stop before we fall apart
- mov es:DMD_ID,IDM ; no longer the last entry
- dec es:DMD_LEN ; shorten last DMD to make room
- mov es,ax ; point to new DMD
- mov es:DMD_ID,IDZ ; there is only one entry in the chain
- mov es:DMD_PSP,8 ; its' owned by "system"
- xchg ax,cx ; CX = DMD
- mov ax,0FFFFh
- sub ax,cx ; it's this big
- mov es:DMD_LEN,ax
- if DOS5
- les bx,func52_ptr
- mov es:F52_DMD_UPPER[bx],cx
- else
- les bx,drdos_ptr
- mov es:DRDOS_DMD_UPPER[bx],cx
- endif
- clc
- initialise_dmd_upper30:
- pop dx
- pop bx
- pop es
- ret
- remove_last_dmd:
- ; On Entry:
- ; None
- ; On Exit:
- ; None
- ;
- ; We have build an upper memory DMD chain, but we have left an extra
- ; DMD around covering the ROMs at the top of memory. Remove it if
- ; it's not required.
- ;
- push es
- les bx,func52_ptr ; ES:BX -> list of lists
- mov es,es:F52_DMDROOT[bx] ; ES -> 1st DMD
- remove_last_dmd10:
- cmp es:DMD_ID,IDM ; do we have any more DMD's ?
- jne remove_last_dmd20 ; bail out if we don't
- mov ax,es ; remember previous DMD
- mov dx,es
- inc dx
- add dx,es:DMD_LEN ; DX:0 -> next DMD
- mov es,dx
- cmp es:DMD_ID,IDZ ; end of DMD chain ?
- jne remove_last_dmd10
- cmp es:DMD_PSP,8 ; is it owned by "system" ?
- jne remove_last_dmd20 ; if so we can ditch this entry
- mov es,ax ; ES = next to last DMD
- mov es:DMD_ID,IDZ ; new end of chain
- inc es:DMD_LEN ; include last para
- if DOS5
- les bx,func52_ptr ; ES:BX -> list of lists
- cmp dx,es:F52_DMD_UPPER[bx]
- jne remove_last_dmd20 ; remove upper memory link if none left
- mov es:F52_DMD_UPPER[bx],0FFFFh
- else
- les bx,drdos_ptr
- cmp dx,es:DRDOS_DMD_UPPER[bx]
- jne remove_last_dmd20 ; remove upper memory link if none left
- mov es:DRDOS_DMD_UPPER[bx],0
- endif
- remove_last_dmd20:
- pop es
- ret
- add_dmd_upper:
- ; On Entry:
- ; BX = base address of DMD
- ; DX = size of DMD
- ; On Exit:
- ; None
- ;
- ; Add this block into the upper memory chain.
- ; To do this we find the DMD containing the block and link it into place
- ;
- push es
- push bx ; save base address
- les bx,func52_ptr ; ES:BX -> list of lists
- mov ax,es:F52_DMDROOT[bx] ; AX -> 1st DMD
- pop bx ; 1st DMD is always below XMS
- cmp ax,bx ; memory, so bomb out if not
- jae add_dmd_upper40 ; as our DMD's must be corrupt
- add_dmd_upper10:
- mov es,ax
- add ax,es:DMD_LEN ; AX:0 -> end of this block
- cmp ax,bx ; is the next block above us ?
- ja add_dmd_upper20 ; if not try the next block
- inc ax ; AX:0 -> next DMD
- cmp es:DMD_ID,IDM ; do we have any more DMD's ?
- je add_dmd_upper10 ; we should have......
- jmps add_dmd_upper40 ; stop, DMD's are screwed up
- add_dmd_upper20:
- ; We have found the block we wish to insert a new free block into
- cmp es:DMD_PSP,8 ; it must be owned by "system"
- jne add_dmd_upper40
- ; Shorten existing DMD to point to new block
- mov ax,bx ; work out how far to new DMD
- mov cx,es
- sub ax,cx ; it's this many para's
- dec ax ; forget the header
- xchg ax,es:DMD_LEN ; set new length
- ; now we need to work out how much is left above the new DMD
- sub ax,dx ; subtract length of new block
- sub ax,es:DMD_LEN ; subtract the portion below
- ; Create DMD covering new block
- mov cl,IDM ; create a new entry
- xchg cl,es:DMD_ID ; CL = existing ID (M/Z)
- mov es,bx ; ES -> base of new DMD
- mov es:DMD_ID,IDM ; it's a link field
- mov es:DMD_PSP,0 ; it's free
- dec dx ; forget the header
- add bx,dx ; last para is here
- dec dx ; forget the next link
- mov es:DMD_LEN,dx ; it's this long
- ; Build a new DMD at the top if the new block for anything above it
- mov es,bx
- mov es:DMD_ID,cl ; inherit the ID field
- mov es:DMD_LEN,ax ; and it's this long
- test ax,ax ; if zero length then
- jz add_dmd_upper30 ; it's free
- mov ax,8 ; else it's system
- add_dmd_upper30:
- mov es:DMD_PSP,ax ; set owner
- add_dmd_upper40:
- pop es
- ret
- func_set: ; SET envar=string
- call whitespace ; deblank the command
- mov di,offset envstart-1 ; point to our environment area
- func_set5:
- inc di
- cmp es:word ptr [di],0 ; are we at the end yet
- jne func_set5
- cmp di,offset envstart ; if nothing is there yet start
- je func_set10 ; at the NUL, else skip the NUL
- inc di ; to leave a seperator
- func_set10:
- lodsb ; get a character
- cmp al,CR ; end of the line yet ?
- je func_set20
- cmp di,offset envend ; have we room ?
- jae func_set30 ; bail out if not
- stosb ; save the character
- jmps func_set10
- func_set20:
- xor ax,ax ; terminate with NULL
- stosb
- func_set30:
- ret
- endif ;not ADDDRV
- func_echo: ; ECHO "string"
- call whitespace ; Scan off all white space
- lodsb ; before the optional
- cmp al,'=' ; '=' character.
- je func_echo10
- dec si ; point at char
- func_echo10:
- mov dx,offset msg_dollar ; NUL error message
- mov al,CR ; SI -> config line anyway
- jmp config_error ; use error reporting routine
- func_yeschar: ; yeschar "string"
- call whitespace ; Scan off all white space
- lodsb ; before the optional
- cmp al,'=' ; '=' character.
- je func_yeschar10
- dec si ; point at char
- func_yeschar10:
- call whitespace
- lodsb
- mov yes_char,al ; update YES character
- ret
- func_chain: ; CHAIN="filename" - use as new CONFIG.SYS
- mov di,offset dev_name ; Copy the Device Filename into a
- mov byte ptr [di],0 ; local buffer and zero terminate
- call copy_file
- jc func_chain10 ; ignore if any problems
- mov ax,(MS_X_OPEN*256)+80h ; Try to open the file
- mov dx,offset dev_name ; as a new config file
- int DOS_INT ; if we can't ignore it
- jc func_chain10
- mov bx,ax
- mov ah,MS_X_CLOSE
- int DOS_INT ; close the new file
- mov si,offset dev_name
- mov di,offset cfg_file
- call copy_asciiz ; copy the new name
- mov cfg_seeklo,0 ; start at begining of it
- mov cfg_seekhi,0
- mov cfg_tail,0 ; force a read
- func_chain10:
- ret
- func_switch: ; SWITCH=option0, option1
- ; GOSUB to appropriate label
- call wait_for_key ; wait until a key is pressed
- jc func_switch01 ; ignore if timeout
- mov ah,MS_C_RAWIN
- int DOS_INT ; read a char
- cmp al,CR
- jne func_switch02
- func_switch01:
- mov al,default_switch_char ; use default character
- func_switch02:
- cmp al,'0' ; ignore if < '0'
- jb func_switch
- cmp al,'9' ; or > '9'
- ja func_switch
- sub al,'1' ; convert from ASCII
- jns func_switch05
- mov al,10 ; make '0' into 10
- func_switch05:
- cbw ; AX = lines to skip
- xchg ax,cx ; make CX the loop count
- jcxz func_switch30
- mov bx,si ; BX -> saved command line start
- func_switch10:
- push bx
- push cx
- mov di,offset dev_name ; copy and discard a label
- call copy_file
- pop cx
- pop bx
- jc func_switch40 ; ignore if any problems
- push bx
- push cx
- call separator ; look for ','
- pop cx
- pop bx
- jc func_switch40 ; stop at end of line
- loop func_switch10
- func_switch30:
- jmp func_gosub ; execute a GOSUB
- func_switch40:
- mov si,bx ; retract to start of line
- jmps func_switch ; then back to sleep again
- func_gosub: ; GOSUB="label"
- ;----------
- pop ax ; get return address
- mov bx,cfg_seeklo ; get existing offset
- mov cx,cfg_seekhi ; in CONFIG file
- sub bx,cfg_tail ; work out begining of buffer
- sbb cx,0
- add bx,cfg_head ; add in current offset in buffer
- adc cx,0
- push bx ; save as position to RETURN to
- push cx
- push ax ; save return address again
- call func_goto ; try to GOTO label
- jc func_return
- ret ; RET, with old offset on stack
- func_return: ; RETURN [n]
- ;-----------
- pop bx ; get return address
- cmp sp,save_sp ; is anything on stack ?
- jae func_return20 ; no, cannot RETURN
- pop cfg_seekhi
- pop cfg_seeklo ; restore position in file
- mov cfg_tail,0 ; force a read
- push bx
- call atoi ; returning a value ?
- pop bx
- jnc func_return10 ; default to 0
- xor ax,ax
- func_return10:
- mov error_level,ax ; return result in error level
- func_return20:
- push bx ; save return address
- ret ; and return to it
- func_goto: ; GOTO="label"
- ;---------
- mov di,offset dev_name ; Copy the label into a
- mov byte ptr [di],0 ; local buffer and zero terminate
- call copy_file
- jc func_goto10 ; ignore if any problems
- mov cfg_seeklo,0 ; Seek to start of file
- mov cfg_seekhi,0
- mov cfg_tail,0 ; force a re-read
- func_goto5:
- call readline ; read in a line
- jc func_goto10 ; stop if end of file
- call strupr ; upper case possible label
- mov bx,offset cfg_buffer
- cmp ds:byte ptr [bx],':' ; is it a label ?
- jne func_goto5 ; no, try next line
- mov si,offset dev_name
- func_goto6:
- inc bx ; next char in possible label
- lodsb ; get a character
- test al,al ; end of label ?
- je func_goto10 ; we have a match !
- cmp al,ds:byte ptr [bx] ; does it match
- jne func_goto5 ; no, try next line
- jmps func_goto6 ; yes, look at next character
- func_goto10:
- ret
- func_exit:
- ; Stop processing CONFIG.SYS
- call readline ; read in a line
- jnc func_exit ; until we can read no more..
- ret
- func_cls:
- ; CLEAR SCREEN
- ; This is PC specific - sorry
- mov ah,15 ; get current
- int 10h ; screen mode
- mov ah,0
- int 10h ; reset it to clear screen
- ret
- func_cpos:
- ; Set cursor position
- call atoi ; AX = row
- jnc func_cpos10 ; check for error
- xor ax,ax ; default to top left
- jmps func_cpos40
- func_cpos10:
- push ax ; save row
- call separator ; look for ','
- jc func_cpos20 ; no col specified
- call atoi ; get col
- jnc func_cpos30
- func_cpos20:
- mov ax,1 ; default to left
- func_cpos30:
- pop dx
- mov ah,dl ; AH = row, AL = col
- sub ax,0101h ; compensate for being one based
- func_cpos40:
- xchg ax,dx ; DH = row, DL = col
- xor bx,bx ; page zero
- mov ah,2 ; set cursor position
- int 10h ; Eeeek!! call the ROS
- ret
- func_timeout:
- ; set TIMEOUT for keyboard input
- call atoi ; AX = # timeout count
- jnc func_timeout10 ; check for error
- xor ax,ax ; bad values mean no timeout
- func_timeout10:
- mov keyb_timeout,ax ; save timeout count
- call separator ; look for ','
- jc func_timeout20
- lodsb ; get default query char
- cmp al,LF ! je func_timeout20
- cmp al,CR ! je func_timeout20
- mov default_query_char,al
- call separator ; look for ','
- jc func_timeout20
- lodsb ; get default switch char
- cmp al,CR ! je func_timeout20
- cmp al,LF ! je func_timeout20
- mov default_switch_char,al
- func_timeout20:
- ret
- func_error:
- ; ERROR='n'
- call atoi ; AX = error count to match
- jc func_error10
- mov error_level,ax ; set error level
- func_error10:
- ret
- func_onerror:
- ; ONERROR='n' optional command
- ;
- call whitespace ; Scan off all white space
- xor bx,bx ; index relationship = 1st item
- xor dx,dx ; DX is bit to set
- func_onerror10:
- or bx,dx ; set reationship bit
- lodsb ; now process a character
- mov dx,2
- cmp al,'=' ; if '=' set bit 1
- je func_onerror10
- mov dx,4
- cmp al,'<' ; if '<' set bit 2
- je func_onerror10
- mov dx,8
- cmp al,'>' ; if '>' set bit 3
- je func_onerror10
- dec si ; point at char
- push bx ; save relationship
- call atoi ; AX = error count to match
- pop bx ; recover relationship
- jc func_onerror20
- cmp error_level,ax ; is it the error level we want ?
- jmp func_onerror_tbl[bx] ; jump to handler
- func_onerror20:
- ret
- func_onerror_tbl:
- dw func_onerror_eq ; . . .
- dw func_onerror_eq ; . . =
- dw func_onerror_lt ; . < .
- dw func_onerror_le ; . < =
- dw func_onerror_gt ; > . .
- dw func_onerror_ge ; > . =
- dw func_onerror_ne ; > < .
- dw func_onerror_take ; > < =
- func_onerror_eq:
- je func_onerror_take
- ret
- func_onerror_ne:
- jne func_onerror_take
- ret
- func_onerror_lt:
- jb func_onerror_take
- ret
- func_onerror_le:
- jbe func_onerror_take
- ret
- func_onerror_gt:
- ja func_onerror_take
- ret
- func_onerror_ge:
- jae func_onerror_take
- ret
- func_onerror_take:
- pop ax ; discard return address
- xor ax,ax ; boot key options = none
- jmp cfg_continue ; and execute this command
- func_query:
- ; ?optional command
- cmp boot_options,F5KEY ; if F5 has been pressed then
- je func_query50 ; do nothing
- call whitespace ; discard any following whitespace
- lodsb ; get a character
- cmp al,'?' ; is it another '?', is so swallow it
- je func_query ; and go round again
- dec si ; it wasn't a '?', forget we looked
- push si ; save current position
- lodsb ; get next real char
- xor cx,cx ; assume no prompt string
- cmp al,'"' ; '?"user prompt"' - keep silent as
- jne func_query10 ; user has supplied prompt
- xchg ax,cx ; CL = " if user prompt
- lodsb
- func_query10:
- cmp al,cl ; is this the user prompt char ?
- je func_query20 ; then stop now
- xchg ax,dx ; DL= character
- mov ah,MS_C_WRITE
- int DOS_INT ; output the character
- lodsb
- cmp al,CR ; is it the end of the line ?
- jne func_query10 ; no, do another character
- mov ah,MS_C_WRITESTR ; Output msg of form " (Y/N) ? "
- mov dx,offset confirm_msg1
- int DOS_INT ; do " ("
- mov ah,MS_C_WRITE
- mov dl,yes_char
- int DOS_INT ; do "Y"
- mov dl,'/'
- int DOS_INT ; do "/"
- mov dl,no_char
- int DOS_INT ; do "N"
- mov ah,MS_C_WRITESTR
- mov dx,offset confirm_msg2
- int DOS_INT ; do ") ? "
- func_query20:
- jcxz func_query30 ; if no user supplied prompt
- pop ax ; don't discard original starting
- push si ; position
- func_query30:
- call wait_for_key ; wait until a key is pressed
- mov al,default_query_char ; if we timeout default
- jc func_query40
- mov ah,MS_C_RAWIN
- int DOS_INT ; read a char
- test al,al ; is it a function key ?
- jnz func_query40
- mov ah,MS_C_RAWIN
- int DOS_INT ; throw away function keys
- jmps func_query30
- func_query40:
- push ax ; save response
- mov ah,MS_C_WRITE
- mov dl,al
- int DOS_INT ; echo the char
- mov ah,MS_C_WRITESTR
- mov dx,offset confirm_msg3
- int DOS_INT ; now do CR/LF to tidy up
- pop ax
- call toupper ; make response upper case
- pop si ; recover starting position
- cmp al,yes_char
- jne func_query50
- pop ax ; Discard Return Address
- xor ax,ax ; boot key options = none
- jmp cfg_continue ; Execute the command
- func_query50:
- ret ; Return without Executing Command
- func_getkey: ; GETKEY
- call wait_for_key ; wait until a key is pressed
- mov ax,CONFIG_ERRLVL ; assume we have timed out
- jc func_getkey10 ; ignore if timeout
- mov ah,MS_C_RAWIN
- int DOS_INT ; read a char
- xor ah,ah ; convert to word
- func_getkey10:
- mov error_level,ax
- ret
- ; CONFIG_ERROR is the global error handler for the CONFIG.SYS
- ; commands. It is called with SI pointing to the CR/LF terminated string
- ; that caused the error and with DX pointing to an "informative" error
- ; message.
- ;
- ; On Entry:- AL Terminating Character
- ; DX Offset of Error Message
- ; SI 0000 No Message to display
- ; Offset of AL terminated string
- ;
- config_error:
- if ADDDRV
- mov error_flag,1
- endif
- push ax
- mov ah,MS_C_WRITESTR ; Print the Error Message
- int DOS_INT ; passed in DX
- pop ax
- mov ah,al ; AH = terminating character
- test si,si ; display the failing string ?
- jz cfg_e20 ; YES then scan for terminator
- cfg_e10:
- lodsb ; get char to display
- cmp al,ah ; have we reached the terminator ?
- je cfg_e20
- xchg ax,dx ; DL = character to display
- mov ah,MS_C_WRITE ; print a character at a time
- int DOS_INT
- xchg ax,dx ; terminator back in AH
- jmps cfg_e10
- cfg_e20:
- ;; jmp crlf ; Terminate with a CRLF
- Public crlf
- crlf:
- push dx
- mov dx,offset msg_crlf ; Print a CR LF
- mov ah,MS_C_WRITESTR
- int DOS_INT
- pop dx
- ret
- ;
- ; Scan the command table for a match with the first entry in the
- ; CR/LF terminated string passed in SI
- scan:
- call whitespace ; scan off all white space
- push bx ; save the CONFIG Handle
- mov bx,offset cfg_table - CFG_SIZE
- scan_10:
- add bx,CFG_SIZE ; bx -> next entry in table
- mov di,CFG_NAME[bx] ; es:di -> next entry name
- test di,di ; end of table ?
- stc ; assume so
- jz scan_exit ; Yes Exit with the Carry Flag Set
- push si ; Save the String Offset
- call compare
- pop ax ; Remove String Address
- jnc scan_20 ; String Matched
- xchg ax,si ; Restore the original String Address
- jmps scan_10 ; and test the next entry
- scan_20:
- and CFG_FLAGS[bx],not CF_QUERY
- test CFG_FLAGS[bx],CF_LC ; should we upper case line ?
- jnz scan_50 ; skip if not
- xchg ax,si
- call strupr ; upper case the command line
- xchg ax,si
- scan_30:
- call whitespace ; Scan off all white space before and
- lodsb ; after the option '=' character
- cmp al,'?' ; are we querying things ?
- jne scan_40
- or CFG_FLAGS[bx],CF_QUERY ; remember the query, now go and
- jmps scan_30 ; remove any other whitespace
- scan_40:
- cmp al,'=' ; '=' character.
- je scan_30
- dec si
- scan_50:
- mov di,bx ; Save the Table Entry
- xor ax,ax ; and exit with the Carry Flag Reset
- scan_exit:
- pop bx
- ret
- ; Compare two strings in case insensitive manner
- ; On Entry:
- ; ds:si -> String 1 (upper/lower case, length determined by string 2)
- ; es:di -> String 2 (uppercase, null terminated)
- ; On Exit:
- ; Carry clear: strings are the same
- ; ds:si -> character immediately following end of string 1
- ; es:di -> character immediately following end on string 2
- ;
- ; Carry set: strings different
- ; ds:si -> As on entry
- ; es:di -> undefined
- ;
- compare:
- ;-------
- push bx
- push si ; save starting position
- compare10:
- mov al,es:[di] ; al = next character
- inc di
- test al,al ; end of string 2 yet ?
- jz compare40 ; yes, strings must be equal
- call dbcs_lead ; DBCS lead byte?
- jnz compare20 ; no
- mov ah,al
- lodsb ; is 1st byte of pair the same ?
- cmp al,ah
- jne compare30
- cmpsb ; is 2nd byte of pair equal ?
- jne compare30
- jmps compare10
- compare20:
- call toupper ; just uppercase this byte
- xchg ax,bx ; BL = string2 character
- lodsb ; al = next char in string 1
- call toupper ; (can't be KANJI if it matches)
- cmp al,bl ; check the characters are
- je compare10 ; identical stop the compare
- compare30:
- stc ; on a mismatch and set CY
- compare40:
- pop bx ; recover starting position
- jnc compare50
- mov si,bx ; SI = original start
- compare50:
- pop bx
- ret
- separator:
- ;---------
- ; On Entry:
- ; DS:SI -> string
- ; On Exit:
- ; DS:SI -> next option
- ; CY set if end of line
- ;
- ; Strips off all whitespace, and the optional ','
- ; CY set at end of line
- call whitespace ; deblank string and
- lodsb ; check for ',' separator
- cmp al,',' ; discarding if found
- je separator10
- cmp al,CR ; end of the line ?
- stc ; assume so
- je separator10
- dec si ; something else, leave alone
- clc ; not end of line
- separator10:
- ret
- separator20:
- call whitespace ; strip of following spaces
- clc ; not end of line
- ret
- strupr:
- ;------
- ; Uppercase a null terminated string.
- ; Entry
- ; ds:si -> null terminated string
- ; Exit
- ; none (string is uppercased)
- ; Lost
- ; no registers changed
- push si
- push ax
- spr_loop:
- mov al, [si] ; al = next byte from string
- test al, al ; end of string?
- jz spr_done ; yes - exit
- ; cmp al,' ' ; BAP. End at first space
- ; je spr_done ; or comma or slash
- ; cmp al,',' ; so that parameters
- ; je spr_done ; are not uppercased
- ; cmp al,'/' ; Took out again cos it caused
- ; je spr_done ; problems with labels (I think).
- call dbcs_lead ; DBCS lead byte?
- jnz spr_not_dbcs ; no
- inc si ; yes - skip first and second bytes of
- inc si ; pair as they cannot be uppercased
- jmp spr_loop ; loop round
- spr_not_dbcs:
- call toupper ; just uppercase this byte
- mov [si], al ; return the result to the string
- inc si
- jmp spr_loop ; continue
- spr_done:
- pop ax
- pop si
- ret
- dbcs_lead:
- ;---------
- ; Return true if given byte is the first of a double byte character.
- ; Entry
- ; al = byte to be tested
- ; Exit
- ; Z Flag = 1 - byte is a DBCS lead
- ; 0 - byte is not a DBCS lead
- ; Lost
- ; no registers changed
- push ds
- push si
- push bx
- push ax
- ; First get a pointer to the double byte lead table in the COUNTRY info.
- lds si, dbcs_tbl ; ds:si -> double byte table
- inc si
- inc si ; skip table length
- ; Examine each entry in the table to see if it defines a range that includes
- ; the given character.
- mov bl, al ; bl = byte to be tested
- dbcs_loop:
- lodsw ; al/ah = start/end of range
- test ax, ax ; end of table?
- jz dbcs_no ; yes - exit (not in table)
- cmp al, bl ; start <= bl?
- ja dbcs_loop ; no - try next range
- cmp ah, bl ; bl <= end?
- jb dbcs_loop ; no - try next range
- cmp al, al ; return with Z flag set
- jmp dbcs_exit
- dbcs_no:
- cmp al, 1 ; return with Z flag reset
- dbcs_exit:
- pop ax
- pop bx
- pop si
- pop ds
- ret
- toupper:
- ;-------
- ; Return the uppercase equivilant of the given character.
- ; The uppercase function defined in the international info block is
- ; called for characters above 80h.
- ; Entry
- ; al = character to uppercase
- ; Exit
- ; al uppercased
- ; Lost
- ; no registers lost
- push bx
- mov bh, ah
- mov ah, 0 ; ax = character to be converted
- cmp al, 'a' ; al < 'a'?
- jb exit_toupper ; yes - done (char unchanged)
- cmp al, 'z' ; al <= 'z'?
- jbe a_z ; yes - do ASCII conversion
- cmp al, 80h ; international char?
- jb exit_toupper ; no - done (char unchanged)
- ; ch >= 80h -- call international routine
- callf dword ptr ctry_info+CI_CASEOFF
- jmp exit_toupper
- a_z:
- ; 'a' <= ch <= 'z' -- convert to uppercase ASCII equivilant
- and al, 0DFh
- exit_toupper:
- mov ah, bh
- pop bx
- ret
- ;
- ; Scan the string DS:SI for ON or OFF return with the carry flag set
- ; on error or AL = 1 for ON and AL = 0 for OFF.
- ;
- check_onoff:
- call whitespace ; Deblank Command
- push si
- mov di,offset cmd_on ; es:di -> "ON"
- call compare ; do we have an "ON"?
- mov al,01 ; Assume ON found
- jnc chk_onoff10
- pop si ! push si ; Save String Location in Case of Error
- mov di,offset cmd_off ; es:di -> "OFF"
- call compare ; do we have an "OFF"?
- mov al,00
- jnc chk_onoff10
- pop si ; No match so return original address
- stc ; with the CARRY falg set.
- ret
- chk_onoff10:
- pop di ; Remove Old String address
- ret ; and return to caller
- atohex:
- ;------
- ; To convert a hex number in the form of an ASCII string to a 32 bit
- ; integer.
- ;
- ; On Entry:
- ; DS:SI -> ASCII hex number
- ; (the end of the number is taken as the first non-digit)
- ; On Exit:
- ; CY clear:
- ; DX:AX = converted number
- ; ds:si -> first non-digit
- ;
- ; CY set:
- ; Either the first character was not a digit
- ; or the number could not be represented in 32 bits
- ; ds:si -> point at which error occured
- ; ax undefined
- ; Lost
- ; no other register
- push bx
- push cx
- push di
- call whitespace ; Deblank Line
- mov di,si ; save string start offset
- xor dx,dx
- xor bx,bx ; number is formed in DX:BX
- atohex10:
- lodsb ; AL = next char from string
- call toupper ; upper case it
- cmp al,'A'
- jb atohex20
- cmp al,'F'
- ja atohex20
- sub al,'A'-10
- jmps atohex30
- atohex20:
- sub al, '0'
- jc atohex40 ; stop if invalid character
- cmp al, 9
- ja atohex40
- atohex30:
- cbw ; AX = digit
- test dh,0f0h ; will we overflow ?
- jnz atohex_error
- mov cl,4
- push bx ; save (top 4 bits)
- shl bx,cl ; *16
- add bx,ax ; add in new digit
- pop ax
- rol ax,cl ; top 4 bits to bottom 4 bits
- and ax,000Fh ; isolate them
- shl dx,cl
- add dx,ax ; add in new digit
- jmp atohex10
- atohex40:
- dec si ; forget the char we stopped on
- cmp si, di ; was there at least one digit?
- ja atohex50 ; yes - exit with carry clear
- atohex_error:
- stc ; set error flag
- atohex50:
- xchg ax,bx ; AX = result
- pop di
- pop cx
- pop bx
- ret
- atoi:
- ;----
- ; To convert a decimal number in the form of an ASCII string to a 16 bit
- ; integer.
- ;
- ; Entry
- ; ds:si -> ASCII decimal number
- ; (the end of the number is taken as the first non-digit)
- ; Exit
- ; Carry clear:
- ; ax = converted number
- ; ds:si -> first non-digit
- ;
- ; Carry set:
- ; Either the first character was not a digit
- ; or the number could not be represented in 16 bits
- ; ds:si -> point at which error occured
- ; ax undefined
- ; Lost
- ; no other register
- push bx ! push cx
- push dx ! push di
- call whitespace ; Deblank Line
- mov di, si ; save string start offset
- mov cx, 10 ; for multiply
- xor ax, ax ; number is formed in ax
- atoi_loop:
- mov bl, [si] ; bl = next char from string
- sub bl, '0'
- jc atoi_done
- cmp bl, 9
- ja atoi_done
- mov bh, 0 ; bx = next digit
- mul cx ; ax = 10 * ax
- jc exit_atoi ; check for 16 bit overflow
- add ax, bx ; ax = (10 * ax) + bx
- jc exit_atoi
- inc si ; ds:si -> next char in string
- jmp atoi_loop
- atoi_done:
- cmp si, di ; was there at least one digit?
- jne exit_atoi ; yes - exit with carry clear
- stc ; no - set error flag
- exit_atoi:
- pop di ! pop dx
- pop cx ! pop bx
- ret
- atol:
- ;----
- ; To convert a decimal number in the form of an ASCII string to a 32 bit
- ; integer.
- ;
- ; Entry
- ; ds:si -> ASCII decimal number
- ; (the end of the number is taken as the first non-digit)
- ; Exit
- ; CY clear:
- ; DX:AX = converted number
- ; ds:si -> first non-digit
- ;
- ; CY set:
- ; Either the first character was not a digit
- ; or the number could not be represented in 32 bits
- ; ds:si -> point at which error occured
- ; ax undefined
- ; Lost
- ; no other register
- push bx
- push cx
- push di
- call whitespace ; Deblank Line
- mov di, si ; save string start offset
- xor ax, ax ; number is formed in
- cwd ; DX/AX
- atol10:
- xor bx,bx ; use CX/BX for next digit
- xor cx,cx
- mov bl,[si] ; BL = next char from string
- sub bl,'0'
- jc atol20
- cmp bl, 9 ; validate digit
- ja atol20
- add ax,ax
- adc dx,dx ; * 2
- jc atol30
- add bx,ax ; * 2 + new digit
- adc cx,dx
- jc atol30
- add ax,ax
- adc dx,dx ; * 4
- jc atol30
- add ax,ax
- adc dx,dx ; * 8
- jc atol30
- add ax,bx ; * 10 + new digit
- add dx,cx
- jc atol30
- inc si ; ds:si -> next char in string
- jmp atol10
- atol20:
- cmp si,di ; was there at least one digit?
- jne atol30 ; yes - exit with carry clear
- stc ; no - set error flag
- atol30:
- pop di
- pop cx
- pop bx
- ret
- readline:
- ;--------
- ; On Entry:
- ; None
- ; On Exit:
- ; DS:SI -> line in buffer
- ; CY set if we have a problem (eg at EOF)
- ;
- mov cx,CFG_BUF_LEN-2 ; Read the next command line
- mov di,offset cfg_buffer ; into the CFG_BUFFER
- mov si,di ; Save the Destination String
- ; address
- read_l10:
- call getchar ; al = next char from file
- cmp al,CR ! jz read_l10 ; end of line ?
- cmp al,LF ! jz read_l10 ; end of line ?
- cmp al,EOF ! jne read_l20 ; end of file ?
- stc ; indicate a problem
- ret
- read_l20:
- stosb ; put next char into the buffer
- call getchar ; al = next char from file
- cmp al,EOF ! jz read_l30 ; end of file ?
- cmp al,CR ! jz read_l30 ; end of line ?
- cmp al,LF ! jz read_l30 ; end of line ?
- loop read_l20 ; loop while space remains
- ; If we fall through to this point the line is too long. Make it a comment.
- mov di, si ; ds:di -> start of buffer
- mov al, ';'
- stosb ; place ';' at buffer start
- mov cx, 1 ; get another one character
- jmps read_l20 ; loop until all of this line consumed
- ; At this point buffer contains a line of text from CCONFIG.SYS.
- ; Terminate it properly
- read_l30:
- mov al,CR ! stosb ; terminate line with CR
- mov al,LF ! stosb ; and a LF
- xor al,al ! stosb ; Reset the Carry Flag
- ret
- getchar:
- mov bx,cfg_head ; we are here in the buffer
- cmp bx,cfg_tail ; are there any more characters ?
- jae getchar10 ; no, read some in from disk
- push ds
- mov ds,init_dseg
- mov al,CONFIG_BUF[bx] ; get a character from the buffer
- pop ds
- inc cfg_head ; inc the pointer
- ret
- getchar10:
- ; we need to read some characters from disk into our buffer
- push cx ! push dx ; Assume something will go wrong
- mov cfg_tail,0 ; say nothing is in the buffer
- mov ax,(MS_X_OPEN*256)+80h ; Open the configuration file
- mov dx,offset cfg_file
- int DOS_INT
- jc getchar40 ; failure, return EOF
- mov bx,ax
- mov ax,(MS_X_LSEEK*256)+0
- mov dx,cfg_seeklo
- mov cx,cfg_seekhi
- int DOS_INT ; seek to current file position
- jc getchar30 ; failure to seek, close and exit
- mov ah,MS_X_READ
- mov cx,CONFIG_BUF_SIZE
- push ds
- mov ds,init_dseg
- mov dx,offset CONFIG_BUF ; lets try and fill out buffer
- int DOS_INT
- pop ds
- jc getchar30
- mov cfg_tail,ax
- mov ax,(MS_X_LSEEK*256)+1
- xor dx,dx
- xor cx,cx
- int DOS_INT ; get current file position
- mov cfg_seeklo,ax ; and save for possible
- mov cfg_seekhi,dx ; future re-opens
- getchar30:
- mov ah,MS_X_CLOSE ; Close the CONFIG file
- int DOS_INT
- getchar40:
- mov bx,cfg_tail ; now lets see if we filled the buffer
- cmp bx,CONFIG_BUF_SIZE ; if not its EOF so mark it as such
- je getchar50
- push ds
- mov ds,init_dseg
- mov CONFIG_BUF[bx],EOF ; add an EOF mark
- pop ds ; in case there isn't one already
- inc cfg_tail
- inc cfg_seeklo
- jnz getchar50
- inc cfg_seekhi
- getchar50:
- push ds
- mov ds,init_dseg
- mov al,CONFIG_BUF ; return 1st char from buffer
- pop ds
- mov cfg_head,1 ; remember we have returned char
- pop dx ! pop cx
- ret
- ;
- ; On a DEVICEHIGH we have encountered a line
- ; /L:r1[,s1][;r2[,s2]]... [/S]
- ; where r1 = load region, s1 = hex size in bytes, r2,s2 etc are further regions
- ; currently only r1/s1 are supported
- ; /S says the regions should m#be minimised
- parse_region:
- ;On Entry:
- ; DS:SI -> command line following '/L:'
- ; On Exit:
- ; DS:SI -> 1st non-parsed character
- ; CY set on error
- ;
- call atoi ; get a region to load in
- jc parse_region40
- mov himem_region,ax ; remember region to try
- call whitespace ; scan off all white space
- lodsb ! dec si ; now see is we have an optional size
- cmp al,',' ; have we a ',' character ?
- mov ax,0 ; assume minimum size not supplied
- jne parse_region30
- inc si
- call atol ; read number into DX:AX
- cmp dx,15 ; is number too big ?
- ja parse_region40
- mov cx,16 ; convert to para's
- div cx
- inc ax ; allow for round up
- inc ax ; and for header
- push ax ; save size of region
- parse_region10:
- mov di,offset slashs_opt ; do we have a "/S" to minimise
- call compare ; the UMB's (ignore it if so)
- jnc parse_region20
- call whitespace ; scan off all white space
- lodsb ! dec si ; strip off other regions
- cmp al,';' ; another region follows ';'
- jne parse_region20
- inc si
- call atoi ; eat the region number
- jc parse_region20
- call whitespace ; scan off all white space
- lodsb ! dec si
- cmp al,',' ; is a size specified ?
- jne parse_region10 ; no, check for another region
- inc si
- call atol ; eat the size
- jnc parse_region10
- parse_region20:
- pop ax
- parse_region30:
- clc ; we can proceed
- ret
- parse_region40:
- mov himem_size,0FFFFh ; 1 MByte wanted (ho, ho)
- stc ; we had problems..
- ret
- ; On a DEVICEHIGH we may encounter a line
- ; SIZE [=] s
- ; where s = size of region in hex bytes
- parse_size:
- ;On Entry:
- ; DS:SI -> command line following '/L:'
- ; On Exit:
- ; DS:SI -> 1st non-parsed character
- ; CY set on error
- ;
- call whitespace ; Scan off all white space
- lodsb ; before and after the optional
- cmp al,'=' ; '=' character.
- je parse_size
- dec si
- call atohex ; read hex number into DX:AX
- jc parse_size10
- cmp dx,15 ; is number too big ?
- ja parse_size20 ; just load low
- mov cx,16 ; convert to para's
- div cx
- inc ax ; allow for round up
- inc ax ; and for header
- mov himem_size,ax ; remember size required
- parse_size10:
- clc
- ret
- parse_size20:
- mov himem_size,0FFFFh ; 1 MByte wanted (ho, ho)
- stc
- ret
- ; A size has not been suppleied with DEVICEHIGH, so guess-timate one
- ; based on file size
- size_file:
- ; On Entry:
- ; DS:SI -> filename
- ; On Exit:
- ; DS:SI preserved
- ;
- push si
- mov di,offset dev_name ; copy the device filename into a
- mov byte ptr [di],0 ; local buffer and zero terminate
- call copy_file
- pop si
- mov ax,(MS_X_OPEN * 256)+0 ; open file r/o
- mov dx,offset dev_name
- int DOS_INT
- jnc size_file10
- mov ax,0FFFFh ; can't open file, force low to prevent
- ret ; two sets of error messages
- size_file10:
- xchg ax,bx ; handle in BX
- mov ah,MS_X_READ
- mov cx,EXE_LENGTH
- mov dx,offset exeBuffer
- int DOS_INT ; read in possible exe header
- jc size_file20
- cmp ax,cx ; did we read all we wanted ?
- jb size_file40 ; if not it can't be an EXE
- cmp exeSignature,'ZM' ; check the signature
- jne size_file40 ; if invalid can't be an EXE
- mov ax,512
- mul exeSize ; DX/AX bytes in image
- add ax,exeFinal
- adc dx,0
- mov cx,16
- cmp dx,cx ; are we too big ?
- jae size_file20 ; yes, force low
- div cx ; AX = para's required
- inc ax ; one for rounding error
- jz size_file20
- add ax,exeMinpara ; add on extra para's required
- jnc size_file30
- size_file20:
- mov ax,0FFFFh ; problems, force a load low
- size_file30:
- push ax ; save para's required
- mov ah,MS_X_CLOSE ; close this file
- int DOS_INT
- pop ax ; AX para's required
- ret
- size_file40:
- mov ax,(MS_X_LSEEK * 256)+2
- xor cx,cx ; now find out how big the file is
- xor dx,dx ; by seeking to zero bytes from end
- int DOS_INT
- jc size_file20
- mov cx,16
- cmp dx,cx ; are we too big ?
- jae size_file20 ; yes, force low
- div cx ; AX = para's required
- inc ax ; one for rounding error
- jmps size_file30
- himem_setup:
- ; On Entry:
- ; AX = minimum amount of upper memory required (in para's)
- ; On Exit:
- ; CY clear if able to satisfy request
- ; CY set on error (we then load low)
- ;
- ; try and find some hi memory
- ; we allocate the biggest available chunk of upper memory
- ;
- push es
- mov cx,ax ; CX = para's required
- mov ax,mem_current_base
- mov himem_current_base,ax ; save mem_current_base
- mov ax,mem_current
- mov himem_current,ax ; save mem_current
- mov ax,mem_max
- mov himem_max,ax ; save mem_max
- mov ah,MS_M_ALLOC
- mov bx,0FFFFh ; give me all memory (please)
- int 21h ; bx = No. of paras available
- cmp bx,cx ; do we have enough ?
- jc himem_setup40 ; no, give up now
- cmp himem_region,0 ; is there a region specified ?
- je himem_setup20 ; no, allocate largest block
- ; Allocate the region specified by /L:
- les bx,func52_ptr ; ES:BX -> list of lists
- mov ax,es:F52_DMD_UPPER[bx] ; get upper memory link
- cmp ax,0FFFFh ; make sure there is one
- je himem_setup20 ; shouldn't happen....
- mov es,ax
- himem_setup10:
- cmp es:DMD_ID,'M' ; is there another block ?
- stc ; if we run out of blocks then
- jne himem_setup40 ; we load low
- mov es,ax ; ES -> DMD
- mov bx,es:DMD_LEN ; get length in para'a
- inc ax
- add ax,bx ; AX -> next DMD
- cmp es:DMD_PSP,0 ; is it free ?
- jne himem_setup10 ; no, try the next
- dec himem_region ; found the right region yet ?
- jnz himem_setup10
- cmp bx,cx ; do we have enough ?
- jc himem_setup40 ; no, go low
- mov ax,es ; ES -> DMD header to allocate
- inc ax
- mov es,ax ; ES -> data in block
- mov ah, MS_M_SETBLOCK
- int 21h ; "allocate" this block
- mov ax,es
- jnc himem_setup30 ; this can only fail if DMD chain
- jmps himem_setup40 ; is corrupt...
- himem_setup20:
- ; allocate the largest block available for DEVICEHIGH
- mov ah, MS_M_ALLOC
- mov bx, 0FFFFh ; give me all memory (please)
- int 21h ; bx = No. of paras available
- mov ah, MS_M_ALLOC ; give me bx paras please
- int 21h ; ax:0 -> my memory
- jc himem_setup40 ; woops, what happened ?
- himem_setup30:
- mov mem_current_base,ax
- mov mem_current,ax ; save base of himem area
- mov mem_max,ax
- add mem_max,bx ; top of himem area
- himem_setup40:
- pop es
- ret
- himem_cleanup:
- ; clean up our high memory - this hook should free up any difference
- ; between himem_current and himem_max
- mov ax,himem_max
- mov mem_max,ax ; restore mem_max
- mov ax,himem_current_base
- xchg mem_current_base,ax ; restore mem_current_base
- mov bx,himem_current
- xchg mem_current,bx ; restore mem_current
- push es
- mov es,ax ; ES -> memory block
- sub bx,ax ; has any memory been used ?
- jz himem_cleanup10
- mov ah,MS_M_SETBLOCK ; try and shrink the block
- int DOS_INT ; to the size we used
- pop es
- ; clc ; return success
- ret
- himem_cleanup10:
- mov ah,MS_M_FREE ; free it all up
- int DOS_INT
- pop es
- stc ; return an error
- ret
- copy_asciiz:
- ;-----------
- lodsb ; get a character
- stosb ; copy it
- test al,al ; is it the terminating NUL ?
- jnz copy_asciiz ; do next char
- ret
- wait_for_key:
- ;------------
- ; On Entry:
- ; None
- ; On Exit:
- ; CY set if no key pressed within timeout
- ;
- mov cx,keyb_timeout ; get timeout value
- clc ; assume no timeout
- jcxz wait_for_key30
- wait_for_key10:
- push cx
- mov ah,MS_T_GETTIME ; get current time
- int DOS_INT ; so we can do timeout
- mov bx,dx ; save secs in BH
- pop cx
- wait_for_key20:
- mov ah,MS_C_STAT ; is a character ready ?
- int DOS_INT ; if so process it
- test al,al ; do we have a character ?
- jnz wait_for_key30
- push cx
- mov ah,MS_T_GETTIME ; get current time
- int DOS_INT ; so we can do timeout
- pop cx
- cmp bh,dh ; have we timed out ?
- je wait_for_key20
- loop wait_for_key10 ; another second gone by
- stc ; we have timed out
- wait_for_key30:
- ret
- ;
- ; COPY_FILE copies the next parameter from DS:SI into the buffer
- ; at ES:DI and terminates with a NULL character. The parameter is
- ; expected to be a FileName. DS:SI are returned pointing to the
- ; next parameter in the command.
- ;
- copy_file:
- call whitespace ; DeBlank the Command Line
- mov cx,MAX_FILELEN ; Limit FileName Length
- push si ; Save SI in case of error
- copy_f10:
- lodsb ; Copy upto the first Space or
- cmp al,' ' ; Control Character
- jbe copy_f20
- cmp al,',' ; stop at ',' too
- je copy_f20
- cmp al,'/' ; Also stop scanning when a switch
- je copy_f20 ; character is detected
- stosb
- loop copy_f10
- pop si ; Restore the original SI
- mov ax,13 ; 13 = invalid data error
- stc ; and return with an error
- ret
- copy_f20:
- pop ax ; Remove Original String address
- dec si ; Point at the failing character
- xor ax,ax
- stosb ; Zero Terminate FileName
- ret
- INITDATA DSEG 'INITDATA'
- if ADDDRV
- extrn err_no_command_file:byte
- extrn err_block_device:byte
- else
- extrn shell:byte ; Default Command Processor
- extrn shell_cline:byte ; Default Command Line
- endif
- extrn dev_epb:byte
- extrn dev_count:byte
- extrn rel_unit:word
- extrn dos_target_seg:word
- extrn bios_target_seg:word
- extrn mem_current_base:word ; Current Base Address
- extrn mem_current:word ; Current Load Address
- extrn mem_max:word ; Top of Available Memory
- extrn mem_size:word ; Real top of Memory
- extrn init_dseg:word ; Current Init Data Segment
- include initmsgs.def ; Include TFT Header File
- ; extrn bad_command:byte
- ; extrn bad_filename:byte
- if not ADDDRV
- ; extrn bad_shell:byte
- ; extrn bad_country:byte
- ; extrn bad_lastdrive:byte
- ; extrn bad_break:byte
- ; extrn bad_buffers:byte
- ; extrn bad_files:byte
- ; extrn bad_fcbs:byte
- ; extrn bad_fopen:byte
- ; extrn bad_drivparm:byte
- ; extrn bad_history:byte
- endif
- ; extrn yes_char:byte ; In BIOSMSGS.ASM
- ; extrn no_char:byte
- extrn dev_load_seg:word
- extrn dev_reloc_seg:word
- extrn dev_epb:byte
- extrn dev_name:byte
- extrn dev_name:byte
- extrn dosVersion:word
- extrn strategy_off:word
- extrn strategy_seg:word
- extrn interrupt_off:word
- extrn interrupt_seg:word
- extrn request_hdr:byte
- extrn next_drv:byte
- extrn strategy_seg:word
- extrn strategy:dword
- extrn interrupt:dword
- extrn func52_ptr:dword
- extrn strategy_seg:word
- extrn condev_off:word
- extrn condev_seg:word
- extrn clkdev_off:word
- extrn clkdev_seg:word
- extrn num_blkdev:byte
- extrn blkdev_table:byte
- extrn last_drv:byte
- extrn next_drv:byte
- extrn max_secsize:word
- extrn max_clsize:word
- extrn country_code:word
- extrn code_page:word
- extrn drdos_ptr:dword
- extrn init_buf:byte
- extrn num_read_ahead_buf:byte
- extrn buffersIn:byte
- extrn num_files:word
- extrn num_fcbs:word
- extrn num_fopen:word
- extrn history_flg:byte ; In INIT code
- extrn history_size:word ;
- extrn num_stacks:word
- extrn stack_size:word
- if not ADDDRV
- extrn hidos:byte
- extrn bios_seg:word
- extrn DeblockSetByUser:Byte
- extrn DeblockSeg:word ; In BIOS data
- endif
- extrn dbcs_tbl:dword
- extrn ctry_info:byte
- Public cfg_file, cfg_file_end
- preload_entry rd 0 ; preload back door entry
- dw 14h ; offset is pre-initialised to 14h
- preload_seg rw 1
- preload_ver dw 10 ; version to give DBLSPACE
- Public preload_drv
- preload_drv db 0 ; number of preload drives
- alt_drive db 0 ; preload checks alternative drive,
- ; (only used loading from A:)
- ; The preload_file is used as is to open a preload device
- ; It is also used to initialise a "DMD" name, and the code to do this
- ; currently finds the "" and then copies the next 8 characters.
- ; This works with the current names - any new names may require modifications
- preload_file dw offset security_file ; initially 'SECURITY.BIN'
- security_file db 'SECURITY.BIN',0
- stacker_file db 'C:STACKER.BIN',0
- dblspace_file db 'C:DBLSPACE.BIN',0
- cfg_file db 'DCONFIG.SYS',0 ; Configuration File
- rb 64 ; space for bigger CHAIN'd file
- cfg_file_end rb 0
- cfg_seeklo dw 0 ; offset we have reached in CONFIG file
- cfg_seekhi dw 0 ; in case Richards CONFIG file > 64k
- cfg_head dw 0 ; offset we are at in CONFIG_BUF
- cfg_tail dw 0 ; # bytes currently in CONFIG_BUF
- cfg_buffer rb CFG_BUF_LEN ; individual lines live here
- ;
- ; EXEC parameter blocks for INSTALL function
- ;
- exec_envseg rw 1 ; Environment Segment
- exec_lineoff rw 1 ; Command Line Offset
- exec_lineseg rw 1 ; Command Line Segment
- exec_fcb1off rw 1 ; Offset of FCB 1 (5Ch)
- exec_fcb1seg rw 1 ; Segment of FCB 1 (5Ch)
- exec_fcb2off rw 1 ; Offset of FCB 2 (6Ch)
- exec_fcb2seg rw 1 ; Segment of FCB 2 (6Ch)
- rd 2 ; Initial SS:SP & CS:IP
- system_sp rw 1
- system_ss rw 1
- ioctl_pb rb 0
- ioctl_func rb 1 ; special functions
- ioctl_type rb 1 ; device type (form factor)
- ioctl_attrib rw 1 ; device attributes
- ioctl_tracks rw 1 ; # of tracks
- ioctl_mtype rb 1 ; media type, usually zero
- ioctl_bpb rb 31 ; default BPB for this type of disk
- ioctl_layout rw 1+64 ; support 64 sectors/track max.
- drivp_drv rb 1 ; drive 0-15
- drivp_chg rb 1 ; change line support
- drivp_prm rb 1 ; permanent media flag
- drivp_ff rb 1 ; form factor
- drivp_trk dw 80
- drivp_spt equ word ptr ioctl_bpb+13
- drivp_heads equ word ptr ioctl_bpb+15 ; # of heads
- ff_table dw bpb360, bpb1200, bpb720 ; 360/1200/720 Kb
- dw bpb243, bpb1200 ; 8" sd/dd
- dw bpb360, bpb360 ; hard disk, tape
- dw bpb1440 ; 1440 Kb
- bpb360 dw 512
- db 2
- dw 1
- db 2
- dw 112
- dw 40*2*9
- db 0FDh
- dw 2
- dw 9
- dw 2
- bpb1200 dw 512
- db 1
- dw 1
- db 2
- dw 224
- dw 80*2*15
- db 0F9h
- dw 7
- dw 15
- dw 2
- bpb720 dw 512 ; bytes per sector
- db 2 ; sectors/cluster
- dw 1 ; FAT address
- db 2 ; # of FAT copies
- dw 112 ; root directory size
- dw 80*2*9 ; sectors/disk
- db 0F9h ; media byte
- dw 3 ; size of single FAT copy
- dw 9 ; sectors per track
- dw 2 ; # of heads
- bpb1440 dw 512
- db 1
- dw 1
- db 2
- dw 224
- dw 80*2*18
- db 0F9h
- dw 7
- dw 18
- dw 2
- bpb243 dw 128
- db 4
- dw 1
- db 2
- dw 64
- dw 77*1*26
- db 0E5h
- dw 1
- dw 26
- dw 1
- msg_crlf db CR, LF
- msg_dollar db '$'
- CFG_NAME equ word ptr .0000h ; Command Name
- CFG_FUNC equ word ptr .0002h ; Command Subroutine
- CFG_FLAGS equ word ptr .0004h ; Command flags
- CFG_SIZE equ 6 ; Size of each Entry
- CF_NOF equ 0001h ; set if F5/F8 should be ignored
- CF_LC equ 0002h ; set if case should be preserved
- CF_QUERY equ 0004h ; set at run time eg. "DEVICE?"
- cfg_table rw 0
- if not ADDDRV
- dw cmd_country, func_country, 0 ; COUNTRY=nnn,nnn,country
- dw cmd_shell, func_shell, 0 ; SHELL=filename
- dw cmd_lastdrive, func_lastdrive, 0 ; LASTDRIVE=d:
- dw cmd_break, func_break, 0 ; BREAK=ON/OFF
- dw cmd_buffers, func_buffers, 0 ; BUFFERS=nn
- dw cmd_hibuffers, func_hibuffers, 0 ; HIBUFFERS=nn
- dw cmd_fcbs, func_fcbs, 0 ; FCBS=nn
- dw cmd_files, func_files, 0 ; FILES=nn
- dw cmd_stacks, func_stacks, 0 ; STACKS=nn
- dw cmd_fastopen, func_fastopen, 0 ; FASTOPEN=nnn
- dw cmd_drivparm, func_drivparm, 0 ; DRIVPARM=/d:nn ...
- dw cmd_history, func_history, 0 ; HISTORY=ON|OFF,NNN
- dw cmd_hiinstall, func_hiinstall, 0 ; HIINSTALL=cmdstring
- dw cmd_installhigh, func_hiinstall, 0 ; INSTALLHIGH=cmdstring
- dw cmd_install, func_install, 0 ; INSTALL=cmdstring
- dw cmd_hidos, func_hidos, 0 ; HIDOS=ON/OFF
- dw cmd_dos, func_dos, 0 ; DOS=HIGH
- dw cmd_set, func_set, CF_LC ; SET envar=string
- dw cmd_switches, func_switches, CF_NOF ; SWITCHES=...
- endif
- dw cmd_hidevice, func_hidevice, 0 ; HIDEVICE=filename
- dw cmd_devicehigh, func_hidevice, 0 ; DEVICEHIGH=filename
- dw cmd_device, func_device, 0 ; DEVICE=filename
- dw cmd_remark, func_remark, CF_NOF ; REM Comment
- dw cmd_semicolon, func_remark, CF_NOF ; ; Comment
- dw cmd_colon, func_remark, CF_NOF ; :label
- dw cmd_chain, func_chain, 0 ; CHAIN=filename
- dw cmd_goto, func_goto, 0 ; GOTO=label
- dw cmd_gosub, func_gosub, 0 ; GOSUB=label
- dw cmd_return, func_return, 0 ; RETURN (from GOSUB)
- dw cmd_cls, func_cls, 0 ; Clear Screen
- dw cmd_cpos, func_cpos, 0 ; Set Cursor Position
- dw cmd_timeout, func_timeout, 0 ; set ? TIMEOUT
- dw cmd_switch, func_switch, 0 ; SWITCH=n
- dw cmd_onerror, func_onerror, CF_LC ; ONERROR='n' optional command
- dw cmd_query, func_query, CF_NOF+CF_LC; ?optional command
- dw cmd_echo, func_echo, CF_LC ; ECHO=string
- dw cmd_exit, func_exit, 0 ; EXIT
- dw cmd_error, func_error, 0 ; ERROR='n'
- dw cmd_getkey, func_getkey, 0 ; GETKEY
- dw cmd_yeschar, func_yeschar, 0 ; YESCHAR=
- dw cmd_deblock, func_deblock, 0 ; DEBLOCK=xxxx
- dw cmd_numlock, func_numlock, 0 ; NUMLOCK=ON/OFF
- dw cmd_common, func_common, 0 ; [COMMON]
- dw 0 ; end of table
- if not ADDDRV
- cmd_country db 'COUNTRY',0
- cmd_shell db 'SHELL',0
- cmd_lastdrive db 'LASTDRIVE',0
- cmd_break db 'BREAK',0
- cmd_buffers db 'BUFFERS',0
- cmd_hibuffers db 'HIBUFFERS',0
- cmd_fcbs db 'FCBS',0
- cmd_files db 'FILES',0
- cmd_stacks db 'STACKS',0
- cmd_fastopen db 'FASTOPEN',0
- cmd_drivparm db 'DRIVPARM', 0
- cmd_history db 'HISTORY', 0
- cmd_install db 'INSTALL', 0
- cmd_hiinstall db 'HIINSTALL', 0
- cmd_installhigh db 'INSTALLHIGH', 0
- cmd_hidos db 'HIDOS',0
- cmd_dos db 'DOS',0
- cmd_set db 'SET',0
- cmd_switches db 'SWITCHES',0
- endif
- cmd_hidevice db 'HIDEVICE',0
- cmd_devicehigh db 'DEVICEHIGH',0
- cmd_device db 'DEVICE',0
- cmd_remark db 'REM', 0
- cmd_semicolon db ';',0
- cmd_colon db ':',0
- cmd_chain db 'CHAIN',0
- cmd_goto db 'GOTO',0
- cmd_gosub db 'GOSUB',0
- cmd_return db 'RETURN',0
- cmd_cls db 'CLS',0
- cmd_cpos db 'CPOS',0
- cmd_timeout db 'TIMEOUT',0
- cmd_switch db 'SWITCH',0
- cmd_onerror db 'ONERROR',0
- cmd_query db '?',0
- cmd_echo db 'ECHO',0
- cmd_exit db 'EXIT',0
- cmd_error db 'ERROR',0
- cmd_getkey db 'GETKEY',0
- cmd_yeschar db 'YESCHAR',0
- cmd_deblock db 'DEBLOCK',0
- cmd_numlock db 'NUMLOCK',0
- cmd_common db '[COMMON]',0
- cmd_on db 'ON',0
- cmd_off db 'OFF',0
- confirm_msg1 db ' ($'
- confirm_msg2 db ') ? $'
- confirm_msg3 db CR,LF,'$'
- region_opt db '/L:',0
- slashs_opt db '/S',0
- size_opt db 'SIZE',0
- high_opt db 'HIGH',0
- low_opt db 'LOW',0
- umb_opt db 'UMB',0
- noumb_opt db 'NOUMB',0
- himem_region dw 0 ; region to hidevice into
- himem_size dw 0 ; minimum size wanted
- himem_current dw 0
- himem_current_base dw 0
- himem_max dw 0
- if ADDDRV
- error_flag db 0 ;1 if error occurred during command
- ;file processing, 0 otherwise
- endif
- default_query_char db CR
- default_switch_char db '1'
- keyb_timeout dw 0 ; default is no timeout
- error_level dw 0 ; default is no error
- save_sp dw 0 ; save SP here for GOSUB/RETURN's
- INITENV DSEG PARA 'INITDATA'
- envstart rb 253 ; initial env buffer
- envend dw 0 ; make it double null terminated
- db 1Ah ; EOF marker env buffer
- Public boot_options
- boot_options dw 0
- ; set by BIOS to either the SHIFT states, or to F5KEY or F8KEY
- EXE_LENGTH equ 001Ch
- exeBuffer rw 0
- exeSignature dw 0 ; 0000 Valid EXE contains 'MZ'
- exeFinal dw 0 ; 0002 Image Length MOD 512
- exeSize dw 0 ; 0004 Image Length DIV 512
- exeRelcnt dw 0 ; 0006 No. of Relocation Items
- exeHeader dw 0 ; 0008 Header Size in paragraphs
- exeMinpara dw 0 ; 000A Minimum No extra paragraphs
- exeMaxpara dw 0 ; 000C Maximum No of extra paragraphs
- exeSS dw 0 ; 000E Displacment of Stack Segment
- exeSP dw 0 ; 0010 Initial SP
- exeChecksum dw 0 ; 0012 Negative CheckSum
- exeIP dw 0 ; 0014 Initial IP
- exeCS dw 0 ; 0016 Code Segment displacement
- exeReloff dw 0 ; 0018 Byte Offset of First REL item
- exeOverlay dw 0 ; 001A Overlay Number (0 == Resident)
- end