; 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.VduGrafI ; ; ARTHUR OPERATING SYSTEM - Vdu Drivers ; ======================= ; ; Vdu driver code - Sprite stuff ; ; Author R C Manby ; Date 10.11.86 ; ; CHANGES ; ------- ; 12.04.94 W Turner Updated to allow the use of 1bpp masks ; 12.01.95 G Simms Fixed MED-04130 where New format sprites with ; LH wastage were being created. ; ***************************************************************************** ; ; FlipAboutXAxis - Flip sprite about X axis ; ; External routine ; ; in: R2 -> sprite ; FlipAboutXAxis ROUT Push R14 BL MaskOffset MOV R7, R0 ; 0/offset for nomask/mask LDR R4, [R2, #spWidth] ; width-1 LDR R5, [R2, #spHeight] ; height-1 LDR R6, [R2, #spImage] TEQ R5, #0 BEQ %FT05 ; nothing to do, if only 1 row ADD R0, R2, R6 ; R0 -> top row in image ADD R3, R4, #1 ; width MUL R1, R5, R3 ; R1 = word offset to bottom row ADD R1, R0, R1, LSL #2 ; R1 -> bottom row in image Push "R0-R1, R2, R4-R5, R7" ; preserve ptrs & mask offset BL FlipAbX10 ; flip main image Pull "R0-R1, R2, R4-R5, R7" CMP R7, #0 BEQ %FT05 ; No mask so skip this bit ADD R0, R0, R7 ; Update the start pointer ;If a new format sprite (we know it has a mask) ;redo R1 & call the 'GetMaskspWidth' routine to alter R3 LDR R8, [R2, #spMode] ; Get sprite mode MOVS R8, R8, LSR #27 ; Isolate sprite type & test for 0 ADDEQ R1, R1, R7 ; Old format, so simple BEQ %FT04 ;Here, we know it is a 1bpp or alpha mask MOV R6, R5 ; Better keep R5 safe, we'll need it in a bit MOV R5, R4 ; The sub wants R4 in r5 BL GetMaskspWidth ; Update the 'width' if needed ADD R3, R5, #1 ; R3=width in words MUL R1, R6, R3 ; R1 = word offset to bottom row ADD R1, R0, R1, LSL #2 ; R1 -> Bottom row in image 04 BL FlipAbX10 ; flip mask 05 Pull R14 RETURNVC ; ***************************************************************************** ; ; FlipAbX10 - Flip area given ptrs and width ; ; Internal routine, called by FlipAboutXAxis ; ; in: R0 -> top row ; R1 -> bottom row ; R3 = width in words ; ; out: R0-R2,R4-R11 corrupted ; R3 preserved ; FlipAbX10 ROUT 10 SUBS R2, R3, #4 ; initialise width count BLT %FT30 20 ; flip in blocks of 4 words LDMIA R0, {R4-R7} LDMIA R1, {R8-R11} STMIA R1!, {R4-R7} STMIA R0!, {R8-R11} SUBS R2, R2, #4 BGE %BT20 30 ADDS R2, R2, #4 BLE %FT50 40 ; do remaining words one by one LDR R4, [R0] LDR R8, [R1] STR R4, [R1], #4 STR R8, [R0], #4 SUBS R2, R2, #1 BNE %BT40 50 SUB R1, R1, R3, LSL #3 ; point to previous row CMP R1, R0 BHI %BT10 ; loop until pointers meet or cross MOV PC, R14 ; only R3 preserved ; ***************************************************************************** ; ; FlipAboutYAxis - Flip a sprite about Y axis ; ; External routine ; ; in: R2 -> sprite ; FlipAboutYAxis ROUT Push R14 BL MaskOffset MOV R8, R0 ;Bung result in R8 'till we want it... ADD R3, R2, #spWidth LDMIA R3, {R3-R7} ; R3 ,R4 ,R5 ,R6 ,R7 ; spWidth,spHeight,spLBit,spRBit,spImage ADD R3, R3, #1 ; use width as row offset (words) MUL R4, R3, R4 ; R4=width x (height-1) in words ADD R4, R4, R3 ; R4=width x height in words ADD R4, R7, R4, LSL #2 ; offset past end of sprite image ADD R4, R4, R2 ; address past end of image RSB R5, R5, #31 ; reflect LBit & RBit RSB R6, R6, #31 STR R5, [R2, #spRBit] ; new RBit := 31- old LBit STR R6, [R2, #spLBit] ; new LBit := 31- old RBit ADD R0, R2, R7 ; R0 -> start of first row LDR R11, [WsPtr, #SprBytesPerChar] ; shift factor to ; reach next pixel LDR R9, [WsPtr, #SprWriteNColour] ; mask for leftmost pixel MOV R10, R9, ROR R11 ; mask for rightmost pixel Push "R0, R2, R5-R8" BL FlipAbY10 ; Do the sprite image Pull "R0, R2, R5-R8" Push "R0,R8" LDR R8, [R2, #spMode] ; Get sprite mode MOVS R8, R8, LSR #27 ; Isolate sprite type & test for 0 BEQ %FT03 ; If old format ignore next bit ; If this is a new format sprite we may have to remove any LH ; wastage that was created by the flip. CMP R6, #0 ; Is there any LH wastage? BEQ %FT03 ; If not skip the next bit. MOV R8, R6 BL RemLHWastage ; If this is a new format sprite then LH wastage = 0 and the RH wastage ; is the same as it was to start with. RSB R5, R6, #31 ; restore old RBit MOV R6, #0 STR R5, [R2, #spRBit] ; new RBit := 31- old LBit STR R6, [R2, #spLBit] ; new LBit := 0 03 Pull "R0,R8" CMP R8, #0 ; Does the sprite have a mask? BEQ %FT05 ; Nope, so skip the mask flip! ;Now, is it an old or new sprite? LDR R1, [R2, #spMode] ; Get sprite mode ADD R0, R0, R8 ; R0 points to start of mask MOVS R1, R1, LSR #27 ; Isolate sprite type & test for 0 ADDEQ R4, R4, R8 ;R4 points to end of mask now BEQ %FT04 ;Skip the next bit (it's for new format only) Push "R5" LDR R5, [R2, #spWidth] BL GetMaskspWidth ADD R3, R5, #1 ;R3 is new row offset (words) Pull "R5" Push "R8" ;Last Bit used for mask, this will enable ;us to remove the left hand wastage after ;the flip LDR R4, [R2, #spHeight] LDR R8, [R2, #spTrans] MUL R4, R3, R4 ; R4=width x (height-1) in words ADD R4, R4, R3 ; R4=width x height in words ADD R4, R8, R4, LSL #2 ; offset past end of sprite mask ADD R4, R4, R2 ; address past end of mask ADD R0, R2, R8 ; R0 -> start of first row of mask ; LDR R11, [WsPtr, #SprBytesPerChar] ; shift factor to ; reach next pixel ; LDR R9, [WsPtr, #SprWriteNColour] ; mask for leftmost pixel MOV R11, #1 MOV R9, #1 MOV R10, R9, ROR R11 ; mask for rightmost pixel Push "R0" BL FlipAbY10 ; Now do the mask Pull "R0" Pull "R8" ; Retrieve last bit used to find LHwastage RSB R8, R8, #31 CMP R8, #0 BEQ %FT05 BL RemLHWastage B %FT05 04 BL FlipAbY10 ; Now do the mask 05 Pull R14 RETURNVC ; ***************************************************************************** ; ; FlipAbY10 - Flip area given ptrs and width ; ; Internal routine, called by FlipAboutYAxis ; ; N.B. This reflects 'user pixels', ie in double pixel modes it ; reflects pairs of screen pixels, this should not matter. ; ; ON ENTRY, we have R0, R3-R4, R9-R11 ; ON EXIT, of these, only R0 is corrupted ; Internally: ; R0 RowPtr, R1 LPtr , R2 RPtr , R3 Row offset, R4 EndAdr ; R5 LWord , R6 RWord, R7 LTemp, R8 RTemp , R9 LPixMask ; R10 RPixMask, R11 ShftFactor, R14 Cnt ; R0-R2, R5-R8 get corrupted FlipAbY10 Push R14 10 MOV R1, R0 ; R1 -> left end of row ADD R0, R0, R3, LSL #2 ; R0 -> past right end of row MOV R2, R0 ; R2 := R0 20 LDR R5, [R1] LDR R6, [R2, #-4]! MOV R14, #32 ; total number of bits to process 30 ; circular pixel shift of LWord & RWord AND R7, R5, R9 ; leftmost pixel (LSPart of LWord) AND R8, R6, R10 ; rightmost pixel (MSPart of RWord) ORR R5, R8, R5, LSR R11 ORR R6, R7, R6, LSL R11 SUBS R14, R14, R11 ; process next pixel BNE %BT30 ; TMD 12-Jan-88 bug fixed here ; I had changed RCM's code and put BCS STR R5, [R1], #4 STR R6, [R2] CMP R2, R1 BHI %BT20 ; loop until pointers meet or cross CMP R0, R4 BCC %BT10 ; if address < end, reflect next row Pull R14 MOV PC, R14 ; ***************************************************************************** ; ; RemLHWastage - Dedicated routine to remove x bits of LH wastage ; after a new format Sprite has been flipped ; ; On Entry: R0 = Start of data ; R3 = Row Offset ; R4 = End of data ; R8 = No. Bits to Remove ; R0 RowPtr, R1 LPtr , R2 RPtr , R3 Row offset, R4 EndAdr RemLHWastage Push "R1,R2,R5-R8,R14" 10 ;start of loop for each line MOV R1, R0 ; R1 -> left end of row ADD R0, R0, R3, LSL #2 ; R0 -> past right end of row SUB R2, R0, #4 ; R2 -> last word in row ; (used for loop check) LDR R5, [R1] ; load current word 20 ;Start of loop for each word CMP R2, R1 ;If we have reached the last word then just shift and store MOVEQ R5, R5, LSR R8 STREQ R5, [R1] BEQ %FT99 ;There are more words left so we need to shift in the LSBits from the next ;word. LDR R6, [R1, #4] ; load next word MOV R5, R5, LSR R8 ; Throw away wastage bits in current word RSB R14, R8, #32 MOV R7, R6, LSL R14 ; Move LSBs from next word to current ORR R5, R5, R7 STR R5, [R1],#4 ; store current word MOV R5, R6 ; move next word to current word ready for ; next loop iteration. B %BT20 ; CMP R2, R1 ; BHI %BT20 ; loop until pointers meet or cross 99 CMP R0, R4 BCC %BT10 ; if address < end, reflect next row Pull "R1,R2,R5-R8,R14" MOV PC, R14 END