mirror of
https://github.com/DOS-History/Paterson-Listings.git
synced 2026-08-13 05:19:35 -07:00
Added printed file version of PAINT.ASM
This commit is contained in:
committed by
Yufeng Gao
parent
6f32a3d141
commit
83ded87591
@@ -0,0 +1,341 @@
|
||||
00100 TITLE PAINT graphics runtime routine
|
||||
00200
|
||||
00300
|
||||
00400 DATA SEGMENT WORD PUBLIC 'RT_DATA'
|
||||
00500
|
||||
00600 EXTRN $M_CUR:BYTE, $M_SAVE:BYTE
|
||||
00700 EXTRN $O_CUR:WORD, $O_SAVE:WORD
|
||||
00800 EXTRN $$SFPT:WORD
|
||||
00900
|
||||
01000 C_SCAN DW ? ;scan count
|
||||
01100 C_SKIP DW ? ;skip count
|
||||
01200 DIRECT DB ? ;paint direction
|
||||
01300 F_L_PAI DB ? ;flag for left already painted
|
||||
01400 F_R_PAI DB ? ;flag for right already painted
|
||||
01500 LEN_Q DW ? ;current queue length
|
||||
01600 P_DEQ DW ? ;pointer to dequeue entry
|
||||
01700 P_ENQ DW ? ;pointer to enqueue entry
|
||||
01800 P_END_Q DW ? ;pointer to end of queue area
|
||||
01900 TOTAL_Q DW ? ;total size available for queue
|
||||
02000
|
||||
02100 DATA ENDS
|
||||
02200
|
||||
02300
|
||||
02400 CONST SEGMENT WORD PUBLIC 'RT_DATA'
|
||||
02500
|
||||
02600 SIZE_ENT EQU 6 ;queue entry size
|
||||
02700
|
||||
02800 SIZE_PAI EQU 4*1024 ;minimal size required to be
|
||||
02900 ;available in string space
|
||||
03000 ;for PAINT queue, otherwise
|
||||
03100 ;a major garbage collection
|
||||
03200 ;is performed
|
||||
03300
|
||||
03400 CONST ENDS
|
||||
03500
|
||||
03600 DGROUP GROUP CONST,DATA
|
||||
03700 PAGE
|
||||
03800
|
||||
03900
|
||||
04000 CODE SEGMENT WORD PUBLIC 'CODE'
|
||||
04100
|
||||
04200
|
||||
04300 PUBLIC $PAI
|
||||
04400
|
||||
04500 EXTRN $ERC_FC:NEAR, $ERC_OM:NEAR
|
||||
04600 EXTRN $LEFTC:NEAR
|
||||
04700 EXTRN $MAPXYC:NEAR
|
||||
04800 EXTRN $PARMS:NEAR, $PNTINI:NEAR
|
||||
04900 EXTRN $SAVREG:NEAR, $SCANL:NEAR, $SCANR:NEAR
|
||||
05000 EXTRN $TDOWNC:NEAR, $TUPC:NEAR
|
||||
05100 EXTRN $$MAG:NEAR
|
||||
05200
|
||||
05300
|
||||
05400 ASSUME CS:CODE, DS:DGROUP, ES:DGROUP
|
||||
05500 PAGE
|
||||
05600
|
||||
05700
|
||||
05800 ;** $PAI - process the PAINT statement
|
||||
05900 ;
|
||||
06000 ; Inputs:
|
||||
06100 ; BX = x coordinate of point in area to be painted
|
||||
06200 ; DX = y coordinate of point in area to be painted
|
||||
06300 ; CX = paint color specification
|
||||
06400 ; AX = border color specification
|
||||
06500 ; Function:
|
||||
06600 ; Paint the figure containing the specified point and with
|
||||
06700 ; edges of the specified boundary color in the specified
|
||||
06800 ; paint color.
|
||||
06900 ; The algorithm used is copied from ADVGRP.MAC in the
|
||||
07000 ; Interpreter; a queue is used to save the skipped area
|
||||
07100 ; boundaries. The space for the queue is obtained from the
|
||||
07200 ; compiler runtime string space.
|
||||
07300 ; Outouts:
|
||||
07400 ; none
|
||||
07500 ; Registers:
|
||||
07600 ; none
|
||||
07700
|
||||
07800 $PAI:
|
||||
07900 CALL $SAVREG ;save state
|
||||
08000 XCHG AX,BP ;save border color spec
|
||||
08100 CALL $PARMS ;process coords and paint color
|
||||
08200 XCHG AX,BP ;retrieve border color spec
|
||||
08300 MOV BP,CX ;save scaled x coord
|
||||
08400 CALL $PNTINI ;initialize for paint
|
||||
08500 JC PAI_ERROR ;error if invalid border color
|
||||
08600 MOV CX,BP ;retrieve x coord
|
||||
08700 CALL $MAPXYC ;map coords to screen position
|
||||
08800 MOV SI,[$$SFPT] ;fetch ptr to next string area
|
||||
08900 LODSW ;AX = size of area
|
||||
09000 CMP AX,SIZE_PAI ;will size be adequate ?
|
||||
09100 JNB PAI_SIZE_SET ;probably, continue
|
||||
09200 CALL $$MAG ;maybe not, grabage collect
|
||||
09300 MOV SI,[$$SFPT]
|
||||
09400 LODSW ;now get ptr to area and size
|
||||
09500 PAI_SIZE_SET:
|
||||
09600 DEC AX ;calculate # bytes left
|
||||
09700 MOV [TOTAL_Q],AX ;save as total queue size
|
||||
09800 MOV [P_ENQ],SI
|
||||
09900 MOV [P_DEQ],SI ;initialize queue ptrs
|
||||
10000 ADD AX,SI
|
||||
10100 SUB AX,SIZE_ENT-1
|
||||
10200 MOV [P_END_Q],AX ;save ptr to end of queue
|
||||
10300 MOV [LEN_Q],0 ;initialize current queue len
|
||||
10400 MOV DX,1 ;init skip cnt for skip no bord
|
||||
10500 CALL PAI_SCAN_R ;scan right from initial pos
|
||||
10600 JZ PAI_RET ;we started on border, return
|
||||
10700 PUSH BX ;save right scan count
|
||||
10800 CALL PAI_SCAN_L ;scan left from initial pos
|
||||
10900 POP DX
|
||||
11000 ADD DX,BX ;DX = left count + right count
|
||||
11100 MOV AL,64 ;set up entry for going down
|
||||
11200 CALL PAI_ENTRY ;enqueue entry
|
||||
11300 MOV AL,192 ;init for painting up
|
||||
11400 JMP SHORT PAI_START
|
||||
11401 PAI_RET:
|
||||
11421 RET
|
||||
11441 PAI_ERROR:
|
||||
11461 JMP $ERC_FC ;illegal function call
|
||||
11500 ;
|
||||
11600 ; Main paint loop
|
||||
11700 ;
|
||||
11800 PAI_LOOP:
|
||||
11900 CALL PAI_DEQ ;fetch next entry from queue
|
||||
12000 MOV [$O_CUR],BX
|
||||
12100 MOV [$M_CUR],CL ;and set as current state
|
||||
12200 PAI_START:
|
||||
12300 MOV [DIRECT],AL ;save direction
|
||||
12400 OR AL,AL
|
||||
12500 JZ PAI_RET ;zero direction, end of queue
|
||||
12600 JNS PAI_DOWN ;positive direction, down
|
||||
12700 CALL $TUPC ;negative direction, test up
|
||||
12800 JMP SHORT PAI_CHECK
|
||||
12900 PAI_DOWN:
|
||||
13000 CALL $TDOWNC ;test down
|
||||
13100 PAI_CHECK: ;salary
|
||||
13200 JC PAI_LOOP ;screen edge, get next entry
|
||||
13300 CALL PAI_SCAN_R ;scan right up to skip cnt bord
|
||||
13400 JZ PAI_LOOP ;nothing painted, get next ent
|
||||
13500 CALL PAI_SCAN_L ;now scan left
|
||||
13600 MOV DX,BX ;save left scan count
|
||||
13700 OR AL,AL ;was line already painted ?
|
||||
13800 JZ PAI_ALREADY ;yes, no overhang
|
||||
13900 CMP BX,1 ;is left scan count .GT. 1 ?
|
||||
14000 JLE PAI_ALREADY ;no, continue
|
||||
14100 MOV AL,[DIRECT]
|
||||
14200 NEG AL ;go in opposite direction
|
||||
14300 CALL PAI_ENTRY ;put current state in queue
|
||||
14400 PAI_ALREADY:
|
||||
14500 ADD DX,[C_SCAN] ;DX = right count + left count
|
||||
14700 MOV AL,[F_L_PAI]
|
||||
14800 OR AL,[F_R_PAI]
|
||||
14900 JZ PAI_SAVE ;don't enqueue if already paint
|
||||
15000 MOV AL,[DIRECT]
|
||||
15100 CALL PAI_ENTRY ;enqueue entry
|
||||
15200 ;
|
||||
15300 ; Set current location back to end of right scan
|
||||
15400 ;
|
||||
15500 PAI_SAVE: ;drugstore
|
||||
15600 MOV AX,[$O_SAVE]
|
||||
15700 MOV [$O_CUR],AX
|
||||
15800 MOV AL,[$M_SAVE]
|
||||
15900 MOV [$M_CUR],AL
|
||||
16000 PAI_OH_L:
|
||||
16100 MOV AX,[C_SKIP]
|
||||
16200 SUB AX,[C_SCAN] ;any more border to skip ?
|
||||
16300 JZ PAI_LOOP ;no, end of this scan
|
||||
16400 JC PAI_OH_R ;yes, but right overhang
|
||||
16500 XCHG AX,DX ;yes, scan right dif of counts
|
||||
16600 CALL PAI_SCAN_R
|
||||
16700 JZ PAI_LOOP ;no more points, proceed
|
||||
16800 OR AL,AL
|
||||
16900 JZ PAI_OH_L ;ignore if line already painted
|
||||
17000 MOV DX,BX ;save right scan count
|
||||
17100 MOV BX,[$O_SAVE]
|
||||
17200 MOV CL,[$M_SAVE]
|
||||
17300 MOV AL,[DIRECT]
|
||||
17400 CALL PAI_ENQ ;enqueue entry for right scanpt
|
||||
17500 JMP PAI_OH_L ;contiue until skipcount .LE. 0
|
||||
17600 PAI_OH_R:
|
||||
17650 NEG AX ;make new skipcount positive
|
||||
17700 CMP AX,1 ;is (skipcnt-scancnt) .LT. -1 ?
|
||||
17800 JLE PAI_LOOP_REACH ;no,overhang too small to enter
|
||||
18000 DEC AX
|
||||
18050 MOV CX,AX ;set up count
|
||||
18100 XCHG AX,DX ;save skipcount
|
||||
18200 PAI_BACK: ;i.o.u.
|
||||
18300 CALL $LEFTC
|
||||
18400 LOOP PAI_BACK ;move left -(skipcnt-scancnt)-1
|
||||
18500 MOV AL,[DIRECT] ;no, make entry in opposite dir
|
||||
18600 NEG AL
|
||||
18700 CALL PAI_ENTRY ;enqueue entry
|
||||
18750 PAI_LOOP_REACH:
|
||||
18800 JMP PAI_LOOP ;go to next entry
|
||||
19300 PAGE
|
||||
19400
|
||||
19500
|
||||
19600 ;** PAI_DEQ - remove next entry from queue and return in registers
|
||||
19700 ;
|
||||
19800 ; Inputs:
|
||||
19900 ; none
|
||||
20000 ; Outputs:
|
||||
20100 ; AL = direction flag (0 if queue is empty)
|
||||
20200 ; BX = cursor screen offset
|
||||
20300 ; CL = screen mask
|
||||
20400 ; DX = scan count
|
||||
20500 ; Registers:
|
||||
20600 ; AH,CH,SI
|
||||
20700
|
||||
20800 PAI_DEQ:
|
||||
20900 XOR AL,AL ;set no entry flag
|
||||
21000 SUB [LEN_Q],SIZE_ENT ;update current queue size
|
||||
21100 JC PAI_DEQ_RET ;return flag if queue empty
|
||||
21200 MOV SI,[P_DEQ] ;fetch ptr to current entry
|
||||
21300 LODSW
|
||||
21400 XCHG AX,BX
|
||||
21500 LODSW
|
||||
21600 XCHG AX,CX
|
||||
21700 LODSW
|
||||
21800 XCHG AX,DX
|
||||
21900 MOV AL,CH ;fetch entry and set into regs
|
||||
22000 CMP SI,[P_END_Q] ;are we at end of queue area ?
|
||||
22100 JB PAI_DEQ_SET ;no, continue
|
||||
22200 MOV SI,[$$SFPT] ;yes, wrap around
|
||||
22300 INC SI
|
||||
22400 INC SI
|
||||
22500 PAI_DEQ_SET:
|
||||
22600 MOV [P_DEQ],SI ;update ptr to next entry
|
||||
22700 PAI_DEQ_RET:
|
||||
22800 RET
|
||||
22900
|
||||
23000
|
||||
23100 ;** PAI_ENTRY - enqueue current scan state
|
||||
23200 ;
|
||||
23300 ; Inputs:
|
||||
23400 ; AL = direction flag
|
||||
23500 ; DX = scan count
|
||||
23600 ; $$SVRS set since queue overflow is detected
|
||||
23700 ; Outputs:
|
||||
23800 ; none
|
||||
23900 ; Registers:
|
||||
24000 ; AX,BX,CX,DI
|
||||
24100
|
||||
24200 PAI_ENTRY:
|
||||
24300 MOV BX,[$O_CUR]
|
||||
24400 MOV CL,[$M_CUR] ;fetch current offset and mask
|
||||
24500 ; now drop into enqueue
|
||||
24600
|
||||
24700
|
||||
24800 ;** PAI_ENQ - place specified entry into next queue location
|
||||
24900 ;
|
||||
25000 ; Inputs:
|
||||
25100 ; AL = direction flag
|
||||
25200 ; BX = cursor screen offset
|
||||
25300 ; CL = screen mask
|
||||
25400 ; DX = scan count
|
||||
25500 ; Outputs:
|
||||
25600 ; none
|
||||
25700 ; Registers:
|
||||
25800 ; AX,CH,DI
|
||||
25900
|
||||
26000 PAI_ENQ:
|
||||
26100 MOV CH,AL
|
||||
26200 MOV AX,[LEN_Q]
|
||||
26300 ADD AX,SIZE_ENT ;update length
|
||||
26400 CMP AX,[TOTAL_Q] ;is queue area filled up ?
|
||||
26500 JNB PAI_ENQ_ERROR ;yes, abort, no more room
|
||||
26600 MOV [LEN_Q],AX
|
||||
26700 MOV DI,[P_ENQ] ;DI = ptr to next avail entry
|
||||
26800 MOV AX,BX
|
||||
26900 STOSW
|
||||
27000 MOV AX,CX
|
||||
27100 STOSW
|
||||
27200 MOV AX,DX
|
||||
27300 STOSW ;enter into queue
|
||||
27400 CMP DI,[P_END_Q] ;are we at end of queue area
|
||||
27500 JB PAI_ENQ_SET ;no, continue
|
||||
27600 MOV DI,[$$SFPT] ;yes, wrap around
|
||||
27700 INC DI
|
||||
27800 INC DI
|
||||
27900 PAI_ENQ_SET:
|
||||
28000 MOV [P_ENQ],DI ;update ptr to next queue entry
|
||||
28100 RET
|
||||
28200 PAI_ENQ_ERROR:
|
||||
28300 JMP $ERC_OM ;out of memory
|
||||
28400
|
||||
28500
|
||||
28600 ;** PAI_SCAN_L - scan left
|
||||
28700 ;
|
||||
28800 ; Inputs:
|
||||
28900 ; DX = skip count
|
||||
29000 ; Function:
|
||||
29100 ; Save state where right scan stopped and reposition to saved
|
||||
29200 ; state, then scan left.
|
||||
29300 ; Outputs:
|
||||
29400 ; AL = already painted flag
|
||||
29500 ; BX = scan count
|
||||
29600 ; Z set if scan count = 0, reset otherwise
|
||||
29700 ; Registers:
|
||||
29800 ; ALL
|
||||
29900
|
||||
30000 PAI_SCAN_L:
|
||||
30100 MOV AX,[$O_CUR]
|
||||
30110 XCHG AX,[$O_SAVE]
|
||||
30120 MOV [$O_CUR],AX
|
||||
30200 MOV AL,[$M_CUR]
|
||||
30400 XCHG AL,[$M_SAVE]
|
||||
30410 MOV [$M_CUR],AL ;xchg current state with saved
|
||||
30500 CALL $SCANL ;scan left
|
||||
30600 MOV AL,CL
|
||||
30700 MOV [F_L_PAI],AL ;save already painted flag
|
||||
30800 OR BX,BX ;set Z accordingly
|
||||
30900 RET
|
||||
31000
|
||||
31100
|
||||
31200 ;** PAI_SCAN_R - scan right
|
||||
31300 ;
|
||||
31400 ; Inputs:
|
||||
31500 ; none
|
||||
31600 ; Function:
|
||||
31700 ; Scan right the specified amount and save state when boundary
|
||||
31800 ; reached.
|
||||
31900 ; Outputs:
|
||||
32000 ; AL = already painted flag
|
||||
32100 ; BX = scan count
|
||||
32150 ; DX = skip count
|
||||
32200 ; Z set if scan count = 0, reset otherwise
|
||||
32300 ; Registers:
|
||||
32400 ; ALL
|
||||
32500
|
||||
32600 PAI_SCAN_R:
|
||||
32700 CALL $SCANR ;scan right specified count
|
||||
32800 MOV [C_SCAN],BX
|
||||
32900 MOV [C_SKIP],DX ;save updated counts
|
||||
33000 MOV AL,CL
|
||||
33100 MOV [F_R_PAI],AL ;save already painted flag
|
||||
33200 OR BX,BX ;set Z accordingly
|
||||
33300 RET
|
||||
33400
|
||||
33500
|
||||
33600 CODE ENDS
|
||||
33700 END
|
||||
Reference in New Issue
Block a user