home *** CD-ROM | disk | FTP | other *** search
- ; Draw.asm
-
- CODE SEGMENT ;*************************
- ASSUME CS:CODE,DS:CODE ;* *
- ORG 100H ;* REMEMBER TO EXE2BIN *
- ;* *
- START: JMP BEGINNING ;*************************
-
- COPYRIGHT DB 'Copyright 1987 Ziff-Davis Publishing Co.',1AH
- PROGRAMMER DB 'Michael J. Mefford'
-
- FILE DB 'DRAW.DAT',0
- PARA_FLAG DB 0
- FILE_FLAG DB 0
- POLL_KEY DB 0
-
- X_POSITION DW 319
- Y_POSITION DW 99
- X_BOUNDRY DW 599
- Y_BOUNDRY EQU 199
- X_DIRECTION DW ?
- Y_DIRECTION DW ?
- X_TEMP DW ?
- Y_TEMP DW ?
- DELTA_X DW ?
- DELTA_Y DW ?
- HALF_X DW ?
- HALF_Y DW ?
- COUNT DW ?
- DIRECTION DW ?
-
- COLOR DB 1
- UPDATE_FLAG DB 1
- PLOT_FLAG DB 1
-
- NEW_COLOR DB ?
- MAX_COLOR DB 1
- BORDER DB ?
- LEFT_X DW ?
- RIGHT_X DW ?
- NEXT_LEFT DW ?
- NEXT_RIGHT DW ?
-
- MONOCHROME DB 'Draw requires CGA adapter.$'
-
- ;----------------------------------------------------------;
- ; Exit if attempting to run on a monochrome system. ;
- ; Capitalize command line and check for switch characters. ;
- ;----------------------------------------------------------;
-
- BEGINNING: MOV AX,40H ;Point to BIOS data segment.
- MOV DS,AX
- CMP DS:[63H],3B4H ;Is it a monochrome adapter?
- PUSH CS
- POP DS
- JNZ CK_PARAMETERS ;If no, check parameters.
- MOV DX,OFFSET MONOCHROME ;Else, display error message.
- MOV AH,9
- INT 21H
- INT 20H ;And terminate.
-
- CK_PARAMETERS: CMP BYTE PTR DS:[80H],0 ;Are there any parameters?
- JZ PARAMETERS ;If no, open DRAW.DAT
-
- CAPITALIZE: MOV SI,81H ;Point to parameters.
- NEXT_CAP: LODSB ;Get a byte.
- CMP AL,13 ;Is it carriage return?
- JZ PARAMETERS ;If yes, done here.
- CMP AL,'/' ;Is it switch character?
- JZ SWITCHES ;If yes, check which one.
- CMP AL,'0' ;Is it a possible command?
- JB NEXT_CAP ;If no, get next byte.
- MOV PARA_FLAG,1 ;Else flag that parameter exists.
- CMP AL,'a' ;Is it lower case?
- JB NEXT_CAP ;If no, get next byte.
- AND BYTE PTR [SI-1],5FH ;Else, capitalize.
- JMP SHORT NEXT_CAP ;Next byte.
-
- SWITCHES: CMP AL,'/' ;Is it switch character?
- JNZ GET_SWITCH ;If no, get next byte.
- MOV BYTE PTR [SI-1],0 ;Else create ASCIIZ for DOS.
- GET_SWITCH: LODSB ;Get a byte.
- CMP AL,13 ;Is it carriage return?
- JZ PARAMETERS ;If yes, done here.
- AND AL,5FH ;Else, capitalize.
- CMP AL,'K' ;Is it /K switch?
- JNZ CK_FILE ;If no, check /F.
- MOV POLL_KEY,1 ;Else, flag as no keyboard poll.
- CK_FILE: CMP AL,'F' ;Is it /F?
- JNZ SWITCHES ;If no, get next byte.
- MOV FILE_FLAG,1 ;Else, flag as filespec.
- JMP SHORT SWITCHES ;Get next byte.
-
- ;-----------------------------------------------------------------;
- ; Check to see if parameters exist and if yes check if filespec. ;
- ; If yes, read file into buffer and process by stripping Wordstar ;
- ; high bit, capitalizing, stripping comments and stripping space ;
- ; characters and below. Finish by tacking on a carriage return. ;
- ;-----------------------------------------------------------------;
-
- PARAMETERS: CMP PARA_FLAG,1 ;Are there parameters?
- JZ FILE_NAME ;If yes, check if filespec.
- MOV DX,OFFSET FILE ;Else, point to DRAW.DAT
- JMP SHORT OPEN_FILE ; and open file.
-
- FILE_NAME: CMP FILE_FLAG,1 ;Is it a filespec?
- JNZ READ_COMMAND ;If no, read the command line.
- MOV DX,82H ;Else, point to filespec.
-
- OPEN_FILE: MOV AX,3D00H ;Open file for reading.
- INT 21H
- JC EXIT ;If not found, exit.
-
- MOV BX,AX ;Else, filehandle in BX.
- MOV DX,OFFSET BUFFER ;Read file into buffer.
- MOV CX,0F000H
- MOV AH,3FH
- INT 21H
-
- MOV CX,AX ;File length in CX.
- MOV SI,OFFSET BUFFER ;Initialized SI and DI
- MOV DI,OFFSET BUFFER ; to head of buffer.
-
- FORMAT: LODSB ;Get a byte.
- AND AL,7FH ;Strip Wordstar high bit.
- CMP AL,':' ;Is it comment character?
- JZ STRIP ;If yes, strip comment.
- CMP AL,'a' ;Is it lower case?
- JB CK_CONTROL ;If no, check space and below.
- AND AL,5FH ;Else, capitalize.
- CK_CONTROL: CMP AL,32 ;Is it space or below?
- JBE NEXT_FORMAT ;If yes, don't store.
- STOSB ;Else store the character.
- NEXT_FORMAT: LOOP FORMAT ;Get next byte.
- END_FORMAT: MOV BYTE PTR [DI],13 ;Tack on carriage return as EOF.
- MOV SI,OFFSET BUFFER ;Point to commands.
- JMP SHORT GRAPHICS_MODE ;Change to graphics mode.
-
- NEXT_STRIP: LODSB ;Get a byte.
- AND AL,7FH ;Strip Wordstar high bit.
- CMP AL,10 ;Is it linefeed?
- JZ NEXT_FORMAT ;If yes get next command.
- STRIP: LOOP NEXT_STRIP ;Else, skip and get next byte.
- JMP SHORT END_FORMAT
-
- ;------------------------------------------------;
-
- EXIT: INT 20H ;Terminate.
-
- ;------------------------------------------------;
-
- ;--------------------------;
- ; Change to graphics mode. ;
- ;--------------------------;
-
- READ_COMMAND: MOV SI,82H ;Initialize pointer to commands.
-
- GRAPHICS_MODE: CMP BYTE PTR [SI],'X' ;Low resolution command?
- JNZ HIGH_RES ;If no, high resolution.
- INC SI ;Else, bump pointer past "X".
- PUSH SI ;Save pointer.
- MOV AX,4 ;Change to 320X200 color.
- INT 10H
- MOV X_POSITION,159 ;Change center position.
- MOV X_BOUNDRY,319 ;Change boundry.
- MOV COLOR,3 ;Change default color.
- MOV MAX_COLOR,3
- CALL CK_NUMBER ;Get palette.
- MOV BH,1
- MOV AH,0BH ;Select palette.
- INT 10H
- POP SI ;INT 10h does not preserve SI.
- JMP SHORT NEXT_COMMAND ;Get commands.
-
- HIGH_RES: MOV AX,6 ;640X200 BW.
- PUSH SI ;Preserve SI.
- INT 10H
- POP SI
-
- ;--------------------------------;
- ; This is the command processor. ;
- ;--------------------------------;
-
- NEXT_COMMAND: CMP POLL_KEY,1 ;Should we poll keyboard?
- JZ GET_COMMAND ;If no, skip.
- MOV AH,1 ;Else, check for keystroke
- INT 16H ; via BIOS.
- JNZ EXIT ;If keystroke, exit.
- GET_COMMAND: LODSB ;Else, get a byte.
- CMP AL,13 ;Is it carriage return?
- JBE EXIT ;If yes, we are done.
- CMP AL,32 ;Is it space, comma or semicolon?
- JZ NEXT_COMMAND ;If yes, skip.
- CMP AL,','
- JZ NEXT_COMMAND
- CMP AL,';'
- JZ NEXT_COMMAND
-
- CK_U: CMP AL,'U' ;Is it "U" ?
- JNZ CK_D ;If no, check "D".
- MOV X_DIRECTION,0
- MOV Y_DIRECTION,-1 ;Else, up one.
- JMP DRAW_COMMAND
-
- CK_D: CMP AL,'D' ;Is it "D" ?
- JNZ CK_L ;If no, check "L".
- MOV X_DIRECTION,0
- MOV Y_DIRECTION,1 ;Else, down one.
- JMP DRAW_COMMAND
-
- CK_L: CMP AL,'L' ;Is it "L" ?
- JNZ CK_R ;If no, check "R".
- MOV X_DIRECTION,-1 ;Else left one.
- MOV Y_DIRECTION,0
- JMP DRAW_COMMAND
-
- CK_R: CMP AL,'R' ;Is it "R" ?
- JNZ CK_E ;If no, check "E".
- MOV X_DIRECTION,1 ;Else, right one.
- MOV Y_DIRECTION,0
- JMP DRAW_COMMAND
-
- CK_E: CMP AL,'E' ;Is it "E" ?
- JNZ CK_F ;If no, check "F".
- MOV X_DIRECTION,1 ;Else, right one.
- MOV Y_DIRECTION,-1 ;Up one.
- JMP SHORT DRAW_COMMAND
-
- CK_F: CMP AL,'F' ;Is it "F" ?
- JNZ CK_G ;If no, check "G".
- MOV X_DIRECTION,1 ;Else, right one.
- MOV Y_DIRECTION,1 ;Down one.
- JMP SHORT DRAW_COMMAND
-
- CK_G: CMP AL,'G' ;Is it "G" ?
- JNZ CK_H ;If no, check "H".
- MOV X_DIRECTION,-1 ;Else, left one.
- MOV Y_DIRECTION,1 ;Down one.
- JMP SHORT DRAW_COMMAND
-
- CK_H: CMP AL,'H' ;Is it "H" ?
- JNZ CK_B ;If no, check "B".
- MOV X_DIRECTION,-1 ;Else left one.
- MOV Y_DIRECTION,-1 ;Up one.
- JMP SHORT DRAW_COMMAND
-
- CK_B: CMP AL,'B' ;Is it "B" ?
- JNZ CK_N ;If no, check "N".
- MOV PLOT_FLAG,0 ;Else, flag no plotting.
- JMP SHORT COMMAND_END
-
- CK_N: CMP AL,'N' ;Is it "N" ?
- JNZ CK_C ;If no, check "C".
- MOV UPDATE_FLAG,0 ;Else, flag no update.
- JMP SHORT COMMAND_END
-
- CK_C: CMP AL,'C' ;Is it "C" ?
- JNZ CK_S ;If no, check "S".
- CALL CK_NUMBER ;Else, get color.
- MOV COLOR,AL ;And store.
- JMP SHORT COMMAND_END
-
- CK_S: CMP AL,'S' ;Is it "S" ?
- JNZ CK_M ;If no, check "M".
- CALL CLS
- JMP SHORT COMMAND_END
-
- CK_M: CMP AL,'M' ;Is it "M" ?
- JNZ CK_P ;If no, check "P".
- CALL MOVE ;Else, move coordinates.
- JMP SHORT COMMAND_END
-
- CK_P: CMP AL,'P' ;Is it "P" ?
- JNZ CK_K ;If no, check "K".
- CALL PAINT ;Else, paint.
- JMP SHORT COMMAND_END
-
- CK_K: CMP AL,'K' ;Is it "K" ?
- JNZ COMMAND_END ;If no, get next command.
- MOV POLL_KEY,1 ;Else, flag as no key poll.
- JMP SHORT COMMAND_END
-
- DRAW_COMMAND: CALL DRAW ;Draw the dot.
- CALL UPDATE_END ;Restore coordinates if needed.
- COMMAND_END: JMP NEXT_COMMAND ;Get next command.
-
- ;*************;
- ; Subroutines ;
- ;*************;
-
- ;--------------------------------------------------------;
- ; This subroutine draws a dot if update flag is not set. ;
- ; Otherwise, just the coordinates are changed. ;
- ;--------------------------------------------------------;
-
- DRAW: CALL CK_PLOT ;Check to see if drawing.
- CALL CK_NUMBER ;Get units to move.
- CMP AX,0 ;If zero, exit.
- JZ END_DRAW
- CALL UPDATE_START ;Check if non-update.
-
- NEXT_DRAW: MOV CX,X_DIRECTION ;Add X direction.
- ADD CX,X_POSITION
- CMP CX,0 ;Check boundries.
- JB END_DRAW
-
- UPPER_X: CMP CX,X_BOUNDRY
- JA END_DRAW
- STORE_X: MOV X_POSITION,CX ;Store new X position.
-
- MOV DX,Y_DIRECTION ;Add Y direction.
- ADD DX,Y_POSITION
- CMP DX,0 ;Check boundries.
- JB END_DRAW
-
- UPPER_Y: CMP DX,Y_BOUNDRY
- JA END_DRAW
- STORE_Y: MOV Y_POSITION,DX ;Store new Y position
-
- CMP PLOT_FLAG,1 ;Is it a blank move.
- JNZ LOOP_DRAW ;If yes, skip draw.
-
- PLOT: MOV AL,COLOR ;Else, color in AL.
- MOV AH,0CH ;Write dot.
- INT 10H
-
- LOOP_DRAW: DEC BX ;Draw all units?
- JNZ NEXT_DRAW ;If no, draw next.
- END_DRAW: RET ;Else, return.
-
- ;------------------------------------------------------------------;
- ; This subroutine moves the X,Y coordinates either to new absolute ;
- ; coordinates or relatively according to Bresenham's Algorithm. ;
- ;------------------------------------------------------------------;
-
- MOVE: CALL CK_SIGN ;Is it prefaced with +/- ?
- JNC DO_ABSOLUTE ;If no, absolute move.
- MOV X_DIRECTION,1 ;Else, assume positive.
- CMP BP,2 ;Is it positive move?
- JNZ STORE_X1 ;If yes, store.
- MOV X_DIRECTION,-1 ;Else, negative direction.
- NEG AX ;Negate units.
-
- STORE_X1: MOV DELTA_X,AX ;Store units.
- INC SI ;Bump pointer past comma.
- CALL CK_SIGN ;Do the same for the Y direction.
- MOV Y_DIRECTION,1
- CMP BP,2
- JNZ STORE_Y1
- MOV Y_DIRECTION,-1
- NEG AX
- STORE_Y1: MOV DELTA_Y,AX
- JMP SHORT CK_SLOPE ;Plot the slope.
-
- DO_ABSOLUTE: SUB AX,X_POSITION ;Target X - current position.
- MOV X_DIRECTION,1 ;Assume positive.
- JGE STORE_X2 ;Is it positive?
- MOV X_DIRECTION,-1 ;If no, negative direction.
- NEG AX ;Negate units.
- STORE_X2: MOV DELTA_X,AX ;Store units.
- INC SI ;Bump pointer past comma.
- CALL CK_SIGN ;Do the same for Y direction.
- SUB AX,Y_POSITION
- MOV Y_DIRECTION,1
- JGE STORE_Y2
- MOV Y_DIRECTION,-1
- NEG AX
- STORE_Y2: MOV DELTA_Y,AX
-
- CK_SLOPE: CALL CK_PLOT ;Check if drawing dots.
- CALL UPDATE_START ;Check if updating position.
- MOV AX,DELTA_X
- CMP AX,DELTA_Y ;Is slope steep?
- JL GOT_STEEP ;If yes, do steep algorithm.
- CALL EASY ;Else, do easy algorithm.
- JMP SHORT MOVE_END
- GOT_STEEP: CALL STEEP
- MOVE_END: CALL UPDATE_END ;Check if no update.
- RET
-
- ;------------------------------------------------------------------;
- ; This is Bresenham's Algorithm for drawing a line with slope < 1. ;
- ;------------------------------------------------------------------;
-
- EASY: MOV AX,DELTA_X ;Get units to plot.
- MOV COUNT,AX ;Store in count.
- INC COUNT ;Adjust for initial plot.
- SHR AX,1 ;Divide units by two.
- MOV HALF_X,AX ;Store.
- MOV HALF_Y,0 ;Initialize half Y.
- MOV AX,Y_DIRECTION ;Retrieve Y direction.
- MOV DIRECTION,AX ;Store.
- JMP SHORT EASY1 ;Already plotted first dot.
-
- NEXT_EASY: MOV BX,1 ;One unit to draw.
- CALL NEXT_DRAW ;Draw it.
- EASY1: MOV Y_DIRECTION,0 ;Assume no addition.
- MOV AX,DELTA_Y ;Add to delta Y to half Y.
- ADD AX,HALF_Y
- MOV HALF_Y,AX ;Store.
- CMP AX,HALF_X ;Is > = half X?
- JLE LOOP_EASY ;If no, don't change Y yet.
-
- SUB AX,DELTA_X ;Else, update half Y
- MOV HALF_Y,AX
- MOV AX,DIRECTION
- MOV Y_DIRECTION,AX ;Restore Y direction.
-
- LOOP_EASY: DEC COUNT ;Done all units?
- JNZ NEXT_EASY ;If no, do next.
- RET
-
- ;--------------------------------------------------------------------;
- ; This is Bresenham's Algorithm for drawing a line with slope > = 1. ;
- ;--------------------------------------------------------------------;
-
- STEEP: MOV AX,DELTA_Y ;Get units to plot.
- MOV COUNT,AX
- INC COUNT
- SHR AX,1
- MOV HALF_Y,AX ;Store.
- MOV HALF_X,0 ;Initialize half X.
- MOV AX,X_DIRECTION ;Retrieve X direction.
- MOV DIRECTION,AX
- JMP SHORT STEEP1
-
- NEXT_STEEP: MOV BX,1
- CALL NEXT_DRAW
- STEEP1: MOV X_DIRECTION,0 ;Assume no addition.
- MOV AX,DELTA_X ;Add delta X to half X.
- ADD AX,HALF_X
- MOV HALF_X,AX
- CMP AX,HALF_Y ;Is it > = half Y?
- JLE LOOP_STEEP ;If no, don't change X yet.
-
- SUB AX,DELTA_Y ;Else, update half X.
- MOV HALF_X,AX
- MOV AX,DIRECTION
- MOV X_DIRECTION,AX ;Restore X direction.
-
- LOOP_STEEP: DEC COUNT ;Done all units?
- JNZ NEXT_STEEP ;If no, do next.
- RET
-
- ;------------------------------------------;
- ; This subroutine checks for signed moves. ;
- ;------------------------------------------;
-
- CK_SIGN: XOR BP,BP ;Use BP for flag.
- CMP BYTE PTR [SI],'+' ;Plus sign?
- JNZ CK_MINUS ;If no, check minus sign.
- INC SI ;Else bump pointer to next byte.
- MOV BP,1 ;Flag as positive, relative move.
- JMP SHORT GET_NUMBER ;Get the number.
-
- CK_MINUS: CMP BYTE PTR [SI],'-' ;Is it minus?
- JNZ GET_NUMBER ;If no, get number.
- INC SI ;Else bump pointer to next byte.
- MOV BP,2 ;Flag as negative, relative move.
-
- GET_NUMBER: CALL CK_NUMBER ;Get the number.
- CMP BP,2 ;Is it minus?
- JNZ CK_ABSOLUTE ;If no check if absolute.
- NEG AX ;Else, negate number.
- CK_ABSOLUTE: CMP BP,0 ;Was it signed?
- JNZ RELATIVE ;If yes, relative move.
- CLC ;Else, flag as absolute move.
- RET
-
- RELATIVE: STC ;Flag a relative move.
- RET
-
- ;----------------------------------------------------;
- ; This subroutine draws the first dot before moving. ;
- ;----------------------------------------------------;
-
- CK_PLOT: CMP PLOT_FLAG,1 ;Is it a blank move?
- JNZ END_PLOT ;If yes, skip.
- MOV DX,Y_POSITION
- MOV CX,X_POSITION
- MOV AL,COLOR
- MOV AH,0CH ;Else, draw dot.
- INT 10H
- END_PLOT: RET
-
- ;---------------------------------------------------------;
- ; These two subroutines store and, when done drawing, ;
- ; restore the current position if it is a no update draw. ;
- ;---------------------------------------------------------;
-
- UPDATE_START: CMP UPDATE_FLAG,1 ;Are we to update postion?
- JZ RET_START ;If yes, skip.
- MOV AX,X_POSITION ;Else, store.
- MOV X_TEMP,AX
- MOV AX,Y_POSITION
- MOV Y_TEMP,AX
- RET_START: RET
-
- ;----------------------------
-
- UPDATE_END: MOV PLOT_FLAG,1 ;Restore blank-move flag.
- CMP UPDATE_FLAG,1 ;Were we to update position?
- JZ RET_END ;If yes skip.
- MOV AX,Y_TEMP ;Else, restore.
- MOV Y_POSITION,AX
- MOV AX,X_TEMP
- MOV X_POSITION,AX
- MOV UPDATE_FLAG,1 ;Reset update flag.
- RET_END: RET
-
- ;---------------------------------------------------------;
- ; This subroutine converts decimal command number to hex. ;
- ;---------------------------------------------------------;
-
- CK_NUMBER: XOR BX,BX ;Initialize to zero.
- NEXT_NUMBER: CMP BYTE PTR [SI],'0' ;Is it a number?
- JB END_NUMBER ;If no, we're done.
- CMP BYTE PTR [SI],'9'
- JA END_NUMBER
- LODSB ;Get number.
- SUB AL,30H ;Convert to hex.
- MOV CL,AL
- MOV AX,10 ;Shift decimal by ten.
- XOR DX,DX
- MUL BX
- MOV BX,AX ;Result in BX.
- XOR CH,CH
- ADD BX,CX ;Add new number.
- JMP SHORT NEXT_NUMBER ;Get next number.
-
- END_NUMBER: MOV AX,BX ;Return with number in AX.
- RET
-
- ;---------------------------------------------------;
- ; This subroutine floods the screen with a pattern. ;
- ;---------------------------------------------------;
-
- CLS: PUSH DS ;Save data segment.
- CALL CK_NUMBER ;Get pattern.
- XOR BX,BX ;Offset zero.
- MOV CX,0B800H ;Point to screen buffer.
- MOV DS,CX
- MOV DX,2 ;Two scan line banks.
- NEXT_PATTERN: MOV CX,2000H ;One bank.
- WRITE_PATTERN: MOV [BX],AL ;Store byte.
- INC BX ;Bump offset.
- LOOP WRITE_PATTERN ;Next byte.
- ROR AL,1 ;Rotate two bytes right.
- ROR AL,1
- DEC DX ;Done second bank?
- JNZ NEXT_PATTERN ;If no, do it now.
- POP DS ;Restore data segment.
- RET
-
- ;-------------------------------------------------------------------------;
- ; This subroutine paints the first run and then calls the recursive fill. ;
- ;-------------------------------------------------------------------------;
-
- PAINT: CALL CK_NUMBER ;Get fill color.
- CMP AL,MAX_COLOR ;In range?
- JA END_PAINT ;If no, exit.
- MOV NEW_COLOR,AL ;Else, store.
- INC SI ;Bump pointer past comma.
- CALL CK_NUMBER ;Get border color.
- CMP AL,MAX_COLOR ;In range?
- JA END_PAINT ;If no, exit.
- MOV BORDER,AL ;Else, store.
-
- MOV DX,Y_POSITION ;Get current coordinates.
- MOV CX,X_POSITION
- CALL READ_DOT ;Is it on screen?
- JC END_PAINT ;If no, exit.
- CMP AL,BORDER ;Is it border color?
- JZ END_PAINT ;If yes, exit.
-
- MOV BX,CX ;Store X.
- START_LEFT: DEC CX ;Look to the left.
- CALL READ_DOT ;Is it on screen?
- JC END_LEFT ;If no, done.
- CMP AL,BORDER ;Is it border?
- JZ END_LEFT ;If yes, done.
- MOV BX,CX ;Else, update X.
- JMP SHORT START_LEFT ;Get next dot to left.
- END_LEFT: MOV LEFT_X,BX ;Store left start of run.
- PUSH BX ;Store for next call.
-
- MOV CX,X_POSITION ;Retrieve X again.
- MOV BX,CX ;Store X.
- START_RIGHT: INC CX ;Look right.
- CALL READ_DOT ;Is it on screen?
- JC END_RIGHT ;If no, done.
- CMP AL,BORDER ;Is it border?
- JZ END_RIGHT ;If yes, done.
- MOV BX,CX ;Else, update X.
- JMP SHORT START_RIGHT ;Get next dot right.
- END_RIGHT: MOV RIGHT_X,BX ;Store right end of run.
- PUSH BX ;Store for next call.
-
- SUB BX,LEFT_X ;Get length of run.
- INC BX
- MOV CX,LEFT_X ;Retrieve start of run.
- FILL_START: MOV AL,NEW_COLOR ;Retrieve fill color.
- MOV AH,0CH ;Write dot.
- INT 10H
- INC CX ;Next dot.
- DEC BX ;Done?
- JNZ FILL_START ;If no, next dot.
-
- PUSH DX ;Store Y.
- DEC DX ;Look up.
- CALL FILL ;And fill shadow.
- POP DX ;Restore Y.
- INC DX ;Look down.
- POP AX ;Retrieve end of run.
- MOV RIGHT_X,AX
- POP AX ;Retrieve start of run.
- MOV LEFT_X,AX
- CALL FILL ;Fill shadow.
-
- END_PAINT: RET
-
- ;------------------------------------------;
- ; This subroutine does the recursive fill. ;
- ;------------------------------------------;
-
- FILL: MOV CX,LEFT_X ;Retrieve left start.
- MOV NEXT_LEFT,CX ;Store as next start.
-
- NEXT_FILL: MOV CX,NEXT_LEFT
- CALL READ_DOT ;Is it on screen?
- JNC AROUND ;If no, done.
- JMP END_FILL
- AROUND: CMP AL,BORDER ;Is it border?
- JZ CK_NEXTLEFT ;If yes, look right for start.
- CMP AL,NEW_COLOR ;Is it already done?
- JZ CK_NEXTLEFT ;If yes, check next left.
-
- MOV NEXT_RIGHT,CX ;Store as next right.
- MOV BX,CX
- CK_LEFT: DEC CX ;Look left.
- CALL READ_DOT
- JC END_CK_LEFT ;Need to be filled?
- CMP AL,BORDER
- JZ END_CK_LEFT
- MOV BX,CX ;If yes, update start and
- JMP SHORT CK_LEFT ; get next left.
- END_CK_LEFT: MOV NEXT_LEFT,BX ;Else, store next left.
- JMP SHORT CK_RANGE
-
- CK_NEXTLEFT: INC CX ;Look right.
- CK_RIGHT_X: CMP CX,RIGHT_X ;Past end of parent run?
- JG END_NEXTLEFT ;If yes, done.
- CALL READ_DOT ;Does it need filling?
- JC END_NEXTLEFT
- CMP AL,NEW_COLOR
- JZ GET_LEFT
- CMP AL,BORDER
- JNZ END_NEXTLEFT
-
- GET_LEFT: INC CX ;If no, look right.
- JMP SHORT CK_RIGHT_X
- END_NEXTLEFT: MOV NEXT_LEFT,CX ;Else, store as new left.
- MOV NEXT_RIGHT,CX ;And right.
-
- CK_RANGE: MOV BX,NEXT_LEFT ;Is next left past right?
- CMP BX,RIGHT_X ;If yes, done.
- JLE FIND_RIGHT
- JMP END_FILL
-
- FIND_RIGHT: MOV BX,NEXT_RIGHT
- MOV CX,BX
- CK_RIGHT: INC CX ;Look right and find end of run.
- CALL READ_DOT
- JC END_CK_RIGHT
- CMP AL,BORDER
- JZ END_CK_RIGHT
- GET_RIGHT: MOV BX,CX
- JMP SHORT CK_RIGHT
- END_CK_RIGHT: MOV NEXT_RIGHT,BX ;Store as next right.
-
- MOV CX,NEXT_LEFT ;Get length of run.
- SUB BX,CX
- INC BX
- FILL_RUN: MOV AL,NEW_COLOR ;And fill with new color.
- MOV AH,0CH
- INT 10H
- INC CX
- DEC BX
- JNZ FILL_RUN
-
- RECURSIVE: PUSH LEFT_X ;Store all variables on stack.
- PUSH RIGHT_X
- MOV CX,NEXT_LEFT
- PUSH CX
- MOV LEFT_X,CX
- MOV CX,NEXT_RIGHT
- PUSH CX
- MOV RIGHT_X,CX
- PUSH DX
- DEC DX ;Look up.
- CALL FILL ;And call on self for shadow.
-
- POP DX ;Retrieve Y, next left
- POP CX ; and next right.
- MOV RIGHT_X,CX
- MOV NEXT_RIGHT,CX
- POP AX
- MOV LEFT_X,AX
- MOV NEXT_LEFT,AX
- PUSH CX ;Store next right and Y
- PUSH DX ; back on the stack.
- INC DX ;Look down.
- CALL FILL ;And call on self for shadow.
-
- POP DX ;Retrieve all variables.
- POP CX
- MOV NEXT_RIGHT,CX
- ADD CX,2 ;Skip to next possible next left.
- MOV NEXT_LEFT,CX
- POP RIGHT_X ;Restore rest of variables.
- POP LEFT_X
-
- CMP CX,RIGHT_X ;Looked all the way right?
- JG END_FILL ;If yes, done.
- JMP NEXT_FILL ;Else, repeat for entire shadow.
-
- END_FILL: RET
-
- ;-----------------------------------------------------;
- ; This subroutine checks to see if the coordinates ;
- ; are on the screen. If it is, it then reads the dot. ;
- ;-----------------------------------------------------;
-
- READ_DOT: CMP CX,0 ;Check column boundries.
- JB OFF_SCREEN
- CMP CX,X_BOUNDRY
- JA OFF_SCREEN
-
- CMP DX,0 ;Check row boundries.
- JB OFF_SCREEN
- CMP DX,Y_BOUNDRY
- JA OFF_SCREEN
-
- MOV AH,0DH ;Read dot.
- INT 10H
- CLC
- RET ;Return with color in AL.
-
- OFF_SCREEN: MOV AL,-1 ;Out of bounds.
- STC
- RET
-
- BUFFER:
-
- CODE ENDS
- END START