; 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.VduPlot ; ; ARTHUR OPERATING SYSTEM - Vdu Drivers ; ======================= ; ; Vdu graphics code - Entry point for plotting & low level primitives ; & Ecf pattern setting ; Author R C Manby ; Date 5.9.86 ; ; ***************************************************************************** ; ; EM ; PLOT - Graphics operation, eg triangle, line etc. ; ==== ; ; The plot operation, and the co-ordinate to plot at given by bytes ; in the vdu queue, as follows ; QQ+0 - plot number ; QQ+1 - xLo ; QQ+2 - xHi ; QQ+3 - yLo ; QQ+4 - yHi ; ; The co-ordinate is in external 16 bit form. ; If 2 or 3 are required, they are taken from ICursor & OldCs ; ; Also, both PLOT and EntryFromSWIPlot are entered with R6 = CursorFlags ; EM PLOT ROUT [ {TRUE} GraphicsMode R0 ; Quit if not a graphics mode MOVNE PC, Link | LDR R0, [WsPtr, #NPix] CMP R0, #0 ; Quit if not a graphics mode MOVEQ PC, Link ] ASSERT ((QQ+1):AND:3)=0 LDR R2, [WsPtr, #QQ+1] ; R2 = xlo,xhi,ylo,yhi MOV R0, R2, LSL #16 ; R0 = 0 ,0 ,xlo,xhi MOV R0, R0, ASR #16 ; R0 = xlo,xhi,sgn,sgn MOV R1, R2, ASR #16 ; R1 = ylo,yhi,sgn,sgn LDRB R2, [WsPtr, #QQ+0] ; plot mode MOV R9, #0 ; indicate coming from VDU Plot EntryFromSWIPlot SaveRetAdr ; now convert to internal coords (modified EIG code) ASSERT OrgY = OrgX +4 ASSERT GCsX = OrgX +8 ASSERT GCsY = OrgX +12 ASSERT YEigFactor = XEigFactor +4 ADD R3, WsPtr, #OrgX LDMIA R3!, {R4-R5} ; R4 = OrgX: R5 = OrgY TST R2, #4 ; If bit2 is clear, then relative LDMEQIA R3, {R7-R8} ; so load old cursor position ADDEQ R0, R0, R7 ; and add ADDEQ R1, R1, R8 STMIA R3, {R0-R1} ; store new coords in GCsX,GCsY ADD R3, WsPtr, #XEigFactor LDMIA R3, {R7-R8} ; R7 = XEigFactor: R8 = YEigFactor ADD R0, R0, R4 ; add on origin ADD R1, R1, R5 MOV R0, R0, ASR R7 ; and shift down MOV R1, R1, ASR R8 ADD R3, WsPtr, #NewPtX STMIA R3, {R0-R1} ; ; The 2 LSBits of the plot code specify fg/bg colour and action as :- ; 0 No effect eqv. of Gcol(5,c) ; 1 Foreground colour using foreground Gcol action ; 2 Invert eqv. of Gcol(4,c) ; 3 Background colour using background Gcol action ; ; *****Change made by DJS ; Original code was: ; MOV R3, R2, LSL #30 ; put bottom 2 bits into top 2 bits ; CMP R3, #&40000000 ; set lots of flags ; ; ADDMI R4, WsPtr, #BgEcfOraEor ; if 0 or 3 ; ADRCC R4, NoEffect ; if 0 ; ADDEQ R4, WsPtr, #FgEcfOraEor ; if 1 ; ADRVS R4, Invert ; if 2 MOVS R3, R2, LSL #31 ;Put bit 1 in C, NOT(bit 0) in Z ADR R4, NoEffect ; if 0, 1, 2 or 3 ADDNE R4, WsPtr, #FgEcfOraEor ; if 1 or 3 ADRCS R4, Invert ; if 2 or 3 ADDHI R4, WsPtr, #BgEcfOraEor ; if CS & NE - i.e. 3 ; *****End of change made by DJS STR R4, [WsPtr, #GColAdr] ; save address of Ecf to plot with TST R6, #ClipBoxEnableBit BLNE DoPlotClipBox BIC R11, R2, #2_111 ; ARMv4 says we have to keep bits 1:0 of PC =0 ADR R14, CTidy ; set up return address ; R0=X, R1=Y, R2=plot code ADD PC, PC, R11, LSR #1 ; jump to branch & 0 ; dummy word B LineDrawSolid ; 0 - Solid line B LineDrawSolid ; 8 - Solid line, endpoint omitted B LineDrawDotted ; 16 - Dot-dash line, restart pattern B LineDrawDotted ; 24 - Dot-dash line, restart pattern, ; endpoint omitted B LineDrawSolid ; 32 - Solid extension line B LineDrawSolid ; 40 - Solid extension line, endpoint omitted B LineDrawDotted ; 48 - Dot-dash extension line, continue pattern B LineDrawDotted ; 56 - Dot-dash extension line, continue pattern, ; endpoint omitted B PlotPoint ; 64 - Point plot B FillLRnonBg ; 72 - Line fill L&R, upto non-background B TriangleFill ; 80 - Triangle fill B FillLRtoBg ; 88 - Fill right, upto background B RectangleFill ; 96 - Rectangle fill B FillLRtoFg ; 104 - Line fill L&R, upto foreground B ParallelogramFill ; 112 - Parallelogram Fill B FillLRnonFg ; 120 - Fill right, upto non-foreground B FloodNonBg ; 128 - Flood to non-bg (ie over bg) B FloodToFg ; 136 - Flood to fg (ie over non-fg) B CircleOutline ; 144 - Circle outline B CircleFill ; 152 - Circle fill B CircleArc ; 160 - Circular arc outline B SegmentFill ; 168 - Segment fill B SectorFill ; 176 - Sector (pie) fill B BlockCopyMove ; 184 - Block copy/move B EllipseOutline ; 192 - Ellipse outline B EllipseFill ; 200 - Ellipse fill B NYA ; 208 - Unassigned B NYA ; 216 - Unassigned B NYA ; 224 - Unassigned B SpritePlot ; 232 - Sprite plot B NYA ; 240 - Assigned to applications B NYA ; 248 - Assigned to applications CTidy ; The "normal" return point after a plot ; operation, any call that does not want ; the cursors moving should pull return ; address off the stack ; Shuffle the cursors along ; NewPt -> ICursor -> OldCs -> OlderCs ; ; ECursor was set earlier by EIG ADD R0, WsPtr, #OldCsX LDMIA R0, {R1,R2, R3,R4, R5,R6} ; OldCs(X,Y) ICursor(X,Y) NewPt(X,Y) ADD R0, WsPtr, #OlderCsX STMIA R0, {R1,R2, R3,R4, R5,R6} Return NYA MOV R0, R2 ; R0 := plot code MOV R10, #UKPLOTV Push "R9, WsPtr, R14" ; save SWIPlot indicator, WsPtr + link BL VduQQVec Pull "R9, WsPtr, PC", VC ; return to CTidy if no error ; error in UKPLOTV Pull "R9, WsPtr" ; restore SWIPlot indicator and WsPtr ADD R13, R13, #8 ; throw away return to CTidy ; and return address stacked by PLOT TEQ R9, #0 ; called from Wrch ? BEQ VduBadExit ; yes, then go to error exit code B SWIPlotBadExit ; no, then go to SWIPlot error exit VduQQVec ADD R1, WsPtr, #QQ VduGoVec CallAVector ; ; Words for forming ZGORA & ZGEOR for colour actions 0 to 7, where ; 0=Store, 1=OR, 2=AND, 3=EOR, 4=Inverse, 5=No change, ; 6=And Not(colour) ie BIC, 7=Or Not(colour) ; ; ; The values correspond to TBzgoo etc on the 6502 and are stored ; in the following order zgoo,zgeo,zgoe,zgee to allow LDM to be used ; ; Action ; 0 1 2 3 4 5 6 7 ; TBzgoo OR the OR :- F,0,0,F,F,F,0,0 ; TBzgeo EOR the OR :- 0,0,F,F,F,F,0,F ; TBzgoe OR the EOR :- 0,F,0,0,F,F,0,F ; TBzgee EOR the EOR :- F,F,F,0,0,F,0,F ; TBscrmasks * 2_10010111000011111110110001010011 [ {FALSE} TBscrmask & &FFFFFFFF ;Store colour to screen ( OR the OR) & &00000000 ; (EOR the OR) & &00000000 ; ( OR the EOR) & &FFFFFFFF ; (EOR the EOR) & &00000000 ;OR colour to screen & &00000000 & &FFFFFFFF & &FFFFFFFF & &00000000 ;AND & &FFFFFFFF & &00000000 & &FFFFFFFF & &FFFFFFFF ;EOR & &FFFFFFFF & &00000000 & &00000000 & &FFFFFFFF ;Invert & &FFFFFFFF & &FFFFFFFF & &00000000 & &FFFFFFFF ;No change & &FFFFFFFF & &FFFFFFFF & &FFFFFFFF & &00000000 ;BIC (ie AND NOTcol) & &00000000 & &00000000 & &00000000 & &00000000 ;OR NOTcol & &FFFFFFFF & &FFFFFFFF & &FFFFFFFF ] MALIGN 64 ; Invert and NoEffect must be aligned to a multiple ; of 64 for line drawing routines (TMD) ;Interleaved zgora & zgeor values to give invert ; and no effect plotting, used when plot code Invert ; overrides Fg/Bg Gcol colour and action. & &00000000 & &FFFFFFFF & &00000000 & &FFFFFFFF & &00000000 & &FFFFFFFF & &00000000 & &FFFFFFFF & &00000000 & &FFFFFFFF & &00000000 & &FFFFFFFF & &00000000 & &FFFFFFFF & &00000000 & &FFFFFFFF NoEffect & &00000000 & &00000000 & &00000000 & &00000000 & &00000000 & &00000000 & &00000000 & &00000000 & &00000000 & &00000000 & &00000000 & &00000000 & &00000000 & &00000000 & &00000000 & &00000000 ; ***************************************************************************** ; ; EIG - External to internal graphic coordinate conversion ; === ; ; Convert external coordinates (either relative or absolute) into ; internal ones. No windowing is done. ; ; ; On entry, R0 (X), R1 (Y) hold coordinate (external co-ords) ; R2 holds plot mode, where bit2 = 0 for relative (add ECursor) ; = 1 for absolute (add origin) ; ; On exit, R0 (X), R1 (Y) hold internal representation ; R2 preserved ; ; R3 corrupt ; ; The external cursor (GCsX,GCsY) is updated to the new point, ; hence in triangle relative mode, the points are relative to ; the last point specified, not the original. ; EIG ;Do Ycoord first TST R2,#4 ;If bit2 is clear LDREQ R3,[WsPtr,#GCsY] ;then co-ord is relative ADDEQ R1,R1,R3 ; so add previous cursor (ext. rep.) STR R1,[WsPtr,#GCsY] ;Update previous cursor LDR R3,[WsPtr,#OrgY] ;Add origin ADD R1,R1,R3 LDR R3, [WsPtr, #YEigFactor] MOV R1,R1,ASR R3 ;Transform 0-1023 to 0-255 or 0-511 ;Do Xcoord LDREQ R3,[WsPtr,#GCsX] ;If relative then ADDEQ R0,R0,R3 ; add previous cursor (ext. rep.) STR R0,[WsPtr,#GCsX] ;Update previous cursor LDR R3,[WsPtr,#OrgX] ;Add origin ADD R0,R0,R3 LDR R3,[WsPtr,#XEigFactor] MOV R0,R0,ASR R3 ;Transform 0-1279 to 0-639/0-319/0-159 MOV PC,R14 ; ***************************************************************************** ; ; IEG - Inverse of EIG. Convert ICursor to ECursor ; === ; ; On exit, R0 (X), R1 (Y) holds ECursor, ECursor updated ; R2, R3 hold XEigFactor, YEigFactor ; R4, R5 corrupt ; ASSERT GCsIY = GCsIX +4 ASSERT YEigFactor = XEigFactor +4 ASSERT OrgY = OrgX +4 ASSERT GCsY = GCsX +4 IEG ADD R0, WsPtr, #GCsIX LDMIA R0, {R0,R1} ; load graphics cursor (internal) IEGB ADD R2, WsPtr, #XEigFactor LDMIA R2, {R2, R3} ; R2 = XEigFactor; R3 = YEigFactor ADD R4, WsPtr, #OrgX LDMIA R4, {R4, R5} ; R4 = OrgX; R5 = OrgY RSB R0, R4, R0, LSL R2 ; R0 = (X << XEigFactor)-OrgX RSB R1, R5, R1, LSL R3 ; R1 = (Y << YEigFactor)-OrgY ADD R4, WsPtr, #GCsX STMIA R4, {R0,R1} ; write graphics cursor (external) MOV PC,R14 [ {FALSE} ; ***************************************************************************** ; ; Window - Check a coordinate against the graphics window ; ====== ; ; On entry, R0 (X), R1 (Y) holds coordinate to window ; On exit, R0,R1 preserved, ; R3 corrupt ; R2 holds result, as follows: ; ; | | ; 1001 | 1000 | 1010 ; | | ; -----+------+----- ; | | ; 0001 | 0000 | 0010 ; | | ; -----+------+----- ; | | ; 0101 | 0100 | 0110 ; | | ; ; ; Window MOV R2,#0 LDR R3,[WsPtr,#GWBRow] ;Test ycoord against window CMP R1,R3 ORRLT R2,R2,#4 ;Set bit 2 if Y < window LDR R3,[WsPtr,#GWTRow] CMP R3,R1 ORRLT R2,R2,#8 ;Set bit 3 if Y > window LDR R3,[WsPtr,#GWLCol] ;Test xcoord against window CMP R0,R3 ORRLT R2,R2,#1 ;Set bit 0 if X < window LDR R3,[WsPtr,#GWRCol] CMP R3,R0 ORRLT R2,R2,#2 ;Set bit 1 if X > window MOV PC,R14 ] ; ***************************************************************************** ; ; ScreenAddr - Generate screen address of coordinate ; ========== ; ; On entry, R0 (X), R1 (Y) holds coordinate - must be within graphics window ; On exit, R0,R1 preserved, ; R2 holds word address ; R3 holds pixel mask ; ; R7,R8 corrupt ScreenAddr ASSERT LineLength = YWindLimit +4 ADD R7, WsPtr, #YWindLimit LDMIA R7, {R7,R8} ; R7=YWindLimit,R8=LineLength SUB R2, R7, R1 ; flip ycoord into R2 LDR R7, [WsPtr, #ScreenStart] ; add the screen start MLA R2, R8, R2, R7 ; to Ycoord * bytes per row LDR R3, [WsPtr, #XShftFactor] ; R7 := 2,3,4 or 5 MOV R8, R0, ASR R3 ; R8 := word offset ADD R2, R2, R8, LSL #2 ; add on to screen address EOR R7, R0, R8, LSL R3 ; R7 := pixel offset ADD R3, WsPtr, #RAMMaskTb LDR R3, [R3, R7, LSL #2] ; R3 := mask for this pixel MOV PC, R14 ; ***************************************************************************** ; ; PlotPoint - Plot a point in the current colour ; ========= ; ; On entry, R0 (X), R1 (Y) holds coordinate of point ; On exit, R0,R1 preserved ; R2-R8 corrupt ; R9-R11 preserved ; PlotPoint WINDow R0,R1, R2,R3,R4,R5 MOVLT PC, R14 ; If outside window, give up ASSERT LineLength = YWindLimit +4 ADD R7, WsPtr, #YWindLimit LDMIA R7, {R7,R8} ; R7=YWindLimit; R8=LineLength SUB R2, R7, R1 ; flip ycoord into R2 ; *****Change made by DJS ; Original code was: ; ASSERT GColAdr = XShftFactor +4 ; ASSERT ScreenStart = XShftFactor +8 ; ; ADD R4, WsPtr, #XShftFactor ; R4=XShftFactor; R5=GColAdr ; LDMIA R4, {R4, R5, R7} ; R7=ScreenStart ; ; MLA R2, R8, R2, R7 ; R2=ScreenStart+Y*LineLength ; MOV R8, R0, ASR R4 ; R8 := XCoord DIV 4,8,16 ; ; or 32 ; EOR R7, R0, R8, LSL R4 ; R7 := pixel offset in word ; ADD R3, WsPtr, #RAMMaskTb ; LDR R3, [R3, R7, LSL #2] ; R3 := mask for this pixel ; ; EOR R6, R1, #7 ; flip Ycoord ; AND R6, R6, #7 ; line within ecf ; This does not calculate the ecf line correctly, resulting in bugs if (e.g.) ; a destination sprite is not a multiple of 8 pixels high. AND R6, R2, #7 ; R6 := line with ecf ASSERT GColAdr = XShftFactor +4 ASSERT ScreenStart = XShftFactor +8 ADD R4, WsPtr, #XShftFactor ; R4=XShftFactor; R5=GColAdr LDMIA R4, {R4, R5, R7} ; R7=ScreenStart MLA R2, R8, R2, R7 ; R2=ScreenStart+Y*LineLength MOV R8, R0, ASR R4 ; R8 := XCoord DIV 4,8,16 or 32 EOR R7, R0, R8, LSL R4 ; R7 := pixel offset in word ADD R3, WsPtr, #RAMMaskTb LDR R3, [R3, R7, LSL #2] ; R3 := mask for this pixel ; *****End of change made by DJS ADD R5, R5, R6, LSL #3 LDMIA R5, {R5, R6} ; get zgora,zgeor AND R5, R5, R3 ; mask zgora AND R6, R6, R3 ; & zgeor for this pixel [ AvoidScreenReads CMP R5, #&FFFFFFFF LDRNE R7, [R2, R8, LSL #2] | LDR R7, [R2, R8, LSL #2] ] ORR R7, R7, R5 ; and hit the screen EOR R7, R7, R6 STR R7, [R2, R8, LSL #2] MOV PC, R14 ; ***************************************************************************** ; ; ComplexEcfPattern ; ================= ; ; On entry, R0 holds pattern number, where 2..6 means Ecf1..4 ; ; Vdu queue holds ; ; QQ+0 pattern number ; QQ+1 pattern bytes 0 ; | | ; QQ+8 7 ; ; ComplexEcfPat10 is an entry point from simple Ecf setting for 8 bpp modes ; ie simple=complex in 8 bpp modes ; R1 points to Ecf(n) to be programmed. ; ; Corrupts R0..R3 ; ComplexEcfPattern ROUT ; R0 holds 2,3,4,5 for Ecfs 1,2,3,4 ADD R1, WsPtr, #(Ecf1-2*8) ADD R1, R1, R0, LSL #3 ; point R1 at Ecf(n) ComplexEcfPat10 ADD R0, WsPtr, #(QQ+1) LDR R2, [WsPtr, #BBCcompatibleECFs] ; if in BBC mode CMP R2, #0 BEQ ComplexEcfPat20 ; then unmangle the interleaved ; pixels LDMIA R0, {R2,R3} ; else (native) use as given STMIA R1, {R2,R3} B SetColour ; update FgEcf & BgEcf incase they use this Ecf ; R1 points at Ecf(n) ; R0 points at QQ+1 ; ; Uses R2 - pointer into InterleaveTB(BitsPerPix) ; R3 - byte to process 7..0 ; R4 - #1 ; R5 - bit within byte to process 7..0 ; R6 - result byte ; R7 - byte from queue ; R8 - bit mask from InterleaveTB(BitsPerPix,R5) ComplexEcfPat20 ADR R2, InterleaveTB LDR R3, [WsPtr, #Log2BPP] ; 0,1,2,3 means 1,2,4,8 bits per pixel ADD R2, R2, R3, LSL #3 ; point R2 at entry in interleave table MOV R3, #7 ; 7..0 bytes to process MOV R4, #1 ComplexEcfPat30 MOV R5, #7 ; 7..0 bits per byte MOV R6, #0 ; clear result byte LDRB R7, [R0, R3] ; byte from queue ComplexEcfPat40 LDRB R8, [R2, R5] TST R8, R7 ORRNE R6, R6, R4, LSL R5 ; set bit in result byte SUBS R5, R5, #1 BGE ComplexEcfPat40 ; process next bit STRB R6, [R1, R3] ; write de-interleaved byte to Ecf(n) SUBS R3, R3, #1 BGE ComplexEcfPat30 ; process next byte from queue B SetColour ; update FgEcf & BgEcf incase they use this Ecf ; ; InterleaveTB - Values used to unpack BBC style interleaved pixels ; InterleaveTB ; 1 bit per pixel eg Mode 0 & 4 - Log2BPP is 0 = &80, &40, &20, &10, &08, &04, &02, &01 ; 2 bits per pixel eg Mode 1 & 5 - Log2BPP is 1 = &08, &80, &04, &40, &02, &20, &01, &10 ; 4 bits per pixel eg Mode 2 - Log2BPP is 2 = &02, &08, &20, &80, &01, &04, &10, &40 ; 8 bits per pixel - no effect - Log2BPP is 3 = &01, &02, &04, &08, &10, &20, &40, &80 ALIGN ; ***************************************************************************** ; ; LineStyle - Setup dotted line style (does not affect repeat length) ; ========= ; ; Corrupts R0..R3 ; LineStyle ROUT MOV R3, #8 ; Copy 8 bytes in reverse order ADD R1, WsPtr, #QQ+9 ADD R2, WsPtr, #DotLineStyle ; from Queue into DotLineStyle LineSty10 LDRB R0, [R1, #-1]! STRB R0, [R2], #1 SUBS R3, R3, #1 BNE LineSty10 MOV PC, R14 LTORG ;limited offsets ; ***************************************************************************** ; ; DefaultLineStyle - Setup default line style and length ; ; Internal routine, called by mode change, SwitchOutputToSprite and ; FX163,242,n code ; ; out: Can corrupt R0-R3, ; PSR preserved ; DefaultLineStyle ROUT MRS R3, CPSR DefaultLineStylePSRready MOV R0, #8 ; dot pattern repeats after 8 pixels STR R0, [WsPtr, #DotLineLength] LDR R0, =&AAAAAAAA ; on-off pattern STR R0, [WsPtr, #DotLineStyle+0] ; 64 bits of pattern STR R0, [WsPtr, #DotLineStyle+4] MOV R0, #0 ; force a restart of the pattern STR R0, [WsPtr, #LineDotCnt] ; if the user does a "continue" MSR CPSR_f, R3 MOV PC, R14 ; ***************************************************************************** ; ; SetPatLength - Set dotted line repeat length ; ; Internal routine, called by DoOsbyte163_242 ; ; in: R2 = 1..64 => set pattern length to this ; 0 => set default length and pattern ; ; out: Can corrupt R0-R3, ; PSR preserved ; SetPatLength ROUT MRS R3, CPSR CMP R2, #0 BEQ DefaultLineStylePSRready STR R2, [WsPtr, #DotLineLength] ; 1..64 MOV R2, #0 ; force restart of the pattern STR R2, [WsPtr, #LineDotCnt] ; if the user does a "continue" MSR CPSR_f, R3 MOV PC, R14 ; ***************************************************************************** ; ; DefaultEcfPattern - Setup all 4 ecf patterns for this mode ; (does not affect line style) ; ; Internal routine, called by mode change, SwitchOutputToSprite and ; VDU 23_11 ; DefaultEcfPattern ROUT MOV R0, #0 STR R0, [WsPtr, #BBCcompatibleECFs] ;Select BBC compatible ECF mode LDR R0, [WsPtr, #ECFIndex] ADR R1, DefEcfTb ADD R0, R1, R0, LSL #4 ; 16 bytes per entry ADD R1, WsPtr, #Ecf1 LDMIA R0, {R2,R4,R6,R8} ; Get all four patterns for each mode LDMIA R0, {R3,R5,R7,R9} ; duplicate top half into bottom half STMIA R1, {R2-R9} ; Write all 4 Ecfs B SetColour ; update FgEcf & BgEcf in case they are Ecfs DefEcfTb ; Table of default ECFs, indexed by ECFIndex (a mode variable) ; Modes 3,6,7 & 0 & 0 & 0 & 0 ; Mode 0 & &00330033 ;Dark grey (3 black, 1 white) & &CC33CC33 ;Grey (2 black, 2 white) & &CCFFCCFF ;Light grey (1 black, 3 white) & &030C30C0 ;Hatching ; Modes 1,5,8,11,19 & &55665566 ;Red orange (3 red, 1 yellow) & &99669966 ;Orange (2 red, 2 yellow) & &99AA99AA ;Yellow orange (1 red, 3 yellow) & &BBEEBBEE ;Cream (2 white, 2 yellow) ; Modes 2,9,12,14,16,17,20(,21) & &31133113 ;Orange (2 red, 2 yellow) & &51155115 ;Pink (2 red, 2 magenta) & &32233223 ;Yellow green (2 green, 2 yellow) & &37733773 ;Cream (2 white, 2 yellow) ; Modes 4,18,22,23 & &00550055 ;Dark grey (3 black, 1 white) & &AA55AA55 ;Grey (2 black, 2 white) & &AAFFAAFF ;Light grey (1 black, 3 white) & &11224488 ;Hatching ; Modes 10,13,15 & &FFFEFDFC ;Its runnier than yoy'll lik itt & &00010203 & &20212223 & &DFDEDDDC ; ***************************************************************************** ; ; SimpleEcfPattern - Setup simple ecf pattern ; ; Internal routine, called by VDU23_12..15 ; ; in: R0 = 12..15 for ecfs 1..4 ; Vdu queue holds ; QQ+0 pattern number ; QQ+1 pattern bytes 0 ; | | ; QQ+8 7 ; SimpleEcfPattern ROUT ADD R1, WsPtr, #(Ecf1-12*8) ADD R1, R1, R0, LSL #3 ; Point R1 at ECF(n) ADD R2, WsPtr, #(QQ+1) ; Point R2 at first colour in queue ADR R3, SimpEcfTb LDR R4, [WsPtr, #ECFIndex] LDRB R10, [R3, R4] ; Mask for this mode CMP R10, #&FF BEQ SimplEc20 ; 256 colour modes are different LDR R5, [WsPtr, #NColour] ADRL R4, TBFullCol ; Base of full colour table (of bytes) ADD R4, R4, R5 ; Access to table is always ; TBFullCol(NColour+(byte AND NColour)) ; so add NColour in now ! MOV R7, #4 ; There are 4 pairs of bytes in queue SimplEc10 LDRB R6, [R2], #1 ; Get first colour of pair from queue AND R6, R6, R5 ; (byte AND NColour) LDRB R6, [R4, R6] ; The full byte for this colour AND R6, R6, R10 ; Extract required pixels LDRB R9, [R2], #1 ; Get next colour of pair from queue AND R9, R9, R5 ; (byte AND Ncolour) LDRB R9, [R4, R9] BIC R9, R9, R10 ; Extract required pixels and ORR R6, R6, R9 ; build into final pattern STRB R6, [R1, #4] ; Replicate pattern in both halves STRB R6, [R1], #1 ; of ECF SUBS R7, R7, #1 BNE SimplEc10 B SetColour ; update FgEcf & BgEcf in case they use this ; R1 -> ECF(n) ; R2 -> first colour in queue SimplEc20 Push R14 MOV R5, #8 SimplEc30 LDRB R0, [R2], #1 ; Get byte from queue AND R3, R0, #&C0 ; Extract Tint AND R0, R0, #&3F ; Colour BL AddTintToColour ; Recombine in our funny fashion STRB R0, [R1], #1 ; And store in the Ecf SUBS R5, R5, #1 BNE SimplEc30 Pull R14 B SetColour ; Update FgEcf & BgEcf incase they use this Ecf SimpEcfTb ; Table of masks for simple ECFs, indexed by ECFIndex ; (bit set => use left pixel, bit clear => use right pixel) = &00 ; Modes 3,6,7 = &33 ; Mode 0 = &33 ; Modes 1,5,8,11,19 = &0F ; Modes 2,9,12,14,16,17,20 = &55 ; Modes 4,18,21,22 = &FF ; Modes 10,13,15 ALIGN ; ***************************************************************************** ; ; ExportedHLine - Routine exported via VDU variable HLineAddr ; ; in: R0,R2 = X coords in some order (internal coords) ; R1 = Y coord (internal coord) ; R3 = 0 => no effect ; R3 = 1 => foreground colour/action ; R3 = 2 => invert ; R3 = 3 => background colour/action ; R3 >= 4 => R3 -> eight word pairs ; ExportedHLine ROUT Push "R0,R2,R4-R10,WsPtr,R14" VDWS WsPtr CMP R3, #4 BCS %FT10 ; *****Change made by DJS ; Original code was: ; MOV R3, R3, LSL #30 ; put bottom 2 bits into top 2 bits ; CMP R3, #&40000000 ; set lots of flags ; ; ADDMI R3, WsPtr, #BgEcfOraEor ; if 0 or 3 ; ADRCC R3, NoEffect ; if 0 ; ADDEQ R3, WsPtr, #FgEcfOraEor ; if 1 ; ADRVS R3, Invert ; if 2 MOVS R3, R3, LSL #31 ;Put bit 1 in C, NOT(bit 0) in Z ADR R3, NoEffect ; if 0, 1, 2 or 3 ADDNE R3, WsPtr, #FgEcfOraEor ; if 1 or 3 ADRCS R3, Invert ; if 2 or 3 ADDHI R3, WsPtr, #BgEcfOraEor ; if CS & NE - i.e. 3 ; *****End of change made by DJS 10 STR R3, [WsPtr, #GColAdr] ; save address of Ecf to plot with BL HLine CLRV Pull "R0,R2,R4-R10,WsPtr,PC" ; ***************************************************************************** ; ; NewHLine - Horizontal line draw an even newer version what does 8 words ; ======== at a time if it can ; ; On entry, R0 (X), R1 (Y) holds coordinate of point ; R2 holds right hand XCoord ; On exit, R3 preserved ; R4..R10 corrupt ; PSR preserved ; ; N.B. R11 WILL BE PRESERVED - This is assumed by rectangle fill and all circle ; operations ; HLine SortT R0, R2, R4 ; Sort the Xcoord into order R0<=R2 NewHLine ROUT ; Entry point for sorted Xcoords ADD R4, WsPtr, #GWLCol LDMIA R4, {R4-R7} ; GWLCol,GWBRow,GWRCol,GWTRow CMP R7, R1 ; Test ycoord against window CMPGE R1, R5 CMPGE R6, R0 ; Test xcoords against window CMPGE R2, R4 MOVLT PC, R14 ; Quit if above,below,left or right ; of window Greatest R0, R0, R4 ; If start of line to left of window ; pull to window edge Least R2, R2, R6 ; If end of line to right of window ; pull to window edge Push "R0-R3,R11,Link" ; ; Now, R0 holds Start (leftX), R1 holds Y and R2 holds End (rightX) ; ; Now pick up ecf word and form the ZGORA & ZGEOR masks ; ASSERT LineLength = YWindLimit +4 ASSERT GColAdr = XShftFactor +4 ASSERT ScreenStart = XShftFactor +8 ADD R11, WsPtr, #YWindLimit LDMIA R11, {R10-R11} ; R10 = YWindLimit; R11 = LineLength ADD R9, WsPtr, #XShftFactor LDMIA R9, {R7-R9} ; R7 = XShftFactor; R8 = GColAdr ; R9 = ScreenStart SUB R1, R10, R1 ; flip ycoord into R1 AND R6, R1, #7 ; R6 = line within ecf ADD R8, R8, R6, LSL #3 ; R8 -> zgora, zgeor LDMIA R8, {R8, R10} ; R8 = zgora; R10 = zgeor MLA R9, R11, R1, R9 ; R9 -> start of this scan line MOV R6, R0, LSR R7 ; R6 = X1Coord word offset MOV R11, R2, LSR R7 ; R11 = X2Coord word offset ADD R9, R9, R6, LSL #2 ; R9 = address of lefthand word ; *****Change made by DJS ; Original code was: ; ; EOR R4, R0, R6, LSL R7 ; R4 = X1 pixel offset ; EOR R5, R2, R11, LSL R7 ; R5 = X2 pixel offset ; ; SUBS R11, R11, R6 ; R11 = number of words -1 ; ; and set Z on it ; ; ADD R7, WsPtr, #RAMMaskTb ; R7 -> MaskTb for this mode ; LDR R6, [R7, R4, LSL #2] ; R6 = left mask ; LDR R14, [R7, R5, LSL #2] ; R14 = right mask ; ; SUB R7, R14, #1 ; in right mask set all bits lower ; ORR R14, R14, R7 ; by RM = RM OR (RM-1) ; ; RSB R7, R6, #0 ; in left mask, set all bits higher ; ORR R6, R6, R7 ; by LM = LM OR (-LM) ; ; The following code is shorter and faster. SUBS R11, R11, R6 ; R11 = number of words -1 ; and set Z on it RSB R7, R7, #5 ; R7 = Log2BPC (quicker than loading!) MOV R14, #31 ; constant to extract bit offsets AND R4, R14, R0, LSL R7 ; R4 = start of X1 pixel offset AND R5, R14, R2, LSL R7 ; R5 = start of X2 pixel offset MOV R14, #-1 ; Useful both as -1 and as &FFFFFFFF SUB R5, R5, R14, LSL R7 ; R5 = end of X2 pixel offset MOV R6, R14, LSL R4 ; R6 = left mask MVN R14, R14, LSL R5 ; R14 = right mask ; *****End of change made by DJS ANDEQ R14, R14, R6 ; if start word = end word BEQ %FT40 ; then combine masks [ AvoidScreenReads AND R1, R8, R6 ; zgora AND left mask CMP R1, #&FFFFFFFF LDRNE R0, [R9] ; do left hand word of line | LDR R0, [R9] ; do left hand word of line AND R1, R8, R6 ; zgora AND left mask ] AND R2, R10, R6 ; zgeor AND left mask ORR R0, R0, R1 ; screen OR or mask EOR R0, R0, R2 ; EOR eor mask STR R0, [R9], #4 ; store to screen SUBS R11, R11, #1 ; decrement word count, if =0 BEQ %FT40 ; then plot RH partial word CMP R8, #-1 ; if R8 = -1 then store action BNE %FT05 ; else do it the slow way MVN R0, R10 ; R0 = word of colour to plot MOV R1, R0 MOV R2, R0 MOV R3, R0 ADDS R8, R8, R11, LSR #3 ; R8 = (no. of words DIV 8)-1 BCC %FT60 ; must be fewer than 8 MOV R4, R0 MOV R5, R0 MOV R6, R0 MOV R7, R0 ; *****Additional message inserted by DJS [ ((.-KernelBase) :AND: 15) = 12 ! 0, "HLine critical loop has bad alignment for running in RAM" ] ; *****End of message inserted by DJS 50 STMCSIA R9!, {R0-R7} ; write 8 words to screen if >=0 STMHIIA R9!, {R0-R7} ; write 8 words to screen if > 0 SUBS R8, R8, #2 ; try for another 16 BCS %BT50 60 TST R11, #4 ; can we do 4 words ? STMNEIA R9!, {R0-R3} ; write 4 words to screen TST R11, #2 ; can we do 2 words ? STMNEIA R9!, {R0-R1} ; write 2 words to screen TST R11, #1 ; can we do 1 word ? STRNE R0, [R9], #4 ; write 1 word to screen AND R10, R10, R14 ; do partial word at end [ AvoidScreenReads CMP R14, #&FFFFFFFF LDRNE R0, [R9] | LDR R0, [R9] ] OrrEor R0,R0, R14,R10 STR R0, [R9],#4 70 Pull "R0-R3,R11,PC" ; code for when not store action 05 SUBS R11, R11, #8 ; else try for 8 words at a time BMI %FT20 ; failed, so try for 4 at a time 10 LDMIA R9, {R0-R7} OrrEor R0,R0, R8,R10 ; Write 8 words to screen OrrEor R1,R1, R8,R10 OrrEor R2,R2, R8,R10 OrrEor R3,R3, R8,R10 OrrEor R4,R4, R8,R10 OrrEor R5,R5, R8,R10 OrrEor R6,R6, R8,R10 OrrEor R7,R7, R8,R10 STMIA R9!, {R0-R7} SUBS R11, R11, #8 ; try for another 8 BPL %BT10 20 ADDS R11, R11, #4 ; can we do 4 words ? BMI %FT30 ; no, then do 1 word at a time LDMIA R9, {R0-R3} OrrEor R0,R0, R8,R10 ; Write 4 words to screen OrrEor R1,R1, R8,R10 OrrEor R2,R2, R8,R10 OrrEor R3,R3, R8,R10 STMIA R9!, {R0-R3} SUB R11, R11, #4 30 ADDS R11, R11, #4 ; Correct for earlier SUB #4 40 ; Plot single words ANDEQ R8, R8, R14 ; If EQ, this is RH word, ANDEQ R10, R10, R14 ; so mask down to required pixels LDR R0, [R9] OrrEor R0,R0, R8,R10 STR R0, [R9],#4 SUBS R11,R11,#1 BPL %BT40 Pull "R0-R3,R11,PC" ; ***************************************************************************** ; ; NewVLine - Vertical line draw for non-dotted solid pattern lines ; ; in: R0 = R2 = X coord ; R1 = bottom Y coord ; R3 = top Y coord ; ; out: R4-R10 corrupt ; PSR preserved ; NewVLine ROUT ; Entry point for sorted Ycoords ADD R4, WsPtr, #GWLCol LDMIA R4, {R4-R7} ; GWLCol,GWBRow,GWRCol,GWTRow CMP R7, R1 ; Test ycoord against window CMPGE R3, R5 CMPGE R6, R0 ; Test xcoords against window CMPGE R2, R4 MOVLT PC, R14 ; Quit if above,below,left or right ; of window Greatest R1, R1, R5 ; If bottom of line below window ; pull to window edge Least R3, R3, R7 ; If top of line above window ; pull to window edge Push "R0-R3,R11,Link" ; Now, R0 holds X, R1 holds bottom Y and R3 holds top Y ; ; Now pick up ecf word and form the ZGORA & ZGEOR masks ; ASSERT LineLength = YWindLimit +4 ASSERT GColAdr = XShftFactor +4 ASSERT ScreenStart = XShftFactor +8 ADD R11, WsPtr, #YWindLimit LDMIA R11, {R10-R11} ; R10 = YWindLimit; R11 = LineLength ADD R9, WsPtr, #XShftFactor LDMIA R9, {R7-R9} ; R7 = XShftFactor; R8 = GColAdr ; R9 = ScreenStart SUB R1, R3, R1 ; R1 = number of dots to do -1 SUB R3, R10, R3 ; R3 = flipped top ycoord MLA R9, R11, R3, R9 ; R9 -> start of this scan line LDMIA R8, {R8, R10} ; R8 = zgora; R10 = zgeor ; (no need to index with Y cos we ; know there's no ECF pattern) MOV R6, R0, LSR R7 ; R6 = X coord word offset ADD R9, R9, R6, LSL #2 ; R9 = address of top word EOR R4, R0, R6, LSL R7 ; R4 = X pixel offset ADD R7, WsPtr, #RAMMaskTb ; R7 -> MaskTb for this mode LDR R6, [R7, R4, LSL #2] ; R6 = pixel mask AND R8, R8, R6 ; zgora = zgora AND pixelmask AND R10, R10, R6 ; zgeor = zgeor AND pixelmask [ AvoidScreenReads CMP R8, #&FFFFFFFF BEQ %FT20 ] ; now do the plotting 10 LDR R6, [R9] ORR R6, R6, R8 EOR R6, R6, R10 STR R6, [R9], R11 SUBS R1, R1, #1 BPL %BT10 Pull "R0-R3,R11,PC" [ AvoidScreenReads 20 MVN R6, R10 25 STR R6, [R9], R11 SUBS R1, R1, #1 BPL %BT25 Pull "R0-R3,R11,PC" ] ; ***************************************************************************** ; ; DoubleHLine - Draw 2 horizontal lines ; =========== ; ; On entry, R0 (X) - Left most point ; R1 (Y) - y ordinate of line ; R2 (X) - Right most point ; R3 (X) - end of left most line ; R4 (X) - start of right most line ; ; On exit, R0..R10 preserved } subject ; R11 corrupt } to change ; DoubleHLine Push "R0-R10, R14" MOV R2, R3 ; draw left line, R0->R3 inc. BL HLine LDMIB R13, {R1-R4} MOV R0, R4 ; draw right line, R4->R2 inc. BL HLine Pull "R0-R10, PC" ; ***************************************************************************** ; ; ExtractTintAndColour - Convert 256-colour mode byte value into ; colour and tint ; ; Internal routine, called by ReadPixelColour, SwiReadPoint ; ; in: R0 = single screen pixel (ie 'half' user pixel in double modes) ; ; out: R0 corrupt ; R2 = colour value (GCOL a,colour) ; R3 = tint Vdu 23,17 etc ; ExtractTintAndColour ROUT ; R0 := B3 G3 G2 R3 B2 R2 T1 T0 MOV R3, R0, LSL #6 ; R3 := T1 T0 0 0 0 0 0 0 AND R3, R3, #&C0 AND R2, R0, #&84 ; R2 := B3 0 0 0 0 R2 0 0 TST R0, #8 ORRNE R2, R2, #&40 ; R2 := B3 B2 0 0 0 R2 0 0 AND R0, R0, #&70 ; R0 := 0 G3 G2 R3 0 0 0 0 ORR R2, R2, R0, LSR #1 ; R2 := B3 B2 G3 G2 R3 R2 0 0 MOV R2, R2, LSR #2 ; R2 := 0 0 B3 B2 G3 G2 R3 R2 MOV PC, R14 ; ***************************************************************************** ; ; SwiReadPoint - Read colour of screen pixel ; ; External routine - entry point for SWI OS_ReadPoint ; ; in: R0, R1 = X, Y coordinate of point ; ; out: R2 = colour (as in GCOL a,colour) } -1 if off screen ; R3 = tint value (as in VDU 23,17 etc) } 0 if off screen ; R4 = 0/-1 for On/Off screen ; R0,R1, R5-R9 preserved (R10-R12 preserved by MOS) ; SwiReadPoint ROUT WritePSRc SVC_mode, WsPtr ; re-enable interrupts VDWS WsPtr ; point R12 at vdu driver workspace [ {TRUE} GraphicsMode R10 ; if not a graphics mode then give up now! BNE %FT20 | LDR R10, [WsPtr, #NPix] ; if not a graphics mode then CMP R10, #0 ; indicate off screen BEQ %FT20 ] Push "R0-R9, R14" ; save registers ADD R7, WsPtr, #GCsX LDMIA R7, {R8,R9} ; preserve GCsX,GCsY around EIG MOV R2, #4 ; absolute coord BL EIG STMIA R7, {R8,R9} ; restore GcsX,GCsY WINDow R0,R1, R2,R3,R4,R5 BLT %FT10 ; outside window Push "R0,R1" ; save internal coords BL PreWrchCursor ; remove any split cursors etc Pull "R0,R1" ; R0,R1,R2 ,R3 ,R4 ,R5 ,R6 ,R7 ,R8 BL ScreenAddr ; in :X ,Y ; out:X ,Y ,Adr,Msk, , , ,crp,crp LDR R8, [WsPtr, #NColour] ;amg - changes here to cope with 16/32bpp which will also return an NCOL with b4-b7 set ; TST R8, #&F0 ; if NColour=63 ; MOVNE R8, #&FF ; then use 255 CMP R8,#63 MOVEQ R8,#255 LDR R9, [WsPtr, #XShftFactor] LDR R10, [WsPtr, #NPix] LDR R11, [WsPtr, #Log2BPC] BitLOffset R7,R0, R9,R10,R11 ; R7 := bit position to align to LDR R0, [R2] AND R0, R8, R0, LSR R7 ; extract one pixel TEQ R8,#255 MOVNE R2,R0 MOVNE R3,#0 BLEQ ExtractTintAndColour ; TST R8, #&F0 ; if not a 256 colour mode ; MOVEQ R2, R0 ; colour = pixel ; MOVEQ R3, #0 ; tint = 0 ; BLNE ExtractTintAndColour ; else extract colour & tint from pixel MOV R4, #0 ; indicate on screen ADD R0, R13, #2*4 ; point to stacked R2 STMIA R0, {R2-R4} BL PostWrchCursor Pull "R0-R9, R14" ; restore R0-R9 & return address BIC R14, R14, #V_bit ExitSWIHandler 10 Pull "R0-R9, R14" ; restore R0-R9 & return address 20 MOV R2, #-1 MOV R3, #0 MOV R4, #-1 BIC R14, R14, #V_bit ExitSWIHandler ; ***************************************************************************** ; ; GenCircleParm - Generate a control block for a circle ; ; Internal routine, called by CircleOutline, CircleFill, GenArcParmBlk ; ; in: R0 (X), R1(Y) centre of circle ; R2 (X), R3(Y) point on circumference ; ; out: R0-R7 hold the following control block ; R0 - xPnt (CurrentX - relative to centre) ; R1 - yPnt (CurrentY - relative to centre) ; R2 - sum (Bres) ; R3 - upcnt ; R4 - downcnt ; R5 - CentreX ; R6 - CentreY ; R7 - Aspect (pixel shape : 0 square, 1 horz rect, 2 vert rect) ; R8-R11 undefined ; GenCircleParm Push R14 LDR R11, [WsPtr, #AspectRatio] SUB R7, R2, R0 TST R11, #1 ; if pixels are horz rects, adjust MOVNE R7, R7, LSL #1 ; x distance MUL R2, R7, R7 ; R2 = (x-cx)^2 SUB R7, R3, R1 TST R11, #2 ; if pixels are vert rects, adjust MOVNE R7, R7, LSL #1 ; y distance MLA R2, R7, R7, R2 ; rawradsqr=(x-cx)^2 + (y-cy)^2 MOV R7, R2 BL SquareRoot ADD R2, R2, R8 ; radsqr=rawradsqr+rawrad STR R2, [WsPtr, #CircleRadSquare] ; needed in seg. line calc MOV R7, R2 BL SquareRoot MOV R4, R8 ; R4=rad, R2=radsqr ; ; Now build the parameter block proper ; ; R0 = CentreX, R1 = CentreY, R2 = radsqr, R4 = rad ; MUL R9, R4, R4 ; R9=rad*rad SUB R2, R2, R9 ; Sum=radsqu-rad*rad MOV R5, R0 ; CentreX MOV R6, R1 ; CentreY MOV R0, R4 ; xPnt starts at rad ADD R4, R4, R4 SUB R4, R4, #1 ; downcnt = 2*rad-1 MOV R1, #0 ; yPnt starts at 0 MOV R3, #1 ; upcnt = 1 LDR R7, [WsPtr,#AspectRatio] ; taking account of pixel shape LDR R11, [WsPtr, #CursorFlags] TST R11, #ClipBoxEnableBit BLNE ClipCircle CMP R7, #1 MOVEQ R0, R0, ASR #1 ; if horz pixel (ie like mode2) ADDEQ R2, R2, R4 SUBEQ R4, R4, #2 SUBGT R2, R2, R3 ; if vert pixel (ie like mode0) ADDGT R3, R3, #2 Pull PC ; ***************************************************************************** ; ; AdvCircleParm - Advance a set of circle parameters ; ; Internal routine, called by CircleOutline, CircleFill, CircleArc, ; SegmentFill, SectorFill ; ; in: R0..R7 hold a circle parameter block ; ; out: R0 (X), R1 (Y) updated ; C=1 <=> R1 (Y) has changed ; Z preserved ; ; Format of a control block ; R0 - xPnt (CurrentX - relative to centre) ; R1 - yPnt (CurrentY - relative to centre) ; R2 - sum (Bres) ; R3 - upcnt ; R4 - downcnt ; R5 - CentreX ; R6 - CentreY ; R7 - Aspect (pixel shape : 0 square, 1 horz rect, 2 vert rect) ; AdvCircleParm ROUT CMP R2, R3 ; if sum >= upcnt advance Y only BGE %FT10 SUB R0, R0, #1 ; else step xPnt inward one point ADD R2, R2, R4 ; Sum := Sum + DownCnt SUB R4, R4, #2 ; DownCnt = next lower odd number TST R7, #1 ; if pixels are horizontal rectangles ADDNE R2, R2, R4 ; modify sum again, so x steps at SUBNE R4, R4, #2 ; half normal rate CMP R2, R3 BGE %FT10 CLC ; if not doing Y, indicate with C=0 MOV PC, R14 10 ; if sum >= upcnt then advance Y ADD R1, R1, #1 ; step yPnt up a line SUB R2, R2, R3 ; Sum := Sum - UpCnt ADD R3, R3, #2 ; UpCnt = next higher odd number TST R7, #2 ; if pixels are vertical rectangles SUBNE R2, R2, R3 ; modify sum again, so y steps ADDNE R3, R3, #2 ; at half normal rate SEC ; Y modified, so return C=1 MOV PC, R14 ; ***************************************************************************** ; ; SquareRoot - Calculate the square root of a 32-bit number ; ; Internal routine, called by GenSegParmBlk, GenCircleParm ; ; SquareRootAlt is a alternative routine which specifies the precision ; of the result in R11 (SquareRoot produces a 16-bit result) ; ; in: R7 = number to squareroot ; ; out: R8 = result ; R9-R11 corrupted ; R9 temp ; R10 sqdiff ; R11 counter ; SquareRoot ROUT MOV R11, #16 ; 16 bit result SquareRootAlt MOV R8, #0 ; result=0 MOV R10, #0 ; sqdiff=0 10 ; *****Change made by DJS ; Original code was: ; ADDS R7, R7, R7 ; (sqdiff,number) = (sqdiff,number)*4 ; ADC R10, R10, R10 ; ADDS R7, R7, R7 ; ADCS R10, R10, R10 ; (C:=0 we hope!) MOVS R10, R10, LSL #2 ; C:=0 (we hope!) while doing (sqdiff, ORR R10, R10, R7, LSR #30 ; number) := (sqdiff, number) * 4 MOV R7, R7, LSL #2 ; *****End of change made by DJS SBCS R9, R10, R8, LSL #2 ; C=0 here, so try to subtract ; result*4 +1 from sqdiff MOVCS R10, R9 ; if successful then shift in a "1" bit ADC R8, R8, R8 ; else shift in a "0" bit SUBS R11, R11, #1 ; decrement loop counter BNE %BT10 MOV PC, R14 ; ***************************************************************************** ; ; DoOsWord13 - Read graphics cursors (in external coords) ; ; in: R1 -> control block ; ; out: [R1+0..1] = old cursor X ; [R1+2..3] = old cursor Y ; [R1+4..5] = current cursor X ; [R1+6..7] = current cursor Y ; ASSERT OldCsY = OldCsX +4 ASSERT YEigFactor = XEigFactor +4 ASSERT OrgY = OrgX +4 ASSERT GCsY = GCsX +4 DoOsWord13 ROUT Push "R0-R6" MOV R6, R1 ; pointer to control block ADD R0, WsPtr, #OldCsX LDMIA R0, {R0, R1} ADD R2, WsPtr, #XEigFactor LDMIA R2, {R2, R3} ; R2 = XEigFactor; R3 = YEigFactor ADD R4, WsPtr, #OrgX LDMIA R4, {R4, R5} ; R4 = OrgX; R5 = OrgY RSB R0, R4, R0, LSL R2 ; R0 = (X << XEigFactor)-OrgX RSB R1, R5, R1, LSL R3 ; R1 = (Y << YEigFactor)-OrgY [ NoARMv6 :LOR: NoUnaligned STRB R0, [R6], #1 MOV R0, R0, LSR #8 STRB R0, [R6], #1 STRB R1, [R6], #1 MOV R1, R1, LSR #8 STRB R1, [R6], #1 | ; Use unaligned halfword stores available from ARMv6 STRH R0, [R6], #2 STRH R1, [R6], #2 ] ADD R0, WsPtr, #GCsX LDMIA R0, {R0, R1} ; get current cursor [ NoARMv6 :LOR: NoUnaligned STRB R0, [R6], #1 MOV R0, R0, LSR #8 STRB R0, [R6], #1 STRB R1, [R6], #1 MOV R1, R1, LSR #8 STRB R1, [R6], #1 | ; Use unaligned halfword stores available from ARMv6 STRH R0, [R6], #2 STRH R1, [R6] ] Pull "R0-R6" MOV PC, R14 LTORG END