; Copyright 1996 Acorn Computers Ltd ; ; Licensed under the Apache License, Version 2.0 (the "License"); ; you may not use this file except in compliance with the License. ; You may obtain a copy of the License at ; ; http://www.apache.org/licenses/LICENSE-2.0 ; ; Unless required by applicable law or agreed to in writing, software ; distributed under the License is distributed on an "AS IS" BASIS, ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ; See the License for the specific language governing permissions and ; limitations under the License. ; ; > $.Source.VduGrafE ; ; ARTHUR OPERATING SYSTEM - Vdu Drivers ; ======================= ; ; Vdu driver code - Line Fill L & R and Flood Fill ; ; Author R C Manby ; Date 17.10.86 ; ; ***************************************************************************** ; ; FillLRnonBg ; =========== ; ; On entry, R0 (X), R1 (Y) hold point to fill from ; ; On exit, R0..R11 corrupt ; FillLRtoFg ADD R2, WsPtr, #FgEcf MOV R3, #0 B FillLRnonBg10 ; Fill L <-> R FillLRnonBg ADD R2, WsPtr, #BgEcf MOV R3, #&80000000 FillLRnonBg10 SaveRetAdr BL FillAlong2 SUBCS R1, R1, #1 ; indicate nothing filled by Y-=1 STR R0, [WsPtr, #GCsIX] ; left X STR R1, [WsPtr, #GCsIY] ; Y Return CS ; external new pt hasn't changed STR R2, [WsPtr, #NewPtX] ; right X MOV R0, R2 BL IEGB ; update external version of new NewPt Return ; then things get shuffled ; ***************************************************************************** ; ; FillLRtoBg (Really only fill right!) ; ========== ; ; On entry, R0 (X), R1 (Y) hold point to fill from ; ; On exit, R0..R11 corrupt ; FillLRnonFg ADD R2, WsPtr, #FgEcf MOV R3, #&80000000 B FillLRtoBg10 ; Fill -> R FillLRtoBg ADD R2, WsPtr, #BgEcf MOV R3, #&0 FillLRtoBg10 SaveRetAdr STR R0, [WsPtr, #GCsIX] ; "left hand point" = given point STR R1, [WsPtr, #GCsIY] BL GenLineFillParm ; if C=1 (nothing can be plotted) SUBCS R0, R0, #1 ; then NewPtX-=1 ie NewPtX < GCsIX BLCC FillLineRightRegs ; else fill right STR R0, [WsPtr, #NewPtX] ; Convert NewPt(X,Y) (internal) into LDR R1, [WsPtr, #NewPtY] ; GCs(X,Y) (external) BL IEGB Return ; On returning, cursors are shuffled ; which updates GCsI(X,Y) ; ***************************************************************************** ; ; GenLineFillParm ; =============== ; ; On entry, R0 (X), R1 (Y) hold point to fill from ; R2 points to delimiting colour (FgEcf/BgEcf) ; R3 fill flag, 0/&80000000 for fill to/to-non ; ; On exit, Carry=0, valid parameter setup, R0-R10 contain copy of control block ; Carry=1, point outside window, R0 preserved, R1-R10 undefined ; ; Format of control block ; ; R0 - StartX ; R1 - DelimitColour ; R2 - FillFlag ; R3 - ScreenAdr ; R4 - PixelMsk ; R5 - zgora ; R6 - zgeor ; R7 - GWLCol ; R8 - GWRCol ; R9 - BytesPerChar ; R10 - NPix ; GenLineFillParm WINDow R0,R1, R7,R8,R9,R10 ; Window(R0,R1) using R7-R10 ; gives GE if in window BGE %FT01 SEC ; If point outside window MOV PC, Link ; then quit with carry set 01 Push "R2,R3,R7,R9,Link" ; Save colourptr, fillflag ; GWLCol, GWRCol BL ScreenAddr ; Returns R2 = Addr, R3 = Mask LDR R9, [WsPtr, #YWindLimit] SUB R9, R9, R1 ; Flip Ycoord AND R9, R9, #7 ; Line within ecf LDR R5, [WsPtr, #GColAdr] ; Base address of ecf pattern ADD R5, R5, R9, LSL #3 LDMIA R5, {R5, R6} ; Get zgora,zgeor MOV R4, R3 MOV R3, R2 Pull "R1,R2,R7,R8,Link" ; restore other registers LDR R1, [R1, R9, LSL #2] ; load delimiting colour LDR R9, [WsPtr, #BytesPerChar] LDR R10, [WsPtr, #NPix] ADD R11, WsPtr, #LineFillBlk ; now save completed control block STMIA R11, {R0-R10} LDR R11, [R3] ; load screen EOR R11, R11, R1 ; screen EOR boundary TST R11, R4 ; just look at this pixel ; Blimey. MRS R7, CPSR TEQ R2, R7, LSL #1 ; N := (Z EOR R2) ie invert test if ; stopping on non-colour BICPL R7, R7, #C_bit ; point can be filled, exit CC ORRMI R7, R7, #C_bit ; point cannot be filled, exit CS MSR CPSR_f, R7 MOV PC, Link ; ***************************************************************************** ; ; FillLineRight - Fill right from point upto delimiting colour ; ============= or graphics window ; ; ; R0 - RightLimitX ; R1 - LimitColour ; R2 - FillFlag ; R3 - ScreenAdr ; R4 - PixelMsk ; R5 - zgora ; R6 - zgeor ; R7 - GWLCol /BPC/NPIX ; R8 - GWRCol ; R9 - ScreenWord ; R10 - NPix ; R11 - MultPixMsk / temp ; ; out: PSR must be preserved ; FillLineRight ROUT ADD R11, WsPtr, #LineFillBlk LDMIA R11, {R0-R10} FillLineRightRegs Push R14 MRS R14, CPSR Push "WsPtr, R14" ; we also need R12 for a temp RSB R7, R9, #32 ; shift factor for next pixel position SUB R0, R8, R0 10 MOV R11, #0 ; clear partial word mask LDR R9, [R3] ; screen word EOR delimit colour EOR R14, R9, R1 30 TST R14, R4 ; test pixel position for delimiting MRS WsPtr, CPSR TEQ R2, WsPtr, LSL #1 ; invert condition if necessary ORRPL R11, R11, R4 ; add pixel to partial word mask SUBPLS R0, R0, #1 ; "increment" X; if on edge of window BMI %FT40 ; then give up and plot partial word TEQ R4, #0 ; test for end of word MOV R4, R4, ROR R7 ; shift pixel mask left BPL %BT30 AND R14, R5, R11 ; fill partial word, using pixel mask AND R11, R6, R11 ; in R11 ORR R9, R9, R14 EOR R9, R9, R11 STR R9, [R3], #4 CMP R2, #2 ; CC => filling until pixel=target BCC %BT10 ; so do it slowly (goto next word) RSB R0, R0, #0 ; make X in range GWLCol-GWRCol .. 0 ADDS R0, R0, R10 ; move R0 to end of word BGT %FT36 ; outside window, continue slowly ORR R14, R1, R5 ; word to store if going fast EOR R14, R14, R6 32 LDR R9, [R3] ; screen word CMP R9, R1 ; EOR target colour (CS if EQ) BNE %FT36 STR R14, [R3], #4 ADCS R0, R0, R10 ; C=1, so add NPix+1 BLE %BT32 36 SUBS R0, R10, R0 ; R0 back to start of word and negate BGE %BT10 ; if still inside, continue slowly B %FT50 40 AND R14, R5, R11 ; fill partial word, using pixel mask AND R11, R6, R11 ; in R11 ORR R9, R9, R14 EOR R9, R9, R11 STR R9, [R3] 50 SUB R0, R8, R0 ; make back into normal coord again SUB R0, R0, #1 ; correct end point Pull "WsPtr, R14" MSR CPSR_f, R14 Pull PC ; ***************************************************************************** ; ; FillLineLeft - Fill left from point upto delimiting colour ; ============ or graphics window ; ; N.B. Starts one pixel left of point given, since ; FillLineRight will have already plotted it. ; ; R0 - LeftLimitX ; R1 - LimitColour ; R2 - FillFlag ; R3 - ScreenAdr ; R4 - PixelMsk ; R5 - zgora ; R6 - zgeor ; R7 - GWLCol } Slightly different from FillLineRight ; R8 - GWRCol /BPC/NPIX } ; R9 - ScreenWord ; R10 - LimitEorScreen / temp ; R11 - MultPixMsk / temp ; ; ; FillLineLeft ROUT ADD R11, WsPtr, #LineFillBlk LDMIA R11, {R0-R10} FillLineLeftRegs Push R14 MRS R14, CPSR Push "WsPtr, R14" ; also need WsPtr for a temp MOV R8, R9 ; shift factor for next pixel position SUB R0, R0, R7 LDR R9, [R3] ; screen word EOR delimit colour EOR R14, R9, R1 MOVS R11, #0 ; clear partial word mask (and set PL) B %FT31 10 MOV R11, #0 ; clear partial word mask LDR R9, [R3] ; screen word EOR delimit colour EOR R14, R9, R1 30 TST R14, R4 ; test pixel position for delimiting MRS WsPtr, CPSR TEQ R2, WsPtr, LSL #1 ; invert condition if appropriate ORRPL R11, R11, R4 ; add pixel to partial word mask 31 SUBPLS R0, R0, #1 ; decrement X; if on edge of window BMI %FT40 ; then give up and plot partial word MOVS R4, R4, ROR R8 ; test for end of word BPL %BT30 ; loop until mask exhausted AND R14, R5, R11 ; fill partial word, using pixel mask AND R11, R6, R11 ; in R11 ORR R9, R9, R14 EOR R9, R9, R11 STR R9, [R3], #-4 CMP R2, #2 ; CC => filling until pixel=target BCC %BT10 ; so do it slowly (goto next word) SUBS R0, R0, R10 ; move R0 to beginning of word BCC %FT36 ; if outside window continue slowly ADD R10, R10, #1 ORR R14, R1, R5 ; compute target word EOR R14, R14, R6 32 LDR R9, [R3] ; screen word CMP R9, R1 BNE %FT35 ; NZ => terminate STR R14, [R3], #-4 SUBS R0, R0, R10 BCS %BT32 35 SUB R10, R10, #1 36 ADDS R0, R0, R10 ; point R0 back to end of word BGE %BT10 ; if still inside, continue but slowly B %FT50 40 AND R14, R5, R11 ; fill partial word, using pixel mask AND R11, R6, R11 ; in R11 ORR R9, R9, R14 EOR R9, R9, R11 STR R9, [R3] 50 ADD R0, R0, R7 ; add GWLCol back on ADD R0, R0, #1 ; Correct endpoint value Pull "WsPtr, R14" MSR CPSR_f, R14 Pull PC ; ***************************************************************************** ; ; FillAlong - Fill left and right from point given ; ========= ; ; On entry, R0 (X), R1(Y) hold point to fill from ; ; On exit, R0 (X) End of scan left ; R1 (Y) Preserved ; R2 (X) End of scan right ; ; Carry set = no fill performed ie outside window or already filled ; Carry clear = fill occured ; ASSERT FldBoundaryFlag = FldBoundaryCol +4 FillAlong ADD R2, WsPtr, #FldBoundaryCol LDMIA R2, {R2,R3} ; R2 = colour, R3 = flag FillAlong2 ; entry point when R2, R3 loaded Push "R1, R14" BL GenLineFillParm ; On exit C=1 if nothing can be plotted BLCC FillLineRightRegs Push R0 ; New RightX BLCC FillLineLeft Pull R2 ; Recover RightX Pull "R1, PC" ; Recover Y, C=1 <=> fill occured ; ***************************************************************************** ; ; FloodFill ; ========= ; ; On entry, R0 (X), R1 (Y) hold point to flood from ; R2 Delimit colour, pointer to FgEcf/BgEcf ; R3 0/&80000000 for flood until/over ; ASSERT FldBoundaryFlag = FldBoundaryCol +4 ASSERT FldY = FldLeftXLimit +4 ASSERT FldRightXLimit = FldLeftXLimit +8 FloodToFg ADD R2, WsPtr, #FgEcf ; delimit colour MOV R3, #0 ; flood until B FloodFill FloodNonBg ADD R2, WsPtr, #BgEcf ; delimit colour MOV R3, #&80000000 ; flood over FloodFill ROUT Push R14 STR R13, [WsPtr, #FldStackLevel] ; save stack level ! ADD R14, WsPtr, #FldBoundaryCol LDR R4, [WsPtr, #YWindLimit] STMIA R14, {R2-R4} ; store colour, flag, YWindLimit [ med_00001_userma ; the idea here is to try to use between 48k and 128k of rma instead of 16k of ; scratchspace. if there's less than 48k of rma in the first place we go back to ; scratchspace. if there's 128k or more we claim the 128k and proceed. For values ; between 48k and 128k we first grow the rma by 128k-largest_free_space. If this ; results in a lump of 128k now being free we claim it and proceed. If the largest ; free space hasn't grown to 128k we then claim the additional balance needed to ; have 128k available. Should either grow fail, we just use whatever (over 48k) ; was available ;R3-R7 spare at presenet Push "R0-R2" MOV R0, #0 STR R0, [WsPtr, #flood_cda_rma] ; set amount to change dyn. area by MOV R0, #ModHandReason_RMADesc SWI XOS_Module ; get the largest free space in rma BVC %FT91 ; if that failed, use scratchspace use_scratchspace LDR R3, =FldQueueStart ; head ptr (== scratchspace) MOV R4, R3 ; tail ptr ADD R5, R3, #FldQueueSize ; end ptr (== scratchspace size) MOV R6, R3 ; start ptr B %FT92 91 CMP R2, #smallest_rma_size ; compare against small threshold BLT use_scratchspace ; not enough free - use scratchspace CMP R2, #largest_rma_size ; compare against high threshold BHS %FT96 ; lots free - use largest ceiling value RSB R1, R2, #largest_rma_size ; work out how much more to claim MOV R0, #1 ; rma SWI XOS_ChangeDynamicArea STRVC R1, [WsPtr, #flood_cda_rma] ; save the amount we grew the rma BVS %FT94 ; if it failed, use the minimum fill up, bit1 => fill down 10 ADD R14, WsPtr, #FldLeftXLimit STMIA R14, {R0-R2} ; store leftX, Y, rightX TST R3, #1 BEQ %FT20 LDR R10, [WsPtr, #GWTRow] ; if below Top of window CMP R10, R1 BLE %FT20 ADD R4, WsPtr, #FldBoundaryCol ; R4=target colour ptr,R5=flag, LDMIA R4, {R4,R5,R6} ; R6=YWindLimit ORR R5, R5, #FillingUpBit ; fill line above Push R3 BL CheckAlong ; (will bomb out if queue explodes) Pull R3 ADD R14, WsPtr, #FldLeftXLimit LDMIA R14, {R0,R1} ; reload leftX, Y 20 TST R3, #2 BEQ %FT30 LDR R10, [WsPtr, #GWBRow] ; if above bottom of window CMP R1, R10 BLE %FT30 ADD R4, WsPtr, #FldBoundaryCol ; R4=target colour ptr,R5=flag, LDMIA R4, {R4,R5,R6} ; R6=YWindLimit ; BIC R5, R5, #FillingUpBit ; fill line below BL CheckAlong ; (will bomb out if queue explodes) 30 ADD R11, WsPtr, #QueuePtrs ; unqueue one item LDMIA R11, {R3,R4,R5} ; head,tail,limit TEQ R3, R4 ; if queue empty [ med_00001_userma BLEQ release_memory ] Pull PC, EQ ; then exit [ med_00001_twowords LDR R1, [R3], #4 MOV R0, R1, LSR #16 ; LeftX MOV R2, R1 EOR R2, R2, R0, LSL #16 ; RightX (with LeftX EORed out) LDR R1, [R3], #4 ; Recover Y | LDR R1, [R3], #4 ; then load word MOV R2, R1, LSR #21 ; Recover RightX EOR R1, R1, R2, LSL #21 ; clear those bits out MOV R0, R1, LSR #10 ; Recover LeftX EOR R1, R1, R0, LSL #10 ; Recover Y ] TEQ R3, R5 ; if at limit LDREQ R3, [R11, #12] ; then reload with start STR R3, [R11, #0] ; store head ptr back MOV R3, #2 ; indicate fill down CMP R2, R0 ; if right < left then subtract 1 off ; larger and swap SBCCC R0, R0, R2 ; R0 := large-small-1 ADDCC R2, R0, R2 ; R2 := (large-small-1)+small = large-1 SUBCC R0, R2, R0 ; R0 := (large-1)-(large-small-1)=small MOVCC R3, #1 ; and indicate fill up B %BT10 ; ***************************************************************************** ; ; CheckAlong - Fill and skip background between LeftXLimit & RightXLimit ; ========== ; ; On entry, R0 LeftXLimit ; R1 Y ; R4 target colour ; R5 fill flag ; R6 YWindLimit ; ; Exits using R14 if normal termination ; Exits using FldStackLevel if queue full ; FillingUpBit * 1 ASSERT FldBoundaryFlag = FldBoundaryCol +4 ASSERT FldYWindLimit = FldBoundaryCol +8 ASSERT FldY = FldLeftXLimit +4 ASSERT FldRightXLimit = FldLeftXLimit +8 CheckAlong ROUT Push R14 TST R5, #FillingUpBit ; if going up ADDNE R1, R1, #1 ; then increment Y SUBEQ R1, R1, #1 ; else decrement Y BL ScreenAddr ; R2=screen addr, R3=mask SUB R6, R6, R1 ; flip Y AND R6, R6, #7 ; ecf offset LDR R4, [R4, R6, LSL #2] ; R4=target colour LDR R7, [WsPtr, #GColAdr] ; base address of plot ecf ADD R7, R7, R6, LSL #3 ; R7 -> zgora, zgeor LDMIA R7, {R10,R11} ; R10=zgora, R11=zgeor LDR R6, [WsPtr, #BytesPerChar] ; R6=pixel shift LDR R9, [WsPtr, #NPix] ; R9=no. of pixels per word-1 ADD R7, WsPtr, #FldSaveArea ; save Y, target colour, STMIA R7, {R1, R4, R9, R10, R11} ; NPix, zgora, zgeor ; test first pixel, to see if we can go left LDR R7, [R2] EOR R1, R7, R4 TST R1, R3 MRS R8, CPSR TEQ R5, R8, LSL #1 ; PL => it's fillable RSBMI R6, R6, #32 ; not fillable, reverse pixel shift LDRMI R8, [WsPtr, #GWRCol] ; load right window limit BMI %FT37 ; and skip left+right filling bit Push "R0, R2, R3" ; save X, screen address, mask LDR R8, [WsPtr, #GWLCol] SUB R0, R0, R8 ; make X in range 0..GWRCol-GWLCol MOV R14, #0 ; clear partial word mask TEQ R5, #0 ; get into correct loop BMI %FT84 BPL %FT64 10 MOV R14, #0 ; clear partial word mask LDR R7, [R2] ; R7 = screen EOR R1, R7, R4 ; ***KJB - very cumbersome. Surely a temporary reg somewhere? TEQ R5, #0 ; check "not" flag BMI %FT80 61 TST R1, R3 ; test pixel position for delimiter BEQ %FT22 ; NE => it's fillable ORR R14, R14, R3 ; add pixel to partial word mask 64 SUBS R0, R0, #1 ; decrement X; if on edge of window BMI %FT22 ; then give up and plot partial word MOVS R3, R3, ROR R6 ; test for end of word BPL %BT61 ; loop until mask wraps B %FT89 80 TST R1, R3 ; test pixel position for delimiter BNE %FT22 ; EQ => it's fillable ORR R14, R14, R3 ; add pixel to partial word mask 84 SUBS R0, R0, #1 ; decrement X; if on edge of window BMI %FT22 ; then give up and plot partial word MOVS R3, R3, ROR R6 ; test for end of word BPL %BT80 ; loop until mask wraps 89 AND R1, R10, R14 ; R1 := zgora AND pixmask ORR R7, R7, R1 ; screen := screen OR R1 AND R1, R11, R14 ; R1 := zgeor AND pixmask EOR R7, R7, R1 ; screen := screen EOR R1 STR R7, [R2], #-4 CMP R5, #2 ; CC => filling until target BCC %BT10 ; so do it slowly (do next word) SUBS R0, R0, R9 ; move R0 to start of word BCC %FT20 ; if outside window continue slowly ADD R9, R9, #1 ; R9 := pixels per word ORR R1, R4, R10 ; compute word to plonk on screen EOR R1, R1, R11 16 LDR R7, [R2] ; screen word CMP R7, R4 BNE %FT18 ; NZ => terminate STR R1, [R2], #-4 SUBS R0, R0, R9 ; back another word BCS %BT16 18 SUB R9, R9, #1 ; R9 := pixels per word -1 20 ADDS R0, R0, R9 ; point R0 back to end of word BGE %BT10 ; if still inside, continue but slowly B %FT24 ; else exit 22 AND R1, R10, R14 ; R1 := zgora AND pixmask ORR R7, R7, R1 ; screen := screen OR R1 AND R1, R11, R14 ; R1 := zgeor AND pixmask EOR R7, R7, R1 ; screen := screen EOR R1 STR R7, [R2] 24 ADD R0, R0, R8 ; add GWLCol back on ADD R0, R0, #1 Pull "R1, R2, R3" ; restore X, screen addr, mask Push R0 ; save left-of-line coordinate MOV R0, R1 ; R0 = start X RSB R6, R6, #32 ; reverse pixel shift LDR R8, [WsPtr, #GWRCol] ; load right window limit ; now the filling right part 26 SUB R0, R8, R0 ; make X in range GWRCol-GWLCol .. 0 ; start of each word 27 MOV R14, #0 LDR R7, [R2] ; screen word EOR R1, R7, R4 ; ***KJB - very cumbersome. Surely a temporary reg somewhere? TEQ R5, #0 BMI %FT75 72 TST R1, R3 ; test pixel position for delimiter BEQ %FT34 ; NE => it's fillable ORR R14, R14, R3 ; add pixel to partial word mask SUBS R0, R0, #1 ; "increment" X; if on edge of window BMI %FT34 ; then give up and plot partial word TEQ R3, #0 ; test for end of word MOV R3, R3, ROR R6 ; shift pixel mask BPL %BT72 ; loop until mask wraps B %FT79 75 TST R1, R3 ; test pixel position for delimiter BNE %FT34 ; EQ => it's fillable ORR R14, R14, R3 ; add pixel to partial word mask SUBS R0, R0, #1 ; "increment" X; if on edge of window BMI %FT34 ; then give up and plot partial word TEQ R3, #0 ; test for end of word MOV R3, R3, ROR R6 ; shift pixel mask BPL %BT75 ; loop until mask wraps 79 AND R1, R10, R14 ; R1 := zgora AND pixmask ORR R7, R7, R1 ; screen := screen OR R1 AND R1, R11, R14 ; R1 := zgeor AND pixmask EOR R7, R7, R1 ; screen := screen EOR R1 STR R7, [R2], #4 CMP R5, #2 ; CC => filling until target BCC %BT27 ; so do it slowly (do next word) RSB R0, R0, #0 ; make X in range GWLCol-GWRCol .. 0 ADDS R0, R0, R9 ; move R0 to end of word BGT %FT32 ; outside window, continue slowly ORR R1, R4, R10 ; word to store if going fast EOR R1, R1, R11 30 LDR R7, [R2] ; screen word CMP R7, R4 ; EOR target colour (CS if EQ) BNE %FT32 ; NZ => terminate STR R1, [R2], #4 ADCS R0, R0, R9 ; C=1, so add NPix +1 BLE %BT30 32 SUBS R0, R9, R0 ; R0 back to start of word and negate BGE %BT27 ; if still inside, continue slowly B %FT36 ; else exit 34 AND R1, R10, R14 ; R1 := zgora AND pixmask ORR R7, R7, R1 ; screen := screen OR R1 AND R1, R11, R14 ; R1 := zgeor AND pixmask EOR R7, R7, R1 ; screen := screen EOR R1 STR R7, [R2] 36 SUB R0, R8, R0 ; make back into normal coord again ; now queue this segment Pull R4 ; R4 := LH end point SUB R7, R0, #1 ; R7 := corrected RH end point LDR R1, [WsPtr, #FldSaveY] ; reload Y coordinate of THIS segment BL Queue ADD R14, WsPtr, #FldLeftXLimit ; load lxlim, (Y+?), rxlim LDMIA R14, {R7,R10,R11} EOR R5, R5, #FillingUpBit ; invert direction SUB R7, R7, #2 ; lxlim -2 CMP R4, R7 ; if leftX <= lxlim-2 BLLE Queue ; then Q LH end bit in opposite dir ADD R4, R11, #2 ; rxlim +2 SUB R7, R0, #1 ; R7 = RH end point CMP R7, R4 ; if rightX >= rxlim+2 BLGE Queue ; then Q RH end bit in opposite dir EOR R5, R5, #FillingUpBit ; invert direction back again SUB R4, R4, #3 ; rxlim -1 CMP R7, R4 ; if rightX >= rxlim-1 Pull PC, GE ; no point in skipping any more ; now do the skipping ; R0 points to first non-fillable pixel; R3=correct mask for this pixel ADD R7, WsPtr, #FldSaveArea ; reload target colour, NPix, LDMIB R7, {R4, R9, R10, R11} ; zgora, zgeor 37 LDR R1, [WsPtr, #FldRightXLimit] 38 LDR R7, [R2], #4 EOR R7, R7, R4 ; screen EOR target 40 TST R7, R3 ; if pixel is fillable MRS R14, CPSR TEQ R5, R14, LSL #1 SUBPL R2, R2, #4 ; then correct address Push R0, PL ; and push new X coord BPL %BT26 ; and go to fill right bit 50 CMP R0, R1 ; on limit of segment ? Pull PC, CS ; yes, so give up ADD R0, R0, #1 ; step coord TEQ R3, #0 ; test for mask wrap MOV R3, R3, ROR R6 ; rotate mask to next pixel BPL %BT40 ; continue within this word B %BT38 ; continue with next word ; ***************************************************************************** ; ; Queue - Queue a line segment ; ; in: R1 = Y coordinate of segment ; R4 = left X coordinate ; R5 = fill flag (Bit0=0/1 => look downwards/upwards) ; R7 = right X coordinate ; ; out: R0-R8, R11, R12 preserved ; R9,R10 corrupted ; exits by pulling stacked R14 if queue was full ; Queue ROUT Push "R0,R11,R14" TEQ R5, R5, LSR #1 ; CS => mangle coords MOVCC R9, R4 MOVCC R10, R7 SUBCS R9, R7, R4 ; R9 = R-L SUBCS R10, R7, R9 ; R10 = R-(R-L) = L ADCCS R9, R9, R10 ; R9 = (R-L)+L+1 = R+1 [ med_00001_twowords ; revised packing, expanded to two words, LeftX in 31..16 of word 1, ; RightX in 15..0 of word 1, and Y in 15..0 of word 2 MOV R9, R9, LSL #16 ; shift LeftX up ORR R9, R9, R10 ; combine in RightX ADD R0, WsPtr, #QueuePtrs LDMIA R0, {R10, R11, R14} ; head,tail,limit STR R9, [R11], #4 ; store word at tail and move on STR R1, [R11], #4 ; store second word | ; pack Y into bits 0..9, L into bits 10..20, R into bits 21..31 ORR R9, R1, R9, LSL #10 ; R9 = Y + (L << 10) ORR R9, R9, R10, LSL #21 ; R9 = Y + (L << 10) + (R <<21) ADD R0, WsPtr, #QueuePtrs LDMIA R0, {R10, R11, R14} ; head,tail,limit STR R9, [R11], #4 ; store word at tail and move on ] TEQ R11, R14 ; if at limit LDREQ R11, [R0, #12] ; then reload with start ptr CMP R11, R10 ; EQ and CS if queue full STRNE R11, [R0, #4] ; store tail ptr back if OK Pull "R0,R11,PC", NE ; queue not full, terminate normally [ med_00001_userma BL release_memory ] LDR R13, [WsPtr, #FldStackLevel] Pull PC ; else bomb out ; ***************************************************************************** [ med_00001_userma release_memory ROUT Push "R0-R5,lr" ADD R0, WsPtr, #QueuePtrs LDMIA R0, {R0-R3} LDR R5, =FldQueueStart CMP R3, R5 ; did we use scratchspace ? BEQ %FT20 MOV R2, R3 MOV R0, #ModHandReason_Free SWI XOS_Module 20 LDR R0, [WsPtr, #flood_cda_rma] CMP R0, #0 BEQ %FT30 ; no need to shrink rma RSB R1, R0, #0 ; get the signed negative value MOV R0, #1 ; rma SWI XOS_ChangeDynamicArea 30 CMP r0, r0 ; ensure we return EQ set Pull "r0-r5,pc" ] ; ***************************************************************************** END