home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / pcmagazi / 1992 / 09 / bd.asm < prev    next >
Assembly Source File  |  1992-04-22  |  239KB  |  5,856 lines

  1.             page    55,132
  2.             title   "BACKDOWN - Background Download Program"
  3.  
  4. ; ---------------------------------------------------------------------
  5. ;
  6. ; Maintenance Log
  7. ;
  8. ; Version    Date   Description                        Who
  9. ; -------  -------  ---------------------------------- ----------------
  10. ;   1.0    08Feb91  Initial version complete           Flanders/Holmes
  11. ;
  12. ; ---------------------------------------------------------------------
  13.  
  14.  
  15. mainline    segment para 'CODE'             ; mainline
  16.             assume  cs:mainline, ds:mainline, es:mainline, ss:mainline
  17.             org     100h
  18. begin:      jmp     start                   ; start processing
  19.  
  20.  
  21. VERSN       equ     "1.0"                   ; Version
  22.  
  23. ; ---------------------------------------------------------------------
  24. ;   macros
  25. ; ---------------------------------------------------------------------
  26.  
  27. CALLDI      macro
  28.             db      0ffh, 0d7h              ; call near ptr di
  29.             endm
  30.  
  31. ; ---------------------------------------------------------------------
  32. ;   interrupt vector control
  33. ; ---------------------------------------------------------------------
  34.  
  35. intblkcnt   =       7                       ; number of int routines
  36. intblklen   =       15                      ; length of blocks
  37. intblk1     equ     offset oldint13         ; first to fill in
  38.  
  39. oldint13    dd      0                       ; old cs:ip
  40. oldss13     dd      0                       ; ss:sp when int invoked
  41. newss13     dd      0                       ; work stack during int
  42.             db      13h                     ; interrupt to take over
  43.             dw      offset int13            ; new interrupt routine
  44.  
  45. oldint2f    dd      0                       ; old cs:ip
  46. oldss2f     dd      0                       ; ss:sp when int invoked
  47. newss2f     dd      0                       ; work stack during int
  48.             db      2fh                     ; interrupt to take over
  49.             dw      offset int2f            ; new interrupt routine
  50.  
  51. oldint09    dd      0                       ; old cs:ip
  52. oldss09     dd      0                       ; ss:sp when int invoked
  53. newss09     dd      0                       ; work stack during int
  54.             db      09h                     ; interrupt to take over
  55.             dw      offset int09            ; new interrupt routine
  56.  
  57. oldint08    dd      0                       ; old cs:ip
  58. oldss08     dd      0                       ; ss:sp when int invoked
  59. newss08     dd      0                       ; work stack during int
  60.             db      08h                     ; interrupt to take over
  61.             dw      offset int08            ; new interrupt routine
  62.  
  63. oldint28    dd      0                       ; old cs:ip
  64. oldss28     dd      0                       ; ss:sp when int invoked
  65. newss28     dd      0                       ; work stack during int
  66.             db      28h                     ; interrupt to take over
  67.             dw      offset int28            ; new interrupt routine
  68.  
  69.             dd      0                       ; old cs:ip (comm interrupt)
  70.             dd      0                       ; ss:sp when int invoked
  71.             dd      0                       ; work stack during int
  72. hd_int      db      0                       ; interrupt to take over
  73.             dw      offset bd_int           ; new interrupt routine
  74.  
  75. oldint10    dd      0                       ; old cs:ip
  76. oldss10     dd      0                       ; ss:sp when int invoked
  77. newss10     dd      0                       ; work stack during int
  78.             db      10h                     ; interrupt to take over
  79.             dw      offset int10            ; new interrupt routine
  80.  
  81. oldss       dw      0                       ; caller's stack segment
  82. oldsp       dw      0                       ; ..and offset
  83.  
  84. ; ---------------------------------------------------------------------
  85. ;   TSR work variables, etc.
  86. ; ---------------------------------------------------------------------
  87.  
  88. nxtavail    dw      mem_end                 ; next available byte
  89. startclr    dw      0                       ; addr to start mem clear
  90. clrlen      dw      0                       ; length to clear
  91.  
  92. psp_seg     dw      0                       ; segment of our psp
  93. dos_busy    dd      0                       ; addr of dos busy flag
  94. i28hflag    db      0                       ; used by DOS Waiting rtn
  95. intsbusy    db      0                       ; interrupts busy flag
  96. i08hflg     dw      0                       ; int 08 in use
  97.  
  98. NCHARS      =       10                      ; Number of chars/dispatch
  99. chars_disp  dw      NCHARS                  ; .. set the work word
  100.  
  101. tsr_active  db      0                       ; tsr pop'd up flag
  102. tsr_req     db      0                       ; tsr requested flag
  103. main_active db      1                       ; main rtn entered
  104.  
  105. io_base     dw      1                       ; base port address
  106. io_int      db      0                       ; ..and interrupt
  107. dos_rc      db      1                       ; dos return code
  108.  
  109.             db      "Hot key>"              ; visual ptr for hot key
  110. shift_mask  db      0ch                     ; ..and shift mask
  111.                                             ; .... ...1 right shift
  112.                                             ; .... ..1. left shift
  113.                                             ; .... .1.. control key
  114.                                             ; .... 1... alt key
  115. hot_key     db      30h                     ; scan code of hotkey (B)
  116.  
  117. multiplex   dw      0c000h                  ; multiplex id for int 2fh
  118. tsr_loaded  dw      0                       ; segment of TSR portion
  119.  
  120. scriptf_len =       64                      ; length of filename field
  121. scriptfile  db      scriptf_len dup (0)     ; startup script filename
  122.  
  123. main_state  dw      0                       ; current state
  124. main_table  dw      bd_trm                  ; 0 = terminal mode
  125.             dw      bd_dnld                 ; 2 = download from terminal mode
  126.             dw      exec_script             ; 4 = running a script
  127.             dw      bd_dnld                 ; 6 = download from a script
  128.  
  129. bd_userdata db      10 dup (0)              ; B+ user data
  130. bd_bstring  db      "B", 0, 0               ; B+ dl startup string
  131. bd_bpinit   db      10h, '++', 10h, '0'     ; ENQ response string
  132.  
  133. ; ---------------------------------------------------------------------
  134. ;   protocol file management
  135. ; ---------------------------------------------------------------------
  136.  
  137. fileinfo    struc                           ; find first/next structure
  138. fiReserved  db      21 dup (0)              ; reserved
  139. fiAttr      db      0                       ; attribute
  140. fiTime      dw      0                       ; time last mod
  141. fiDate      dw      0                       ; date last mod
  142. fiSize      dd      0                       ; length of file
  143. fiName      db      13 dup (0)              ; name of file
  144. fileinfo    ends
  145.  
  146. bdprot      struc                           ; protocol structure
  147. bdpchar     db      0                       ; invocation charcter
  148. bdpname     db      17 dup (0)              ; protocol name
  149. bdpnbr      db      0                       ; protocol nbr in module
  150. bdpfile     db      65 dup (0)              ; protocol file name
  151. bdprot      ends
  152.  
  153. bdprotlen   =       84                      ; entry length
  154.  
  155. ; ---------------------------------------------------------------------
  156. ;   download protocol interface items
  157. ; ---------------------------------------------------------------------
  158.  
  159. bd_work     dw      0                       ; work register save area
  160. bd_isi      dw      0                       ; incoming string pointer
  161. bd_state    dw     -2                       ; current download state
  162.  
  163.                                             ; download interface states
  164.             dw      bd_gstringx             ; -8 get a string (part II)
  165.             dw      bd_ok                   ; -6 last request succeeded
  166.             dw      bd_failed               ; -4 last request failed
  167.             dw      bd_init                 ; -2 initialize protocol
  168. bd_table    dw      bd_call                 ;  0 call download
  169.             dw      bd_open                 ;  2 open an output file
  170.             dw      bd_write                ;  4 write a file
  171.             dw      bd_close                ;  6 close a file
  172.             dw      bd_delete               ;  8 delete file
  173.             dw      bd_done                 ; 10 finished w/protocol
  174.             dw      bd_dstring              ; 12 display string
  175.             dw      bd_dbyte                ; 14 display a character
  176.             dw      bd_gstring              ; 16 get a string
  177.             dw      bd_sstring              ; 18 send characters
  178.             dw      bd_sbyte                ; 20 send one character
  179.             dw      bd_ticks                ; 22 set tick down counter
  180.             dw      bd_xstring              ; 24 display w/o CR xlate
  181.  
  182. bd_handle   dw      0                       ; dl file handle
  183. bd_offset   dw      0                       ; overlay area
  184. bd_proto    dd      0                       ; protocol entry point
  185.  
  186. badproto    db      "Bad protocol selected",13,0
  187. protonfnd   db      "Protocol file missing",13,0
  188. bd_prompt   db      13,"Enter protocol letter and parameters: ",0
  189.  
  190. ; ---------------------------------------------------------------------
  191. ;   screen management items
  192. ; ---------------------------------------------------------------------
  193.  
  194. pop_video   dw      0                       ; video page
  195. pop_cursor  dw      0                       ; cursor position
  196. cursor_line equ     byte ptr pop_cursor+1   ; pointer to current row
  197. cursor_col  equ     byte ptr pop_cursor     ; pointer to current column
  198. pop_cmode   dw      001fh                   ; cursor mode
  199. disp_seg    dw      0                       ; seg for bd_disp routine
  200. disp_bufseg dw      0                       ; seg for our display buf
  201.  
  202. lines       =       25                      ; 25 lines
  203. cols        =       80                      ; .. of 80 columns
  204.  
  205. monoattr    =       07h                     ; monochrome attribute
  206. colattr     =       1fh                     ; color attribute
  207.  
  208. ourattr     db      07h                     ; attr to use, default mono
  209.  
  210. ; ---------------------------------------------------------------------
  211. ;   script execution work areas
  212. ; ---------------------------------------------------------------------
  213.  
  214. script_ids  db      12h, 34h, 31h           ; script file id/version bytes
  215. SCRIPT_ID   equ     word ptr script_ids     ; pointer to ID bytes
  216. SCRIPT_VER  equ     byte ptr script_ids+2   ; pointer to version
  217. script_amt  dw      1024                    ; script buffer size
  218. script_buf  dw      0                       ; start of script buffer
  219. script_wrk  dw      0                       ; current IP in script buffer
  220. script_var  dw      0                       ; addr of next script variable
  221. script_wsl  dw      0                       ; length of entered text
  222. script_ws   db      64 dup (0)              ; work string area
  223. script_fn   db      64 dup (0)              ; file name
  224. script_cs   db      14                      ; current state
  225. script_dm   dw      1                       ; debug mask
  226.                                             ; .... ...1 disp received text
  227.                                             ; .... ..1. disp sent text
  228. script_dmx  dw      0                       ; xtra debug mask (for reply)
  229. script_isi  dw      0                       ; incoming script parameter
  230. recurse_lim db      5                       ; recursion limit
  231. next_token  dw      0                       ; addr of next input token
  232.  
  233. timeout     dw      (182 * 5)/10            ; timeout value in ticks (5sec)
  234. timeout_lbl dw      -1                      ; offset of timeout label
  235. tick_wait   dw      0                       ; tick wait downcounter
  236. cancel_flag db      0                       ; cancel flag
  237.  
  238. dot_bdc     db      "."                     ; .BDC ..
  239. bdc         db      "BDC",0                 ; script file extension
  240.  
  241. exec_fnf    db      13,"Script file not found",13,0
  242. exec_too    db      13,"Script file too large",13,0
  243. exec_nbdc   db      13,"Script not compiled. Compile at the DOS prompt "
  244.             db      "with the following command."
  245.             db      13,"  BD /c {script_filename}",13,0
  246. exec_nver   db      13,"Wrong version script.  Please recompile.",13,0
  247. scriptfull  db      13,"Script buffer full",13,0
  248. cancelmsg   db      13,"Script terminated by operator",13,7,0
  249. script_pt   db      13,"Script name: ",0
  250.  
  251. exec_cmds   dw      exec_done               ;  0 script done
  252.             dw      exec_init               ;  1 initialize port
  253.             dw      exec_send               ;  2 send string
  254.             dw      exec_oper               ;  3 notify operator
  255.             dw      exec_reply              ;  4 wait for reply
  256.             dw      exec_tout               ;  5 set timeout
  257.             dw      exec_hang               ;  6 hangup
  258.             dw      exec_down               ;  7 download file
  259.             dw      exec_prompt             ;  8 prompt for variable
  260.             dw      exec_wait               ;  9 wait (setup)
  261.             dw      exec_goto               ; 10 goto label
  262.  
  263.             dw      exec_rwait              ; 11 reply wait loop
  264.             dw      exec_wait1              ; 12 wait loop
  265.             dw      exec_pwait              ; 13 prompt wait loop
  266.             dw      exec_start              ; 14 look for new script
  267.             dw      exec_opt                ; 15 options cmd
  268.             dw      exec_equate             ; 16 equate cmd
  269.  
  270. replacables dw      9 + 26 dup (0)          ; %1 - %9 and %A - %Z ptr array
  271.  
  272. user_i1b    dw      int23                   ; ^Break handler
  273. user_i1bs   dw      0                       ; segment ..
  274.  
  275. user_i23    dw      int23                   ; ^C handler
  276. user_i23s   dw      0                       ; segment ..
  277.  
  278. user_i24    dw      int24                   ; critical error handler
  279. user_i24s   dw      0                       ; segment ..
  280.  
  281. ; ---------------------------------------------------------------------
  282. ;   communications interrupt and buffering
  283. ; ---------------------------------------------------------------------
  284.  
  285. io_bdiv     dw      48                      ; current baud divisor  (2400)
  286. io_lcr      db      lcr_n81                 ; ..and comm parms      (N81)
  287.  
  288. ier         =       1                       ; offset of int enable reg
  289. iir         =       2                       ; offset of int id reg
  290. lcr         =       3                       ; offset of line ctl reg
  291. mcr         =       4                       ; offset of modem ctl reg
  292. lsr         =       5                       ; offset of line stat reg
  293. msr         =       6                       ; offset of modem stat reg
  294.  
  295. dl_lsb      =       0                       ; lsb of divisor if DLAB=1
  296. dl_msb      =       1                       ; msb of divisor if DLAB=1
  297.  
  298. ier_all     =       00001111b               ; enable all interrupts
  299.  
  300. ; - line status register definition
  301.  
  302. lsr_drdy    =       00000001b               ; data ready
  303. lsr_orun    =       00000010b               ; overrun error
  304. lsr_prty    =       00000100b               ; parity error
  305. lsr_frm     =       00001000b               ; framing error
  306. lsr_brk     =       00010000b               ; break interrupt
  307. lsr_thre    =       00100000b               ; transmit holding reg empty
  308. lsr_tsre    =       01000000b               ; transmit shift register emtpy
  309. lsr_err     =       lsr_frm+lsr_prty+lsr_orun   ; error conditions
  310.  
  311. ; - line control register definition
  312.  
  313. lcr_wlen    =       00000011b               ; word length:
  314.                                             ;  10 = 7 bits, 11 = 8 bits
  315. lcr_stop    =       00000100b               ; stop bits:
  316.                                             ;  0 = 1 stopbit
  317.                                             ;  1 = 2 stopbits
  318. lcr_parity  =       00001000b               ; Parity enable
  319.                                             ;  0 = No parity
  320.                                             ;  1 = Send/Check parity
  321. lcr_even    =       00010000b               ; Even/Odd parity
  322.                                             ;  0 = Odd parity
  323.                                             ;  1 = Even parity
  324. lcr_break   =       01000000b               ; Break: set to xmit break
  325. lcr_dlab    =       10000000b               ; divisor latch access bit
  326.  
  327. ; - modem control register definitions
  328.  
  329. mcr_dtr     =       00000001b               ; turn on DTR
  330. mcr_rts     =       00000010b               ; turn on Req to Send
  331. mcr_out2    =       00001000b               ; out2 control bit
  332.  
  333. mcr_DO      =       mcr_dtr+mcr_rts+mcr_out2    ; dtr, rts & out2
  334.  
  335. ; - common definitions
  336.  
  337. lcr_N81     =       00000011b               ; set 8 data, no parity, 1 stop
  338. lcr_E71     =       00011010b               ; set 7 data, even par, 1 stop
  339. lcr_O71     =       00001010b               ; set 7 data, odd par, 1 stop
  340.  
  341. ; - line status register definitions
  342.  
  343. lsr_datardy =       00000001b               ; data byte ready to read
  344. lsr_overrun =       00000010b               ; data overrun occurred
  345. lsr_parerr  =       00000100b               ; parity error
  346. lsr_framerr =       00001000b               ; framing error
  347. lsr_break   =       00010000b               ; break occurred
  348. lsr_thre    =       00100000b               ; xmit hold reg empty
  349. lsr_tsre    =       01000000b               ; xmit shift reg empty
  350.  
  351. ; - modem status register definitions
  352.  
  353. msr_dcts    =       00000001b               ; delta clear to send
  354. msr_ddsr    =       00000010b               ; delta data set ready
  355. msr_teri    =       00000100b               ; trailing edge ring indicator
  356. msr_dcd     =       00001000b               ; delta carrier detect
  357. msr_cts     =       00010000b               ; clear to send
  358. msr_dsr     =       00100000b               ; data set ready (modem ready)
  359. msr_ri      =       01000000b               ; ring indicated
  360. msr_cd      =       10000000b               ; carrier detected
  361.  
  362. ; - 8259 programmable interrupt controller definitions
  363.  
  364. i8259       =       20h                     ; 8259 control register addr
  365. eoi         =       20h                     ; 8259 end of interrupt command
  366. i8259m      =       21h                     ; 8259 mask register
  367.  
  368. ; - common control characters
  369.  
  370. soh         =       01h                     ; start of header
  371. stx         =       02h                     ; start of text
  372. etx         =       03h                     ; end of text
  373. ack         =       06h                     ; acknowledge
  374. nak         =       15h                     ; non-acknowledge
  375.  
  376. ; - definition of disk transfer area
  377.  
  378. dta         =       0h                      ; default dta offset
  379. dta_attr    equ     byte ptr dta+21         ; file attribute
  380. dta_time    equ     word ptr dta_attr+1     ; file time
  381. dta_date    equ     word ptr dta_time+2     ; file date
  382. dta_lsiz    equ     word ptr dta_date+2     ; file lsw of size
  383. dta_hsiz    equ     word ptr dta_lsiz+2     ; file msw of size
  384. dta_name    equ     byte ptr dta_hsiz+2     ; file name of file
  385. dta_len     equ     dta_name+15-dta         ; length of dta find entry
  386. dta_default =       80h                     ; default dta address
  387.  
  388. bd_int_use  db      0                       ; interrupt in use
  389. last_msr    db      ?                       ; last msr seen
  390. last_lsr    db      ?                       ; last lsr seen
  391.  
  392. ;last_iir   db      ?                       ; last iir seen
  393.  
  394. ; -------------------------------------------------------------------
  395. ;   send buffer pointers
  396. ; -------------------------------------------------------------------
  397.  
  398. send_equsiz =       512                     ; buffer size
  399. send_bufget dw      0                       ; get offset - used by int
  400. send_bufseg dw      ?                       ; segment for send buffer
  401. send_bufint equ     dword ptr send_bufget   ; far ptr for next get
  402. send_bufsiz dw      send_equsiz             ; size of send buffer
  403. send_bufput dw      0                       ; put offset - used by send
  404. send_done   db      1                       ; all characters sent
  405.  
  406. ; -------------------------------------------------------------------
  407. ;   receive buffer pointers
  408. ; -------------------------------------------------------------------
  409. rcv_equsiz  =       520 * 2                 ; buffer size
  410. rcv_bufput  dw      0                       ; put offset - used by int
  411. rcv_bufseg  dw      ?                       ; segment for rcv buffer
  412. rcv_bufint  equ     dword ptr rcv_bufput    ; far ptr for next put
  413. rcv_bufsiz  dw      rcv_equsiz              ; size of rcv buffer
  414. rcv_bufget  dw      0                       ; get offset - used by rcv
  415. rcv_ovfl    db      0                       ; overflow occurred flag
  416.  
  417. ; -------------------------------------------------------------------
  418. ;   terminal interface messages and data areas
  419. ; -------------------------------------------------------------------
  420.  
  421. bd_help$    db      13, "                  BackDown ", VERSN
  422.             db      13, "╔═════════════════════════════════════════════╗"
  423.             db      13, "║ F2: Settings  F4: Break       F10: Script   ║"
  424.             db      13, "║ F3: Hangup    F9: DownLoad  Alt-X: DOS/Exit ║"
  425.             db      13, "╚═════════════════════════════════════════════╝"
  426. bd_cr$      db      13, 0
  427.  
  428. bd_set$     db      13, "  Speed     Comm Parms     "
  429.             db      "Display    B+ Protocol", 13, 13
  430.             db      "A = 9600   1 = 8,None,1   7 = 7 Bit   + = Enabled", 13
  431.             db      "B = 2400   2 = 7,Odd, 1   8 = 8 Bit   - = Disabled", 13
  432.             db      "C = 1200   3 = 7,Even,1  ", 13
  433.             db      "D =  300", 13
  434. bd_set1$    db      13, "<CR> to end, Enter a choice:", 0
  435.  
  436. bd_hang$    db      13, "<<HANGUP>>", 13, 7, 0
  437. bd_break$   db      "<<Break>>", 0
  438.  
  439. case_flag   db      1                       ; ignore case in R cmds
  440. enq_flag    db      1                       ; ENQ respected for B+
  441. data_7flag  db      1                       ; 7bit mode for terminal
  442.  
  443. bd_bptable  db      "A", 6                  ; A - 9600 baud
  444.             dw      bd_selbaud
  445.             db      "9600 Baud", 0
  446.  
  447.             db      "B", 24                 ; B - 2400 baud
  448.             dw      bd_selbaud
  449.             db      "2400 Baud", 0
  450.  
  451.             db      "C", 48                 ; C - 1200 baud
  452.             dw      bd_selbaud
  453.             db      "1200 Baud", 0
  454.  
  455.             db      "D", 192                ; D - 300 baud
  456.             dw      bd_selbaud
  457.             db      "300 Baud", 0
  458.  
  459.             db      "1", lcr_N81            ; 1 - N81
  460.             dw      bd_selline
  461.             db      "8,None,1", 0
  462.  
  463.             db      "2", lcr_O71            ; 2 - O71
  464.             dw      bd_selline
  465.             db      "7,Odd,1", 0
  466.  
  467.             db      "3", lcr_E71            ; 3 - E71
  468.             dw      bd_selline
  469.             db      "7,Even,1", 0
  470.  
  471.             db      "7", 1                  ; A - 7BIT mode
  472.             dw      bd_sel78
  473.             db      "7 Bit Mode", 0
  474.  
  475.             db      "8", 0                  ; B - 8BIT mode
  476.             dw      bd_sel78
  477.             db      "8 Bit Mode", 0
  478.  
  479.             db      "+", 1                  ; C - B+ enabled
  480.             dw      bd_selbp
  481.             db      "B+ Enabled", 0
  482.  
  483.             db      "-", 0                  ; D - B+ disabled
  484.             dw      bd_selbp
  485.             db      "B+ Disabled", 0
  486.  
  487.             db      0                       ; end of table marker
  488.  
  489. prottype    db      13, "Type ", 0
  490. proteq      db      " for ", 0
  491. protnl      db      13, "     ", 0
  492. noprots     db      "No protocol modules available", 13, 10
  493. noprots_1   db      "$"
  494.  
  495. ; -------------------------------------------------------------------
  496. ;   interrupt jump table
  497. ; -------------------------------------------------------------------
  498.  
  499. bdintab     dw      offset bdi_msi          ; modem status interrupt
  500.             dw      offset bdi_thre         ; transmit done
  501.             dw      offset bdi_rcv          ; receive interrupt
  502.             dw      offset bdi_lsi          ; line status interrupt
  503.  
  504.  
  505.  
  506. ; -------------------------------------------------------------------
  507. ;   bd_int - communications interrupt handler
  508. ; -------------------------------------------------------------------
  509.  
  510. bd_int      proc    near                    ; interrupt handler entry point
  511.  
  512.             push    ax                      ; save registers
  513.             push    bx
  514.             push    dx
  515.  
  516.             mov     dx, cs:io_base          ; dx = io base register
  517.  
  518. bdint10:    add     dx, iir                 ; dx = int id reg
  519.             in      al, dx                  ; al = int id
  520.             sub     dx, iir                 ; dx = base register
  521.  
  522.             test    al, 1                   ; q. any interrupt?
  523.             jnz     bdint90                 ; a. no .. exit now.
  524.  
  525.             xor     ah, ah                  ; make it a word
  526.             mov     bx, ax                  ; bx = interrupt id
  527.             call    cs:word ptr bdintab[bx] ; .. call appropriate rtn
  528.             jmp     bdint10                 ; .. see if another
  529.  
  530. bdint90:    mov     al, eoi                 ; al = eoi instruction
  531.             out     i8259, al               ; .. reset the 8259
  532.  
  533.             pop     dx                      ; restore registers
  534.             pop     bx
  535.  
  536.             pop     ax
  537.             iret                            ; return to interrupted code
  538.  
  539. bd_int      endp
  540.  
  541.  
  542.  
  543. ; -------------------------------------------------------------------
  544. ;   bdi_msi - process modem status interrupt
  545. ;
  546. ;   entry: dx = io_base
  547. ; -------------------------------------------------------------------
  548.  
  549. bdi_msi     proc    near
  550.  
  551.             add     dx, msr                 ; dx -> msr
  552.             in      al, dx                  ; .. get the msr
  553.             sub     dx, msr                 ; .. return to io_base
  554.  
  555.             mov     cs:last_msr, al         ; save last msr value
  556.             ret                             ; .. return to caller
  557.  
  558. bdi_msi     endp
  559.  
  560.  
  561.  
  562. ; -------------------------------------------------------------------
  563. ;   bdi_lsi - process line status interrupt
  564. ;
  565. ;   entry: dx = io_base
  566. ; -------------------------------------------------------------------
  567.  
  568. bdi_lsi     proc    near
  569.  
  570.             add     dx, lsr                 ; dx -> lsr
  571.             in      al, dx                  ; .. get the msr
  572.             sub     dx, lsr                 ; .. return to io_base
  573.  
  574.             or      cs:last_lsr, al         ; save last lsr value
  575.             ret                             ; .. return to caller
  576.  
  577. bdi_lsi     endp
  578.  
  579.  
  580.  
  581. ; -------------------------------------------------------------------
  582. ;   bdi_rcv - process received character interrupt
  583. ;
  584. ;   entry: dx = io_base
  585. ; -------------------------------------------------------------------
  586.  
  587. bdi_rcv     proc    near
  588.  
  589.             in      al, dx                  ; Get the character
  590.  
  591.             push    ds                      ; save the DS register
  592.             lds     bx, cs:rcv_bufint       ; ds:bx -> next rcv byte
  593.             mov     byte ptr [bx], al       ; save the char
  594.             pop     ds                      ; restore ds
  595.  
  596.             inc     bx                      ; bx -> next position
  597.  
  598.             cmp     bx, cs:rcv_bufsiz       ; q. end of buffer?
  599.             jne     bdi_rcv10               ; a. no .. continue
  600.             xor     bx, bx                  ; .. else .. reset pointer
  601.  
  602. bdi_rcv10:  cmp     bx, cs:rcv_bufget       ; q. overrun?
  603.             jne     bdi_rcv90               ; a. no .. save ptr & leave
  604.  
  605.             mov     cs:rcv_ovfl,1           ; show an overrun occurred
  606.             ret                             ; .. and return to caller
  607.  
  608. bdi_rcv90:  mov     cs:rcv_bufput, bx       ; save buffer pointer
  609.             ret
  610.  
  611. bdi_rcv     endp
  612.  
  613.  
  614.  
  615. ; -------------------------------------------------------------------
  616. ;   bdi_thre - process transmit holding register empty interrupt
  617. ;
  618. ;   entry: dx = io_base
  619. ; -------------------------------------------------------------------
  620.  
  621. bdi_thre    proc    near
  622.  
  623.             mov     bx, cs:send_bufget      ; bx = get pointer
  624.  
  625.             cmp     bx, cs:send_bufput      ; q. buffer empty?
  626.             je      bdi_thre90              ; a. yes .. exit now
  627.  
  628.             mov     cs:send_done, 0         ; show send not done
  629.  
  630.             push    ds                      ; save ds
  631.             lds     bx, cs:send_bufint      ; ds:bx -> next put byte
  632.             mov     al, byte ptr [bx]       ; al = char to send
  633.             out     dx, al                  ; .. send the char
  634.             pop     ds                      ; restore ds
  635.  
  636.             inc     bx                      ; bx -> next position
  637.  
  638.             cmp     bx, cs:send_bufsiz      ; q. end of buffer?
  639.             jne     bdi_thre10              ; a. no .. continue
  640.             xor     bx, bx                  ; .. else .. bx = 0
  641.  
  642. bdi_thre10: mov     cs:send_bufget, bx      ; save the buffer pointer
  643.             ret                             ; .. return to caller
  644.  
  645. bdi_thre90: mov     cs:send_done, 1         ; show the send is done
  646.             ret                             ; .. return to caller
  647.  
  648. bdi_thre    endp
  649.  
  650.  
  651.  
  652. ; -------------------------------------------------------------------
  653. ;   ch_send - send a char
  654. ;
  655. ;   al = char to send
  656. ; -------------------------------------------------------------------
  657.  
  658. ch_send     proc    near
  659.  
  660.             push    bx                      ; save regs
  661.             push    dx                      ;
  662.             push    es
  663.  
  664.             mov     es, send_bufseg         ; es -> send segment
  665.  
  666. ch_send10:  mov     bx, send_bufput         ; bx -> next out position
  667.             mov     es:[bx], al             ; write to output buffer
  668.  
  669.             inc     bx                      ; bx -> next pos
  670.  
  671.             cmp     bx, send_bufsiz         ; q. end of buffer?
  672.             jne     ch_send20               ; a. no .. continue
  673.             xor     bx, bx                  ; .. else .. reset pointer
  674.  
  675. ch_send20:  cmp     bx, send_bufget         ; q. buffer full?
  676.             je      ch_send10               ; a. yes .. try again
  677.  
  678.             mov     send_bufput, bx         ; save bufput addr
  679.  
  680.             cmp     send_done, 0            ; q. prime pump?
  681.             je      ch_send90               ; a. no .. done for now.
  682.  
  683.             mov     dx, io_base             ; dx = io base
  684.             add     dx, lsr                 ; ds = lsr
  685.  
  686. ch_send30:  in      al, dx                  ; al = lsr
  687.  
  688.             test    al, lsr_thre            ; q. xmit hold reg empty?
  689.             jz      ch_send30               ; a. no .. loop 'til it is
  690.  
  691.             sub     dx, lsr                 ; dx = base register
  692.             call    bdi_thre                ; .. prime the pump
  693.  
  694. ch_send90:  pop     es                      ; restore registers
  695.             pop     dx
  696.             pop     bx
  697.             ret                             ; return to caller
  698.  
  699. ch_send     endp
  700.  
  701.  
  702.  
  703. ; -------------------------------------------------------------------
  704. ;   any_ch - test for char in buffer
  705. ;
  706. ;   exit: zero flag = no character available
  707. ; -------------------------------------------------------------------
  708.  
  709. any_ch      proc    near
  710.  
  711.             mov     ax, rcv_bufget          ; ax -> next get char
  712.  
  713.             cmp     ax, rcv_bufput          ; q. any put char?
  714.             ret                             ; a. return zf to caller
  715.  
  716. any_ch      endp
  717.  
  718.  
  719.  
  720. ; -------------------------------------------------------------------
  721. ;   ch_get - get a char from buffer
  722. ;
  723. ;   exit: ah = overflow flag
  724. ;         al = char
  725. ;         carry = no character available
  726. ; -------------------------------------------------------------------
  727.  
  728. ch_get      proc    near
  729.  
  730.             push    bx                      ; save regs
  731.             push    es
  732.  
  733.             xor     ah, ah                  ; ah = 0
  734.             xchg    ah, rcv_ovfl            ; ah = overflow flag
  735.  
  736.             mov     bx, rcv_bufget          ; bx = get address
  737.  
  738.             cmp     bx, rcv_bufput          ; q. buffer empty?
  739.             je      ch_get80                ; a. yes .. show the user
  740.  
  741.             mov     es, rcv_bufseg          ; es -> buffer
  742.             mov     al, es:[bx]             ; al = next char in buf
  743.  
  744.             inc     bx                      ; bx -> next position
  745.  
  746.             cmp     bx, rcv_bufsiz          ; q. end of buffer?
  747.             jne     ch_get10                ; a. no .. continue
  748.             xor     bx, bx                  ; .. else .. restart ptr
  749.  
  750. ch_get10:   mov     rcv_bufget, bx          ; save next get ptr
  751.  
  752.             clc                             ; show char received
  753.             jmp     short ch_get90          ; .. return to caller
  754.  
  755. ch_get80:   stc                             ; show no char available
  756.  
  757. ch_get90:   pop     es                      ; restore regs
  758.             pop     bx
  759.  
  760.             ret                             ; return to caller
  761. ch_get      endp
  762.  
  763.  
  764.  
  765. ; ---------------------------------------------------------------------
  766. ;   io_init - initialize the async port and 8259
  767. ; ---------------------------------------------------------------------
  768.  
  769. io_init     proc    near
  770.  
  771.             xor     dx, dx                  ; dx = base offset
  772.             call    in_reg                  ; .. clear any character
  773.  
  774.             mov     dx, ier                 ; dx = ier offset
  775.             xor     al, al                  ; al = zero (no interrupts)
  776.             call    out_reg                 ; no ints for now
  777.  
  778.             mov     dx, mcr                 ; dx = mcr offset; al still 0
  779.             call    out_reg                 ; .. set off all stats
  780.  
  781.             mov     dx, lsr                 ; dx = line status register
  782.             call    in_reg                  ; read/reset interrupt reg
  783.  
  784.             mov     dx, msr                 ; dx = modem status register
  785.             call    in_reg                  ; read/reset interrupt reg
  786.  
  787.             mov     dx, iir                 ; dx = interrupt id register
  788.             call    in_reg                  ; read/reset interrupt reg
  789.  
  790.             xor     dx, dx                  ; dx = data register
  791.             call    in_reg                  ; read/reset pending interrupts
  792.  
  793.             call    io_baud                 ; set baud rate
  794.             call    io_pards                ; ..and comm parms
  795.  
  796.             mov     dx, mcr                 ; dx = modem control reg offset
  797.             mov     al, mcr_DO              ; al = set on DTR, OUT2 and RTS
  798.             call    out_reg                 ; .. set mcr value
  799.  
  800.             in      al, i8259m              ; al = current int mask
  801.             mov     cl, io_int              ; cl = interrupt to use
  802.             mov     ah, 1                   ; ah = 1 ..
  803.             shl     ah, cl                  ; .. shift bit to mask pos
  804.             not     ah                      ; .. and invert mask
  805.             and     al, ah                  ; .. set off mask bit
  806.             out     i8259m, al              ; .. allow com interrupts
  807.  
  808.             mov     dx, ier                 ; dx = int enable reg offset
  809.             mov     al, ier_all             ; al = allow all interrupts
  810.             call    out_reg                 ; .. set int enable register
  811.  
  812.             ret                             ; .. return to caller
  813.  
  814. io_init     endp
  815.  
  816.  
  817.  
  818. ; ----------------------------------------------------------------------
  819. ;   in_reg - get a register's value from the UART
  820. ;
  821. ;   entry: dx = register offset
  822. ;
  823. ;    exit: al = value
  824. ; ----------------------------------------------------------------------
  825.  
  826. in_reg      proc
  827.  
  828.             add     dx, io_base             ; dx = register wanted
  829.             in      al, dx                  ; .. get the value
  830.             ret                             ; return to caller
  831.  
  832. in_reg      endp
  833.  
  834.  
  835. ; ----------------------------------------------------------------------
  836. ;   out_reg - send a value out to a port
  837. ;
  838. ;   entry: dx = reg offset
  839. ;
  840. ;    exit: al = value
  841. ; ----------------------------------------------------------------------
  842.  
  843. out_reg     proc
  844.  
  845.             add     dx, io_base             ; dx = register wanted
  846.             out     dx, al                  ; .. send the value
  847.             ret                             ; return to caller
  848.  
  849. out_reg     endp
  850.  
  851.  
  852.  
  853. ; ----------------------------------------------------------------------
  854. ;   io_reset - reset and shutdown com port hardware interrupts
  855. ; ----------------------------------------------------------------------
  856.  
  857. io_reset    proc
  858.  
  859.             mov     dx, mcr                 ; dx = modem control reg offset
  860.             xor     al, al                  ; al = reset mcr
  861.             call    out_reg                 ; .. reset mcr value
  862.  
  863.             mov     dx, ier                 ; dx = int enable reg offset
  864.             call    out_reg                 ; .. reset int enable register
  865.  
  866.             in      al, i8259m              ; al = current int mask
  867.             mov     cl, io_int              ; cl = interrupt to use
  868.             mov     ah, 1                   ; ah = 1 ..
  869.             shl     ah, cl                  ; .. shift bit to mask pos
  870.             or      al, ah                  ; .. set on mask bit
  871.             out     i8259m, al              ; .. allow com interrupts
  872.  
  873.             ret                             ; .. return to caller
  874.  
  875. io_reset    endp
  876.  
  877.  
  878.  
  879. ; ----------------------------------------------------------------------
  880. ;   io_baud - set baud rate
  881. ;
  882. ;   entry: io_bdiv = baud rate divisor
  883. ; ----------------------------------------------------------------------
  884.  
  885. io_baud     proc
  886.  
  887.             push    ax                      ; save registers
  888.             push    dx
  889.  
  890.             mov     dx, lcr                 ; dx = lcr offset
  891.             call    in_reg                  ; get current lcr
  892.             mov     ah, al                  ; ah = old lcr
  893.  
  894.             or      al, lcr_dlab            ; set on dlab
  895.             mov     dx, lcr                 ; dx = lcr offset
  896.             cli                             ; no interrupts ..
  897.             call    out_reg                 ; .. set on the dlab
  898.  
  899.             mov     dx, dl_msb              ; dx = div latch msb
  900.             mov     al, byte ptr io_bdiv+1  ; al = msb of divisor
  901.             call    out_reg                 ; .. set the msb up
  902.  
  903.             mov     dx, dl_lsb              ; dx = div latch lsb
  904.             mov     al, byte ptr io_bdiv    ; al = lsb of divisor
  905.             call    out_reg                 ; .. set the lsb up
  906.  
  907.             mov     al, ah                  ; al = old lcr
  908.             mov     dx, lcr                 ; dx = lcr offset
  909.             call    out_reg                 ; .. turn off dlab
  910.             sti                             ; .. allow ints again
  911.  
  912.             pop     dx                      ; restore registers
  913.             pop     ax
  914.             ret
  915.  
  916. io_baud     endp
  917.  
  918.  
  919.  
  920. ; ----------------------------------------------------------------------
  921. ;   io_pards - set parity, stop, data bits
  922. ;
  923. ;   entry: io_lcr = line control data
  924. ; ----------------------------------------------------------------------
  925.  
  926. io_pards    proc
  927.  
  928.             push    dx                      ; save register
  929.  
  930.             mov     al, io_lcr              ; al = comm parms
  931.             mov     dx, lcr                 ; dx = lcr offset
  932.             call    out_reg                 ; .. set comm parms
  933.  
  934.             pop     dx                      ; restore register
  935.             ret                             ; return to caller
  936.  
  937. io_pards    endp
  938.  
  939.  
  940.  
  941. ; ---------------------------------------------------------------------
  942. ;   io_hangup - break a connection using DTR
  943. ; ---------------------------------------------------------------------
  944.  
  945. io_hangup   proc
  946.  
  947.             push    ax                      ; save registers
  948.             push    bx
  949.             push    dx
  950.  
  951.             mov     dx, mcr                 ; dx = modem control
  952.             call    in_reg                  ; al = mcr
  953.  
  954.             mov     dx, mcr                 ; dx = modem control
  955.             and     al, not mcr_dtr         ; al = shut off DTR
  956.             call    out_reg                 ; .. shut down DTR
  957.  
  958.             mov     bx, 3                   ; bx = ticks to wait
  959.             call    tmr_wait                ; .. wait .2 secs
  960.  
  961.             call    io_init                 ; re-init the uart
  962.  
  963.             mov     bx, 18                  ; bx = time to wait
  964.             call    tmr_wait                ; .. wait a second
  965.  
  966.             pop     dx                      ; restore registers
  967.             pop     bx
  968.             pop     ax
  969.             ret                             ; .. return to caller
  970.  
  971. io_hangup   endp
  972.  
  973.  
  974.  
  975. ; ----------------------------------------------------------------------
  976. ;   ck_dtr - check if DTR has dropped
  977. ; ----------------------------------------------------------------------
  978.  
  979. ck_dtr      proc
  980.             push    ax                      ; save registers
  981.             push    dx
  982.  
  983.             mov     dx, mcr                 ; dx = modem control reg offset
  984.             call    in_reg                  ; get mcr value
  985.  
  986.             and     al, mcr_dtr             ; q. DTR up?
  987.             jnz     ck_dtr90                ; a. yes .. return
  988.  
  989.             call    io_init                 ; initialize port and mcr
  990.  
  991.             mov     bx, 9                   ; bx = time to wait
  992.             call    tmr_wait                ; .. wait half a second
  993.  
  994. ck_dtr90:   pop     dx                      ; restore registers
  995.             pop     ax
  996.             ret                             ; .. then return to caller
  997.  
  998. ck_dtr      endp
  999.  
  1000.  
  1001.  
  1002. ; ---------------------------------------------------------------------
  1003. ;   tmr_wait - wait some number of ticks
  1004. ;
  1005. ;   entry: bx = ticks to wait
  1006. ; ---------------------------------------------------------------------
  1007.  
  1008. tmr_wait    proc
  1009.             mov     tick_wait, bx           ; number of ticks to wait
  1010.  
  1011. tmr_wait10: cmp     tick_wait, 0            ; q. waited enough?
  1012.             jge     tmr_wait10              ; a. no .. wait some more
  1013.  
  1014.             ret                             ; return to caller
  1015. tmr_wait    endp
  1016.  
  1017.  
  1018.  
  1019. ; ---------------------------------------------------------------------
  1020. ;   io_break - send a break
  1021. ; ---------------------------------------------------------------------
  1022.  
  1023. io_break    proc
  1024.  
  1025.             push    ax                      ; save registers
  1026.             push    bx
  1027.             push    dx
  1028.  
  1029.             mov     dx, lcr                 ; dx = lcr offset
  1030.             call    in_reg                  ; al = lcr value
  1031.             mov     ah, al                  ; ah = old lcr value
  1032.  
  1033.             or      al, lcr_break           ; set break bit in al
  1034.             mov     dx, lcr                 ; dx = lcr offset
  1035.             call    out_reg                 ; .. send the break
  1036.  
  1037.             mov     bx, 9                   ; bx = length of break
  1038.             call    tmr_wait                ; .. wait .5 secs
  1039.  
  1040.             mov     al, ah                  ; al = old lcr value
  1041.             mov     dx, lcr                 ; dx = lcr offset
  1042.             call    out_reg                 ; .. restore lcr
  1043.  
  1044.             pop     dx                      ; restore registers
  1045.             pop     bx
  1046.             pop     ax
  1047.  
  1048.             ret
  1049.  
  1050. io_break    endp
  1051.  
  1052.  
  1053.  
  1054. ; ----------------------------------------------------------------------
  1055. ;   usingdos - returns the availability of DOS for file i/o
  1056. ;
  1057. ;   exit: carry = DOS not ready for file i/o
  1058. ;
  1059. ; ----------------------------------------------------------------------
  1060.  
  1061. usingdos    proc
  1062.  
  1063.             cmp     intsbusy, 0             ; q. one of interrupts busy?
  1064.             jne     usingdos95              ; a. yes .. exit w/wait code
  1065.  
  1066.             push    es                      ; save registers
  1067.             push    bx                      ; ..
  1068.             les     bx, dos_busy            ; es:bx -> DOS busy flag
  1069.  
  1070.             cmp     word ptr es:[bx], 0     ; q. DOS available?
  1071.             je      usingdos80              ; a. yes .. tell caller ok
  1072.  
  1073.             cmp     i28hflag, 0             ; q. called from DOS Waiting
  1074.             je      usingdos90              ; a. no .. DOS is busy
  1075.  
  1076.             cmp     byte ptr es:[bx+1], 1   ; q. DOS available during int 28
  1077.             jne     usingdos90              ; a. yes .. tell caller ok
  1078.  
  1079. usingdos80: pop     bx                      ; ...restore registers
  1080.             pop     es                      ; ...
  1081.  
  1082.             clc                             ; show DOS is available ..
  1083.             ret                             ; ..and return to caller
  1084.  
  1085. usingdos90: pop     bx                      ; ...restore registers
  1086.             pop     es                      ; ...
  1087.  
  1088. usingdos95: stc                             ; show DOS busy ..
  1089.             ret                             ; ..and return to caller
  1090.  
  1091. usingdos    endp
  1092.  
  1093.  
  1094.  
  1095. ; ----------------------------------------------------------------------
  1096. ;   main - this routine is the main control tsr loop
  1097. ; ----------------------------------------------------------------------
  1098.  
  1099. main        proc
  1100.  
  1101.             inc     cs:main_active          ; show main in use
  1102.  
  1103.             cmp     cs:main_active, 1       ; q. already in main?
  1104.             je      main10                  ; a. no .. continue
  1105.  
  1106.             dec     cs:main_active          ; decrement our use
  1107.             ret                             ; else .. just return
  1108.  
  1109. main10:     push    ax                      ; save registers
  1110.             push    ds
  1111.             push    es
  1112.  
  1113.             mov     ax, cs                  ; ax -> us
  1114.             mov     ds, ax                  ; ds -> our data
  1115.             mov     es, ax                  ; es -> there too
  1116.  
  1117.             mov     oldss, ss               ; save caller's stack
  1118.             mov     oldsp, sp               ;
  1119.  
  1120.             cli                             ; hold up interrupts
  1121.             mov     ss, ax                  ; setup new stack
  1122.             mov     sp, offset wstack       ; ..
  1123.             sti                             ; enable interrupts
  1124.  
  1125.             push    bx                      ; save rest on our stack
  1126.             push    cx
  1127.             push    dx
  1128.             push    si
  1129.             push    di
  1130.             push    bp
  1131.  
  1132.             cld                             ; clear direction flag
  1133.  
  1134.             cmp     tsr_req, 0              ; q. need to pop up?
  1135.             je      main20                  ; a. no .. continue
  1136.  
  1137.             call    usingdos                ; q. DOS available?
  1138.             jc      main20                  ; a. no .. continue
  1139.  
  1140.             call    popup                   ; else .. pop up our screen
  1141.  
  1142. main20:     mov     bx, main_state          ; bx = current state
  1143.             call    main_table[bx]          ; dispatch to term, dl, script
  1144.  
  1145.             cmp     tsr_active, 0           ; q. are we popped up?
  1146.             jne     main20                  ; a. yes .. stay in main
  1147.  
  1148.             call    any_ch                  ; q. any chars in buffer?
  1149.             jz      main90                  ; a. no .. exit now
  1150.  
  1151.             dec     chars_disp              ; q. enough chars/dispatch?
  1152.             jnz     main20                  ; a. no .. one more time
  1153.  
  1154. main90:     mov     chars_disp, NCHARS      ; refill dispatch quantity
  1155.  
  1156.             pop     bp                      ; restore registers
  1157.             pop     di
  1158.             pop     si
  1159.             pop     dx
  1160.             pop     cx
  1161.             pop     bx
  1162.  
  1163.             cli                             ; hold interrupts
  1164.             mov     ss, oldss               ; restore caller's stack
  1165.             mov     sp, oldsp               ; ..
  1166.             sti                             ; enable interrupts again
  1167.  
  1168.             pop     es                      ; restore more registers
  1169.             pop     ds
  1170.             pop     ax
  1171.  
  1172.             dec     cs:main_active          ; ..show we're out of here
  1173.             ret                             ; ..and return to caller
  1174.  
  1175. main        endp
  1176.  
  1177.  
  1178.  
  1179. ; ----------------------------------------------------------------------
  1180. ;   int28 - DOS waiting interrupt handler
  1181. ; ----------------------------------------------------------------------
  1182.  
  1183. int28       proc
  1184.             sti                             ; enable interrupts
  1185.             inc     cs:i28hflag             ; show we're in int 28 rtn
  1186.  
  1187.             call    main                    ; do a small amount of work
  1188.  
  1189.             dec     cs:i28hflag             ; show we're out of int 28
  1190.             jmp     dword ptr cs:oldint28   ; jump to old int 28 routine
  1191.  
  1192. int28       endp
  1193.  
  1194.  
  1195.  
  1196. ; ----------------------------------------------------------------------
  1197. ;   int13 - Disk I/O in progress interrupt handler
  1198. ; ----------------------------------------------------------------------
  1199.  
  1200. int13       proc    far
  1201.             push    bp                      ; save caller's bp
  1202.             mov     bp, sp                  ; bp -> stack
  1203.             push    [bp+6]                  ; push caller's flags
  1204.             mov     bp, [bp]                ; ..restore bp contents
  1205.  
  1206.             inc     cs:intsbusy             ; show interrupt is busy
  1207.  
  1208.             call    dword ptr cs:oldint13   ; call the old int 13 rtn
  1209.             pushf                           ; save int 13 return flags
  1210.  
  1211.             dec     cs:intsbusy             ; now show we're done
  1212.             popf                            ; ..restore int 13's flags
  1213.  
  1214.             pop     bp                      ; ..remove BP from stack
  1215.             ret     2                       ; ..and return to caller
  1216. int13       endp
  1217.  
  1218.  
  1219.  
  1220. ; ----------------------------------------------------------------------
  1221. ;   int10 - BIOS Video call in progress interrupt handler
  1222. ; ----------------------------------------------------------------------
  1223.  
  1224. int10       proc    far
  1225.             pushf                           ; save int 10 return flags
  1226.             sti                             ; enable interrupts
  1227.             inc     cs:intsbusy             ; show interrupt is busy
  1228.  
  1229.             call    dword ptr cs:oldint10   ; call the old int 10 rtn
  1230.  
  1231.             dec     cs:intsbusy             ; now show we're done
  1232.             iret                            ; ..and return to caller
  1233. int10       endp
  1234.  
  1235.  
  1236.  
  1237. ; ----------------------------------------------------------------------
  1238. ;   int2f - multiplexor interrupt handler
  1239. ;
  1240. ;   exit: di = tsr segment if ax = multiplex nbr
  1241. ; ----------------------------------------------------------------------
  1242.  
  1243. int2f       proc                            ; multiplex interrupt
  1244.  
  1245.             cmp     ax, cs:multiplex        ; q. for us?
  1246.             jne     i2fh90                  ; a. no .. try someone else
  1247.  
  1248.             mov     di, cs                  ; di -> our segment
  1249.             iret                            ; ..then return to caller
  1250.  
  1251. i2fh90:     jmp     dword ptr cs:oldint2f   ; chain to old int 2f rtn
  1252.  
  1253. int2f       endp
  1254.  
  1255.  
  1256.  
  1257. ; ----------------------------------------------------------------------
  1258. ;   int08 - timer tick interrupt handler
  1259. ; ----------------------------------------------------------------------
  1260.  
  1261. int08       proc
  1262.             pushf                           ; fake interrupt call
  1263.             call    cs:oldint08             ; call old timer stuff
  1264.  
  1265.             dec     cs:tick_wait            ; downcount timer ticks
  1266.  
  1267.             call    main                    ; call our main routine
  1268.             iret                            ; ..and return to caller
  1269.  
  1270. int08       endp
  1271.  
  1272.  
  1273.  
  1274. ; ----------------------------------------------------------------------
  1275. ;   int09 - keyboard interrupt handler
  1276. ; ----------------------------------------------------------------------
  1277.  
  1278. int09       proc
  1279.             cmp     cs:tsr_active, 0        ; q. tsr in use?
  1280.             jne     i09h15                  ; a. yes .. get out quickly
  1281.  
  1282.             push    ax                      ; save used register
  1283.             in      al, 60h                 ; get key scan code
  1284.             cmp     al, cs:hot_key          ; q. our hot-key?
  1285.             je      i09h10                  ; a. yes .. continue
  1286.  
  1287.             pop     ax                      ; restore register
  1288.             jmp     short i09h15            ; ..and get out
  1289.  
  1290. i09h10:     mov     ah, 2                   ; ah = get shift status fnc
  1291.             int     16h                     ; call BIOS
  1292.  
  1293.             and     al, 0fh                 ; al = 'shift' bits
  1294.  
  1295.             cmp     al, cs:shift_mask       ; q. match our combo?
  1296.             pop     ax                      ; restore register
  1297.             je      i09h20                  ; a. yes . continue
  1298. i09h15:     jmp     cs:oldint09             ; else .. do key as normal
  1299.  
  1300. i09h20:     pushf                           ; call old int 9
  1301.             call    cs:oldint09             ; ..to finish reading key
  1302.  
  1303.             sti                             ; allow interrupts
  1304.             push    ax                      ; save work register
  1305.  
  1306. i09h30:     mov     ah, 1                   ; ah = get status
  1307.             int     16h                     ; q. any keys availabl?
  1308.             jz      i09h40                  ; a. no .. exit loop
  1309.  
  1310.             mov     ah, 0                   ; ah = get key
  1311.             int     16h                     ; get the key ..
  1312.             jmp     i09h30                  ; ..and loop till kb empty
  1313.  
  1314. i09h40:     pop     ax                      ; restore register
  1315.             inc     cs:tsr_req              ; show tsr request made
  1316.             iret                            ; go back where we came from
  1317.  
  1318. int09       endp
  1319.  
  1320.  
  1321.  
  1322. ; ----------------------------------------------------------------------
  1323. ;   int23 - ^C and ctrl-break interrupt handler
  1324. ; ----------------------------------------------------------------------
  1325.  
  1326. int23       proc
  1327.  
  1328.             iret                            ; just return to caller
  1329.  
  1330. int23       endp
  1331.  
  1332.  
  1333.  
  1334. ; ----------------------------------------------------------------------
  1335. ;   int24 - critical error handler
  1336. ; ----------------------------------------------------------------------
  1337.  
  1338. int24       proc
  1339.  
  1340.             mov     al, 3                   ; al = failed call
  1341.             iret                            ; ..then return to caller
  1342.  
  1343. int24       endp
  1344.  
  1345.  
  1346.  
  1347. ; ----------------------------------------------------------------------
  1348. ;   popup - pop up our window
  1349. ; ----------------------------------------------------------------------
  1350.  
  1351. popup       proc
  1352.             sti                             ; allow interrupts
  1353.  
  1354.             mov     tsr_req, 0              ; clear tsr request flag
  1355.  
  1356.             mov     ah, 0fh                 ; get current display mode
  1357.             int     10h                     ; .. ask BIOS
  1358.  
  1359.             mov     bx, 0b800h              ; bx = assume color adapter
  1360.  
  1361.             cmp     al, 2                   ; q. bw mode?
  1362.             je      popup10                 ; a. yes .. ok to do it.
  1363.  
  1364.             cmp     al, 3                   ; q. color mode?
  1365.             je      popup10                 ; a. yes .. ok to do it.
  1366.  
  1367.             mov     bx, 0b000h              ; bx = assume mono adapter
  1368.  
  1369.             cmp     al, 7                   ; q. mono mode?
  1370.             jne     popup90                 ; a. no .. we're history
  1371.  
  1372. popup10:    mov     disp_seg, bx            ; set bd_disp segment
  1373.  
  1374.             call    swap_1b                 ; swap ^break handler in
  1375.  
  1376.             inc     tsr_active              ; show we're pop'd up
  1377.             call    swap_screen             ; swap screens
  1378.  
  1379. popup90:    ret                             ; ..then return to caller
  1380.  
  1381. popup       endp
  1382.  
  1383.  
  1384.  
  1385. ; ----------------------------------------------------------------------
  1386. ;   popdown - pop down our screen
  1387. ; ----------------------------------------------------------------------
  1388.  
  1389. popdown     proc
  1390.  
  1391.             call    swap_screen             ; swap screens
  1392.  
  1393.             mov     bx, disp_bufseg         ; bx = segment for bd_disp
  1394.             mov     disp_seg, bx            ; setup for display routine
  1395.  
  1396.             call    swap_1b                 ; swap ^break handler out
  1397.  
  1398.             dec     tsr_active              ; show we're pop'down
  1399.             mov     tsr_req, 0              ; ..and clear any requests
  1400.  
  1401.             ret                             ; ..then return to caller
  1402.  
  1403. popdown     endp
  1404.  
  1405.  
  1406.  
  1407. ; ----------------------------------------------------------------------
  1408. ;   swap_screen - swap tsr screen with display memory
  1409. ;
  1410. ;   exit: carry = bad video mode mode
  1411. ; ----------------------------------------------------------------------
  1412.  
  1413. swap_screen proc
  1414.  
  1415.             mov     ah, 0fh                 ; ah = get current info
  1416.             int     10h                     ; call BIOS
  1417.  
  1418.             xchg    pop_video, bx           ; save current video page
  1419.  
  1420.             mov     al, bh                  ; al = active page
  1421.             mov     ah, 5                   ; ah = setup active page
  1422.             int     10h                     ; call BIOS
  1423.  
  1424.             mov     ah, 3                   ; ah = get cursor position
  1425.             int     10h                     ; call BIOS
  1426.  
  1427.             xchg    pop_cursor, dx          ; save cursor position
  1428.             xchg    pop_cmode, cx           ; ..and cursor mode
  1429.  
  1430.             mov     ah, 1                   ; ah = set cursor mode
  1431.             int     10h                     ; .. do it
  1432.  
  1433.             mov     ah, 2                   ; ah = set cursor position
  1434.             int     10h                     ; call BIOS
  1435.  
  1436.             push    ds                      ; save registers
  1437.             push    es
  1438.  
  1439.             mov     es, disp_bufseg         ; es -> our screen buffer
  1440.             xor     di, di                  ; di = offset in our buf
  1441.  
  1442.             mov     ds, disp_seg            ; ds -> video buffer
  1443.             xor     si, si                  ; si = offset in vid buf
  1444.  
  1445.             mov     cx, 80 * 25             ; columns to swap
  1446.  
  1447. swap_sc20:  mov     ax, es:[di]             ; ax = char/attr @our buf
  1448.  
  1449.             xchg    ax, ds:[si]             ; swap with buffer
  1450.             inc     si                      ; si -> next
  1451.             inc     si                      ; .. char
  1452.  
  1453.             stosw                           ; .. complete the exchange
  1454.             loop    swap_sc20               ; .. continue 'til done
  1455.  
  1456.             pop     es                      ; restore registers
  1457.             pop     ds
  1458.             ret                             ; return to caller
  1459.  
  1460. swap_screen endp
  1461.  
  1462.  
  1463.  
  1464. ; ----------------------------------------------------------------------
  1465. ;   bd_trm - terminal interface routine.
  1466. ; ----------------------------------------------------------------------
  1467.  
  1468. bd_trm      proc    near
  1469.  
  1470.             call    bd_key                  ; q. key ready?
  1471.             jc      bd_trm50                ; a. no .. display chars
  1472.  
  1473.             or      al, al                  ; q. special key?
  1474.             jnz     bd_trm10                ; a. no .. continue
  1475.  
  1476.             call    bd_skey                 ; process special keys
  1477.             jmp     short bd_trm50          ; ..then get a com character
  1478.  
  1479. bd_trm10:   call    ch_send                 ; send the character
  1480.  
  1481. bd_trm50:   call    ch_get                  ; q. character available?
  1482.             jc      bd_trm90                ; a. no .. do main loop
  1483.  
  1484.             call    bd_bpstuff              ; handle CIS B+ and 7 bit stuff
  1485.             jc      bd_trm90                ; ..if processed.. continue
  1486.  
  1487.             call    bd_disp                 ; display the char gotten
  1488.             jmp     bd_trm                  ; .. see if anything typed
  1489.  
  1490. bd_trm90:   ret                             ; return to caller
  1491.  
  1492. bd_trm      endp
  1493.  
  1494.  
  1495.  
  1496. ; ----------------------------------------------------------------------
  1497. ;   bd_disp - display a character on screen
  1498. ;
  1499. ;   entry: al = char to display
  1500. ; ----------------------------------------------------------------------
  1501.  
  1502. bd_disp     proc    near                    ; display char on screen
  1503.             push    ax                      ; save registers
  1504.             push    bx
  1505.             push    si
  1506.             push    di
  1507.  
  1508.             or      al, al                  ; q. nul character?
  1509.             jnz     bd_disp10               ; a. no .. let's show it!
  1510.             jmp     bd_disp90               ; .. else .. exit
  1511.  
  1512. bd_disp10:  cmp     tsr_active, 0           ; q. popped up?
  1513.             je      bd_disp50               ; a. no .. process in memory
  1514.  
  1515.             mov     ah, 0eh                 ; ah = write, tty style
  1516.             xor     bx, bx                  ; .. bh = page, bl = FG color
  1517.             int     10h                     ; .. write w/BIOS
  1518.  
  1519.             cmp     al, 8                   ; q. backspace?
  1520.             je      bd_disp20               ; a. yes .. process it
  1521.             jmp     bd_disp90               ; .. else .. exit
  1522.  
  1523. bd_disp20:  mov     ax, 0e20h               ; al = write a blank
  1524.             int     10h                     ; .. write w/ bios
  1525.  
  1526.             mov     ax, 0e08h               ; al = write another bs
  1527.             int     10h                     ; .. write w/ bios
  1528.             jmp     bd_disp90               ; .. and return to caller
  1529.  
  1530. bd_disp50:  cmp     al, 0dh                 ; q. above <CR>
  1531.             ja      bd_disp70               ; a. yes .. display it
  1532.             jb      bd_disp55               ; a. below .. check it out
  1533.  
  1534.             mov     cursor_col, 0           ; move cursor to first char
  1535.             jmp     short bd_disp90         ; .. and exit
  1536.  
  1537. bd_disp55:  cmp     al, 0ah                 ; q. <LF>?
  1538.             jne     bd_disp60               ; a. no .. continue
  1539.  
  1540.             cmp     cursor_line, 24         ; q. at "bottom"?
  1541.             jne     bd_disp57               ; a. no .. increment
  1542.             call    bd_scroll               ; else .. scroll
  1543.             jmp     short bd_disp90         ; .. and continue
  1544.  
  1545. bd_disp57:  inc     cursor_line             ; increment line
  1546.             jmp     short bd_disp90         ; .. and continue
  1547.  
  1548. bd_disp60:  cmp     al, 08h                 ; q. backspace?
  1549.             jne     bd_disp65               ; a. no .. continue
  1550.  
  1551.             cmp     cursor_col, 0           ; q. at start of line?
  1552.             je      bd_disp90               ; a. yes .. go no further
  1553.  
  1554.             dec     cursor_col              ; move back a char
  1555.             mov     al, ' '                 ; change to blank
  1556.             call    bd_disp                 ; .. display the blank
  1557.             dec     cursor_col              ; .. move back again
  1558.             jmp     short bd_disp90         ; .. and continue
  1559.  
  1560. bd_disp65:  cmp     al, 07h                 ; a. bell?
  1561.             jne     bd_disp70               ; a. no .. continue
  1562.  
  1563.             mov     ah,0eh                  ; ah = write tty
  1564.             int     10h                     ; .. tweet-tweet
  1565.             jmp     short bd_disp90         ; .. and continue
  1566.  
  1567. bd_disp70:  push    ax                      ; save character
  1568.  
  1569.             mov     bx, pop_cursor          ; bx = cursor postion
  1570.             mov     al, bh                  ; al = row
  1571.             xor     ah, ah                  ; .. clear upper bits
  1572.             mov     bh, 160                 ; bh = row len
  1573.             mul     bh                      ; .. get row offset
  1574.  
  1575.             xor     bh, bh                  ; kill the upper bits
  1576.             shl     bx, 1                   ; bx = bx * 2 (Line offset)
  1577.             add     bx, ax                  ; bx -> byte offset for line
  1578.             pop     ax                      ; ax = entry contents
  1579.  
  1580.             push    es                      ; save es
  1581.             mov     es, disp_bufseg         ; .. get pointer to buffer
  1582.             mov     es:[bx], al             ; .. save the byte
  1583.             pop     es                      ; .. restore es
  1584.  
  1585.             inc     cursor_col              ; go to next position
  1586.  
  1587.             cmp     cursor_col, 80          ; q. end of line?
  1588.             jb      bd_disp90               ; a. no .. we are done
  1589.  
  1590.             mov     cursor_col, 0           ; reset the row
  1591.  
  1592.             cmp     cursor_line, 24         ; q. at "bottom"
  1593.             jne     bd_disp80               ; a. no .. increment
  1594.  
  1595.             call    bd_scroll               ; else .. scroll
  1596.             jmp     short bd_disp90         ; .. and exit
  1597.  
  1598. bd_disp80:  inc     cursor_line             ; next line
  1599.  
  1600. bd_disp90:  pop     di                      ; restore registers
  1601.             pop     si
  1602.             pop     bx
  1603.             pop     ax
  1604.             ret                             ; return to caller
  1605.  
  1606. bd_disp     endp
  1607.  
  1608.  
  1609.  
  1610. ; ----------------------------------------------------------------------
  1611. ;  bd_scroll - scroll the display buffer up one line
  1612. ; ----------------------------------------------------------------------
  1613.  
  1614. bd_scroll   proc
  1615.             push    cx                      ; save registers
  1616.             push    si
  1617.             push    di
  1618.             push    ds
  1619.             push    es
  1620.  
  1621.             xor     di, di                  ; di -> start of buffer
  1622.             mov     si, 160                 ; si -> second line
  1623.             mov     cx, 24*80               ; scroll up 24 lines
  1624.             mov     es, disp_bufseg         ; es -> display buffer
  1625.             mov     ds, disp_bufseg         ; .. and ds
  1626.             cld                             ; .. clear the direction
  1627.      rep    movsw                           ; .. scroll 'er up
  1628.  
  1629.             mov     cx, 80                  ; cx = bytes in last to clear
  1630.             mov     al, ' '                 ; al = blank
  1631.  
  1632. bd_scroll1: stosb                           ; clear a character
  1633.             inc     di                      ; .. skip the attribute
  1634.             loop    bd_scroll1              ; .. until all done
  1635.  
  1636.             pop     es                      ; restore regs
  1637.             pop     ds
  1638.             pop     di
  1639.             pop     si
  1640.             pop     cx
  1641.             ret
  1642.  
  1643. bd_scroll   endp
  1644.  
  1645.  
  1646. ; ----------------------------------------------------------------------
  1647. ;  bd_skey - handle special keys
  1648. ; ----------------------------------------------------------------------
  1649.  
  1650. bd_skey     proc    near
  1651.  
  1652. ; - see if ALT-X (Exit)
  1653.  
  1654.             cmp     ah, 2dh                 ; q. alt-X?
  1655.             jne     bd_skeyf1               ; a. no .. check f1
  1656.  
  1657.             call    popdown                 ; restore screen
  1658.             ret                             ; ..and return to caller
  1659.  
  1660.  
  1661. ; - see if F1 (Help)
  1662.  
  1663. bd_skeyf1:  cmp     ah, 3bh                 ; q. F1? (Help)
  1664.             jne     bd_skeyf2               ; a. no .. check f2
  1665.  
  1666.             mov     si, offset bd_help$     ; si -> help message
  1667.             call    disp_msg                ; display ASCIIZ msg
  1668.             ret                             ; .. return to caller
  1669.  
  1670.  
  1671. ; - see if F2 (Comm Parameters)
  1672.  
  1673. bd_skeyf2:  cmp     ah, 3ch                 ; q. F2? (Comm parms)
  1674.             jne     bd_skeyf3               ; a. no .. check f3
  1675.  
  1676.             mov     si, offset bd_set$      ; si -> parms message
  1677.             lea     di, bd_bptable          ; di -> toggle table
  1678.             call    bd_select               ; select an entry or two
  1679.             ret                             ; return to caller
  1680.  
  1681.  
  1682. ; - see if F3 (Hang Up)
  1683.  
  1684. bd_skeyf3:  cmp     ah, 3dh                 ; q. F3? (hangup)
  1685.             jne     bd_skeyf4               ; a. no .. check F4
  1686.  
  1687.             call    io_hangup               ; else .. hang it up
  1688.  
  1689.             mov     si, offset bd_hang$     ; si -> message
  1690.             call    disp_msg                ; .. display it
  1691.             ret                             ; .. return to caller
  1692.  
  1693.  
  1694. ; - see if F4 (Break)
  1695.  
  1696. bd_skeyf4:  cmp     ah, 3eh                 ; q. F4? (Break)
  1697.             jne     bd_skeyf9               ; a. no .. check F8
  1698.  
  1699.             call    io_break                ; else .. send a break
  1700.  
  1701.             mov     si, offset bd_break$    ; si -> message
  1702.             call    disp_msg                ; .. display it
  1703.             ret                             ; .. return to caller
  1704.  
  1705.  
  1706. ; - see if F9 (Download)
  1707.  
  1708. bd_skeyf9:  cmp     ah, 43h                 ; q. F9? (Download)
  1709.             jne     bd_skeyf10              ; a. no .. see if script
  1710.  
  1711.             mov     bx, offset bdprot1      ; bx -> 1st protocol
  1712.             lea     si, prottype            ; si -> "Type " string
  1713.             mov     cx, bdprotn             ; cx = loop count
  1714.  
  1715.             or      cx, cx                  ; q. any protocol modules?
  1716.             jnz     bd_skf9_10              ; a. yes .. continue
  1717.  
  1718.             lea     si, noprots             ; si -> sorry none there msg
  1719.             call    disp_msg                ; display error msg
  1720.             ret                             ; ..and return to caller
  1721.  
  1722. bd_skf9_10: call    disp_msg                ; display header msg
  1723.  
  1724.             mov     al, [bx].bdpchar        ; al = protocol letter
  1725.             call    bd_disp                 ; put it out
  1726.  
  1727.             lea     si, proteq              ; si -> " = " msg
  1728.             call    disp_msg                ; put it out too
  1729.  
  1730.             lea     si, [bx].bdpname        ; si -> protocol name
  1731.             call    disp_msg                ; display it also
  1732.  
  1733.             lea     si, protnl              ; si -> <CR>"   "
  1734.             add     bx, bdprotlen           ; bx -> next table entry
  1735.             loop    bd_skf9_10              ; ..loop up till done
  1736.  
  1737.             mov     script_wsl, 0           ; reset string length
  1738.             lea     si, bd_prompt           ; si -> prompt
  1739.             call    disp_msg                ; display prompt
  1740.  
  1741. bd_skf9_20: call    get_line                ; q. get a complete line?
  1742.             jnc     bd_skf9_20              ; a. no .. try again
  1743.  
  1744.             mov     di, offset script_ws    ; di -> inputted line
  1745.  
  1746.             cmp     byte ptr [di], 0        ; q. user enter anything?
  1747.             je      bd_skf9_30              ; a. no .. just continue
  1748.  
  1749.             mov     bd_isi, di              ; save user response
  1750.             add     main_state, 2           ; show download active
  1751.  
  1752. bd_skf9_30: call    exec_crlf               ; do a cr/lf
  1753.             ret                             ; ..and return to caller
  1754.  
  1755.  
  1756. ; - see if F10 (Run Script)
  1757.  
  1758. bd_skeyf10: cmp     ah, 44h                 ; q. F10? (Script)
  1759.             jne     bd_skey90               ; a. no .. error beep
  1760.  
  1761.             mov     script_wsl, 0           ; reset string length
  1762.             mov     si, offset script_pt    ; si -> script prompt
  1763.             call    disp_msg                ; display prompt
  1764.  
  1765. bd_skf10_1: call    get_line                ; q. get a complete line?
  1766.             jnc     bd_skf10_1              ; a. no .. try again
  1767.  
  1768.             mov     di, offset script_ws    ; di -> inputted line
  1769.             mov     script_isi, di          ; save script name
  1770.             mov     main_state, 4           ; show script state
  1771.             call    exec_crlf               ; do a cr/lf
  1772.             ret                             ; ..and return to caller
  1773.  
  1774. bd_skey90:  mov     al, 07h                 ; al = beep
  1775.             call    bd_disp                 ; ..tell 'em about the key
  1776.             ret                             ; ..return to caller
  1777.  
  1778. bd_skey     endp
  1779.  
  1780.  
  1781.  
  1782. ; ----------------------------------------------------------------------
  1783. ;   bd_key - see if key available, get it if there is
  1784. ;
  1785. ;   exit: ah = scan code
  1786. ;         al = ASCII or 0
  1787. ;         carry set = no key
  1788. ; ----------------------------------------------------------------------
  1789.  
  1790. bd_key      proc    near
  1791.  
  1792.             cmp     tsr_active, 0           ; q. popped up?
  1793.             je      bd_key05                ; a. no .. no key available
  1794.  
  1795.             mov     ah, 1                   ; ah = get kb status
  1796.  
  1797.             int     16h                     ; q. any key hit?
  1798.             jnz     bd_key10                ; a. yes .. get the key
  1799.  
  1800. bd_key05:   stc                             ; show no key available
  1801.             ret                             ; .. return to caller
  1802.  
  1803. bd_key10:   mov     ah, 0                   ; ah = get keystroke
  1804.             int     16h                     ; .. read the kb
  1805.  
  1806.             call    ck_dtr                  ; check for DTR active
  1807.  
  1808.             clc                             ; show key available
  1809.             ret                             ; .. return to caller
  1810.  
  1811. bd_key      endp
  1812.  
  1813.  
  1814.  
  1815. ; ----------------------------------------------------------------------
  1816. ;   bd_select - Get/process key against menu table
  1817. ;
  1818. ;   entry: bx =  table entry length
  1819. ;          si -> header message
  1820. ;          di -> table to process against
  1821. ; ----------------------------------------------------------------------
  1822.  
  1823. bd_select   proc
  1824.  
  1825. bd_selec10: call    disp_msg                ; display the message
  1826.  
  1827. bd_selec20: call    bd_key                  ; get a key
  1828.             jc      bd_selec20              ; .. try again if none
  1829.  
  1830.             cmp     al, 0dh                 ; q. <CR>?
  1831.             jnz     bd_selec30              ; a. no .. continue
  1832.  
  1833.             mov     si, offset bd_cr$       ; si -> ASCIIZ <CR>
  1834.             call    disp_msg                ; .. display it
  1835.             ret                             ; return to caller
  1836.  
  1837. bd_selec30: call    comp_ul                 ; al = uppercase letter
  1838.             mov     si, di                  ; si -> table to work with
  1839.  
  1840. bd_selec40: cmp     byte ptr [si], 0        ; q. end of list?
  1841.             je      bd_selec20              ; a. yes .. wait for good val
  1842.  
  1843.             cmp     al, [si]                ; q. this entry?
  1844.             je      bd_selec50              ; a. yes .. process it
  1845.  
  1846.             add     si, 12                  ; si -> a little way down string
  1847.  
  1848. bd_selec45: cmp     byte ptr [si-1], 0      ; q. hit end of string?
  1849.             je      bd_selec40              ; a. yes .. check next operand
  1850.  
  1851.             inc     si                      ; si -> next character
  1852.             jmp     bd_selec45              ; ..check next char for EOS
  1853.  
  1854. bd_selec50: call    word ptr [si+2]         ; call routine for key
  1855.  
  1856.             add     si, 4                   ; si -> message
  1857.             call    disp_msg                ; .. display it
  1858.  
  1859.             lea     si, bd_set1$            ; si -> continuation message
  1860.             jmp     bd_selec10              ; ..loop up and try for another
  1861.  
  1862. bd_select   endp
  1863.  
  1864.  
  1865.  
  1866. ; ----------------------------------------------------------------------
  1867. ;   bd_selbaud - process baud selections
  1868. ;
  1869. ;   entry: si -> table entry
  1870. ; ----------------------------------------------------------------------
  1871.  
  1872. bd_selbaud  proc
  1873.  
  1874.             mov     al, [si+1]              ; al = divisor / 2
  1875.             xor     ah, ah                  ; ax = cast to (int)
  1876.             shl     ax, 1                   ; ax = baud divisor
  1877.             mov     io_bdiv, ax             ; ..save value
  1878.             call    io_init                 ; set the baud rate
  1879.             ret                             ; ..then return to caller
  1880.  
  1881. bd_selbaud  endp
  1882.  
  1883.  
  1884.  
  1885. ; ----------------------------------------------------------------------
  1886. ;   bd_selline - process line selections
  1887. ;
  1888. ;   entry: si -> table entry
  1889. ; ----------------------------------------------------------------------
  1890.  
  1891. bd_selline  proc
  1892.  
  1893.             mov     al, [si+1]              ; al = lcr setting
  1894.             mov     io_lcr, al              ; save for init routine
  1895.             call    io_init                 ; set the comm parms
  1896.             ret                             ; ..then return to caller
  1897.  
  1898. bd_selline  endp
  1899.  
  1900.  
  1901.  
  1902. ; ----------------------------------------------------------------------
  1903. ;   bd_selbp - process B+ toggle
  1904. ;
  1905. ;   entry: si -> table entry
  1906. ; ----------------------------------------------------------------------
  1907.  
  1908. bd_selbp    proc
  1909.  
  1910.             mov     al, [si+1]              ; al = flag setting
  1911.             mov     enq_flag, al            ; save for terminal routine
  1912.             ret                             ; ..then return to caller
  1913.  
  1914. bd_selbp    endp
  1915.  
  1916.  
  1917.  
  1918. ; ----------------------------------------------------------------------
  1919. ;   bd_sel78 - process 7/8 bit display
  1920. ;
  1921. ;   entry: si -> table entry
  1922. ; ----------------------------------------------------------------------
  1923.  
  1924. bd_sel78    proc
  1925.  
  1926.             mov     al, [si+1]              ; al = flag setting
  1927.             mov     data_7flag, al          ; save for terminal routine
  1928.             ret                             ; ..then return to caller
  1929.  
  1930. bd_sel78    endp
  1931.  
  1932.  
  1933.  
  1934. ; ----------------------------------------------------------------------
  1935. ;   bd_bpstuff - handle CIS B+ launch sequences and 7 bit ASCII data
  1936. ;
  1937. ;   entry: al = character
  1938. ;    exit: carry = character processed
  1939. ; ----------------------------------------------------------------------
  1940.  
  1941. bd_bpstuff  proc
  1942.  
  1943.             cmp     enq_flag, 0             ; q. allow CIS B+ sequences?
  1944.             je      bd_bpstu50              ; a. no .. continue
  1945.  
  1946.             cmp     al, 5                   ; q. ENQ character?
  1947.             jne     bd_bpstu30              ; a. no .. continue
  1948.  
  1949.             mov     cx, 5                   ; cx = count
  1950.             lea     si, bd_bpinit           ; si -> init data
  1951.  
  1952. bd_bpstu10: lodsb                           ; al = char to display
  1953.             call    ch_send                 ; put out a character
  1954.             loop    bd_bpstu10              ; ..and loop back for next
  1955.  
  1956.             lea     di, bd_userdata         ; di -> B+ user data
  1957.             mov     ax, 3000h               ; ax = init constant
  1958.             stosw                           ; ..save in user area
  1959.  
  1960.             mov     cx, 4                   ; cx = repeat count
  1961.             mov     ax, 0ffffh              ; ax = init constant
  1962.        rep  stosw                           ; initialize user area
  1963.  
  1964.             stc                             ; carry = character processed
  1965.             ret                             ; ..return to caller
  1966.  
  1967. bd_bpstu30: cmp     al, 10h                 ; q. DLE character?
  1968.             jne     bd_bpstu50              ; a. no .. continue
  1969.  
  1970.             mov     bd_isi, offset bd_bstring   ; save addr of proto cmd
  1971.             add     main_state, 2               ; show download active
  1972.  
  1973.             stc                             ; carry = character processed
  1974.             ret                             ; ..return to caller
  1975.  
  1976. bd_bpstu50: cmp     data_7flag, 0           ; q. need to trim 7 bits?
  1977.             je      bd_bpstu90              ; a. no .. continue
  1978.  
  1979.             and     al, 07fh                ; al = trimmed to size
  1980.  
  1981. bd_bpstu90: clc                             ; carry = not processed
  1982.             ret                             ; ..and return to caller
  1983.  
  1984. bd_bpstuff  endp
  1985.  
  1986.  
  1987.  
  1988. ; ----------------------------------------------------------------------
  1989. ;   bd_dnld - interface to protocols
  1990. ;
  1991. ;   when calling protocol module
  1992. ;       ax = current tick downcounter
  1993. ;
  1994. ;       di =  0 initialization call         bx -> oper  dx = prot nbr
  1995. ;             2 last fnc ok | wasting time
  1996. ;             4 last fnc requested failed
  1997. ;             6 comm character              dl = character
  1998. ;             8 keyboard character          dl = character
  1999. ;
  2000. ;   return from protocol module
  2001. ;       di =  0 ok
  2002. ;             2 open output file            bx -> filename
  2003. ;             4 write file                  bx -> 2cnt + data
  2004. ;             6 close file
  2005. ;             8 delete file                 bx -> filename
  2006. ;            10 done
  2007. ;            12 display an ASCIIZ string    bx -> string
  2008. ;            14 display one character       bl = character
  2009. ;            16 get a line                  bx -> area
  2010. ;            18 send characters over comm   bx -> 2cnt + data
  2011. ;            20 send one character          bl = character
  2012. ;            22 set tick downcounter        bx = count
  2013. ;            24 display without <CR> xlate  bx -> string
  2014. ;
  2015. ; ----------------------------------------------------------------------
  2016.  
  2017. bd_dnld     proc
  2018.  
  2019.             mov     bx, bd_work             ; bx = work register
  2020.             mov     di, bd_state            ; di = current state
  2021.  
  2022. bd_dnld10:  call    bd_table[di]            ; call current state routine
  2023.             jc      bd_dnld10               ; ..loop again
  2024.  
  2025.             mov     bd_state, di            ; save state for next time
  2026.             mov     bd_work, bx             ; ..and work register
  2027.  
  2028.             ret                             ; return to caller
  2029.  
  2030. bd_dnld     endp
  2031.  
  2032.  
  2033.  
  2034. ; ----------------------------------------------------------------------
  2035. ;   bd_failed - last function request failed
  2036. ; ----------------------------------------------------------------------
  2037.  
  2038. bd_failed   proc
  2039.  
  2040.             mov     di, 4                   ; di = fail fnc code
  2041.             mov     ax, tick_wait           ; ax = current tick value
  2042.             call    dword ptr bd_proto      ; call protocol
  2043.  
  2044.             clc                             ; clear carry = wait
  2045.             ret                             ; ..and return to caller
  2046.  
  2047. bd_failed   endp
  2048.  
  2049.  
  2050.  
  2051. ; ----------------------------------------------------------------------
  2052. ;   bd_init - load and initialize a protocol
  2053. ; ----------------------------------------------------------------------
  2054.  
  2055. bd_init     proc
  2056.  
  2057.             call    setupdos                ; q. dos available?
  2058.             jnc     bd_init10               ; a. yes .. continue
  2059.  
  2060.             clc                             ; clear carry ..
  2061.             ret                             ; else .. return to caller
  2062.  
  2063. bd_init10:  call    bd_lookup               ; q. find bdp name/size
  2064.             jnc     bd_init20               ; a. yes .. continue
  2065.  
  2066.             call    swap_psp                ; swap psp's again
  2067.             mov     si, offset badproto     ; si -> error message
  2068.             jmp     short bd_init95         ; ..display and return
  2069.  
  2070. bd_init20:  push    bx                      ; save registers
  2071.             push    cx                      ;
  2072.  
  2073.             mov     ax, 3d00h               ; ax = open file
  2074.             int     21h                     ; issue DOS call
  2075.             jnc     bd_init30               ; ..if ok, continue
  2076.  
  2077.             call    swap_psp                ; swap psp's again
  2078.             mov     si, offset protonfnd    ; si -> file not found
  2079.             jmp     short bd_init95         ; ..display msg and return
  2080.  
  2081. bd_init30:  mov     bx, ax                  ; bx = file handle
  2082.             mov     ah, 3fh                 ; ah = read file
  2083.             mov     cx, bdplen              ; cx = bdp overlay size
  2084.             mov     dx, bd_offset           ; dx -> overlay area
  2085.             int     21h                     ; issue DOS call
  2086.  
  2087.             mov     ah, 3eh                 ; ah = close file
  2088.             int     21h                     ; issue DOS call
  2089.  
  2090.             call    swap_psp                ; swap psp's again
  2091.             xor     di, di                  ; di = init call to protocol
  2092.             pop     dx                      ; dx = protocol nbr
  2093.             pop     bx                      ; ds:bx -> operands
  2094.  
  2095.             mov     ax, tick_wait           ; ax = current tick value
  2096.             lea     si, bd_userdata         ; si -> user area
  2097.             call    dword ptr bd_proto      ; call protocol
  2098.  
  2099.             clc                             ; clear carry = wait
  2100.             ret                             ; ..then return to caller
  2101.  
  2102. bd_init95:  call    disp_msg                ; display the error msg
  2103.  
  2104.             sub     main_state, 2           ; reset state to term/script
  2105.             mov     di, -2                  ; di = init state
  2106.             clc                             ; clear carry ..
  2107.             ret                             ; else .. return to caller
  2108.  
  2109. bd_init     endp
  2110.  
  2111.  
  2112.  
  2113. ; ----------------------------------------------------------------------
  2114. ;   bd_lookup - lookup protocol in table
  2115. ;
  2116. ;   entry: bd_isi -> entered string
  2117. ;    exit: dx -> filename to load
  2118. ;          bx -> operands to protocol
  2119. ;          cx =  protocol number
  2120. ; ----------------------------------------------------------------------
  2121.  
  2122. bd_lookup   proc
  2123.  
  2124.             mov     bx, bd_isi              ; bx -> operands string
  2125.             mov     bd_isi, 0               ; clear string pointer
  2126.             mov     next_token, bx          ; setup tokenizer
  2127.  
  2128.             call    token                   ; di -> protocol letter
  2129.             mov     al, [di]                ; al = requested protocol
  2130.             call    comp_ul                 ; al = uppercase letter
  2131.  
  2132.             mov     bx, offset bdprot1      ; bx -> table of protocols
  2133.             mov     cx, bdprotn             ; cx = nbr of entries
  2134.  
  2135. bd_look10:  cmp     al, [bx].bdpchar        ; q. find table entry?
  2136.             je      bd_look20               ; a. yes .. exit loop
  2137.  
  2138.             add     bx, bdprotlen           ; bx -> next table entry
  2139.             loop    bd_look10               ; ..loop till found/done
  2140.  
  2141.             stc                             ; carry = not found
  2142.             ret                             ; ..then return to caller
  2143.  
  2144. bd_look20:  lea     dx, [bx].bdpfile        ; dx -> filename
  2145.             mov     cl, [bx].bdpnbr         ; cl = protocol nbr
  2146.             xor     ch, ch                  ; cx = (int) protocol nbr
  2147.  
  2148.             call    next                    ; di -> next operand
  2149.             mov     bx, di                  ; bx -> next operand
  2150.             clc                             ; clear carry = ok
  2151.             ret                             ; ..just return to caller
  2152.  
  2153. bd_lookup   endp
  2154.  
  2155.  
  2156.  
  2157. ; ----------------------------------------------------------------------
  2158. ;   bd_ok - last function request succeeded
  2159. ; ----------------------------------------------------------------------
  2160.  
  2161. bd_ok       proc
  2162.  
  2163.             mov     di, 2                   ; di = ok fnc code
  2164.             mov     ax, tick_wait           ; ax = current tick value
  2165.             call    dword ptr bd_proto      ; call protocol
  2166.  
  2167.             clc                             ; clear carry = wait
  2168.             ret                             ; ..and return to caller
  2169.  
  2170. bd_ok       endp
  2171.  
  2172.  
  2173.  
  2174. ; ----------------------------------------------------------------------
  2175. ;   bd_call - things ok, just call protocol
  2176. ; ----------------------------------------------------------------------
  2177.  
  2178. bd_call     proc
  2179.  
  2180.             call    ch_get                  ; q. get a comm character?
  2181.             jc      bd_call20               ; a. no .. check keyboard
  2182.  
  2183.             mov     di, 6                   ; di = comm char coming
  2184.             mov     dl, al                  ; dl = character
  2185.             jmp     short bd_call50         ; ..continue with common code
  2186.  
  2187. bd_call20:  call    bd_key                  ; q. get a keyboard character?
  2188.             jc      bd_call40               ; a. no .. continue
  2189.  
  2190.             cmp     ax, 2d00h               ; q. Alt-X, pop down?
  2191.             jne     bd_call30               ; a. no .. continue
  2192.  
  2193.             call    popdown                 ; else .. close down our window
  2194.             jmp     short bd_call40         ; ..and call with "all ok"
  2195.  
  2196. bd_call30:  mov     di, 8                   ; di = keyboard char coming
  2197.             mov     dx, ax                  ; dx = scan code & character
  2198.             jmp     short bd_call50         ; ..continue with common code
  2199.  
  2200. bd_call40:  mov     di, 2                   ; di = everything's ok
  2201.  
  2202. bd_call50:  mov     ax, tick_wait           ; ax = current tick value
  2203.             call    dword ptr bd_proto      ; call protocol
  2204.  
  2205.             clc                             ; clear carry = wait
  2206.             ret                             ; ..and return to caller
  2207.  
  2208. bd_call     endp
  2209.  
  2210.  
  2211.  
  2212. ; ----------------------------------------------------------------------
  2213. ;   bd_open - open an output file for the protocol
  2214. ; ----------------------------------------------------------------------
  2215.  
  2216. bd_open     proc
  2217.  
  2218.             call    setupdos                ; q. dos available?
  2219.             jnc     bd_open10               ; a. yes .. continue
  2220.  
  2221.             clc                             ; clear carry ..
  2222.             ret                             ; else .. return to caller
  2223.  
  2224. bd_open10:  add     bx, bd_offset           ; bx -> file name in dl memory
  2225.  
  2226.             mov     ah, 3ch                 ; ah = create function
  2227.             mov     cx, 0                   ; cx = normal file attribute
  2228.             mov     dx, bx                  ; ds:dx -> string
  2229.             int     21h                     ; issue DOS call
  2230.             jc      bd_open90               ; ..on error try again
  2231.  
  2232.             mov     bd_handle, ax           ; save the handle
  2233.             mov     di, -6                  ; di = request ok
  2234.             jmp     short bd_open95         ; ..and exit via common point
  2235.  
  2236. bd_open90:  mov     di, -4                  ; di = request failed
  2237. bd_open95:  call    swap_psp                ; swap caller psp back
  2238.             stc                             ; carry = do next state now
  2239.             ret                             ; ..then return to caller
  2240.  
  2241. bd_open     endp
  2242.  
  2243.  
  2244.  
  2245. ; ----------------------------------------------------------------------
  2246. ;   bd_write - write file
  2247. ; ----------------------------------------------------------------------
  2248.  
  2249. bd_write    proc
  2250.  
  2251.             call    setupdos                ; q. dos available?
  2252.             jnc     bd_write10              ; a. yes .. continue
  2253.  
  2254.             clc                             ; clear carry ..
  2255.             ret                             ; else .. return to caller
  2256.  
  2257. bd_write10: add     bx, bd_offset           ; bx -> count and data
  2258.  
  2259.             mov     ah, 40h                 ; ah = write file
  2260.             mov     cx, [bx]                ; cx = count
  2261.             lea     dx, [bx+2]              ; dx -> data
  2262.             mov     bx, bd_handle           ; bx = file handle
  2263.             int     21h                     ; issue DOS call
  2264.             jc      bd_write90              ; ..on error try again
  2265.  
  2266.             mov     di, -6                  ; di = request ok
  2267.             jmp     short bd_write95        ; ..and exit via common point
  2268.  
  2269. bd_write90: mov     di, -4                  ; di = request failed
  2270. bd_write95: call    swap_psp                ; swap caller psp back
  2271.             stc                             ; carry = do next state now
  2272.             ret                             ; ..then return to caller
  2273.  
  2274. bd_write    endp
  2275.  
  2276.  
  2277.  
  2278. ; ----------------------------------------------------------------------
  2279. ;   bd_close - close file
  2280. ; ----------------------------------------------------------------------
  2281.  
  2282. bd_close    proc
  2283.  
  2284.             call    setupdos                ; q. dos available?
  2285.             jnc     bd_close10              ; a. yes .. continue
  2286.  
  2287.             clc                             ; clear carry ..
  2288.             ret                             ; else .. return to caller
  2289.  
  2290. bd_close10: mov     ah, 3eh                 ; ah = close file
  2291.             mov     bx, bd_handle           ; bx = file handle
  2292.             int     21h                     ; issue DOS call
  2293.  
  2294.             call    swap_psp                ; swap caller psp back
  2295.             mov     bd_handle, 0            ; clear file handle field
  2296.             mov     di, -6                  ; di = request ok
  2297.             stc                             ; carry = do next state now
  2298.             ret                             ; ..then return to caller
  2299.  
  2300. bd_close    endp
  2301.  
  2302.  
  2303.  
  2304. ; ----------------------------------------------------------------------
  2305. ;   bd_delete - delete file
  2306. ; ----------------------------------------------------------------------
  2307.  
  2308. bd_delete   proc
  2309.  
  2310.             call    setupdos                ; q. dos available?
  2311.             jnc     bd_delet10              ; a. yes .. continue
  2312.  
  2313.             clc                             ; clear carry ..
  2314.             ret                             ; else .. return to caller
  2315.  
  2316. bd_delet10: push    bx                      ; save register
  2317.  
  2318.             mov     ah, 3eh                 ; ah = close file
  2319.             mov     bx, bd_handle           ; bx = file handle
  2320.             int     21h                     ; issue DOS call
  2321.  
  2322.             pop     bx                      ; restore register
  2323.             add     bx, bd_offset           ; bx -> filename to delete
  2324.             mov     ah, 41h                 ; ah = delete file
  2325.             mov     dx, bx                  ; ds:dx -> filename
  2326.             int     21h                     ; issue DOS call
  2327.  
  2328.             call    swap_psp                ; swap caller's psp back
  2329.             mov     di, -6                  ; di = request ok
  2330.             stc                             ; carry = do next state now
  2331.             ret                             ; ..then return to caller
  2332.  
  2333. bd_delete   endp
  2334.  
  2335.  
  2336.  
  2337. ; ----------------------------------------------------------------------
  2338. ;   bd_done - download finished
  2339. ; ----------------------------------------------------------------------
  2340.  
  2341. bd_done     proc
  2342.  
  2343.             mov     bx, bd_handle           ; bx = file handle
  2344.  
  2345.             or      bx, bx                  ; q. file open?
  2346.             jz      bd_done80               ; a. no .. continue
  2347.  
  2348.             call    setupdos                ; q. dos usable?
  2349.             jc      bd_done90               ; a. no .. continue                   
  2350.  
  2351.             mov     ah, 3eh                 ; ah = close file
  2352.             int     21h                     ; issue DOS call
  2353.  
  2354.             call    swap_psp                ; swap caller psp back
  2355.  
  2356. bd_done80:  sub     main_state, 2           ; reset state to term/script
  2357.             mov     di, -2                  ; di = init state
  2358.  
  2359.             cmp     tsr_active, 0           ; q. already pop'd up?
  2360.             jne     bd_done90               ; a. yes .. skip request
  2361.  
  2362.             cmp     main_state, 0           ; q. terminal mode again?
  2363.             jne     bd_done90               ; a. no .. probaly script
  2364.  
  2365.             inc     tsr_req                 ; else .. make window popup
  2366.  
  2367. bd_done90:  clc                             ; ..ensure we leave the loop
  2368.             ret                             ; ..and return to caller
  2369.  
  2370. bd_done     endp
  2371.  
  2372.  
  2373.  
  2374. ; ----------------------------------------------------------------------
  2375. ;   bd_dstring - display a null terminated string
  2376. ; ----------------------------------------------------------------------
  2377.  
  2378. bd_dstring  proc
  2379.  
  2380.             add     bx, bd_offset           ; bx -> protocol's msg
  2381.             mov     si, bx                  ; si -> msg
  2382.             call    disp_msg                ; call display
  2383.  
  2384.             mov     di, -6                  ; di = request ok
  2385.             stc                             ; carry = do next state now
  2386.             ret                             ; ..then return to caller
  2387.  
  2388. bd_dstring  endp
  2389.  
  2390.  
  2391.  
  2392. ; ----------------------------------------------------------------------
  2393. ;   bd_xstring - display a null terminated string without <CR> translate
  2394. ; ----------------------------------------------------------------------
  2395.  
  2396. bd_xstring  proc
  2397.  
  2398.             add     bx, bd_offset           ; bx -> protocol's msg
  2399.             mov     si, bx                  ; si -> msg
  2400.  
  2401. bd_xstr10:  lodsb                           ; al = char to display
  2402.  
  2403.             or      al, al                  ; q. end of string?
  2404.             jz      bd_xstr90               ; a. yes .. leave
  2405.  
  2406.             call    bd_disp                 ; display the char
  2407.             jmp     bd_xstr10               ; .. get next char
  2408.  
  2409. bd_xstr90:  mov     di, -6                  ; di = request ok
  2410.             stc                             ; carry = do next state now
  2411.             ret                             ; ..then return to caller
  2412.  
  2413. bd_xstring  endp
  2414.  
  2415.  
  2416.  
  2417.  
  2418. ; ----------------------------------------------------------------------
  2419. ;   bd_dbyte - display a character
  2420. ; ----------------------------------------------------------------------
  2421.  
  2422. bd_dbyte    proc
  2423.  
  2424.             mov     al, bl                  ; al = character to display
  2425.             call    exec_dispx              ; call display one character
  2426.  
  2427.             mov     di, -6                  ; di = request ok
  2428.             stc                             ; carry = do next state now
  2429.             ret                             ; ..then return to caller
  2430.  
  2431. bd_dbyte    endp
  2432.  
  2433.  
  2434.  
  2435. ; ----------------------------------------------------------------------
  2436. ;   bd_gstring - get a string from user
  2437. ; ----------------------------------------------------------------------
  2438.  
  2439. bd_gstring  proc                            ; initialization procedure
  2440.  
  2441.             mov     script_wsl, 0           ; clear length byte
  2442.             mov     di, -8                  ; di = wait state for get string
  2443.             stc                             ; carry = do next state now
  2444.             ret                             ; ..then return to caller
  2445.  
  2446. bd_gstring  endp
  2447.  
  2448.  
  2449. bd_gstringx proc                            ; wait procedure
  2450.  
  2451.             call    get_line                ; q. get a whole line?
  2452.             jc      bd_gstr10               ; a. yes .. continue
  2453.  
  2454.             clc                             ; clear carry = wait a little
  2455.             ret                             ; ..and return to caller
  2456.  
  2457. bd_gstr10:  add     bx, bd_offset           ; bx -> user's data area
  2458.             mov     cx, script_wsl          ; cx = length
  2459.             mov     si, offset script_ws    ; si -> work area
  2460.             mov     di, bx                  ; di -> destination
  2461.             call    string_copy             ; copy to protocol's area
  2462.  
  2463.             mov     di, -6                  ; di = request ok
  2464.             stc                             ; carry = do next state now
  2465.             ret                             ; ..then return to caller
  2466.  
  2467. bd_gstringx endp
  2468.  
  2469.  
  2470.  
  2471. ; ----------------------------------------------------------------------
  2472. ;   bd_sstring - send a string out the comm port
  2473. ; ----------------------------------------------------------------------
  2474.  
  2475. bd_sstring  proc
  2476.  
  2477.             add     bx, bd_offset           ; bx -> string to send
  2478.             mov     cx, [bx]                ; cx = count
  2479.             lea     si, [bx + 2]            ; si -> data
  2480.  
  2481. bd_sstr10:  lodsb                           ; al = char to display
  2482.             call    ch_send                 ; put out a character
  2483.             loop    bd_sstr10               ; ..and loop back for next
  2484.  
  2485.             mov     di, -6                  ; di = request ok
  2486.             stc                             ; carry = do next state now
  2487.             ret                             ; ..then return to caller
  2488.  
  2489. bd_sstring  endp
  2490.  
  2491.  
  2492.  
  2493. ; ----------------------------------------------------------------------
  2494. ;   bd_sbyte - send a byte out the comm port
  2495. ; ----------------------------------------------------------------------
  2496.  
  2497. bd_sbyte    proc
  2498.  
  2499.             mov     al, bl                  ; al = character to send
  2500.             call    ch_send                 ; put out a character
  2501.  
  2502.             mov     di, -6                  ; di = request ok
  2503.             stc                             ; carry = do next state now
  2504.             ret                             ; ..then return to caller
  2505.  
  2506. bd_sbyte    endp
  2507.  
  2508.  
  2509.  
  2510. ; ----------------------------------------------------------------------
  2511. ;   bd_ticks - set the down counter timer
  2512. ; ----------------------------------------------------------------------
  2513.  
  2514. bd_ticks    proc
  2515.  
  2516.             mov     tick_wait, bx           ; set downcounter
  2517.  
  2518.             mov     di, -6                  ; di = request ok
  2519.             stc                             ; carry = do next state now
  2520.             ret                             ; ..then return to caller
  2521.  
  2522. bd_ticks    endp
  2523.  
  2524.  
  2525.  
  2526. ; ----------------------------------------------------------------------
  2527. ;   setupdos - setup to use DOS
  2528. ;
  2529. ;   exit: carry = DOS isn't ready yet
  2530. ; ----------------------------------------------------------------------
  2531.  
  2532. setupdos    proc
  2533.  
  2534.             call    usingdos                ; q. can we use DOS?
  2535.             jc      setupdos90              ; a. no .. return to caller
  2536.  
  2537.             call    swap_psp                ; swap psp and handlers
  2538.             clc                             ; clear carry flag
  2539. setupdos90: ret                             ; ..and return to caller
  2540.  
  2541. setupdos    endp
  2542.  
  2543.  
  2544.  
  2545. ; ----------------------------------------------------------------------
  2546. ;   exec_script - script state machine dispatcher
  2547. ; ----------------------------------------------------------------------
  2548.  
  2549. exec_script proc
  2550.             push    ax                      ; save registers
  2551.             push    bx
  2552.             push    cx
  2553.             push    dx
  2554.             push    si
  2555.             push    di
  2556.             push    es
  2557.  
  2558.             call    exec_term               ; display incoming
  2559.             jc      exec_scr90              ; ..and exit if ENQ recieved
  2560.  
  2561.             call    exec_key                ; handle keyboard
  2562.  
  2563.             mov     bl, script_cs           ; bl = current state number
  2564.             xor     bh, bh                  ; bx = cmd number
  2565.             shl     bx, 1                   ; bx = command offset
  2566.             mov     si, script_wrk          ; si -> compiled command
  2567.             call    exec_cmds[bx]           ; call current state rtn
  2568.  
  2569.             call    exec_cancel             ; check for cancel request
  2570.  
  2571.             mov     script_wrk, si          ; save current location
  2572.  
  2573. exec_scr90: pop     es                      ; restore registers
  2574.             pop     di
  2575.             pop     si
  2576.             pop     dx
  2577.             pop     cx
  2578.             pop     bx
  2579.             pop     ax
  2580.             ret                             ; ..then return to caller
  2581.  
  2582. exec_script endp
  2583.  
  2584.  
  2585.  
  2586. ; ----------------------------------------------------------------------
  2587. ;   exec_start - start script execution
  2588. ;
  2589. ;   entry: script_isi -> script name/parms
  2590. ;    exit: si -> start of script
  2591. ; ----------------------------------------------------------------------
  2592.  
  2593. exec_start  proc
  2594.  
  2595.             mov     si, script_isi          ; si -> script name/parms
  2596.  
  2597.             or      si, si                  ; q. anything there?
  2598.             jnz     exec_sta00              ; a. yes .. try to open it
  2599.  
  2600.             ret                             ; else .. just return
  2601.  
  2602. exec_sta00: call    usingdos                ; q. using DOS?
  2603.             jnc     exec_sta05              ; a. no .. continue
  2604.  
  2605.             ret                             ; else .. just return
  2606.  
  2607. exec_sta05: mov     script_isi, 0           ; clear script name pointer
  2608.             mov     cancel_flag, 0          ; ..and cancel flag
  2609.             mov     next_token, si          ; save start of command
  2610.  
  2611.             call    token                   ; di -> filename
  2612.             jnc     exec_sta10              ; if ok, continue
  2613.  
  2614.             call    exec_done               ; clean up ..
  2615.             ret                             ; ..and return
  2616.  
  2617. exec_sta10: call    string_len              ; cx = string length
  2618.             mov     si, offset script_fn    ; si -> script filename
  2619.             push    si                      ; save registers
  2620.             push    si                      ;
  2621.             xchg    si, di                  ; si -> token, di -> field
  2622.             call    string_copy             ; copy script filename local
  2623.  
  2624.             pop     di                      ; di -> script filename
  2625.             mov     al, '.'                 ; al = search character
  2626.  
  2627.       repne scasb                           ; q. find the period?
  2628.             je      exec_sta15              ; a. yes .. continue
  2629.  
  2630.             mov     cx, 5                   ; cx = length of .ext
  2631.             mov     si, offset dot_bdc      ; si -> compiled script extension
  2632.             call    string_copy             ; copy our extension
  2633.  
  2634. exec_sta15: pop     dx                      ; dx -> script filename
  2635.             call    swap_psp                ; swap psp's
  2636.  
  2637.             mov     ax, 3d00h               ; ax = open file for read
  2638.             int     21h                     ; call DOS function
  2639.             jnc     exec_sta20              ; ..if ok, continue
  2640.  
  2641.             call    swap_psp                ; swap psp's back
  2642.             mov     si, offset exec_fnf     ; si -> script not found msg
  2643.             call    disp_msg                ; put out message
  2644.             call    exec_done               ; reset our state
  2645.             ret                             ; ..and return to caller
  2646.  
  2647. exec_sta20: mov     bx, ax                  ; bx = file handle
  2648.             mov     ax, 4202h               ; ax = seek to eof
  2649.             xor     cx, cx                  ; cx = offset of zero
  2650.             xor     dx, dx                  ; dx = zero, too
  2651.             int     21h                     ; call DOS function
  2652.  
  2653.             or      dx, dx                  ; q. larger that 64k?
  2654.             jnz     exec_sta25              ; a. yes .. bad news
  2655.  
  2656.             cmp     ax, script_amt          ; q. larger than allocated space?
  2657.             jle     exec_sta30              ; a. no .. continue
  2658.  
  2659. exec_sta25: call    swap_psp                ; swap psp's back
  2660.             mov     si, offset exec_too     ; si -> script too large msg
  2661.             call    disp_msg                ; put out message
  2662.             call    exec_done               ; reset our state
  2663.             ret                             ; ..and return to caller
  2664.  
  2665. exec_sta30: push    ax                      ; save file size
  2666.             push    ax                      ; ..twice
  2667.             mov     ax, 4200h               ; ax = seek to top of file
  2668.             xor     cx, cx                  ; cx = offset of zero
  2669.             int     21h                     ; call DOS function
  2670.  
  2671.             mov     ah, 3fh                 ; ah = read file
  2672.             mov     cx, 3                   ; cx = length to read
  2673.             mov     dx, script_buf          ; ds:dx -> buffer
  2674.             int     21h                     ; call DOS function
  2675.  
  2676.             mov     si, dx                  ; si -> script buffer
  2677.             mov     ax, [si]                ; ax = 1st two bytes from file
  2678.  
  2679.             mov     dx, offset exec_nbdc    ; dx -> script not compiled
  2680.  
  2681.             cmp     ax, SCRIPT_ID           ; q. compiled file?
  2682.             jne     exec_sta35              ; a. no .. error message
  2683.  
  2684.             mov     dx, offset exec_nver    ; dx -> script wrong version
  2685.  
  2686.             mov     al, SCRIPT_VER          ; al = version supported
  2687.  
  2688.             cmp     al, [si+2]              ; q. right version?
  2689.             je      exec_sta40              ; a. yes..  continue
  2690.  
  2691. exec_sta35: mov     ah, 3eh                 ; ah = close file
  2692.             int     21h                     ; call DOS function
  2693.  
  2694.             add     sp, 4                   ; backout both pushes
  2695.             call    swap_psp                ; swap psp's back
  2696.             mov     si, dx                  ; si -> error message
  2697.             call    disp_msg                ; put out message
  2698.             call    exec_done               ; reset our state
  2699.             ret                             ; ..and return to caller
  2700.  
  2701. exec_sta40: mov     ah, 3fh                 ; ah = read file
  2702.             pop     cx                      ; cx = length to read
  2703.             mov     dx, script_buf          ; ds:dx -> buffer
  2704.             int     21h                     ; call DOS function
  2705.  
  2706.             mov     ah, 3eh                 ; ah = close file
  2707.             int     21h                     ; call DOS function
  2708.  
  2709.             call    swap_psp                ; swap psp's back
  2710.             pop     si                      ; si = length of script
  2711.             add     si, script_buf          ; si -> replacables area
  2712.             mov     cx, 9 + 26              ; cx = nbr of replacables
  2713.             mov     bx, offset replacables  ; bx -> pointer array
  2714.  
  2715. exec_sta50: call    token                   ; di -> token
  2716.             jc      exec_sta60              ; ..on error, just clear entry
  2717.  
  2718.             mov     [bx], si                ; save addr of token
  2719.  
  2720.             push    cx                      ; save registers
  2721.             call    comp_copy               ; copy to script buffer
  2722.             pop     cx                      ; restore loop count
  2723.             inc     si                      ; si -> next usable location
  2724.             jmp     short exec_sta70        ; ..continue with common code
  2725.  
  2726. exec_sta60: mov     word ptr [bx], 0        ; clear pointer entry
  2727.  
  2728. exec_sta70: add     bx, 2                   ; bx -> next pointer entry
  2729.             loop    exec_sta50              ; ..and loop till done
  2730.  
  2731.             mov     script_var, si          ; save addr for next variable
  2732.             mov     si, script_buf          ; si -> start of script
  2733.             call    exec_ncmd               ; setup to handle first cmd
  2734.  
  2735.             ret                             ; ..and returning to caller
  2736.  
  2737. exec_start  endp
  2738.  
  2739.  
  2740.  
  2741. ; ----------------------------------------------------------------------
  2742. ;   exec_ncmd - handle next command
  2743. ;
  2744. ;   entry: si -> next script command
  2745. ; ----------------------------------------------------------------------
  2746.  
  2747. exec_ncmd   proc
  2748.  
  2749.             call    ck_dtr                  ; check DTR is active
  2750.  
  2751.             mov     al, [si]                ; al = next command byte
  2752.             mov     script_cs, al           ; store as current state
  2753.             inc     si                      ; si -> command | data byte
  2754.             ret                             ; ..then return to caller
  2755.  
  2756. exec_ncmd   endp
  2757.  
  2758.  
  2759.  
  2760. ; ----------------------------------------------------------------------
  2761. ;   exec_key - handle unrequested keys during script
  2762. ; ----------------------------------------------------------------------
  2763.  
  2764. exec_key    proc
  2765.  
  2766.             cmp     script_cs, 13           ; q. waiting at a prompt?
  2767.             je      exec_key90              ; a. yes .. exit
  2768.  
  2769.             call    bd_key                  ; q. get a key?
  2770.             jc      exec_key90              ; a. no .. continue
  2771.  
  2772.             cmp     al, 1bh                 ; q. ESC key?
  2773.             jne     exec_key10              ; a. no .. continue
  2774.  
  2775.             mov     cancel_flag, 1          ; show cancel requested
  2776.             jmp     short exec_key90        ; ..and return to caller
  2777.  
  2778. exec_key10: cmp     ax, 2d00h               ; q. Alt-X, pop down?
  2779.             jne     exec_key90              ; a. no .. continue
  2780.  
  2781.             call    popdown                 ; else .. close down our window
  2782.  
  2783. exec_key90: ret                             ; ..and return to caller
  2784.  
  2785. exec_key    endp
  2786.  
  2787.  
  2788.  
  2789. ; ----------------------------------------------------------------------
  2790. ;   exec_cancel - check for cancel request
  2791. ; ----------------------------------------------------------------------
  2792.  
  2793. exec_cancel proc
  2794.  
  2795.             cmp     cancel_flag, 0          ; q. need to cancel?
  2796.             je      exec_can90              ; a. no .. continue
  2797.  
  2798.             mov     si, offset cancelmsg    ; si -> terminated msg
  2799.             call    disp_msg                ; put out message
  2800.             call    exec_done               ; cleanup/ready for next time
  2801.  
  2802. exec_can90: ret                             ; ..then return to caller
  2803.  
  2804. exec_cancel endp
  2805.  
  2806.  
  2807.  
  2808. ; ----------------------------------------------------------------------
  2809. ;   exec_done - end of script
  2810. ; ----------------------------------------------------------------------
  2811.  
  2812. exec_done   proc
  2813.  
  2814.             mov     script_cs, 14           ; clear script state
  2815.             mov     main_state, 0           ; put back in terminal mode
  2816.             inc     tsr_req                 ; make window popup
  2817.             ret                             ; ..and return to caller
  2818.  
  2819. exec_done   endp
  2820.  
  2821.  
  2822.  
  2823. ; ----------------------------------------------------------------------
  2824. ;   exec_init - port and options initialization
  2825. ; ----------------------------------------------------------------------
  2826.  
  2827. exec_init   proc
  2828.  
  2829.             xor     bx, bx                  ; bx = io_init needed flag
  2830.             mov     al, [si]                ; al = baud rate divisor
  2831.  
  2832.             or      al, al                  ; q. need to change baud?
  2833.             jz      exec_in10               ; a. no ..continue
  2834.  
  2835.             xor     ah, ah                  ; ah = cast as integer
  2836.             shl     ax, 1                   ; ax = divisor
  2837.             mov     io_bdiv, ax             ; save for init routine
  2838.             inc     bx                      ; show io_init needed
  2839.  
  2840. exec_in10:  mov     al, 1[si]               ; al = line control register
  2841.  
  2842.             or      al, al                  ; q. need to lcr?
  2843.             jz      exec_in20               ; a. no ..continue
  2844.  
  2845.             mov     io_lcr, al              ; save for init rtn too
  2846.             inc     bx                      ; show io_init needed
  2847.  
  2848. exec_in20:  or      bx, bx                  ; q. need to call io_init?
  2849.             jz      exec_in30               ; a. no .. continue
  2850.  
  2851.             call    io_init                 ; call uart init routine
  2852.  
  2853. exec_in30:  mov     al, 2[si]               ; al = 7/8 toggle info
  2854.  
  2855.             or      al, al                  ; q. changing modes?
  2856.             jz      exec_in40               ; a. no .. continue
  2857.  
  2858.             dec     al                      ; al = flag
  2859.             mov     data_7flag, al          ; setup in toggle
  2860.  
  2861. exec_in40:  mov     al, 3[si]               ; al = B+ toggle info
  2862.  
  2863.             or      al, al                  ; q. changing modes?
  2864.             jz      exec_in50               ; a. no .. continue
  2865.  
  2866.             dec     al                      ; al = flag
  2867.             mov     enq_flag, al            ; setup in toggle
  2868.  
  2869. exec_in50:  mov     al, 4[si]               ; al = case compare option
  2870.  
  2871.             or      al, al                  ; q. changing modes?
  2872.             jz      exec_in60               ; a. no .. continue
  2873.  
  2874.             dec     al                      ; al = flag
  2875.             mov     case_flag, al           ; setup in toggle
  2876.  
  2877. exec_in60:  add     si, 5                   ; si -> next command
  2878.             call    exec_ncmd               ; handle next command
  2879.             ret                             ; ..and return to caller
  2880.  
  2881. exec_init   endp
  2882.  
  2883.  
  2884.  
  2885. ; ----------------------------------------------------------------------
  2886. ;   exec_opt - display options command
  2887. ; ----------------------------------------------------------------------
  2888.  
  2889. exec_opt    proc
  2890.  
  2891.             mov     ax, [si]                ; ax = debug bits
  2892.             mov     script_dm, ax           ; save display mask
  2893.             add     si, 2                   ; si -> next command
  2894.             call    exec_ncmd               ; handle next command
  2895.             ret                             ; ..and return to caller
  2896.  
  2897. exec_opt    endp
  2898.  
  2899.  
  2900. ; ----------------------------------------------------------------------
  2901. ;   exec_send - send text to host computer
  2902. ; ----------------------------------------------------------------------
  2903.  
  2904. exec_send   proc
  2905.  
  2906.             test    script_dm, 2            ; q. display outgoing?
  2907.             jz      exec_se10               ; a. no .. continue
  2908.  
  2909.             push    si                      ; save string pointer
  2910.             call    exec_disp               ; display what we're sending
  2911.             pop     si                      ; restore register
  2912.  
  2913. exec_se10:  mov     di, offset ch_send      ; di -> send char routine
  2914.             call    exec_expand             ; ..expand string and send
  2915.             call    exec_ncmd               ; setup to handle next cmd
  2916.             ret                             ; ..and return to caller
  2917.  
  2918. exec_send   endp
  2919.  
  2920.  
  2921.  
  2922. ; ----------------------------------------------------------------------
  2923. ;   exec_oper - write message to operator's display
  2924. ; ----------------------------------------------------------------------
  2925.  
  2926. exec_oper   proc
  2927.  
  2928.             call    exec_disp               ; expand string & display
  2929.             call    exec_ncmd               ; setup to handle next cmd
  2930.             ret                             ; ..and return to caller
  2931.  
  2932. exec_oper   endp
  2933.  
  2934.  
  2935.  
  2936. ; ----------------------------------------------------------------------
  2937. ;   exec_reply - wait a reply (setup)
  2938. ; ----------------------------------------------------------------------
  2939.  
  2940. exec_reply  proc
  2941.  
  2942.             mov     ax, timeout             ; ax = current timeout value
  2943.             mov     tick_wait, ax           ; setup timeout timer
  2944.  
  2945.             mov     script_wsl, 0           ; looking for 1st character
  2946.             mov     script_cs, 11           ; setup for new state
  2947.  
  2948.             mov     ax, script_dm           ; get current mask
  2949.             mov     script_dmx, ax          ; save temporarily
  2950.             and     script_dm, 0fffeh       ; turn off display bit
  2951.             ret                             ; ..and return
  2952.  
  2953. exec_reply  endp
  2954.  
  2955.  
  2956.  
  2957. ; ----------------------------------------------------------------------
  2958. ;   exec_rwait - wait for a host reply (loop)
  2959. ; ----------------------------------------------------------------------
  2960.  
  2961. exec_rwait  proc
  2962.  
  2963.             mov     bx, script_wsl          ; bx = offset in string
  2964.  
  2965. exec_rwa10: cmp     cancel_flag, 0          ; q. cancel request?
  2966.             jne     exec_rwa18              ; a. yes .. patch up and exit
  2967.  
  2968.             cmp     tick_wait, 0            ; q. timeout yet?
  2969.             jg      exec_rwa20              ; a. no .. continue
  2970.  
  2971.             mov     al, 7                   ; give timeout beep
  2972.             call    bd_disp                 ; ..let'em know we're here
  2973.  
  2974.             mov     bx, timeout_lbl         ; bx = offset of timeout
  2975.  
  2976.             cmp     bx, -1                  ; q. do next statement?
  2977.             je      exec_rwa40              ; a. yes .. find next statement
  2978.  
  2979. exec_rwa15: mov     si, bx                  ; si -> timeout label
  2980.             call    exec_ncmd               ; setup to handle next cmd
  2981. exec_rwa18: mov     ax, script_dmx          ; get old debug bits
  2982.             mov     script_dm, ax           ; ..and restore it
  2983.             jmp     short exec_rwa70        ; ..and exit via common point
  2984.  
  2985. exec_rwa20: call    ch_get                  ; q. get a character?
  2986.             jc      exec_rwa80              ; a. no .. come back later
  2987.  
  2988.             call    bd_bpstuff              ; handle B+ and 7bit
  2989.             jc      exec_rwa80              ; ..if eaten, continue
  2990.  
  2991.             test    script_dmx, 1           ; q. want display as we go?
  2992.             jz      exec_rwa25              ; a. no .. continue
  2993.  
  2994.             call    bd_disp                 ; else .. show'em the incoming
  2995.  
  2996. exec_rwa25: mov     cl, 1[bx+si]            ; cl = char from wait string
  2997.  
  2998.             cmp     case_flag, 0            ; q. ignore case?
  2999.             je      exec_rwa28              ; a. no .. respect case
  3000.  
  3001.             call    comp_ul                 ; al = upcased host char
  3002.             xchg    cl, al                  ; al = wait string char
  3003.             call    comp_ul                 ; ..now upcased
  3004.             xchg    cl, al                  ; al = host char again
  3005.  
  3006. exec_rwa28: cmp     al, cl                  ; q. match character?
  3007.             je      exec_rwa30              ; a. yes .. continue
  3008.  
  3009.             or      bx, bx                  ; q. have we found any yet?
  3010.             jz      exec_rwa10              ; a. no .. start again
  3011.  
  3012.             xor     bx, bx                  ; bx = start from beginning
  3013.             jmp     exec_rwa25              ; ..and this character
  3014.  
  3015. exec_rwa30: inc     bx                      ; bump char found count
  3016.  
  3017.             cmp     byte ptr [si], bl       ; q. find all characters yet?
  3018.             jne     exec_rwa10              ; a. yes .. goto next state
  3019.  
  3020. exec_rwa40: mov     bl, [si]                ; bl = length of string
  3021.             xor     bh, bh                  ; bx = length now
  3022.             add     si, bx                  ; si -> last character
  3023.             inc     si                      ; si -> next command
  3024.             call    exec_ncmd               ; setup to handle next cmd
  3025.  
  3026. exec_rwa70: mov     ax, script_dmx          ; get old debug bits
  3027.             mov     script_dm, ax           ; ..and restore it
  3028.  
  3029. exec_rwa80: mov     script_wsl, bx          ; save found count
  3030.             ret                             ; ..and return to caller
  3031.  
  3032. exec_rwait  endp
  3033.  
  3034.  
  3035.  
  3036. ; ----------------------------------------------------------------------
  3037. ;   exec_tout - setup timeout value/location command
  3038. ; ----------------------------------------------------------------------
  3039.  
  3040. exec_tout   proc
  3041.  
  3042.             mov     ax, 0[si]               ; ax = timeout value
  3043.             mov     timeout, ax             ; save value for timeout counter
  3044.  
  3045.             mov     ax, 2[si]               ; ax => timeout label
  3046.  
  3047.             cmp     ax, -1                  ; q. just do next statement?
  3048.             je      exec_tout1              ; a. yes .. continue
  3049.  
  3050.             add     ax, script_buf          ; ax -> timeout label
  3051.             mov     timeout_lbl, ax         ; save offset for next timeout
  3052.  
  3053. exec_tout1: add     si, 4                   ; si -> next command
  3054.             call    exec_ncmd               ; setup to handle next cmd
  3055.             ret                             ; ..and return to caller
  3056.  
  3057. exec_tout   endp
  3058.  
  3059.  
  3060.  
  3061. ; ----------------------------------------------------------------------
  3062. ;   exec_hang - hangup line command
  3063. ; ----------------------------------------------------------------------
  3064.  
  3065. exec_hang   proc
  3066.  
  3067.             call    io_hangup               ; issue a hangup
  3068.  
  3069.             call    exec_ncmd               ; setup to handle next cmd
  3070.             ret                             ; ..and return to caller
  3071.  
  3072. exec_hang   endp
  3073.  
  3074.  
  3075.  
  3076. ; ----------------------------------------------------------------------
  3077. ;   exec_down - download a file
  3078. ; ----------------------------------------------------------------------
  3079.  
  3080. exec_down   proc
  3081.  
  3082.             mov     cl, byte ptr 0[si]      ; cl = length of command
  3083.             xor     ch, ch                  ; cx = len of command
  3084.             inc     si                      ; si -> next command
  3085.             mov     di, offset script_ws    ; di -> work area
  3086.             mov     bd_isi, di              ; save user response
  3087.             call    string_copy             ; copy/ASCIIZ the string
  3088.             add     main_state, 2           ; show download active
  3089.  
  3090.             call    exec_ncmd               ; setup to handle next cmd
  3091.             ret                             ; ..and return to caller
  3092.  
  3093. exec_down   endp
  3094.  
  3095.  
  3096.  
  3097. ; ----------------------------------------------------------------------
  3098. ;   exec_prompt - prompt for variable data (setup)
  3099. ; ----------------------------------------------------------------------
  3100.  
  3101. exec_prompt proc
  3102.  
  3103.             call    exec_disp               ; display prompt message
  3104.  
  3105.             mov     script_wsl, 0           ; clear entered count
  3106.             mov     script_cs, 13           ; setup new state to get data
  3107.             ret                             ; ..and return to caller
  3108.  
  3109. exec_prompt endp
  3110.  
  3111.  
  3112.  
  3113. ; ----------------------------------------------------------------------
  3114. ;   exec_pwait - wait for user to enter prompt data (loop)
  3115. ; ----------------------------------------------------------------------
  3116.  
  3117. exec_pwait  proc
  3118.  
  3119.             call    get_line                ; q. get a line?
  3120.             jc      exec_pwa10              ; a. yes .. continue
  3121.  
  3122.             ret                             ; else .. just return
  3123.  
  3124. exec_pwa10: mov     di, script_var          ; di -> next script buffer
  3125.             mov     ax, di                  ; ax -> next location
  3126.             sub     ax, script_buf          ; ax = what's been used
  3127.             mov     cx, script_wsl          ; cx = length of string w/null
  3128.             add     ax, cx                  ; ax = length after copy
  3129.  
  3130.             cmp     ax, script_amt          ; q. going over our bounds?
  3131.             jl      exec_pwa20              ; a. no .. continue
  3132.  
  3133.             mov     si, offset scriptfull   ; si -> script full message
  3134.             call    disp_msg                ; display error message
  3135.             call    exec_done               ; setup for next script
  3136.             ret                             ; ..and return to caller
  3137.  
  3138. exec_pwa20: mov     al, [si]                ; al = index into repl table
  3139.             cbw                             ; ax = index, too
  3140.             shl     al, 1                   ; al = offset in table
  3141.             mov     bx, offset replacables  ; bx -> replacables table
  3142.             add     bx, ax                  ; bx -> table entry
  3143.  
  3144.             mov     [bx], di                ; save addr of this variable
  3145.             push    si                      ; save register
  3146.             mov     si, offset script_ws    ; si -> input'ed string
  3147.             xchg    si, di                  ; si -> dest, di -> entered text
  3148.             call    comp_copy               ; copy to script buffer
  3149.             mov     script_var, si          ; save next usable addr
  3150.  
  3151.             pop     si                      ; restore instruction pointer
  3152.             inc     si                      ; si -> next command
  3153.             call    exec_ncmd               ; setup to handle next cmd
  3154.             ret                             ; ..and return to caller
  3155.  
  3156. exec_pwait  endp
  3157.  
  3158.  
  3159.  
  3160. ; ----------------------------------------------------------------------
  3161. ;   exec_equate - equate a variable w/some text
  3162. ; ----------------------------------------------------------------------
  3163.  
  3164. exec_equate proc
  3165.  
  3166.             mov     di, si                  ; di -> equate string
  3167.             mov     al, [si]                ; al = length of string
  3168.             cbw                             ; ax = len of string
  3169.  
  3170.             add     si, ax                  ; si -> last char of string
  3171.             inc     si                      ; si -> offset in variable tbl
  3172.             mov     al, [si]                ; al = index into repl table
  3173.             cbw                             ; ax = index, too
  3174.             shl     al, 1                   ; al = offset in table
  3175.             mov     bx, offset replacables  ; bx -> replacables table
  3176.             add     bx, ax                  ; bx -> table entry
  3177.             mov     [bx], di                ; save addr of this variable
  3178.  
  3179.             inc     si                      ; si -> next command
  3180.             call    exec_ncmd               ; setup to handle next cmd
  3181.             ret                             ; ..and return to caller
  3182.  
  3183. exec_equate endp
  3184.  
  3185.  
  3186.  
  3187. ; ----------------------------------------------------------------------
  3188. ;   exec_wait - wait the script execution a couple of ticks (setup)
  3189. ; ----------------------------------------------------------------------
  3190.  
  3191. exec_wait   proc
  3192.  
  3193.             mov     ax, [si]                ; ax = number of ticks
  3194.             mov     tick_wait, ax           ; save value
  3195.             mov     script_cs, 12           ; setup for wait state
  3196.             ret                             ; ..and return to caller
  3197.  
  3198. exec_wait   endp
  3199.  
  3200.  
  3201.  
  3202. ; ----------------------------------------------------------------------
  3203. ;   exec_wait1 - help wait a couple of ticks (loop)
  3204. ; ----------------------------------------------------------------------
  3205.  
  3206. exec_wait1  proc
  3207.  
  3208.             cmp     tick_wait, 0            ; q. time expired?
  3209.             jnz     exec_wait2              ; a. yes .. exit loop
  3210.  
  3211.             add     si, 2                   ; si -> next command
  3212.             call    exec_ncmd               ; setup to handle next cmd
  3213. exec_wait2: ret                             ; ..and return to caller
  3214.  
  3215. exec_wait1  endp
  3216.  
  3217.  
  3218.  
  3219. ; ----------------------------------------------------------------------
  3220. ;   exec_goto - goto label
  3221. ; ----------------------------------------------------------------------
  3222.  
  3223. exec_goto   proc
  3224.  
  3225.             mov     si, [si]                ; get new pointer offset
  3226.             add     si, script_buf          ; si -> new pointer
  3227.             call    exec_ncmd               ; setup to handle next cmd
  3228.             ret                             ; ..and return to caller
  3229.  
  3230. exec_goto   endp
  3231.  
  3232.  
  3233.  
  3234. ; ----------------------------------------------------------------------
  3235. ;   next - get next token start address
  3236. ;
  3237. ;   entry: next_token -> where to start scan
  3238. ;    exit: di -> start of non-blank token
  3239. ;          carry set if no token available
  3240. ; ----------------------------------------------------------------------
  3241.  
  3242. next        proc
  3243.             mov     di, next_token          ; di -> start of string
  3244.  
  3245. next10:     cmp     byte ptr [di], 0        ; q. at end of string?
  3246.             je      next90                  ; a. yes .. exit loop
  3247.  
  3248.             cmp     byte ptr [di], ' '      ; q. blank?
  3249.             jne     next80                  ; a. no .. exit loop
  3250.  
  3251.             inc     di                      ; di -> next character
  3252.             jmp     short next10            ; ..then loop
  3253.  
  3254. next80:     clc                             ; show something found
  3255.             ret                             ; ..and return to caller
  3256.  
  3257. next90:     stc                             ; show null token
  3258.             ret                             ; ..and return
  3259.  
  3260. next        endp
  3261.  
  3262.  
  3263.  
  3264. ; ----------------------------------------------------------------------
  3265. ;   token - get next token
  3266. ;
  3267. ;   entry: next_token -> where to start scan
  3268. ;    exit: next_token -> where to start next scan
  3269. ;          di -> token, null terminated
  3270. ;          carry = no token available
  3271. ; ----------------------------------------------------------------------
  3272.  
  3273. token       proc
  3274.             call    next                    ; q. di -> start of string
  3275.             jc      token90                 ; a. no .. just null char
  3276.  
  3277.             push    di                      ; save start point
  3278.  
  3279. token10:    cmp     byte ptr [di], 0        ; q. end of the line?
  3280.             je      token80                 ; a. yes .. bail out now
  3281.  
  3282.             cmp     byte ptr [di], ' '      ; q. blank?
  3283.             je      token70                 ; a. yes .. exit loop
  3284.  
  3285.             inc     di                      ; di -> next character
  3286.             jmp     short token10           ; ..then loop
  3287.  
  3288. token70:    mov     byte ptr [di], 0        ; make into null terminated string
  3289.             inc     di                      ; di -> 1st byte after this token
  3290.  
  3291. token80:    mov     next_token, di          ; save next start location
  3292.             pop     di                      ; get this token's start
  3293.             clc                             ; show token found
  3294. token90:    ret                             ; ..and return to caller
  3295.  
  3296. token       endp
  3297.  
  3298.  
  3299.  
  3300. ; ----------------------------------------------------------------------
  3301. ;   exec_crlf - display a CR/LF
  3302. ; ----------------------------------------------------------------------
  3303.  
  3304. exec_crlf   proc
  3305.  
  3306.             mov     al, 0dh                 ; al = <CR>
  3307.             call    bd_disp                 ; display it
  3308.  
  3309.             mov     al, 0ah                 ; al = <LF>
  3310.             call    bd_disp                 ; ..and line feed too
  3311.  
  3312.             ret                             ; ..then return to caller
  3313.  
  3314. exec_crlf   endp
  3315.  
  3316.  
  3317.  
  3318. ; ----------------------------------------------------------------------
  3319. ;   exec_disp - display string
  3320. ;
  3321. ;   entry: si -> counted string
  3322. ; ----------------------------------------------------------------------
  3323.  
  3324. exec_disp   proc
  3325.  
  3326.             push    di                      ; save registers
  3327.  
  3328.             mov     di, offset exec_dispx   ; di -> display char routine
  3329.             call    exec_expand             ; ..expand string & display
  3330.  
  3331.             pop     di                      ; restore registers
  3332.             ret                             ; ..and return to caller
  3333.  
  3334. exec_disp   endp
  3335.  
  3336.  
  3337.  
  3338. ; ----------------------------------------------------------------------
  3339. ;   exec_dispx - display a char with CR/LF handling
  3340. ;
  3341. ;   entry: ax = char to display
  3342. ; ----------------------------------------------------------------------
  3343.  
  3344. exec_dispx  proc
  3345.  
  3346.             cmp     al, 0dh                 ; q. CR?
  3347.             jne     exec_dx9                ; a. no .. just continue
  3348.  
  3349.             push    ax                      ; save register
  3350.  
  3351.             mov     al, 0ah                 ; al = a linefeed character
  3352.             call    bd_disp                 ; put out the LF
  3353.  
  3354.             pop     ax                      ; restore the CR
  3355.  
  3356. exec_dx9:   call    bd_disp                 ; display original char
  3357.             ret                             ; ..then return to caller
  3358.  
  3359. exec_dispx  endp
  3360.  
  3361.  
  3362.  
  3363. ; ----------------------------------------------------------------------
  3364. ;   exec_expand - process and expand string
  3365. ;
  3366. ;   entry: si -> counted string
  3367. ;          di -> routine to call to output each character
  3368. ; ----------------------------------------------------------------------
  3369.  
  3370. exec_expand proc
  3371.  
  3372.             xor     dl, dl                  ; dl = current recursion level
  3373.  
  3374. exec_ex00:  push    bx                      ; recursion entry point
  3375.             push    cx
  3376.  
  3377.             inc     dl                      ; dl = new recursion level
  3378.  
  3379.             or      si, si                  ; q. null pointer?
  3380.             jz      exec_ex90               ; a. yes .. just exit
  3381.  
  3382.             mov     cl, byte ptr [si]       ; cl = length of string
  3383.             xor     ch, ch                  ; cx = length now
  3384.  
  3385.             or      cx, cx                  ; q. null string?
  3386.             jz      exec_ex90               ; a. yes .. exit here
  3387.  
  3388.             inc     si                      ; si -> first char of string
  3389.  
  3390. exec_ex10:  lodsb                           ; al = character from string
  3391.  
  3392.             cmp     dl, recurse_lim         ; q. hit limit?
  3393.             jg      exec_ex40               ; a. yes .. exit now
  3394.  
  3395.             cmp     al, '%'                 ; q. control character?
  3396.             jne     exec_ex40               ; a. no .. put it out
  3397.  
  3398.             cmp     cx, 1                   ; q. last character
  3399.             je      exec_ex40               ; a. yes .. put out char
  3400.  
  3401.             dec     cx                      ; else .. take one off tally
  3402.             lodsb                           ; al = next character
  3403.  
  3404.             cmp     al, '%'                 ; q. need a percent symbol?
  3405.             je      exec_ex40               ; a. yes .. put one out
  3406.  
  3407.             cmp     al, '1'                 ; q. within 1 to 9?
  3408.             jl      exec_ex40               ; a. no .. just put it out
  3409.  
  3410.             cmp     al, '9'                 ; q. numeric?
  3411.             jg      exec_ex20               ; a. no .. check alpha
  3412.  
  3413.             sub     al, '1'                 ; al = offset
  3414.             jmp     short exec_ex30         ; ..continue w/common code
  3415.  
  3416. exec_ex20:  call    comp_ul                 ; ..and make uppercase
  3417.  
  3418.             cmp     al, 'A'                 ; q. within A to Z?
  3419.             jl      exec_ex40               ; a. no .. just put it out
  3420.  
  3421.             cmp     al, 'Z'                 ; q. alpha?
  3422.             jg      exec_ex40               ; a. no .. just put it out
  3423.  
  3424.             sub     al, 'A' - 9             ; al = offset
  3425. exec_ex30:  xor     ah, ah                  ; ah = clear upper byte
  3426.             shl     ax, 1                   ; ax = table offset
  3427.             mov     bx, offset replacables  ; bx -> table
  3428.             add     bx, ax                  ; bx -> entry
  3429.             mov     bx, [bx]                ; bx -> string to display
  3430.             xchg    bx, si                  ; si -> replacement string
  3431.             call    exec_ex00               ; put out string
  3432.             mov     si, bx                  ; si -> where we left off
  3433.             jmp     short exec_ex50         ; ..then continue in loop
  3434.  
  3435. exec_ex40:  CALLDI                          ; al = char to send/display
  3436. exec_ex50:  loop    exec_ex10               ; ..then loop till end of string
  3437.  
  3438. exec_ex90:  dec     dl                      ; decriment recursion level
  3439.             pop     cx                      ; restore registers
  3440.             pop     bx
  3441.             ret                             ; ..and return to caller
  3442.  
  3443. exec_expand endp
  3444.  
  3445.  
  3446.  
  3447. ; ----------------------------------------------------------------------
  3448. ;   exec_term - display async stream during script
  3449. ;
  3450. ;   exit: carry = special char received
  3451. ; ----------------------------------------------------------------------
  3452.  
  3453. exec_term   proc
  3454.  
  3455.             test    script_dm, 1            ; q. display as we go?
  3456.             jz      exec_ter85              ; a. no .. continue
  3457.  
  3458.             mov     cx, 100                 ; cx = loop limit
  3459.  
  3460. exec_ter10: call    ch_get                  ; q. character available?
  3461.             jc      exec_ter85              ; a. no .. exit loop
  3462.  
  3463.             call    bd_bpstuff              ; handle B+ stuff
  3464.             jc      exec_ter90              ; ..if char processed
  3465.  
  3466.             call    bd_disp                 ; display recieved character
  3467.             loop    exec_ter10              ; ..then loop a while
  3468.  
  3469. exec_ter85: clc                             ; clear carry = just continue
  3470.  
  3471. exec_ter90: ret                             ; return to caller
  3472.  
  3473. exec_term   endp
  3474.  
  3475.  
  3476.  
  3477. ; ----------------------------------------------------------------------
  3478. ;   disp_msg - display a simple msg
  3479. ;
  3480. ;   entry: si -> null terminated string
  3481. ; ----------------------------------------------------------------------
  3482.  
  3483. disp_msg    proc
  3484.  
  3485.             push    si                      ; save registers
  3486.  
  3487. disp_msg10: lodsb                           ; al = char to display
  3488.  
  3489.             or      al, al                  ; q. end of string?
  3490.             jz      disp_msg90              ; a. yes .. exit loop
  3491.  
  3492.             call    exec_dispx              ; else .. put out character
  3493.             jmp     disp_msg10              ; ..and loop back for next
  3494.  
  3495. disp_msg90: pop     si                      ; restore register
  3496.             ret                             ; ..and return to caller
  3497.  
  3498. disp_msg    endp
  3499.  
  3500.  
  3501.  
  3502. ; ----------------------------------------------------------------------
  3503. ;   string_len - count null terminated string
  3504. ;
  3505. ;   entry: di -> input string
  3506. ;    exit: cx = length
  3507. ; ----------------------------------------------------------------------
  3508.  
  3509. string_len  proc
  3510.  
  3511.             push    ax                      ; save registers
  3512.             push    di
  3513.  
  3514.             mov     al, 0                   ; al = search argument
  3515.             mov     cx, 0ffh                ; cx = max length
  3516.       repne scasb                           ; search for null
  3517.  
  3518.             mov     ax, 0feh                ; ax = init count
  3519.             sub     ax, cx                  ; ax = string length
  3520.             mov     cx, ax                  ; cx = length to return
  3521.  
  3522.             pop     di                      ; restore registers
  3523.             pop     ax
  3524.             ret                             ; ..and return to caller
  3525.  
  3526. string_len  endp
  3527.  
  3528.  
  3529.  
  3530. ; ----------------------------------------------------------------------
  3531. ;   string_copy - null terminated string copy
  3532. ;
  3533. ;   entry: si -> source
  3534. ;          di -> destination
  3535. ;          cx =  max length
  3536. ;    exit: di -> destination null terminator
  3537. ; ----------------------------------------------------------------------
  3538.  
  3539. string_copy proc
  3540.             push    ax                      ; save registers
  3541.             push    cx
  3542.  
  3543. string_co1: lodsb                           ; al = character from string
  3544.             stosb                           ; store char @ destination
  3545.  
  3546.             cmp     al, 0                   ; q. end of the line?
  3547.             je      string_c90              ; a. yes .. exit loop
  3548.  
  3549.             loop    string_co1              ; ..and loop till end of string
  3550.  
  3551. string_c90: pop     cx                      ; restore registers
  3552.             pop     ax
  3553.             ret                             ; ..and return
  3554.  
  3555. string_copy endp
  3556.  
  3557.  
  3558.  
  3559. ; ----------------------------------------------------------------------
  3560. ;   get_line - get a line from user
  3561. ;
  3562. ;   exit: no carry = string not complete
  3563. ;         carry = string completed
  3564. ;         script_ws  = null term string
  3565. ;         script_wsl = length w/null
  3566. ; ----------------------------------------------------------------------
  3567.  
  3568. get_line    proc
  3569.             push    si                      ; save register
  3570.  
  3571. get_line00: call    bd_key                  ; q. key ready?
  3572.             jnc     get_line10              ; a. yes .. check it out
  3573.  
  3574.             clc                             ; clear finish flag
  3575.             jmp     short get_line95        ; ..and return to caller
  3576.  
  3577. get_line10: or      al, al                  ; q. function key?
  3578.             jz      get_line00              ; a. yes .. get another key
  3579.  
  3580.             cmp     al, 0dh                 ; q. carriage return?
  3581.             jne     get_line20              ; a. no .. continue
  3582.  
  3583.             call    exec_crlf               ; do a CR/LF
  3584.             jmp     short get_line90        ; ..then clean up and return
  3585.  
  3586. get_line20: cmp     al, 8                   ; q. backspace?
  3587.             jne     get_line30              ; a. no .. continue
  3588.  
  3589.             cmp     script_wsl, 0           ; q. anything in line?
  3590.             je      get_line00              ; a. no .. just get next char
  3591.  
  3592.             dec     script_wsl              ; cx = one less
  3593.             dec     si                      ; si -> previous character
  3594.             jmp     short get_line40        ; ..display backspace
  3595.  
  3596. get_line30: cmp     al, ' '                 ; q. below a blank?
  3597.             jl      get_line00              ; a. yes .. get another
  3598.  
  3599.             cmp     al, 127                 ; q. above a zee and "{|}~" ?
  3600.             jg      get_line00              ; a. yes .. get another
  3601.  
  3602.             mov     si, offset script_ws    ; si -> work area
  3603.             add     si, script_wsl          ; si -> next available character
  3604.             mov     [si], al                ; store character in line
  3605.             inc     script_wsl              ; save new length
  3606.  
  3607. get_line40: call    bd_disp                 ; echo the character
  3608.  
  3609.             cmp     script_wsl, 64          ; q. hit max length?
  3610.             jl      get_line00              ; a. no .. get next character
  3611.  
  3612. get_line90: mov     si, offset script_ws    ; si -> work area
  3613.             add     si, script_wsl          ; si -> next available character
  3614.             mov     word ptr [si], 0        ; move in null terminator
  3615.             inc     script_wsl              ; save new length
  3616.             stc                             ; set carry flag
  3617.  
  3618. get_line95: pop     si                      ; restore register
  3619.             ret                             ; ..and return to caller
  3620.  
  3621. get_line    endp
  3622.  
  3623.  
  3624.  
  3625. ; ----------------------------------------------------------------------
  3626. ;   comp_ul - uppercase a letter
  3627. ;
  3628. ;   entry: al = a character
  3629. ;    exit: al = uppercase character
  3630. ; ----------------------------------------------------------------------
  3631.  
  3632. comp_ul     proc
  3633.  
  3634.             cmp     al, 'a'                 ; q. need uppercasing?
  3635.             jl      comp_ul1                ; a. no .. continue
  3636.  
  3637.             cmp     al, 'z'                 ; q. within range?
  3638.             jg      comp_ul1                ; a. no .. continue
  3639.  
  3640.             and     al, not 20h             ; al = uppercase letter
  3641.  
  3642. comp_ul1:   ret                             ; ..just return to caller
  3643.  
  3644. comp_ul     endp
  3645.  
  3646.  
  3647.  
  3648. ; ----------------------------------------------------------------------
  3649. ;   comp_copy - copy null terminated string and make into counted string
  3650. ;
  3651. ;   entry: si -> target destination
  3652. ;          di -> string to copy
  3653. ;    exit: si -> next target buffer location
  3654. ; ----------------------------------------------------------------------
  3655.  
  3656. comp_copy   proc
  3657.  
  3658.             push    ax                      ; save registers
  3659.             push    bx
  3660.  
  3661.             call    string_len              ; cx = string length
  3662.             mov     bx, si                  ; bx -> count byte
  3663.             mov     [si], cl                ; store counted string byte
  3664.             inc     si                      ; si -> next compile buffer
  3665.             xchg    di, si                  ; get src and dest in order
  3666.  
  3667.             or      cx, cx                  ; q. zero length string?
  3668.             jz      comp_copy9              ; a. yes .. don't loop
  3669.  
  3670. comp_copy1: lodsb                           ; al = character from string
  3671.             stosb                           ; store char @ destination
  3672.  
  3673.             cmp     al, 0                   ; q. end of the line?
  3674.             je      comp_copy9              ; a. yes .. exit loop
  3675.  
  3676.             cmp     al, '^'                 ; q. control character?
  3677.             jne     comp_copy3              ; a. no .. continue
  3678.  
  3679.             dec     cx                      ; q. run out of string?
  3680.             jz      comp_copy9              ; a. yes .. exit here..
  3681.  
  3682.             lodsb                           ; al = next character
  3683.  
  3684.             cmp     al, '^'                 ; q. need a carot?
  3685.             je      comp_copy2              ; a. yes .. then leave one out
  3686.  
  3687.             call    comp_ul                 ; ..and make uppercase
  3688.             sub     al, '@'                 ; al = control-@ to control-z
  3689.             mov     [di-1], al              ; store over carot character
  3690. comp_copy2: dec     byte ptr [bx]           ; ..shorten counted string by one
  3691.  
  3692. comp_copy3: loop    comp_copy1              ; ..and loop till end of string
  3693.  
  3694. comp_copy9: mov     si, di                  ; si -> new dest in compile buffer
  3695.             pop     bx                      ; restore registers
  3696.             pop     ax
  3697.             ret                             ; ..and return to caller
  3698.  
  3699. comp_copy   endp
  3700.  
  3701.  
  3702.  
  3703. ; ----------------------------------------------------------------------
  3704. ;   swap_psp - swap PSP and error handlers
  3705. ; ----------------------------------------------------------------------
  3706.  
  3707. swap_psp    proc
  3708.  
  3709.             push    bx                      ; save registers
  3710.             push    dx
  3711.             push    es
  3712.             push    ds
  3713.  
  3714.             mov     ah, 62h                 ; ah = get user's psp
  3715.             int     21h                     ; call DOS
  3716.  
  3717.             xchg    bx, psp_seg             ; bx = other psp
  3718.  
  3719.             mov     ah, 50h                 ; ah = setup psp address
  3720.             int     21h                     ; call DOS
  3721.  
  3722.             cmp     tsr_active, 0           ; q. tsr pop'd up?
  3723.             jne     swap_psp10              ; a. yes .. continue
  3724.  
  3725.             call    swap_1b                 ; swap ^break handler in/out
  3726.  
  3727. swap_psp10: mov     ax, 3523h               ; ax = get ^C vector
  3728.             int     21h                     ; call DOS
  3729.  
  3730.             lds     dx, dword ptr cs:user_i23  ; ds:dx = other handler
  3731.  
  3732.             mov     cs:user_i23, bx         ; save old fields
  3733.             mov     cs:user_i23s, es        ; ..and swap segment registers
  3734.  
  3735.             mov     ax, 2523h               ; ax = setup interrupt vector
  3736.             int     21h                     ; call DOS
  3737.  
  3738.  
  3739.             mov     ax, 3524h               ; ax = get critical err vector
  3740.             int     21h                     ; call DOS
  3741.  
  3742.             lds     dx, dword ptr cs:user_i24  ; ds:dx = other handler
  3743.  
  3744.             mov     cs:user_i24, bx         ; save old fields
  3745.             mov     cs:user_i24s, es        ; ..and swap segment registers
  3746.  
  3747.             mov     ax, 2524h               ; ax = setup interrupt vector
  3748.             int     21h                     ; call DOS
  3749.  
  3750.  
  3751.             pop     ds                      ; restore register
  3752.             pop     es
  3753.             pop     dx
  3754.             pop     bx
  3755.             ret                             ; ..and return to caller
  3756.  
  3757. swap_psp    endp
  3758.  
  3759.  
  3760.  
  3761. ; ----------------------------------------------------------------------
  3762. ;   swap_1b - swap ^break handler
  3763. ; ----------------------------------------------------------------------
  3764.  
  3765. swap_1b     proc
  3766.  
  3767.             push    bx                      ; save registers
  3768.             push    ds
  3769.             push    es
  3770.  
  3771.             mov     ax, 351bh               ; ax = get ^break vector
  3772.             int     21h                     ; call DOS
  3773.  
  3774.             lds     dx, dword ptr cs:user_i1b  ; ds:dx = other handler
  3775.  
  3776.             mov     cs:user_i1b, bx         ; save old fields
  3777.             mov     cs:user_i1bs, es        ; ..and swap segment registers
  3778.  
  3779.             mov     ax, 251bh               ; ax = setup interrupt vector
  3780.             int     21h                     ; call DOS
  3781.  
  3782.             pop     es                      ; restore registers
  3783.             pop     ds
  3784.             pop     bx
  3785.             ret                             ; ..and return to caller
  3786.  
  3787. swap_1b     endp
  3788.  
  3789.  
  3790. ; ----------------------------------------------------------------------
  3791. ;   start - start backdown program
  3792. ; ----------------------------------------------------------------------
  3793.  
  3794. start       proc
  3795.             cld                             ; clear direction flag!
  3796.             mov     sp, offset wstack       ; ..
  3797.  
  3798.             call    cmd                     ; initialize the system
  3799.             call    get_buffers             ; get i/o buffers
  3800.             call    script_init             ; initialize script buffer
  3801.             call    scrinit                 ; clear screen buffer
  3802.  
  3803. ; - get ready to go TSR
  3804.  
  3805.             mov     dx, nxtavail            ; dx = high water area in bytes
  3806.             shr     dx, 1
  3807.             shr     dx, 1
  3808.             shr     dx, 1
  3809.             shr     dx, 1                   ; dx = nbr of paragraphs
  3810.             add     dx, 16                  ; ..and adjust for psp
  3811.  
  3812.             mov     ah, 4ah                 ; ah = set memory block size
  3813.             mov     es, psp_seg             ; es -> our memory
  3814.             mov     bx, dx                  ; bx = nbr of paragraphs
  3815.             int     21h                     ; issue DOS call
  3816.             jnc     start50                 ; ..if ok, continue
  3817.  
  3818.             xor     al, al                  ; al = no help
  3819.             mov     dx, offset toosmall     ; dx -> error message
  3820.             call    die                     ; ..and quit with message
  3821.  
  3822. start50:    push    dx                      ; save paragraphs needed
  3823.             mov     si, intblk1             ; si -> 1st interrupt block
  3824.             mov     cx, intblkcnt           ; cx = nbr of ints handled
  3825.  
  3826. start60:    mov     ah, 35h                 ; ah = get interrupt vector
  3827.             mov     al, [si+12]             ; al = interrupt number
  3828.             int     21h                     ; .. get the current setting
  3829.  
  3830.             mov     [si+2], es              ; save segment of old int
  3831.             mov     [si], bx                ; .. and offset
  3832.  
  3833.             mov     dx, [si+13]             ; dx -> new interrupt
  3834.             mov     ah, 25h                 ; ah = set interrupt vector
  3835.             int     21h                     ; .. set up new vector
  3836.  
  3837.             add     si, intblklen           ; si -> next entry
  3838.             loop    start60                 ; .. set next interrupt
  3839.  
  3840.             call    io_init                 ; initialize the io port
  3841.  
  3842.             cmp     scriptfile, 0           ; q. run a script?
  3843.             je      start70                 ; a. no .. continue
  3844.  
  3845.             mov     ah, 9                   ; ah = display message
  3846.             lea     dx, tsrsetup            ; dx -> script will run msg
  3847.             int     21h                     ; issue DOS msg
  3848.  
  3849. start70:    lea     dx, installed           ; dx -> installed ok
  3850.             mov     ah, 9                   ; ah = say ok
  3851.             int     21h                     ; .. display message
  3852.  
  3853.             mov     byte ptr dollar, 0      ; change $ to null termination
  3854.             mov     byte ptr hdrmsg_1, ' '  ; change <lf> to blank
  3855.             lea     si, hdrmsg              ; dx -> header/copyright msg
  3856.             call    disp_msg                ; display on TSR's screen
  3857.  
  3858.             lea     si, bd_help$            ; dx -> help message
  3859.             call    disp_msg                ; display on TSR's screen
  3860.  
  3861.             dec     main_active             ; let main run now
  3862.  
  3863.             mov     ax, 3100h               ; ax = be TSR, w/rc = 0
  3864.             pop     dx                      ; restore para's needed
  3865.             int     21h                     ; .. now hope & pray
  3866.  
  3867. start       endp
  3868.  
  3869.  
  3870.  
  3871. ; ----------------------------------------------------------------------
  3872. ;   scrinit - initiailize tsr screen buffer
  3873. ; ----------------------------------------------------------------------
  3874.  
  3875. scrinit     proc
  3876.             push    ax                      ; save registers
  3877.             push    cx
  3878.             push    di
  3879.             push    es
  3880.  
  3881.             mov     ah, 0fh                 ; get current display mode
  3882.             int     10h                     ; .. ask BIOS
  3883.  
  3884.             cmp     al, 3                   ; q. Color mode?
  3885.             jne     scrinit10               ; a. No .. leave in mono
  3886.  
  3887.             mov     ourattr, colattr        ; else .. assume color attr
  3888.  
  3889. scrinit10:  mov     ax, 4000                ; ax = size of screen buffer
  3890.             call    getmem                  ; get some memory
  3891.  
  3892.             mov     disp_bufseg, ax         ; save segment of buffer
  3893.             mov     es, ax                  ; es = screen buffer segment
  3894.             xor     di, di                  ; di = offset of zero
  3895.  
  3896.             mov     ah, ourattr             ; ah = attribute to use
  3897.             mov     al, ' '                 ; al = blank character
  3898.             mov     cx, 25 * 80             ; .. words to move
  3899.  
  3900. scrinit20:  stosw                           ; save a char & attribute
  3901.             loop    scrinit20               ; .. until all moved
  3902.  
  3903.             pop     es                      ; restore regs
  3904.             pop     di
  3905.             pop     cx
  3906.             pop     ax
  3907.             ret                             ; return to caller
  3908.  
  3909. scrinit     endp
  3910.  
  3911.  
  3912. ; ----------------------------------------------------------------------
  3913. ;   getmem - get some TSR memory
  3914. ;
  3915. ;   entry: ax = bytes of request
  3916. ;
  3917. ;    exit: ax = segment of available memory
  3918. ;          bx = offset from DS of available memory
  3919. ; ----------------------------------------------------------------------
  3920.  
  3921. getmem      proc
  3922.  
  3923.             push    dx                      ; save register
  3924.  
  3925.             mov     bx, nxtavail            ; bx = offset of avail memory
  3926.             add     ax, 15                  ; ax = request full paragraphs
  3927.             and     ax, 0fff0h              ; ax = even paragraph amt
  3928.             add     nxtavail, ax            ; update next available offset
  3929.             mov     ax, bx                  ; ax = current offset
  3930.  
  3931.             shr     ax, 1                   ; convert byte offset to para's
  3932.             shr     ax, 1
  3933.             shr     ax, 1
  3934.             shr     ax, 1
  3935.             mov     dx, ds                  ; dx = our segment
  3936.             add     ax, dx                  ; ax = absolute seg of new memory
  3937.  
  3938.             pop     dx                      ; restore register
  3939.             ret                             ; ..and return to caller
  3940.  
  3941. getmem      endp
  3942.  
  3943.  
  3944.  
  3945. ; ----------------------------------------------------------------------
  3946. ;   get_buffers - get i/o buffers and protocol overlay area
  3947. ; ----------------------------------------------------------------------
  3948.  
  3949. get_buffers proc
  3950.  
  3951.             mov     ax, send_equsiz         ; ax = size of send in para's
  3952.             call    getmem                  ; allocate some memory
  3953.  
  3954.             mov     send_bufseg, ax         ; save segment for later
  3955.  
  3956.             mov     ax, bdplen              ; ax = size of largest .BDP file
  3957.             call    getmem                  ; allocate some memory
  3958.  
  3959.             mov     word ptr bd_proto+2, ax ; save segment address
  3960.             mov     bd_offset, bx           ; ..and offset too
  3961.  
  3962.             mov     ax, rcv_equsiz          ; ax = size of rcv in para's
  3963.             call    getmem                  ; allocate some memory
  3964.  
  3965.             mov     rcv_bufseg, ax          ; save segment for later
  3966.  
  3967.             ret                             ; ..and return to caller
  3968.  
  3969. get_buffers endp
  3970.  
  3971.  
  3972.  
  3973. ; ----------------------------------------------------------------------
  3974. ;  script_init - initialize script buffer
  3975. ; ----------------------------------------------------------------------
  3976.  
  3977. script_init proc
  3978.  
  3979.             mov     ax, script_amt          ; ax = para's for script buf
  3980.             add     ax, 15                  ; .. correct for boundary
  3981.             call    getmem                  ; get the memory
  3982.             mov     script_buf, bx          ; save script buffer offset
  3983.             ret
  3984.  
  3985. script_init endp
  3986.  
  3987.  
  3988. ; ----------------------------------------------------------------------
  3989. ;   stack area, which will grow back over above routines
  3990. ; ----------------------------------------------------------------------
  3991.  
  3992.             even
  3993.             db      20 dup ('STACK')        ; our stack
  3994. wstack      dw      0
  3995.  
  3996.  
  3997. ; **********************************************************************
  3998.             align   16                      ; align to a paragraph
  3999.  
  4000. mem_end     =       $                  ; end of code
  4001.                                        ; memory after this point is
  4002.                                        ; overlayed when we go TSR
  4003. ; **********************************************************************
  4004.  
  4005.  
  4006. ; ----------------------------------------------------------------------
  4007. ;   protocol header structures
  4008. ; ----------------------------------------------------------------------
  4009.  
  4010. bdmaxprots  =       10                      ; number of protocols supported
  4011. bdprotn     dw      0                       ; protocols found
  4012.  
  4013. bdprot1     label   byte
  4014.             rept    bdmaxprots              ; protocol headers
  4015.             bdprot  <>
  4016.             endm
  4017.  
  4018. bdpath      db      65 dup (0)              ; path for BPD files
  4019. bdplen      dw      0                       ; longest .BDP found
  4020.  
  4021. ; ----------------------------------------------------------------------
  4022. ;   Non-TSR messages
  4023. ; ----------------------------------------------------------------------
  4024.  
  4025. installed   db      "Backdown installed successfully",13,10,"$"
  4026. hdrmsg      db      "BD ", VERSN, " ■ Copyright (c) 1992, Bob Flanders"
  4027.             db      " and Michael Holmes"
  4028. hdrmsg_1    db      10
  4029.             db      13, "Backdown first appeared in PC Magazine, "
  4030.             db      "May 12, 1992", 10
  4031. crlf$       db      13,10
  4032. dollar      db      "$",0
  4033.  
  4034. help        db      "    BackDown, the background download utility"
  4035.             db      13,10,10,"Usage:",13,10,10
  4036.             db      "BD  [/Pn|/Hxxx,i] /C /Szz /T /U script {operands}"
  4037.             db      13,10,10
  4038.             db      "where /Pn      is the COMn port",13,10
  4039.             db      "      /Hxxx,i  is the port addr, interrupt"
  4040.             db      " for non-standard COM ports",13,10
  4041.             db      "      /C       compiles a script",13,10
  4042.             db      "      /Szz     is the max script size in bytes",13,10
  4043.             db      "      /T       tests for TSR resident and/or busy",13,10
  4044.             db      "      /U       uninstalls the TSR",13,10
  4045.             db      "      script   is the script filename",13,10
  4046.             db      "      operands are passed when the script executes",13,10
  4047.             db      13,10,"$"
  4048.  
  4049. dosmsg      db      "Must be DOS 3.1 or higher",13,10,"$"
  4050. protsavail  db      "Protocols available ..$"
  4051. protsetup   db      13,10,"    $"
  4052. noport      db      "COM port not present or responding",13,10,"$"
  4053. readymsg    db      "Backdown is resident and not busy",13,10,"$"
  4054. busymsg     db      "Backdown is resident but busy",13,10,"$"
  4055. notup       db      "Backdown not resident",13,10,"$"
  4056. tsrsetup    db      "TSR will start script",13,10,"$"
  4057. tsrbusy     db      "TSR too busy to start a script",13,10,"$"
  4058. toosmall    db      "Not enough memory to run",13,10,"$"
  4059.  
  4060. invopnd     db      "Invalid operand for "
  4061. invopnc     db      "  ",13,10,"$"
  4062.  
  4063. badopnd     db      "Invalid operand",13,10,"$"
  4064. upalrdy     db      "Already installed",13,10,"$"
  4065. cantfree    db      "Can't uninstall at this time",13,10,"$"
  4066. freeok      db      "Uninstalled successfully",13,10,"$"
  4067. uninscan    db      "Uninstall cancelled.  BACKDOWN still resident.",13,10,"$"
  4068. done        db      13,10,"Script finished",13,10,"$"
  4069. waitmsg     db      "Download still active ..",13,10
  4070.             db      "  hit ESC to leave BD resident",13,10
  4071.             db      "  any other key to force uninstall",13,10,10,"$"
  4072. needfile    db      "Script filename missing or not found",13,10,"$"
  4073.  
  4074. compdone    db      "Compile completed sucessfully, compiled file is$"
  4075. compamt     db      "       bytes long",13,10,"$"
  4076.  
  4077. badcmd      db      ">> Bad command letter",13,10,"$"
  4078. nolabel     db      ">> No label for GOTO command",13,10,"$"
  4079. undefined   db      ">> Undefined label for GOTOs",13,10,"$"
  4080.  
  4081. undef_msg   db      "     "
  4082. undef_item  db      12 dup (0)
  4083.  
  4084. tablefull   db      ">> No room for additional labels or references",13,10,"$"
  4085. badvariable db      ">> Bad prompt variable letter (A-Z)",13,10,"$"
  4086. lab_missing db      ">> Label name missing",13,10,"$"
  4087. duplabel    db      ">> Label already used",13,10,"$"
  4088. wontopen    db      ">> Cannot open compiled output file",13,10,"$"
  4089. cantwrite   db      ">> Error writing output file",13,10,"$"
  4090. missingmsg  db      ">> Missing text in following command",13,10,"$"
  4091. badtype     db      ">> Bad operand value",13,10,"$"
  4092.  
  4093. ; ----------------------------------------------------------------------
  4094. ;   Initialization time constants and work areas
  4095. ; ----------------------------------------------------------------------
  4096.  
  4097. io_table    dw      3f8h                    ; i/o address - COM1
  4098.             db      4                       ;  & interrupt
  4099.             dw      2f8h                    ;             - COM2
  4100.             db      3
  4101.             dw      3e8h                    ;             - COM3
  4102.             db      4
  4103.             dw      2e8h                    ;             - COM4
  4104.             db      3
  4105.  
  4106. cmd_line    db      127 dup (0)             ; temporary cmd line
  4107.  
  4108. ; ----------------------------------------------------------------------
  4109. ;   find protocol modules work area
  4110. ; ----------------------------------------------------------------------
  4111.  
  4112. bdpenvar    db      "BDP="                  ; variable to look for
  4113. bdpfiles    db      "*.BDP", 0              ; files to look for
  4114. bdpwrk      db      65 dup (0)              ; work area for lookup/read
  4115. bdpdta      db      128 dup (?)             ; work DTA
  4116.  
  4117. ; ----------------------------------------------------------------------
  4118. ;   script compiler work areas
  4119. ; ----------------------------------------------------------------------
  4120.  
  4121. compile_flg db      0                       ; compile wanted switch
  4122. scr_handle  dw      0                       ; file handle for script input
  4123. line_size   db      0                       ; length of last line read
  4124. line_buffer db      100 dup (0)             ; line buffer
  4125. line_end    =       $                       ; line buffer end
  4126. bds         db      ".BDS",0                ; input file extension
  4127. eof         db      0                       ; eof flag
  4128.  
  4129. comp_cmds   db      'O', 1                  ; options and init port
  4130.             dw      comp_init
  4131.             db      'S', 2                  ; send string
  4132.             dw      comp_send
  4133.             db      'N', 3                  ; notify operator
  4134.             dw      comp_send
  4135.             db      'R', 4                  ; wait for reply
  4136.             dw      comp_send
  4137.             db      'T', 5                  ; set timeout
  4138.             dw      comp_time
  4139.             db      'H', 6                  ; hangup
  4140.             dw      comp_hang
  4141.             db      'D', 7                  ; download file
  4142.             dw      comp_down
  4143.             db      'P', 8                  ; prompt for variable
  4144.             dw      comp_what
  4145.             db      'W', 9                  ; wait
  4146.             dw      comp_wait
  4147.             db      'G', 10                 ; goto label
  4148.             dw      comp_goto
  4149.             db      ':', 0                  ; label declaration
  4150.             dw      comp_label
  4151.             db      ';', 0                  ; comment line
  4152.             dw      comp_nada
  4153.             db      'E', 15                 ; echo options
  4154.             dw      comp_opt
  4155.             db      '=', 16                 ; equate
  4156.             dw      comp_what
  4157.             db      0                       ; end of list marker
  4158.  
  4159. comp_parms  db      "300",0,0,0, 0, 0, 384/2    ; baud rates
  4160.             db      "1200",0,0,  0, 0, 96/2
  4161.             db      "2400",0,0,  0, 0, 48/2
  4162.             db      "9600",0,0,  0, 0, 12/2
  4163.             db      "8N1",0,0,0, 0, 1, lcr_N81  ; line control array
  4164.             db      "7E1",0,0,0, 0, 1, lcr_E71
  4165.             db      "7O1",0,0,0, 0, 1, lcr_O71
  4166.             db      "7BIT",0,0,  0, 2, 2        ; 7 and 8 bit toggle
  4167.             db      "8BIT",0,0,  0, 2, 1
  4168.             db      "B+",0,0,0,0,0, 3, 2        ; B+ toggle
  4169.             db      "B-",0,0,0,0,0, 3, 1
  4170.             db      "CASE",0,0,  0, 4, 1        ; case control
  4171.             db      "NOCASE",    0, 4, 2
  4172. comp_parme  =       $
  4173. comp_parml  =       9                       ; length of one entry
  4174. comp_parmn  =       (comp_parme - comp_parms) / comp_parml
  4175.  
  4176. sym_name    equ     byte ptr 0              ; null ended symbol string
  4177. sym_flag    equ     byte ptr 9              ; flag: 0 = unused
  4178.                                             ;       1 = reference
  4179.                                             ;       2 = resolved
  4180. sym_offset  equ     word ptr 10             ; offset into table
  4181. sym_entry   =       12                      ; length of one entry
  4182. sym_number  =       50                      ; number of symbol entries
  4183. sym_size    =       sym_entry * sym_number  ; size of symbol table
  4184.  
  4185. symbols     db      sym_size dup (0)        ; symbol table
  4186.  
  4187. compile_ptr dw      compile_buf             ; where to put next cmd
  4188.  
  4189.  
  4190.  
  4191. ; ----------------------------------------------------------------------
  4192. ;   cmd - initialize and process command line
  4193. ;
  4194. ;   entry: cs -> our segment
  4195. ; ----------------------------------------------------------------------
  4196.  
  4197. cmd         proc                            ; find/process command
  4198.             mov     cs:psp_seg, ds          ; save addr of our psp
  4199.             mov     ax, cs                  ; ax = our segment
  4200.             mov     es, ax                  ; .. and es
  4201.  
  4202.             mov     si, 81h                 ; ds:si -> command line
  4203.             mov     di, offset cmd_line     ; es:di -> local cmd line
  4204.             mov     cx, 127                 ; cx = max length
  4205.        rep  movsb                           ; ..and move locally
  4206.  
  4207.             mov     ds, ax                  ; ds -> our segment too
  4208.             mov     user_i23s, ax           ; save our segment
  4209.             mov     user_i24s, ax           ; ..
  4210.             mov     user_i1bs, ax           ; ..
  4211.  
  4212.             mov     dx, offset hdrmsg       ; ds:dx -> header message
  4213.             mov     ah, 9                   ; ah = print ASCII$ string
  4214.             int     21h                     ; .. display header
  4215.  
  4216.             mov     ah, 30h                 ; ah = get version nbr
  4217.             int     21h                     ; call DOS
  4218.  
  4219.             cmp     al, 3                   ; q. DOS 3.0 or higher?
  4220.             jb      cmd_1                   ; a. no .. give error msg
  4221.             ja      cmd_2                   ; else .. greater than 3.x
  4222.  
  4223.             or      ah, ah                  ; q. 3.0?
  4224.             jnz     cmd_2                   ; a. no .. 3.1 or better
  4225.  
  4226. cmd_1:      mov     dx, offset dosmsg       ; dx -> must be >= DOS 3.1
  4227.             xor     al, al                  ; al = no help for them
  4228.             call    die                     ; give msg and die
  4229.  
  4230. cmd_2:      call    loaded                  ; check if loaded
  4231.             mov     tsr_loaded, di          ; save load addr, if loaded
  4232.  
  4233.             mov     si, offset cmd_line     ; si -> command line
  4234.             call    upcase                  ; upcase the command line
  4235.  
  4236. cmd00:      call    nxtop                   ; q. any operands left?
  4237.             jnc     cmd05                   ; a. yes .. continue
  4238.  
  4239.             call    init                    ; do initialization
  4240.             ret                             ; return to caller
  4241.  
  4242. cmd05:      cmp     word ptr [si], '?/'     ; q. help request?
  4243.             jnz     cmd07                   ; a. yes .. give some help
  4244.  
  4245.             mov     dx, offset dollar       ; dx -> null message
  4246.             mov     al, 1                   ; al = give help
  4247.             call    die                     ; terminal w/help
  4248.  
  4249. cmd07:      cmp     word ptr [si], 'P/'     ; q. port number?
  4250.             jnz     cmd20                   ; a. no .. check next
  4251.  
  4252.             mov     al, [si + 2]            ; al = port nbr in ASCII
  4253.  
  4254.             cmp     al, '1'                 ; q. less than COM1?
  4255.             jl      cmd10                   ; a. yes .. give error message
  4256.  
  4257.             cmp     al, '4'                 ; q. greater than COM4?
  4258.             jg      cmd10                   ; a. yes .. give error message
  4259.  
  4260.             sub     al, '0'                 ; al = COMn number
  4261.             cbw                             ; ax = COMn number
  4262.             mov     io_base, ax             ; save for later
  4263.             add     si, 3                   ; si -> after this operand
  4264.             jmp     short cmd00             ; ..continue w/next operand
  4265.  
  4266. cmd10:      mov     word ptr invopnc, 'P/'  ; move /P into message
  4267.             mov     dx, offset invopnd      ; dx -> error message
  4268.             xor     al, al                  ; al = no help
  4269.             call    die                     ; ..give error message
  4270.  
  4271. cmd20:      cmp     word ptr [si], 'H/'     ; q. hex port addr
  4272.             jnz     cmd30                   ; a. no .. check next
  4273.  
  4274.             add     si, 2                   ; si -> hex address
  4275.             call    htoi                    ; ax = hex port addr
  4276.  
  4277.             cmp     ax, 100h                ; q. less than reasonable?
  4278.             jl      cmd25                   ; a. yes .. give error message
  4279.  
  4280.             cmp     ax, 400h                ; q. greater than reasonable?
  4281.             jg      cmd25                   ; a. yes .. give error message
  4282.  
  4283.             mov     io_base, ax             ; save port addr for later
  4284.  
  4285.             cmp     byte ptr [si], ','      ; q. proper format?
  4286.             jne     cmd25                   ; a. no .. give error message
  4287.  
  4288.             inc     si                      ; si -> next char in cmd line
  4289.             call    atoi                    ; al = interrupt nbr
  4290.  
  4291.             cmp     ax, 2                   ; q. less than reasonable?
  4292.             jl      cmd25                   ; a. yes .. give error message
  4293.  
  4294.             cmp     ax, 15                  ; q. greater than reasonable?
  4295.             jg      cmd25                   ; a. yes .. give error message
  4296.  
  4297.             mov     io_int, al              ; save interrupt nbr for latter
  4298.             jmp     short cmd00             ; ..continue w/next operand
  4299.  
  4300. cmd25:      mov     word ptr invopnc, 'H/'  ; move /H into message
  4301.             mov     dx, offset invopnd      ; dx -> error message
  4302.             xor     al, al                  ; al = no help
  4303.             call    die                     ; ..give error message
  4304.  
  4305. cmd30:      cmp     word ptr [si], 'U/'     ; q. uninstall?
  4306.             jne     cmd40                   ; a. no .. continue
  4307.             jmp     uninstall               ; else .. jump into uninstall
  4308.  
  4309. cmd40:      cmp     word ptr [si], 'C/'     ; q. compile?
  4310.             jne     cmd45                   ; a. no .. continue
  4311.  
  4312.             add     si, 2                   ; si -> next operand
  4313.             mov     byte ptr compile_flg, 1 ; set compile flag
  4314.             jmp     cmd00                   ; ..then get next token
  4315.  
  4316. cmd45:      cmp     word ptr [si], 'T/'     ; q. test if script running?
  4317.             jne     cmd50                   ; a. no .. continue
  4318.  
  4319.             xor     al, al                  ; al = no help
  4320.  
  4321.             cmp     tsr_loaded, 0           ; q. loaded at all?
  4322.             jne     cmd46                   ; a. yes .. continue
  4323.  
  4324.             mov     dx, offset notup        ; dx -> not here message
  4325.             mov     dos_rc, 2               ; set errorlevel
  4326.             call    die                     ; ..and exit w/message
  4327.  
  4328. cmd46:      call    needwait                ; q. just waiting around?
  4329.             jc      cmd47                   ; a. no .. give right msg
  4330.  
  4331.             mov     dx, offset readymsg     ; dx -> not busy message
  4332.             mov     dos_rc, 0               ; set errorlevel
  4333.             call    die                     ; ..give msg and quit
  4334.  
  4335. cmd47:      mov     dx, offset busymsg      ; dx -> doing something
  4336.             call    die                     ; ..give msg and quit too
  4337.  
  4338. cmd50:      cmp     word ptr [si], 'S/'     ; q. set script buffer size?
  4339.             jne     cmd60                   ; a. no .. continue
  4340.  
  4341.             add     si, 2                   ; si -> next operand
  4342.             call    atoi                    ; ax = buffer size
  4343.  
  4344.             cmp     ax, 150                 ; q. less than reasonable?
  4345.             jb      cmd55                   ; a. yes .. give error message
  4346.  
  4347.             cmp     ax, 32000               ; q. greater than reasonable?
  4348.             ja      cmd55                   ; a. yes .. give error message
  4349.  
  4350.             mov     script_amt, ax          ; save amount for later
  4351.             jmp     cmd00                   ; ..then get next token
  4352.  
  4353. cmd55:      mov     word ptr invopnc, 'S/'  ; move /S into message
  4354.             mov     dx, offset invopnd      ; dx -> error message
  4355.             xor     al, al                  ; al = no help
  4356.             call    die                     ; ..give error message
  4357.  
  4358. cmd60:      cmp     byte ptr scriptfile, 0  ; q. filename already given?
  4359.             jz      cmd70                   ; a. no .. continue
  4360.  
  4361.             mov     dx, offset badopnd      ; dx -> error message
  4362.             xor     al, al                  ; al = no help
  4363.             call    die                     ; ..give error message
  4364.  
  4365. cmd70:      mov     cx, scriptf_len         ; cx = max string size
  4366.             mov     di, offset scriptfile   ; di -> destination area
  4367.             mov     script_isi, di          ; save addr of string
  4368.             mov     main_state, 4           ; ..and setup for script
  4369.             call    token_copy              ; copy next token
  4370.             jmp     cmd00                   ; then loop up for next operand
  4371.  
  4372. cmd         endp                            ; end of scan routine
  4373.  
  4374.  
  4375.  
  4376. ; ----------------------------------------------------------------------
  4377. ;   token_copy - copy blank delimited token
  4378. ;
  4379. ;   entry: si -> source
  4380. ;          di -> destination
  4381. ;          cx =  max length
  4382. ; ----------------------------------------------------------------------
  4383.  
  4384. token_copy  proc
  4385.  
  4386.             lodsb                           ; al = character from string
  4387.  
  4388.             cmp     al, ' '                 ; q. end of the line?
  4389.             jge     token_c10               ; a. no .. continue
  4390.  
  4391.             dec     si                      ; si -> null character
  4392.             ret                             ; ..then return to caller
  4393.  
  4394. token_c10:  stosb                           ; store char @ destination
  4395.             loop    token_copy              ; ..and loop till end
  4396.  
  4397. token_c90:  ret                             ; ..and return
  4398.  
  4399. token_copy  endp
  4400.  
  4401.  
  4402.  
  4403. ; ----------------------------------------------------------------------
  4404. ;   upcase - upcase string
  4405. ;
  4406. ;   entry: si -> source
  4407. ; ----------------------------------------------------------------------
  4408.  
  4409. upcase      proc
  4410.             push    ax                      ; save registers
  4411.             push    si
  4412.             push    di
  4413.  
  4414.             mov     di, si                  ; di -> dest, same as source
  4415.  
  4416. upcase10:   lodsb                           ; al = character from string
  4417.  
  4418.             cmp     al, 0                   ; q. end of the line?
  4419.             je      upcase90                ; a. yes .. exit loop
  4420.  
  4421.             cmp     al, 0dh                 ; q. end of the line?
  4422.             je      upcase90                ; a. yes .. exit loop
  4423.  
  4424.             cmp     al, 'a'                 ; q. already upper case?
  4425.             jl      upcase20                ; a. yes .. continue
  4426.  
  4427.             and     al, not 20h             ; al = upper case letter
  4428.  
  4429. upcase20:   stosb                           ; store char @ destination
  4430.             jmp     short upcase10          ; ..and loop till end of string
  4431.  
  4432. upcase90:   mov     byte ptr [di], 0        ; mark end of string
  4433.  
  4434.             pop     di                      ; restore registers
  4435.             pop     si
  4436.             pop     ax
  4437.             ret                             ; ..and return
  4438.  
  4439. upcase      endp
  4440.  
  4441.  
  4442.  
  4443. ; ----------------------------------------------------------------------
  4444. ;   atoi - character to integer
  4445. ;
  4446. ;   entry: si -> string
  4447. ;
  4448. ;    exit: ax = number
  4449. ;          si -> 1st non-numeric character
  4450. ; ----------------------------------------------------------------------
  4451.  
  4452. atoi        proc
  4453.  
  4454.             push    bx                      ; save registers
  4455.             push    cx
  4456.             push    dx
  4457.             xor     ax, ax                  ; ax = zero for accumulation
  4458.             xor     bh, bh                  ; bh = zero for addition
  4459.             mov     cx, 10                  ; cx = multiplier
  4460.  
  4461. atoi10:     mov     bl, [si]                ; bl = character from string
  4462.  
  4463.             cmp     bl, '0'                 ; q. less than a zero?
  4464.             jl      atoi90                  ; a. yes .. done
  4465.  
  4466.             cmp     bl, '9'                 ; q. greater than a nine?
  4467.             jg      atoi90                  ; a. yes .. done here too
  4468.  
  4469.             sub     bl, '0'                 ; bl = ATOI of character
  4470.             mul     cx                      ; ax = ax * 10
  4471.             add     ax, bx                  ; ax = new accumulator
  4472.             inc     si                      ; si -> next string character
  4473.             jmp     short atoi10            ; ..then loop till end of string
  4474.  
  4475. atoi90:     pop     dx                      ; restore registers
  4476.             pop     cx
  4477.             pop     bx
  4478.             ret                             ; ..and return to caller
  4479.  
  4480. atoi        endp
  4481.  
  4482.  
  4483.  
  4484. ; ----------------------------------------------------------------------
  4485. ;   htoi - hex character to integer
  4486. ;
  4487. ;   entry: si -> string
  4488. ;
  4489. ;    exit: ax = number
  4490. ;          si -> 1st non-numeric character
  4491. ; ----------------------------------------------------------------------
  4492.  
  4493. htoi        proc
  4494.  
  4495.             push    cx                      ; save registers
  4496.             xor     ax, ax                  ; ax = zero for accumulation
  4497.  
  4498. htoi10:     mov     ch, [si]                ; cl = character from string
  4499.  
  4500.             cmp     ch, '0'                 ; q. less than a zero?
  4501.             jl      htoi90                  ; a. yes .. done
  4502.  
  4503.             cmp     ch, '9'                 ; q. greater than a nine?
  4504.             jg      htoi20                  ; a. yes .. done here too
  4505.  
  4506.             sub     ch, '0'                 ; ch = ATOI of character
  4507.             jmp     short htoi30            ; ..continue w/common code
  4508.  
  4509. htoi20:     cmp     ch, 'A'                 ; q. less than an ah?
  4510.             jl      htoi90                  ; a. yes .. done here
  4511.  
  4512.             cmp     ch, 'F'                 ; q. greater than an ef?
  4513.             jl      htoi90                  ; a. yes .. done here too
  4514.  
  4515.             sub     ch, 'A' - 10            ; ch = HTOI of character
  4516.  
  4517. htoi30:     mov     cl, 4                   ; ch = shift factor
  4518.             shl     ax, cl                  ; ax = ax << 4
  4519.             or      al, ch                  ; ax = new accumulator
  4520.             inc     si                      ; si -> next char from string
  4521.             jmp     short htoi10            ; ..then loop till end of string
  4522.  
  4523. htoi90:     pop     cx                      ; restore registers
  4524.             ret                             ; ..and return to caller
  4525.  
  4526. htoi        endp
  4527.  
  4528.  
  4529.  
  4530. ; ----------------------------------------------------------------------
  4531. ;   loaded - check if TSR loaded
  4532. ;
  4533. ;   exit: di = 0 or segment of TSR
  4534. ; ----------------------------------------------------------------------
  4535.  
  4536. loaded      proc
  4537.             xor     di, di                  ; di = initially TSR not avail
  4538.  
  4539.             mov     ax, multiplex           ; ax = multiplex identifier
  4540.             int     2fh                     ; issue multiplex interrupt
  4541.  
  4542.             ret
  4543.  
  4544. loaded      endp
  4545.  
  4546.  
  4547.  
  4548. ; ----------------------------------------------------------------------
  4549. ;   nxtop - find next operand
  4550. ;
  4551. ;   entry: si -> current position
  4552. ;
  4553. ;    exit: si -> 1st non-blank character
  4554. ;          carry = end of line
  4555. ; ----------------------------------------------------------------------
  4556.  
  4557. nxtop       proc
  4558.             cmp     byte ptr [si], 0        ; q. end of line?
  4559.             jne     nxtop10                 ; a. no .. continue
  4560.  
  4561.             stc                             ; show end of line condition
  4562.             ret                             ; ..and return to caller
  4563.  
  4564. nxtop10:    cmp     byte ptr [si], ' '      ; q. whitespace?
  4565.             jna     nxtop20                 ; a. yes .. skip whitespace
  4566.  
  4567.             clc                             ; show operand found
  4568.             ret                             ; ..and return to caller
  4569.  
  4570. nxtop20:    inc     si                      ; si -> next char
  4571.             jmp     short nxtop             ; ..loop to find nxt operand
  4572.  
  4573. nxtop       endp
  4574.  
  4575.  
  4576.  
  4577. ; ----------------------------------------------------------------
  4578. ;   init - operands are parsed, now process the command line
  4579. ; ----------------------------------------------------------------
  4580.  
  4581. init        proc
  4582.  
  4583.             cmp     compile_flg, 0          ; q. need compile?
  4584.             je      init05                  ; a. no .. continue
  4585.             jmp     compile                 ; else .. do it
  4586.  
  4587. init05:     cmp     tsr_loaded, 0           ; q. already loaded?
  4588.             je      init10                  ; a. no .. ok to load
  4589.  
  4590.             cmp     scriptfile, 0           ; q. run a script?
  4591.             je      init08                  ; a. no .. continue
  4592.  
  4593.             push    es                      ; save register
  4594.             mov     es, tsr_loaded          ; es -> loaded copy
  4595.             cmp     es:main_state, 0        ; q. terminal mode?
  4596.             pop     es                      ; ..restore register
  4597.             je      init07                  ; a. yes .. continue
  4598.  
  4599.             xor     al, al                  ; al = no help
  4600.             mov     dx, offset tsrbusy      ; dx -> error msg
  4601.             call    die                     ; ..issue msg and die
  4602.  
  4603. init07:     mov     di, offset scriptfile   ; di -> cmd line script name
  4604.             call    string_len              ; cx = string length
  4605.             mov     es, tsr_loaded          ; es -> loaded copy of BD
  4606.             mov     es:script_isi, di       ; save addr of string
  4607.             mov     si, di                  ; si -> non-tsr script name
  4608.             call    string_copy             ; copy to tsr
  4609.             mov     es:main_state, 4        ; ..and setup for script
  4610.  
  4611.             xor     al, al                  ; al = no help needed
  4612.             mov     dx, offset tsrsetup     ; dx -> compl msg
  4613.             call    die                     ; ..give msg and die
  4614.  
  4615. init08:     xor     al, al                  ; al = no help needed
  4616.             mov     dx, offset upalrdy      ; dx -> up already message
  4617.             call    die                     ; .. die .. with honor
  4618.  
  4619. init10:     push    es                      ; save es
  4620.  
  4621.             mov     ah, 34h                 ; ah = get DOS busy flg addr
  4622.             int     21h                     ; call DOS
  4623.  
  4624.             dec     bx                      ; bx -> InDos Flags
  4625.             mov     word ptr dos_busy, bx   ; save offset
  4626.             mov     word ptr dos_busy+2, es ; ..and segment of busy flag
  4627.             pop     es                      ;
  4628.  
  4629.             mov     ax, io_base             ; ax = comm base addr
  4630.  
  4631.             cmp     ax, 4                   ; q. COMn specified?
  4632.             jg      init20                  ; a. no .. continue
  4633.  
  4634.             dec     ax                      ; al = zero based entry nbr
  4635.             mov     cl, 3                   ; cl = entry size
  4636.             mul     cl                      ; ax = table offset
  4637.             mov     bx, ax                  ; bx = same
  4638.  
  4639.             mov     ax, io_table[bx]        ; ax = base address
  4640.             mov     io_base, ax             ; ..save for later
  4641.  
  4642.             mov     al, byte ptr io_table+2[bx] ; al = interrupt number
  4643.             mov     io_int, al                  ; ..save for later
  4644.  
  4645. init20:     mov     al, io_int              ; al = interrupt to attach
  4646.             add     al, 8                   ; al = hardware vector nbr
  4647.             mov     hd_int, al              ; save in interrupt table
  4648.  
  4649.             mov     dx, iir                 ; dx = interrupt id register
  4650.             call    in_reg                  ; al = iir if UART present
  4651.  
  4652.             test    al, 0f8h                ; q. UART present?
  4653.             jz      init30                  ; a. yes .. continue
  4654.  
  4655.             xor     al, al                  ; al = no help
  4656.             mov     dx, offset noport       ; dx -> no port message
  4657.             call    die                     ; give message and exit
  4658.  
  4659. init30:     call    bdenv                   ; find BDP= environment
  4660.  
  4661.             ret                             ; return to caller
  4662.  
  4663. init        endp
  4664.  
  4665.  
  4666.  
  4667. ; ----------------------------------------------------------------------
  4668. ;   uninstall - process the uninstall request
  4669. ; ----------------------------------------------------------------------
  4670.  
  4671. uninstall   proc
  4672.             cmp     tsr_loaded, 0           ; q. tsr loaded?
  4673.             jne     unins05                 ; a. yes .. continue
  4674.  
  4675.             xor     ax, ax                  ; ax = zero, no extra help
  4676.             mov     dx, offset notup        ; dx -> message
  4677.             jmp     die                     ; .. die now, sucker
  4678.  
  4679. unins05:    call    needwait                ; q. need to wait?
  4680.             jnc     unins09                 ; a. no .. continue
  4681.  
  4682.             lea     dx, waitmsg             ; dx -> wait message
  4683.             mov     ah, 9                   ; ah = print ASCII$ message
  4684.             int     21h                     ; print message
  4685.  
  4686. unins08:    call    needwait                ; q. need to wait more?
  4687.             jnc     unins09                 ; a. no .. continue
  4688.  
  4689.             mov     ah, 0bh                 ; ah = check keyboard status
  4690.             int     21h                     ; call DOS
  4691.  
  4692.             cmp     al, 0ffh                ; q. character waiting?
  4693.             jne     unins08                 ; a. no .. continue waiting
  4694.  
  4695.             mov     ah, 08h                 ; ah = get char
  4696.             int     21h                     ; al = char
  4697.  
  4698.             cmp     al, 1bh                 ; q. escape?
  4699.             jne     unins09                 ; a. no .. continu
  4700.  
  4701.             mov     dx, offset uninscan     ; dx -> cancelled message
  4702.             jmp     short unins90           ; .. and finish now
  4703.  
  4704. unins09:    mov     si, tsr_loaded          ; si -> tsr's memory
  4705.             mov     ds, si                  ; ds -> same
  4706.             mov     es, si                  ; es -> same
  4707.  
  4708.             call    io_reset                ; turn off UART's interrupts
  4709.  
  4710.             mov     di, intblk1             ; bx -> first interrupt blk
  4711.             mov     cx, intblkcnt           ; cx = number of ints used
  4712.  
  4713. unins10:    mov     ah, 35h                 ; ah = get interrupt
  4714.             mov     al, [di+12]             ; al = interrupt number
  4715.             int     21h                     ; es:bx -> interrupt
  4716.  
  4717.             mov     ax, es                  ; ax = int segment
  4718.             cmp     ax, si                  ; q. our segment?
  4719.             jne     unins80                 ; a. no .. can't uninstall
  4720.  
  4721.             add     di, intblklen           ; si -> next block
  4722.             loop    unins10                 ; .. check next block
  4723.  
  4724.             mov     di, intblk1             ; si -> first interrupt blk
  4725.             mov     cx, intblkcnt           ; cx = number of ints used
  4726.  
  4727.             cli                             ; no ints ..
  4728. unins20:    lds     dx, dword ptr es:[di]   ; ds:dx -> old interrupt rtn
  4729.             mov     ah, 25h                 ; ah = set interrupt
  4730.             mov     al, es:[di+12]          ; al = int to set
  4731.             int     21h                     ; .. set the interrupt
  4732.  
  4733.             add     di, intblklen           ; si -> next block
  4734.             loop    unins20                 ; .. reset next interrupt
  4735.             sti                             ; .. allow interrupts again
  4736.  
  4737.             mov     es, es:psp_seg          ; es = tsr's psp
  4738.             mov     ah, 49h                 ; ah = free tsr memory
  4739.             int     21h                     ; .. do it
  4740.  
  4741.             mov     dx, offset freeok       ; dx -> freed ok.
  4742.             jmp     short unins90           ; .. end the job, painlessly
  4743.  
  4744. unins80:    mov     dx, offset cantfree     ; dx -> can't free message
  4745.  
  4746. unins90:    xor     al, al                  ; al = no help
  4747.  
  4748.             push    cs                      ; restore our ..
  4749.             pop     ds                      ; ..own segment
  4750.  
  4751.             call    die                     ; die .. hard & fast
  4752.  
  4753. uninstall   endp
  4754.  
  4755.  
  4756.  
  4757. ; ----------------------------------------------------------------------
  4758. ;   needwait - checks for the need to wait while download finishes
  4759. ;
  4760. ;   exit: carry = wait needed
  4761. ; ----------------------------------------------------------------------
  4762.  
  4763. needwait    proc
  4764.  
  4765.             push    es                      ; save register
  4766.  
  4767.             mov     es, tsr_loaded          ; es -> tsr's data segment
  4768.  
  4769.             cmp     es:main_state, 0        ; q. just waiting around?
  4770.             pop     es                      ; ..restore register
  4771.             je      needwait1               ; a. yes .. continue
  4772.  
  4773.             stc                             ; set carry / wait
  4774.             ret                             ; ..then return to caller
  4775.  
  4776. needwait1:  clc                             ; clear carry / no-wait
  4777.             ret                             ; ..then return to caller
  4778.  
  4779. needwait    endp
  4780.  
  4781.  
  4782.  
  4783. ; ----------------------------------------------------------------------
  4784. ;   die - terminate w/optional help message
  4785. ;
  4786. ;   entry: dx -> intermediate message
  4787. ;          al = not zero if help wanted
  4788. ; ----------------------------------------------------------------------
  4789.  
  4790. die         proc
  4791.             push    ax                      ; save help request
  4792.  
  4793.             mov     ah, 9                   ; ah = print ASCII$ message
  4794.             int     21h                     ; print the error message
  4795.  
  4796.             pop     ax                      ; restore help request
  4797.             or      al, al                  ; q. help wanted?
  4798.             jz      die10                   ; a. no .. exit
  4799.  
  4800.             mov     dx, offset help         ; dx -> help message
  4801.             mov     ah, 9                   ; ah = print ASCII$ message
  4802.             int     21h                     ; ... print the help
  4803.  
  4804. die10:      mov     ah, 4ch                 ; ah = exit to DOS
  4805.             mov     al, dos_rc              ; al = return code
  4806.             int     21h                     ; ..return to dos
  4807. die         endp
  4808.  
  4809.  
  4810.  
  4811. ; ----------------------------------------------------------------------
  4812. ;  Find BDP environment variable, move path local
  4813. ; ----------------------------------------------------------------------
  4814.  
  4815. bdenv       proc    near
  4816.             push    es                      ; save registers
  4817.             push    ds
  4818.  
  4819.             mov     ds, psp_seg             ; ds -> psp segment
  4820.             mov     ds, ds:[002ch]          ; ds -> environment
  4821.             push    cs                      ; save our segment
  4822.             pop     es                      ; es -> our segment
  4823.             cld                             ; direction is up
  4824.  
  4825.             xor     si,si                   ; di -> start of environment
  4826.  
  4827. bdenv10:    push    si                      ; save current env offset
  4828.             mov     di, offset bdpenvar     ; di -> variable to look for
  4829.             mov     cx, 4                   ; length of string
  4830.       repe  cmpsb                           ; q. same string?
  4831.             je      bdenv50                 ; a. yes .. move in path
  4832.  
  4833.             pop     si                      ; si -> start of env var
  4834.  
  4835. bdenv20:    lodsb                           ; al = char
  4836.  
  4837.             or      al, al                  ; q. end of string?
  4838.             jnz     bdenv20                 ; a. no .. get next byte
  4839.  
  4840.             cmp     byte ptr [si], 0        ; q. end of enviroment?
  4841.             jne     bdenv10                 ; a. no .. check next var
  4842.             jmp     short bdenv90           ; else .. not found, exit
  4843.  
  4844. bdenv50:    pop     ax                      ; kill pushed address
  4845.             mov     di, offset bdpath       ; di -> path variable
  4846.  
  4847. bdenv60:    lodsb                           ; al = char from env
  4848.             stosb                           ; .. put in path
  4849.  
  4850.             or      al, al                  ; q. end of var?
  4851.             jnz     bdenv60                 ; a. no .. get next char
  4852.  
  4853. bdenv90:    pop     ds                      ; ds -> our segment
  4854.             mov     es, psp_seg             ; es -> psp segment
  4855.             mov     es, es:[002ch]          ; es -> environment
  4856.             mov     ah, 49h                 ; ax = release it
  4857.             int     21h                     ; .. tell dos to make it so
  4858.  
  4859.             pop     es                      ; restore regs
  4860.  
  4861.             call    bdpsch                  ; search for .BDP files
  4862.  
  4863.             ret                             ; return to caller
  4864.  
  4865. bdenv       endp
  4866.  
  4867.  
  4868.  
  4869. ; ----------------------------------------------------------------------
  4870. ;   bdpbld - build .BDP path/filename
  4871. ;
  4872. ;   entry: es:di -> fully qualified (FQ) file name area
  4873. ;          ds:si -> ASCIIZ name to append
  4874. ;
  4875. ;    exit: di -> ASCIIZ FQ file name
  4876. ; ----------------------------------------------------------------------
  4877.  
  4878. bdpbld      proc                            ; build file name
  4879.             push    di                      ; save pointer
  4880.             push    si                      ; save append name
  4881.  
  4882.             mov     si, offset bdpath       ; si -> path to move
  4883.  
  4884. bdpbld10:   cmp     byte ptr [si], 0        ; q. end of path?
  4885.             je      bdpbld20                ; a. yes .. append name
  4886.  
  4887.             movsb                           ; move a byte
  4888.             jmp     bdpbld10                ; .. check next byte
  4889.  
  4890. bdpbld20:   pop     si                      ; si -> name to move
  4891.  
  4892. bdpbld30:   movsb                           ; move a byte of name
  4893.  
  4894.             cmp     byte ptr [si-1], 0      ; q. last byte zero?
  4895.             jne     bdpbld30                ; a. no .. move another
  4896.  
  4897.             pop     di                      ; restore ptr
  4898.             ret                             ; return to caller
  4899.  
  4900. bdpbld      endp
  4901.  
  4902.  
  4903.  
  4904. ; ----------------------------------------------------------------------
  4905. ;  bdpsch - search for .BDP modules
  4906. ; ----------------------------------------------------------------------
  4907.  
  4908. bdpsch      proc
  4909.  
  4910.             mov     dx, offset bdpdta       ; ds:dx -> new DTA
  4911.             mov     ah, 1ah                 ; ah = set new DTA fnc
  4912.             int     21h                     ; .. tell DOS to do it
  4913.  
  4914.             cmp     bdpath, 0               ; q. any environment set?
  4915.             jne     bdpsch10                ; a. yes .. use it
  4916.  
  4917.             mov     ah, 19h                 ; ah = get default drive
  4918.             int     21h                     ; al = default drive
  4919.             add     al, 'A'                 ; .. change to a letter
  4920.  
  4921.             mov     bdpath, al              ; set the drive
  4922.             mov     bdpath+1, ':'           ; .. with colon
  4923.             mov     bdpath+2, '\'           ; .. and root dir
  4924.  
  4925.             mov     si, offset bdpath+3     ; si -> place to put path
  4926.             xor     dl, dl                  ; dl = current drive
  4927.             mov     ah, 47h                 ; ah = get current dir
  4928.             int     21h                     ; .. read in current dir
  4929.  
  4930. bdpsch10:   mov     di, offset bdpath       ; di -> bdp directory
  4931.             xor     al, al                  ; al = look for zero
  4932.             mov     cx, 65                  ; cx = max 65 chars
  4933.             cld                             ; .. in upward direction
  4934.      repne  scasb                           ; scan for the end
  4935.  
  4936.             cmp     byte ptr [di-2], '\'    ; q. end in backslash?
  4937.             je      bdpsch15                ; a. yes .. continue
  4938.  
  4939.             mov     byte ptr [di-1], '\'    ; else .. force ending
  4940.             mov     byte ptr [di], 0        ; .. in backslash
  4941.  
  4942. bdpsch15:   mov     di, offset bdpwrk       ; di -> work area
  4943.             mov     si, offset bdpfiles     ; si -> file names
  4944.             call    bdpbld                  ; .. build search environment
  4945.  
  4946.             mov     dx, di                  ; dx -> search argument
  4947.             lea     di, bdprot1             ; di -> 1st entry
  4948.             xor     cx, cx                  ; cx = no attributes
  4949.             mov     ah, 4eh                 ; ah = find first
  4950. bdpsch20:   int     21h                     ; q. file found?
  4951.             jc      bdpsch70                ; a. no .. exit
  4952.  
  4953.             cmp     word ptr bdpdta.fiSize+2, 0  ; q. valid file size?
  4954.             jne     bdpsch30                     ; a. no check next
  4955.  
  4956.             cmp     bdprotn, 0              ; q. 1st protocol?
  4957.             jne     bdpsch25                ; a. no .. skip message
  4958.  
  4959.             mov     ah, 9                   ; ah = print message
  4960.             lea     dx, protsavail          ; dx -> available protocols msg
  4961.             int     21h                     ; issue DOS call
  4962.  
  4963. bdpsch25:   call    bdpgetinfo              ; get the file information
  4964.  
  4965.             cmp     bdprotn, bdmaxprots     ; q. all protocols filled?
  4966.             je      bdpsch70                ; a. yes .. look no further
  4967.  
  4968. bdpsch30:   mov     ah, 4fh                 ; ah = find next file
  4969.             jmp     bdpsch20                ; .. ask DOS about it
  4970.  
  4971. bdpsch70:   mov     dx, 80h                 ; dx -> original dta
  4972.             mov     ah, 1ah                 ; ah = setup new dta
  4973.             int     21h                     ; .. tell DOS to do it
  4974.  
  4975.             add     di, 15                  ; di = rounding up..
  4976.             and     di, 0fff0h              ; ..to next paragraph
  4977.             mov     nxtavail, di            ; start alloc's after hdrs
  4978.  
  4979.             cmp     bdprotn, 0              ; q. any protocols?
  4980.             je      bdpsch80                ; a. no .. give warning msg
  4981.  
  4982.             mov     ah, 9                   ; ah = display message
  4983.             lea     dx, crlf$               ; dx -> spacing message
  4984.             int     21h                     ; issue DOS call
  4985.             int     21h                     ; ..again
  4986.  
  4987.             jmp     short bdpsch90          ; ..and exit thru bottom
  4988.  
  4989. bdpsch80:   mov     ah, 9                   ; ah = display a message
  4990.             lea     dx, noprots             ; dx -> no protocols avail
  4991.             int     21h                     ; issue DOS call
  4992.             mov     noprots_1, 0            ; make null terminated string
  4993.  
  4994. bdpsch90:   ret                             ; return to caller
  4995.  
  4996. bdpsch      endp
  4997.  
  4998.  
  4999. ; ----------------------------------------------------------------------
  5000. ;   bdpgetinfo - get .BDP file header information
  5001. ;
  5002. ;   entry: di -> table entry to fill in
  5003. ;    exit: di -> next available entry
  5004. ; ----------------------------------------------------------------------
  5005.  
  5006. bdpgetinfo  proc                            ; get information on protocol
  5007.  
  5008.             push    di                      ; save bdprot pointer
  5009.  
  5010.             lea     di, [di].bdpfile        ; di -> prot file name area
  5011.             lea     si, bdpdta.fiName       ; si -> protocol file name
  5012.             call    bdpbld                  ; .. build FQ file name
  5013.  
  5014.             mov     dx, di                  ; ds:dx -> file name
  5015.             pop     di                      ; .. restore prot pointer
  5016.  
  5017.             mov     ax, 3d00h               ; ax = open for read
  5018.             int     21h                     ; open the file
  5019.             jc      bdpget90                ; .. exit if error
  5020.  
  5021.             push    ax                      ; save the handle
  5022.             mov     bx, ax                  ; bx = handle
  5023.             mov     ah, 3fh                 ; ah = read
  5024.             mov     cx, 6                   ; ..JMP through protocol count
  5025.             lea     dx, bdpwrk              ; dx -> into the work area
  5026.             int     21h                     ; read the header
  5027.             jc      bdpget80                ; ..skip file if error
  5028.  
  5029.             mov     ax, word ptr bdpwrk+3   ; get the "BD"
  5030.  
  5031.             cmp     ax, "DB"                ; q. backdown module?
  5032.             jne     bdpget80                ; a. no .. skip this file
  5033.  
  5034.             mov     cl, bdpwrk+5            ; cl = protocols in this module
  5035.             xor     ch, ch                  ; cx = loop counter
  5036.  
  5037. bdpget10:   push    cx                      ; save loop counter
  5038.             mov     ah, 3fh                 ; ah = read
  5039.             mov     cx, 19                  ; cx = bytes to move
  5040.             mov     dx, di                  ; dx = di = header area
  5041.             int     21h                     ; read the header
  5042.  
  5043.             lea     di, [di].bdpfile        ; di -> prot file name area
  5044.             lea     si, bdpdta.fiName       ; si -> protocol file name
  5045.             call    bdpbld                  ; build FQ file name
  5046.             mov     di, dx                  ; di -> start of entry again
  5047.  
  5048.             mov     ah, 9                   ; ah = display message
  5049.             lea     dx, protsetup           ; dx -> spacing message
  5050.             int     21h                     ; issue DOS call
  5051.  
  5052.             push    bx                      ; save registers
  5053.             mov     bx, 1                   ; bx =  STDOUT handle
  5054.             mov     cx, 17                  ; cx =  chars to write
  5055.             lea     dx, [di+1]              ; dx -> protocol description
  5056.             mov     ah, 40h                 ; ah =  write to file
  5057.             int     21h                     ; .. do it DOS
  5058.             pop     bx                      ; restore registers
  5059.             pop     cx                      ;
  5060.  
  5061.             inc     bdprotn                 ; increment num of protocols
  5062.  
  5063.             cmp     bdprotn, bdmaxprots     ; q. all protocols filled?
  5064.             je      bdpget80                ; a. yes .. look no further
  5065.  
  5066.             add     di, bdprotlen           ; di -> next table entry
  5067.             loop    bdpget10                ; loop till table filled
  5068.  
  5069.             mov     ax, word ptr bdpdta.fiSize  ; ax = size of file
  5070.  
  5071.             cmp     ax, bdplen              ; q. bigger than largest so far?
  5072.             jna     bdpget80                ; a. no .. check next
  5073.  
  5074.             mov     bdplen, ax              ; .. set new len
  5075.  
  5076. bdpget80:   pop     bx                      ; bx = handle to close
  5077.             mov     ah, 3eh                 ; ah = close function
  5078.             int     21h                     ; .. do it DOS
  5079.  
  5080. bdpget90:   ret                             ; return to caller
  5081.  
  5082. bdpgetinfo  endp
  5083.  
  5084.  
  5085.  
  5086. ; ----------------------------------------------------------------------
  5087. ;   compile - script compiler
  5088. ; ----------------------------------------------------------------------
  5089.  
  5090. compile     proc
  5091.             call    comp_open               ; open script file
  5092.  
  5093. comp10:     call    comp_read               ; read a line
  5094.             jc      comp50                  ; at eof, cleanup
  5095.  
  5096.             call    comp_pars               ; parse line into buffer
  5097.             jmp     short comp10            ; ..and loop till eof
  5098.  
  5099. comp50:     call    comp_check              ; check for unresolved references
  5100.             call    comp_write              ; write out compiled file
  5101.             call    comp_stats              ; give completion msg and die
  5102.  
  5103. compile     endp
  5104.  
  5105.  
  5106.  
  5107. ; ----------------------------------------------------------------------
  5108. ;   comp_open - open script file
  5109. ;
  5110. ;   entry: scriptfile = filename
  5111. ;
  5112. ;    exit: scr_handle = file handle
  5113. ; ----------------------------------------------------------------------
  5114.  
  5115. comp_open   proc
  5116.             cmp     scriptfile, 0           ; q. script filename given?
  5117.             je      comp_open3              ; a. yes .. continue
  5118.  
  5119. comp_open1: mov     di, offset scriptfile   ; di -> script filename
  5120.             mov     al, '.'                 ; al = search character
  5121.             call    string_len              ; cx = string length
  5122.  
  5123.       repne scasb                           ; q. find the period?
  5124.             je      comp_open2              ; a. yes .. continue
  5125.  
  5126.             mov     si, offset bds          ; si -> script extension
  5127.             call    string_copy             ; copy our extension
  5128.  
  5129. comp_open2: mov     dx, offset scriptfile   ; dx -> filename
  5130.             mov     ax, 3d00h               ; ax = open for read function
  5131.             int     21h                     ; call DOS
  5132.             jnc     comp_open4              ; ..if ok, continue
  5133.  
  5134. comp_open3: mov     dx, offset needfile     ; dx -> error message
  5135.             xor     ax, ax                  ; ax = give msg only
  5136.             call    die                     ; ..give 'em some help
  5137.  
  5138. comp_open4: mov     scr_handle, ax          ; save file handle for later
  5139.             ret                             ; ..and return
  5140.  
  5141. comp_open   endp
  5142.  
  5143.  
  5144.  
  5145. ; ----------------------------------------------------------------------
  5146. ;   comp_read - read a script line
  5147. ;
  5148. ;   exit: line_buffer = inputted line
  5149. ; ----------------------------------------------------------------------
  5150.  
  5151. comp_read   proc
  5152.  
  5153.             cmp     eof, 1                  ; q. at eof, already?
  5154.             je      comp_rea9               ; a. no .. continue
  5155.  
  5156. comp_rea0:  mov     bx, scr_handle          ; bx = handle number
  5157.             mov     cx, 1                   ; cx = nbr of chars to read
  5158.             mov     dx, offset line_buffer  ; dx -> input buffer
  5159.  
  5160. comp_rea1:  mov     ah, 3fh                 ; ah = read function code
  5161.             int     21h                     ; call DOS
  5162.  
  5163.             or      ax, ax                  ; q. anything read?
  5164.             jz      comp_rea7               ; a. no .. must be at eof
  5165.  
  5166.             mov     si, dx                  ; si -> last character read
  5167.  
  5168.             cmp     byte ptr [si], ' '      ; q. less than a blank?
  5169.             jle     comp_rea1               ; a. yes .. get next character
  5170.  
  5171.             inc     dx                      ; dx -> next buffer spot
  5172.  
  5173. comp_rea2:  mov     ah, 3fh                 ; ah = read function code
  5174.             int     21h                     ; call DOS
  5175.  
  5176.             or      ax, ax                  ; q. anything read?
  5177.             jz      comp_rea7               ; a. no .. must be at eof
  5178.  
  5179.             mov     si, dx                  ; si -> last character read
  5180.  
  5181.             cmp     byte ptr [si], 0dh      ; q. carriage return?
  5182.             je      comp_rea3               ; a. yes .. exit loop
  5183.  
  5184.             inc     dx                      ; dx -> next buffer spot
  5185.  
  5186.             cmp     dx, offset line_end     ; q. at end of input buffer?
  5187.             jl      comp_rea2               ; a. no .. loop
  5188.  
  5189. comp_rea3:  mov     si, dx                  ; si -> next line buffer position
  5190.             mov     word ptr [si], 0        ; make into null terminated string
  5191.             jmp     short comp_rea8         ; ..and test if ok to leave
  5192.  
  5193. comp_rea7:  mov     eof, 1                  ; show input at eof
  5194.  
  5195. comp_rea8:  cmp     dx, offset line_buffer  ; q. anything read?
  5196.             je      comp_rea9               ; a. no .. return eof
  5197.  
  5198.             mov     next_token, offset line_buffer + 1  ; init token pointer
  5199.             clc                             ; show everything is ok
  5200.             ret                             ; ..and return to caller
  5201.  
  5202. comp_rea9:  stc                             ; show at eof
  5203.             ret                             ; ..and return to caller
  5204.  
  5205. comp_read   endp
  5206.  
  5207.  
  5208.  
  5209. ; ----------------------------------------------------------------------
  5210. ;   comp_pars - parse script command
  5211. ; ----------------------------------------------------------------------
  5212.  
  5213. comp_pars   proc
  5214.             mov     al, line_buffer         ; al = command letter
  5215.             call    comp_ul                 ; ..make sure its uppercase
  5216.  
  5217.             mov     bx, offset comp_cmds    ; bx -> commands list
  5218.  
  5219. comp_par1:  cmp     [bx], al                ; q. find command?
  5220.             je      comp_par2               ; a. yes .. exit loop
  5221.  
  5222.             add     bx, 4                   ; bx -> next cmd entry
  5223.  
  5224.             cmp     byte ptr [bx], 0        ; q. at end of table?
  5225.             jne     comp_par1               ; a. no .. continue
  5226.  
  5227.             mov     dx, offset badcmd       ; dx -> error message
  5228.             jmp     comp_die                ; print line and die
  5229.  
  5230. comp_par2:  mov     si, compile_ptr         ; si -> next offset
  5231.             mov     al, 1[bx]               ; al = compiled rtn nbr
  5232.             mov     [si], al                ; save in compiled buffer
  5233.             inc     si                      ; si -> next place in buffer
  5234.             call    word ptr 2[bx]          ; call specific cmds parse rtn
  5235.                                             ; ..with  si -> compile buffer
  5236.             mov     compile_ptr, si         ; save next compile ptr
  5237.             ret                             ; then return to caller
  5238.  
  5239. comp_pars   endp
  5240.  
  5241.  
  5242.  
  5243. ; ----------------------------------------------------------------------
  5244. ;   comp_init - parse initialize port command
  5245. ; ----------------------------------------------------------------------
  5246.  
  5247. comp_init   proc
  5248.  
  5249.             xor     ax, ax                  ; ax = zero for init'g
  5250.             mov     [si], ax                ; init defaults
  5251.             mov     2[si], ax
  5252.             mov     4[si], al
  5253.             mov     bx, si                  ; bx -> output area
  5254.  
  5255. comp_ini2:  call    token                   ; di -> a token
  5256.             jc      comp_ini9               ; ..if none, exit
  5257.  
  5258.             mov     si, di                  ; si -> the token
  5259.             call    upcase                  ; uppercase the token
  5260.  
  5261.             mov     si, offset comp_parms   ; bx -> line info table
  5262.             mov     cx, comp_parmn          ; cx = table length
  5263.  
  5264. comp_ini3:  call    string_comp             ; q. find correct type?
  5265.             jc      comp_ini4               ; a. yes .. exit loop
  5266.  
  5267.             add     si, comp_parml          ; si -> next entry
  5268.             loop    comp_ini3               ; ..and try next entry
  5269.  
  5270.             mov     dx, offset badtype      ; dx -> bad type msg
  5271.             jmp     comp_die                ; ..and die gracefully
  5272.  
  5273. comp_ini4:  mov     al, 7[si]               ; al = offset into output
  5274.             xor     ah, ah                  ; ax = offset
  5275.             push    bx                      ; save register
  5276.             add     bx, ax                  ; bx -> target in output
  5277.             mov     al, 8[si]               ; al = data value
  5278.             mov     [bx], al                ; save in compile buffer
  5279.             pop     bx                      ; restore register
  5280.  
  5281.             call    string_len              ; cx = string length
  5282.             add     di, cx                  ; di -> null
  5283.             mov     byte ptr [di], ' '      ; fixup statement
  5284.  
  5285.             jmp     comp_ini2               ; ..loop back for next token
  5286.  
  5287. comp_ini9:  mov     si, bx                  ; si -> back to compile buffer
  5288.             add     si, 5                   ; si -> next compile output area
  5289.             ret                             ; ..and return to caller
  5290.  
  5291. comp_init   endp
  5292.  
  5293.  
  5294.  
  5295. ; ----------------------------------------------------------------------
  5296. ;   comp_send - parse send string, notify operator, and wait commands
  5297. ; ----------------------------------------------------------------------
  5298.  
  5299. comp_send   proc
  5300.  
  5301.             call    next                    ; q. di -> start of string?
  5302.             jnc     comp_send1              ; a. yes .. continue
  5303.  
  5304.             mov     dx, offset missingmsg   ; dx -> error msg
  5305.             jmp     comp_die                ; give message and quit
  5306.  
  5307. comp_send1: call    comp_copy               ; copy rest of line
  5308.             ret                             ; ..then return to caller
  5309.  
  5310. comp_send   endp
  5311.  
  5312.  
  5313.  
  5314. ; ----------------------------------------------------------------------
  5315. ;   comp_time - parse timeout command
  5316. ; ----------------------------------------------------------------------
  5317.  
  5318. comp_time   proc
  5319.  
  5320.             call    token                   ; get timeout value
  5321.  
  5322.             push    si                      ; save register
  5323.             mov     si, di                  ; si -> token
  5324.             call    atoi                    ; ax = nbr
  5325.             pop     si                      ; restore register
  5326.  
  5327.             or      ax, ax                  ; q. any time?
  5328.             jz      comp_time1              ; a. no .. save zero ticks
  5329.  
  5330.             cwd                             ; dx:ax = nbr of seconds
  5331.             mov     cx, 182                 ; cx = 18.2 ticks/second
  5332.             mul     cx                      ; dx:ax = ticks * 10
  5333.             mov     cx, 10                  ; cx = divisor
  5334.             div     cx                      ; ax = nbr of ticks
  5335.  
  5336. comp_time1: mov     [si], ax                ; save value
  5337.  
  5338.             add     si, 2                   ; si -> next compile output area
  5339.             mov     word ptr [si], -1       ; init label field to -1
  5340.  
  5341.             call    token                   ; get label string
  5342.             jc      comp_time9              ; ..exit if no label given
  5343.  
  5344.             call    comp_ltoo               ; ax = label offset
  5345.             mov     [si], ax                ; save in compile buffer
  5346.  
  5347. comp_time9: add     si, 2                   ; si -> next compile output area
  5348.             ret                             ; return to caller
  5349.  
  5350. comp_time   endp
  5351.  
  5352.  
  5353.  
  5354. ; ----------------------------------------------------------------------
  5355. ;   comp_hang - parse hangup command
  5356. ; ----------------------------------------------------------------------
  5357.  
  5358. comp_hang   proc
  5359.             ret                             ; return to caller
  5360. comp_hang   endp
  5361.  
  5362.  
  5363.  
  5364. ; ----------------------------------------------------------------------
  5365. ;   comp_down - parse download command
  5366. ; ----------------------------------------------------------------------
  5367.  
  5368. comp_down   proc
  5369.  
  5370.             call    next                    ; get protocol/operands
  5371.             call    comp_copy               ; copy to compile buffer
  5372.             ret                             ; return to caller
  5373.  
  5374. comp_down   endp
  5375.  
  5376.  
  5377.  
  5378. ; ----------------------------------------------------------------------
  5379. ;   comp_what - parse prompt command
  5380. ; ----------------------------------------------------------------------
  5381.  
  5382. comp_what   proc
  5383.  
  5384.             call    token                   ; get timeout value
  5385.  
  5386.             mov     al, [di]                ; al = prompt variable
  5387.             call    comp_ul                 ; ..and turn into uppercase
  5388.  
  5389.             call    string_len              ; cx = string length
  5390.             add     di, cx                  ; di -> null
  5391.             mov     byte ptr [di], ' '      ; fixup statement
  5392.  
  5393.             cmp     al, 'A'                 ; q. valid variable (A-Z)?
  5394.             jl      comp_wha1               ; a. no .. give error msg
  5395.  
  5396.             cmp     al, 'Z'                 ; q. within upper limit?
  5397.             jle     comp_wha2               ; a. yes .. good, continue
  5398.  
  5399. comp_wha1:  mov     dx, offset badvariable  ; dx -> error message
  5400.             jmp     comp_die                ; ..then give msg and die
  5401.  
  5402. comp_wha2:  sub     al, 'A' - 9             ; al = var nbr in replacable tbl
  5403.             push    ax                      ; save prompt entry nbr
  5404.             call    next                    ; q. find prompt in command
  5405.             jnc     comp_wha3               ; a. yes .. continue
  5406.  
  5407.             cmp     byte ptr [si-1], 16     ; q. equate statement
  5408.             je      comp_wha3               ; a. yes .. allow null string
  5409.  
  5410.             mov     dx, offset missingmsg   ; dx -> error msg
  5411.             jmp     comp_die                ; give message and quit
  5412.  
  5413. comp_wha3:  call    comp_copy               ; copy rest of line
  5414.  
  5415.             pop     ax                      ; restore register
  5416.             mov     [si], al                ; save prompt character
  5417.             inc     si                      ; si -> next compile location
  5418.             ret                             ; ..then return to caller
  5419.  
  5420. comp_what   endp
  5421.  
  5422.  
  5423.  
  5424. ; ----------------------------------------------------------------------
  5425. ;   comp_goto - parse goto label command
  5426. ; ----------------------------------------------------------------------
  5427.  
  5428. comp_goto   proc
  5429.  
  5430.             call    token                   ; q. get label?
  5431.             jnc     comp_goto1              ; a. yes .. continue
  5432.  
  5433.             mov     dx, offset nolabel      ; dx -> error message
  5434.             jmp     comp_die                ; give msg and quit
  5435.  
  5436. comp_goto1: mov     byte ptr 8[di], 0       ; trim length if too long
  5437.  
  5438.             call    comp_ltoo               ; ax = label offset
  5439.             mov     [si], ax                ; save in compile buffer
  5440.             add     si, 2                   ; si -> next compile output area
  5441.             ret                             ; return to caller
  5442.  
  5443. comp_goto   endp
  5444.  
  5445.  
  5446.  
  5447. ; ----------------------------------------------------------------------
  5448. ;   comp_label - parse label statement
  5449. ; ----------------------------------------------------------------------
  5450.  
  5451. comp_label  proc
  5452.             dec     si                      ; si -> correct output area
  5453.             push    si                      ; save registers
  5454.  
  5455.             call    token                   ; get the label token
  5456.             jnc     comp_labe1              ; a. yes .. continue
  5457.  
  5458.             mov     dx, offset lab_missing  ; dx -> error message
  5459.             jmp     comp_die                ; give msg and quit
  5460.  
  5461. comp_labe1: mov     ax, si                  ; ax -> current compile buffer
  5462.             sub     ax, offset compile_buf  ; ax = offset into compile buffer
  5463.             xor     bx, bx                  ; clear addr of an open slot
  5464.             mov     cx, sym_number          ; cx = loop count
  5465.             mov     si, di                  ; si -> new label
  5466.             mov     di, offset symbols      ; di -> symbol table
  5467.  
  5468. comp_labe2: cmp     sym_flag[di], 0         ; q. unused entry?
  5469.             jne     comp_labe3              ; a. no .. continue
  5470.  
  5471.             or      bx, bx                  ; q. need an open entry?
  5472.             jnz     comp_labe5              ; a. no .. continue
  5473.  
  5474.             mov     bx, di                  ; bx -> unused entry
  5475.             jmp     short comp_labe5        ; ..continue with common code
  5476.  
  5477. comp_labe3: call    string_comp             ; q. find a previous reference?
  5478.             jnc     comp_labe5              ; a. no .. try next
  5479.  
  5480.             cmp     sym_flag[di], 1         ; q. referenced entry?
  5481.             je      comp_labe4              ; a. yes .. continue
  5482.  
  5483.             mov     dx, offset duplabel     ; dx -> error message
  5484.             jmp     comp_die                ; give message and quit
  5485.  
  5486. comp_labe4: mov     sym_flag[di], 0         ; make entry usable again
  5487.             push    di                      ; save register
  5488.             mov     di, sym_offset[di]      ; di -> compile buffer reference
  5489.             mov     [di], ax                ; save reference
  5490.             pop     di                      ; restore register
  5491.             jmp     short comp_labe2        ; ..check if we need a free entry
  5492.  
  5493. comp_labe5: add     di, sym_entry           ; di -> next entry
  5494.             loop    comp_labe2              ; ..and loop to next entry
  5495.  
  5496.             or      bx, bx                  ; q. any free entries?
  5497.             jnz     comp_labe6              ; a. yes .. continue
  5498.  
  5499.             mov     dx, offset tablefull    ; dx -> error message
  5500.             xor     ax, ax                  ; ah = no help
  5501.             call    die                     ; give err msg and die
  5502.  
  5503. comp_labe6: mov     di, bx                  ; di -> new unresolved entry
  5504.             call    string_copy             ; copy name to table
  5505.             mov     sym_flag[bx], 2         ; show entry in use
  5506.             pop     si                      ; restore register
  5507.             mov     sym_offset[bx], si      ; save reference for fixup
  5508.  
  5509.             ret                             ; ..and return to caller
  5510.  
  5511. comp_label  endp
  5512.  
  5513.  
  5514.  
  5515. ; ----------------------------------------------------------------------
  5516. ;   comp_nada - parse comment line
  5517. ; ----------------------------------------------------------------------
  5518.  
  5519. comp_nada   proc
  5520.  
  5521.             dec     si                      ; don't compile in an opcode
  5522.             ret                             ; just return to caller
  5523.  
  5524. comp_nada   endp
  5525.  
  5526.  
  5527.  
  5528. ; ----------------------------------------------------------------------
  5529. ;   comp_wait - parse wait command
  5530. ; ----------------------------------------------------------------------
  5531.  
  5532. comp_wait   proc
  5533.  
  5534.             call    token                   ; get wait value
  5535.  
  5536.             push    si                      ; save register
  5537.             mov     si, di                  ; si -> token
  5538.             call    atoi                    ; ax = nbr
  5539.             pop     si                      ; restore register
  5540.  
  5541.             or      ax, ax                  ; q. any time to wait?
  5542.             jz      comp_wait1              ; a. no .. save zero ticks
  5543.  
  5544.             cwd                             ; dx:ax = nbr of seconds
  5545.             mov     cx, 182                 ; cx = 18.2 ticks/second
  5546.             mul     cx                      ; dx:ax = ticks * 10
  5547.             mov     cx, 10                  ; cx = divisor
  5548.             div     cx                      ; ax = nbr of ticks
  5549.  
  5550. comp_wait1: mov     [si], ax                ; save value
  5551.  
  5552.             add     si, 2                   ; si -> next compile output area
  5553.             ret                             ; return to caller
  5554.  
  5555. comp_wait   endp
  5556.  
  5557.  
  5558.  
  5559. ; ----------------------------------------------------------------------
  5560. ;   comp_opt - parse display options command
  5561. ; ----------------------------------------------------------------------
  5562.  
  5563. comp_opt    proc
  5564.  
  5565.             call    token                   ; di -> next token
  5566.             push    si                      ; save register
  5567.             mov     si, di                  ; si -> token
  5568.             call    atoi                    ; ax = baud rate
  5569.             pop     si                      ; restore register
  5570.             mov     [si], ax                ; save token in compile buffer
  5571.             add     si, 2                   ; si -> next compile output area
  5572.             ret                             ; ..and return to caller
  5573.  
  5574. comp_opt    endp
  5575.  
  5576.  
  5577.  
  5578. ; ----------------------------------------------------------------------
  5579. ;   comp_check - check for undefines
  5580. ; ----------------------------------------------------------------------
  5581.  
  5582. comp_check  proc
  5583.  
  5584.             xor     bx, bx                  ; clear error found flag
  5585.             mov     cx, sym_number          ; cx = loop count
  5586.             mov     di, offset symbols      ; di -> symbol table
  5587.  
  5588. comp_chec1: cmp     sym_flag[di], 1         ; q. referenced and not resolved?
  5589.             jne     comp_chec3              ; a. no .. give error
  5590.  
  5591.             or      bx, bx                  ; q. 1st time?
  5592.             jnz     comp_chec2              ; a. no .. continue
  5593.  
  5594.             inc     bx                      ; bx = error found
  5595.             mov     dx, offset undefined    ; dx -> header error msg
  5596.             mov     ah, 9h                  ; ah = print string
  5597.             int     21h                     ; display error line
  5598.  
  5599. comp_chec2: push    di                      ; save register
  5600.             mov     si, di                  ; si -> symbol entry
  5601.             add     si, sym_name            ; si -> symbol name
  5602.             mov     di, offset undef_item   ; di -> part of error msg
  5603.             call    string_copy             ; copy in symbol name
  5604.  
  5605.             mov     si, offset crlf$        ; si -> message terminator
  5606.             call    string_copy             ; copy msg ending
  5607.             mov     dx, offset undef_msg    ; dx -> error message
  5608.             mov     ah, 9h                  ; ah = print string
  5609.             int     21h                     ; display error line
  5610.             pop     di                      ; restore register
  5611.  
  5612. comp_chec3: add     di, sym_entry           ; di -> next entry
  5613.             loop    comp_chec1              ; ..and check next entry
  5614.  
  5615.             or      bx, bx                  ; q. any errors?
  5616.             jz      comp_chec9              ; a. no .. continue
  5617.  
  5618.             mov     dx, offset crlf$        ; dx -> just a <CR><LF>
  5619.             xor     ax, ax                  ; ax = no help
  5620.             call    die                     ; ..and exit gracefully
  5621.  
  5622. comp_chec9: ret                             ; ..now return to caller
  5623.  
  5624. comp_check  endp
  5625.  
  5626.  
  5627.  
  5628. ; ----------------------------------------------------------------------
  5629. ;   comp_ltoo - label to offset
  5630. ;
  5631. ;   entry: di -> label string
  5632. ;          si =  current compile buffer offset
  5633. ;    exit: ax = label offset or -1
  5634. ; ----------------------------------------------------------------------
  5635.  
  5636. comp_ltoo   proc
  5637.             push    si                      ; save register
  5638.  
  5639.             mov     ax, si                  ; ax = current compile buff offset
  5640.             xor     bx, bx                  ; clear addr of an open slot
  5641.             mov     cx, sym_number          ; cx = loop count
  5642.             mov     si, di                  ; si -> new label
  5643.             mov     di, offset symbols      ; di -> symbol table
  5644.  
  5645. comp_lto1:  cmp     sym_flag[di], 2         ; q. resolved entry?
  5646.             jne     comp_lto2               ; a. yes .. continue
  5647.  
  5648.             call    string_comp             ; q. find entry?
  5649.             jnc     comp_lto3               ; a. no .. try next
  5650.  
  5651.             mov     ax, sym_offset[di]      ; ax -> compile buffer
  5652.             sub     ax, offset compile_buf  ; ax = offset of label
  5653.             jmp     short comp_lto9         ; ..exit via common point
  5654.  
  5655. comp_lto2:  or      bx, bx                  ; q. need an open entry?
  5656.             jnz     comp_lto3               ; a. no .. continue
  5657.  
  5658.             cmp     sym_flag[di], 0         ; q. unused entry?
  5659.             jnz     comp_lto3               ; a. no .. continue
  5660.  
  5661.             mov     bx, di                  ; bx -> unused entry
  5662.             jmp     short comp_lto3         ; ..continue with common code
  5663.  
  5664. comp_lto3:  add     di, sym_entry           ; di -> next entry
  5665.             loop    comp_lto1               ; ..and loop to next entry
  5666.  
  5667.             or      bx, bx                  ; q. any free entries?
  5668.             jnz     comp_lto4               ; a. yes .. continue
  5669.  
  5670.             mov     dx, offset tablefull    ; dx -> error message
  5671.             xor     ax, ax                  ; ah = no help
  5672.             call    die                     ; give err msg and die
  5673.  
  5674. comp_lto4:  mov     di, bx                  ; di -> new unresolved entry
  5675.             mov     sym_flag[di], 1         ; show entry in use
  5676.             mov     sym_offset[di], ax      ; save reference for fixup
  5677.             call    string_copy             ; copy name to table
  5678.  
  5679.             mov     ax, -1                  ; ax = dummy value
  5680. comp_lto9:  pop     si                      ; restore register
  5681.             ret                             ; ..and return to caller
  5682.  
  5683. comp_ltoo   endp
  5684.  
  5685.  
  5686. ; ----------------------------------------------------------------------
  5687. ;   comp_write - write compile buffer
  5688. ;
  5689. ;   entry: compile buffer
  5690. ;    exit: ax = compiled filesize
  5691. ; ----------------------------------------------------------------------
  5692.  
  5693. comp_write  proc
  5694.  
  5695.             mov     ah, 3eh                 ; ah = close file handle
  5696.             mov     bx, scr_handle          ; bx = input file handle
  5697.             int     21h                     ; call DOS
  5698.  
  5699.             mov     di, offset scriptfile   ; di -> script filename
  5700.             mov     al, '.'                 ; al = search character
  5701.             call    string_len              ; cx = string length
  5702.       repne scasb                           ; find the period, if any
  5703.  
  5704.             mov     si, offset bdc          ; si -> compiled script extension
  5705.             call    string_copy             ; copy our extension
  5706.  
  5707.             mov     dx, offset scriptfile   ; dx -> filename
  5708.             mov     ah, 3ch                 ; ax = create file
  5709.             xor     cx, cx                  ; cx = normal file
  5710.             int     21h                     ; call DOS
  5711.             jnc     comp_writ1              ; ..if ok, continue
  5712.  
  5713.             mov     dx, offset wontopen     ; dx -> error message
  5714.             xor     ax, ax                  ; ax = give msg only
  5715.             call    die                     ; ..give 'em some help
  5716.  
  5717. comp_writ1: mov     bx, ax                  ; bx = file handle
  5718.             mov     ah, 40h                 ; ah = write file
  5719.             lea     dx, script_id           ; dx -> script id bytes
  5720.             mov     cx, 3                   ; cx = length of special hdr
  5721.             int     21h                     ; call DOS
  5722.  
  5723.             mov     si, compile_ptr         ; si -> next compile buffer addr
  5724.             mov     dx, offset compile_buf  ; dx -> output buffer
  5725.             mov     byte ptr [si], 0        ; make last entry be a null
  5726.             inc     si                      ; si -> past last entry
  5727.  
  5728.             sub     si, dx                  ; si = length used
  5729.             mov     cx, si                  ; cx = length to write
  5730.             push    cx                      ; save .bdc filesize
  5731.             mov     ah, 40h                 ; ah = write
  5732.             int     21h                     ; call DOS
  5733.  
  5734.             or      ax, ax                  ; q. ok?
  5735.             jnz     comp_writ2              ; a. yes .. continue
  5736.  
  5737.             mov     dx, offset cantwrite    ; dx -> error message
  5738.             xor     ax, ax                  ; ax = give msg only
  5739.             call    die                     ; ..give 'em some help
  5740.  
  5741. comp_writ2: mov     ah, 3eh                 ; ah = close file handle
  5742.             int     21h                     ; call DOS
  5743.  
  5744.             pop     ax                      ; ax = compiled script size
  5745.             inc     ax                      ; ..
  5746.             inc     ax                      ; ax = filesize
  5747.             ret                             ; ..then return to caller
  5748.  
  5749. comp_write  endp
  5750.  
  5751.  
  5752.  
  5753. ; ----------------------------------------------------------------------
  5754. ;   comp_stats - print completion msg
  5755. ;
  5756. ;   entry: ax = output file size
  5757. ; ----------------------------------------------------------------------
  5758.  
  5759. comp_stats  proc
  5760.  
  5761.             push    ax                      ; save register
  5762.             mov     ah, 9h                  ; ah = print string
  5763.             mov     dx, offset compdone     ; dx -> completion message
  5764.             int     21h                     ; display part 1 of message
  5765.  
  5766.             pop     ax                      ; restore register
  5767.             mov     bx, 10                  ; setup for itoa()
  5768.             xor     dx, dx                  ; dx = zero for the divides
  5769.             mov     di, offset compamt + 5  ; di -> lsb of size
  5770.  
  5771. comp_stat1: div     bx                      ; dx = digit for this place
  5772.             add     dx, '0'                 ; dl = ascii digit
  5773.             mov     [di], dl                ; store in output area
  5774.             xor     dl, dl                  ; dl = 0 for rest of divides
  5775.             dec     di                      ; di -> next location
  5776.  
  5777.             or      ax, ax                  ; q. any more signif digits?
  5778.             jnz     comp_stat1              ; a. yes .. continue
  5779.  
  5780.             mov     dx, di                  ; dx -> part 2 of message
  5781.             xor     ax, ax                  ; ax = no help
  5782.             call    die                     ; ..and quit, gracefully
  5783.  
  5784. comp_stats  endp
  5785.  
  5786. ; ----------------------------------------------------------------------
  5787. ;   comp_die - compiler's die routine
  5788. ;
  5789. ;   entry: dx -> specific error message
  5790. ; ----------------------------------------------------------------------
  5791.  
  5792. comp_die    proc
  5793.  
  5794.             mov     ah, 9h                  ; ah = print string
  5795.             int     21h                     ; display error message
  5796.  
  5797.             mov     di, offset line_buffer  ; di -> input line
  5798.             call    string_len              ; cx = string length
  5799.             add     di, cx                  ; di -> null character
  5800.  
  5801.             mov     si, offset crlf$        ; si -> line terminator
  5802.             mov     cx, 4                   ; cx = length of terminator
  5803.             call    string_copy             ; copy our extension
  5804.  
  5805.             mov     dx, offset line_buffer  ; dx -> input line
  5806.             xor     ax, ax                  ; ax = no help needed
  5807.             jmp     die                     ; ..then die
  5808.  
  5809. comp_die    endp
  5810.  
  5811.  
  5812.  
  5813. ; ----------------------------------------------------------------------
  5814. ;   string_comp - compare strings
  5815. ;
  5816. ;   entry: si -> string 1
  5817. ;          di -> string 2
  5818. ;    exit: carry = equal
  5819. ; ----------------------------------------------------------------------
  5820.  
  5821. string_comp proc
  5822.  
  5823.             push    ax                      ; save registers
  5824.             push    cx
  5825.             push    di
  5826.             push    si
  5827.  
  5828.             call    string_len              ; cx = length
  5829.             inc     cx                      ; cx = now includes null character
  5830.  
  5831.        repe cmpsb                           ; q. strings equal?
  5832.             jz      string_cp1              ; a. yes .. set carry
  5833.  
  5834.             clc                             ; else .. clear carry flag
  5835.             jmp     short string_cp9        ; ..and exit via common code
  5836.  
  5837. string_cp1: stc                             ; show strings equal
  5838.  
  5839. string_cp9: pop     si                      ; restore registers
  5840.             pop     di
  5841.             pop     cx
  5842.             pop     ax
  5843.             ret                             ; ..and return to caller
  5844.  
  5845. string_comp endp
  5846.  
  5847.  
  5848.  
  5849. ; ----------------------------------------------------------------------
  5850. ;   Compile buffer .. nothing past this
  5851. ; ----------------------------------------------------------------------
  5852.  
  5853. compile_buf db      ?                     ; compiled buffer
  5854. mainline    ends
  5855.             end     begin
  5856.