home *** CD-ROM | disk | FTP | other *** search
- REM > <Graphics$Dir>.Line draw routine for 8 bpp modes
- REM
- REM Version 1.04 ⌐ Jan-Herman Buining (24-May-1991)
- REM
- REM For one byte per pixel screen modes only
- REM
- :
- REM Screen mode, boundaries, size and resolution
- MODE 13 : REM Screen mode
- XShift=2 : REM X pixel shift factor
- YShift=2 : REM Y pixel shift factor
- HSize =1280 : REM Screen width in pixels (bytes)
- VSize =1024 : REM Screen height in pixels (bytes)
- LBound=0 +320 : REM Minimum X >= 0
- RBound=1280-320 : REM Maximum X+1 <= HSize
- BBound=0 +256 : REM Minimum Y >= 0
- TBound=1024-256 : REM Maximum Y+1 <= VSize
- :
- REM Random generator coords resolution in bits
- Random=11 : REM -1024 <= Random <= 1023
- :
- REM Bounding box, lines should clip inside this
- RECTANGLE LBound-1,BBound-1,RBound-LBound+1,TBound-BBound+1
- VDU 24,LBound;BBound;RBound-1;TBound-1;
- :
- PROCAssemble(Start%,End%)
- :
- REM Repeated drawing of random lines until <Escape>
- CALL CallLine
- :
- END
- :
- DEF PROCLine(A%,B%,C%,D%,E%)
- CALL Line
- ENDPROC
- :
- REM +++++ ASSEMBLY +++++
- :
- DEF PROCAssemble(RETURN Code%,RETURN O%)
- LOCAL Opt%,L%,P%,CodeSize%
- :
- REM Size of code
- CodeSize=4<<10
- :
- DIM Code% CodeSize,L% -1
- :
- FOR Opt%=%1100 TO %1110 STEP %0010
- P%=Code%
- O%=Code%
- [OPT Opt%
- ;**********************************************
- ;**********************************************
- ;** Data **
- ;**********************************************
- ;**********************************************
- .ScreenAddress EQUD FNScreenAddress ; Screen base address
- ; Optionally you could choose to store window
- ; clipping (bound) variables in this block
- ;----------------------------------------------
- .RandomSeed1 EQUD RND(TIME) ; Random seed
- .RandomSeed2 EQUD RND(2) ; 33rd bit
- ;**********************************************
- ;**********************************************
- ;** Random coordinates **
- ;**********************************************
- ;**********************************************
- .RandomCoordinates
- STMFD R13!,{R8-R10,R14}
- LDR R8,RandomSeed1
- LDR R9,RandomSeed2
- ;----------------------------------------------
- TST R9,R9,LSR #1 ; Fast random number
- MOVS R10,R8,RRX
- ADC R9,R9,R9
- EOR R10,R10,R8,LSL #12
- EOR R8,R10,R10,LSR #20 ; Random mumber in R8
- MOV R0,R8
- ;----------------------------------------------
- TST R9,R9,LSR #1 ; Fast random number
- MOVS R10,R8,RRX
- ADC R9,R9,R9
- EOR R10,R10,R8,LSL #12
- EOR R8,R10,R10,LSR #20 ; Random mumber in R8
- MOV R1,R8
- ;----------------------------------------------
- TST R9,R9,LSR #1 ; Fast random number
- MOVS R10,R8,RRX
- ADC R9,R9,R9
- EOR R10,R10,R8,LSL #12
- EOR R8,R10,R10,LSR #20 ; Random mumber in R8
- MOV R2,R8
- ;----------------------------------------------
- TST R9,R9,LSR #1 ; Fast random number
- MOVS R10,R8,RRX
- ADC R9,R9,R9
- EOR R10,R10,R8,LSL #12
- EOR R8,R10,R10,LSR #20 ; Random mumber in R8
- MOV R3,R8
- ;----------------------------------------------
- TST R9,R9,LSR #1 ; Fast random number
- MOVS R10,R8,RRX
- ADC R9,R9,R9
- EOR R10,R10,R8,LSL #12
- EOR R8,R10,R10,LSR #20 ; Random mumber in R8
- MOV R4,R8,LSR #24 ; Colour
- ;----------------------------------------------
- STR R8,RandomSeed1
- STR R9,RandomSeed2
- ;----------------------------------------------
- MOV R8,#LBound ; Centre random coordinates
- ADD R8,R8,#RBound ; for neater display
- MOV R8,R8,ASR #1 ; Window X centre
- MOV R9,#BBound
- ADD R9,R9,#TBound
- MOV R9,R9,ASR #1 ; Window Y centre
- MOV R0,R0,LSR #32-Random ; X1
- SUB R0,R0,#1<<(Random-1)
- ADD R0,R0,R8
- MOV R1,R1,LSR #32-Random ; Y1
- SUB R1,R1,#1<<(Random-1)
- ADD R1,R1,R9
- MOV R2,R2,LSR #32-Random ; X2
- SUB R2,R2,#1<<(Random-1)
- ADD R2,R2,R8
- MOV R3,R3,LSR #32-Random ; Y2
- SUB R3,R3,#1<<(Random-1)
- ADD R3,R3,R9
- LDMFD R13!,{R8-R10,PC}^ ; {R0=X start point}
- ; {R1=Y start point}
- ; {R2=X end point}
- ; {R3=Y end point}
- ; {R4=Colour byte}
- ;**********************************************
- .CallLine STMFD R13!,{R0-R5,R14}
- SWI "XOS_RemoveCursors"
- .CallLineCont MOV R5,#256 ; 256 lines at a time
- .CallLineNext BL RandomCoordinates ; Get random point and colour
- BL Line ; Plot the line
- SUBS R5,R5,#1 ; Next line
- BGT CallLineNext
- SWI "XOS_ReadEscapeState"
- BCC CallLineCont ; Next 256 lines
- SWI "XOS_RestoreCursors"
- LDMFD R13!,{R0-R5,PC}^ ; Preserve mode and state
- ;**********************************************
- ;**********************************************
- ;** Line preprocessing **
- ;**********************************************
- ;**********************************************
- ; {R0=X start point}
- ; {R1=Y start point}
- ; {R2=X end point}
- ; {R3=Y end point}
- ; {R4=Colour byte}
- ; {Preserve mode and state}
- .Line STMFD R13!,{R0-R6,R11,R14}
- MOV R0,R0,LSL #16 ; Ensure 16 bit coords
- MOV R1,R1,LSL #16 ; Don't combine these two
- MOV R2,R2,LSL #16 ; shifts as line rejection
- MOV R3,R3,LSL #16 ; compatibility will be lost
- MOV R0,R0,ASR #XShift ; Shift to screen resolution
- MOV R1,R1,ASR #XShift
- MOV R2,R2,ASR #XShift
- MOV R3,R3,ASR #XShift
- ;----------------------------------------------
- CMP R3,R1 ; Delta Y
- BEQ LineHorizontal ; Line is horizontal or point
- CMP R2,R0 ; Delta X
- BEQ LineVertical ; Line is vertical
- BGT LinePreprocess ; Coordinates in right order
- ;----------------------------------------------
- EOR R0,R0,R2 ; Swap X coordinates
- EOR R2,R0,R2
- EOR R0,R0,R2
- EOR R1,R1,R3 ; Swap Y coordinates also
- EOR R3,R1,R3
- EOR R1,R1,R3
- ;----------------------------------------------
- .LinePreprocess MOV R5,#0 ; Point state
- CMP R0,#LBound<<16-XShift
- ORRLT R5,R5,#%0001 ; Left of border
- CMP R0,#RBound<<16-XShift
- ORRGE R5,R5,#%0010 ; Right of border
- CMP R1,#BBound<<16-YShift
- ORRLT R5,R5,#%0100 ; Below border
- CMP R1,#TBound<<16-YShift
- ORRGE R5,R5,#%1000 ; Above border
- ;----------------------------------------------
- MOV R6,#0 ; Point state
- CMP R2,#LBound<<16-XShift
- ORRLT R6,R6,#%0001 ; Left of border
- CMP R2,#RBound<<16-XShift
- ORRGE R6,R6,#%0010 ; Right of border
- CMP R3,#BBound<<16-YShift
- ORRLT R6,R6,#%0100 ; Below border
- CMP R3,#TBound<<16-YShift
- ORRGE R6,R6,#%1000 ; Above border
- ;----------------------------------------------
- ORRS R11,R5,R6 ; Combination
- BEQ LineOnScreen ; Line already on screen
- EOR R14,R5,R6 ; Difference
- BICS R14,R11,R14 ; Logical intersection
- LDMNEFD R13!,{R0-R6,R11,PC}^ ; Line outside boundaries
- TST R11,#%0011 ; Actually, this can only be
- BNE LineClipToX ; called first (or never)
- ;----------------------------------------------
- .LineClipToY STMFD R13!,{R7-R10} ; {R5,R6,R11,R14 Corruptable}
- MOV R7,R2,ASR #1 ; Dx was positive
- SUB R7,R7,R0,ASR #1 ; Subdivide X
- MOV R8,R3,ASR #1 ; Dy can be anything
- SUBS R8,R8,R1,ASR #1 ; Subdivide Y
- BEQ LineClipToYExit ; No more clipping possible
- RSBLT R8,R8,#0 ; Dy must be positive
- RSBLT R7,R7,#0 ; Negate Dx
- ;----------------------------------------------
- MOV R9,#BBound>>YShift ; Screen Y boundary (bottom)
- MOV R10,#TBound>>YShift ; Screen Y boundary (top)
- SUB R10,R10,#1 ; Visible boundary
- ;----------------------------------------------
- .LineClipToYNext TST R5,#%0100 ; Clip to line Y=R9 ?
- BEQ LineClipToYNBY1 ; No
- CMP R1,R9,LSL #16 ; Position from clipping line
- ADDLT R0,R0,R7 ; Under
- ADDLT R1,R1,R8
- SUBGE R0,R0,R7 ; Over
- SUBGE R1,R1,R8
- CMP R9,R1,ASR #16 ; Am I on the clipping line ?
- BICEQ R5,R5,#%0100 ; Yes
- B LineClipToYNTY1 ; Mutual exclusive
- ;----------------------------------------------
- .LineClipToYNBY1 TST R5,#%1000 ; Clip to line Y=R10 ?
- BEQ LineClipToYNTY1 ; No
- CMP R1,R10,LSL #16 ; Position from clipping line
- ADDLT R0,R0,R7 ; Under
- ADDLT R1,R1,R8
- SUBGE R0,R0,R7 ; Over
- SUBGE R1,R1,R8
- CMP R10,R1,ASR #16 ; Am I on the clipping line ?
- BICEQ R5,R5,#%1000 ; Yes
- ;----------------------------------------------
- .LineClipToYNTY1 TST R6,#%0100 ; Clip to line Y=R9 ?
- BEQ LineClipToYNBY2 ; No
- CMP R3,R9,LSL #16 ; Position from clipping line
- ADDLT R2,R2,R7 ; Under
- ADDLT R3,R3,R8
- SUBGE R2,R2,R7 ; Over
- SUBGE R3,R3,R8
- CMP R9,R3,ASR #16 ; Am I on the clipping line ?
- BICEQ R6,R6,#%0100 ; Yes
- B LineClipToYNTY2 ; Mutual exclusive
- ;----------------------------------------------
- .LineClipToYNBY2 TST R6,#%1000 ; Clip to line Y=R10 ?
- BEQ LineClipToYNTY2 ; No
- CMP R3,R10,LSL #16 ; Position from clipping line
- ADDLT R2,R2,R7 ; Under
- ADDLT R3,R3,R8
- SUBGE R2,R2,R7 ; Over
- SUBGE R3,R3,R8
- CMP R10,R3,ASR #16 ; On the clipping line ?
- BICEQ R6,R6,#%1000 ; Yes
- ;----------------------------------------------
- .LineClipToYNTY2 MOVS R8,R8,ASR #1 ; Subdivide Y
- BEQ LineClipToYExit ; No more clipping possible
- MOV R7,R7,ASR #1 ; Subdivide X
- ;----------------------------------------------
- ORR R11,R5,R6 ; Combination
- ANDS R11,R11,#%1100 ; Y clipping done ?
- BNE LineClipToYNext ; No
- ;----------------------------------------------
- .LineClipToYExit CMP R0,#LBound<<16-XShift; Round off error ?
- MOVLT R0,#LBound<<16-XShift; Yes
- CMP R1,#BBound<<16-YShift
- MOVLT R1,#BBound<<16-YShift
- CMP R2,#LBound<<16-XShift
- MOVLT R2,#LBound<<16-XShift
- CMP R3,#BBound<<16-YShift
- MOVLT R3,#BBound<<16-YShift
- LDMFD R13!,{R7-R10}
- ;----------------------------------------------
- MOV R5,R3,ASR #16
- CMP R5,R1,ASR #16 ; Delta Y
- BEQ LineHorizontal ; Line is horizontal or point
- MOV R5,R2,ASR #16
- CMP R5,R0,ASR #16 ; Delta X
- BEQ LineVertical ; Line is vertical
- ;----------------------------------------------
- .LineOnScreen MOV R0,R0,ASR #16 ; Hardware coords
- MOV R1,R1,ASR #16
- MOV R2,R2,ASR #16
- MOV R3,R3,ASR #16
- ;----------------------------------------------
- SUB R2,R2,R0 ; Delta X
- MOV R5,#(HSize>>XShift) ; Pixels per line
- SUBS R3,R3,R1 ; Delta Y
- RSBLT R3,R3,#0 ; Absolute value of Delta Y
- RSBGT R5,R5,#0 ; Ascending, is down in memory
- FNPixelAddress ; Returns pixel address in R11
- ;----------------------------------------------
- CMP R2,R3
- BGT LineAroundHorizontal
- BLT LineAroundVertical
- BEQ LineDiagonal
- ;**********************************************
- ;**********************************************
- ;** Horizontal clipping **
- ;**********************************************
- ;**********************************************
- .LineClipToX STMFD R13!,{R7-R10} ; {R5,R6,R11,R14 Corruptable}
- MOV R8,R3,ASR #1 ; Dy can be anything
- SUB R8,R8,R1,ASR #1 ; Subdivide Y
- MOV R7,R2,ASR #1 ; Dx was positive
- SUBS R7,R7,R0,ASR #1 ; Subdivide X
- BEQ LineClipToXExit ; No more clipping possible
- ;----------------------------------------------
- MOV R9,#LBound>>XShift ; Screen X boundary (left)
- MOV R10,#RBound>>XShift ; Screen X boundary (right)
- SUB R10,R10,#1 ; Visible boundary
- ;----------------------------------------------
- .LineClipToXNext TST R5,#%0001 ; Clip to line X=R9 ?
- BEQ LineClipToXNLX1 ; No
- CMP R0,R9,LSL #16 ; Position from clipping line
- ADDLT R0,R0,R7 ; Left
- ADDLT R1,R1,R8
- SUBGE R0,R0,R7 ; Right
- SUBGE R1,R1,R8
- CMP R9,R0,ASR #16 ; Am I on the clipping line ?
- BICEQ R5,R5,#%0001 ; Yes
- B LineClipToXNRX1 ; Mutual exclusive
- ;----------------------------------------------
- .LineClipToXNLX1 TST R5,#%0010 ; Clip to line X=R10 ?
- BEQ LineClipToXNRX1 ; No
- CMP R0,R10,LSL #16 ; Position from clipping line
- ADDLT R0,R0,R7 ; Left
- ADDLT R1,R1,R8
- SUBGE R0,R0,R7 ; Right
- SUBGE R1,R1,R8
- CMP R10,R0,ASR #16 ; Am I on the clipping line ?
- BICEQ R5,R5,#%0010 ; Yes
- ;----------------------------------------------
- .LineClipToXNRX1 TST R6,#%0001 ; Clip to line X=R9 ?
- BEQ LineClipToXNLX2 ; No
- CMP R2,R9,LSL #16 ; Position from clipping line
- ADDLT R2,R2,R7 ; Left
- ADDLT R3,R3,R8
- SUBGE R2,R2,R7 ; Right
- SUBGE R3,R3,R8
- CMP R9,R2,ASR #16 ; Am I on the clipping line ?
- BICEQ R6,R6,#%0001 ; Yes
- B LineClipToXNRX2 ; Mutual exclusive
- ;----------------------------------------------
- .LineClipToXNLX2 TST R6,#%0010 ; Clip to line X=R10 ?
- BEQ LineClipToXNRX2 ; No
- CMP R2,R10,LSL #16 ; Position from clipping line
- ADDLT R2,R2,R7 ; Left
- ADDLT R3,R3,R8
- SUBGE R2,R2,R7 ; Right
- SUBGE R3,R3,R8
- CMP R10,R2,ASR #16 ; On the clipping line ?
- BICEQ R6,R6,#%0010 ; Yes
- ;----------------------------------------------
- .LineClipToXNRX2 MOVS R7,R7,ASR #1 ; Subdivide X
- BEQ LineClipToXExit ; No more clipping possible
- MOV R8,R8,ASR #1 ; Subdivide Y
- ;----------------------------------------------
- ORR R11,R5,R6 ; Combination
- ANDS R11,R11,#%0011 ; X clipping done ?
- BNE LineClipToXNext ; No
- ;----------------------------------------------
- .LineClipToXExit CMP R0,#LBound<<16-XShift; Round off error ?
- MOVLT R0,#LBound<<16-XShift; Yes
- LDMFD R13!,{R7-R10}
- ;----------------------------------------------
- MOV R5,R3,ASR #16
- CMP R5,R1,ASR #16 ; Delta Y
- BEQ LineHorizontal ; Line is horizontal or point
- MOV R5,R2,ASR #16
- CMP R5,R0,ASR #16 ; Delta X
- BEQ LineVertical ; Line is vertical
- B LinePreprocess ; Now clip, reject or draw
- ;**********************************************
- ;**********************************************
- ;** Horizontal line drawing **
- ;**********************************************
- ;**********************************************
- ; {R0=X start point <<16}
- ; {R1=Y start point <<16}
- ; {R2=X end point <<16}
- ; {R3=Y end point <<16}
- ; {R4=Colour byte}
- .LineHorizontal CMP R1,#BBound<<16-YShift; Line below border ?
- LDMLTFD R13!,{R0-R6,R11,PC}^
- CMP R1,#TBound<<16-YShift; Line above border ?
- LDMGEFD R13!,{R0-R6,R11,PC}^
- ;----------------------------------------------
- CMP R2,R0 ; X coordinates order
- EORLT R0,R0,R2 ; Swap X coordinates
- EORLT R2,R0,R2
- EORLT R0,R0,R2
- ;----------------------------------------------
- CMP R2,#LBound<<16-XShift; Line left of border ?
- LDMLTFD R13!,{R0-R6,R11,PC}^
- CMP R0,#RBound<<16-XShift; Line right of border ?
- LDMGEFD R13!,{R0-R6,R11,PC}^
- ;----------------------------------------------
- MOV R0,R0,ASR #16 ; Hardware coords
- MOV R1,R1,ASR #16
- MOV R2,R2,ASR #16
- MOV R3,R3,ASR #16
- ;----------------------------------------------
- CMP R0,#LBound>>XShift ; Clip X start ?
- MOVLT R0,#LBound>>XShift
- CMP R2,#RBound>>XShift ; Clip X end ?
- MOVGE R2,#RBound>>XShift ; One too high therefore ADDLT
- SUB R2,R2,R0 ; Delta X, one too low
- ADDLT R2,R2,#1 ; Number of pixels to plot
- FNPixelAddress ; Returns pixel address in R11
- ;----------------------------------------------
- RSBS R5,R2,#11 ; Short lines breakeven point
- ADDGE PC,PC,R5,LSL #2 ; 1*4 bytes of code
- B LineHorizontalLong ; 12 or more pixels
- STRB R4,[R11],#1 ; 11 pixels
- STRB R4,[R11],#1
- STRB R4,[R11],#1
- STRB R4,[R11],#1 ; 8 pixels
- STRB R4,[R11],#1
- STRB R4,[R11],#1
- STRB R4,[R11],#1
- STRB R4,[R11],#1 ; 4 pixels
- STRB R4,[R11],#1
- STRB R4,[R11],#1
- STRB R4,[R11],#1 ; 1 pixel
- LDMFD R13!,{R0-R6,R11,PC}^
- ;----------------------------------------------
- .LineHorizontalLong
- ANDS R5,R11,#%11 ; Bytes before aligned part
- BEQ LineHorizontalAligned
- RSB R5,R5,#4 ; Bytes to plot to align
- CMP R5,#2
- STRGTB R4,[R11],#1 ; 3 pixels
- STRGEB R4,[R11],#1 ; 2 pixels
- STRALB R4,[R11],#1 ; 1 pixel
- SUBS R2,R2,R5 ; Pixels left to be plotted
- LDMLEFD R13!,{R0-R6,R11,PC}^ ; All pixels done
- ;----------------------------------------------
- .LineHorizontalAligned
- AND R4,R4,#&FF ; Colour byte
- ORR R4,R4,R4,LSL #8 ; Set up colour byte to
- ORR R4,R4,R4,LSL #16 ; become colour word
- MOV R0,R4 ; For multiple stores
- MOV R1,R4 ; R0,R1,R3,R4
- MOV R3,R4
- ;----------------------------------------------
- MOV R5,R2,LSR #4 ; 16 or more pixels to plot ?
- MOV R14,R5,LSR #5 ; 512 pixels a time
- AND R5,R5,#%11111 ; Multiple of 512 pixels
- RSB R5,R5,#32 ; Number of entries to skip
- ADD PC,PC,R5,LSL #2 ; 1*4 bytes of code
- MOVNV R0,R0 ; Dummy instruction
- .LineHorizontalAlignedNext512
- STMIA R11!,{R0,R1,R3,R4} ; 16 MPixels/sec store
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- STMIA R11!,{R0,R1,R3,R4}
- SUBS R14,R14,#1
- BGE LineHorizontalAlignedNext512
- ;----------------------------------------------
- AND R2,R2,#%1111 ; Modulo of 16 pixels
- MOVS R5,R2,LSR #2 ; Multiple of 4 pixels left ?
- BEQ LineHorizontalLessThan4
- CMP R5,#2
- STMGTIA R11!,{R0,R1,R3} ; 12-15 pixels
- STMEQIA R11!,{R0,R1} ; 8-11 pixels
- STMLTIA R11!,{R0} ; 4- 7 pixels
- ;----------------------------------------------
- .LineHorizontalLessThan4 ; 0- 3 pixels
- ANDS R5,R2,#%11 ; Some pixels left ?
- LDMEQFD R13!,{R0-R6,R11,PC}^ ; No
- CMP R5,#2
- STRGTB R4,[R11],#1 ; 3 pixels
- STRGEB R4,[R11],#1 ; 2 pixels
- STRALB R4,[R11],#1 ; 1 pixel
- LDMFD R13!,{R0-R6,R11,PC}^
- ;**********************************************
- ;**********************************************
- ;** Vertical line drawing **
- ;**********************************************
- ;**********************************************
- ; {R0=X start point <<16}
- ; {R1=Y start point <<16}
- ; {R2=X end point <<16}
- ; {R3=Y end point <<16}
- ; {R4=Colour byte}
- .LineVertical CMP R0,#LBound<<16-XShift; Line left of border ?
- LDMLTFD R13!,{R0-R6,R11,PC}^
- CMP R0,#RBound<<16-XShift; Line right of border ?
- LDMGEFD R13!,{R0-R6,R11,PC}^
- ;----------------------------------------------
- CMP R1,R3 ; Y coordinates order
- EORLT R1,R1,R3 ; Swap Y coordinates
- EORLT R3,R1,R3
- EORLT R1,R1,R3
- ;----------------------------------------------
- CMP R1,#BBound<<16-YShift; Line below border ?
- LDMLTFD R13!,{R0-R6,R11,PC}^
- CMP R3,#TBound<<16-YShift; Line above border ?
- LDMGEFD R13!,{R0-R6,R11,PC}^
- ;----------------------------------------------
- MOV R0,R0,ASR #16 ; Hardware coords
- MOV R1,R1,ASR #16
- MOV R2,R2,ASR #16
- MOV R3,R3,ASR #16
- ;----------------------------------------------
- CMP R1,#TBound>>YShift ; Clip Y start ?
- MOVGE R1,#TBound>>YShift
- SUBGE R1,R1,#1
- CMP R3,#BBound>>YShift ; Clip Y end ?
- MOVLT R3,#BBound>>YShift
- SUB R3,R1,R3 ; Delta Y
- ADD R3,R3,#1 ; Number of pixels to plot
- FNPixelAddress ; Returns pixel address in R11
- ;----------------------------------------------
- MOV R14,R3,LSR #3 ; Initialise pixel counter
- AND R1,R3,#%111 ; Low bits for unfold
- RSB R1,R1,#8 ; Skip MOD 8 entries in table
- ADD PC,PC,R1,LSL #2 ; 1*4 bytes of code
- MOVNV R0,R0 ; Dummy instruction
- .LineVerticalNextPixel ; 1.75 MPixels/sec store
- ;----------------------------------------------
- STRB R4,[R11],#(HSize>>XShift)
- STRB R4,[R11],#(HSize>>XShift)
- STRB R4,[R11],#(HSize>>XShift)
- STRB R4,[R11],#(HSize>>XShift)
- STRB R4,[R11],#(HSize>>XShift)
- STRB R4,[R11],#(HSize>>XShift)
- STRB R4,[R11],#(HSize>>XShift)
- STRB R4,[R11],#(HSize>>XShift)
- SUBS R14,R14,#1 ; 8 more pixels to plot?
- BGE LineVerticalNextPixel
- LDMFD R13!,{R0-R6,R11,PC}^
- ;**********************************************
- ;**********************************************
- ;** Random line drawing **
- ;**********************************************
- ;**********************************************
- ; {R2=Delta X > 0 (DX>DY)}
- ; {R3=Delta Y > 0}
- ; {R4=Colour byte}
- ; {R5=Y screen line increment}
- ; {R11=Pixel base address}
- .LineAroundHorizontal
- RSB R0,R2,#0 ; Initialise error term
- MOV R14,R2,LSR #3 ; Initialise pixel counter
- AND R1,R2,#%111 ; Low bits for unfold
- RSB R1,R1,#8 ; Skip MOD 8 entries in table
- ADD PC,PC,R1,LSL #4 ; 4*4 bytes of code
- MOVNV R0,R0 ; Dummy instruction
- .LineAroundHorizontalNextPixel ; 1 MPixels/sec store
- ;----------------------------------------------
- STRB R4,[R11],#1 ; Plot pixel and update X coord
- ADDS R0,R0,R3,LSL #1 ; Increase error term
- ADDGT R11,R11,R5 ; Update Y coord
- SUBGT R0,R0,R2,LSL #1 ; And decrease error term
- ;----------------------------------------------
- STRB R4,[R11],#1 ; Plot pixel and update X coord
- ADDS R0,R0,R3,LSL #1 ; Increase error term
- ADDGT R11,R11,R5 ; Update Y coord
- SUBGT R0,R0,R2,LSL #1 ; And decrease error term
- ;----------------------------------------------
- STRB R4,[R11],#1 ; Plot pixel and update X coord
- ADDS R0,R0,R3,LSL #1 ; Increase error term
- ADDGT R11,R11,R5 ; Update Y coord
- SUBGT R0,R0,R2,LSL #1 ; And decrease error term
- ;----------------------------------------------
- STRB R4,[R11],#1 ; Plot pixel and update X coord
- ADDS R0,R0,R3,LSL #1 ; Increase error term
- ADDGT R11,R11,R5 ; Update Y coord
- SUBGT R0,R0,R2,LSL #1 ; And decrease error term
- ;----------------------------------------------
- STRB R4,[R11],#1 ; Plot pixel and update X coord
- ADDS R0,R0,R3,LSL #1 ; Increase error term
- ADDGT R11,R11,R5 ; Update Y coord
- SUBGT R0,R0,R2,LSL #1 ; And decrease error term
- ;----------------------------------------------
- STRB R4,[R11],#1 ; Plot pixel and update X coord
- ADDS R0,R0,R3,LSL #1 ; Increase error term
- ADDGT R11,R11,R5 ; Update Y coord
- SUBGT R0,R0,R2,LSL #1 ; And decrease error term
- ;----------------------------------------------
- STRB R4,[R11],#1 ; Plot pixel and update X coord
- ADDS R0,R0,R3,LSL #1 ; Increase error term
- ADDGT R11,R11,R5 ; Update Y coord
- SUBGT R0,R0,R2,LSL #1 ; And decrease error term
- ;----------------------------------------------
- STRB R4,[R11],#1 ; Plot pixel and update X coord
- ADDS R0,R0,R3,LSL #1 ; Increase error term
- ADDGT R11,R11,R5 ; Update Y coord
- SUBGT R0,R0,R2,LSL #1 ; And decrease error term
- ;----------------------------------------------
- SUBS R14,R14,#1 ; 8 more pixels to plot?
- BGE LineAroundHorizontalNextPixel
- ;----------------------------------------------
- STRB R4,[R11],#1 ; End pixel
- LDMFD R13!,{R0-R6,R11,PC}^
- ;**********************************************
- ; {R2=Delta X > 0 (DX<DY)}
- ; {R3=Delta Y > 0}
- ; {R4=Colour byte}
- ; {R5=Y screen line increment}
- ; {R11=Pixel base address}
- .LineAroundVertical
- RSB R0,R3,#0 ; Initialise error term
- MOV R14,R3,LSR #3 ; Initialise pixel counter
- AND R1,R3,#%111 ; Low bits for unfold
- RSB R1,R1,#8 ; Skip MOD 8 entries in table
- ADD PC,PC,R1,LSL #4 ; 4*4 bytes of code
- MOVNV R0,R0 ; Dummy instruction
- .LineAroundVerticalNextPixel ; 1.75 MPixels/sec store
- ;----------------------------------------------
- STRB R4,[R11],R5 ; Plot pixel and update Y coord
- ADDS R0,R0,R2,LSL #1 ; Increase error term
- ADDGT R11,R11,#1 ; Update X coord
- SUBGT R0,R0,R3,LSL #1 ; And decrease error term
- ;----------------------------------------------
- STRB R4,[R11],R5 ; Plot pixel and update Y coord
- ADDS R0,R0,R2,LSL #1 ; Increase error term
- ADDGT R11,R11,#1 ; Update X coord
- SUBGT R0,R0,R3,LSL #1 ; And decrease error term
- ;----------------------------------------------
- STRB R4,[R11],R5 ; Plot pixel and update Y coord
- ADDS R0,R0,R2,LSL #1 ; Increase error term
- ADDGT R11,R11,#1 ; Update X coord
- SUBGT R0,R0,R3,LSL #1 ; And decrease error term
- ;----------------------------------------------
- STRB R4,[R11],R5 ; Plot pixel and update Y coord
- ADDS R0,R0,R2,LSL #1 ; Increase error term
- ADDGT R11,R11,#1 ; Update X coord
- SUBGT R0,R0,R3,LSL #1 ; And decrease error term
- ;----------------------------------------------
- STRB R4,[R11],R5 ; Plot pixel and update Y coord
- ADDS R0,R0,R2,LSL #1 ; Increase error term
- ADDGT R11,R11,#1 ; Update X coord
- SUBGT R0,R0,R3,LSL #1 ; And decrease error term
- ;----------------------------------------------
- STRB R4,[R11],R5 ; Plot pixel and update Y coord
- ADDS R0,R0,R2,LSL #1 ; Increase error term
- ADDGT R11,R11,#1 ; Update X coord
- SUBGT R0,R0,R3,LSL #1 ; And decrease error term
- ;----------------------------------------------
- STRB R4,[R11],R5 ; Plot pixel and update Y coord
- ADDS R0,R0,R2,LSL #1 ; Increase error term
- ADDGT R11,R11,#1 ; Update X coord
- SUBGT R0,R0,R3,LSL #1 ; And decrease error term
- ;----------------------------------------------
- STRB R4,[R11],R5 ; Plot pixel and update Y coord
- ADDS R0,R0,R2,LSL #1 ; Increase error term
- ADDGT R11,R11,#1 ; Update X coord
- SUBGT R0,R0,R3,LSL #1 ; And decrease error term
- ;----------------------------------------------
- SUBS R14,R14,#1 ; 8 more pixels to plot?
- BGE LineAroundVerticalNextPixel
- ;----------------------------------------------
- STRB R4,[R11],R5 ; End pixel
- LDMFD R13!,{R0-R6,R11,PC}^
- ;**********************************************
- ; {R2=Delta X > 0 (DX=DY)}
- ; {R3=Delta Y > 0}
- ; {R4=Colour byte}
- ; {R5=Y screen line increment}
- ; {R11=Pixel base address}
- .LineDiagonal ADD R5,R5,#1 ; Automatic X increment
- ADD R3,R3,#1 ; Increment for last pixel
- MOV R14,R3,LSR #3 ; Initialise pixel counter
- AND R1,R3,#%111 ; Low bits for unfold
- RSB R1,R1,#8 ; Skip MOD 8 entries in table
- ADD PC,PC,R1,LSL #2 ; 1*4 bytes of code
- MOVNV R0,R0 ; Dummy instruction
- .LineDiagonalNextPixel ; 1.75 MPixels/sec store
- ;----------------------------------------------
- STRB R4,[R11],R5 ; Plot pixel asn update coords
- STRB R4,[R11],R5
- STRB R4,[R11],R5
- STRB R4,[R11],R5
- STRB R4,[R11],R5
- STRB R4,[R11],R5
- STRB R4,[R11],R5
- STRB R4,[R11],R5
- ;----------------------------------------------
- SUBS R14,R14,#1 ; 8 more pixels to plot?
- BGE LineDiagonalNextPixel
- LDMFD R13!,{R0-R6,R11,PC}^
- ;**********************************************
- ;**********************************************
- ;** End **
- ;**********************************************
- ;**********************************************
- ]
- NEXT
- ENDPROC
- :
- REM ----- ASSEMBLY -----
- :
- REM +++++ MACRO'S +++++
- :
- DEF FNPixelAddress
- REM Returns the screen address for a
- REM pixel with (R0,R1) coordinates in R11
- [OPT Opt%
- LDR R11,ScreenAddress ; Screen base address
- ADD R11,R11,R0 ; X coordinate
- RSB R1,R1,#(VSize>>YShift) ; Reverse Y coordinate
- SUB R1,R1,#1 ; to visible area maximum
- MOV R0,#(HSize>>XShift) ; Just this way for overscan
- MLA R11,R0,R1,R11 ; Address of Y coordinate line
- ]
- =Opt%
- :
- DEF FNScreenAddress
- DIM Block% 16
- Block%!00=149
- Block%!04=-1
- SYS "OS_ReadVduVariables",Block%,Block%+8
- =Block%!08
- :
- DEF FNADR(R%,Label%)
- REM Prevents bad immediate constant problems
- REM Limited to addresses in the range
- REM -&7FFF to &7FFF relative to the PC
- LOCAL Move%
- IF (Opt% AND %10)=0 THEN
- [OPT Opt%
- EQUD 0
- EQUD 0
- ]
- ELSE
- Move%=Label%-(P%+8)
- IF Move%<0 THEN
- [OPT Opt%
- SUB R%,PC,#(-Move% AND &00FF)
- SUB R%,R%,#(-Move% AND &FF00)
- ]
- ELSE
- [OPT Opt%
- ADD R%,PC,#(Move% AND &00FF)
- ADD R%,R%,#(Move% AND &FF00)
- ]
- ENDIF
- ENDIF
- =Opt%
- :
- REM ----- MACRO'S -----
- :
-