home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-386-Vol-2of3.iso / b / bbl-v-1.zip / BBL.ASM < prev    next >
Assembly Source File  |  1992-08-24  |  37KB  |  1,213 lines

  1.     Title    BBL -- Big Block Letters on screen
  2.     Page    58,132
  3.     .8086        ;use only 8086 for compatibility
  4.  
  5. ;*************************************************************************
  6. ;    This is an MS DOS device driver that prints in big block letters
  7. ;    on screen any characters sent to device BBL-DRVR: .
  8. ;
  9. ;    Install as 
  10. ;        device=c:\bbl.sys {mode=[0|1|2]} 
  11. ;                {font=[ATT|EGA|VGA|SSSS:OOOO]}
  12. ;    where mode 0 uses 8x8 blocks to write 3 rows x 10 cols
  13. ;           1 uses 16x16 blocks to write 1 row x 5 cols
  14. ;           2 uses 24x24 blocks to write 1 row x 3 cols
  15. ;    The default is to assume EGA/VGA as the video type and use
  16. ;    the 8x8 character set from the adapter board, so font would
  17. ;    normally not be specified.  ATT specifies to use the font
  18. ;    from the AT&T 6300 video adapter.  The SSSS:OOOO form specifies
  19. ;    that the 8x8 character-cell font is at segment SSSS, offset OOOO, 
  20. ;    (probably in the video adapter).
  21. ;
  22. ;    The basic program and data structures are in place to support 
  23. ;    a nx16 character-cell font, but the display mode logic would change
  24. ;    and the ROM pointer logic would change.  The code that displays
  25. ;    the char shouldn't require modification.
  26. ;
  27. ;*************************************************************************
  28. ;    Written by H. D. Todd, Wesleyan University, August, 1992,
  29. ;      adapted from prototypes in Digital's MS DOS Tech Doc Manual and
  30. ;      Robert Lai's "MS DOS Device Drivers".
  31. ;
  32. ;        H. David Todd
  33. ;        Computing Center
  34. ;        Wesleyan University
  35. ;        Middletown, CT  06459
  36. ;        email via Internet: hdtodd@eagle.wesleyan.edu
  37. ;
  38. ;    The author retains the copyright to BBL and documentation, but
  39. ;    you may use the software for personal, non-commercial purposes.   
  40. ;    The author makes no warranty as to the quality, performance, or 
  41. ;    fitness for a particular purpose.  You may distribute this software 
  42. ;    freely via magnetic, digital or electronic means, if you do not:
  43. ;
  44. ;    *   Charge fees or ask donations in exchange for copies of the software.
  45. ;
  46. ;    *   Distribute the software with commercial products without the
  47. ;        written permission from the author and copyright owner.
  48. ;
  49. ;    *   Remove author or copyright information from the software and
  50. ;        documentation. 
  51. ;*************************************************************************
  52. ;
  53. ;    Edit history
  54. ;    2 August    Version 1.0    Basic features in place
  55. ;                    
  56. ;*************************************************************************
  57.     page
  58. ;*************************************************************************
  59. ;    Assembler directives
  60. ;*************************************************************************
  61.  
  62. CharWidth    EQU    08h        ;width of chars in pixels
  63. CharHeight    EQU    08h        ;height of chars in pixels
  64. DispChar    EQU    219        ;solid block to construct display
  65. CharAttr    EQU    07h        ;attribute of char to display
  66. ModeMax        EQU    '2'        ;max number of virtual display modes
  67. DefMode        EQU    1        ;default display mode on startup
  68.  
  69. BELChar    EQU    07h            ;chars we use for control
  70. BSChar    EQU    08h
  71. HTChar    EQU    09h
  72. LFChar    EQU    0ah
  73. VTChar    EQU    0bh
  74. FFChar    EQU    0ch
  75. CRChar    EQU    0dh
  76. SOChar    EQU    0eh
  77. SIChar    EQU    0fh
  78.  
  79. ;*************************************************************************
  80. ;    States in the automaton that processes commands embedded in
  81. ;    the input character stream
  82. ;*************************************************************************
  83.  
  84. S$Init    EQU    0        ;State 0 ==> Initial
  85. S$VP    EQU    1        ;State 1 ==> Vertical position
  86. S$HP    EQU    2        ;State 2 ==> Horizontal position
  87. S$SM    EQU    3        ;State 3 ==> Set Mode (BBL display mode)
  88.  
  89. ;*************************************************************************
  90. ;    Classification of characters from the input stream into
  91. ;    token types, used by the automaton to process embedded commands
  92. ;*************************************************************************
  93.  
  94. TT$NOND    EQU    0        ;Token type 0 ==> non-operation, non-digit
  95. TT$Dig    EQU    1        ;Token type 1 ==> digit
  96. TT$CM    EQU    2        ;Token type 2 ==> cursor movement
  97. TT$HP    EQU    3        ;Token type 3 ==> horizontal position
  98. TT$VP    EQU    4        ;Token type 4 ==> vertical position
  99. TT$SM    EQU    5        ;Token type 5 ==> set mode
  100. NumTokTyp EQU    6
  101.  
  102. Page
  103. ;*************************************************************************
  104. ;    Structures used to describe screen virtual display modes
  105. ;    (3x10, 1x5, 1x3 displays), state transitions for the
  106. ;    automaton, and token classifications
  107. ;*************************************************************************
  108.  
  109. ModeDesc    STRUC
  110.     Mag        DB    ?    ;magnification for bit pattern
  111.     MaxRows        DB    ?    ;max rows with this mode
  112.     MaxCols        DB    ?    ;max cols with this mode
  113.     RowOff        DB    ?    ;row offset on phys screen 
  114.     ColOff        DB    ?    ;col offset on phys screen
  115. ModeDesc    ENDS
  116.  
  117. StateDesc     STRUC
  118.     ActionProc    DW    ?    ;action this token invokes in this state
  119.     NextState    DB    ?    ;next state
  120. StateDesc    ENDS
  121.  
  122. ;    The token classes are stored in the table "TC", and the
  123. ;    default of TT$NOND (non-op, non-digit) is created at assembly time.
  124. ;    We build the token table exceptions at "init" time by processing 
  125. ;    a table of exceptions, labeled with the characters (tokens), into 
  126. ;    the TC table, addressed by char value.  This struc defines
  127. ;    the structure we use to build the exceptions table.
  128.  
  129. TokDef STRUC
  130.     char    DB    ?    ;character being classified ("typed")
  131.     ctype    DB    ?    ;type of that char
  132. TokDef ENDS
  133.  
  134. Page
  135. ;*************************************************************************
  136. ;    Command request header structures used by DOS to communicate with
  137. ;    device drivers --- standard definitions.
  138. ;*************************************************************************
  139.  
  140. rh    STRUC                ;request header
  141. rh_len       DB    ?            ;length of command packet
  142. rh_unit       DB    ?            ;unit code (block devices only)
  143. rh_cmd       DB    ?            ;device driver command
  144. rh_status  DW    ?            ;status returned by DD
  145. rh_res       DQ    ?            ;reserved
  146. rh    ENDS
  147.  
  148. c0    STRUC                ;Init (command 0)
  149. c0_h       DB    SIZE rh DUP (?)        ;common header
  150. c0_nunits  DB    ?            ;number of units
  151. c0_brk_ofs DW    ?            ;offset addr of break (end of DD)
  152. c0_brk_seg DW    ?            ;seg addr of break (end of DD)
  153. c0_bpb       DD    ?            ;offset & seg ptr to BPB array
  154. c0_drv       DB    ?            ;first avail drive (DOS 3+, block only)
  155. c0    ENDS
  156.  
  157. c1    STRUC                ;Media-check (command 1)
  158. c1_h       DB    SIZE rh DUP (?)        ;common header
  159. c1_media   DB    ?            ;media descriptor from DPB
  160. c1_md_stat DB    ?            ;media status returned by DD
  161. c1    ENDS
  162.  
  163. c2    STRUC                ;Get-BPB (command 2)
  164. c2_h       DB    SIZE rh DUP (?)        ;common header
  165. c2_media   DB    ?            ;media descriptor from DPB
  166. c2_buf_ofs DW    ?            ;offset addr of data buffer
  167. c2_buf_seg DW    ?            ;seg addr of data buffer
  168. c2_pbpo       DW    ?            ;offset addr of ptr to BPB
  169. c2_pbps       DW    ?            ;seg addr of ptr to BPB
  170. c2    ENDS
  171.  
  172. c4    STRUC                ;IOCTL input, Input, Output,
  173.                     ; Output with verify, IOCTL Output
  174.                     ;(commands 3, 4, 8, 9, and 12)
  175. c4_h       DB    SIZE rh DUP (?)        ;common header
  176. c4_media   DB    ?            ;media descriptor from DBP
  177. c4_buf_ofs DW     ?            ;offset addr of data buffer
  178. c4_buf_seg DW    ?            ;seg addr of data buffer
  179. c4_count   DW    ?            ;byte/sector(block) count
  180. c4_start   DW    ?            ;starting sector # (block device only)
  181.                     ; ignored on char devices
  182. c4    ENDS
  183.  
  184. c5    STRUC                ;Non-destructive read -- no wait
  185.                     ;(command 5)
  186. c5_h       DB    SIZE rh DUP (?)        ;common header
  187. c5_byte       DB    ?            ;byte read from device
  188. c5    ENDS
  189.  
  190. c15    STRUC                ;Removable (command 15)
  191. c15_h       DB    SIZE rh DUP (?)        ;common header
  192. c15_len    DB    ?            ;length of packet
  193. c15_unit   DB    ?            ;unit code (block device only)
  194. c15_cmd       DB    ?            ;device driver command
  195. c15_res    DQ    ?            ;reserved
  196. c15    ENDS
  197.  
  198. Page
  199. ;*************************************************************************
  200. ;    Flags used in command request packet, device header
  201. ;*************************************************************************
  202.  
  203. ;    Bit value assigments for device command packet status word
  204.  
  205.     st$err=8000H            ;error flag
  206.     st$don=80H            ;done bit
  207.     st$bus=100H            ;busy bit
  208.  
  209.     st$wp =0            ;write protect error
  210.     st$uu =1            ;unknown unit
  211.     st$dnr=2            ;drive not ready
  212.     st$uc =3            ;unknown command
  213.     st$crc=4            ;CRC error
  214.     st$str=5            ;bad drive-request structure length
  215.     st$se =6            ;seek error
  216.     st$um =7            ;unknown media
  217.     st$snf=8            ;sector not found
  218.     st$pop=9            ;printer out of paper
  219.     st$wf =0AH            ;write fault
  220.     st$rf =0BH            ;read fault
  221.     st$gf =0CH            ;general fault
  222.     st$idc=0FH            ;invalid disk change
  223.  
  224. ;    Attribute bits in device header word
  225.  
  226.     at$sid=1 SHL 0            ;standard input device
  227.     at$sod=1 SHL 1            ;standard output device
  228.     at$nul=1 SHL 2            ;null device
  229.     at$clk=1 SHL 3            ;clock
  230.     at$spl=1 SHL 4            ;special device
  231.     at$ocr=1 SHL 11            ;device supports open/close/remove
  232.     at$nib=1 SHL 13            ;non-IBM format
  233.     at$ctl=1 SHL 14            ;supports IOCTL
  234.     at$chr=1 SHL 15            ;char device (0 ==> block device)
  235.  
  236. Page
  237. ;*************************************************************************
  238. ;    Start code segment.  Begins with the device-driver data structure
  239. ;    used to communicate with DOS.
  240. ;*************************************************************************
  241. cseg    SEGMENT    PARA    PUBLIC    'CODE'
  242. BBLProc    PROC    FAR
  243.     ASSUME    CS:cseg, ES:cseg, DS:cseg
  244.  
  245. ;*************************************************************************
  246. ;    Device header
  247. ;*************************************************************************
  248.  
  249. BBL:
  250. next_dev    DD    -1        ;no device after this
  251. attrib        DW    at$chr        ;char device
  252. strategy    DW    BBL_strategy    ;address of strategy routine
  253. interrupt    DW    BBL_interrupt    ;address of interrupt routine
  254. BBL_name    DB    'BBL-DRVR'    ;for chr device, must be 8 chrs
  255.  
  256. Page
  257. ;*************************************************************************
  258. ;    Permanent storage used by BBL during operation
  259. ;*************************************************************************
  260.  
  261. rh_adr        DD    ?        ;offset & seg of request header
  262.  
  263. CurMode    db    DefMode            ;default mode on startup
  264. CurXY    DW    0            ;row,,col of cur virtual position
  265. CurPhys    DW    0            ;row,,col of cur phys position
  266. CurChar    db    0            ;space for char being written
  267. CurPage    db    0            ;current video page on entry
  268. CurState db    0            ;current state of input char processing
  269.  
  270. Mode    ModeDesc    3 DUP(<1,3,10,0,0>,<2,1,5,4,0>,<3,1,3,0,0>)
  271.                     ;describe layout for each of
  272.                     ; the three display sizes
  273. BitMask    dw    0
  274. ft_ptr    dd    0
  275.  
  276. ;    The following table describes the actions and next-states
  277. ;    that result when a token is given to BBL.  There are four 
  278. ;    states (rows) and six token types (columns) in the table 
  279. ;    (in version 1).  The table is addressed as a matrix ... 
  280. ;    State[Current_State,Type_of_Incoming_Token], so the number of
  281. ;    token types is needed to compute the address for a given
  282. ;    (state, toktype) entry.
  283. ;    [future] To add commands, extend the States table in number of
  284. ;        cols and number of rows to describe transitions based on 
  285. ;        current state and input token type
  286.  
  287. States    StateDesc    <ShowChar,S$Init>,<ShowChar,S$Init>,<Move,S$Init> ;state 0
  288.     StateDesc        <Noop,S$HP>,<Noop,S$VP>,<Noop,S$SM>    
  289.     StateDesc    <Beep,S$Init>,<VertPos,S$Init>,<Beep,S$Init>    ;state 1
  290.     StateDesc        <Beep,S$Init>,<Beep,S$Init>,<Beep,S$Init>
  291.     StateDesc    <Beep,S$Init>,<HorPos,S$Init>,<Beep,S$Init>    ;state 2
  292.     StateDesc        <Beep,S$Init>,<Beep,S$Init>,<Beep,S$Init>
  293.     StateDesc    <Beep,S$Init>,<SetMode,S$Init>,<Beep,S$Init>    ;state 3
  294.     StateDesc        <Beep,S$Init>,<Beep,S$Init>,<Beep,S$Init>
  295.  
  296. ;    The token class table with default values
  297. ;    Bytes contain token type of chars <even,,odd>, with token type
  298. ;    stored as a 4-bit nibble.  Updated during initialization with
  299. ;    exceptions to the default.
  300.  
  301. TC    db    128 dup(0)    ; <TT$NOND<<4 + TT$NOND> ))
  302.  
  303. Page
  304. ;*************************************************************************
  305. ;    Strategy routine
  306. ;*************************************************************************
  307.  
  308. StratP    PROC    FAR
  309. BBL_strategy:
  310.     MOV    WORD PTR CS:[rh_adr],BX        ;save offset of addr of req
  311.     MOV    WORD PTR CS:[rh_adr+2],ES    ;and seg of addr
  312.     RET                    ;that's all
  313. StratP    ENDP
  314.  
  315. ;*************************************************************************
  316. ;    Interrupt routine
  317. ;*************************************************************************
  318.  
  319. BBL_interrupt:
  320.     push    ds            ;save regs
  321.     push    es
  322.     push    ax
  323.     push    bx
  324.     push    cx
  325.     push    dx
  326.     push    di
  327.     push    si
  328.  
  329.     push    cs            ;set DS to point to this seg
  330.     pop    ds
  331.     les    bx,cs:rh_adr        ;restore ES:BX saved by strategy
  332.     mov    es:[bx].rh_status,0    ;zero returned status
  333.     xor    ax,ax            ;zero ax for calculation
  334.     mov    al,es:[bx].rh_cmd    ;get command request #
  335.     cmp    al,cmd_tbl_len        ;is it in range?
  336.      jg    cmd_err            ;no -- say so
  337.     shl    ax,1            ;cmd is in table, compute addr
  338.     lea    di,cmd_tbl        ; into table of the routine
  339.     add    di,ax            ; to handle this command
  340.     jmp    word ptr[di]        ;and go to it
  341.  
  342. cmd_tbl    label    word
  343.     DW    BBL_init        ;init - 0
  344.     DW    BBL_mc            ;media check - 1
  345.     DW    BBL_gbpb        ;get BPB - 2
  346.     DW    BBL_ctli        ;IOCTL input - 3
  347.     DW    BBL_in            ;Input - 4
  348.     DW    BBL_ndi            ;non-destructive input - 5
  349.     DW    BBL_ins            ;input status - 6
  350.     DW    BBL_inf            ;input flush - 7
  351.     DW    BBL_out            ;output - 8
  352.     DW    BBL_outv        ;output & verify - 9
  353.     DW    BBL_outs        ;output status - 10
  354.     DW    BBL_outf        ;output flush - 11
  355.     DW    BBL_ctlo        ;IOCTL output - 12
  356.     DW    BBL_opn            ;open - 13
  357.     DW    BBL_cls            ;close - 14
  358.     DW    BBL_rmv            ;removable media - 15
  359.     DW    BBL_otb            ;output til busy - 16
  360. cmd_tbl_len = ($-cmd_tbl) SHR 1
  361.  
  362. Page    
  363. ;*************************************************************************
  364. ;    Local procedures for dev driver call-return handling
  365. ;*************************************************************************
  366. cmd_err:
  367. unk:    or    es:[bx].rh_status,(st$err OR st$uc)    ;set error cond
  368.     jmp    done
  369.  
  370. busy:    or    es:[bx].rh_status,st$bus    ;set busy flag
  371. done:    or    es:[bx].rh_status,st$don    ;set done flag
  372.     pop    si                ;restore regs
  373.     pop    di
  374.     pop    dx
  375.     pop    cx
  376.     pop    bx
  377.     pop    ax
  378.     pop    es
  379.     pop    ds
  380.     ret                ;and return
  381.  
  382.     page
  383. ;*************************************************************************
  384. ;    Command processing for individual DOS I/O requests
  385. ;*************************************************************************
  386.  
  387. BBL_init:                ;init - 0
  388.     call    initial            ;set up, process cmd line, & inform
  389.     lea    ax,WORD PTR once_only    ;let MS DOS have anything after
  390.     mov    es:[bx].c0_brk_ofs,ax    ; the location called "once_only"
  391.     mov    es:[bx].c0_brk_seg,cs
  392.     jmp    done    
  393.  
  394. BBL_mc:                    ;media check - 1
  395.     jmp    unk
  396.  
  397. BBL_gbpb:                ;get BPB - 2
  398.     jmp    unk
  399.  
  400. BBL_ctli:                ;IOCTL input - 3
  401.     jmp    unk
  402.  
  403. BBL_in:                    ;Input - 4
  404.     jmp    done
  405.  
  406. BBL_ndi:                ;non-destructive input - 5
  407.     jmp    done
  408.  
  409. BBL_ins:                ;input status - 6
  410.     jmp    unk
  411.  
  412. BBL_inf:                ;input flush - 7
  413.     jmp    done
  414.  
  415. BBL_out:                ;output - 8
  416.     mov    cx,es:[bx].c4_count    ;get output char count
  417.     mov    si,es:[bx].c4_buf_ofs    ;get offset to DOS buffer
  418.     mov    ax,es:[bx].c4_buf_seg    ;get seg to DOS buffer
  419.     mov    es,ax            ; into es
  420.  
  421. Lup:    mov    dl,es:[si]        ;get next char
  422.     inc    si            ;  and prepare for following
  423.     push    si            ;save the things we care about
  424.     push    es
  425.     push    cx
  426.     call    ProcessChar        ;process the char
  427.     pop    cx            ;restore things we need
  428.     pop    es
  429.     pop    si
  430.     loop    Lup            ;and go back for next char in buffer
  431.  
  432.     les    bx,rh_adr        ;restore es:bx to req header
  433.     jmp    Done
  434.  
  435.  
  436. BBL_outv:                ;output & verify - 9
  437.     jmp    BBL_out
  438.  
  439. BBL_outs:                ;output status - 10
  440.     jmp    done
  441.  
  442. BBL_outf:                ;output flush - 11
  443.     jmp    done
  444.  
  445. BBL_ctlo:                ;IOCTL output - 12
  446.     jmp    done
  447.  
  448. BBL_opn:                ;open - 13
  449.     jmp    done
  450.  
  451. BBL_cls:                ;close - 14
  452.     jmp    done
  453.  
  454. BBL_rmv:                ;removable media - 15
  455.     jmp    done
  456.  
  457. BBL_otb:                ;output til busy - 16
  458.     jmp    done
  459.  
  460. Page
  461. ;*************************************************************************
  462. ;    Local procedures
  463. ;*************************************************************************
  464.  
  465. ProcessChar PROC NEAR
  466. ;*************************************************************************
  467. ;    Process the character in dl as command or to display
  468. ;    Preserve nothing but leave char in dl 
  469. ;*************************************************************************
  470.     mov    al,CurMode        ; for this mode
  471.     mov    bl,SIZE ModeDesc    ;size of mode record
  472.     mul    bl            
  473.     lea    si,Mode
  474.     add    si,ax            ;si now points to the right block
  475.  
  476.     mov    CurChar,dl        ;keep this char
  477.     xor    bh,bh            ;clear high byte for addressing
  478.     mov    bl,dl            ;get char & compute token-class
  479.     shr    bl,1            ; table address
  480.     mov    ch,TC[bx]        ;get the byte containing the class
  481.      jc    TCxtr            ;odd-valued chars are in right nibble
  482.     mov    cl,4
  483.     shr    ch,cl
  484. TCxtr:    and    ch,0fh            ;mask out that nibble
  485.                     ;ch contains the token class of this char
  486.     xor    ax,ax            ;now compute the addr of the state-table
  487.     mov    al,CurState        ; entry for the current state
  488.     mov    bl,NumTokTyp        ; matrix address is
  489.     mul    bl            ; States + (CurState*NumTokTypes
  490.     add    al,ch            ;            + TokenType) 
  491.     mov    bl,SIZE StateDesc
  492.     mul    bl            ;  [adjusted for size of entries]
  493.     mov    bx,ax
  494.     lea    bx,States[bx]
  495.     mov    al,[bx].NextState    ;get next state from this transition
  496.     mov    CurState,al
  497.     mov    bx,[bx].ActionProc
  498.     jmp    bx            ;and act on this token/state
  499.                     ; dl still contains input char
  500.  
  501. Beep:    mov    ax,0e07h        ;write a bell in teletype mode
  502.     xor    bx,bx
  503.     int    10h
  504.     ret
  505.  
  506. Noop:    ret
  507.  
  508. VertPos: sub    dl,'0'            ;convert char in dl to integer in dl
  509.     mov    cl,[si].MaxRows    
  510.     cmp    dl,cl            ;too large for this mode?
  511.      jle    VPSet            ; no ..
  512.     xchg    dl,cl            ; yes ... set to max
  513. VPSet:    mov    BYTE PTR CurXY+1,dl    ;store into row-byte of position word
  514.     ret
  515.  
  516. HorPos:    sub    dl,'0'            ;convert char in dl to integer in dl
  517.     mov    cl,[si].MaxCols
  518.     cmp    dl,cl            ;too large for this mode?
  519.      jle    HPSet            ; no ...
  520.     xchg    dl,cl            ; yes ... set to max
  521. HPSet:    mov    BYTE PTR CurXY,dl    ;store into col-byte of position word
  522.     ret
  523.  
  524. SetMode: sub    dl,'0'            ;convert char in dl to integer in dl
  525.     mov    CurMode,dl        ;store into current mode byte
  526.     call    FF            ;clear screen & reset CurXY
  527.     ret
  528.  
  529. ProcessChar ENDP
  530.  
  531. Page
  532. Move    PROC    NEAR
  533. ;*************************************************************************
  534. ; Assumptions:
  535. ; On entry, dl contains character to display
  536. ; si points to struc that describes the display parameters in this mode
  537. ; On exit, no regs will have been preserved
  538. ;*************************************************************************
  539.  
  540.     cmp    dl,CRChar        ;is CurChar a CR?
  541.      je    CR            ; yes
  542.     cmp    dl,LFChar        ;no, is it a LF?
  543.      je    LF            ; yes
  544.     cmp    dl,BSChar        ;no, is it a BackSpace?
  545.      je    BS            ; yes
  546.     cmp    dl,FFChar        ;no, is it a FF?
  547.      jne    Beep            ; no -- beep & ignore
  548.  
  549.                     ;yes, do screen clear
  550. FF:    mov    ah,0fh            ;get current mode
  551.     int    10h            ; mode left in al
  552.     mov    ah,00h            ;where we use it now
  553.     int    10h            ;reset in same mode clears
  554.     xor    ax,ax            ;reset our virtual pointer
  555.     mov    CurXY,ax
  556.     ret
  557.  
  558. CR:    mov    ax,CurXY        ;reset pointer to col 0
  559.     xor    al,al
  560.     mov    CurXY,ax
  561.     ret
  562.  
  563. BS:    mov    ax,CurXY        ;decrement virtual col position by 1
  564.     dec    al
  565.     mov    CurXY,ax
  566.     ret
  567.  
  568. LF:    mov    dx,CurXY        ;inc virtual row if we can
  569.     inc    dh
  570.     cmp    dh,[si].MaxRows        ;can we?
  571.      jl    LFDone            ; yes! Done
  572.     call    ScrollUp        ;no -- scroll up screen
  573.     ret                ;note that we haven't changed CurXY
  574. LFDone:    mov    CurXY,dx        ;but we did here
  575.     ret
  576. ScrollUp:
  577.     mov    ch,[si].RowOff        ;rows down to top of scroll region
  578.     mov    cl,[si].ColOff        ;cols to left side of scroll region
  579.  
  580.     mov    al,[si].MaxRows        ;compute bottom addr of scroll region
  581.     xor    ah,ah
  582.     mov    bl,CharHeight
  583.     mul    bl
  584.     mov    bl,[si].mag
  585.     mul    bl
  586.     mov    dh,al
  587.     add    dh,ch            ;dh now has addr of last row of scroll reg
  588.  
  589.     mov    al,[si].MaxCols        ;compute right col of scroll reg
  590.     xor    ah,ah
  591.     mov    bl,CharWIdth
  592.     mul    bl
  593.     mov    bl,[si].mag
  594.     mul    bl
  595.     mov    dl,al
  596.     add    dl,cl            ;dl now has addr of las col of scroll reg
  597.  
  598.     mov    al,CharHeight        ;finally, compute scroll distance
  599.     xor    ah,ah
  600.     mov    bl,[si].Mag
  601.     mul    bl            ;al now has # rows to scroll
  602.     mov    bh,CharAttr
  603.     mov    ah,06h            ;function 6 scrolls up
  604.     int    10h            ;scroll that region
  605.     ret
  606. Move    ENDP
  607.  
  608. Page
  609. ShowChar PROC    NEAR
  610. ;*************************************************************************
  611. ; Assumptions:
  612. ; On entry, dl contains character to display
  613. ; si points to struc that describes the display parameters in this mode
  614. ; On exit, no regs will have been preserved
  615. ;*************************************************************************
  616.     mov    dx,CurXY        ;see if there's room on this line
  617.     cmp    dl,[si].MaxCols
  618.      jl    Proceed            ;yes, go on with it
  619.     call    CR            ;no, move back
  620.     call    LF            ; and down
  621.  
  622. Proceed:
  623.     mov    ah,0fh            ;get current video page
  624.     int    10h
  625.     xor    bl,bl            ;[hdt] zero for now 
  626.     mov    CurPage,bl        ;and save for future use
  627.  
  628.     mov    al,CurChar        ;now get pointer to our char bit pattern
  629.     mov    bl,CharWidth
  630.     mul    bl
  631.     les    bx,ft_ptr
  632.     add    bx,ax
  633.     mov    di,bx            ;es:di points to the pattern
  634.  
  635.      mov    dx,CurXY        ;compute phys row/col starting position
  636.     mov    al,dh            ;first, row position
  637.     mov    bl,CharHeight
  638.     mul    bl
  639.     mov    bl,[si].Mag
  640.     mul    bl
  641.     add    al,[si].RowOff
  642.     mov    dh,al            ;store back in our active pointer
  643.     mov    al,dl            ;now compute col position
  644.     mov    bl,CharWidth
  645.     mul    bl
  646.     mov    bl,[si].Mag
  647.     mul    bl
  648.     add    al,[si].ColOff
  649.     mov    dl,al            ;store col back into pointer
  650.  
  651.     mov    cx,CharHeight        ;set up counter to count down rows
  652.                     ;of char's pixel pattern
  653.  
  654. ; assumptions in this section:
  655. ; si points to descriptor block for this mode
  656. ; es:di points to next row of pixels for this character
  657. ; dx contains row,,col (dh,,dl) of PHYSICAL location to write next on screen
  658.  
  659. RowLoop:                ;loop over all the rows of the pattern
  660.     push    cx            ;save row counter
  661.                     ;get a word from the pattern ...
  662.     mov    bp,word ptr es:[di]    ; even if we use only 8 bits
  663.     add    di,CharWidth/8        ;and bump the pointer appropriately
  664.  
  665.     xor    cx,cx
  666.     mov    cl,si.[mag]        ;display each row "mag" times
  667.                     ;for magnification effect
  668. MagLoop:
  669.     push    cx            ;save magnification count
  670.                     ;# of screen rows written with this
  671.                     ; character pixel row
  672.     push    dx            ;save phys screen position
  673.  
  674.     mov    bx,0080h        ;starting mask for copying this row
  675.     mov    BitMask,bx
  676.  
  677.     mov    cx,CharWidth        ;set up counter to copy pixels
  678.  
  679. ColLoop:
  680.     push    cx            ;save column (pixel) counter
  681.  
  682.     mov    bh,CurPage        ;set position on page
  683.     mov    ah,02h            ; dx already points to position
  684.     int    10h
  685.  
  686.     mov    bx,BitMask        ;get the mask & check the char
  687.     test    bp,bx            ;now is the pixel bit on?
  688.      jnz    LoadBlock        ; yes
  689.     mov    al,' '            ;no ... write a blank
  690.     jmp    DispIt            ; go do it
  691. LoadBlock:
  692.     mov    al,DispChar        ;write the block char
  693. DispIt:    
  694.     ror    bx,1            ;ready to mask the next pixel
  695.     mov    BitMask,bx
  696.  
  697.                     ;write out the designated disp char
  698.     mov    ah,09h            ; al already has char to write
  699.     mov    bh,CurPage        ; to this video page
  700.     mov    bl,CharAttr        ; with appropriate video attribute
  701.     xor    cx,cx
  702.     mov    cl,[si].Mag        ; with appropriate magnification for
  703.     int    10h            ;  this BL mode
  704.  
  705.     add    dl,[si].Mag        ;update col position
  706.     pop    cx            ;retrieve our pixel-width counter
  707.     loop    ColLoop            ;and process next pixel, if any
  708.  
  709.     pop    dx            ;done with that row.  Restore phys
  710.     inc    dh            ; postion and update phys row
  711.     pop    cx            ;and repeat "mag" times
  712.     loop    MagLoop
  713.  
  714.     pop    cx            ;retrieve counter of # of rows of pattern
  715.     loop    RowLoop            ;and process next row of pattern
  716.     mov    cx,CurXY        ;note change in virtual col
  717.     inc    cl
  718.     mov    CurXY,cx
  719.     ret
  720.  
  721. ShowChar ENDP
  722.  
  723. page
  724. ;*************************************************************************
  725. ;    Disposable code -- removed after initialization call from DOS
  726. ;*************************************************************************
  727.  
  728. once_only:            ;everything after this point is given 
  729.                 ; back to DOS upon exit from initialization
  730.  
  731. ;*************************************************************************
  732. ;    First, the local storage
  733. ;*************************************************************************
  734. ATTMsg    db    'BBL-DRVR: ATT font ptr loaded',CRChar, LFChar,'$'
  735. VEGAMsg    db    'BBL-DRVR: V/EGA font ptr loaded',CRChar, LFChar,'$'
  736. HexMsg    db    'BBL-DRVR: User-defined hex font ptr loaded',CRChar, LFChar,'$'
  737. ModMsg    db    'BBL-DRVR mode set to $'
  738. FontStr    db    'FONT'
  739. ModeStr    db    'MODE'
  740. ATTStr    db    'ATT'
  741. EGAStr    db    'EGA'
  742. VGAStr    db    'VGA'
  743. CmdErrStr db    'BBL-DRVR: Unrecognized switch: $'
  744. ModErrStr db    'BBL-DRVR: Invalid Mode value (must be 0..2): $'
  745. HexErrStr db    'BBL-DRVR: Invalid hexidecimal string: $'
  746. BBLMsg    db    'Loaded BBL-DRVR device driver',CRChar,LFChar,'$'
  747. CRLF    db    CRChar,LFChar,'$'
  748. HexStart dw    0
  749. FontNotSet db    1        ;not set by default
  750.  
  751. ;*************************************************************************
  752. ;    Next define the Non-Default Tokens: the token-class exceptions
  753. ;    These are processed at assembly time and so can be thrown away 
  754. ;    after init -- hence are in "once-only"    section
  755. ;    [future] This is where you add token types for new one-char 
  756. ;    command introducers.
  757. ;*************************************************************************
  758. NDT    TokDef    <FFChar,TT$CM>
  759.     irp    x,<'0','1','2','3','4','5','6','7','8','9'>
  760.     TokDef    <x,TT$Dig>        
  761.     endm
  762.     TokDef    <BSCHar,TT$CM>
  763.     TokDef    <LFChar,TT$CM>
  764.     TokDef    <CRChar,TT$CM>
  765.     TokDef    <HTChar,TT$HP>
  766.     TokDef    <VTChar,TT$VP>
  767.     TokDef    <SOChar,TT$SM>
  768. NumTokDefs = ($-NDT)/SIZE TokDef
  769.  
  770. Page
  771. Initial    PROC    NEAR
  772. ;*************************************************************************
  773. ;    The initialization procedure itself
  774. ;*************************************************************************
  775.  
  776.     call    FillTT        ;init token table with non-defaults
  777.     call    ProcessCmd    ;process command-line switches
  778.     mov    al,FontNotSet    ;has the video type been set?
  779.     test    al,0ffh        
  780.      je    InitDone    ; yes
  781.     call    SetEGA        ;no -- assume V/EGA default video
  782. InitDone: lea    dx,BBLmsg    ;say we're here
  783.     mov    ah,9H
  784.     int    21H
  785.     les    bx,rh_adr    ;point es:bx to req header for return
  786.     ret
  787. Initial    ENDP
  788.  
  789. ProcessCmd PROC    NEAR
  790. ;*************************************************************************
  791. ;    This procedure processes the input command line when the
  792. ;    device driver is loaded.
  793. ;*************************************************************************
  794.  
  795.     les    bx,rh_adr    ;point es:bx to req header
  796.     les    si,es:[bx].c0_bpb ;get ptr to command-line string
  797.  
  798. CmdLup:    call    SkipSwitch    ;skip everthing to & including '/'
  799.      jc    CmdDone        ; hit end of line ... we're done
  800.     call    GetToken    ;get the next token after the /
  801.      jc    CmdDone        ;wasn't one ... we're done
  802.  
  803.                 ;es:si points to the start of the token
  804.                 ;es:di points to the first char after it
  805.     lea    dx,FontStr    ;compare with "FONT"
  806.     call    ChkTok
  807.      jne    NotFont        ;skip if not "FONT"
  808.     mov    si,di        ;update over recognized keyword
  809.     call    Font        ;yes, got "FONT" ... do it
  810.     jmp    CmdLup        ;and return for more
  811.  
  812. NotFont: lea    dx,ModeStr    ;check "MODE"
  813.     call    ChkTok
  814.      jne    NotMode        ;skip if not "MODE"
  815.     mov    si,di        ;update over recognized keyword
  816.     call    ProcMode    ;yes, got "MODE"
  817.     jmp    CmdLup        ;and return for more
  818.  
  819. NotMode:
  820. ;insert others here with the pattern
  821. ;    lea    dx,CMDStr    ;check "CMD"
  822. ;    call    ChkTok
  823. ;     jne    NotCMD        ;skip if not "CMD"
  824. ;    call    CMD        ;process "CMD"
  825. ;    jmp    CmdLup        ;and return for more
  826.  
  827. NotCmd:    
  828.     mov    ah,09h        ;if none of the above, issue error
  829.     lea    dx,CmdErrStr    
  830.     int    21h
  831.     call    PrtStr        ;print the offending string & advance si
  832.     mov    ah,09h        ;now the suffix
  833.     lea    dx,CRLF
  834.     int    21h
  835.     jmp    CmdLup
  836. CmdDone: ret
  837.  
  838. ProcessCmd ENDP
  839.  
  840. SkipSwitch PROC    NEAR
  841. SSLoop:    cmp    BYTE PTR es:[si],'/' ;got a switch?
  842.      je    GotS        ;yes
  843.     cmp    BYTE PTR es:[si],0ah ;end of line?
  844.      je    EndLine        ;yes
  845.     inc    si        ;none of the above ... skip it
  846.      jmp    SSLoop
  847.  
  848. Gots:    inc    si        ;skip that /
  849.     clc            ;clear the flag
  850.     ret            ;done
  851. EndLine: stc            ;set the flag to alert of eol
  852.     ret
  853. SkipSwitch ENDP
  854.  
  855. GetToken PROC    NEAR
  856.     call    SkipBlanks
  857.     mov    di,si        ;advance es:di over the token
  858. GetLup:    mov    al,BYTE PTR es:[di] ;examine next char
  859.     call    MakeUpper    ;make sure it's upper case
  860.     mov    BYTE PTR es:[di],al
  861. NotLow:    cmp    al,' '        ;blank, tab, '=', '/' or eoln is a delimiter
  862.      je    GetDone
  863.     cmp    al,LFChar
  864.      je    GetDone
  865.     cmp    al,HTChar
  866.      je    GetDone
  867.     cmp    al,'/'
  868.      je    GetDone
  869.     cmp    al,'='
  870.      je    GetDone
  871.     inc    di        ;it was none of them ... part of token
  872.     jmp    GetLup
  873. GetDone: ret
  874. GetToken ENDP
  875.  
  876. SkipBlanks PROC    NEAR
  877. ;*************************************************************************
  878. ;    Skip whitespace in string es:si return advanced si pointer
  879. ;    On return,
  880. ;        si advanced
  881. ;        carry set ==> eoln (end of string) encountered
  882. ;        carry clear ==> found non-space
  883. ;*************************************************************************
  884. SBLup:    cmp    BYTE PTR es:[si],' '    ;spaces or tabs and eoln are "blanks"
  885.      je    SBInc
  886.     cmp    BYTE PTR es:[si],HTChar
  887.      je    SBInc
  888.     cmp    BYTE PTR es:[si],LFChar
  889.      je    SBeoln        ;if eoln, say so
  890.     clc            ;otherwise, clear carry (not at eoln)
  891.     ret            ; and we've done our job
  892. SBeoln:    stc            ;got an eoln ... flag it
  893.     ret            ;and ... we're done
  894. SBInc:    inc    si
  895.     jmp    SBLup        ;go look at next one
  896.  
  897. SkipBlanks ENDP
  898.  
  899. Page
  900. Font    PROC    NEAR
  901. ;*************************************************************************
  902. ;    This procedure processes the /FONT= option on the command line
  903. ;*************************************************************************
  904.  
  905.     call    SkipEqual    ;skip the equal sign
  906.     call    GetToken    ;get the option value
  907.     lea    dx,ATTStr    ;is it "ATT"?
  908.     call    ChkTok
  909.      jne    NotATT
  910.     call    SetATT        ;yes
  911.     mov    si,di        ;skip that token
  912.     ret
  913. NotATT:    lea    dx,EGAStr    ;is it "EGA"?
  914.     call    ChkTok
  915.      jne    NotEGA
  916.     call    SetEGA        ;yes
  917.     mov    si,di        ;skip that token
  918.     ret
  919. NotEGA:    lea    dx,VGAStr    ;is it "VGA"?
  920.     call    ChkTok
  921.      jne    NotVGA
  922.     call    SetEGA        ;yes
  923.     mov    si,di        ;skip that token
  924.     ret
  925.                 ;if we get here, must be hex addr (we hope)
  926. NotVGA:    mov    HexStart,si    ;save ptr to start of hex string for error msg
  927.     call    GetHex
  928.      jc    HexErr
  929.     mov    WORD PTR ft_ptr+2,dx    ;save seg of font table
  930.     cmp    BYTE PTR es:[si],':'    ;need ':' as a separator
  931.      jc    HexErr        ;oops
  932.     inc    si        ;ok, go on
  933.     call    GetHex
  934.      jc    HexErr
  935.     mov    WORD PTR ft_ptr,dx    ;save offset of font table
  936.     xor    dl,dl        ;signal that we've set mode
  937.     mov    FontNotSet,dl
  938.     lea    dx,HexMsg    ;say what we've done
  939.     mov    ah,09h
  940.     int    21h
  941.     ret            ;return from successful font set
  942.  
  943. HexErr:    mov    ah,09h        ;prints out error message for invalid
  944.                 ;hex string started at es:si and ending
  945.                 ;the char before es:di
  946.                 ;advances es:si past that string
  947.     lea    dx,HexErrStr    ;print the error msg
  948.     int    21h
  949.     call    PrtStr        ;print the offending string
  950.     mov    ah,09h
  951.     lea    dx,CRLF        ;and finish it off
  952.     int    21h
  953.     mov    si,di        ;make sure we advance past it
  954.     ret            ;and we're done
  955.  
  956. Font    ENDP
  957.  
  958. GetHex    PROC    NEAR
  959. ;*************************************************************************
  960. ;  Converts a 4-digit hex string beginning at es:si into a binary hex value.
  961. ;  Returns binary value in dx
  962. ;    If no error, returns es:si advanced over hex string and carry bit clear
  963. ;    If the string was invalid, es:si not advanced and carry is set
  964. ;  Saves other regs
  965. ;*************************************************************************
  966.  
  967.     push    ax
  968.     push    cx
  969.     push    si
  970.     mov    cx,4        ;we always do 4 digits!
  971.     xor    dx,dx
  972.  
  973. GHLup:    xor    ax,ax
  974.     mov    al,BYTE PTR es:[si]    ;get the next char
  975.     inc    si        ;and record that
  976.     cmp    al,'0'        ;is it a digit?
  977.      jl    GHErr        ; no
  978.     cmp    al,'9'        ;maybe
  979.      jg    GHAlpha        ; well, not 0..9
  980.     sub    al,'0'        ;yes, valid digit
  981. GHInsert:            ;ok, insert it into the resulting word
  982.     shl    dx,1
  983.     shl    dx,1
  984.     shl    dx,1
  985.     shl    dx,1
  986.     or    dx,ax
  987.     loop    GHLup        ;and do it again
  988.     clc            ;all done - flag no error
  989.     pop    cx        ;throw away saved si -- leave string
  990.                 ;pointer advanced
  991.     pop    cx        ;restore real cx
  992.     pop    ax
  993.     ret
  994. GHAlpha: call    MakeUpper    ;raise if alpha
  995.     cmp    al,'A'        ;is it in hex range
  996.      jl    GHErr        ;no
  997.     cmp    al,'F'
  998.      jg    GHErr
  999.     sub    al,'A'        ;yes -- convert to binary value
  1000.     add    al,0ah
  1001.     jmp    GHInsert    ;and insert it into the resulting word
  1002.  
  1003. GHerr:    stc            ;oops ... some character offended ... say so
  1004.     pop    si        ;restore original si
  1005.     pop    cx
  1006.     pop    ax
  1007.     ret
  1008.  
  1009. GetHex    ENDP
  1010.  
  1011.  
  1012. SkipEqual PROC    NEAR
  1013. ;*************************************************************************
  1014. ;    Advances es:si to the first char past next '=' on line
  1015. ;    Sets carry if eoln found during scan
  1016. ;    Clears carry if valid char follows '='
  1017. ;*************************************************************************
  1018. SELup:    cmp    BYTE PTR es:[si],'='    ;found it yet?
  1019.      je    FndEqual        ;yes
  1020.     cmp    BYTE PTR es:[si],LFChar    ;no ... at end of line?
  1021.      je    SEeoln        ;if eoln, say so
  1022.     inc    si        ;otherwise, go look at next char
  1023.     jmp    SELup
  1024. SEeoln:    stc            ;got an eoln ... flag it
  1025.     ret            ;and we're done
  1026. FndEqual:            ;found an =
  1027.     inc    si        ;skip it
  1028.     cmp    BYTE PTR es:[si],LFChar    ;is it eoln?
  1029.      je    SEeoln        ;yes, flag and return
  1030.     clc            ;no, we're ok, just return
  1031.     ret    
  1032.  
  1033. SkipEqual ENDP
  1034.  
  1035.  
  1036. SetATT    PROC    NEAR
  1037. ;*************************************************************************
  1038. ;    Set ATT video mode using standard memory locs for ptrs
  1039. ;*************************************************************************
  1040.     ATTMPOff=6        ;offset to font ptr in ATT master pointer table
  1041.  
  1042.     push    es
  1043.     push    di
  1044.     mov    di,0040h    ;get ptr to master table 
  1045.     mov    es,di
  1046.     les    di,es:0084h
  1047.     les    di,es:[di].ATTMPOff    ;get ptr to font table
  1048.     mov    WORD PTR ft_ptr,di ;save offset in proper locs
  1049.     mov    di,es
  1050.     mov    WORD PTR ft_ptr+2,di ;and segment
  1051.     pop    di
  1052.     pop    es
  1053.     xor    dl,dl        ;signal that we've set mode
  1054.     mov    FontNotSet,dl
  1055.     lea    dx,ATTMsg
  1056.     mov    ah,09h
  1057.     int    21h
  1058.     ret
  1059.  
  1060. SetATT    ENDP
  1061.  
  1062. SetEGA    PROC    NEAR
  1063. ;*************************************************************************
  1064. ;    Set EGA font pointer; get pointer from BIOS and set locally
  1065. ;*************************************************************************
  1066.     push    bp
  1067.     push    es
  1068.     mov    ax,1130h    ;get char font address from BIOS
  1069.     mov    bh,03h
  1070.     int    10h
  1071.     mov    word ptr ft_ptr,bp ;save seg:off
  1072.     mov    word ptr ft_ptr+2,es
  1073.  
  1074.     xor    dl,dl        ;signal that we've set mode
  1075.     mov    FontNotSet,dl
  1076.     lea    dx,VEGAMsg    ;say what we've done
  1077.     mov    ah,09h
  1078.     int    21h
  1079.     pop    es
  1080.     pop    bp
  1081.     ret
  1082.  
  1083. SetEGA    ENDP
  1084.  
  1085.  
  1086. MakeUpper PROC    NEAR
  1087. ;*************************************************************************
  1088. ;    Converts the char in al to upper case, if necessary
  1089. ;*************************************************************************
  1090.     cmp    al,'a'
  1091.      jl    MUDone
  1092.     cmp    al,'z'
  1093.      jg    MUDone
  1094.     sub    al,'a'-'A'
  1095. MUDone:    ret
  1096.  
  1097. MakeUpper ENDP
  1098.  
  1099. PrtStr    PROC    NEAR
  1100. ;*************************************************************************
  1101. ;    Prints the string between es:si and the char before es:di 
  1102. ;     and advances si
  1103. ;    Returns si with value of initial di
  1104. ;*************************************************************************
  1105.     push    ax
  1106.     push    dx
  1107. PSLup:  cmp    si,di        ;any left to print?
  1108.      jge    PSDone        ;no
  1109.     mov    dl,BYTE PTR es:[si]
  1110.     mov    ah,02h
  1111.     int    21h
  1112.     inc    si
  1113.     jmp    PSLup
  1114. PSDone:    pop    dx
  1115.     pop    ax
  1116.     ret
  1117.  
  1118. PrtStr    ENDP
  1119.  
  1120.  
  1121. ChkTok    PROC    NEAR
  1122. ;*************************************************************************
  1123. ;    Compare string between es:si & es:di with string pointed to by ds:dx
  1124. ;    use je to check for equality on return
  1125. ;*************************************************************************
  1126.     push    cx
  1127.     mov    cx,di        ;compute char count for cmpsb
  1128.     sub    cx,si
  1129.     push    si        ;save registers
  1130.     push    di
  1131.     push    si
  1132.     pop    di
  1133.     mov    si,dx
  1134.     cmpsb            ;do compare
  1135.     pop    di        ;restore & return
  1136.     pop    si
  1137.     pop    cx
  1138.     ret
  1139.  
  1140. ChkTok    ENDP
  1141.  
  1142. ProcMode PROC    NEAR
  1143. ;*************************************************************************
  1144. ;    Process /MODE= command-line option
  1145. ;*************************************************************************
  1146.     call    SkipEqual    ;skip equal sign
  1147.     mov    al,BYTE PTR es:[si]    ;get that char
  1148.     inc    si        ;move over it
  1149.     cmp    al,'0'        ;got a digit?
  1150.      jl    ModErr        ; nope ... error
  1151.     cmp    al,ModeMax    ;within upper range limit?    
  1152.      jg    ModErr        ; no ... report error
  1153.     push    ax        ;save that char
  1154.     sub    al,'0'        ;convert to digit
  1155.     mov    CurMode,al    ;set it
  1156.     lea    dx,ModMsg    ;say what mode we set
  1157.     mov    ah,09h
  1158.     int    21h
  1159.     pop    dx        ;restore mode digit for printing
  1160.     mov    ah,02h
  1161.     int    21h
  1162.     mov    ah,09h
  1163.     lea    dx,CRLF
  1164.     int    21h
  1165.     ret            ;and we're done
  1166.  
  1167. ModErr:    push    ax        ;save the offending digit
  1168.     mov    ah,09h        ;print error header
  1169.     lea    dx,ModErrStr
  1170.     int    21h
  1171.     pop    dx
  1172.     mov    ah,02h        ;print digit
  1173.     int    21h
  1174.     mov    ah,09h
  1175.     lea    dx,CRLF        ;end the message
  1176.     int    21h
  1177.     ret
  1178. ProcMode ENDP
  1179.  
  1180.  
  1181. FillTT    PROC    NEAR
  1182. ;*************************************************************************
  1183. ;    This procedure fills the TC ("Token Class") table with
  1184. ;    exceptions to the default.
  1185. ;*************************************************************************
  1186.     mov    cx,NumTokDefs        ;process all the exceptions
  1187.     xor    bx,bx            ;start with index 0
  1188.     lea    si,NDT            ;point to the non-def token table
  1189.  
  1190. FillLoop:
  1191.     mov    al,[si][bx].char    ;get char
  1192.     mov    dl,[si][bx].ctype    ;and its type
  1193.     shr    al,1            ;compute address of char in token class table
  1194.      jc    StoreType        ;if char was even, goes to left half
  1195.     shl    dx,1            ; of the byte we're ready to write
  1196.     shl    dx,1
  1197.     shl    dx,1
  1198.     shl    dx,1
  1199. StoreType:
  1200.     xor    ah,ah
  1201.     mov    di,ax            ;ready to point to char in TokenClass table
  1202.     xor    BYTE PTR TC[di],dl
  1203.     add    bx,SIZE TokDef
  1204.     loop    FillLoop
  1205.  
  1206.     ret
  1207. FILLTT    ENDP
  1208.  
  1209. BBLProc    ENDP
  1210. cseg    ENDS
  1211.  
  1212.     END    BBL
  1213.