GENERCFG.A86
上传用户:xiaogehua
上传日期:2007-01-08
资源大小:1183k
文件大小:92k
源码类别:

操作系统开发

开发平台:

Asm

  1. ;    File              : $GENERCFG.A86$
  2. ;
  3. ;    Description       :
  4. ;
  5. ;    Original Author   : DIGITAL RESEARCH
  6. ;
  7. ;    Last Edited By    : $CALDERA$
  8. ;
  9. ;-----------------------------------------------------------------------;
  10. ;    Copyright Work of Caldera, Inc. All Rights Reserved.
  11. ;      
  12. ;    THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
  13. ;    PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
  14. ;    ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
  15. ;    WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
  16. ;    THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
  17. ;    HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
  18. ;    AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
  19. ;    AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
  20. ;    COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
  21. ;    CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
  22. ;    TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
  23. ;    CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
  24. ;    AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
  25. ;    CIVIL LIABILITY.
  26. ;-----------------------------------------------------------------------;
  27. ;
  28. ;    *** Current Edit History ***
  29. ;    *** End of Current Edit History ***
  30. ;
  31. ;    $Log$
  32. ;
  33. ;    GENERCFG.A86 1.51 93/12/02 00:15:06
  34. ;    When auto-sizing DEVICEHIGH requirements use EXE header info if present
  35. ;    GENERCFG.A86 1.49 93/11/29 14:10:29
  36. ;    Add NUMLOCK=ON/OFF support
  37. ;    GENERCFG.A86 1.48 93/11/28 15:32:22
  38. ;    Support HIBUFFERS in UMB's
  39. ;    GENERCFG.A86 1.47 93/11/22 15:45:11
  40. ;    Ignore [COMMON] statements
  41. ;    GENERCFG.A86 1.46 93/11/18 16:20:16
  42. ;    Add primitive multi-master checking
  43. ;    GENERCFG.A86 1.45 93/11/17 20:07:17
  44. ;    change history defaults
  45. ;    GENERCFG.A86 1.44 93/11/16 14:10:21
  46. ;    F5 has precedence over ?
  47. ;    GENERCFG.A86 1.42 93/11/08 17:37:06
  48. ;    Move INSTALLHIGH to before INSTALL, so it's now recognised
  49. ;    GENERCFG.A86 1.41 93/11/04 16:28:08
  50. ;    Cosmetic change - the preload name field now strips off "C:" properly
  51. ;    GENERCFG.A86 1.40 93/11/03 22:52:14
  52. ;    Replace chardev test with one for zero units
  53. ;    GENERCFG.A86 1.39 93/11/03 18:21:16
  54. ;    disable CHARDEV test until it gets fixed
  55. ;    GENERCFG.A86 1.38 93/11/03 17:11:05
  56. ;    Preloaded compression drivers maybe loaded from C: when booting
  57. ;    from a diskette.    
  58. ;    GENERCFG.A86 1.37 93/10/29 19:42:51
  59. ;    DOS=UMB turns HIDOS on
  60. ;    GENERCFG.A86 1.36 93/09/28 19:54:52
  61. ;    Support "DEVICE?=" syntax, and "SWITCHES=/N"
  62. ;    GENERCFG.A86 1.35 93/09/02 22:35:16 
  63. ;    Add header to system allocations
  64. ;    GENERCFG.A86 1.32 93/08/02 14:46:21
  65. ;    hide preload drives from func_device
  66. ;    support INSTALLHIGH
  67. ;    GENERCFG.A86 1.30 93/07/29 14:47:15
  68. ;    Change SETVER method
  69. ;    GENERCFG.A86 1.28 93/07/20 22:32:07
  70. ;    default upper memory link = FFFF
  71. ;    ENDLOG
  72. include config.equ
  73. include i:msdos.equ
  74. include i:char.def
  75. include i:reqhdr.equ
  76. include i:driver.equ
  77. include i:fdos.equ
  78. include i:f52data.def ; Function 52 DOS Data Area
  79. include i:doshndl.def ; DOS Handle Structure Definition
  80. include i:country.def
  81. TRUE     equ 0FFFFh ; value of TRUE
  82. FALSE     equ 0 ; value of FALSE
  83. F5KEY equ 3F00h ; keys returned by BIOS
  84. F8KEY equ 4200h ;  in boot_options
  85. CGROUP group INITCODE, INITDATA, INITENV
  86. INITCODE CSEG PARA 'INITCODE'
  87. extrn whitespace:near
  88. extrn build_cmd_tail:near
  89. extrn device_init:near
  90. extrn init_static_request:near
  91. extrn block_device:near
  92. extrn device_insert:near
  93. if not ADDDRV
  94. extrn nls_hook:near
  95. extrn nls_unhook:near
  96. endif
  97. CONFIG_ERRLVL equ 400h ; special 'CONFIG' error level
  98. ; config_process returns CF set if an error occurred during command file
  99. ; processing for ADDDRV.EXE
  100. Public config_process
  101. config_process: ; Process CONFIG.SYS
  102. mov save_sp,sp ; save SP for unstructured GOSUB's
  103. if ADDDRV
  104. mov error_flag,0
  105. else
  106. mov ax,offset envstart ; env buffer is para aligned
  107. mov cl,4
  108. shr ax,cl ; convert offset to paras
  109. mov cx,ds
  110. add ax,cx ; segment of env variables
  111. les bx,drdos_ptr
  112. mov es:DRDOS_ENVSEG[bx],ax ; tell COMMAND.COM where we are
  113. push ds ! pop es
  114. endif
  115. mov ah,MS_DRV_GET ; check whether we are loading from
  116. int DOS_INT ;   drive C:
  117. cmp al,2
  118.  je preload_security
  119. push ds
  120. mov ah,32h ; get DOS parameter block
  121. mov dl,3 ; ensure drive C: is valid (no critical
  122. int DOS_INT ;  errors)
  123. pop ds
  124. cmp al,0ffh ; skip if the drive is not valid
  125.  je preload_stacker
  126. mov alt_drive,1 ; drive C: should be used also
  127. jmp preload_stacker
  128. preload_security:
  129. call preload_device ; preload the SECURITY device driver
  130. preload_stacker:
  131. mov preload_file,offset stacker_file+2
  132. call preload_device ; preload STACKER from default drive
  133.  jnc preload_done
  134. mov preload_file,offset dblspace_file+2
  135. call preload_device ; STACKER failed, try DBLSPACE from default
  136.  jnc preload_done
  137. cmp alt_drive,0 ; STACKER and DBLSPACE failed on A:,
  138.  je preload_done ;   should we look on drive C:?
  139. mov preload_file,offset stacker_file
  140. call preload_device ; preload STACKER from drive C:
  141.  jnc preload_done
  142. mov preload_file,offset dblspace_file
  143. call preload_device ; STACKER failed, try DBLSPACE from C:
  144. preload_done:
  145. mov ax,(MS_X_OPEN*256)+80h ; Open the configuration file
  146. mov dx,offset cfg_file ; Try Opening the file DCONFIG.SYS
  147. int DOS_INT ; if this fails then open CONFIG.SYS
  148.  jnc cfg_20 ; Found DCONFIG.SYS
  149. if ADDDRV
  150. mov si,dx
  151. mov dx,offset err_no_command_file
  152. xor al,al
  153. call config_error
  154. jmps cfg_exit
  155. else
  156. mov si,offset cfg_file+1
  157. mov di,offset cfg_file
  158. call copy_asciiz ; make DCONFIG.SYS = CONFIG.SYS
  159. mov ax,(MS_X_OPEN*256)+80h ; Open the configuration file
  160. int DOS_INT ; CONFIG.SYS
  161.  jc cfg_exit ; Return on error without complaint
  162. endif
  163. cfg_20:
  164. mov bx,ax ; get the CONFIG handle
  165. mov ah,MS_X_CLOSE ; Close the CONFIG file
  166. int DOS_INT
  167. cfg_nextline: ; Read the next command line
  168. call readline ; If Carry then Terminal Error
  169.  jc cfg_exit ;  so Exit
  170. mov ax,boot_options
  171. cfg_continue:
  172. push ax ; save query options
  173. call scan ; Now Scan the command List 
  174. pop ax ; recover query options
  175.  jc cfg_error ; for a matching command name
  176. call cfg_query ; prompt to see if we want it
  177.  jc cfg_nextline
  178. call CFG_FUNC[di] ; Execute the request command
  179. jmps cfg_nextline ; and loop till the end of the file
  180. cfg_error:
  181. mov dx,offset bad_command ; Display a Bad command error msg
  182. mov al,CR ; and the CR terminated string
  183. call config_error ; then continue processing
  184. jmps cfg_nextline ; Carry Returned On Error
  185. cfg_exit:
  186. mov sp,save_sp ; get back the real stack
  187. call preload_complete ; move transcient code to final position
  188. if ADDDRV
  189. cmp error_flag,1 ;Set CF if error flag is zero
  190. cmc ;Set CF if error flag is 1
  191. endif
  192. ret
  193. cfg_query:
  194. ; On Entry:
  195. ; AX = boot_options key
  196. ; SI -> command tail
  197. ; DI -> CFG_
  198. ; On Exit:
  199. ; CY set if we should skip command
  200. ; SI/DI preserved
  201. ;
  202. push si
  203. push di
  204. test CFG_FLAGS[di],CF_NOF ; are Function Keys allowed ?
  205. ; clc ; if not process the command
  206.  jz $+5 ! jmp cfg_query90
  207. cmp ax,F5KEY ; F5 bypasses CONFIG processing
  208. stc ;  so bypass this line
  209.  je cfg_query90
  210. test CFG_FLAGS[di],CF_QUERY ; specific QUERY request ?
  211.  jnz cfg_query10
  212. cmp ax,F8KEY ; should we prompt for everything ?
  213. clc ; if not process the command
  214.  jne cfg_query90
  215. cfg_query10:
  216. push si
  217. mov si,CFG_NAME[di] ; DS:SI -> command name we matched
  218. cfg_query20:
  219. lodsb ; get character
  220. test al,al ; zero terminated
  221.  jz cfg_query30
  222. xchg ax,dx ; DL= character
  223. mov ah,MS_C_WRITE
  224. int DOS_INT ; output the character
  225. jmps cfg_query20 ; "DEVICE"
  226. cfg_query30:
  227. mov dl,'='
  228. mov ah,MS_C_WRITE
  229. int DOS_INT ; "DEVICE="
  230. pop si ; rest of command line
  231. cfg_query40:
  232. lodsb
  233. cmp al,CR ; is it the end of the line ?
  234.  je cfg_query50 ;  no, do another character
  235. xchg ax,dx ; DL= character
  236. mov ah,MS_C_WRITE
  237. int DOS_INT ; output the character
  238. jmps cfg_query40 ; "DEVICE=FILENAME.SYS"
  239. cfg_query50:
  240. mov ah,MS_C_WRITESTR ; Output msg of form " (Y/N) ? "
  241. mov dx,offset confirm_msg1
  242. int DOS_INT ; do " ("
  243. mov ah,MS_C_WRITE
  244. mov dl,yes_char
  245. int DOS_INT ; do "Y"
  246. mov dl,'/'
  247. int DOS_INT ; do "/"
  248. mov dl,no_char
  249. int DOS_INT ; do "N"
  250. mov ah,MS_C_WRITESTR
  251. mov dx,offset confirm_msg2
  252. int DOS_INT ; do ") ? "
  253. cfg_query60:
  254. call wait_for_key ; wait until a key is pressed
  255. mov al,default_query_char ; if we timeout default
  256.  jc cfg_query70
  257. mov ah,MS_C_RAWIN
  258. int DOS_INT ; read a char
  259. test al,al ; is it a function key ?
  260.  jnz cfg_query70
  261. mov ah,MS_C_RAWIN
  262. int DOS_INT ; throw away function keys
  263.     jmps    cfg_query60  
  264. cfg_query70:
  265. push ax ; save response
  266. mov ah,MS_C_WRITE
  267. mov dl,al
  268. int DOS_INT ; echo the char
  269. mov ah,MS_C_WRITESTR
  270. mov dx,offset confirm_msg3 ; "DEVICE=FILENAME.SYS (Y/N) ?"
  271. int DOS_INT ; now do CR/LF to tidy up
  272. pop ax
  273. call toupper ; make response upper case
  274. cmp al,yes_char ; is it yes ?
  275.  je cfg_query90
  276. stc ; return CY set, skip this line
  277. cfg_query90:
  278. pop di
  279. pop si
  280. ret
  281. call_preload_entry: ; call the preload device driver back door
  282. push ds ; all DBLSPACE calls destroy DS register
  283. callf preload_entry
  284. pop ds
  285. ret
  286. preload_complete: ; CONFIG processing complete
  287. push ds
  288. push es
  289. mov ax,4a11h ; DBLSPACE presence check
  290. xor bx,bx
  291. int 2fh
  292. or ax,ax
  293.  jnz reloc_end
  294. test dx,8000h ; is relocation already complete (may
  295.  jz reloc_end ;   be done by HIDEVICE statement)
  296. mov bx,0ffffh ; query the size of the transcient
  297. mov ax,4a11h ;   portion
  298. int 2fh
  299. mov cx,mem_current ; pull transcient portion down to low
  300. mov es,cx ;   memory
  301. inc cx
  302. mov es:DMD_ID,'D' ; control block type is 'D' (device
  303. mov es:DMD_PSP,cx ;   driver), owner is self
  304. mov es:DMD_LEN,ax
  305. inc ax ; control block overhead
  306. add mem_current,ax
  307. mov di,8 ; copy the name to the control block
  308. mov si,preload_file ; device filename
  309. preload_complete10:
  310. lodsb ; get a character
  311. cmp al,'' ; have we found the '' yet ?
  312.  jne preload_complete10 ; no, go swallow another character
  313. movsw ! movsw ! movsw ! movsw ; copy the 8 bytes
  314. mov ax,es
  315. inc ax ; segment address of free memory
  316. mov es,ax
  317. mov bx,0fffeh ; move transcient portion down
  318. mov ax,4a11h
  319. int 2fh
  320. reloc_end:
  321. pop es
  322. pop ds
  323. ret
  324. PreloadFixup:
  325. ;------------
  326. ; On Entry:
  327. ; None
  328. ; On Exit:
  329. ; None
  330. ; All regs preserved
  331. ;
  332. push es
  333. push bx
  334. push ax
  335. mov al,preload_drv ; get number of preload drives
  336. les bx,func52_ptr
  337. sub es:F52_PHYDRV[bx],al
  338. sub es:F52_LASTDRV[bx],al
  339. pop ax
  340. pop bx
  341. pop es
  342. ret
  343. PreloadCleanup:
  344. ;--------------
  345. ; On Entry:
  346. ; None
  347. ; On Exit:
  348. ; None
  349. ;
  350. ; inform DBLSPACE about each device driver
  351. push ds
  352. push es
  353. xor ax,ax
  354. xchg al,preload_drv ; get number of preload drives
  355. les bx,func52_ptr
  356. add es:F52_PHYDRV[bx],al
  357. add es:F52_LASTDRV[bx],al
  358. mov ax,4a11h ; DBLSPACE installation check
  359. xor bx,bx
  360. int 2fh
  361. or ax,ax
  362.  jnz broadcast_exit
  363. test dx,8000h ; initialisation complete?
  364.  jz broadcast_exit
  365. mov preload_drv,ch ; save # preload drives
  366. mov dx,mem_max ; top of available memory
  367. mov cx,mem_current ; base of available memory
  368. sub dx,cx
  369. mov ah,55h ; version number
  370. mov al,dev_count ; number of new units installed
  371.     mov bx,02h          
  372. callf preload_entry
  373. broadcast_exit:
  374. pop es
  375. pop ds
  376. ret
  377. preload_device: ; preload disk compression driver before
  378. ;   processing (D)CONFIG.SYS file
  379. mov dx,preload_file
  380. mov cx,mem_current ; next available segment address
  381. mov es,cx
  382. inc cx
  383. mov es:DMD_ID,'D' ; control block type is 'D' (device
  384. mov es:DMD_PSP,cx ;   driver), owner is self
  385. mov di,8 ; copy the name to the control block
  386. mov si,dx ; device filename
  387. preload_device10:
  388. lodsb ; get a character
  389. cmp al,'' ; have we found the '' yet ?
  390.  jne preload_device10 ; no, go swallow another character
  391. movsw ! movsw ! movsw ! movsw ; copy the 8 bytes
  392. mov ax,es
  393. inc ax ; segment address of free memory
  394. mov dev_load_seg,ax ; destination segment for EXEC call
  395. mov dev_reloc_seg,ax ; relocation factor for .EXE drivers
  396. push ax
  397. push ds ! pop es
  398. mov bx,offset dev_epb ; ES:BX control structure
  399. mov ax,(MS_X_EXEC * 256)+3
  400. int DOS_INT
  401. pop es ; ES:0 -> preload driver
  402.  jnc load_ok
  403. load_bad:
  404. jmp preload_exit
  405. load_ok:
  406. cmp es:WORD PTR .12h,2e2ch ; preload device signature
  407.  jne load_bad
  408. mov preload_seg,es ; back door entry to preload driver
  409. cmp es:word ptr .82h,6 ; is it the old DBLSPACE driver ?
  410.  jne load_new_dblspace
  411. mov preload_ver,6 ; yes, give it the old version
  412. load_new_dblspace:
  413. mov rel_unit,0 ; reset driver relative unit no.
  414. mov bx,offset request_hdr ; DS:BX static INIT request header
  415. mov ax,mem_max ; highest segment available to the
  416. mov ds:RH0_RESIDENT,0 ;   driver
  417. mov ds:RH0_RESIDENT+2,ax
  418. mov ax,cs
  419. mov es,ax
  420. push ds
  421. call init_static_request ; initialise remaining fields
  422.     mov ax,cs:preload_ver   
  423. callf preload_entry
  424. pop ds
  425.  jc preload_exit ; INIT function fails if CARRY set
  426. or ax,ax ;   or AX != 0
  427.  jnz preload_exit
  428. ;; mov ax,ds:RH0_RESIDENT ; end of resident portion (offset)
  429. ;; add ax,15 ; convert offset to paragraph size
  430. ;; mov cl,4
  431. ;; shr ax,cl
  432. ;; add ax,ds:RH0_RESIDENT+2 ; end of resident portion (segment)
  433. ;JS we should check that the source and destination do not overlap here!
  434. mov bx,04h ; find the size of the transient code
  435. call call_preload_entry
  436. sub mem_max,ax ; move the top of available memory down
  437. mov es,mem_max ; ES destination for relocatable code
  438. dec mem_max ; last free segment address
  439. mov bx,06h ; call driver to relocate code etc.
  440. call call_preload_entry
  441.     inc ax          
  442. mov mem_current,ax ; update base of free TPA
  443. mov es,preload_seg
  444. xor di,di ; ES:DI -> preload driver
  445. mov bx,offset request_hdr
  446. mov al,ds:RH0_NUNITS
  447. test al,al
  448.  jz preload_char_dev
  449. add preload_drv,al ; remember how many preloaded drives
  450. call block_device ; setup the DPBs and other block structures
  451. preload_char_dev:
  452. mov cx,mem_current
  453. mov ax,preload_seg
  454. sub cx,ax ; CX = length of preload driver
  455. dec ax
  456. mov es,ax ; ES:0 -> "DMD" for preload driver
  457. mov es:DMD_LEN,cx
  458. inc ax
  459. mov es,ax
  460. xor di,di ; ES:DI -> "device" header
  461. mov ax,0FFFFh
  462. mov es:[di],ax
  463. mov es:2[di],ax
  464. call device_insert ; insert device into chain
  465. mov dx,mem_max ; top of available memory
  466. mov cx,mem_current ; base of available memory
  467. sub dx,cx
  468. mov ax,5500h ; AH = version, AL = all internal drives
  469. mov bx,02h ; mount existing container files
  470. call call_preload_entry
  471. xor bx,bx ; complete initialisation (hook
  472. call call_preload_entry ;   interrupts etc.)
  473. preload_exit:
  474. push cs ! pop es
  475. ret
  476. func_hidevice: ; HIDEVICE=filename
  477. ; Look for /L:r1[,s1][;r2[,s2]] [/S] filename
  478. ; Look for SIZE=<hexnumber> filename
  479. mov himem_region,0 ; assume no region supplied
  480. mov himem_size,0 ;  and no size
  481. mov di,offset region_opt ; check out /L: region option
  482. call compare
  483.  jc hidevice10
  484. call parse_region ; get region and size
  485.  jnc hidevice20
  486. xor si,si ; something wrong, give an error
  487. mov dx,offset bad_filename
  488. jmp config_error
  489. hidevice10:
  490. mov di,offset size_opt ; check out SIZE= option
  491. call compare
  492.  jc hidevice20 ; if no SIZE= just try to load it
  493. call parse_size ;  else get supplied value
  494. hidevice20:
  495. call whitespace ; we may have a '=' lurking
  496. hidevice30:
  497. lodsb ; strip off optional '='
  498. cmp al,'=' ;  before the filename
  499.  je hidevice30
  500. dec si ; it wasn't a '=' after all
  501. call whitespace
  502. mov ax,himem_size ; get size parameter
  503. cmp ax,6000h ; should we just load low ?
  504.  jae func_device
  505. push si
  506. test ax,ax ; have we been given a size ?
  507.  jne hidevice40
  508. call size_file ; get requirements from file size
  509. hidevice40:
  510. call himem_setup ; try and find some hi memory
  511. pop si
  512.  jc func_device ; if we can't load low
  513. push si
  514. call func_device ; now try and install the device
  515. call himem_cleanup ; clean up our hi memory
  516. pop si
  517.  jc func_device ; error loading hi, try low
  518. ret
  519. func_device: ; DEVICE=filename
  520. push si
  521. mov di,offset dev_name ; Copy the Device Filename into a 
  522. mov byte ptr [di],0 ; local buffer and zero terminate
  523. call copy_file
  524. pop si ; Restore original SI
  525.  jc  device_error
  526. push es
  527. push si
  528. mov es,mem_current ; ES points at structure
  529. call BuildHeader
  530. pop si
  531. push si
  532. call FindName ; DS:SI -> leafname
  533. call SetName ; Fill in name info
  534. pop si
  535. pop es
  536. mov ax,mem_current ; Get Current Memory Base
  537. inc ax ; allow a para for a header
  538. mov dev_load_seg,ax ; Setup the Load Address and the
  539. mov dev_reloc_seg,ax ; relocation factor to be applied to
  540. ; .EXE device drivers
  541. mov ax,(MS_X_OPEN * 256)+0 ; open file r/o
  542. mov dx,offset dev_name
  543. int DOS_INT
  544.  jc device_error
  545. mov bx,ax ; now find out how big the file is
  546. mov ax,(MS_X_LSEEK * 256)+2
  547. xor cx,cx
  548. xor dx,dx ; by seeking to zero bytes from end
  549. int DOS_INT
  550.  jc device_error
  551. xchg ax,cx ; save lo byte of length
  552. mov ah,MS_X_CLOSE ; close this file
  553. int DOS_INT
  554.  jc device_error
  555. mov ax,cx ; DX:AX file length
  556. or cx,dx ; do we have a zero length file
  557.  jz device_error ; if so stop now
  558. mov cl,4
  559. shr ax,cl ; convert file size to para
  560. mov cl,12
  561. shl dx,cl ; ignore > 1 MByte portion
  562. or dx,ax ; dx = file size in para
  563. inc dx ; one for rounding error
  564. add dx,mem_current ; top of area needed for the load
  565. cmp dx,mem_max ; will file fit (really HIDEVICE check)
  566.  jb func_device10 ; no, stop now
  567. ret
  568. device_error:
  569. mov error_level,ax ; save error code
  570. mov al,0
  571. mov si,offset dev_name
  572. mov dx,offset bad_filename
  573. jmp config_error
  574. func_device10:
  575. mov ax,(MS_X_EXEC * 256)+3 ; Use the Load Overlay function to
  576. mov bx,offset dev_epb ; Read in and Relocate the Device
  577. mov dx,offset dev_name ; driver
  578. int DOS_INT ;
  579.  jc device_error
  580. ; mov dosVersion,ax ; set version number
  581. push es
  582. mov ax,mem_current ; Get Current Memory Base
  583. push ax
  584. inc ax ; skip the header
  585. xor di,di ; Address of the first device header
  586. mov es,ax ; in the device chain
  587. if ADDDRV
  588. test es:DH_ATTRIB[di],DA_CHARDEV
  589.  jnz f_dev30 ;Character device driver ?
  590. ; Can't install block device drivers so output error message and exit.
  591. pop es
  592. pop es
  593. xor al,al
  594. mov si,offset dev_name
  595. mov dx,offset err_block_device
  596. jmp config_error
  597. f_dev30:
  598. endif
  599. call PreloadFixup ; fiddle things for preload
  600. if DOS5
  601. call ProtmanFixup ; fiddle int 12 memory for PROTMAN$
  602. endif
  603. call device_init ; initialise the device drivers
  604. if DOS5
  605. call ProtmanCleanup ; restore int 12 memory after PROTMAN$
  606. endif
  607. mov error_level,ax ; save error code
  608. pop es ;  by old EMM386.SYS
  609. mov ax,mem_current
  610. mov es:DMD_LEN,ax ; save memory field
  611. mov ax,es
  612. inc ax
  613. sub es:DMD_LEN,ax
  614. pop es
  615. call PreloadCleanup ; cleanup after ourselves
  616. ret
  617. BuildHeader:
  618. ;-----------
  619. ; On Entry:
  620. ; ES:0 -> header
  621. ; On Exit:
  622. ; None
  623. ;
  624. xor di,di
  625. mov al,'D'
  626. stosb ; ID_FIELD
  627. mov ax,es
  628. inc ax
  629. stosw ; OWNER_FIELD
  630. xor ax,ax
  631. stosb ! stosw ! stosw ; zero rest up to name
  632. ret
  633. FindName:
  634. ;--------
  635. ; On Entry:
  636. ; DS:SI -> pathname of file
  637. ; On Exit:
  638. ; DS:SI -> final leaf name of file
  639. ; CX = length of leaf name
  640. ;
  641. mov cx,si ; remember start of leaf
  642. FindName10:
  643. lodsb
  644. cmp al,' ' ; end of the name ?
  645.  jbe FindName30
  646. call dbcs_lead ; is it a double byte pair ?
  647.  jne FindName20
  648. lodsb ; include the second byte
  649. jmps FindName10
  650. FindName20:
  651. cmp al,'' ; is it a seperator ?
  652.  je FindName
  653. cmp al,'/'
  654.  je FindName
  655. jmps FindName10
  656. FindName30:
  657. xchg cx,si ; SI -> start of leaf name
  658. sub cx,si
  659. dec cx ; CX = length
  660. ret
  661. SetName:
  662. ;-------
  663. ; On Entry:
  664. ; DS:SI -> leaf name to update
  665. ; ES = DMD to update
  666. ; On Exit:
  667. ; CX/SI preserved
  668. ;
  669. push si
  670. mov di,offset DMD_NAME ; point at the owners name field
  671. SetName10:
  672. lodsb
  673. cmp al,' ' ; end of the name ?
  674.  jbe SetName30
  675. call dbcs_lead ; is it a double byte pair ?
  676.  jne SetName20
  677. stosb ; copy 1st byte of pair
  678. cmp di,(offset DMD_NAME)+DMD_NAME_LEN
  679.  jae SetName30 ; don't overflow if name too long
  680. movsb ; and the second
  681. jmps SetName10
  682. SetName20:
  683. stosb
  684. cmp al,'.' ; discard all following '.'
  685.  je SetName30
  686. cmp di,(offset DMD_NAME)+DMD_NAME_LEN
  687.  jb SetName10 ; don't overflow if name too long
  688. SetName30:
  689. dec di
  690. xor ax,ax
  691. SetName40:
  692. stosb ; zero the '.'
  693. cmp di,(offset DMD_NAME)+DMD_NAME_LEN
  694.  jb SetName40 ; zero the rest of the name
  695. SetName50:
  696. pop si
  697. ret
  698. if DOS5
  699. ROS_MEMORY equ .413h ; main memory on KB
  700. protmanName db 'PROTMAN$'
  701. protmanAdjust dw 0
  702. ProtmanFixup:
  703. ;------------
  704. ; On Entry:
  705. ; ES:DI -> device driver header
  706. ; On Exit:
  707. ; All regs preserved
  708. ;
  709. ; fiddle int 12 memory for PROTMAN$
  710. ;
  711. push cx
  712. push si
  713. push di
  714. mov cs:protmanAdjust,0 ; assume it's not protman
  715. mov si,offset protmanName
  716. lea di,DH_NAME[di] ; ES:DI -> device driver name
  717. mov cx,8/2
  718. repe cmpsw ; does the name match ?
  719.  jne ProtmanFixup10
  720. mov si,mem_max ; SI = top of memory in para
  721. push ds
  722. ; xor cx,cx
  723. mov ds,cx
  724. mov cl,10-4
  725. shr si,cl ; convert para to KBytes
  726. mov cx,ds:ROS_MEMORY ; CX = existing top of memory
  727. sub cx,si ; CX = amount to hide
  728. sub ds:ROS_MEMORY,cx ; hide it
  729. pop ds
  730. mov cs:protmanAdjust,cx ; remember how much we hid
  731. ProtmanFixup10:
  732. pop di
  733. pop si
  734. pop cx
  735. ret
  736. ProtmanCleanup:
  737. ;--------------
  738. ; On Entry:
  739. ; None
  740. ; On Exit:
  741. ; All regs preserved
  742. ; restore int 12 memory after PROTMAN$
  743. ;
  744. push ds
  745. push ax
  746. xor ax,ax
  747. mov ds,ax
  748. mov ax,cs:protmanAdjust ; normally zero..
  749. add ds:ROS_MEMORY,ax
  750. pop ax
  751. pop ds
  752. ret
  753. endif
  754. ;
  755. ; The syntax currently supported is "COUNTRY=NNN,[YYY],[FILENAME]" 
  756. ; where:-
  757. ; NNN   is a valid country code based on
  758. ;  the International Dialing Code
  759. ;
  760. ; YYY  is the default CODEPAGE
  761. ;
  762. ; FILENAME is the location and name of the COUNTRY.SYS
  763. ;  file containing the extended country info.
  764. ;
  765. ;
  766. if not ADDDRV
  767. func_country: ; COUNTRY=nnn,[yyy],[filename]
  768. call atoi ; ax = country code
  769.  jc f_ctry50 ; check for error
  770. mov country_code,ax ; save the Country Code
  771. call separator ; look for ','
  772.  jc f_ctry20
  773. call atoi ; Get the Code Page
  774.  jc f_ctry10 ; invalid or non existent code page
  775. mov code_page,ax ; save default Code Page
  776. f_ctry10:
  777. call separator ; look for ','
  778.  jc f_ctry20 ; copy the supplied pathname
  779. les bx,drdos_ptr ; Get the internal data area
  780. mov di,es:DRDOS_COUNTRY_FILE[bx]
  781. ; ES:DI -> pcmode buffer for name
  782. call copy_file
  783. push cs ; restore ES
  784. pop es
  785. f_ctry20:
  786. call nls_hook ; install our lang support
  787. mov bx, country_code ; bx = country code
  788. mov ah, MS_S_COUNTRY
  789. mov al, 0FFh ; 16 bit country code
  790. mov dx, 0FFFFh ; set country code subfunction
  791. int DOS_INT
  792.  jc f_ctry40 ; check for error
  793. mov bx, code_page ; bx = code page
  794. or bx,bx
  795.  jz f_ctry30 ; No Code Page Set leave as 437
  796. mov ax, MS_X_SETCP ; set codepage subfunction
  797. int DOS_INT ; to set Current CodePage
  798. f_ctry30:
  799. jmp nls_unhook ; remove our lang support
  800. ; ret
  801. f_ctry40:
  802. call nls_unhook ; remove our lang support
  803. f_ctry50:
  804. ; Bad or non-existant number in command tail. Display error message.
  805. xor si,si
  806. mov dx, offset bad_country
  807. jmp config_error
  808. func_shell: ; SHELL=filename
  809. mov di,offset shell ; Copy the New Command Name
  810. call copy_file ; into the BIOSINIT buffer
  811. mov al,0 ! stosb ; Terminate the Environment Correctly
  812. jc shell_error
  813. mov di,offset shell_cline+1 ; Now copy the default command
  814. mov al,' ' ! stosb ; into place
  815. mov cx,0 ; 
  816. f_sh10:
  817. lodsb ! stosb ; Copy the next Character
  818. inc cx ; Increment the count
  819. cmp al,CR ; Was this the end of string Char
  820. jnz f_sh10 ; No so Repeat
  821. mov shell_cline,cl ; Save Command Length
  822. ret
  823. shell_error:
  824. mov al,CR
  825. mov dx,offset bad_shell
  826. jmp config_error
  827. func_lastdrive: ; LASTDRIVE=d:
  828. call atoi ; are we supplying a decimal number?
  829.  jc f_lastdrive10
  830. cmp al,32 ; is it in range ?
  831.  jbe f_lastdrive20
  832. lastdrv_error:
  833. xor si,si ; Do not display Failing String
  834. mov dx,offset bad_lastdrive ; and display an error message
  835. jmp config_error
  836. f_lastdrive10:
  837. lodsb ; Get the Option Character 
  838. call toupper ; and convert to Upper Case
  839. sub al, 'A' ; al should be between 0..25
  840. jc lastdrv_error
  841. cmp al, 'Z'-'A'
  842. ja lastdrv_error
  843. inc al ; al = number of drives in system
  844. f_lastdrive20:
  845. mov last_drv,al ; remember for later
  846. ret
  847. func_break: ; BREAK=ON/OFF
  848. call check_onoff ; Check for ON or OFF
  849. mov dl,al ; Get value found
  850. jnc set_break ; and check for error
  851. xor si,si ; Do not display Failing String
  852. mov dx, offset bad_break ; Bad or non-existant ON/OFF string
  853. jmp config_error ; in command tail. Display error message.
  854. set_break:
  855. mov ah,MS_S_BREAK ; Set the Default Break Flag
  856. mov al,01 ; Set Sub-Function
  857. int DOS_INT ; Execute function and return
  858. ret
  859. func_numlock: ; NUMLOCK=ON/OFF
  860. call check_onoff ; Check for ON or OFF
  861.  jc numlock20
  862. push ds
  863. xor bx,bx
  864. mov ds,bx
  865. mov bx,417h ; DS:BX -> keyboard control
  866. or ds:byte ptr [bx],20h ; set numlock bit
  867. test al,al ; was it numlock on ?
  868.  jnz numlock10 ; if not, better clear the bit
  869. and ds:byte ptr [bx],not 20h
  870. numlock10:
  871. pop ds
  872. mov ah,MS_C_STAT ; get console status
  873. int DOS_INT ; (usually int 16 update NUMLOCK state)
  874. numlock20:
  875. ret
  876. func_hibuffers: ; HIBUFFERS=nn[,nn]
  877. or buffersIn,BUFFERS_IN_HMA
  878. ; jmp func_buffers
  879. func_buffers: ; BUFFERS=nn[,nn]
  880. call atoi ; AX = # of buffers
  881.  jc buffer_error ; check for error
  882. cmp ax,MIN_NUM_BUFFS ; check if less than minimum
  883.  jae func_buf1
  884. mov ax,3 ; force to use minimum if less
  885. func_buf1:
  886. cmp ax,MAX_NUM_BUFFS ; check if more than maximum
  887.  jbe func_buf2
  888. mov ax,MAX_NUM_BUFFS ; force to use maximum if more
  889. func_buf2:
  890. mov init_buf,al ; update if we want more
  891. call separator ; look for ','
  892.  jc func_buf4
  893. call atoi ; Get read-ahead buffer size
  894.  jc buffer_error
  895. cmp ax,MIN_READ_AHEAD
  896.  jb buffer_error
  897. cmp ax,MAX_READ_AHEAD
  898.  ja buffer_error
  899. mov num_read_ahead_buf,al
  900. func_buf4:
  901. ret
  902. buffer_error:
  903. xor si,si ; Do not display Failing String
  904. mov dx, offset bad_buffers
  905. jmp config_error
  906. func_files: ; FILES=nn
  907. call atoi ; AX = # of files
  908.  jc files_error ; check for error
  909. cmp ax,MIN_NUM_FILES ; check if less than minimum
  910.  jae func_fil1
  911. mov ax,MIN_NUM_FILES ; force to use minimum if less
  912. func_fil1:
  913. cmp ax,MAX_NUM_FILES ; check if more than maximum
  914.  jbe func_fil2
  915. mov ax,MAX_NUM_FILES ; force to use maximum if more
  916. func_fil2:
  917. mov num_files,ax ; update the number required
  918. ret
  919. files_error:
  920. xor si,si ; Do not display Failing String
  921. mov dx, offset bad_files
  922. jmp config_error
  923. func_fcbs: ; FCBS=nn
  924. call atoi ; AX = # of files
  925.  jc fcbs_error ; check for error
  926. cmp ax,MIN_NUM_FCBS ; check if less than minimum
  927.  jae func_fcb1
  928. mov ax,MIN_NUM_FCBS ; force to use minimum if less
  929. func_fcb1:
  930. cmp ax,MAX_NUM_FCBS ; check if more than maximum
  931.  jbe func_fcb2
  932. mov ax,MAX_NUM_FCBS ; force to use maximum if more
  933. func_fcb2:
  934. mov num_fcbs,ax ; update number of FCB's
  935. ret
  936. fcbs_error:
  937. xor si,si ; Do not display Failing String
  938. mov dx, offset bad_fcbs
  939. jmp config_error
  940. endif ;not ADDDRV
  941. func_common: ; [COMMON]
  942. func_remark: ; REM Comment field
  943. ret
  944. func_switches: ; SWITCHES=...
  945. ; /N = disable F5/F8 feature
  946. ; /W = zap wina20.386 name
  947. ; /K = disable enhanced keyboard support
  948. ; /F = skip statup delay
  949. call whitespace ; skip all spaces
  950. lodsw ; get '/x'
  951. cmp al,CR ; check for end-of-line
  952.  je func_switches10
  953. cmp ah,CR ; check for end-of-line
  954.  je func_switches10
  955. cmp ax,'N/'
  956.  jne func_switches
  957. mov boot_options,0 ; disable boot options
  958. func_switches10:
  959. ret
  960. func_stacks: ; STACKS=number,size
  961. ;-----------
  962. call atoi ; ax = number of stacks
  963.  jc func_stacks20 ; check for error
  964. test ax,ax ; special case ? (disabled)
  965.  jz func_stacks10
  966. cmp ax,MIN_NUM_STACKS ; range check for a sensible value
  967.  jb func_stacks20
  968. cmp ax,MAX_NUM_STACKS
  969.  ja func_stacks20
  970. func_stacks10:
  971. mov num_stacks,ax
  972. call separator ; look for ','
  973.  jc func_stacks20
  974. call atoi ; get size of a stack frame
  975.  jc func_stacks20
  976. cmp ax,MIN_SIZE_STACK ; range check it
  977.  jb func_stacks20
  978. cmp ax,MAX_SIZE_STACK
  979.  ja func_stacks20
  980. mov stack_size,ax
  981. func_stacks20:
  982. ret
  983. if not ADDDRV
  984. func_deblock: ; DEBLOCK=xxxx
  985. ;------------
  986. call atohex ; read hex number into DX:AX
  987.  jc func_deblock10
  988. test dx,dx
  989.  jnz func_deblock10
  990. mov DeblockSetByUser,TRUE ; the user has supplied a setting
  991. push ds
  992. mov ds,bios_seg
  993. mov DeblockSeg,ax ; save deblocking segment
  994. pop ds
  995. func_deblock10:
  996. ret
  997. func_fastopen: ; FASTOPEN=nn
  998. call atoi ; AX = # of files to cache
  999.  jc fopen_error ; check for error
  1000. test ax,ax ; disable fast open?
  1001.  jz func_fopen2 ; yes, allow to set to 0000
  1002. cmp ax,MIN_NUM_FOPEN ; check if less than minimum
  1003.  jae func_fopen1
  1004. mov ax,MIN_NUM_FOPEN ; force to use minimum if less
  1005. func_fopen1:
  1006. cmp ax,MAX_NUM_FOPEN ; check if more than maximum
  1007.  jbe func_fopen2
  1008. mov ax,MAX_NUM_FOPEN ; force to use maximum if more
  1009. func_fopen2:
  1010. mov num_fopen,ax ; update if we want more
  1011. func_fopen3:
  1012. ret
  1013. fopen_error:
  1014. xor si,si ; Do not display Failing String
  1015. mov dx, offset bad_fopen
  1016. jmp config_error
  1017. func_drivparm: ; DRIVPARM = /d:nn [/c] [/f:ff] [h:hh] [/n] [/s:ss] [/t:tt]
  1018. ;-------------
  1019. ; This function specifies the drive parameters for a device
  1020. ; and overrides the defaults assumed by the device driver.
  1021. mov drivp_drv,0FFh ; invalid drive
  1022. call get_switch ; get next switch
  1023. cmp al,'d' ; first option must be /d:dd
  1024.  jne drivparm_error
  1025. call get_number ; get numeric parameter
  1026. mov drivp_drv,al
  1027. mov drivp_chg,FALSE
  1028. mov drivp_prm,FALSE
  1029. mov drivp_trk,80 ; assume 80 tracks
  1030. mov bl,drivp_drv ; get drive to set up
  1031. cmp bl,'Z'-'A'
  1032.  ja drivparm_error
  1033. inc bl
  1034. mov ioctl_pb,0 ; return defaults
  1035. mov ax,440Dh ; generic IOCTL
  1036. mov cx,0860h ; get device parameters
  1037. mov dx,offset ioctl_func
  1038. int DOS_INT
  1039.  jc drivparm_error ; skip if we can't get parameters
  1040. mov drivp_ff,2 ; assume 720K 3.5" drive
  1041. call set_form_factor ; set defaults for form factor
  1042. call get_switch ; get next switch
  1043. cmp al,'c' ; is it /c (change line available)
  1044.  jne drivparm1
  1045. mov drivp_chg,TRUE ; disk change line available
  1046. call get_switch ; get next switch
  1047. drivparm1:
  1048. cmp al,'f' ; form factor specification?
  1049.  jne drivparm2
  1050. call get_number ; get numeric parameter
  1051. mov drivp_ff,al ; set form factor
  1052. call set_form_factor ; set defaults for form factor
  1053. jmps drivparm_loop ; get more parameters
  1054. drivparm_error:
  1055. xor si,si
  1056. mov dx,offset bad_drivparm
  1057. jmp config_error
  1058. drivparm_loop:
  1059. call get_switch ; get next switch
  1060. drivparm2:
  1061. cmp al,'h' ; specify number of heads
  1062.  jne drivparm3
  1063. call get_number ; get numeric parameter
  1064. cmp ax,99
  1065.  ja drivparm_error
  1066. mov drivp_heads,ax ; set # of heads
  1067. jmps drivparm_loop
  1068. drivparm3:
  1069. cmp al,'n'
  1070.  jne drivparm4
  1071. mov drivp_prm,TRUE ; non-removable media
  1072. jmps drivparm_loop
  1073. drivparm4:
  1074. cmp al,'s'
  1075.  jne drivparm5
  1076. call get_number ; get numeric parameter
  1077. cmp ax,63 ; range check sector per track
  1078.  ja drivparm_error
  1079. mov drivp_spt,ax ; set # of sectors/track
  1080. jmps drivparm_loop
  1081. drivparm5:
  1082. cmp al,'t'
  1083.  jne drivparm_error
  1084. call get_number ; get numeric parameter
  1085. cmp ax,999
  1086.  ja drivparm_error
  1087. mov drivp_trk,ax ; set # of sectors/track
  1088. jmps drivparm_loop
  1089. drivparm_done: ; now set drive parameters
  1090. mov bl,drivp_drv
  1091. cmp bl,'Z'-'A'
  1092.  ja drivparm_error
  1093. mov ioctl_func,0000$0100b ; normal track layout assumed,
  1094. ; set device BPB for drive
  1095. mov al,drivp_ff ; get form factor
  1096. mov ioctl_type,al
  1097. sub ax,ax ; assume removable, no disk change
  1098. cmp drivp_prm,FALSE
  1099.  je drivp_d1
  1100. or ax,1 ; drive is permanent media
  1101. drivp_d1:
  1102. cmp drivp_chg,FALSE
  1103.  je drivp_d2
  1104. or ax,2 ; drive supports disk change line
  1105. drivp_d2:
  1106. mov ioctl_attrib,ax ; set drive attributes
  1107. mov ax,drivp_trk ; set # of cylinders
  1108. mov ioctl_tracks,ax
  1109. mov ioctl_mtype,0 ; assume standard type
  1110. mov ax,drivp_spt ; get sectors/track
  1111. mov di,offset ioctl_layout
  1112. push ds ! pop es ; ES:DI -> layout table
  1113. stosw ; set # of sectors
  1114. xchg ax,cx ; CX = # of sectors
  1115. mov ax,1 ; start with sector 1
  1116. drivp_d3:
  1117. stosw ; set next sector #
  1118. inc ax ; move to next sector
  1119. loop drivp_d3 ; repeat for all sectors
  1120. mov ax,drivp_heads
  1121. mul drivp_spt
  1122. mov dx,drivp_trk
  1123. mul dx ; AX/DX = # of sectors/disk
  1124. mov di,offset ioctl_bpb
  1125. mov 8[di],ax ; set sectors per disk
  1126. test dx,dx
  1127.  jz drivp_d4
  1128. mov word ptr 8[di],0 ; indicate large partition
  1129. mov 21[di],ax ; set disk size in sectors
  1130. mov 23[di],dx
  1131. drivp_d4:
  1132. mov bl,drivp_drv
  1133. inc bl
  1134. mov ax,440Dh
  1135. mov cx,0840h ; set drive parameters
  1136. mov dx,offset ioctl_func
  1137. int DOS_INT ; tell the BIOS, ignore errors
  1138. ret
  1139. get_switch: ; get next command line switch
  1140. call whitespace ; skip all spaces & tabs
  1141. lodsb ; get next character
  1142. pop dx ; get return address
  1143. cmp al,'/' ; did we get a switch?
  1144.  je get_swt9 ; yes, return the character
  1145. jmp drivparm_done
  1146. get_swt9:
  1147. lodsb
  1148. or al,('a' xor 'A') ; return upper-cased character
  1149. jmp dx
  1150. get_number:
  1151. ; entry: SI -> next character (must be ':')
  1152. lodsb ; get next character
  1153. cmp al,':' ; must be colon
  1154.  jne get_num_err ; return error if not
  1155. call atoi ; get numeric value
  1156.  jc get_num_err ; must be number
  1157. ret ; AX = number
  1158. get_num_err:
  1159. pop dx
  1160. jmp drivparm_error ; reject this command
  1161. set_form_factor:
  1162. mov bl,drivp_ff
  1163. cmp bl,7
  1164.  ja set_form9
  1165. mov bh,0
  1166. shl bx,1
  1167. push si ! push es
  1168. mov si,ff_table[bx] ; SI -> default media BPB
  1169. push ds ! pop es
  1170. mov di,offset ioctl_bpb ; ES:DI -> local BPB
  1171. mov cx,21 ; copy initialized portion
  1172. rep movsb
  1173. pop es ! pop si
  1174. ret
  1175. set_form9:
  1176. jmp drivparm_error
  1177. ;
  1178. ; This function modifies the History buffer support provided by
  1179. ; DR DOS the defaults are History OFF, 512 byte buffers,
  1180. ; Insert ON, Search OFF, Matching OFF.
  1181. ;
  1182. func_history: ; HISTORY = ON|OFF[,NNNN[,ON|OFF[,ON|OFF[,ON|OFF]]]]
  1183. ;------------
  1184. mov history_flg,0 ; start with it all off
  1185. call check_onoff ; Check for ON|OFF Switch 
  1186.  jc f_hist_err
  1187. test al,al ! jz f_hist_exit ; if OFF forget the rest
  1188. or history_flg,RLF_ENHANCED+RLF_INS
  1189. call separator ; look for ','
  1190.  jc f_hist_exit ; Buffer Size not Specified
  1191. call atoi ; Get the Buffer Size
  1192.  jc f_hist_err ; Invalid on no existant size
  1193. cmp ax,128 ! jb f_hist_err ; Buffer Size to Small
  1194. cmp ax,4096 ! ja f_hist_err ; Buffer Size to Large
  1195. mov history_size,ax ; Save History Buffer Size
  1196. call separator ; look for ','
  1197.  jc f_hist_exit ; Insert mode not Specified
  1198. call check_onoff ; Check for ON|OFF Switch 
  1199.  jc f_hist_err
  1200. test al,al ! jnz func_hist10
  1201. and history_flg,not RLF_INS ; Insert state OFF
  1202. func_hist10:
  1203. call separator ; look for ','
  1204.  jc f_hist_exit ; Search mode not Specified
  1205. call check_onoff ; Check for ON|OFF Switch 
  1206.  jc f_hist_err
  1207. test al,al ! jz func_hist20
  1208. or history_flg,RLF_SEARCH ; Search state ON
  1209. func_hist20:
  1210. call separator ; look for ','
  1211.  jc f_hist_exit ; Match mode not Specified
  1212. call check_onoff ; Check for ON|OFF Switch 
  1213.  jc f_hist_err
  1214. test al,al ! jz func_hist30
  1215. or history_flg,RLF_MATCH ; Match state ON
  1216. func_hist30:
  1217. f_hist_exit:
  1218. ret
  1219. f_hist_err:
  1220. xor si,si ; Do not display Failing String
  1221. mov dx, offset bad_history ; Bad or non-existant ON/OFF string
  1222. jmp config_error ; in command tail. Display error message.
  1223. ;
  1224. ; HIINSTALL filename [Command Line Parameters]
  1225. ;
  1226. ; As INSTALL, but uses high memory if possible
  1227. ;
  1228. func_hiinstall:
  1229.     mov ax,5802h       
  1230. int DOS_INT ;   get upper memory link
  1231. cbw
  1232. push ax ; save upper memory link
  1233.     mov ax,5800h       
  1234. int DOS_INT ;   get alloc strategy
  1235. push ax ; save alloc strategy
  1236.     mov ax,5803h       
  1237. mov bx,1 ;   set upper memory link
  1238. int DOS_INT ;   to 1
  1239.     mov ax,5801h       
  1240. mov bx,80h ;   set alloc strategy to lowest-upper
  1241. int DOS_INT ;   if available
  1242. call func_install ; try and install it
  1243.     mov ax,5801h       
  1244. pop bx ;   set alloc strategy
  1245. int DOS_INT ;   to original value
  1246.     mov ax,5803h       
  1247. pop bx ;   set upper memory link
  1248. int DOS_INT ;   to original value
  1249. ret
  1250. ;
  1251. ; INSTALL filename [Command Line Parameters]
  1252. ;
  1253. ; INSTALL will load and execute "FILENAME" with the optional command 
  1254. ; line parameters and continue processing the DCONFIG.SYS file when
  1255. ; the application terminates.
  1256. ;
  1257. ; Entry
  1258. ; ds:si -> first character of CR terminated filename and option string.
  1259. ; Exit
  1260. ; none
  1261. ;
  1262. ; WARNING -
  1263. ; This code make certain assumptions about memory layout. 
  1264. ; If memory gets fragmented then it all starts falling apart.
  1265. ;
  1266. func_install:
  1267. ;------------
  1268. push ds ! push es
  1269. ;
  1270. ; Shrink the previously allocated memory block to MEM_CURRENT
  1271. ; in preparation of the INSTALL EXEC function.
  1272. ;
  1273. mov es,mem_current_base ; ES: Base Allocated Memory
  1274. mov bx,mem_current ; Get the currently allocated memory
  1275. sub bx,mem_current_base ;  and subtract mem_current_base to
  1276. mov ah,MS_M_FREE ;  give the number of paragraphs used
  1277.  jz func_i10 ; if none, free it all up
  1278. mov ah,MS_M_SETBLOCK ; else modify block accordingly
  1279. func_i10:
  1280. int DOS_INT
  1281. ; Now to protect the CONFIG code in high memory
  1282. mov ah,MS_M_ALLOC ; we now try to find base of TPA
  1283. mov bx,0ffffh ; ASSUME it is the biggest bit
  1284. int 21h ;  of free memory about
  1285. mov ah,MS_M_ALLOC ; give it to me please
  1286. int 21h ; ax:0 -> exec memory
  1287. push bx ; we have allocated BX para's
  1288. mov es,ax ; ES -> exec memory
  1289. mov bx,init_dseg ; we want to protect BX:0 and above
  1290. dec bx ; allow for DMD
  1291. sub bx,ax ; we can spare this many paras
  1292. mov ah,MS_M_SETBLOCK ;  for the exec so grow the 
  1293. int 21h ;  block accordingly
  1294. pop ax ; AX = total, BX = amount for install
  1295. sub ax,bx ; AX = amount we just freed
  1296. dec ax ; allow for DMD
  1297. xchg ax,bx ; BX = freed portion (the Init code)
  1298. mov ah,MS_M_ALLOC ; ASSUME an allocation of this size
  1299. int 21h ;  will contain SYSDAT/CONFIG
  1300. push ax ; save seg so we can free mem later
  1301. mov ah, MS_M_FREE ; now free up the bit we prepared
  1302. int 21h ;  earlier so exec has something
  1303. push ds ! pop es ;  to work in
  1304. mov di,offset dev_name ; Copy the filename into a local
  1305. call copy_file ; buffer
  1306. ; Calculate the command line length
  1307. mov di,si ; by scanning the command line for
  1308. mov al,CR ; the terminating CR
  1309. mov cx,128
  1310. repnz scasb
  1311. dec di
  1312. mov ax,di
  1313. sub ax,si
  1314. dec si ; Point to the byte before the 
  1315. mov byte ptr [si],al ; command line string and update 
  1316. ; the count
  1317. mov ax,offset envstart ; env buffer is para aligned
  1318. mov cl,4
  1319. shr ax,cl ; convert offset to paras
  1320. mov cx,ds
  1321. add ax,cx ; segment of env variables
  1322. mov exec_envseg,ax
  1323. mov exec_lineoff,si
  1324. mov exec_lineseg,ds
  1325. mov exec_fcb1off,0FFFEh   ; Force PCMODE to generate
  1326. mov exec_fcb2off,0FFFEh   ; correct FCB References
  1327. mov system_ss,ss
  1328. mov system_sp,sp
  1329. mov dx,offset dev_name ; Get ASCIIZ Command
  1330. mov bx,offset exec_envseg ; and Parameter Block Offset
  1331. mov ax,4B00h ; Load and Execute Program with Handle
  1332. int DOS_INT ; EXEC the application
  1333. cli ; Swap back to the original stack
  1334. mov ss,cs:system_ss ; again with interrupts disabled
  1335.     mov sp,cs:system_sp
  1336. sti
  1337. mov ah,MS_X_WAIT ; if all went well return the
  1338.  jnc func_i20 ;  termination code
  1339. mov ah,MS_F_ERROR ; if we had an error from EXEC
  1340. xor bx,bx ;  get extended error
  1341. func_i20:
  1342. int DOS_INT ; retrieve error value
  1343. mov cs:error_level,ax ;  and save for testing
  1344. pop es ; recover the seg we protected
  1345. mov ah, MS_M_FREE ; so we can free that memory up
  1346. int 21h
  1347. mov ah,MS_M_ALLOC ; try and allocate as much as possible
  1348. mov bx, 0FFFFh ; ASSUME this will cover CONFIG
  1349. int 21h ; bx = No. of paras available
  1350. mov ah, MS_M_ALLOC ;  give me bx paras please
  1351. int 21h ;  ax:0 -> my memory
  1352. pop es ! pop ds
  1353. mov mem_current_base,ax ; save memory base
  1354. mov mem_current,ax ; for future allocations
  1355. ret
  1356. func_hidos: ; HIDOS ON/OFF
  1357. call check_onoff ; Check for ON or OFF
  1358.  jc f_hidos10 ; Return on error
  1359. mov hidos,al ; update hidos flag
  1360. f_hidos10:
  1361. ret
  1362. func_dos: ; DOS=HIGH - relocate BIOS/BDOS/Buffer etc to FFFF
  1363. call separator ; Deblank Command
  1364. mov di,offset high_opt ; es:di -> "HIGH"
  1365. call compare ; do we have an "HIGH"?
  1366.  jc func_dos10
  1367. push si
  1368. call func_dos_high ; execute HIGH
  1369. pop si
  1370. jmps func_dos
  1371. func_dos10:
  1372. mov di,offset low_opt ; es:di -> "LOW"
  1373. call compare
  1374.  jc func_dos20
  1375. push si
  1376. call func_dos_low ; execute LOW
  1377. pop si
  1378. jmps func_dos
  1379. func_dos20:
  1380. mov di,offset umb_opt ; es:di -> "UMB"
  1381. call compare
  1382.  jc func_dos30
  1383. push si
  1384. call func_dos_umb ; execute UMB
  1385. pop si
  1386. jmps func_dos
  1387. func_dos30:
  1388. mov di,offset noumb_opt ; es:di -> "NOUMB"
  1389. call compare
  1390.  jc func_dos40
  1391. push si
  1392. call func_dos_noumb ; execute NOUMB
  1393. pop si
  1394. jmps func_dos
  1395. func_dos40:
  1396. ret
  1397. func_dos_high:
  1398. ;-------------
  1399. ; Move DOS into the HMA and allocate buffers etc. high too.
  1400. ;
  1401. mov dos_target_seg,0FFFFh
  1402. mov bios_target_seg,0FFFFh
  1403. mov hidos,TRUE ; update hidos flag to be ON
  1404. or buffersIn,BUFFERS_IN_HMA; buffers at seg FFFF too
  1405. ret
  1406. func_dos_low:
  1407. ;------------
  1408. ; force all allocation to be low
  1409. ;
  1410. mov dos_target_seg,0
  1411. mov bios_target_seg,0
  1412. mov hidos,FALSE ; system allocation from low memory
  1413. mov buffersIn,0 ; buffers from low memory
  1414. ret
  1415. func_dos_umb:
  1416. ;------------
  1417. ; allocate Upper Memory Blocks and link them to the DMD chain
  1418. ;
  1419. mov hidos,TRUE ; update hidos flag to be ON
  1420. call initialise_dmd_upper ; build initial upper memory DMD
  1421.  jc func_dos_umb30
  1422. func_dos_umb10:
  1423. call alloc_xms_umb ; allocate XMS upper memory
  1424.  jc func_dos_umb20
  1425. call add_dmd_upper ; add to upper memory DMD's
  1426. jmps func_dos_umb10 ;  go around again
  1427. func_dos_umb20:
  1428. call remove_last_dmd ; get rid of useless last DMD
  1429. func_dos_umb30:
  1430. mov ax,(MS_M_STRATEGY*256)+3
  1431. mov bx,1 ; link in upper memory region
  1432. int 21h
  1433. ret
  1434. func_dos_noumb:
  1435. ;--------------
  1436. ; Unlink Upper Memory blocks from the DMD chain
  1437. ;
  1438. mov ax,(MS_M_STRATEGY*256)+3
  1439. xor bx,bx ; unlink upper memory region
  1440. int 21h
  1441. ret
  1442. alloc_xms_umb:
  1443. ; On Entry:
  1444. ; None
  1445. ; On Exit:
  1446. ; CY set is no upper memory available
  1447. ; else
  1448. ; BX = para base address
  1449. ; DX = para size
  1450. ;
  1451. ; Try to allocate the largest possible block of XMS memory
  1452. ; so we can link it to the upper memory chain
  1453. ;
  1454. push es
  1455. mov ax,4300h ; check for XMS installation
  1456. int 2fh
  1457. cmp al,80h
  1458.  jne alloc_xms10
  1459. mov ax,4310h ; get address of XMS driver
  1460. int 2fh
  1461. mov word ptr xms_driver,bx
  1462. mov word ptr xms_driver+2,es
  1463. mov ah,10h ; allocate upper memory block
  1464. mov dx,0FFFFh ; DX set to find largest block
  1465. callf xms_driver
  1466. cmp dx,3 ; we need at least 3 para's
  1467.  jb alloc_xms10 ;  before we contruct a DMD
  1468. mov ah,10h ; now allocate largest block
  1469. callf xms_driver
  1470. cmp ax,1 ; did we succeed ?
  1471.  je alloc_xms20
  1472. alloc_xms10:
  1473. stc ; return CY set indicating failure
  1474. alloc_xms20:
  1475. pop es
  1476. ret
  1477. xms_driver rd 0
  1478. dw 0,0
  1479. initialise_dmd_upper:
  1480. ; On Entry:
  1481. ; None
  1482. ; On Exit:
  1483. ; CY set if chain already exists
  1484. ; (BX/DX preserved)
  1485. ;
  1486. ; build initial upper memory DMD
  1487. ; we rely on the fact the last para in memory is unused
  1488. ; (but BIOSINIT makes sure that is true)
  1489. ;
  1490. push es
  1491. push bx
  1492. push dx
  1493. if DOS5
  1494. les bx,func52_ptr ; ES:BX -> list of lists
  1495. cmp es:F52_DMD_UPPER[bx],0FFFFh
  1496. else
  1497. les bx,drdos_ptr
  1498. cmp es:DRDOS_DMD_UPPER[bx],0
  1499. les bx,funv52_ptr ; ES:BX -> list of lists
  1500. endif
  1501. stc ; assume error return required
  1502.  jne initialise_dmd_upper30 ; bail out if chain already established
  1503. mov es,es:F52_DMDROOT ; ES -> 1st DMD
  1504. initialise_dmd_upper10:
  1505. cmp es:DMD_ID,IDZ ; end of DMD chain ?
  1506.  je initialise_dmd_upper20
  1507. cmp es:DMD_ID,IDM ; do we have any more DMD's ?
  1508. stc
  1509.  jne initialise_dmd_upper30  ; woops, chain must be bad
  1510. mov ax,es ; better point to it
  1511. inc ax
  1512. add ax,es:DMD_LEN ; AX:0 -> next DMD
  1513. mov es,ax
  1514. jmps initialise_dmd_upper10
  1515. initialise_dmd_upper20:
  1516. mov ax,es
  1517. add ax,es:DMD_LEN ; AX:0 -> will be upper memory chain
  1518. cmp ax,0A000h ; if the DMD chain is already into
  1519. cmc ;  upper memory, lets make sure we
  1520.  jb initialise_dmd_upper30 ;  stop before we fall apart
  1521. mov es:DMD_ID,IDM ; no longer the last entry
  1522. dec es:DMD_LEN ; shorten last DMD to make room
  1523. mov es,ax ; point to new DMD
  1524. mov es:DMD_ID,IDZ ; there is only one entry in the chain
  1525. mov es:DMD_PSP,8 ; its' owned by "system"
  1526. xchg ax,cx ; CX = DMD
  1527. mov ax,0FFFFh
  1528. sub ax,cx ; it's this big
  1529. mov es:DMD_LEN,ax
  1530. if DOS5
  1531. les bx,func52_ptr
  1532. mov es:F52_DMD_UPPER[bx],cx
  1533. else
  1534. les bx,drdos_ptr
  1535. mov es:DRDOS_DMD_UPPER[bx],cx
  1536. endif
  1537. clc
  1538. initialise_dmd_upper30:
  1539. pop dx
  1540. pop bx
  1541. pop es
  1542. ret
  1543. remove_last_dmd:
  1544. ; On Entry:
  1545. ; None
  1546. ; On Exit:
  1547. ; None
  1548. ;
  1549. ; We have build an upper memory DMD chain, but we have left an extra
  1550. ; DMD around covering the ROMs at the top of memory. Remove it if
  1551. ; it's not required.
  1552. ;
  1553. push es
  1554. les bx,func52_ptr ; ES:BX -> list of lists
  1555. mov es,es:F52_DMDROOT[bx] ; ES -> 1st DMD
  1556. remove_last_dmd10:
  1557. cmp es:DMD_ID,IDM ; do we have any more DMD's ?
  1558.  jne remove_last_dmd20 ; bail out if we don't
  1559. mov ax,es ; remember previous DMD
  1560. mov dx,es
  1561. inc dx
  1562. add dx,es:DMD_LEN ; DX:0 -> next DMD
  1563. mov es,dx
  1564. cmp es:DMD_ID,IDZ ; end of DMD chain ?
  1565.  jne remove_last_dmd10
  1566. cmp es:DMD_PSP,8 ; is it owned by "system" ?
  1567.  jne remove_last_dmd20 ;  if so we can ditch this entry
  1568. mov es,ax ; ES = next to last DMD
  1569. mov es:DMD_ID,IDZ ; new end of chain
  1570. inc es:DMD_LEN ; include last para
  1571. if DOS5
  1572. les bx,func52_ptr ; ES:BX -> list of lists
  1573. cmp dx,es:F52_DMD_UPPER[bx]
  1574.  jne remove_last_dmd20 ; remove upper memory link if none left
  1575. mov es:F52_DMD_UPPER[bx],0FFFFh
  1576. else
  1577. les bx,drdos_ptr
  1578. cmp dx,es:DRDOS_DMD_UPPER[bx]
  1579.  jne remove_last_dmd20 ; remove upper memory link if none left
  1580. mov es:DRDOS_DMD_UPPER[bx],0
  1581. endif
  1582. remove_last_dmd20:
  1583. pop es
  1584. ret
  1585. add_dmd_upper:
  1586. ; On Entry:
  1587. ; BX = base address of DMD
  1588. ; DX = size of DMD
  1589. ; On Exit:
  1590. ; None
  1591. ;
  1592. ; Add this block into the upper memory chain.
  1593. ; To do this we find the DMD containing the block and link it into place
  1594. ;
  1595. push es
  1596. push bx ; save base address
  1597. les bx,func52_ptr ; ES:BX -> list of lists
  1598. mov ax,es:F52_DMDROOT[bx] ; AX -> 1st DMD
  1599. pop bx ; 1st DMD is always below XMS
  1600. cmp ax,bx ;  memory, so bomb out if not
  1601.  jae add_dmd_upper40 ;  as our DMD's must be corrupt
  1602. add_dmd_upper10:
  1603. mov es,ax
  1604. add ax,es:DMD_LEN ; AX:0 -> end of this block
  1605. cmp ax,bx ; is the next block above us ?
  1606.  ja add_dmd_upper20 ; if not try the next block
  1607. inc ax ; AX:0 -> next DMD
  1608. cmp es:DMD_ID,IDM ; do we have any more DMD's ?
  1609.  je add_dmd_upper10 ;  we should have......
  1610. jmps add_dmd_upper40 ; stop, DMD's are screwed up
  1611. add_dmd_upper20:
  1612. ; We have found the block we wish to insert a new free block into
  1613. cmp es:DMD_PSP,8 ; it must be owned by "system"
  1614.  jne add_dmd_upper40
  1615. ; Shorten existing DMD to point to new block
  1616. mov ax,bx ; work out how far to new DMD
  1617. mov cx,es
  1618. sub ax,cx ; it's this many para's
  1619. dec ax ; forget the header
  1620. xchg ax,es:DMD_LEN ; set new length
  1621. ; now we need to work out how much is left above the new DMD
  1622. sub ax,dx ; subtract length of new block
  1623. sub ax,es:DMD_LEN ; subtract the portion below
  1624. ; Create DMD covering new block
  1625. mov cl,IDM ; create a new entry
  1626. xchg cl,es:DMD_ID ; CL = existing ID (M/Z)
  1627. mov es,bx ; ES -> base of new DMD
  1628. mov es:DMD_ID,IDM ; it's a link field
  1629. mov es:DMD_PSP,0 ; it's free
  1630. dec dx ; forget the header
  1631. add bx,dx ; last para is here
  1632. dec dx ; forget the next link
  1633. mov es:DMD_LEN,dx ; it's this long
  1634. ; Build a new DMD at the top if the new block for anything above it
  1635. mov es,bx
  1636. mov es:DMD_ID,cl ; inherit the ID field
  1637. mov es:DMD_LEN,ax ; and it's this long
  1638. test ax,ax ; if zero length then
  1639.  jz add_dmd_upper30 ;  it's free
  1640. mov ax,8 ; else it's system
  1641. add_dmd_upper30:
  1642. mov es:DMD_PSP,ax ; set owner
  1643. add_dmd_upper40:
  1644. pop es
  1645. ret
  1646. func_set: ; SET envar=string
  1647. call whitespace ; deblank the command
  1648. mov di,offset envstart-1 ; point to our environment area
  1649. func_set5:
  1650. inc di
  1651. cmp es:word ptr [di],0 ; are we at the end yet
  1652.  jne func_set5
  1653. cmp di,offset envstart ; if nothing is there yet start
  1654.  je func_set10 ;  at the NUL, else skip the NUL
  1655. inc di ;  to leave a seperator
  1656. func_set10:
  1657. lodsb ; get a character
  1658. cmp al,CR ; end of the line yet ?
  1659.  je func_set20
  1660. cmp di,offset envend ; have we room ?
  1661.  jae func_set30 ; bail out if not
  1662. stosb ; save the character
  1663. jmps func_set10
  1664. func_set20:
  1665. xor ax,ax ; terminate with NULL
  1666. stosb
  1667. func_set30:
  1668. ret
  1669. endif ;not ADDDRV
  1670. func_echo: ; ECHO "string"
  1671. call whitespace ; Scan off all white space
  1672. lodsb ; before the optional
  1673. cmp al,'=' ; '=' character.
  1674.  je func_echo10
  1675. dec si ; point at char
  1676. func_echo10:
  1677. mov dx,offset msg_dollar ; NUL error message
  1678. mov al,CR ; SI -> config line anyway
  1679. jmp config_error ; use error reporting routine
  1680. func_yeschar: ; yeschar "string"
  1681. call whitespace ; Scan off all white space
  1682. lodsb ; before the optional
  1683. cmp al,'=' ; '=' character.
  1684.  je func_yeschar10
  1685. dec si ; point at char
  1686. func_yeschar10:
  1687. call whitespace
  1688. lodsb
  1689. mov yes_char,al ; update YES character
  1690. ret
  1691. func_chain: ; CHAIN="filename" - use as new CONFIG.SYS
  1692. mov di,offset dev_name ; Copy the Device Filename into a 
  1693. mov byte ptr [di],0 ; local buffer and zero terminate
  1694. call copy_file
  1695.  jc func_chain10 ; ignore if any problems
  1696. mov ax,(MS_X_OPEN*256)+80h ; Try to open the file
  1697. mov dx,offset dev_name ; as a new config file
  1698. int DOS_INT ; if we can't ignore it
  1699.  jc func_chain10
  1700. mov bx,ax
  1701. mov ah,MS_X_CLOSE
  1702. int DOS_INT ; close the new file
  1703. mov si,offset dev_name
  1704. mov di,offset cfg_file
  1705. call copy_asciiz ; copy the new name
  1706. mov cfg_seeklo,0 ; start at begining of it
  1707. mov cfg_seekhi,0
  1708. mov cfg_tail,0 ; force a read
  1709. func_chain10:
  1710. ret
  1711. func_switch: ; SWITCH=option0, option1
  1712. ; GOSUB to appropriate label
  1713. call wait_for_key ; wait until a key is pressed
  1714.  jc func_switch01 ; ignore if timeout
  1715. mov ah,MS_C_RAWIN
  1716. int DOS_INT ; read a char
  1717. cmp al,CR
  1718.  jne func_switch02
  1719. func_switch01:
  1720. mov al,default_switch_char ; use default character
  1721. func_switch02:
  1722. cmp al,'0' ; ignore if < '0'
  1723.  jb func_switch
  1724. cmp al,'9' ;  or > '9'
  1725.  ja func_switch
  1726. sub al,'1' ; convert from ASCII
  1727.  jns func_switch05
  1728. mov al,10 ; make '0' into 10
  1729. func_switch05:
  1730. cbw ; AX = lines to skip
  1731. xchg ax,cx ; make CX the loop count
  1732.  jcxz func_switch30
  1733. mov bx,si ; BX -> saved command line start
  1734. func_switch10:
  1735. push bx
  1736. push cx
  1737. mov di,offset dev_name ; copy and discard a label
  1738. call copy_file
  1739. pop cx
  1740. pop bx
  1741.  jc func_switch40 ; ignore if any problems
  1742. push bx
  1743. push cx
  1744. call separator ; look for ','
  1745. pop cx
  1746. pop bx
  1747.  jc func_switch40 ; stop at end of line
  1748. loop func_switch10
  1749. func_switch30:
  1750. jmp func_gosub ; execute a GOSUB
  1751. func_switch40:
  1752. mov si,bx ; retract to start of line
  1753. jmps func_switch ;  then back to sleep again
  1754. func_gosub: ; GOSUB="label"
  1755. ;----------
  1756. pop ax ; get return address
  1757. mov bx,cfg_seeklo ; get existing offset
  1758. mov cx,cfg_seekhi ;  in CONFIG file
  1759. sub bx,cfg_tail ; work out begining of buffer
  1760. sbb cx,0
  1761. add bx,cfg_head ; add in current offset in buffer
  1762. adc cx,0
  1763. push bx ; save as position to RETURN to
  1764. push cx
  1765. push ax ; save return address again
  1766. call func_goto ; try to GOTO label
  1767.  jc func_return
  1768. ret ; RET, with old offset on stack
  1769. func_return: ; RETURN [n]
  1770. ;-----------
  1771. pop bx ; get return address
  1772. cmp sp,save_sp ; is anything on stack ?
  1773.  jae func_return20 ; no, cannot RETURN
  1774. pop cfg_seekhi
  1775. pop cfg_seeklo ; restore position in file
  1776. mov cfg_tail,0 ; force a read
  1777. push bx
  1778. call atoi ; returning a value ?
  1779. pop bx
  1780.  jnc func_return10 ; default to 0
  1781. xor ax,ax
  1782. func_return10:
  1783. mov error_level,ax ; return result in error level
  1784. func_return20:
  1785. push bx ; save return address
  1786. ret ;  and return to it
  1787. func_goto: ; GOTO="label"
  1788. ;---------
  1789. mov di,offset dev_name ; Copy the label into a 
  1790. mov byte ptr [di],0 ; local buffer and zero terminate
  1791. call copy_file
  1792.  jc func_goto10 ; ignore if any problems
  1793. mov cfg_seeklo,0 ; Seek to start of file
  1794. mov cfg_seekhi,0
  1795. mov cfg_tail,0 ; force a re-read
  1796. func_goto5:
  1797. call readline ; read in a line
  1798.  jc func_goto10 ; stop if end of file
  1799. call strupr ; upper case possible label
  1800. mov bx,offset cfg_buffer
  1801. cmp ds:byte ptr [bx],':' ; is it a label ?
  1802.  jne func_goto5 ; no, try next line
  1803. mov si,offset dev_name
  1804. func_goto6:
  1805. inc bx ; next char in possible label
  1806. lodsb ; get a character
  1807. test al,al ; end of label ?
  1808.  je func_goto10 ; we have a match !
  1809. cmp al,ds:byte ptr [bx] ; does it match
  1810.  jne func_goto5 ; no, try next line
  1811. jmps func_goto6 ; yes, look at next character
  1812. func_goto10:
  1813. ret
  1814. func_exit:
  1815. ; Stop processing CONFIG.SYS
  1816. call readline ; read in a line
  1817.  jnc func_exit ;  until we can read no more..
  1818. ret
  1819. func_cls:
  1820. ; CLEAR SCREEN
  1821. ; This is PC specific - sorry
  1822. mov ah,15 ; get current
  1823. int 10h ; screen mode
  1824. mov ah,0
  1825. int 10h ; reset it to clear screen
  1826. ret
  1827. func_cpos:
  1828. ; Set cursor position
  1829. call atoi ; AX = row
  1830.  jnc func_cpos10 ; check for error
  1831. xor ax,ax ; default to top left
  1832. jmps func_cpos40
  1833. func_cpos10:
  1834. push ax ; save row
  1835. call separator ; look for ','
  1836.  jc func_cpos20 ; no col specified
  1837. call atoi ; get col
  1838.  jnc func_cpos30
  1839. func_cpos20:
  1840. mov ax,1 ; default to left
  1841. func_cpos30:
  1842. pop dx
  1843. mov ah,dl ; AH = row, AL = col
  1844. sub ax,0101h ; compensate for being one based
  1845. func_cpos40:
  1846. xchg ax,dx ; DH = row, DL = col
  1847. xor bx,bx ; page zero
  1848. mov ah,2 ; set cursor position
  1849. int 10h ; Eeeek!! call the ROS
  1850. ret
  1851. func_timeout:
  1852. ; set TIMEOUT for keyboard input
  1853. call atoi ; AX = # timeout count
  1854.  jnc func_timeout10 ; check for error
  1855. xor ax,ax ; bad values mean no timeout
  1856. func_timeout10:
  1857. mov keyb_timeout,ax ; save timeout count
  1858. call separator ; look for ','
  1859.  jc func_timeout20
  1860. lodsb ; get default query char
  1861. cmp al,LF ! je func_timeout20
  1862. cmp al,CR ! je func_timeout20
  1863. mov default_query_char,al
  1864. call separator ; look for ','
  1865.  jc func_timeout20
  1866. lodsb ; get default switch char
  1867. cmp al,CR ! je func_timeout20
  1868. cmp al,LF ! je func_timeout20
  1869. mov default_switch_char,al
  1870. func_timeout20:
  1871. ret
  1872. func_error:
  1873. ; ERROR='n'
  1874. call atoi ; AX = error count to match
  1875.  jc func_error10
  1876. mov error_level,ax ; set error level
  1877. func_error10:
  1878. ret
  1879. func_onerror:
  1880. ; ONERROR='n' optional command
  1881. ;
  1882. call whitespace ; Scan off all white space
  1883. xor bx,bx ; index relationship = 1st item
  1884. xor dx,dx ; DX is bit to set
  1885. func_onerror10:
  1886. or bx,dx ; set reationship bit
  1887. lodsb ; now process a character
  1888. mov dx,2
  1889. cmp al,'=' ; if '=' set bit 1
  1890.  je func_onerror10
  1891. mov dx,4
  1892. cmp al,'<' ; if '<' set bit 2
  1893.  je func_onerror10
  1894. mov dx,8
  1895. cmp al,'>' ; if '>' set bit 3
  1896.  je func_onerror10
  1897. dec si ; point at char
  1898. push bx ; save relationship
  1899. call atoi ; AX = error count to match
  1900. pop bx ; recover relationship
  1901.  jc func_onerror20
  1902. cmp error_level,ax ; is it the error level we want ?
  1903. jmp func_onerror_tbl[bx] ; jump to handler
  1904. func_onerror20:
  1905. ret
  1906. func_onerror_tbl:
  1907. dw func_onerror_eq ; . . .
  1908. dw func_onerror_eq ; . . =
  1909. dw func_onerror_lt ; . < .
  1910. dw func_onerror_le ; . < =
  1911. dw func_onerror_gt ; > . .
  1912. dw func_onerror_ge ; > . =
  1913. dw func_onerror_ne ; > < .
  1914. dw func_onerror_take ; > < =
  1915. func_onerror_eq:
  1916.  je func_onerror_take
  1917. ret
  1918. func_onerror_ne:
  1919.  jne func_onerror_take
  1920. ret
  1921. func_onerror_lt:
  1922.  jb func_onerror_take
  1923. ret
  1924. func_onerror_le:
  1925.  jbe func_onerror_take
  1926. ret
  1927. func_onerror_gt:
  1928.  ja func_onerror_take
  1929. ret
  1930. func_onerror_ge:
  1931.  jae func_onerror_take
  1932. ret
  1933. func_onerror_take:
  1934. pop ax ; discard return address
  1935. xor ax,ax ; boot key options = none
  1936. jmp cfg_continue ; and execute this command
  1937. func_query:
  1938. ; ?optional command
  1939. cmp boot_options,F5KEY ; if F5 has been pressed then
  1940.  je func_query50 ;  do nothing
  1941. call whitespace ; discard any following whitespace
  1942. lodsb ; get a character
  1943. cmp al,'?' ; is it another '?', is so swallow it
  1944.  je func_query ;  and go round again
  1945. dec si ; it wasn't a '?', forget we looked
  1946. push si ; save current position
  1947. lodsb ; get next real char
  1948. xor cx,cx ; assume no prompt string
  1949. cmp al,'"' ; '?"user prompt"' - keep silent as
  1950.  jne func_query10 ; user has supplied prompt
  1951. xchg ax,cx ; CL = " if user prompt
  1952. lodsb
  1953. func_query10:
  1954. cmp al,cl ; is this the user prompt char ?
  1955.  je func_query20 ;  then stop now
  1956. xchg ax,dx ; DL= character
  1957. mov ah,MS_C_WRITE
  1958. int DOS_INT ; output the character
  1959. lodsb
  1960. cmp al,CR ; is it the end of the line ?
  1961.  jne func_query10 ;  no, do another character
  1962. mov ah,MS_C_WRITESTR ; Output msg of form " (Y/N) ? "
  1963. mov dx,offset confirm_msg1
  1964. int DOS_INT ; do " ("
  1965. mov ah,MS_C_WRITE
  1966. mov dl,yes_char
  1967. int DOS_INT ; do "Y"
  1968. mov dl,'/'
  1969. int DOS_INT ; do "/"
  1970. mov dl,no_char
  1971. int DOS_INT ; do "N"
  1972. mov ah,MS_C_WRITESTR
  1973. mov dx,offset confirm_msg2
  1974. int DOS_INT ; do ") ? "
  1975. func_query20:
  1976.  jcxz func_query30 ; if no user supplied prompt
  1977. pop ax ; don't discard original starting
  1978. push si ;  position
  1979. func_query30:
  1980. call wait_for_key ; wait until a key is pressed
  1981. mov al,default_query_char ; if we timeout default
  1982.  jc func_query40
  1983. mov ah,MS_C_RAWIN
  1984. int DOS_INT ; read a char
  1985. test al,al ; is it a function key ?
  1986.  jnz func_query40
  1987. mov ah,MS_C_RAWIN
  1988. int DOS_INT ; throw away function keys
  1989.     jmps    func_query30
  1990. func_query40:
  1991. push ax ; save response
  1992. mov ah,MS_C_WRITE
  1993. mov dl,al
  1994. int DOS_INT ; echo the char
  1995. mov ah,MS_C_WRITESTR
  1996. mov dx,offset confirm_msg3
  1997. int DOS_INT ; now do CR/LF to tidy up
  1998. pop ax
  1999. call toupper ; make response upper case
  2000. pop si ; recover starting position
  2001. cmp al,yes_char
  2002.  jne func_query50
  2003. pop ax ; Discard Return Address
  2004. xor ax,ax ; boot key options = none
  2005. jmp cfg_continue ; Execute the command
  2006. func_query50:
  2007. ret ; Return without Executing Command
  2008. func_getkey: ; GETKEY
  2009. call wait_for_key ; wait until a key is pressed
  2010. mov ax,CONFIG_ERRLVL ; assume we have timed out
  2011.  jc func_getkey10 ; ignore if timeout
  2012. mov ah,MS_C_RAWIN
  2013. int DOS_INT ; read a char
  2014. xor ah,ah ; convert to word
  2015. func_getkey10:
  2016. mov error_level,ax
  2017. ret
  2018. ; CONFIG_ERROR is the global error handler for the CONFIG.SYS
  2019. ; commands. It is called with SI pointing to the CR/LF terminated string
  2020. ; that caused the error and with DX pointing to an "informative" error
  2021. ; message.
  2022. ;
  2023. ; On Entry:-  AL Terminating Character
  2024. ; DX Offset of Error Message
  2025. ; SI 0000 No Message to display
  2026. ; Offset of AL terminated string
  2027. ;
  2028. config_error:
  2029. if ADDDRV
  2030. mov error_flag,1
  2031. endif
  2032. push ax
  2033. mov ah,MS_C_WRITESTR ; Print the Error Message
  2034. int DOS_INT ; passed in DX
  2035. pop ax
  2036. mov ah,al ; AH = terminating character
  2037. test si,si ; display the failing string ?
  2038.  jz cfg_e20 ;  YES then scan for terminator
  2039. cfg_e10:
  2040. lodsb ; get char to display
  2041. cmp al,ah ; have we reached the terminator ?
  2042.  je cfg_e20
  2043. xchg ax,dx ; DL = character to display
  2044. mov ah,MS_C_WRITE ; print a character at a time
  2045. int DOS_INT
  2046. xchg ax,dx ; terminator back in AH
  2047. jmps cfg_e10
  2048. cfg_e20:
  2049. ;; jmp crlf ; Terminate with a CRLF
  2050. Public crlf
  2051. crlf:
  2052. push dx
  2053. mov dx,offset msg_crlf ; Print a CR LF
  2054. mov ah,MS_C_WRITESTR
  2055. int DOS_INT
  2056. pop dx
  2057. ret
  2058. ;
  2059. ; Scan the command table for a match with the first entry in the
  2060. ; CR/LF terminated string passed in SI
  2061. scan:
  2062. call whitespace ; scan off all white space
  2063. push bx ; save the CONFIG Handle
  2064. mov bx,offset cfg_table - CFG_SIZE
  2065. scan_10:
  2066. add bx,CFG_SIZE ; bx -> next entry in table
  2067. mov di,CFG_NAME[bx] ; es:di -> next entry name
  2068. test di,di ; end of table ?
  2069. stc ; assume so
  2070.  jz scan_exit ; Yes Exit with the Carry Flag Set
  2071. push si ; Save the String Offset
  2072. call compare
  2073. pop ax ; Remove String Address
  2074.  jnc scan_20 ; String Matched
  2075. xchg ax,si ; Restore the original String Address
  2076. jmps scan_10 ; and test the next entry
  2077. scan_20:
  2078. and CFG_FLAGS[bx],not CF_QUERY
  2079. test CFG_FLAGS[bx],CF_LC ; should we upper case line ?
  2080.  jnz scan_50 ;  skip if not
  2081. xchg ax,si
  2082. call strupr ; upper case the command line
  2083. xchg ax,si
  2084. scan_30:
  2085. call whitespace ; Scan off all white space before and
  2086. lodsb ;  after the option '=' character
  2087. cmp al,'?' ; are we querying things ?
  2088.  jne scan_40
  2089. or CFG_FLAGS[bx],CF_QUERY ; remember the query, now go and
  2090. jmps scan_30 ;  remove any other whitespace
  2091. scan_40:
  2092. cmp al,'=' ; '=' character.
  2093.  je scan_30
  2094. dec si
  2095. scan_50:
  2096. mov di,bx ; Save the Table Entry
  2097. xor ax,ax ; and exit with the Carry Flag Reset
  2098. scan_exit:
  2099. pop bx
  2100. ret
  2101. ; Compare two strings in case insensitive manner
  2102. ; On Entry:
  2103. ; ds:si -> String 1 (upper/lower case, length determined by string 2)
  2104. ; es:di -> String 2 (uppercase, null terminated)
  2105. ; On Exit:
  2106. ; Carry clear: strings are the same
  2107. ; ds:si -> character immediately following end of string 1
  2108. ; es:di -> character immediately following end on string 2
  2109. ;
  2110. ; Carry set: strings different
  2111. ; ds:si -> As on entry
  2112. ; es:di -> undefined
  2113. ;
  2114. compare:
  2115. ;-------
  2116. push bx
  2117. push si ; save starting position
  2118. compare10:
  2119. mov al,es:[di] ; al = next character 
  2120. inc di
  2121. test al,al ; end of string 2 yet ?
  2122.  jz compare40 ; yes, strings must be equal
  2123. call dbcs_lead ; DBCS lead byte?
  2124.  jnz compare20 ;  no
  2125. mov ah,al
  2126. lodsb ; is 1st byte of pair the same ?
  2127. cmp al,ah
  2128.  jne compare30
  2129. cmpsb ; is 2nd byte of pair equal ?
  2130.  jne compare30
  2131. jmps compare10
  2132. compare20:
  2133. call toupper ; just uppercase this byte
  2134. xchg ax,bx ; BL = string2 character
  2135. lodsb ; al = next char in string 1
  2136. call toupper ; (can't be KANJI if it matches)
  2137. cmp al,bl ; check the characters are
  2138.  je compare10 ;  identical stop the compare 
  2139. compare30:
  2140. stc ; on a mismatch and set CY
  2141. compare40:
  2142. pop bx ; recover starting position
  2143.  jnc compare50
  2144. mov si,bx ; SI = original start
  2145. compare50:
  2146. pop bx
  2147. ret
  2148. separator:
  2149. ;---------
  2150. ; On Entry:
  2151. ; DS:SI -> string
  2152. ; On Exit:
  2153. ; DS:SI -> next option
  2154. ; CY set if end of line
  2155. ;
  2156. ; Strips off all whitespace, and the optional ','
  2157. ; CY set at end of line
  2158. call whitespace ; deblank string and
  2159. lodsb ;  check for ',' separator
  2160. cmp al,',' ;  discarding if found
  2161.  je separator10
  2162. cmp al,CR ; end of the line ?
  2163. stc ; assume so
  2164.  je separator10
  2165. dec si ; something else, leave alone
  2166. clc ; not end of line
  2167. separator10:
  2168. ret
  2169. separator20:
  2170. call whitespace ; strip of following spaces
  2171. clc ; not end of line
  2172. ret
  2173. strupr:
  2174. ;------
  2175. ; Uppercase a null terminated string.
  2176. ; Entry
  2177. ; ds:si -> null terminated string
  2178. ; Exit
  2179. ; none (string is uppercased)
  2180. ; Lost
  2181. ; no registers changed
  2182. push si
  2183. push ax
  2184. spr_loop:
  2185. mov al, [si] ; al = next byte from string
  2186. test al, al ; end of string?
  2187. jz spr_done ;  yes - exit
  2188. ; cmp al,' ' ; BAP. End at first space
  2189. ; je spr_done ; or comma or slash
  2190. ; cmp al,',' ; so that parameters
  2191. ; je spr_done ; are not uppercased
  2192. ; cmp al,'/' ; Took out again cos it caused
  2193. ; je spr_done ; problems with labels (I think).
  2194. call dbcs_lead ; DBCS lead byte?
  2195. jnz spr_not_dbcs ;  no
  2196. inc si ;  yes - skip first and second bytes of
  2197. inc si ;  pair as they cannot be uppercased
  2198. jmp spr_loop ; loop round
  2199. spr_not_dbcs:
  2200. call toupper ; just uppercase this byte
  2201. mov [si], al ; return the result to the string
  2202. inc si
  2203. jmp spr_loop ; continue
  2204. spr_done:
  2205. pop ax
  2206. pop si
  2207. ret
  2208. dbcs_lead:
  2209. ;---------
  2210. ; Return true if given byte is the first of a double byte character.
  2211. ; Entry
  2212. ; al  = byte to be tested
  2213. ; Exit
  2214. ; Z Flag = 1 - byte is a DBCS lead
  2215. ;   0 - byte is not a DBCS lead
  2216. ; Lost
  2217. ; no registers changed
  2218. push ds
  2219. push si
  2220. push bx
  2221. push ax
  2222. ; First get a pointer to the double byte lead table in the COUNTRY info.
  2223. lds si, dbcs_tbl ; ds:si -> double byte table
  2224. inc si
  2225. inc si ; skip table length
  2226. ; Examine each entry in the table to see if it defines a range that includes
  2227. ; the given character.
  2228. mov bl, al ; bl = byte to be tested
  2229. dbcs_loop:
  2230. lodsw ; al/ah = start/end of range
  2231. test  ax, ax ; end of table?
  2232. jz dbcs_no ;  yes - exit (not in table)
  2233. cmp al, bl ; start <= bl?
  2234. ja dbcs_loop ;  no - try next range
  2235. cmp ah, bl ; bl <= end?
  2236. jb dbcs_loop ;  no - try next range
  2237. cmp al, al ; return with Z flag set
  2238. jmp dbcs_exit
  2239. dbcs_no:
  2240. cmp al, 1 ; return with Z flag reset
  2241. dbcs_exit:
  2242. pop ax
  2243. pop bx
  2244. pop si
  2245. pop ds
  2246. ret
  2247. toupper:
  2248. ;-------
  2249. ; Return the uppercase equivilant of the given character.
  2250. ; The uppercase function defined in the international info block is 
  2251. ; called for characters above 80h.
  2252. ; Entry
  2253. ; al = character to uppercase
  2254. ; Exit
  2255. ; al uppercased
  2256. ; Lost
  2257. ;  no registers lost
  2258. push bx
  2259. mov bh, ah
  2260. mov ah, 0 ; ax = character to be converted
  2261. cmp al, 'a' ; al < 'a'?
  2262. jb exit_toupper ;  yes - done (char unchanged)
  2263. cmp al, 'z' ; al <= 'z'?
  2264. jbe a_z ;  yes - do ASCII conversion
  2265. cmp al, 80h ; international char?
  2266. jb exit_toupper ;  no - done (char unchanged)
  2267. ; ch >= 80h  -- call international routine
  2268. callf dword ptr ctry_info+CI_CASEOFF
  2269. jmp exit_toupper
  2270. a_z:
  2271. ; 'a' <= ch <= 'z'  -- convert to uppercase ASCII equivilant
  2272. and al, 0DFh
  2273. exit_toupper:
  2274. mov ah, bh
  2275. pop bx
  2276. ret
  2277. ;
  2278. ; Scan the string DS:SI for ON or OFF return with the carry flag set
  2279. ; on error or AL = 1 for ON and AL = 0 for OFF.
  2280. ;
  2281. check_onoff:
  2282. call whitespace ; Deblank Command
  2283. push si
  2284. mov di,offset cmd_on ; es:di -> "ON"
  2285. call compare ; do we have an "ON"?
  2286. mov al,01 ; Assume ON found
  2287. jnc chk_onoff10
  2288. pop si ! push si ; Save String Location in Case of Error
  2289. mov di,offset cmd_off ; es:di -> "OFF"
  2290. call compare ; do we have an "OFF"?
  2291. mov al,00
  2292. jnc chk_onoff10
  2293. pop si ; No match so return original address
  2294. stc ; with the CARRY falg set.
  2295. ret
  2296. chk_onoff10:
  2297. pop di ; Remove Old String address
  2298. ret ; and return to caller 
  2299. atohex:
  2300. ;------
  2301. ; To convert a hex number in the form of an ASCII string to a 32 bit 
  2302. ; integer.
  2303. ;
  2304. ; On Entry:
  2305. ; DS:SI -> ASCII hex number 
  2306. ;  (the end of the number is taken as the first non-digit)
  2307. ; On Exit:
  2308. ; CY clear:
  2309. ; DX:AX = converted number
  2310. ; ds:si -> first non-digit
  2311. ;
  2312. ; CY set:
  2313. ; Either the first character was not a digit
  2314. ; or the number could not be represented in 32 bits
  2315. ; ds:si -> point at which error occured
  2316. ; ax undefined
  2317. ; Lost
  2318. ; no other register
  2319. push bx
  2320. push cx
  2321. push di
  2322. call whitespace ; Deblank Line
  2323. mov di,si ; save string start offset
  2324. xor dx,dx
  2325. xor bx,bx ; number is formed in DX:BX
  2326. atohex10:
  2327. lodsb ; AL = next char from string
  2328. call toupper ; upper case it
  2329. cmp al,'A'
  2330.  jb atohex20
  2331. cmp al,'F'
  2332.  ja atohex20
  2333. sub al,'A'-10
  2334. jmps atohex30
  2335. atohex20:
  2336. sub al, '0'
  2337.  jc atohex40 ; stop if invalid character
  2338. cmp al, 9
  2339.  ja atohex40
  2340. atohex30:
  2341. cbw ; AX = digit
  2342. test dh,0f0h ; will we overflow ?
  2343.  jnz atohex_error
  2344. mov cl,4
  2345. push bx ; save (top 4 bits)
  2346. shl bx,cl ; *16
  2347. add bx,ax ; add in new digit
  2348. pop ax
  2349. rol ax,cl ; top 4 bits to bottom 4 bits
  2350. and ax,000Fh ; isolate them
  2351. shl dx,cl
  2352. add dx,ax ; add in new digit
  2353. jmp atohex10
  2354. atohex40:
  2355. dec si ; forget the char we stopped on
  2356. cmp si, di ; was there at least one digit?
  2357.  ja atohex50 ;  yes - exit with carry clear
  2358. atohex_error:
  2359. stc ; set error flag
  2360. atohex50:
  2361. xchg ax,bx ; AX = result
  2362. pop di
  2363. pop cx
  2364. pop bx
  2365. ret
  2366. atoi:
  2367. ;----
  2368. ; To convert a decimal number in the form of an ASCII string to a 16 bit 
  2369. ; integer.
  2370. ;
  2371. ; Entry
  2372. ; ds:si -> ASCII decimal number 
  2373. ;  (the end of the number is taken as the first non-digit)
  2374. ; Exit
  2375. ; Carry clear:
  2376. ; ax = converted number
  2377. ; ds:si -> first non-digit
  2378. ;
  2379. ; Carry set:
  2380. ; Either the first character was not a digit
  2381. ; or the number could not be represented in 16 bits
  2382. ; ds:si -> point at which error occured
  2383. ; ax undefined
  2384. ; Lost
  2385. ; no other register
  2386. push bx ! push cx
  2387. push dx ! push di
  2388. call whitespace ; Deblank Line
  2389. mov di, si ; save string start offset
  2390. mov cx, 10 ; for multiply
  2391. xor ax, ax ; number is formed in ax
  2392. atoi_loop:
  2393. mov bl, [si] ; bl = next char from string
  2394. sub bl, '0'
  2395. jc atoi_done
  2396. cmp bl, 9
  2397. ja atoi_done
  2398. mov bh, 0 ; bx = next digit
  2399. mul cx ; ax = 10 * ax
  2400. jc exit_atoi ; check for 16 bit overflow
  2401. add ax, bx ; ax = (10 * ax) + bx
  2402. jc exit_atoi
  2403. inc si ; ds:si -> next char in string
  2404. jmp atoi_loop
  2405. atoi_done:
  2406. cmp si, di ; was there at least one digit?
  2407. jne exit_atoi ;  yes - exit with carry clear
  2408. stc ;  no - set error flag
  2409. exit_atoi:
  2410. pop di ! pop dx
  2411. pop cx ! pop bx
  2412. ret
  2413. atol:
  2414. ;----
  2415. ; To convert a decimal number in the form of an ASCII string to a 32 bit 
  2416. ; integer.
  2417. ;
  2418. ; Entry
  2419. ; ds:si -> ASCII decimal number 
  2420. ;  (the end of the number is taken as the first non-digit)
  2421. ; Exit
  2422. ; CY clear:
  2423. ; DX:AX = converted number
  2424. ; ds:si -> first non-digit
  2425. ;
  2426. ; CY set:
  2427. ; Either the first character was not a digit
  2428. ; or the number could not be represented in 32 bits
  2429. ; ds:si -> point at which error occured
  2430. ; ax undefined
  2431. ; Lost
  2432. ; no other register
  2433. push bx
  2434. push cx
  2435. push di
  2436. call whitespace ; Deblank Line
  2437. mov di, si ; save string start offset
  2438. xor ax, ax ; number is formed in
  2439. cwd ;  DX/AX
  2440. atol10:
  2441. xor bx,bx ; use CX/BX for next digit
  2442. xor cx,cx
  2443. mov bl,[si] ; BL = next char from string
  2444. sub bl,'0'
  2445.  jc atol20
  2446. cmp bl, 9 ; validate digit
  2447.  ja atol20
  2448. add ax,ax
  2449. adc dx,dx ; * 2
  2450.  jc atol30
  2451. add bx,ax ; * 2 + new digit
  2452. adc cx,dx
  2453.  jc atol30
  2454. add ax,ax
  2455. adc dx,dx ; * 4
  2456.  jc atol30
  2457. add ax,ax
  2458. adc dx,dx ; * 8
  2459.  jc atol30
  2460. add ax,bx ; * 10 + new digit
  2461. add dx,cx
  2462.  jc atol30
  2463. inc si ; ds:si -> next char in string
  2464. jmp atol10
  2465. atol20:
  2466. cmp si,di ; was there at least one digit?
  2467.  jne atol30 ;  yes - exit with carry clear
  2468. stc ;  no - set error flag
  2469. atol30:
  2470. pop di
  2471. pop cx
  2472. pop bx
  2473. ret
  2474. readline:
  2475. ;--------
  2476. ; On Entry:
  2477. ; None
  2478. ; On Exit:
  2479. ; DS:SI -> line in buffer
  2480. ; CY set if we have a problem (eg at EOF)
  2481. ;
  2482. mov cx,CFG_BUF_LEN-2 ; Read the next command line
  2483. mov di,offset cfg_buffer ; into the CFG_BUFFER
  2484. mov si,di ; Save the Destination String
  2485. ; address
  2486. read_l10:
  2487. call getchar ; al = next char from file
  2488. cmp al,CR ! jz read_l10 ; end of line ?
  2489. cmp al,LF ! jz read_l10 ; end of line ?
  2490. cmp al,EOF ! jne read_l20 ; end of file ?
  2491. stc ; indicate a problem
  2492. ret
  2493. read_l20:
  2494. stosb ; put next char into the buffer
  2495. call getchar ; al = next char from file
  2496. cmp al,EOF ! jz read_l30 ; end of file ?
  2497. cmp al,CR ! jz read_l30 ; end of line ?
  2498. cmp al,LF ! jz read_l30 ; end of line ?
  2499. loop read_l20 ; loop while space remains
  2500. ; If we fall through to this point the line is too long. Make it a comment.
  2501. mov di, si ; ds:di -> start of buffer
  2502. mov  al, ';'
  2503. stosb ; place ';' at buffer start
  2504. mov cx, 1 ; get another one character
  2505. jmps read_l20 ; loop until all of this line consumed
  2506. ; At this point buffer contains a line of text from CCONFIG.SYS.
  2507. ; Terminate it properly
  2508. read_l30:
  2509. mov al,CR ! stosb ; terminate line with CR
  2510. mov al,LF ! stosb ; and a LF
  2511. xor al,al ! stosb ; Reset the Carry Flag
  2512. ret
  2513. getchar:
  2514. mov bx,cfg_head ; we are here in the buffer
  2515. cmp bx,cfg_tail ; are there any more characters ?
  2516.  jae getchar10 ; no, read some in from disk
  2517. push ds
  2518. mov ds,init_dseg
  2519. mov al,CONFIG_BUF[bx] ; get a character from the buffer
  2520. pop ds
  2521. inc cfg_head ; inc the pointer
  2522. ret
  2523. getchar10:
  2524. ; we need to read some characters from disk into our buffer
  2525. push cx ! push dx ; Assume something will go wrong
  2526. mov cfg_tail,0 ;  say nothing is in the buffer
  2527. mov ax,(MS_X_OPEN*256)+80h ; Open the configuration file
  2528. mov dx,offset cfg_file
  2529. int DOS_INT
  2530.  jc getchar40 ; failure, return EOF
  2531. mov bx,ax
  2532. mov ax,(MS_X_LSEEK*256)+0
  2533. mov dx,cfg_seeklo
  2534. mov cx,cfg_seekhi
  2535. int DOS_INT ; seek to current file position
  2536.  jc getchar30 ; failure to seek, close and exit
  2537. mov ah,MS_X_READ
  2538. mov cx,CONFIG_BUF_SIZE
  2539. push ds
  2540. mov ds,init_dseg
  2541. mov dx,offset CONFIG_BUF ; lets try and fill out buffer
  2542. int DOS_INT
  2543. pop ds
  2544.  jc getchar30
  2545. mov cfg_tail,ax
  2546. mov ax,(MS_X_LSEEK*256)+1
  2547. xor dx,dx
  2548. xor cx,cx
  2549. int DOS_INT ; get current file position
  2550. mov cfg_seeklo,ax ;  and save for possible
  2551. mov cfg_seekhi,dx ;  future re-opens
  2552. getchar30:
  2553. mov ah,MS_X_CLOSE ; Close the CONFIG file
  2554. int DOS_INT
  2555. getchar40:
  2556. mov bx,cfg_tail ; now lets see if we filled the buffer
  2557. cmp bx,CONFIG_BUF_SIZE ;  if not its EOF so mark it as such
  2558.  je getchar50
  2559. push ds
  2560. mov ds,init_dseg
  2561. mov CONFIG_BUF[bx],EOF ; add an EOF mark
  2562. pop ds ;  in case there isn't one already
  2563. inc cfg_tail
  2564. inc cfg_seeklo
  2565.  jnz getchar50
  2566. inc cfg_seekhi
  2567. getchar50:
  2568. push ds
  2569. mov ds,init_dseg
  2570. mov al,CONFIG_BUF ; return 1st char from buffer
  2571. pop ds
  2572. mov cfg_head,1 ; remember we have returned char
  2573. pop dx ! pop cx
  2574. ret
  2575. ;
  2576. ; On a DEVICEHIGH we have encountered a line
  2577. ; /L:r1[,s1][;r2[,s2]]... [/S]
  2578. ; where r1 = load region, s1 = hex size in bytes, r2,s2 etc are further regions
  2579. ; currently only r1/s1 are supported
  2580. ; /S says the regions should m#be minimised
  2581. parse_region:
  2582. ;On Entry:
  2583. ; DS:SI -> command line following '/L:'
  2584. ; On Exit:
  2585. ; DS:SI -> 1st non-parsed character
  2586. ; CY set on error
  2587. ;
  2588. call atoi ; get a region to load in
  2589.  jc parse_region40
  2590. mov himem_region,ax ; remember region to try
  2591. call whitespace ; scan off all white space
  2592. lodsb ! dec si ; now see is we have an optional size
  2593. cmp al,',' ; have we a ',' character ?
  2594. mov ax,0 ; assume minimum size not supplied
  2595.  jne parse_region30
  2596. inc si
  2597. call atol ; read number into DX:AX
  2598. cmp dx,15 ; is number too big ?
  2599.  ja parse_region40
  2600. mov cx,16 ; convert to para's
  2601. div cx
  2602. inc ax ; allow for round up
  2603. inc ax ;  and for header
  2604. push ax ; save size of region
  2605. parse_region10:
  2606. mov di,offset slashs_opt ; do we have a "/S" to minimise
  2607. call compare ;  the UMB's (ignore it if so)
  2608.  jnc parse_region20
  2609. call whitespace ; scan off all white space
  2610. lodsb ! dec si ; strip off other regions
  2611. cmp al,';' ; another region follows ';'
  2612.  jne parse_region20
  2613. inc si
  2614. call atoi ; eat the region number
  2615.  jc parse_region20
  2616. call whitespace ; scan off all white space
  2617. lodsb ! dec si
  2618. cmp al,',' ; is a size specified ?
  2619.  jne parse_region10 ; no, check for another region
  2620. inc si
  2621. call atol ; eat the size
  2622.  jnc parse_region10
  2623. parse_region20:
  2624. pop ax
  2625. parse_region30:
  2626. clc ; we can proceed
  2627. ret
  2628. parse_region40:
  2629. mov himem_size,0FFFFh ; 1 MByte wanted (ho, ho)
  2630. stc ; we had problems..
  2631. ret
  2632. ; On a DEVICEHIGH we may encounter a line
  2633. ; SIZE [=] s
  2634. ; where s = size of region in hex bytes
  2635. parse_size:
  2636. ;On Entry:
  2637. ; DS:SI -> command line following '/L:'
  2638. ; On Exit:
  2639. ; DS:SI -> 1st non-parsed character
  2640. ; CY set on error
  2641. ;
  2642. call whitespace ; Scan off all white space
  2643. lodsb ; before and after the optional
  2644. cmp al,'=' ; '=' character.
  2645.  je parse_size
  2646. dec si
  2647. call atohex ; read hex number into DX:AX
  2648.  jc parse_size10
  2649. cmp dx,15 ; is number too big ?
  2650.  ja parse_size20 ; just load low
  2651. mov cx,16 ; convert to para's
  2652. div cx
  2653. inc ax ; allow for round up
  2654. inc ax ;  and for header
  2655. mov himem_size,ax ; remember size required
  2656. parse_size10:
  2657. clc
  2658. ret
  2659. parse_size20:
  2660. mov himem_size,0FFFFh ; 1 MByte wanted (ho, ho)
  2661. stc
  2662. ret
  2663. ; A size has not been suppleied with DEVICEHIGH, so guess-timate one
  2664. ; based on file size
  2665. size_file:
  2666. ; On Entry:
  2667. ; DS:SI -> filename
  2668. ; On Exit:
  2669. ; DS:SI preserved
  2670. ;
  2671. push si
  2672. mov di,offset dev_name ; copy the device filename into a
  2673. mov byte ptr [di],0 ;  local buffer and zero terminate
  2674. call copy_file
  2675. pop si
  2676. mov ax,(MS_X_OPEN * 256)+0 ; open file r/o
  2677. mov dx,offset dev_name
  2678. int DOS_INT
  2679.  jnc size_file10
  2680. mov ax,0FFFFh ; can't open file, force low to prevent
  2681. ret ;  two sets of error messages
  2682. size_file10:
  2683. xchg ax,bx ; handle in BX
  2684. mov ah,MS_X_READ
  2685. mov cx,EXE_LENGTH
  2686. mov dx,offset exeBuffer
  2687. int DOS_INT ; read in possible exe header
  2688.  jc size_file20
  2689. cmp ax,cx ; did we read all we wanted ?
  2690.  jb size_file40 ; if not it can't be an EXE
  2691. cmp exeSignature,'ZM' ; check the signature
  2692.  jne size_file40 ; if invalid can't be an EXE
  2693. mov ax,512
  2694. mul exeSize ; DX/AX bytes in image
  2695. add ax,exeFinal
  2696. adc dx,0
  2697. mov cx,16
  2698. cmp dx,cx ; are we too big ?
  2699.  jae size_file20 ; yes, force low
  2700. div cx ; AX = para's required
  2701. inc ax ; one for rounding error
  2702.  jz size_file20
  2703. add ax,exeMinpara ; add on extra para's required
  2704.  jnc size_file30
  2705. size_file20:
  2706. mov ax,0FFFFh ; problems, force a load low
  2707. size_file30:
  2708. push ax ; save para's required
  2709. mov ah,MS_X_CLOSE ; close this file
  2710. int DOS_INT
  2711. pop ax ; AX para's required
  2712. ret
  2713. size_file40:
  2714. mov ax,(MS_X_LSEEK * 256)+2
  2715. xor cx,cx ; now find out how big the file is
  2716. xor dx,dx ;  by seeking to zero bytes from end
  2717. int DOS_INT
  2718.  jc size_file20
  2719. mov cx,16
  2720. cmp dx,cx ; are we too big ?
  2721.  jae size_file20 ; yes, force low
  2722. div cx ; AX = para's required
  2723. inc ax ; one for rounding error
  2724. jmps size_file30
  2725. himem_setup:
  2726. ; On Entry:
  2727. ; AX = minimum amount of upper memory required (in para's)
  2728. ; On Exit:
  2729. ; CY clear if able to satisfy request
  2730. ; CY set on error (we then load low)
  2731. ;
  2732. ; try and find some hi memory
  2733. ; we allocate the biggest available chunk of upper memory
  2734. ;
  2735. push es
  2736. mov cx,ax ; CX = para's required
  2737. mov ax,mem_current_base
  2738. mov himem_current_base,ax ; save mem_current_base
  2739. mov ax,mem_current
  2740. mov himem_current,ax ; save mem_current
  2741. mov ax,mem_max
  2742. mov himem_max,ax ; save mem_max
  2743. mov ah,MS_M_ALLOC
  2744. mov bx,0FFFFh ; give me all memory (please)
  2745. int 21h ; bx = No. of paras available
  2746. cmp bx,cx ; do we have enough ?
  2747.  jc himem_setup40 ; no, give up now
  2748. cmp himem_region,0 ; is there a region specified ?
  2749.  je himem_setup20 ; no, allocate largest block
  2750. ; Allocate the region specified by /L:
  2751. les bx,func52_ptr ; ES:BX -> list of lists
  2752. mov ax,es:F52_DMD_UPPER[bx] ; get upper memory link
  2753. cmp ax,0FFFFh ; make sure there is one
  2754.  je himem_setup20 ; shouldn't happen....
  2755. mov es,ax
  2756. himem_setup10:
  2757. cmp es:DMD_ID,'M' ; is there another block ?
  2758. stc ; if we run out of blocks then
  2759.  jne himem_setup40 ;  we load low
  2760. mov es,ax ; ES -> DMD
  2761. mov bx,es:DMD_LEN ; get length in para'a
  2762. inc ax
  2763. add ax,bx ; AX -> next DMD
  2764. cmp es:DMD_PSP,0 ; is it free ?
  2765.  jne himem_setup10 ; no, try the next
  2766. dec himem_region ; found the right region yet ?
  2767.  jnz himem_setup10
  2768. cmp bx,cx ; do we have enough ?
  2769.  jc himem_setup40 ; no, go low
  2770. mov ax,es ; ES -> DMD header to allocate
  2771. inc ax
  2772. mov es,ax ; ES -> data in block
  2773. mov ah, MS_M_SETBLOCK
  2774. int 21h ; "allocate" this block
  2775. mov ax,es
  2776.  jnc himem_setup30 ; this can only fail if DMD chain
  2777. jmps himem_setup40 ;  is corrupt...
  2778. himem_setup20:
  2779. ; allocate the largest block available for DEVICEHIGH
  2780. mov ah, MS_M_ALLOC
  2781. mov bx, 0FFFFh ; give me all memory (please)
  2782. int 21h ; bx = No. of paras available
  2783. mov ah, MS_M_ALLOC ; give me bx paras please
  2784. int 21h ; ax:0 -> my memory
  2785.  jc himem_setup40 ; woops, what happened ?
  2786. himem_setup30:
  2787. mov mem_current_base,ax
  2788. mov mem_current,ax ; save base of himem area
  2789. mov mem_max,ax
  2790. add mem_max,bx ; top of himem area
  2791. himem_setup40:
  2792. pop es
  2793. ret
  2794. himem_cleanup:
  2795. ; clean up our high memory - this hook should free up any difference
  2796. ; between himem_current and himem_max
  2797. mov ax,himem_max
  2798. mov mem_max,ax ; restore mem_max
  2799. mov ax,himem_current_base
  2800. xchg mem_current_base,ax ; restore mem_current_base
  2801. mov bx,himem_current
  2802. xchg mem_current,bx ; restore mem_current
  2803. push es
  2804. mov es,ax ; ES -> memory block
  2805. sub bx,ax ; has any memory been used ?
  2806.  jz himem_cleanup10
  2807. mov ah,MS_M_SETBLOCK ; try and shrink the block
  2808. int DOS_INT ; to the size we used
  2809. pop es
  2810. ; clc ; return success
  2811. ret
  2812. himem_cleanup10:
  2813. mov ah,MS_M_FREE ; free it all up
  2814. int DOS_INT
  2815. pop es
  2816. stc ; return an error
  2817. ret
  2818. copy_asciiz:
  2819. ;-----------
  2820. lodsb ; get a character
  2821. stosb ; copy it
  2822. test al,al ; is it the terminating NUL ?
  2823.  jnz copy_asciiz ; do next char
  2824. ret
  2825. wait_for_key:
  2826. ;------------
  2827. ; On Entry:
  2828. ; None
  2829. ; On Exit:
  2830. ; CY set if no key pressed within timeout
  2831. ;
  2832. mov cx,keyb_timeout ; get timeout value
  2833. clc ; assume no timeout
  2834.  jcxz wait_for_key30
  2835. wait_for_key10:
  2836. push cx
  2837. mov ah,MS_T_GETTIME ; get current time
  2838. int DOS_INT ;  so we can do timeout
  2839. mov bx,dx ;  save secs in BH
  2840. pop cx
  2841. wait_for_key20:
  2842. mov ah,MS_C_STAT ; is a character ready ?
  2843. int DOS_INT ; if so process it
  2844. test al,al ; do we have a character ?
  2845.  jnz wait_for_key30
  2846. push cx
  2847. mov ah,MS_T_GETTIME ; get current time
  2848. int DOS_INT ;  so we can do timeout
  2849. pop cx
  2850. cmp bh,dh ; have we timed out ?
  2851.  je wait_for_key20
  2852. loop wait_for_key10 ; another second gone by
  2853. stc ; we have timed out
  2854. wait_for_key30:
  2855. ret
  2856. ;
  2857. ; COPY_FILE copies the next parameter from DS:SI into the buffer
  2858. ; at ES:DI and terminates with a NULL character. The parameter is
  2859. ; expected to be a FileName. DS:SI are returned pointing to the 
  2860. ; next parameter in the command.
  2861. ;
  2862. copy_file:
  2863. call whitespace ; DeBlank the Command Line
  2864. mov cx,MAX_FILELEN ; Limit FileName Length
  2865. push si ; Save SI in case of error
  2866. copy_f10:
  2867. lodsb ; Copy upto the first Space or 
  2868. cmp al,' ' ; Control Character
  2869.  jbe copy_f20
  2870. cmp al,',' ; stop at ',' too
  2871.  je copy_f20
  2872. cmp al,'/' ; Also stop scanning when a switch 
  2873.  je copy_f20 ; character is detected
  2874. stosb
  2875. loop copy_f10
  2876. pop si ; Restore the original SI
  2877. mov ax,13 ; 13 = invalid data error
  2878. stc ; and return with an error
  2879. ret
  2880. copy_f20:
  2881. pop ax ; Remove Original String address
  2882. dec si ; Point at the failing character 
  2883. xor ax,ax
  2884. stosb ; Zero Terminate FileName
  2885. ret
  2886. INITDATA DSEG 'INITDATA'
  2887. if ADDDRV
  2888. extrn err_no_command_file:byte
  2889. extrn err_block_device:byte
  2890. else
  2891. extrn shell:byte ; Default Command Processor
  2892. extrn shell_cline:byte ; Default Command Line
  2893. endif
  2894. extrn dev_epb:byte
  2895. extrn dev_count:byte
  2896. extrn rel_unit:word
  2897. extrn dos_target_seg:word
  2898. extrn bios_target_seg:word
  2899. extrn mem_current_base:word ; Current Base Address
  2900. extrn mem_current:word ; Current Load Address
  2901. extrn mem_max:word ; Top of Available Memory
  2902. extrn mem_size:word ; Real top of Memory
  2903. extrn init_dseg:word ; Current Init Data Segment
  2904. include initmsgs.def ; Include TFT Header File
  2905. ; extrn bad_command:byte
  2906. ; extrn bad_filename:byte
  2907. if not ADDDRV
  2908. ; extrn bad_shell:byte
  2909. ; extrn bad_country:byte
  2910. ; extrn bad_lastdrive:byte
  2911. ; extrn bad_break:byte
  2912. ; extrn bad_buffers:byte
  2913. ; extrn bad_files:byte
  2914. ; extrn bad_fcbs:byte
  2915. ; extrn bad_fopen:byte
  2916. ; extrn bad_drivparm:byte
  2917. ; extrn bad_history:byte
  2918. endif
  2919. ; extrn yes_char:byte ; In BIOSMSGS.ASM
  2920. ; extrn no_char:byte
  2921. extrn dev_load_seg:word
  2922. extrn dev_reloc_seg:word
  2923. extrn dev_epb:byte
  2924. extrn dev_name:byte
  2925. extrn dev_name:byte
  2926. extrn dosVersion:word
  2927. extrn strategy_off:word
  2928. extrn strategy_seg:word
  2929. extrn interrupt_off:word
  2930. extrn interrupt_seg:word
  2931. extrn request_hdr:byte
  2932. extrn next_drv:byte
  2933. extrn strategy_seg:word
  2934. extrn strategy:dword
  2935. extrn interrupt:dword
  2936. extrn func52_ptr:dword
  2937. extrn strategy_seg:word
  2938. extrn condev_off:word
  2939. extrn condev_seg:word
  2940. extrn clkdev_off:word
  2941. extrn clkdev_seg:word
  2942. extrn num_blkdev:byte
  2943. extrn blkdev_table:byte
  2944. extrn last_drv:byte
  2945. extrn next_drv:byte
  2946. extrn max_secsize:word
  2947. extrn max_clsize:word
  2948. extrn country_code:word
  2949. extrn code_page:word
  2950. extrn drdos_ptr:dword
  2951. extrn init_buf:byte
  2952. extrn num_read_ahead_buf:byte
  2953. extrn buffersIn:byte
  2954. extrn num_files:word
  2955. extrn num_fcbs:word
  2956. extrn num_fopen:word
  2957. extrn history_flg:byte ; In INIT code
  2958. extrn history_size:word ;
  2959. extrn num_stacks:word
  2960. extrn stack_size:word
  2961. if not ADDDRV
  2962. extrn hidos:byte
  2963. extrn bios_seg:word
  2964. extrn DeblockSetByUser:Byte
  2965. extrn DeblockSeg:word ; In BIOS data
  2966. endif
  2967. extrn dbcs_tbl:dword
  2968. extrn ctry_info:byte
  2969. Public cfg_file, cfg_file_end
  2970. preload_entry rd 0 ; preload back door entry
  2971. dw 14h ; offset is pre-initialised to 14h
  2972. preload_seg rw 1
  2973. preload_ver dw 10 ; version to give DBLSPACE
  2974. Public preload_drv
  2975. preload_drv db 0 ; number of preload drives
  2976. alt_drive db 0 ; preload checks alternative drive,
  2977. ;   (only used loading from A:)
  2978. ; The preload_file is used as is to open a preload device
  2979. ; It is also used to initialise a "DMD" name, and the code to do this
  2980. ; currently finds the "" and then copies the next 8 characters.
  2981. ; This works with the current names - any new names may require modifications
  2982. preload_file dw offset security_file ; initially 'SECURITY.BIN'
  2983. security_file db 'SECURITY.BIN',0
  2984. stacker_file db 'C:STACKER.BIN',0
  2985. dblspace_file db 'C:DBLSPACE.BIN',0
  2986. cfg_file db 'DCONFIG.SYS',0 ; Configuration File
  2987. rb 64 ; space for bigger CHAIN'd file
  2988. cfg_file_end rb 0
  2989. cfg_seeklo dw 0 ; offset we have reached in CONFIG file
  2990. cfg_seekhi dw 0 ; in case Richards CONFIG file > 64k
  2991. cfg_head dw 0 ; offset we are at in CONFIG_BUF
  2992. cfg_tail dw 0 ; # bytes currently in CONFIG_BUF
  2993. cfg_buffer rb CFG_BUF_LEN ; individual lines live here
  2994. ;
  2995. ; EXEC parameter blocks for INSTALL function
  2996. ;
  2997. exec_envseg rw 1 ; Environment Segment
  2998. exec_lineoff rw 1 ; Command Line Offset
  2999. exec_lineseg rw 1 ; Command Line Segment
  3000. exec_fcb1off rw 1 ; Offset of FCB 1 (5Ch)
  3001. exec_fcb1seg rw 1 ; Segment of FCB 1 (5Ch)
  3002. exec_fcb2off rw 1 ; Offset of FCB 2 (6Ch)
  3003. exec_fcb2seg rw 1 ; Segment of FCB 2 (6Ch)
  3004. rd 2 ; Initial SS:SP & CS:IP
  3005. system_sp rw 1
  3006. system_ss rw 1
  3007. ioctl_pb rb 0
  3008. ioctl_func rb 1 ; special functions
  3009. ioctl_type rb 1 ; device type (form factor)
  3010. ioctl_attrib rw 1 ; device attributes
  3011. ioctl_tracks rw 1 ; # of tracks
  3012. ioctl_mtype rb 1 ; media type, usually zero
  3013. ioctl_bpb rb 31 ; default BPB for this type of disk
  3014. ioctl_layout rw 1+64 ; support 64 sectors/track max.
  3015. drivp_drv rb 1 ; drive 0-15
  3016. drivp_chg rb 1 ; change line support
  3017. drivp_prm rb 1 ; permanent media flag
  3018. drivp_ff rb 1 ; form factor
  3019. drivp_trk dw 80
  3020. drivp_spt equ word ptr ioctl_bpb+13
  3021. drivp_heads equ word ptr ioctl_bpb+15 ; # of heads
  3022. ff_table dw bpb360, bpb1200, bpb720 ; 360/1200/720 Kb
  3023. dw bpb243, bpb1200 ; 8" sd/dd
  3024. dw bpb360, bpb360 ; hard disk, tape
  3025. dw bpb1440 ; 1440 Kb
  3026. bpb360 dw 512
  3027. db 2
  3028. dw 1
  3029. db 2
  3030. dw 112
  3031. dw 40*2*9
  3032. db 0FDh
  3033. dw 2
  3034. dw 9
  3035. dw 2
  3036. bpb1200 dw 512
  3037. db 1
  3038. dw 1
  3039. db 2
  3040. dw 224
  3041. dw 80*2*15
  3042. db 0F9h
  3043. dw 7
  3044. dw 15
  3045. dw 2
  3046. bpb720 dw 512 ; bytes per sector
  3047. db 2 ; sectors/cluster
  3048. dw 1 ; FAT address
  3049. db 2 ; # of FAT copies
  3050. dw 112 ; root directory size
  3051. dw 80*2*9 ; sectors/disk
  3052. db 0F9h ; media byte
  3053. dw 3 ; size of single FAT copy
  3054. dw 9 ; sectors per track
  3055. dw 2 ; # of heads
  3056. bpb1440 dw 512
  3057. db 1
  3058. dw 1
  3059. db 2
  3060. dw 224
  3061. dw 80*2*18
  3062. db 0F9h
  3063. dw 7
  3064. dw 18
  3065. dw 2
  3066. bpb243 dw 128
  3067. db 4
  3068. dw 1
  3069. db 2
  3070. dw 64
  3071. dw 77*1*26
  3072. db 0E5h
  3073. dw 1
  3074. dw 26
  3075. dw 1
  3076. msg_crlf db CR, LF
  3077. msg_dollar db '$'
  3078. CFG_NAME equ word ptr .0000h ; Command Name
  3079. CFG_FUNC equ word ptr .0002h ; Command Subroutine
  3080. CFG_FLAGS equ word ptr .0004h ; Command flags
  3081. CFG_SIZE equ 6 ; Size of each Entry
  3082. CF_NOF equ 0001h ; set if F5/F8 should be ignored
  3083. CF_LC equ 0002h ; set if case should be preserved
  3084. CF_QUERY equ 0004h ; set at run time eg. "DEVICE?"
  3085. cfg_table rw 0
  3086. if not ADDDRV
  3087. dw cmd_country, func_country, 0 ; COUNTRY=nnn,nnn,country
  3088. dw cmd_shell, func_shell, 0 ; SHELL=filename
  3089. dw cmd_lastdrive, func_lastdrive, 0 ; LASTDRIVE=d:
  3090. dw cmd_break, func_break, 0 ; BREAK=ON/OFF
  3091. dw cmd_buffers, func_buffers, 0 ; BUFFERS=nn
  3092. dw cmd_hibuffers, func_hibuffers, 0 ; HIBUFFERS=nn
  3093. dw cmd_fcbs, func_fcbs, 0 ; FCBS=nn
  3094. dw cmd_files, func_files, 0 ; FILES=nn
  3095. dw cmd_stacks, func_stacks, 0 ; STACKS=nn
  3096. dw cmd_fastopen, func_fastopen, 0 ; FASTOPEN=nnn
  3097. dw cmd_drivparm, func_drivparm, 0 ; DRIVPARM=/d:nn ...
  3098. dw cmd_history, func_history, 0 ; HISTORY=ON|OFF,NNN
  3099. dw cmd_hiinstall, func_hiinstall, 0 ; HIINSTALL=cmdstring
  3100. dw cmd_installhigh, func_hiinstall, 0 ; INSTALLHIGH=cmdstring
  3101. dw cmd_install, func_install, 0 ; INSTALL=cmdstring
  3102. dw cmd_hidos, func_hidos, 0 ; HIDOS=ON/OFF
  3103. dw cmd_dos, func_dos, 0 ; DOS=HIGH
  3104. dw cmd_set, func_set, CF_LC ; SET envar=string
  3105. dw cmd_switches, func_switches, CF_NOF ; SWITCHES=...
  3106. endif
  3107. dw cmd_hidevice, func_hidevice, 0 ; HIDEVICE=filename
  3108. dw cmd_devicehigh, func_hidevice, 0 ; DEVICEHIGH=filename
  3109. dw cmd_device, func_device, 0 ; DEVICE=filename
  3110. dw cmd_remark, func_remark, CF_NOF ; REM Comment
  3111. dw cmd_semicolon, func_remark, CF_NOF ; ; Comment
  3112. dw cmd_colon, func_remark, CF_NOF ; :label
  3113. dw cmd_chain, func_chain, 0 ; CHAIN=filename
  3114. dw cmd_goto, func_goto, 0 ; GOTO=label
  3115. dw cmd_gosub, func_gosub, 0 ; GOSUB=label
  3116. dw cmd_return, func_return, 0 ; RETURN (from GOSUB)
  3117. dw cmd_cls, func_cls, 0 ; Clear Screen
  3118. dw cmd_cpos, func_cpos, 0 ; Set Cursor Position
  3119. dw cmd_timeout, func_timeout, 0 ; set ? TIMEOUT
  3120. dw cmd_switch, func_switch, 0 ; SWITCH=n
  3121. dw cmd_onerror, func_onerror, CF_LC ; ONERROR='n' optional command
  3122. dw cmd_query, func_query, CF_NOF+CF_LC; ?optional command
  3123. dw cmd_echo, func_echo, CF_LC ; ECHO=string
  3124. dw cmd_exit, func_exit, 0 ; EXIT
  3125. dw cmd_error, func_error, 0 ; ERROR='n'
  3126. dw cmd_getkey, func_getkey, 0 ; GETKEY
  3127. dw cmd_yeschar, func_yeschar, 0 ; YESCHAR=
  3128. dw cmd_deblock, func_deblock, 0 ; DEBLOCK=xxxx
  3129. dw cmd_numlock, func_numlock, 0 ; NUMLOCK=ON/OFF
  3130. dw cmd_common, func_common, 0 ; [COMMON]
  3131.   dw 0 ; end of table
  3132. if not ADDDRV
  3133. cmd_country db 'COUNTRY',0
  3134. cmd_shell db 'SHELL',0
  3135. cmd_lastdrive db 'LASTDRIVE',0
  3136. cmd_break db 'BREAK',0
  3137. cmd_buffers db 'BUFFERS',0
  3138. cmd_hibuffers db 'HIBUFFERS',0
  3139. cmd_fcbs db 'FCBS',0
  3140. cmd_files db 'FILES',0
  3141. cmd_stacks db 'STACKS',0
  3142. cmd_fastopen db 'FASTOPEN',0
  3143. cmd_drivparm db 'DRIVPARM', 0
  3144. cmd_history db 'HISTORY', 0
  3145. cmd_install db 'INSTALL', 0
  3146. cmd_hiinstall db 'HIINSTALL', 0
  3147. cmd_installhigh db 'INSTALLHIGH', 0
  3148. cmd_hidos db 'HIDOS',0
  3149. cmd_dos db 'DOS',0
  3150. cmd_set db 'SET',0
  3151. cmd_switches db 'SWITCHES',0
  3152. endif
  3153. cmd_hidevice db 'HIDEVICE',0
  3154. cmd_devicehigh db 'DEVICEHIGH',0
  3155. cmd_device db 'DEVICE',0
  3156. cmd_remark db 'REM', 0
  3157. cmd_semicolon db ';',0
  3158. cmd_colon db ':',0
  3159. cmd_chain db 'CHAIN',0
  3160. cmd_goto db 'GOTO',0
  3161. cmd_gosub db 'GOSUB',0
  3162. cmd_return db 'RETURN',0
  3163. cmd_cls db 'CLS',0
  3164. cmd_cpos db 'CPOS',0
  3165. cmd_timeout db 'TIMEOUT',0
  3166. cmd_switch db 'SWITCH',0
  3167. cmd_onerror db 'ONERROR',0
  3168. cmd_query db '?',0
  3169. cmd_echo db 'ECHO',0
  3170. cmd_exit db 'EXIT',0
  3171. cmd_error db 'ERROR',0
  3172. cmd_getkey db 'GETKEY',0
  3173. cmd_yeschar db 'YESCHAR',0
  3174. cmd_deblock db 'DEBLOCK',0
  3175. cmd_numlock db 'NUMLOCK',0
  3176. cmd_common db '[COMMON]',0
  3177. cmd_on db 'ON',0
  3178. cmd_off db 'OFF',0
  3179. confirm_msg1 db ' ($'
  3180. confirm_msg2 db ') ? $'
  3181. confirm_msg3 db CR,LF,'$'
  3182. region_opt db '/L:',0
  3183. slashs_opt db '/S',0
  3184. size_opt db 'SIZE',0
  3185. high_opt db 'HIGH',0
  3186. low_opt db 'LOW',0
  3187. umb_opt db 'UMB',0
  3188. noumb_opt db 'NOUMB',0
  3189. himem_region dw 0 ; region to hidevice into
  3190. himem_size dw 0 ; minimum size wanted
  3191. himem_current dw 0
  3192. himem_current_base dw 0
  3193. himem_max dw 0
  3194. if ADDDRV
  3195. error_flag db 0 ;1 if error occurred during command
  3196. ;file processing, 0 otherwise
  3197. endif
  3198. default_query_char db CR
  3199. default_switch_char db '1'
  3200. keyb_timeout dw 0 ; default is no timeout
  3201. error_level dw 0 ; default is no error
  3202. save_sp dw 0 ; save SP here for GOSUB/RETURN's
  3203. INITENV DSEG PARA 'INITDATA'
  3204. envstart rb 253 ; initial env buffer
  3205. envend dw 0 ; make it double null terminated
  3206. db 1Ah ; EOF marker env buffer
  3207. Public boot_options
  3208. boot_options dw 0
  3209. ; set by BIOS to either the SHIFT states, or to F5KEY or F8KEY
  3210. EXE_LENGTH equ 001Ch
  3211. exeBuffer rw 0
  3212. exeSignature dw 0 ; 0000 Valid EXE contains 'MZ'
  3213. exeFinal dw 0 ; 0002 Image Length MOD 512
  3214. exeSize dw 0 ; 0004 Image Length DIV 512
  3215. exeRelcnt dw 0 ; 0006 No. of Relocation Items
  3216. exeHeader dw 0 ; 0008 Header Size in paragraphs
  3217. exeMinpara dw 0 ; 000A Minimum No extra paragraphs
  3218. exeMaxpara dw 0 ; 000C Maximum No of extra paragraphs
  3219. exeSS dw 0 ; 000E Displacment of Stack Segment
  3220. exeSP dw 0 ; 0010 Initial SP
  3221. exeChecksum dw 0 ; 0012 Negative CheckSum
  3222. exeIP dw 0 ; 0014 Initial IP
  3223. exeCS dw 0 ; 0016 Code Segment displacement
  3224. exeReloff dw 0 ; 0018 Byte Offset of First REL item
  3225. exeOverlay dw 0 ; 001A Overlay Number (0 == Resident)
  3226. end