home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / asmutil / bluebook.zip / GRAPHICS.ASM < prev    next >
Assembly Source File  |  1986-05-08  |  24KB  |  894 lines

  1.                                       COMMENT ~
  2. GRAPHICS.ASM -- Graphic Plotting Procedures
  3.  
  4.    From `BLUEBOOK of ASSEMBLY ROUTINES for the IBM PC & XT'
  5.          by Christopher L. Morgan
  6.          Copyright (C) 1984 by The Waite Group, Inc.
  7.  
  8.    Contents:
  9.    ---------
  10.    CLS        --  Clear the screen
  11.    GET_COLOR    --  Get the color of a point on the med res color screen
  12.    GMSG_OUT    --  Plot a string
  13.    PAINT    --  Fill an area with specified color
  14.    RCHAR    --  Plot a raster character
  15.    SCHAR    --  Plot a stroke character
  16.    SET_BOX    --  Fill a rectangular box with specified color
  17.    SET_LIN    --  Draw a line
  18.    SET_PT    --  Plot a point
  19.    XOR_BOX    --  Fill a rectangular box using XOR
  20.    XOR_PT    --  Plot a point using XOR
  21.  
  22.    >>>>>  See GRAPHICS.DOC for complete descriptions of these routines. <<<<<
  23.  ------------------------------------------------------------------------------
  24.  These variables need to be defined in the source code calling the GRAPHICS
  25.    routines. See GRAPHICS.DOC.                                                ~
  26. EXTRN    CBYTES:BYTE,    COLOR:WORD,    DELDE:WORD,    DELDX:WORD
  27. EXTRN    DELDY:WORD,    DELP:WORD,    DELS:WORD,    DELSE:WORD
  28. EXTRN    DELSX:WORD,    DELSY:WORD,    FONT:BYTE,    PAINT_STAK:WORD
  29. EXTRN    X0:WORD,    X1:WORD,    X2:WORD,    XMAGN:BYTE
  30. EXTRN    XMSG:WORD,    Y0:WORD,    Y1:WORD,    Y2:WORD
  31. EXTRN    YMAGN:BYTE,    YMSG:WORD
  32. ;______________________________________________________________________________
  33. ;These tables would be better included in the source code calling the 
  34. ;  GRAPHICS routines, and then commented out here.  See GRAPHICS.DOC
  35. ;        
  36. DATAS    SEGMENT    PUBLIC
  37.     CTABLE    DW    0003FH,0403FH,0803FH,0C03FH
  38.         DW    000CFH,010CFH,020CFH,030CFH
  39.         DW    000F3H,004F3H,008F3H,00CF3H
  40.         DW    000FCH,001FCH,002FCH,003FCH
  41.  
  42.     PTABLE    DW    32 DUP(?)        ;A dummy (See GRAPHICS.DOC) 
  43.  
  44.     XTABLE    DW    0FFC0H,0FFF0H,0FFFCH,0FFFFH
  45.         DW    03FC0H,03FF0H,03FFCH,03FFFH
  46.         DW    00FC0H,00FF0H,00FFCH,00FFFH
  47.         DW    003C0H,003F0H,003FCH,003FFH
  48. DATAS    ENDS 
  49. ;______________________________________________________________________________
  50. ;        
  51. CODES    SEGMENT
  52.     PUBLIC CLS,SET_PT,XOR_PT,GET_COLOR,SET_BOX,XOR_BOX
  53.     PUBLIC SET_LIN,SCHAR,RCHAR,GMSG_OUT,PAINT
  54. ASSUME CS:CODES,DS:DATAS
  55. ;____________________________I/O ROUTINES______________________________________
  56. ;Routine to clear the graphics screen
  57. ;
  58. CLS    PROC    FAR
  59.     PUSH    CX                ;Save registers
  60.     PUSH    AX
  61. ;
  62. ;Set up the registers
  63.     MOV    CX,2000H            ;Word count of whole screen
  64.     MOV    AX,0                ;Zero pattern for the screen
  65.     MOV    DI,AX                ;Set starting address
  66.     CLD                    ;Go in forward direction
  67. ;
  68. ;Clear the screen with a single string operation
  69.     REP    STOSW                ;This clears the screen
  70. ;    
  71.     POP    AX                ;Restore registers
  72.     POP    CX
  73.     RET
  74. CLS    ENDP
  75. ;------------------------------------------------------------------------------
  76. ;Routine to plot a point on medium resolution color screen
  77. ;
  78. SET_PT    PROC    FAR
  79.     PUSH    BX                ;Save registers
  80.     PUSH    SI
  81.     PUSH    AX 
  82. ;
  83. ;Multiply Y-coord by bytes/row & adjust for even/odd lines
  84.     MOV    AX,DI                ;Get Y-coordinate into part
  85.     MOV    AH,AL                ; and  into high part
  86.     AND    AX,01FEH            ;Mask off unwanted parts
  87.     SAL    AX,1                ;Times 4
  88.     SAL    AX,1                ;Times 8
  89.     SAL    AX,1                ;Times 16
  90.     MOV    BX,AX                ;Goes into address
  91.     AND    BH,7                ; without adjustment
  92.     SAL    AX,1                ;Times 32
  93.     SAL    AX,1                ;Times 64
  94.     ADD    BX,AX                ;Addr gets Y-coord times 80
  95. ;
  96. ;Add X-coordinate to address
  97.     MOV    AX,SI                ;Get X-coordinate
  98.     SAR    AX,1                ;Divide
  99.     SAR    AX,1                ; by 4
  100.     ADD    BX,AX                ;Here is the address
  101. ;
  102. ;Compute the rotated mask and color
  103.     AND    SI,3                ;Just pixel position into index
  104.     SAL    SI,1                ;Index times 2
  105.     SAL    SI,1                ;Index times 4
  106.     ADD    SI,DX                ;4 * pixel position + color
  107.     SAL    SI,1                ;8 * pixel position + 2 * color
  108.     MOV    AX,CTABLE[SI]            ;Look up rotated color & mask
  109. ;
  110. ;Insert the color into the video byte
  111.     AND    AL,ES:[BX]            ;Get old byte & remove old pixel
  112.     OR    AL,AH                ;Insert new color
  113.     MOV    ES:[BX],AL            ;Put the byte back
  114. ;
  115.     POP    AX                ;Restore registers
  116.     POP    SI
  117.     POP    BX
  118.     RET
  119. SET_PT    ENDP
  120. ;------------------------------------------------------------------------------
  121. ;Routine to XOR a point onto medium resolution color screen 
  122. ;
  123. XOR_PT    PROC    FAR
  124.     PUSH    BX                ;Save registers
  125.     PUSH    SI
  126.     PUSH    AX
  127. ;
  128. ;Multiply Y-coord by bytes/row & adjust for even/odd lines
  129.     MOV    AX,DI                ;Get Y-coordinate into part
  130.     MOV    AH,AL                ; and  into high part
  131.     AND    AX,01FEH            ;Mask off unwanted parts
  132.     SAL    AX,1                ;Times 4
  133.     SAL    AX,1                ;Times 8
  134.     SAL    AX,1                ;Times 16
  135.     MOV    BX,AX                ;Goes into address
  136.     AND    BH,7                ; without adjustment
  137.     SAL    AX,1                ;Times 32
  138.     SAL    AX,1                ;Times 64
  139.     ADD    BX,AX                ;Addr gets Y-coord times 80
  140. ;
  141. ;Add X-coordinate to address
  142.     MOV    AX,SI                ;Get X-coordinate
  143.     SAR    AX,1                ;Divide
  144.     SAR    AX,1                ; by 4
  145.     ADD    BX,AX                ;Here is the address
  146. ;
  147. ;Compute the mask for color and use it
  148.     AND    SI,3                ;Just the bit count into index
  149.     SAL    SI,1                ;Index times 2
  150.     SAL    SI,1                ;Index times 4
  151.     ADD    SI,DX                ;4 * pixel position + color
  152.     SAL    SI,1                ;8 * pixel position + 2 * color
  153.     MOV    AX,CTABLE[SI]            ;Look up rotated color & mask
  154.     XOR    ES:[BX],AH            ;XOR the byte with the color
  155. ;
  156.     POP    AX                ;Restore registers
  157.     POP    SI
  158.     POP    BX
  159.     RET
  160. XOR_PT    ENDP
  161. ;------------------------------------------------------------------------------
  162. ;Routine to return color of a point on med res color screen 
  163. ;
  164. GET_COLOR    PROC    FAR
  165.     PUSH    BX                ;Save registers
  166.     PUSH    CX
  167. ;
  168. ;Multiply Y-coord by bytes/row & adjust for even/odd lines
  169.     MOV    AX,DI                ;Get Y-coordinate into part
  170.     MOV    AH,AL                ; and  into high part
  171.     AND    AX,01FEH            ;Mask off unwanted parts
  172.     SAL    AX,1                ;Times 4
  173.     SAL    AX,1                ;Times 8
  174.     SAL    AX,1                ;Times 16
  175.     MOV    BX,AX                ;Goes into address
  176.     AND    BH,7                ; without adjustment
  177.     SAL    AX,1                ;Times 32
  178.     SAL    AX,1                ;Times 64
  179.     ADD    BX,AX                ;Addr gets Y-coord times 80
  180. ;
  181. ;Add X-coordinate to address
  182.     MOV    AX,SI                ;Get X-coordinate
  183.     SAR    AX,1                ;Divide
  184.     SAR    AX,1                ; by 4
  185.     ADD    BX,AX                ;Here is the address
  186. ;
  187. ;Compute the position of the pixel in the byte
  188.     MOV    CX,SI                ;Use X-coord to determine count
  189.     AND    CX,3                ;Just the bit count
  190.     INC    CX                ; plus one
  191.     SAL    CX,1                ;2 bits/pixel
  192. ;
  193. ;Get the byte and rotate into place
  194.     MOV    AL,ES:[BX]            ;Get old byte
  195.     ROL     AL,CL                ;Rotate left this many times
  196.     AND    AX,3                ;Just the pixel color
  197. ;
  198.     POP    CX                ;Restore registers
  199.     POP    BX
  200.     RET
  201. GET_COLOR    ENDP
  202. ;------------------------------------------------------------------------------
  203. ;Routine to set & fill a rectangular box
  204. ;
  205. SET_BOX    PROC    FAR
  206.     PUSH    SI                ;Save registers
  207.     PUSH    DI
  208.     PUSH    DX
  209.     PUSH    BX
  210.     PUSH    CX
  211.     PUSH    AX
  212. ;
  213. ;Determine byte position for start
  214. ;
  215. ;Get Y contribution
  216.     MOV    AX,Y1                ;Get starting Y-coordinate
  217.     MOV    AH,AL                ;Replicate for odd/even bank
  218.     AND    AX,01FEH            ;Mask off unwanted parts
  219.     SAL    AX,1                ;Times 4
  220.     SAL    AX,1                ;Times 8
  221.     SAL    AX,1                ;Times 16
  222.     MOV    DI,AX                ;Addr gets Y-coord * 16
  223.     AND    DI,7FFH                ;Not the odd/even bit
  224.     SAL    AX,1                ;Times 32
  225.     SAL    AX,1                ;Times 64
  226.     ADD    DI,AX                ;Addr gets Y-coord * 80
  227. ;
  228. ;Add in X contribution
  229.     MOV    AX,X1                ;Get X-coordinate
  230.     SAR    AX,1                ;Divide
  231.     SAR    AX,1                ; by 4
  232.     ADD    DI,AX                ;Beginning of offset
  233. ;
  234. ;Count for outer loop
  235.     MOV    CX,Y2                ;Ending Y-coordinate
  236.     SUB    CX,Y1                ; minus starting Y-coordinate
  237.     INC    CX                ; plus one
  238. ;
  239. ;Count for inner loop
  240.     MOV    SI,X2                ;Ending X-coordinate
  241.     SAR    AX,1                ;Divide
  242.     SAR    AX,1                ; by 4
  243.     MOV    AX,X1                ;Starting X-coordinate
  244.     SAR    AX,1                ;Divide
  245.     SAR    AX,1                ; by 4
  246.     SUB    SI,AX                ;Take the difference
  247.  
  248. ;Get the color
  249.     MOV    BX,COLOR            ;Get the color
  250.     AND    BX,3                ;Just between 0 & 3
  251.     MOV    DL,CBYTES[BX]            ;Look up color pattern
  252. ;
  253. ;Determine mask for start & ending bytes
  254.     MOV    BX,X1                ;Starting byte
  255.     AND    BX,3                ;Just the pixel position
  256.     SAL    BX,1                ;Times 2
  257.     SAL    BX,1                ;Times 4
  258.     MOV    AX,X2                ;Ending byte
  259.     AND    AX,3                ;Just the pixel position
  260.     ADD    BX,AX                ;4 * starting + ending
  261.     SAL    BX,1                ;8 * starting + 2 * ending
  262.     MOV    BX,XTABLE[BX]            ;Look up the masks
  263. ;
  264. ;Set up masked color bytes
  265.     MOV    DH,DL                ;Color for left bytes
  266.     MOV    AH,DL                ;Color for middle bytes
  267.     AND    DX,BX                ;Mask left & right color bytes
  268. ;
  269.     CLD                    ;Forward
  270. SBOXLOOP:
  271.     PUSH    CX                ;Save count of outer loop
  272.     PUSH    DI                ;Save initial byte position
  273. ;
  274.     MOV    CX,SI                ;Count for inner loop
  275. ;
  276. ;Check for only one byte
  277.     MOV    AL,BH                ;Get the mask
  278.     JCXZ    SBOXLOOP2            ;If ending byte coincides
  279. ;
  280. ;Color leftmost byte of the scan line
  281.     NOT    AL                ;Reverse the mask for clearing
  282.     AND    AL,ES:[DI]            ;Get byte frm mem & clr pixels
  283.     OR    AL,DH                ;Put color in place
  284.     STOSB                    ;Put byte in place
  285. ;
  286. ;Check for just two bytes
  287.     DEC    CX                ;Count the byte
  288.     JCXZ    SBOXLOOP1            ;Done?
  289. ;
  290. ;Color middle bytes of the scan line
  291. ;
  292.     MOV    AL,AH                ;Color for middle bytes
  293.     REP    STOSB                ;Put middle bytes in place
  294. ;
  295. ;Handle rightmost byte of the scan line
  296. ;
  297. ;Come here if two or more bytes
  298. SBOXLOOP1:
  299.     MOV    AL,0FFH                ;Set full mask
  300. ;
  301. ;In any case, come here to adjust the masks
  302. SBOXLOOP2:
  303.     AND    AL,BL                ;Bring in right part of mask
  304.     AND    DL,AL                ;Clear left part of color
  305. ;
  306. ;Color the byte
  307.     NOT    AL                ;Reverse the mask for clearing
  308.     AND    AL,ES:[DI]            ;Get byte from mem & clr pixels
  309.     OR    AL,DL                ;Put pixels in the byte
  310.     STOSB                    ;Put byte back into video RAM
  311. ;
  312. ;Compute next scan line
  313.     POP    DI                ;Restor addr of lft side of box
  314.     TEST    DI,2000H            ;Odd or even line?
  315.     JZ    SBOXLOOP3            ;Skip if even
  316.     ADD    DI,80                ; else add 80 bytes/line
  317. SBOXLOOP3:
  318.     XOR    DI,2000H            ;Change banks in any case
  319.     POP    CX                ;Restore outer loop count
  320.     LOOP    SBOXLOOP            ;Next scan line
  321. ;
  322.     POP    AX                ;Restore registers
  323.     POP    CX
  324.     POP    BX
  325.     POP    DX
  326.     POP    DI
  327.     POP    SI
  328.     RET
  329. SET_BOX    ENDP
  330. ;------------------------------------------------------------------------------
  331. ;Routine to fill a rectangular box with color using XOR
  332. ;
  333. XOR_BOX    PROC    FAR
  334.     PUSH    SI                ;Save registers
  335.     PUSH    DI
  336.     PUSH    DX
  337.     PUSH    BX
  338.     PUSH    CX
  339.     PUSH    AX
  340. ;
  341. ;Determine byte position for start
  342. ;
  343. ;Get Y contribution
  344.     MOV    AX,Y1                ;Get starting Y-coordinate
  345.     MOV    AH,AL                ;Replicate for odd/even bank
  346.     AND    AX,01FEH            ;Mask off unwanted parts
  347.     SAL    AX,1                ;Times 4
  348.     SAL    AX,1                ;Times 8
  349.     SAL    AX,1                ;Times 16
  350.     MOV    DI,AX                ;Addr gets Y-coord * 16
  351.     AND    DI,7FFH                ;Not the odd/even bit
  352.     SAL    AX,1                ;Times 32
  353.     SAL    AX,1                ;Times 64
  354.     ADD    DI,AX                ;Addr gets Y-coord * 80
  355. ;
  356. ;Add in X contribution
  357.     MOV    AX,X1                ;Get X-coordinate
  358.     SAR    AX,1                ;Divide
  359.     SAR    AX,1                ; by 4
  360.     ADD    DI,AX                ;Beginning of offset
  361. ;
  362. ;Count for outer loop
  363.     MOV    CX,Y2                ;Ending Y-coordinate
  364.     SUB    CX,Y1                ; minus starting Y-coordinate
  365.     INC    CX                ; plus one
  366. ;
  367. ;Count for inner loop
  368.     MOV    SI,X2                ;Ending X-coordinate
  369.     SAR    AX,1                ;Divide
  370.     SAR    AX,1                ; by 4
  371.     MOV    AX,X1                ;Starting X-coordinate
  372.     SAR    AX,1                ;Divide
  373.     SAR    AX,1                ; by 4
  374.     SUB    SI,AX                ;Take the difference
  375. ;
  376. ;Get the color
  377.     MOV    BX,COLOR            ;Get the color
  378.     AND    BX,3                ;Just between 0 & 3
  379.     MOV    DL,CBYTES[BX]            ;Look up color pattern
  380. ;
  381. ;Determine mask for start and ending bytes
  382.     MOV    BX,X1                ;Starting bytes
  383.     AND    BX,3                ;Just the pixel position
  384.     SAL    BX,1                ;Times 2
  385.     SAL    BX,1                ;Times 4
  386.     MOV    AX,X2                ;Ending byte
  387.     AND    AX,3                ;Just the pixel position
  388.     ADD    BX,AX                ;4 * starting + ending
  389.     SAL    BX,1                ;8 * starting + 2 * ending
  390.     MOV    BX,XTABLE[BX]            ;Look up the masks
  391. ;
  392. ;Set up masked color bytes
  393.     MOV    DH,DL                ;Color for left bytes
  394.     MOV    AH,DL                ;Color for middle bytes
  395.     AND    DX,BX                ;Mask left & right color bytes
  396. ;
  397.     CLD                    ;Forward
  398. XBOXLOOP:
  399.     PUSH    CX                ;Save count of outer loop
  400.     PUSH    DI                ;Save initial byte position
  401. ;
  402.     MOV    CX,SI                ;Count for inner loop
  403. ;
  404. ;Check if only one byte in a scan line
  405.     MOV    AL,BH                ;Get the mask
  406.     JCXZ    XBOXLOOP3            ;If ending byte coincides
  407. ;
  408. ;XOR the leftmost byte
  409.     XOR    ES:[DI],DH            ;XOR color into memory
  410.     INC    DI                ;Next byte
  411.     DEC    CX                ;Count it
  412.     JCXZ    XBOXLOOP2            ;Done?
  413. ;
  414. ;XOR the middle bytes
  415. XBOXLOOP1:
  416.     XOR    ES:[DI],AH            ;XOR color byte into memory
  417.     INC    DI                ;Next byte
  418.     LOOP    XBOXLOOP1            ;Loop to get all the middle
  419. ;
  420. ;Handle rightmost byte
  421. ;
  422. ;Come here if two or more bytes
  423. XBOXLOOP2:
  424.     MOV    AL,0FFH                ;Set full mask
  425. ;
  426. ;In any case, come here to adjust the masks
  427. XBOXLOOP3:
  428.     AND    AL,BL                ;Bring in right part of mask
  429.     AND    DL,AL                ;Clear left part of color
  430. ;
  431. ;XOR the rightmost byte
  432.     XOR    ES:[DI],DL            ;XOR byte into memory
  433.     INC    DI                ;Next byte
  434. ;
  435.     POP    DI                ;Restore the leftmost address
  436.     TEST    DI,2000H            ;Odd or even line?
  437.     JZ    XBOXLOOP4            ;Skip if even
  438.     ADD    DI,80                ; else add 80 bytes/line
  439. XBOXLOOP4:
  440.     XOR    DI,2000H            ;Change banks in any case
  441.     POP    CX                ;Restore outer loop count
  442.     LOOP    XBOXLOOP            ;Next scan line
  443. ;
  444.     POP    AX                ;Restore registers
  445.     POP    CX
  446.     POP    BX
  447.     POP    DX
  448.     POP    DI
  449.     POP    SI
  450.     RET
  451. XOR_BOX    ENDP
  452. ;------------------------------------------------------------------------------
  453. ;Routine to draw a line 
  454. ;
  455. SET_LIN    PROC    FAR
  456.     PUSH    BX                ;Save registers
  457.     PUSH    CX
  458.     PUSH    DX
  459.     PUSH    SI
  460.     PUSH    DI
  461.     PUSH    AX
  462. ;
  463. ;Set up X and Y updates
  464.     MOV    SI,1                ;Start with positive 1 for
  465.     MOV    DI,1                ; X and Y update
  466. ;
  467. ;Find |Y2-Y1|
  468.     MOV    DX,Y2                ;Get Y2
  469.     SUB    DX,Y1                ;Subtract Y1
  470.     JGE    STOR_Y                ;Skip if Y2-Y1 is not negative 
  471.     NEG    DI                ;Mov in negative Y direction
  472.     NEG    DX                ;Absolute value of Y2-Y1
  473. STOR_Y:
  474.     MOV    DELDY,DI            ;Store Y update for diag moves
  475. ;
  476. ;Find |X2-X1|
  477.     MOV    CX,X2                ;Get X2
  478.     SUB    CX,X1                ;Subtract X1
  479.     JGE    STOR_X                ;Skip if X2-X1 is not negative
  480.     NEG    SI                ;Mov in negative X direction
  481.     NEG    CX                ;Absolute value of X2-X1
  482. STOR_X:
  483.     MOV    DELDX,SI            ;Store X update for diag moves
  484. ;
  485. ;Sort |Y2-Y1| & |X2-X1|
  486.     CMP    CX,DX                ;Compare DELS with DELP
  487.     JGE    SET_DIAG            ;Skip if straight move along X
  488.     MOV    SI,0                ;If straight=vert, kill X updat
  489.     XCHG    CX,DX                ; & exchange differences
  490.     JMP    STOR_DELSXY
  491. SET_DIAG:
  492.     MOV    DI,0                ;If straight=horz, kill Y updat
  493. ;
  494. ;Store DELS, DELP, DELSX, & DELSY
  495. STOR_DELSXY:
  496.     MOV    DELS,CX                ;Change in straight direction
  497.     MOV    DELP,DX                ;Change in perpndic to straight
  498.     MOV    DELSX,SI            ;X update in straight direction
  499.     MOV    DELSY,DI            ;Y update in straight direction
  500. ;
  501. ;Get initial values for X & Y
  502.     MOV    SI,X1                ;X-coordinate
  503.     MOV    DI,Y1                ;Y-coordinate
  504. ;
  505. ;Compute initial value & increments for error function
  506.     MOV    AX,DELP    
  507.     SAL    AX,1                ;2 * DELP
  508.     MOV    DELSE,AX            ;Change if straight move
  509. ;
  510.     SUB    AX,CX                ;2 * DELP - DELS
  511.     MOV    BX,AX                ;Initial value
  512. ;
  513.     SUB    AX,CX                ;2 * DELP - 2 * DELS
  514.     MOV    DELDE,AX            ;Change if diagonal move
  515. ;
  516. ;Adjust count
  517.     INC    CX
  518. ;
  519. ;Set the color
  520.     MOV    DX,COLOR            ;Get the color
  521. ;
  522. ;Main loop structure
  523. LIN_LOOP:
  524.     CALL    SET_PT                ;Plot the point
  525.     CMP    BX,0                ;Determine straight or
  526.     JGE    DIAGONAL            ; diagonal move?
  527. ;
  528. ;Straight move case
  529. STRAIGHT:
  530.     ADD    SI,DELSX            ;Update X
  531.     ADD    DI,DELSY            ;Update Y
  532.     ADD    BX,DELSE            ;Update error term
  533.     LOOP    LIN_LOOP            ;Next point
  534.     JMP    LIN_XIT                
  535. ;Diagonal move case
  536. DIAGONAL:
  537.     ADD    SI,DELDX            ;Update X
  538.     ADD    DI,DELDY            ;Update Y
  539.     ADD    BX,DELDE            ;Update error term
  540.     LOOP    LIN_LOOP            ;Next point
  541. LIN_XIT:
  542.     POP    AX                ;Restore registers
  543.     POP    DI
  544.     POP    SI
  545.     POP    DX
  546.     POP    CX
  547.     POP    BX
  548.     RET
  549. SET_LIN    ENDP
  550. ;------------------------------------------------------------------------------
  551. ;Routine to plot a stroke character 
  552. ;
  553. SCHAR    PROC    FAR
  554.     PUSH    SI                ;Save registers
  555.     PUSH    CX
  556.     PUSH    AX
  557. ;
  558.     CBW                    ;Make ASCII code into 16-bit
  559.     SAL    AX,1                ;Times 2
  560.     MOV    SI,AX                ;Into the index
  561.     MOV    SI,PTABLE[SI]            ;Look up the particular char
  562.     MOV    AX,X0                ;X-coord of upper left corner
  563.     MOV    X2,AX
  564.     MOV    AX,Y0                ;Y-coord of upper left corner
  565.     MOV    Y2,AX
  566. ;
  567. ;Run through the strokes
  568. NEWSTROKE:
  569.     LODSB                    ;Get the code byte
  570.     CMP    AL,1AH                ;End of strokes?
  571.     JZ    SCHAR_XIT
  572.     MOV    DL,AL                ;Save code
  573. ;
  574. ;Update X-coordinate of current position
  575.     MOV    AX,X2                ;Old X-coordinate
  576.     MOV    X1,AX                ; gets pushed back
  577.     LODSB                    ;New X-coordinate
  578.     MOV    CL,XMAGN            ; times XMAGN
  579.     MUL    CL                ;Multiply
  580.     ADD    AX,X0                ;Add to upper left corner
  581.     MOV    X2,AX                ; & put into current position
  582. ;
  583. ;Update Y-coordinate of current position
  584.     MOV    AX,Y2                ;Old Y-coordinate
  585.     MOV    Y1,AX                ; gets pushed back
  586.     LODSB                    ;New Y-coordinate
  587.     MOV    CL,YMAGN            ; times YMAGN
  588.     MUL    CL                ;Multiply
  589.     ADD    AX,Y0                ;Add to upper left corner
  590.     MOV    Y2,AX                ; & put into current position
  591. ;
  592.     CMP    DL,'U'                ;Pen up?
  593.     JE    NEWSTROKE            ;Skip, if so
  594. ;
  595.     CALL    SET_LIN                ;Draw the stroke
  596. ;
  597.     JMP    NEWSTROKE            ;Get next stroke
  598. SCHAR_XIT:
  599.     POP    AX                ;Restore registers
  600.     POP    CX
  601.     POP    SI
  602.     RET
  603. SCHAR    ENDP
  604. ;------------------------------------------------------------------------------
  605. ;Routine to plot a raster character
  606. ;
  607. RCHAR    PROC    FAR
  608.     PUSH    SI                ;Save registers
  609.     PUSH    DX
  610.     PUSH    CX
  611.     PUSH    AX
  612. ;
  613. ;Look up pattern for character
  614.     CBW                    ;Make ASCII code into 16-bit
  615.     SAL    AX,1                ;Times 2
  616.     SAL    AX,1                ;Times 4
  617.     SAL    AX,1                ;Times 8
  618.     ADD    AX,0FA6EH + 7            ;Character table + pattern end
  619.     MOV    SI,AX                ;Here is the offset
  620. ;
  621.     MOV    DX,DS                ;Save old DS
  622.     MOV    AX,0F000H            ;Point DS to ROM segment
  623.     MOV    DS,AX                ;Here is the data segment
  624. ;
  625. ;Store the pattern on the stack
  626.     MOV    CX,8                ;For a count of 8 bytes
  627.     STD                    ;Backward direction
  628. RCHAR1:
  629.     LODSB                    ;Load
  630.     PUSH    AX                ;Push onto stack
  631.     LOOP    RCHAR1
  632. ;
  633.     MOV    DS,DX                ;Restore data segment
  634. ;
  635. ;Get the starting point
  636.     MOV    AX,X0                ;Get X-coordinate
  637.     MOV    X1,AX
  638.     MOV    AX,Y0                ;Get Y-coordinate
  639.     MOV    Y1,AX
  640. ;
  641.     MOV    CX,8                ;For a count of 8 rows
  642. RCHAR2:
  643.     POP    DX                ;Get the next row
  644.     PUSH    CX                ;Save the count
  645. ;
  646.     MOV    AL,YMAGN            ;Vertical sizing
  647.     CBW
  648.     DEC    AX                ;One less
  649.     ADD    AX,Y1                ;Add to new dot position
  650.     MOV    Y2,AX
  651. ;
  652.     MOV    CX,8                ;For a count of 8 dots
  653. RCHAR3:
  654.     PUSH    CX                ;Save the count
  655. ;
  656.     MOV    AL,XMAGN            ;Horizontal sizing
  657.     CBW
  658.     DEC    AX                ;One less
  659.     ADD    AX,X1                ;Add to new dot position
  660.     MOV    X2,AX
  661. ;
  662.     TEST     DL,80H                ;Check the dot
  663.     JZ    RCHAR4                ; & skip if zero
  664. ;
  665.     CALL    SET_BOX                ;Plot if a one
  666. RCHAR4:
  667.     MOV    AX,X2                ;Next column
  668.     INC    AX                ;One over from end of box
  669.     MOV    X1,AX                ;Into next dot position
  670.     ROL    DL,1                ;Next dot from pattern
  671.     POP    CX                ;Restore count of dots
  672.     LOOP    RCHAR3                ;Loop for next dot
  673. ;
  674.     MOV    AX,X0                ;Restore to first column
  675.     MOV    X1,AX                ;Beginning of row
  676.     MOV    AX,Y2                ;Next row
  677.     INC    AX                ;One down from end of box
  678.     MOV    Y1,AX                ;Into next row position
  679.     POP    CX                ;Restore count of rows
  680.     LOOP    RCHAR2                ;Loop for next row
  681. ;
  682.     POP    AX                ;Restore registers
  683.     POP    CX
  684.     POP    DX
  685.     POP    SI
  686.     RET
  687. RCHAR    ENDP
  688. ;------------------------------------------------------------------------------
  689. ;Routine to print a message on the graphics screen 
  690. ;
  691. GMSG_OUT    PROC    FAR
  692. ;
  693. ;Get (X,Y) location of message on the screen
  694.     MOV    AX,XMSG                ;Get X-coordinate on screen
  695.     MOV    X0,AX                ; for first character
  696.     MOV    AX,YMSG                ;Get Y-coordinate on screen
  697.     MOV    Y0,AX                ; for first character
  698.     CLD                    ;Go in forward direction
  699. ;
  700. ;Main loop through characters of the message
  701. GMSG_LOOP:
  702.     CLD                    ;Forward direction
  703.     LODSB                    ;Get the ASCII code
  704.     CMP    AL,0                ;End of string?
  705.     JE    GMSG_XIT
  706. ;
  707. ;Check for fonts
  708. FONT0:
  709.     CMP    FONT,0                ;Use font 0?
  710.     JNE    FONT1
  711.     CALL    SCHAR                ;Use stroke characters
  712. FONT1:
  713.     CMP    FONT,1                ;Use font 1?
  714.     JNE    NEXTCHAR
  715.     CALL    RCHAR                ;Use raster characters
  716. NEXTCHAR:
  717.     MOV    AL,8                ;Character cell width
  718.     MOV    CL,XMAGN            ;Times horizontal magnitude
  719.     MUL    CL                ;Multiply
  720.     ADD    X0,AX                ;Add to loc of previous char
  721. ;
  722.     JMP    GMSG_LOOP            ;Loop for next character
  723. GMSG_XIT:
  724.     RET
  725. GMSG_OUT    ENDP
  726. ;------------------------------------------------------------------------------
  727. ;Routine to fill an area with a specified color 
  728. ;  Uses two subroutines: PUSHPAINT & POPPAINT
  729. ;
  730. ;PUSHPAINT pushes X- & Y-coordinates on paint stack
  731. PUSHPAINT    PROC    NEAR
  732.     DEC    BP                ;BP is the paint stack pointer
  733.     DEC    BP                ; & gets decremented first
  734.     MOV    [BP],SI                ;Push X
  735.     DEC    BP
  736.     DEC    BP
  737.     MOV    [BP],DI                ;Push Y
  738.     RET
  739. PUSHPAINT    ENDP
  740. ;
  741. ;POPPAINT pops X- & Y-coordinates on paint stack
  742. POPPAINT    PROC    NEAR
  743.     MOV    DI,[BP]                ;Pop Y
  744.     INC    BP                ; then increment stack
  745.     INC    BP
  746.     MOV    SI,[BP]                ;Pop X
  747.     INC    BP
  748.     INC    BP
  749.     RET
  750. POPPAINT    ENDP
  751. ;
  752. ;Main PAINT routine
  753. PAINT    PROC    FAR
  754. ;
  755. ;Initialize paint color
  756.     MOV    DX,COLOR
  757. ;
  758. ;Initialize paint stack
  759.     LEA    BP,PAINT_STAK            ;BP is set to top of stack
  760.     CALL    PUSHPAINT            ;Push seed onto stack
  761. ;
  762. ;Main loop for painting
  763. PAINT1:
  764.     LEA    AX,PAINT_STAK            ;Stack empty?
  765.     CMP    BP,AX
  766.     JNE    PAINT2                ;Continue, if not
  767.     JMP    PAINT_XIT            ;Else exit
  768. ;
  769. ;Get the next place to paint
  770. PAINT2:
  771.     CALL    POPPAINT            ;Pop the next place to paint
  772.     CALL    GET_COLOR            ;Color is returned in AL
  773.     CMP    AL,DL                ;Is it filled?
  774.     JE    PAINT1
  775.     CMP    AL,DH                ;Is it boundary?
  776.     JE    PAINT1
  777.     CMP    DI,0                ;Top of screen?
  778.     JL    PAINT1
  779.     CMP    DI,199                ;Bottom of screen?
  780.     JG    PAINT1
  781. ;
  782. ;Move right until boundary is reached
  783. PAINT3:
  784.     INC    SI                ;X <-- X + 1
  785.     CALL    GET_COLOR            ;Look right
  786.     DEC    SI                ;Restore X
  787. ;
  788.     CMP    AL,DL                ;Is it filled?
  789.     JE    PAINT4
  790.     CMP    AL,DH                ;Is it boundary color?
  791.     JE    PAINT4
  792.     CMP    SI,319                ;At right screen boundary?
  793.     JE    PAINT4
  794.     INC    SI                ;X <-- X + 1
  795.     JMP    PAINT3
  796. ;
  797. ;Push above and below
  798. PAINT4:
  799.     DEC    DI                ;Y <-- Y - 1
  800.     CALL    GET_COLOR            ;Check above
  801.     MOV    BH,AL                ;Save above state
  802.     CMP    AL,DL                ;Is it filled?
  803.     JE    PAINT5
  804.     CMP    AL,DH                ;Is it boundary color?
  805.     JE    PAINT5
  806.     CALL    PUSHPAINT            ;Push above
  807. PAINT5:
  808.     INC    DI                ;Restore Y
  809.     INC    DI                ;Y <-- Y + 1
  810.     CALL    GET_COLOR            ;Check below
  811.     MOV    BL,AL                ;Save below state
  812.     CMP    AL,DL                ;Is it filled?
  813.     JE    PAINT6
  814.     CMP    AL,DH                ;Is it boundary color?
  815.     JE    PAINT6
  816.     CALL    PUSHPAINT            ;Push below
  817. PAINT6:
  818.     DEC    DI                ;Restore Y
  819. ;
  820. ;Anchor the end point of the scan line
  821.     MOV    X2,SI                ;Store X-coord, end of scan lin
  822.     MOV    Y2,DI                ;Store Y-coord, end of scan lin
  823. ;
  824. ;Plot as we scan left, checking above & below
  825. PAINT7:
  826. ;Check above
  827.     DEC    DI                ;Y <-- Y - 1
  828.     CALL    GET_COLOR            ;Check above
  829.     CMP    AL,DL                ;Is it filled?
  830.     JE    PAINT9
  831.     CMP    AL,DH                ;Is it boundary color?
  832.     JE    PAINT9
  833. ;
  834.     CMP    BH,DL                ;Last above filled?
  835.     JE    PAINT8
  836.     CMP    BH,DH                ;Was it boundary color?
  837.     JE    PAINT8
  838.     JMP    PAINT9
  839. PAINT8:
  840.     CALL    PUSHPAINT            ;Push above if new place 
  841. ;                          to paint
  842. PAINT9:
  843.     MOV    BH,AL                ;Update last above
  844. ;
  845.     INC    DI                ;Restore Y
  846. ;
  847. ;Check below
  848.     INC    DI                ;Y <-- Y + 1
  849.     CALL    GET_COLOR            ;Check below
  850.     CMP    AL,DL                ;Is it filled?
  851.     JE    PAINT11
  852.     CMP    AL,DH                ;Is it boundary color?
  853.     JE    PAINT11
  854. ;
  855.     CMP    BL,DL                ;Last below filled?
  856.     JE    PAINT10
  857.     CMP    BL,DH                ;Was it boundary color?
  858.     JE    PAINT10
  859.     JMP    PAINT11
  860. PAINT10:
  861.     CALL    PUSHPAINT            ;Push below if new place 
  862. ;                          to paint
  863. PAINT11:
  864.     DEC    DI
  865.     MOV    BL,AL                ;Update last below
  866. ;
  867.     INC    DI                ;Restore Y
  868. ;
  869. ;Move left
  870.     DEC    SI                ;X <-- X - 1
  871.     JL    PAINT12                ;Stop the scan if too far left
  872.     CALL    GET_COLOR            ;Check the point
  873.     CMP    AL,DL                ;Is it filled yet?
  874.     JE    PAINT12                ; if so, next scan line
  875.     CMP    AL,DH                ;Is it boundary yet?
  876.     JE    PAINT12                ; if so, next scan line
  877.     JMP    PAINT7                ;Continue painting scan line
  878. PAINT12:
  879.     INC    SI                ;Restore X
  880.     MOV    X1,SI                ;Store X-coordinate of start
  881.     MOV    Y1,DI                ;Store Y-coordinate of start
  882.     CALL    SET_BOX                ;Plot the scan line
  883.     JMP    PAINT1                ;Next place to paint
  884. ;
  885. PAINT_XIT:
  886.     RET
  887. PAINT    ENDP
  888. ;------------------------------------------------------------------------------
  889. CODES    ENDS
  890. ;
  891.     END
  892. ;______________________________________________________________________________
  893. ;>>>>> Physical EOF GRAPHICS.ASM <<<<<
  894.