home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / pcmagazi / 1985 / 25 / monograf.asm next >
Assembly Source File  |  1986-02-05  |  9KB  |  312 lines

  1. ;    MONOGRAF.DRV -- Lotus Driver for Graphics on Monochrome Display
  2. ;    ============
  3. ;
  4. ;        (For use with Lotus 1-2-3 Version 1A)
  5. ;
  6. ;    (C) Copyright Charles Petzold, 1985
  7.  
  8. CSEG        Segment
  9.         Assume    CS:CSEG
  10.  
  11.         Org    0
  12. Beginning    dw    Offset EndDriver,1,1,Offset Initialize
  13.  
  14.         Org    18h
  15.         db    "Monochrome Graphics (C) Charles Petzold, 1985",0
  16.  
  17.         Org    40h
  18.         dw    40 * 8 - 1        ; Maximum Dot Column
  19.         dw    25 * 8 - 1        ; Maximum Dot Row
  20.         dw    10, 7, 6, 10, 7, 6, 256
  21.         db    -1            ; For one monitor
  22.  
  23.         Org    53h
  24.         Jmp    Near Ptr ClearScreen    ; Call 0 -- Clear Screen
  25.         Jmp    Near Ptr ColorSet    ; Call 1 -- Set Color
  26.         Jmp    Near Ptr SetAddress    ; Call 2 -- Set Row/Col Addr
  27.         Jmp    Near Ptr DrawLine    ; Call 3 -- Draw a Line
  28.         Jmp    Near Ptr Initialize    ; Call 4 -- Write Dot (nothing)
  29.         Jmp    Near Ptr WriteChar    ; Call 5 -- Write a Character
  30.         Jmp    Near Ptr DrawBlock    ; Call 6 -- Draw a Block
  31.         Jmp    Near Ptr Initialize    ; Call 7 -- Read Dot (nothing)
  32.         Jmp    Near Ptr Initialize    ; Call 8 -- Video Reset
  33.  
  34. ;    Initialization Routine
  35. ;    ----------------------
  36.  
  37. Initialize    Proc    Far
  38.         Mov    AX,0        ; This is standard
  39.         Or    AX,AX        ;   for all drivers 
  40.         Ret
  41. Initialize    EndP
  42.  
  43. ;    Common Data Used in Routines
  44. ;    -----------------------------------
  45.  
  46. CharacterRow    dw    ?                ; from 0 to 24
  47. CharacterCol    dw    ?                ; from 0 to 79
  48. ScreenAddress    dw    ?,0B000h            ; Offset & Segment
  49. CurrentColor    db    ?,7                ; For Screen Output
  50. Colors        db    219,219,178,177,176,219,178    ; Actually blocks
  51.  
  52. ;    Row and Column Conversion of AX from graphics to character
  53. ;    ----------------------------------------------------------
  54.  
  55. Rounder        dw    0            ; Value to add before division
  56. Divisor        db    ?            ; Value to divide by
  57. MaxDots        dw    ?            ; Number of dots
  58.  
  59. RowConvertRnd:    Mov    [Rounder],4        ; Row rounding -- add 4
  60. RowConvert:    Mov    [Divisor],8        ; Row normal -- divide by 8
  61.         Mov    [MaxDots],200        ; 25 lines times 8 dots
  62.         Jmp    Short Convert        ; And do generalized conversion
  63.  
  64. ColConvertRnd:    Mov    [Rounder],2        ; Column rounding -- add 2
  65. ColConvert:    Mov    [Divisor],4        ; Will divide by 4
  66.         Mov    [MaxDots],320        ; 40 columns times 4 dots
  67.  
  68. Convert:    Cmp    AX,[MaxDots]        ; See if graphics value OK
  69.         Jb    OKToConvert        ; It is if under maximum
  70.         Jl    Negative        ; But could be negative
  71.         Sub    AX,[MaxDots]        ; Otherwise wrap down
  72.         Jmp    Convert            ; And check again
  73. Negative:    Add    AX,[MaxDots]        ; Negatives wrap up
  74.         Jmp    Convert            ; And check again
  75.  
  76. OkToConvert:    Add    AX,[Rounder]        ; Add rounding value
  77.         Div    [Divisor]        ; Divide    
  78.         Cbw                ; And convert to word
  79.         Mov    [Rounder],0        ; For next time through
  80.         Ret
  81.  
  82. ;    Calc Offset -- DX, CX character positions in
  83. ;    -----------
  84.  
  85. CalcOffset:    Push    AX
  86.         Push    DX
  87.  
  88.         Mov    AX,80            ; Columns Per Line
  89.         Mul    DX            ; AX now at beginning of row
  90.         Add    AX,CX            ; Add column value
  91.         Add    AX,AX            ; Double for attributes
  92.         Mov    [ScreenAddress],AX    ; Save as the current address
  93.  
  94.         Pop    DX
  95.         Pop    AX
  96.  
  97.         Ret
  98.  
  99. ;    Address Convert -- DX, CX row and column converted to character
  100. ;    ---------------
  101.  
  102. AddrConvert:    Push    AX
  103.  
  104.         Mov    AX,DX            ; This is graphics row
  105.         Call    RowConvert        ; Convert to character row
  106.         Mov    DX,AX            ; Save back in DX
  107.         Mov    [CharacterRow],AX    ; And save value in memory
  108.  
  109.         Mov    AX,CX            ; This is graphics column
  110.         Call    ColConvert        ; Convert to character column
  111.         Mov    CX,AX            ; Back in CX
  112.         Mov    [CharacterCol],AX    ; And value also saved
  113.  
  114.         Call    CalcOffset        ; Find the screen destination
  115.  
  116.         Pop    AX
  117.  
  118.         Ret
  119.  
  120. ;    Call 0 -- Clear Screen -- AL = 0 for B&W
  121. ;    ======================        -1 for Color
  122.  
  123. ClearScreen    Proc    Far
  124.         Mov    AX,0B000h    ; Monochrome Segment 
  125.         Mov    ES,AX        ; Set EX to it 
  126.         Sub    DI,DI        ; Start at zero
  127.         Mov    CX,25 * 80    ; Number of characters
  128.         Mov    AX,0720h    ; Blanks only
  129.         Cld            ; Forward direction
  130.         Rep    Stosw        ; Do it
  131.         Ret
  132. ClearScreen    EndP
  133.  
  134. ;    Call 1 -- Color Set -- AL = Color (0, 1-6)
  135. ;    -------------------
  136.  
  137. ColorSet    Proc    Far
  138.         Mov    BX,Offset Colors    ; Blocks for 7 colors 
  139.         Xlat    Colors            ; Translate the bytes
  140.         Mov    [CurrentColor],AL    ; And save it
  141.         Ret
  142. ColorSet    EndP
  143.  
  144. ;    Call 2 -- Set Address -- DX = Graphics Row
  145. ;    ---------------------     CX = Graphics Columns
  146.  
  147. SetAddress    Proc    Far
  148.         Call    AddrConvert        ; One routine does it all
  149.         Ret
  150. SetAddress    EndP
  151.  
  152. ;    Call 3 -- Draw Line -- DX = End Row
  153. ;    -------------------    CX = End Column
  154.  
  155. DrawLine    Proc    Far
  156.         Les    DI,DWord Ptr [ScreenAddress]    ; Beginning address
  157.         Mov    AX,[CharacterCol]    ; AX now beginning column
  158.         Mov    BX,[CharacterRow]    ; BX now beginning row
  159.  
  160.         Call    AddrConvert        ; CX,DX now ending col, row
  161.  
  162.         Cmp    AX,CX            ; See if cols are the same
  163.         Je    VertLine        ; If so, it's vertical line    
  164.  
  165.         Cmp    BX,DX            ; See if rows are the same
  166.         Jne    DrawLineEnd        ; If not, don't draw anything
  167.  
  168. HorizLine:    Sub    CX,AX            ; Find the number of bytes
  169.         Mov    BX,2            ; Increment for next byte
  170.         Mov    AL,196            ; The horizontal line
  171.         Mov    AH,179            ; The vertical line
  172.         Jae    DrawTheLine        ; If CX > AX, left to right
  173.         Jmp    Short ReverseLine    ; Otherwise right to left
  174.  
  175. VertLine:    Mov    CX,DX            ; This is the ending column
  176.         Sub    CX,BX            ; Subtract beginning from it
  177.         Mov    BX,80 * 2        ; Increment for next line
  178.         Mov    AL,179            ; The vertical line
  179.         Mov    AH,196            ; The horizontal line
  180.         Jae    DrawTheLine        ; If CX > BX, up to down
  181.  
  182. ReverseLine:    Neg    BX            ; Reverse Increment
  183.         Neg    CX            ; Make a positive value
  184.  
  185. DrawTheLine:    Inc    CX            ; One more byte than calced 
  186.  
  187. DrawLineLoop:    Cmp    Byte Ptr ES:[DI],197    ; See if criss-cross there
  188.         Je    DrawLineCont        ; If so, branch around
  189.  
  190.         Cmp    ES:[DI],AH        ; See if opposite line
  191.         Jne    NoOverLap        ; If not, skip next code
  192.  
  193.         Mov    Byte Ptr ES:[DI],197    ; Write out criss-cross
  194.         Jmp    Short DrawLineCont    ; And continue
  195.  
  196. NoOverLap:    Mov    ES:[DI],AL        ; Display line chararacter
  197.  
  198. DrawLineCont:    Add    DI,BX            ; Next destination
  199.         Loop    DrawLineLoop        ; For CX repetitions
  200.  
  201. DrawLineEnd:    Ret
  202. DrawLine    EndP
  203.  
  204. ;    Call 5 -- Write Character -- DX, CX = row, col; BX = count,
  205. ;    -------------------------    AH = direction, AL = type
  206.  
  207. Direction    db    ?
  208.  
  209. WriteChar    Proc    Far
  210.  
  211.         Push    BX            ; Save count
  212.         Add    BX,BX            ; Initialize adjustment
  213.         Mov    [Direction],AH        ; Save direction
  214.  
  215.         Or    AL,AL            ; Branch according to type
  216.         Jz    WriteType0
  217.         Dec    AL
  218.         Jz    WriteType1
  219.         Dec    AL
  220.         Jz    WriteType2
  221.         Dec    AL
  222.         Jz    WriteType3
  223.  
  224. WriteType4:    Mov    AX,4            ; Adjustment to row
  225.         Jmp    Short WriteCharCont
  226.  
  227. WriteType3:    Add    BX,BX            ; Center on column
  228. WriteType2:    Sub    AX,AX            ; No adjustment to row
  229.         Jmp    Short WriteCharCont
  230.  
  231. WriteType1:    Sub    BX,BX            ; No adjustment on column
  232. WriteType0:    Mov    AX,2            ; Adjustment to row
  233.  
  234. WriteCharCont:    Cmp    [Direction],0        ; Check the direction
  235.         Jz    HorizChars
  236.  
  237.         Sub    DX,BX            ; Vertical -- adjust row
  238.         Sub    DX,BX
  239.         Sub    CX,AX            ; Adjust column
  240.         Mov    AX,80 * 2 - 1        ; Increment for writes 
  241.         Jmp    Short DoWriteChar        
  242.  
  243. HorizChars:    Sub    DX,AX            ; Horizontal -- adjust row
  244.         Sub    DX,AX            
  245.         Sub    CX,BX            ; Adjust column
  246.         Mov    AX,1            ; Increment for writes
  247.  
  248. DoWriteChar:    Call    AddrConvert        ; Convert the address
  249.         Les    DI,DWord Ptr [ScreenAddress]    ; Get video address
  250.         Cld
  251.         Pop    CX            ; Get back character count
  252.         Jcxz    WriteCharEnd        ; Do nothing if no characters
  253.  
  254. CharacterLoop:    Movsb                ; Write character to display
  255.         Add    DI,AX            ; Increment address
  256.         Loop    CharacterLoop        ; Do it CX times
  257.  
  258. WriteCharEnd:    Ret
  259. WriteChar    EndP
  260.  
  261. ;    Call 6 -- Draw Block -- BX,DX = Rows; AX,CX = Columns
  262. ;    --------------------
  263.  
  264. DrawBlock    Proc    Far
  265.         Call    ColConvertRnd        ; AX now first char col
  266.         Xchg    AX,CX            ; Switch with 2nd graph col
  267.         Call    ColConvertRnd        ; AX now 2nd char col
  268.         Cmp    AX,CX            ; Compare two char cols
  269.         Je    DrawBlockEnd        ; End routine if the same
  270.         Ja    NowDoRow        ; If CX lowest, just continue
  271.  
  272.         Xchg    AX,CX            ; Otherwise switch them
  273.  
  274. NowDoRow:    Xchg    AX,BX            ; AX now 1st graph row
  275.         Call    RowConvertRnd        ; AX now 1st char row
  276.         Xchg    AX,DX            ; AX now 2nd graph row
  277.         Call    RowConvertRnd        ; AX now 2nd char row
  278.         Cmp    AX,DX            ; Compare two character columns
  279.         Je    DrawBlockEnd        ; End routine if the same
  280.         Ja    BlockRowLoop        ; If DX lowest, just continue
  281.  
  282.         Xchg    AX,DX            ; Otherwise switch them
  283.  
  284. BlockRowLoop:    Push    CX            ; Beginning Column
  285.         Push    BX            ; Ending Column 
  286.  
  287. BlockColLoop:    Call    CalcOffset        ; Calculate screen address
  288.         Les    DI,DWord Ptr [ScreenAddress]    ; And set ES:DI
  289.  
  290.         Push    Word Ptr [CurrentColor]    ; Push the current color
  291.         Pop    ES:[DI]            ; And Pop it on the screen
  292.  
  293.         Inc    CX            ; Next Column
  294.         Cmp    CX,BX            ; Are we an end?
  295.         Jb    BlockColLoop        ; Nope -- loop again
  296.  
  297.         Pop    BX            ; Get back beginning col
  298.         Pop    CX            ; And the end
  299.  
  300.         Inc    DX            ; Prepare for next row
  301.         Cmp    DX,AX            ; Are we at the end?
  302.         Jb    BlockRowLoop        ; If not, loop 
  303.  
  304. DrawBlockEnd:    Ret
  305. DrawBlock    EndP
  306.  
  307.         Org    $ + 16 - (($ - Beginning) Mod 16)
  308. EndDriver    Label    Byte
  309.  
  310. CSEG        EndS
  311.         End
  312.