home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / pcmagazi / 1987 / 09 / draw.asm < prev    next >
Assembly Source File  |  1987-02-16  |  35KB  |  757 lines

  1. ;            Draw.asm
  2.  
  3. CODE SEGMENT                           ;*************************
  4. ASSUME CS:CODE,DS:CODE                 ;*                       *
  5. ORG 100H                               ;*  REMEMBER TO EXE2BIN  *
  6.                                        ;*                       *
  7. START:         JMP    BEGINNING        ;*************************
  8.  
  9. COPYRIGHT      DB     'Copyright 1987 Ziff-Davis Publishing Co.',1AH
  10. PROGRAMMER     DB     'Michael J. Mefford'
  11.  
  12. FILE           DB     'DRAW.DAT',0
  13. PARA_FLAG      DB     0
  14. FILE_FLAG      DB     0
  15. POLL_KEY       DB     0
  16.  
  17. X_POSITION     DW     319
  18. Y_POSITION     DW      99
  19. X_BOUNDRY      DW     599
  20. Y_BOUNDRY      EQU    199
  21. X_DIRECTION    DW       ?
  22. Y_DIRECTION    DW       ?
  23. X_TEMP         DW       ?
  24. Y_TEMP         DW       ?
  25. DELTA_X        DW       ?
  26. DELTA_Y        DW       ?
  27. HALF_X         DW       ?
  28. HALF_Y         DW       ?
  29. COUNT          DW       ?
  30. DIRECTION      DW       ?
  31.  
  32. COLOR          DB       1
  33. UPDATE_FLAG    DB       1
  34. PLOT_FLAG      DB       1
  35.  
  36. NEW_COLOR      DB       ?
  37. MAX_COLOR      DB       1
  38. BORDER         DB       ?
  39. LEFT_X         DW       ?
  40. RIGHT_X        DW       ?
  41. NEXT_LEFT      DW       ?
  42. NEXT_RIGHT     DW       ?
  43.  
  44. MONOCHROME     DB       'Draw requires CGA adapter.$'
  45.  
  46. ;----------------------------------------------------------;
  47. ; Exit if attempting to run on a monochrome system.        ;
  48. ; Capitalize command line and check for switch characters. ;
  49. ;----------------------------------------------------------;
  50.  
  51. BEGINNING:     MOV    AX,40H                 ;Point to BIOS data segment.
  52.                MOV    DS,AX
  53.                CMP    DS:[63H],3B4H          ;Is it a monochrome adapter?
  54.                PUSH   CS
  55.                POP    DS
  56.                JNZ    CK_PARAMETERS          ;If no, check parameters.
  57.                MOV    DX,OFFSET MONOCHROME   ;Else, display error message.
  58.                MOV    AH,9
  59.                INT    21H
  60.                INT    20H                    ;And terminate.
  61.  
  62. CK_PARAMETERS: CMP    BYTE PTR DS:[80H],0    ;Are there any parameters?
  63.                JZ     PARAMETERS             ;If no, open DRAW.DAT
  64.  
  65. CAPITALIZE:    MOV    SI,81H                 ;Point to parameters.
  66. NEXT_CAP:      LODSB                         ;Get a byte.
  67.                CMP    AL,13                  ;Is it carriage return?
  68.                JZ     PARAMETERS             ;If yes, done here.
  69.                CMP    AL,'/'                 ;Is it switch character?
  70.                JZ     SWITCHES               ;If yes, check which one.
  71.                CMP    AL,'0'                 ;Is it a possible command?
  72.                JB     NEXT_CAP               ;If no, get next byte.
  73.                MOV    PARA_FLAG,1            ;Else flag that parameter exists.
  74.                CMP    AL,'a'                 ;Is it lower case?
  75.                JB     NEXT_CAP               ;If no, get next byte.
  76.                AND    BYTE PTR [SI-1],5FH    ;Else, capitalize.
  77.                JMP    SHORT NEXT_CAP         ;Next byte.
  78.  
  79. SWITCHES:      CMP    AL,'/'                 ;Is it switch character?
  80.                JNZ    GET_SWITCH             ;If no, get next byte.
  81.                MOV    BYTE PTR [SI-1],0      ;Else create ASCIIZ for DOS.
  82. GET_SWITCH:    LODSB                         ;Get a byte.
  83.                CMP    AL,13                  ;Is it carriage return?
  84.                JZ     PARAMETERS             ;If yes, done here.
  85.                AND    AL,5FH                 ;Else, capitalize.
  86.                CMP    AL,'K'                 ;Is it /K switch?
  87.                JNZ    CK_FILE                ;If no, check /F.
  88.                MOV    POLL_KEY,1             ;Else, flag as no keyboard poll.
  89. CK_FILE:       CMP    AL,'F'                 ;Is it /F?
  90.                JNZ    SWITCHES               ;If no, get next byte.
  91.                MOV    FILE_FLAG,1            ;Else, flag as filespec.
  92.                JMP    SHORT SWITCHES         ;Get next byte.
  93.  
  94. ;-----------------------------------------------------------------;
  95. ; Check to see if parameters exist and if yes check if filespec.  ;
  96. ; If yes, read file into buffer and process by stripping Wordstar ;
  97. ; high bit, capitalizing, stripping comments and stripping space  ;
  98. ; characters and below.  Finish by tacking on a carriage return.  ;
  99. ;-----------------------------------------------------------------;
  100.  
  101. PARAMETERS:    CMP    PARA_FLAG,1            ;Are there parameters?
  102.                JZ     FILE_NAME              ;If yes, check if filespec.
  103.                MOV    DX,OFFSET FILE         ;Else, point to DRAW.DAT
  104.                JMP    SHORT OPEN_FILE        ; and open file.
  105.  
  106. FILE_NAME:     CMP    FILE_FLAG,1            ;Is it a filespec?
  107.                JNZ    READ_COMMAND           ;If no, read the command line.
  108.                MOV    DX,82H                 ;Else, point to filespec.
  109.  
  110. OPEN_FILE:     MOV    AX,3D00H               ;Open file for reading.
  111.                INT    21H
  112.                JC     EXIT                   ;If not found, exit.
  113.  
  114.                MOV    BX,AX                  ;Else, filehandle in BX.
  115.                MOV    DX,OFFSET BUFFER       ;Read file into buffer.
  116.                MOV    CX,0F000H
  117.                MOV    AH,3FH
  118.                INT    21H
  119.  
  120.                MOV    CX,AX                  ;File length in CX.
  121.                MOV    SI,OFFSET BUFFER       ;Initialized SI and DI
  122.                MOV    DI,OFFSET BUFFER       ; to head of buffer.
  123.  
  124. FORMAT:        LODSB                         ;Get a byte.
  125.                AND    AL,7FH                 ;Strip Wordstar high bit.
  126.                CMP    AL,':'                 ;Is it comment character?
  127.                JZ     STRIP                  ;If yes, strip comment.
  128.                CMP    AL,'a'                 ;Is it lower case?
  129.                JB     CK_CONTROL             ;If no, check space and below.
  130.                AND    AL,5FH                 ;Else, capitalize.
  131. CK_CONTROL:    CMP    AL,32                  ;Is it space or below?
  132.                JBE    NEXT_FORMAT            ;If yes, don't store.
  133.                STOSB                         ;Else store the character.
  134. NEXT_FORMAT:   LOOP   FORMAT                 ;Get next byte.
  135. END_FORMAT:    MOV    BYTE PTR [DI],13       ;Tack on carriage return as EOF.
  136.                MOV    SI,OFFSET BUFFER       ;Point to commands.
  137.                JMP    SHORT GRAPHICS_MODE    ;Change to graphics mode.
  138.  
  139. NEXT_STRIP:    LODSB                         ;Get a byte.
  140.                AND    AL,7FH                 ;Strip Wordstar high bit.
  141.                CMP    AL,10                  ;Is it linefeed?
  142.                JZ     NEXT_FORMAT            ;If yes get next command.
  143. STRIP:         LOOP   NEXT_STRIP             ;Else, skip and get next byte.
  144.                JMP    SHORT END_FORMAT
  145.  
  146. ;------------------------------------------------;
  147.  
  148. EXIT:          INT 20H               ;Terminate.
  149.  
  150. ;------------------------------------------------;
  151.  
  152. ;--------------------------;
  153. ; Change to graphics mode. ;
  154. ;--------------------------;
  155.  
  156. READ_COMMAND:  MOV    SI,82H                 ;Initialize pointer to commands.
  157.  
  158. GRAPHICS_MODE: CMP    BYTE PTR [SI],'X'      ;Low resolution command?
  159.                JNZ    HIGH_RES               ;If no, high resolution.
  160.                INC    SI                     ;Else, bump pointer past "X".
  161.                PUSH   SI                     ;Save pointer.
  162.                MOV    AX,4                   ;Change to 320X200 color.
  163.                INT    10H
  164.                MOV    X_POSITION,159         ;Change center position.
  165.                MOV    X_BOUNDRY,319          ;Change boundry.
  166.                MOV    COLOR,3                ;Change default color.
  167.                MOV    MAX_COLOR,3
  168.                CALL   CK_NUMBER              ;Get palette.
  169.                MOV    BH,1
  170.                MOV    AH,0BH                 ;Select palette.
  171.                INT    10H
  172.                POP    SI                     ;INT 10h does not preserve SI.
  173.                JMP    SHORT NEXT_COMMAND     ;Get commands.
  174.  
  175. HIGH_RES:      MOV    AX,6                   ;640X200 BW.
  176.                PUSH   SI                     ;Preserve SI.
  177.                INT    10H
  178.                POP    SI
  179.  
  180. ;--------------------------------;
  181. ; This is the command processor. ;
  182. ;--------------------------------;
  183.  
  184. NEXT_COMMAND:  CMP    POLL_KEY,1             ;Should we poll keyboard?
  185.                JZ     GET_COMMAND            ;If no, skip.
  186.                MOV    AH,1                   ;Else, check for keystroke
  187.                INT    16H                    ; via BIOS.
  188.                JNZ    EXIT                   ;If keystroke, exit.
  189. GET_COMMAND:   LODSB                         ;Else, get a byte.
  190.                CMP    AL,13                  ;Is it carriage return?
  191.                JBE    EXIT                   ;If yes, we are done.
  192.                CMP    AL,32                  ;Is it space, comma or semicolon?
  193.                JZ     NEXT_COMMAND           ;If yes, skip.
  194.                CMP    AL,','
  195.                JZ     NEXT_COMMAND
  196.                CMP    AL,';'
  197.                JZ     NEXT_COMMAND
  198.  
  199. CK_U:          CMP    AL,'U'                 ;Is it "U" ?
  200.                JNZ    CK_D                   ;If no, check "D".
  201.                MOV    X_DIRECTION,0
  202.                MOV    Y_DIRECTION,-1         ;Else, up one.
  203.                JMP    DRAW_COMMAND
  204.  
  205. CK_D:          CMP    AL,'D'                 ;Is it "D" ?
  206.                JNZ    CK_L                   ;If no, check "L".
  207.                MOV    X_DIRECTION,0
  208.                MOV    Y_DIRECTION,1          ;Else, down one.
  209.                JMP    DRAW_COMMAND
  210.  
  211. CK_L:          CMP    AL,'L'                 ;Is it "L" ?
  212.                JNZ    CK_R                   ;If no, check "R".
  213.                MOV    X_DIRECTION,-1         ;Else left one.
  214.                MOV    Y_DIRECTION,0
  215.                JMP    DRAW_COMMAND
  216.  
  217. CK_R:          CMP    AL,'R'                 ;Is it "R" ?
  218.                JNZ    CK_E                   ;If no, check "E".
  219.                MOV    X_DIRECTION,1          ;Else, right one.
  220.                MOV    Y_DIRECTION,0
  221.                JMP    DRAW_COMMAND
  222.  
  223. CK_E:          CMP    AL,'E'                 ;Is it "E" ?
  224.                JNZ    CK_F                   ;If no, check "F".
  225.                MOV    X_DIRECTION,1          ;Else, right one.
  226.                MOV    Y_DIRECTION,-1         ;Up one.
  227.                JMP    SHORT DRAW_COMMAND
  228.  
  229. CK_F:          CMP    AL,'F'                 ;Is it "F" ?
  230.                JNZ    CK_G                   ;If no, check "G".
  231.                MOV    X_DIRECTION,1          ;Else, right one.
  232.                MOV    Y_DIRECTION,1          ;Down one.
  233.                JMP    SHORT DRAW_COMMAND
  234.  
  235. CK_G:          CMP    AL,'G'                 ;Is it "G" ?
  236.                JNZ    CK_H                   ;If no, check "H".
  237.                MOV    X_DIRECTION,-1         ;Else, left one.
  238.                MOV    Y_DIRECTION,1          ;Down one.
  239.                JMP    SHORT DRAW_COMMAND
  240.  
  241. CK_H:          CMP    AL,'H'                 ;Is it "H" ?
  242.                JNZ    CK_B                   ;If no, check "B".
  243.                MOV    X_DIRECTION,-1         ;Else left one.
  244.                MOV    Y_DIRECTION,-1         ;Up one.
  245.                JMP    SHORT DRAW_COMMAND
  246.  
  247. CK_B:          CMP    AL,'B'                 ;Is it "B" ?
  248.                JNZ    CK_N                   ;If no, check "N".
  249.                MOV    PLOT_FLAG,0            ;Else, flag no plotting.
  250.                JMP    SHORT COMMAND_END
  251.  
  252. CK_N:          CMP    AL,'N'                 ;Is it "N" ?
  253.                JNZ    CK_C                   ;If no, check "C".
  254.                MOV    UPDATE_FLAG,0          ;Else, flag no update.
  255.                JMP    SHORT COMMAND_END
  256.  
  257. CK_C:          CMP    AL,'C'                 ;Is it "C" ?
  258.                JNZ    CK_S                   ;If no, check "S".
  259.                CALL   CK_NUMBER              ;Else, get color.
  260.                MOV    COLOR,AL               ;And store.
  261.                JMP    SHORT COMMAND_END
  262.  
  263. CK_S:          CMP    AL,'S'                 ;Is it "S" ?
  264.                JNZ    CK_M                   ;If no, check "M".
  265.                CALL   CLS
  266.                JMP    SHORT COMMAND_END
  267.  
  268. CK_M:          CMP    AL,'M'                 ;Is it "M" ?
  269.                JNZ    CK_P                   ;If no, check "P".
  270.                CALL   MOVE                   ;Else, move coordinates.
  271.                JMP    SHORT COMMAND_END
  272.  
  273. CK_P:          CMP    AL,'P'                 ;Is it "P" ?
  274.                JNZ    CK_K                   ;If no, check "K".
  275.                CALL   PAINT                  ;Else, paint.
  276.                JMP    SHORT COMMAND_END
  277.  
  278. CK_K:          CMP    AL,'K'                 ;Is it "K" ?
  279.                JNZ    COMMAND_END            ;If no, get next command.
  280.                MOV    POLL_KEY,1             ;Else, flag as no key poll.
  281.                JMP    SHORT COMMAND_END
  282.  
  283. DRAW_COMMAND:  CALL   DRAW                   ;Draw the dot.
  284.                CALL   UPDATE_END             ;Restore coordinates if needed.
  285. COMMAND_END:   JMP    NEXT_COMMAND           ;Get next command.
  286.  
  287.                ;*************;
  288.                ; Subroutines ;
  289.                ;*************;
  290.  
  291. ;--------------------------------------------------------;
  292. ; This subroutine draws a dot if update flag is not set. ;
  293. ; Otherwise, just the coordinates are changed.           ;
  294. ;--------------------------------------------------------;
  295.  
  296. DRAW:          CALL   CK_PLOT                ;Check to see if drawing.
  297.                CALL   CK_NUMBER              ;Get units to move.
  298.                CMP    AX,0                   ;If zero, exit.
  299.                JZ     END_DRAW
  300.                CALL   UPDATE_START           ;Check if non-update.
  301.  
  302. NEXT_DRAW:     MOV    CX,X_DIRECTION         ;Add X direction.
  303.                ADD    CX,X_POSITION
  304.                CMP    CX,0                   ;Check boundries.
  305.                JB     END_DRAW
  306.  
  307. UPPER_X:       CMP    CX,X_BOUNDRY
  308.                JA     END_DRAW
  309. STORE_X:       MOV    X_POSITION,CX          ;Store new X position.
  310.  
  311.                MOV    DX,Y_DIRECTION         ;Add Y direction.
  312.                ADD    DX,Y_POSITION
  313.                CMP    DX,0                   ;Check boundries.
  314.                JB     END_DRAW
  315.  
  316. UPPER_Y:       CMP    DX,Y_BOUNDRY
  317.                JA     END_DRAW
  318. STORE_Y:       MOV    Y_POSITION,DX          ;Store new Y position
  319.  
  320.                CMP    PLOT_FLAG,1            ;Is it a blank move.
  321.                JNZ    LOOP_DRAW              ;If yes, skip draw.
  322.  
  323. PLOT:          MOV    AL,COLOR               ;Else, color in AL.
  324.                MOV    AH,0CH                 ;Write dot.
  325.                INT    10H
  326.  
  327. LOOP_DRAW:     DEC    BX                     ;Draw all units?
  328.                JNZ    NEXT_DRAW              ;If no, draw next.
  329. END_DRAW:      RET                           ;Else, return.
  330.  
  331. ;------------------------------------------------------------------;
  332. ; This subroutine moves the X,Y coordinates either to new absolute ;
  333. ; coordinates or relatively according to Bresenham's Algorithm.    ;
  334. ;------------------------------------------------------------------;
  335.  
  336. MOVE:          CALL   CK_SIGN                ;Is it prefaced with +/- ?
  337.                JNC    DO_ABSOLUTE            ;If no, absolute move.
  338.                MOV    X_DIRECTION,1          ;Else, assume positive.
  339.                CMP    BP,2                   ;Is it positive move?
  340.                JNZ    STORE_X1               ;If yes, store.
  341.                MOV    X_DIRECTION,-1         ;Else, negative direction.
  342.                NEG    AX                     ;Negate units.
  343.  
  344. STORE_X1:      MOV    DELTA_X,AX             ;Store units.
  345.                INC    SI                     ;Bump pointer past comma.
  346.                CALL   CK_SIGN                ;Do the same for the Y direction.
  347.                MOV    Y_DIRECTION,1
  348.                CMP    BP,2
  349.                JNZ    STORE_Y1
  350.                MOV    Y_DIRECTION,-1
  351.                NEG    AX
  352. STORE_Y1:      MOV    DELTA_Y,AX
  353.                JMP    SHORT CK_SLOPE         ;Plot the slope.
  354.  
  355. DO_ABSOLUTE:   SUB    AX,X_POSITION          ;Target X - current position.
  356.                MOV    X_DIRECTION,1          ;Assume positive.
  357.                JGE    STORE_X2               ;Is it positive?
  358.                MOV    X_DIRECTION,-1         ;If no, negative direction.
  359.                NEG    AX                     ;Negate units.
  360. STORE_X2:      MOV    DELTA_X,AX             ;Store units.
  361.                INC    SI                     ;Bump pointer past comma.
  362.                CALL   CK_SIGN                ;Do the same for Y direction.
  363.                SUB    AX,Y_POSITION
  364.                MOV    Y_DIRECTION,1
  365.                JGE    STORE_Y2
  366.                MOV    Y_DIRECTION,-1
  367.                NEG    AX
  368. STORE_Y2:      MOV    DELTA_Y,AX
  369.  
  370. CK_SLOPE:      CALL   CK_PLOT                ;Check if drawing dots.
  371.                CALL   UPDATE_START           ;Check if updating position.
  372.                MOV    AX,DELTA_X
  373.                CMP    AX,DELTA_Y             ;Is slope steep?
  374.                JL     GOT_STEEP              ;If yes, do steep algorithm.
  375.                CALL   EASY                   ;Else, do easy algorithm.
  376.                JMP    SHORT MOVE_END
  377. GOT_STEEP:     CALL   STEEP
  378. MOVE_END:      CALL   UPDATE_END             ;Check if no update.
  379.                RET
  380.  
  381. ;------------------------------------------------------------------;
  382. ; This is Bresenham's Algorithm for drawing a line with slope < 1. ;
  383. ;------------------------------------------------------------------;
  384.  
  385. EASY:          MOV    AX,DELTA_X             ;Get units to plot.
  386.                MOV    COUNT,AX               ;Store in count.
  387.                INC    COUNT                  ;Adjust for initial plot.
  388.                SHR    AX,1                   ;Divide units by two.
  389.                MOV    HALF_X,AX              ;Store.
  390.                MOV    HALF_Y,0               ;Initialize half Y.
  391.                MOV    AX,Y_DIRECTION         ;Retrieve Y direction.
  392.                MOV    DIRECTION,AX           ;Store.
  393.                JMP    SHORT EASY1            ;Already plotted first dot.
  394.  
  395. NEXT_EASY:     MOV    BX,1                   ;One unit to draw.
  396.                CALL   NEXT_DRAW              ;Draw it.
  397. EASY1:         MOV    Y_DIRECTION,0          ;Assume no addition.
  398.                MOV    AX,DELTA_Y             ;Add to delta Y to half Y.
  399.                ADD    AX,HALF_Y
  400.                MOV    HALF_Y,AX              ;Store.
  401.                CMP    AX,HALF_X              ;Is > = half X?
  402.                JLE    LOOP_EASY              ;If no, don't change Y yet.
  403.  
  404.                SUB    AX,DELTA_X             ;Else, update half Y
  405.                MOV    HALF_Y,AX
  406.                MOV    AX,DIRECTION
  407.                MOV    Y_DIRECTION,AX         ;Restore Y direction.
  408.  
  409. LOOP_EASY:     DEC    COUNT                  ;Done all units?
  410.                JNZ    NEXT_EASY              ;If no, do next.
  411.                RET
  412.  
  413. ;--------------------------------------------------------------------;
  414. ; This is Bresenham's Algorithm for drawing a line with slope > = 1. ;
  415. ;--------------------------------------------------------------------;
  416.  
  417. STEEP:         MOV    AX,DELTA_Y             ;Get units to plot.
  418.                MOV    COUNT,AX
  419.                INC    COUNT
  420.                SHR    AX,1
  421.                MOV    HALF_Y,AX              ;Store.
  422.                MOV    HALF_X,0               ;Initialize half X.
  423.                MOV    AX,X_DIRECTION         ;Retrieve X direction.
  424.                MOV    DIRECTION,AX
  425.                JMP    SHORT STEEP1
  426.  
  427. NEXT_STEEP:    MOV    BX,1
  428.                CALL   NEXT_DRAW
  429. STEEP1:        MOV    X_DIRECTION,0          ;Assume no addition.
  430.                MOV    AX,DELTA_X             ;Add delta X to half X.
  431.                ADD    AX,HALF_X
  432.                MOV    HALF_X,AX
  433.                CMP    AX,HALF_Y              ;Is it > = half Y?
  434.                JLE    LOOP_STEEP             ;If no, don't change X yet.
  435.  
  436.                SUB    AX,DELTA_Y             ;Else, update half X.
  437.                MOV    HALF_X,AX
  438.                MOV    AX,DIRECTION
  439.                MOV    X_DIRECTION,AX         ;Restore X direction.
  440.  
  441. LOOP_STEEP:    DEC    COUNT                  ;Done all units?
  442.                JNZ    NEXT_STEEP             ;If no, do next.
  443.                RET
  444.  
  445. ;------------------------------------------;
  446. ; This subroutine checks for signed moves. ;
  447. ;------------------------------------------;
  448.  
  449. CK_SIGN:       XOR    BP,BP                  ;Use BP for flag.
  450.                CMP    BYTE PTR [SI],'+'      ;Plus sign?
  451.                JNZ    CK_MINUS               ;If no, check minus sign.
  452.                INC    SI                     ;Else bump pointer to next byte.
  453.                MOV    BP,1                   ;Flag as positive, relative move.
  454.                JMP    SHORT GET_NUMBER       ;Get the number.
  455.  
  456. CK_MINUS:      CMP    BYTE PTR [SI],'-'      ;Is it minus?
  457.                JNZ    GET_NUMBER             ;If no, get number.
  458.                INC    SI                     ;Else bump pointer to next byte.
  459.                MOV    BP,2                   ;Flag as negative, relative move.
  460.  
  461. GET_NUMBER:    CALL   CK_NUMBER              ;Get the number.
  462.                CMP    BP,2                   ;Is it minus?
  463.                JNZ    CK_ABSOLUTE            ;If no check if absolute.
  464.                NEG    AX                     ;Else, negate number.
  465. CK_ABSOLUTE:   CMP    BP,0                   ;Was it signed?
  466.                JNZ    RELATIVE               ;If yes, relative move.
  467.                CLC                           ;Else, flag as absolute move.
  468.                RET
  469.  
  470. RELATIVE:      STC                           ;Flag a relative move.
  471.                RET
  472.  
  473. ;----------------------------------------------------;
  474. ; This subroutine draws the first dot before moving. ;
  475. ;----------------------------------------------------;
  476.  
  477. CK_PLOT:       CMP    PLOT_FLAG,1            ;Is it a blank move?
  478.                JNZ    END_PLOT               ;If yes, skip.
  479.                MOV    DX,Y_POSITION
  480.                MOV    CX,X_POSITION
  481.                MOV    AL,COLOR
  482.                MOV    AH,0CH                 ;Else, draw dot.
  483.                INT    10H
  484. END_PLOT:      RET
  485.  
  486. ;---------------------------------------------------------;
  487. ; These two subroutines store and, when done drawing,     ;
  488. ; restore the current position if it is a no update draw. ;
  489. ;---------------------------------------------------------;
  490.  
  491. UPDATE_START:  CMP    UPDATE_FLAG,1          ;Are we to update postion?
  492.                JZ     RET_START              ;If yes, skip.
  493.                MOV    AX,X_POSITION          ;Else, store.
  494.                MOV    X_TEMP,AX
  495.                MOV    AX,Y_POSITION
  496.                MOV    Y_TEMP,AX
  497. RET_START:     RET
  498.  
  499. ;----------------------------
  500.  
  501. UPDATE_END:    MOV    PLOT_FLAG,1            ;Restore blank-move flag.
  502.                CMP    UPDATE_FLAG,1          ;Were we to update position?
  503.                JZ     RET_END                ;If yes skip.
  504.                MOV    AX,Y_TEMP              ;Else, restore.
  505.                MOV    Y_POSITION,AX
  506.                MOV    AX,X_TEMP
  507.                MOV    X_POSITION,AX
  508.                MOV    UPDATE_FLAG,1          ;Reset update flag.
  509. RET_END:       RET
  510.  
  511. ;---------------------------------------------------------;
  512. ; This subroutine converts decimal command number to hex. ;
  513. ;---------------------------------------------------------;
  514.  
  515. CK_NUMBER:     XOR    BX,BX                  ;Initialize to zero.
  516. NEXT_NUMBER:   CMP    BYTE PTR [SI],'0'      ;Is it a number?
  517.                JB     END_NUMBER             ;If no, we're done.
  518.                CMP    BYTE PTR [SI],'9'
  519.                JA     END_NUMBER
  520.                LODSB                         ;Get number.
  521.                SUB    AL,30H                 ;Convert to hex.
  522.                MOV    CL,AL
  523.                MOV    AX,10                  ;Shift decimal by ten.
  524.                XOR    DX,DX
  525.                MUL    BX
  526.                MOV    BX,AX                  ;Result in BX.
  527.                XOR    CH,CH
  528.                ADD    BX,CX                  ;Add new number.
  529.                JMP    SHORT NEXT_NUMBER      ;Get next number.
  530.  
  531. END_NUMBER:    MOV    AX,BX                  ;Return with number in AX.
  532.                RET
  533.  
  534. ;---------------------------------------------------;
  535. ; This subroutine floods the screen with a pattern. ;
  536. ;---------------------------------------------------;
  537.  
  538. CLS:           PUSH   DS                     ;Save data segment.
  539.                CALL   CK_NUMBER              ;Get pattern.
  540.                XOR    BX,BX                  ;Offset zero.
  541.                MOV    CX,0B800H              ;Point to screen buffer.
  542.                MOV    DS,CX
  543.                MOV    DX,2                   ;Two scan line banks.
  544. NEXT_PATTERN:  MOV    CX,2000H               ;One bank.
  545. WRITE_PATTERN: MOV    [BX],AL                ;Store byte.
  546.                INC    BX                     ;Bump offset.
  547.                LOOP   WRITE_PATTERN          ;Next byte.
  548.                ROR    AL,1                   ;Rotate two bytes right.
  549.                ROR    AL,1
  550.                DEC    DX                     ;Done second bank?
  551.                JNZ    NEXT_PATTERN           ;If no, do it now.
  552.                POP    DS                     ;Restore data segment.
  553.                RET
  554.  
  555. ;-------------------------------------------------------------------------;
  556. ; This subroutine paints the first run and then calls the recursive fill. ;
  557. ;-------------------------------------------------------------------------;
  558.  
  559. PAINT:         CALL   CK_NUMBER              ;Get fill color.
  560.                CMP    AL,MAX_COLOR           ;In range?
  561.                JA     END_PAINT              ;If no, exit.
  562.                MOV    NEW_COLOR,AL           ;Else, store.
  563.                INC    SI                     ;Bump pointer past comma.
  564.                CALL   CK_NUMBER              ;Get border color.
  565.                CMP    AL,MAX_COLOR           ;In range?
  566.                JA     END_PAINT              ;If no, exit.
  567.                MOV    BORDER,AL              ;Else, store.
  568.  
  569.                MOV    DX,Y_POSITION          ;Get current coordinates.
  570.                MOV    CX,X_POSITION
  571.                CALL   READ_DOT               ;Is it on screen?
  572.                JC     END_PAINT              ;If no, exit.
  573.                CMP    AL,BORDER              ;Is it border color?
  574.                JZ     END_PAINT              ;If yes, exit.
  575.  
  576.                MOV    BX,CX                  ;Store X.
  577. START_LEFT:    DEC    CX                     ;Look to the left.
  578.                CALL   READ_DOT               ;Is it on screen?
  579.                JC     END_LEFT               ;If no, done.
  580.                CMP    AL,BORDER              ;Is it border?
  581.                JZ     END_LEFT               ;If yes, done.
  582.                MOV    BX,CX                  ;Else, update X.
  583.                JMP    SHORT START_LEFT       ;Get next dot to left.
  584. END_LEFT:      MOV    LEFT_X,BX              ;Store left start of run.
  585.                PUSH   BX                     ;Store for next call.
  586.  
  587.                MOV    CX,X_POSITION          ;Retrieve X again.
  588.                MOV    BX,CX                  ;Store X.
  589. START_RIGHT:   INC    CX                     ;Look right.
  590.                CALL   READ_DOT               ;Is it on screen?
  591.                JC     END_RIGHT              ;If no, done.
  592.                CMP    AL,BORDER              ;Is it border?
  593.                JZ     END_RIGHT              ;If yes, done.
  594.                MOV    BX,CX                  ;Else, update X.
  595.                JMP    SHORT START_RIGHT      ;Get next dot right.
  596. END_RIGHT:     MOV    RIGHT_X,BX             ;Store right end of run.
  597.                PUSH   BX                     ;Store for next call.
  598.  
  599.                SUB    BX,LEFT_X              ;Get length of run.
  600.                INC    BX
  601.                MOV    CX,LEFT_X              ;Retrieve start of run.
  602. FILL_START:    MOV    AL,NEW_COLOR           ;Retrieve fill color.
  603.                MOV    AH,0CH                 ;Write dot.
  604.                INT    10H
  605.                INC    CX                     ;Next dot.
  606.                DEC    BX                     ;Done?
  607.                JNZ    FILL_START             ;If no, next dot.
  608.  
  609.                PUSH   DX                     ;Store Y.
  610.                DEC    DX                     ;Look up.
  611.                CALL   FILL                   ;And fill shadow.
  612.                POP    DX                     ;Restore Y.
  613.                INC    DX                     ;Look down.
  614.                POP    AX                     ;Retrieve end of run.
  615.                MOV    RIGHT_X,AX
  616.                POP    AX                     ;Retrieve start of run.
  617.                MOV    LEFT_X,AX
  618.                CALL   FILL                   ;Fill shadow.
  619.  
  620. END_PAINT:     RET
  621.  
  622. ;------------------------------------------;
  623. ; This subroutine does the recursive fill. ;
  624. ;------------------------------------------;
  625.  
  626. FILL:          MOV    CX,LEFT_X              ;Retrieve left start.
  627.                MOV    NEXT_LEFT,CX           ;Store as next start.
  628.  
  629. NEXT_FILL:     MOV    CX,NEXT_LEFT
  630.                CALL   READ_DOT               ;Is it on screen?
  631.                JNC    AROUND                 ;If no, done.
  632.                JMP    END_FILL
  633. AROUND:        CMP    AL,BORDER              ;Is it border?
  634.                JZ     CK_NEXTLEFT            ;If yes, look right for start.
  635.                CMP    AL,NEW_COLOR           ;Is it already done?
  636.                JZ     CK_NEXTLEFT            ;If yes, check next left.
  637.  
  638.                MOV    NEXT_RIGHT,CX          ;Store as next right.
  639.                MOV    BX,CX
  640. CK_LEFT:       DEC    CX                     ;Look left.
  641.                CALL   READ_DOT
  642.                JC     END_CK_LEFT            ;Need to be filled?
  643.                CMP    AL,BORDER
  644.                JZ     END_CK_LEFT
  645.                MOV    BX,CX                  ;If yes, update start and
  646.                JMP    SHORT CK_LEFT          ; get next left.
  647. END_CK_LEFT:   MOV    NEXT_LEFT,BX           ;Else, store next left.
  648.                JMP    SHORT CK_RANGE
  649.  
  650. CK_NEXTLEFT:   INC    CX                     ;Look right.
  651. CK_RIGHT_X:    CMP    CX,RIGHT_X             ;Past end of parent run?
  652.                JG     END_NEXTLEFT           ;If yes, done.
  653.                CALL   READ_DOT               ;Does it need filling?
  654.                JC     END_NEXTLEFT
  655.                CMP    AL,NEW_COLOR
  656.                JZ     GET_LEFT
  657.                CMP    AL,BORDER
  658.                JNZ    END_NEXTLEFT
  659.  
  660. GET_LEFT:      INC    CX                     ;If no, look right.
  661.                JMP    SHORT CK_RIGHT_X
  662. END_NEXTLEFT:  MOV    NEXT_LEFT,CX           ;Else, store as new left.
  663.                MOV    NEXT_RIGHT,CX          ;And right.
  664.  
  665. CK_RANGE:      MOV    BX,NEXT_LEFT           ;Is next left past right?
  666.                CMP    BX,RIGHT_X             ;If yes, done.
  667.                JLE    FIND_RIGHT
  668.                JMP    END_FILL
  669.  
  670. FIND_RIGHT:    MOV    BX,NEXT_RIGHT
  671.                MOV    CX,BX
  672. CK_RIGHT:      INC    CX                     ;Look right and find end of run.
  673.                CALL   READ_DOT
  674.                JC     END_CK_RIGHT
  675.                CMP    AL,BORDER
  676.                JZ     END_CK_RIGHT
  677. GET_RIGHT:     MOV    BX,CX
  678.                JMP    SHORT CK_RIGHT
  679. END_CK_RIGHT:  MOV    NEXT_RIGHT,BX          ;Store as next right.
  680.  
  681.                MOV    CX,NEXT_LEFT           ;Get length of run.
  682.                SUB    BX,CX
  683.                INC    BX
  684. FILL_RUN:      MOV    AL,NEW_COLOR           ;And fill with new color.
  685.                MOV    AH,0CH
  686.                INT    10H
  687.                INC    CX
  688.                DEC    BX
  689.                JNZ    FILL_RUN
  690.  
  691. RECURSIVE:     PUSH   LEFT_X                 ;Store all variables on stack.
  692.                PUSH   RIGHT_X
  693.                MOV    CX,NEXT_LEFT
  694.                PUSH   CX
  695.                MOV    LEFT_X,CX
  696.                MOV    CX,NEXT_RIGHT
  697.                PUSH   CX
  698.                MOV    RIGHT_X,CX
  699.                PUSH   DX
  700.                DEC    DX                     ;Look up.
  701.                CALL   FILL                   ;And call on self for shadow.
  702.  
  703.                POP    DX                     ;Retrieve Y, next left
  704.                POP    CX                     ; and next right.
  705.                MOV    RIGHT_X,CX
  706.                MOV    NEXT_RIGHT,CX
  707.                POP    AX
  708.                MOV    LEFT_X,AX
  709.                MOV    NEXT_LEFT,AX
  710.                PUSH   CX                     ;Store next right and Y
  711.                PUSH   DX                     ; back on the stack.
  712.                INC    DX                     ;Look down.
  713.                CALL   FILL                   ;And call on self for shadow.
  714.  
  715.                POP    DX                     ;Retrieve all variables.
  716.                POP    CX
  717.                MOV    NEXT_RIGHT,CX
  718.                ADD    CX,2                   ;Skip to next possible next left.
  719.                MOV    NEXT_LEFT,CX
  720.                POP    RIGHT_X                ;Restore rest of variables.
  721.                POP    LEFT_X
  722.  
  723.                CMP    CX,RIGHT_X             ;Looked all the way right?
  724.                JG     END_FILL               ;If yes, done.
  725.                JMP    NEXT_FILL              ;Else, repeat for entire shadow.
  726.  
  727. END_FILL:      RET
  728.  
  729. ;-----------------------------------------------------;
  730. ; This subroutine checks to see if the coordinates    ;
  731. ; are on the screen. If it is, it then reads the dot. ;
  732. ;-----------------------------------------------------;
  733.  
  734. READ_DOT:      CMP    CX,0                   ;Check column boundries.
  735.                JB     OFF_SCREEN
  736.                CMP    CX,X_BOUNDRY
  737.                JA     OFF_SCREEN
  738.  
  739.                CMP    DX,0                   ;Check row boundries.
  740.                JB     OFF_SCREEN
  741.                CMP    DX,Y_BOUNDRY
  742.                JA     OFF_SCREEN
  743.  
  744.                MOV    AH,0DH                 ;Read dot.
  745.                INT    10H
  746.                CLC
  747.                RET                           ;Return with color in AL.
  748.  
  749. OFF_SCREEN:    MOV    AL,-1                  ;Out of bounds.
  750.                STC
  751.                RET
  752.  
  753. BUFFER:
  754.  
  755. CODE ENDS
  756. END  START
  757.