; 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. ; ; > Sources.SprAdjSize ;;---------------------------------------------------------------------------- ;; AdjustManyRows or Columns ;;---------------------------------------------------------------------------- MakeSpriteErrorBlock InvalidRowOrCol,,InvRC MakeSpriteErrorBlock NoRoomToInsert,,NoIRoom input_out_of_range ADR R0, ErrorBlock_InvalidRowOrCol addr r1, Title BL copy_error_one ; Always sets the V bit Pull "R1-R11,PC" no_room_to_insert ADR R0, ErrorBlock_NoRoomToInsert addr r1, Title BL copy_error_one ; Always sets the V bit Pull "R1-R11,PC" ; ---------------------------------------------------------- Go_InsertDeleteRows Push "R1-R11,R14" Debug id,"Entry:",R3,R4 ; ; see if reason code indicated a sprite name or sprite pointer in R2 BLVC findsprite ; R2 --> sprite Pull "R1-R11,PC",VS ; ; Check for insertion/deletion ; CMP R4, #0 Pull "R1-R11,PC",EQ BMI delete_many_rows B insert_many_rows ; ---------------------------------------------------------- delete_many_rows ; Updated to work with new format sprites ; ; Check that the call is trying to start deleting at a row inside the sprite RSB R4, R4, #0 CMP R3, #0 BLT input_out_of_range LDR R6, [R2, #spHeight] ADD R6, R6, #1 CMP R3, R6 BGE input_out_of_range ; ; Check that the call is trying to finish deleting at a row inside the sprite ADD R3, R3, R4 SUBS R3, R3, #1 BMI input_out_of_range CMP R3, R6 BGE input_out_of_range ; ; Check for all rows being deleted CMP R4, R6 BGE input_out_of_range LDR R5, [R2, #spWidth] ; R5 = sprite width (in words) ADD R5, R5, #1 MOV R5, R5, LSL #2 ; in bytes MUL R0, R4, R5 ; Get length of block to delete LDR R7, [R2, #spImage] ; Get offset to image R7, and mask R8 LDR R8, [R2, #spTrans] Debug id,"In range. Details are: (W,H,I,T,size,start)",R5,R6,R7,R8,R0,R3 ; Now check for mask CMP R7, R8 ; If they're the same then there is no mask BEQ deleting_rows_no_mask ; ; Delete the mask rows ;First, are we new or old format? LDR R9, [R2, #spMode] MOVS R9, R9, LSR #27 BEQ %FT10 LDR R5, [R2, #spWidth] ; R5 = mask width - 1 (in words) Push R8 BL GetMaskspWidth ; Change it 'cos we're new format Pull R8 ADD R5, R5, #1 MOV R5, R5, LSL #2 ; mask row width in bytes MUL R0, R4, R5 ; Get length of block to delete 10 SUB R9, R6, R3 ; Get address of starting row (from top of sprite) SUB R9, R9, #1 MUL R9, R5, R9 ADD R9, R2, R9 ; Add to mask start ADD R9, R8, R9 LDR R10, [R1, #saFree] ; Get address of last word to move down ADD R10, R10, R1 BL move_memory_down ; Move the memory from [R9+R0 to R10] down to [R9 to R10-R0] ; ; Account for loss of mask rows in the sprite area block and sprite block LDR R9, [R1, #saFree] ; Move the 'free space' pointer back by size deleted in bytes SUB R9, R9, R0 STR R9, [R1, #saFree] LDR R9, [R2, #spNext] ; Move offset to next sprite back by size in bytes SUB R9, R9, R0 STR R9, [R2, #spNext] ;Finally redo our R5 stuff LDR R5, [R2, #spWidth] ; R5 = sprite width (in bytes) ADD R5, R5, #1 MOV R5, R5, LSL #2 ; in bytes MUL R0, R4, R5 ; Get length of block to delete ; ; Delete the image rows deleting_rows_no_mask SUB R9, R6, R3 ; Get address of starting row (from top of sprite) SUB R9, R9, #1 MUL R9, R5, R9 ADD R9, R2, R9 ; Add to image start ADD R9, R7, R9 LDR R10, [R1, #saFree] ; Get address of last word to move down ADD R10, R10, R1 BL move_memory_down ; Move the memory from [R9+R0 to R10] down to [R9 to R10-R0] ; ; Account for loss of mask rows in the sprite area block and sprite block LDR R9, [R1, #saFree] ; Move the 'free space' pointer back by size deleted in bytes SUB R9, R9, R0 STR R9, [R1, #saFree] CMP R7, R8 ;Only change the ptr if there is a mask LDRNE R8, [R2, #spTrans] ; Move the mask pointer back by size in bytes SUBNE R8, R8, R0 STRNE R8, [R2, #spTrans] LDR R9, [R2, #spNext] ; Move offset to next sprite back by size in bytes SUB R9, R9, R0 STR R9, [R2, #spNext] ; ; Remove rows from data Debug id, "Height, delta",R6,R4 SUB R6, R6, #1 SUB R6, R6, R4 STR R6, [R2, #spHeight] ; ; Exit CLRV Pull "R1-R11,PC" ; ---------------------------------------------------------- insert_many_rows ; Updated to work with new format sprites ; ; Check that the call is trying to start inserting at a row inside the sprite CMP R3, #0 BLT input_out_of_range LDR R6, [R2, #spHeight] ; R6 = sprite height ADD R6, R6, #1 CMP R3, R6 BGT input_out_of_range ; LDR R5, [R2, #spWidth] ; R5 = sprite width (in bytes) ADD R5, R5, #1 MOV R5, R5, LSL #2 ; in bytes MUL R0, R4, R5 ; Get length of block to insert LDR R7, [R2, #spImage] ; Get offset to image R7, and mask R8 LDR R8, [R2, #spTrans] LDR R9, [R1, #saFree] ; Check that the end of the block after insertion ADD R9, R9, R0 CMP R7, R8 ; (allowing for mask) BEQ little_skip LDR R10, [R2, #spMode] MOVS R10, R10, LSR #27 ADDEQ R9, R9, R0 ; Old format, so sprite is same size as image BEQ little_skip Push R5 ;New format, so we need a quick conversion LDR R5, [R2, #spWidth] Push R8 BL GetMaskspWidth Pull R8 ADD R5, R5, #1 MOV R5, R5, LSL #2 MUL R10, R4, R5 ADD R9, R9, R10 Pull R5 ;End of quick conversion little_skip LDR R10, [R1, #saEnd] ; is before the end of the block CMP R9, R10 BGT no_room_to_insert Debug id,"In range. Details are: (W,H,I,T,size,start)",R5,R6,R7,R8,R0,R3 ; ; Now check for mask CMP R7, R8 ; If they're the same then there is no mask BEQ inserting_rows_no_mask ; ; Insert the mask rows ; Debug ag,"Eh up, we've got a mask" ;First, are we a new or old format sprite? LDR R9, [R2,#spMode] MOVS R9, R9, LSR #27 ; DebugIf NE,ag,"And it's a new format one at that!" BEQ %FT10 LDR R5, [R2, #spWidth] ; DebugIf NE,ag,"Image width-1 (words) is ",R5 Push R8 BL GetMaskspWidth ;Convert it to 1bpp values (words) Pull R8 ; DebugIf NE,ag,"Mask (1bpp) width-1 (words) is now ",R5 ADD R5, R5, #1 MOV R5, R5, LSL #2 ;(bytes) MUL R0, R4, R5 10 ; Debug ag,"The grand total of bytes to be moved up by is ",R0 SUB R9, R6, R3 ; Get address of starting row (from top of sprite) MUL R9, R5, R9 ADD R9, R2, R9 ; Add to mask start ADD R9, R8, R9 ; Debug ag,"Moving from ",R9 LDR R10, [R1, #saFree] ; Get address of last word to move down ADD R10, R10, R1 ; Debug ag,"Moving amount ",R10 BL move_memory_up ; Move the memory from [R9 to R10] up to [R9+R0 to R10+R0] ; ; Account for gain of mask rows in the sprite area block and sprite block LDR R9, [R1, #saFree] ; Move the 'free space' pointer forward by size inserted in bytes ADD R9, R9, R0 STR R9, [R1, #saFree] LDR R9, [R2, #spNext] ; Move offset to next sprite forward by size in bytes ADD R9, R9, R0 STR R9, [R2, #spNext] ;Finally redo our R5 stuff LDR R5, [R2, #spWidth] ; R5 = sprite width (in bytes) ADD R5, R5, #1 MOV R5, R5, LSL #2 ; in bytes MUL R0, R4, R5 ; Get length of block to delete ; Debug ag,"After the rehash of R5, it is (bytes) ",R5 ; Debug ag,"and the amount to be moved by is ",R0 ; ; Insert the image rows inserting_rows_no_mask SUB R9, R6, R3 ; Get address of starting row (from top of sprite) MUL R9, R5, R9 ADD R9, R2, R9 ; Add to image start ADD R9, R7, R9 LDR R10, [R1, #saFree] ; Get address of last word to move up ADD R10, R10, R1 BL move_memory_up ; Move and clear the memory from [R9 to R10] up to [R9+R0 to R10+R0] ; ; Account for loss of mask rows in the sprite area block and sprite block LDR R9, [R1, #saFree] ; Move the 'free space' pointer forward by size deleted in bytes ADD R9, R9, R0 STR R9, [R1, #saFree] CMP R7, R8 LDRNE R8, [R2, #spTrans] ; Move the mask pointer forward by size in bytes ADDNE R8, R8, R0 STRNE R8, [R2, #spTrans] LDR R9, [R2, #spNext] ; Move offset to next sprite forward by size in bytes ADD R9, R9, R0 STR R9, [R2, #spNext] ; ; Add rows to data Debug id, "Height, delta",R6,R4 SUB R6, R6, #1 ADD R6, R6, R4 STR R6, [R2, #spHeight] ; ; Exit CLRV Pull "R1-R11,PC" ; ---------------------------------------------------------- Go_InsertDeleteColumns Push "R1-R11,R14" Debug id,"Entry:",R3,R4 ; ; see if reason code indicated a sprite name or sprite pointer in R2 BLVC findsprite ; R2 --> sprite Pull "R1-R11,PC",VS ; ; Check for insertion/deletion ; CMP R4, #0 Pull "R1-R11,PC",EQ BMI delete_many_columns B insert_many_columns ; ---------------------------------------------------------- delete_many_columns ; Updated to work with new format sprites ; ; Check that the call is trying to start deleting at a column inside the sprite RSB R4, R4, #0 CMP R3, #0 BLT input_out_of_range ; ; Get log2bpp for the sprite Push "R1-R2" LDR R0, [R2, #spMode] MOV R1, #VduExt_Log2BPP SWI XOS_ReadModeVariable Debug id,"Read mode variable log2bpp for mode:",R2,R0 ;unknown modes will return CS. It's not safe to proceed from here, ;so exit. SETV CS MOVVC R5, R2 Pull "R1-R2" Pull "R1-R11,PC",VS Push "R3-R5" ; We'll want these later... ; ; Make R3 = left bit to delete, R4 = right bit to delete (if deleting zeroth column ; then also delete left-hand wastage ADD R4, R3, R4 MOV R3, R3, LSL R5 ; R3 = left-bit of column to delete MOV R4, R4, LSL R5 ; R4 = right-bit SUB R4, R4, #1 LDR R5, [R2, #spLBit] ; Account for left-hand wastage CMP R3, #0 ; (but only for R3 if it is non-zero) ADDNE R3, R3, R5 ADD R4, R4, R5 Debug id, "Deleting from bit to bit ",R3,R4 ; ; Check that the call is trying to finish deleting at a column inside the sprite LDR R5, [R2, #spWidth] ; Get number of bits to be deleted after the SUB R5, R4, R5, LSL #5 ; start of the last word in each sprite row LDR R6, [R2, #spRBit] ; If it is greater than the last bit used then CMP R5, R6 ; an attempt is being made to delete past Pull "R3-R5",GT BGT input_out_of_range ; the end of the sprite row BLT not_deleting_rhcolumn ; Check for all columns being deleted CMP R3, #0 Pull "R3-R5",EQ BEQ input_out_of_range ; NOTE: The following commented-out chunk of code appears to be superfluous. If preceded by ; a CMP R5,R6 (which might be the expected intention), the routine breaks, messing up when the ; deleted columns include the leftmost column (ie 0). It is left in the source purely to prevent ; someone putting it back in. WT ; RSBEQ R6, R6, #31 ; If it is equal (i.e. deleting the last column) ; ADDEQ R4, R4, R6 ; then delete the right-hand wastage too ; MOVEQ R6, #31 ; And set RHwastage = 0, for deletion ; STREQ R6, [R2, #spRBit] not_deleting_rhcolumn Debug id, "Deleting from bit to bit ",R3,R4 ; ; Okay, now to delete the bits from R3 to R4 in both the image (and the mask) ; ; Delete the columns from the mask LDR R6, [R2, #spTrans] ; Check there is a mask LDR R7, [R2, #spImage] CMP R6, R7 BEQ %FT99 ;Branch if no mask ;Ok, so we have a mask, but is it new or old format? LDR R5, [R2, #spMode] MOVS R5, R5, LSR #27 ;Isolate the 'tell-tale' bits BEQ %FT98 ;Skip the next bit if old format ;First of all, 'fix' R3, R4, R5 to be 1bpp width LDMFD R13, {R3-R5} ; Read but don't pull! ADD R4, R3, R4 ; MOV R3, R3, LSL #0 ; R3 = left-bit of column to delete ; MOV R4, R4, LSL #0 ; R4 = right-bit SUB R4, R4, #1 LDR R5, [R2, #spLBit] ; Account for left-hand wastage CMP R3, #0 ; (but only for R3 if it is non-zero) ADDNE R3, R3, R5 ADD R4, R4, R5 Debug id, "Mask deleting from bit to bit ",R3,R4 98 ; First a counter for the rows, and a pointer to the start of the row LDR R5, [R2, #spWidth] ;load word width of image LDR R8, [R2,#spRBit] BL GetMaskspWidth ;Work out width of 1bpp mask in words MOV R0, R5 ;Put it in r0 for the Bl LDR R5, [R2, #spHeight] ; Number of rows - 1 ADD R6, R6, R2 BL delete_columns_from_data ; Note this returns change in size in R0 Debug id,"Change in size after mask op is noted as ",R0 ; ; Rearrange the pointers LDR R9, [R2, #spNext] SUB R9, R9, R0 STR R9, [R2, #spNext] LDR R9, [R1, #saFree] SUB R9, R9, R0 STR R9, [R1, #saFree] ; ; Delete the columns from the image 99 Pull "R3-R5" ; Unstack 'em this time ADD R4, R3, R4 MOV R3, R3, LSL R5 ; R3 = left-bit of column to delete MOV R4, R4, LSL R5 ; R4 = right-bit SUB R4, R4, #1 LDR R5, [R2, #spLBit] ; Account for left-hand wastage CMP R3, #0 ; (but only for R3 if it is non-zero) ADDNE R3, R3, R5 ADD R4, R4, R5 Debug id, "Image deleting from bit to bit ",R3,R4 ; First a counter for the rows, and a pointer to the start of the row LDR R0, [R2, #spWidth] ;load word width of image LDR R5, [R2, #spHeight] ; Number of rows - 1 LDR R6, [R2, #spImage] ; Source for deletion ADD R6, R6, R2 LDR R8, [R2,#spRBit] BL delete_columns_from_data ; Note this returns change in size in R0 Debug id,"Change in size after image op is noted as ",R0 ; ; Rearrange the pointers LDR R8, [R2, #spImage] LDR R9, [R2, #spTrans] CMP R8, R9 SUBNE R9, R9, R0 STRNE R9, [R2, #spTrans] LDR R9, [R2, #spNext] SUB R9, R9, R0 STR R9, [R2, #spNext] LDR R9, [R1, #saFree] SUB R9, R9, R0 STR R9, [R1, #saFree] ; ; Completed the image/mask. ; Now adjust number of columns/width in words/LBit/RBit etc. LDR R7, [R2, #spWidth] ; R7 = width in bits - 32 MOV R7, R7, LSL #5 LDR R5, [R2, #spLBit] ; R5 = First bit column used LDR R6, [R2, #spRBit] ; R6 = Number of bit columns used - 1 ADD R6, R6, R7 ADD R7, R7, #32 ; R7 = width in bits Debug id, "Width (bits), LBit, columns used:",R7,R5,R6 CMP R3, #0 ; Change LBit if deleted first column STREQ R3, [R2, #spLBit] Debug id, "Last bit column before deletion, after LH wastage (perhaps):",R6 SUB R8, R4, R3 ; R8 = number of bit columns deleted ADD R8, R8, #1 SUB R6, R6, R8 ; R6 = last bit column used after columns deleted Debug id, "Last bit column after deletion:",R6 AND R8, R6, #31 ; R8 = RBit STR R8, [R2, #spRBit] MOV R6, R6, LSR #5 ; R6 = number of words used - 1 STR R6, [R2, #spWidth] Debug id, "RBit and Words-1:",R8,R6 ; ; Exit CLRV Pull "R1-R11,PC" ; ---------------------------------------------------------- insert_many_columns ; ; Check that the call is trying to start inserting at a column inside the sprite CMP R3, #0 BLT input_out_of_range ; ; Get log2bpp for the sprite Push "R1-R2" LDR R0, [R2, #spMode] MOV R1, #VduExt_Log2BPP SWI XOS_ReadModeVariable Debug id,"Read mode variable log2bpp for mode:",R2,R0 SETV CS MOVVC R5, R2 Pull "R1-R2" Pull "R1-R11,PC",VS ; ; Make R3 = left bit to start inserting at, R4 = number of bits to insert MOV R3, R3, LSL R5 ; R3 = left-bit of column to delete LDR R6, [R2, #spLBit] ; Account for left-hand wastage ADD R3, R3, R6 MOV R4, R4, LSL R5 ; R4 = number of bits ; ; Get change in width in words of the new sprite versus the old sprite LDR R5, [R2, #spRBit] ; Check the bit to insert at is inside the sprite LDR R6, [R2, #spWidth] ADD R6, R5, R6, LSL #5 ; R6 = current right-most bit column + 1 ADD R6, R6, #1 Debug id,"Insert at bit, Last bit=",r3,r6 CMP R3, R6 ; If this is before the insertion point then trying BGT input_out_of_range ; to insert off the end of the sprite ADD R5, R4, R5 ; Work out the right-most bit after insertion MOV R5, R5, LSR #5 ; Find out if it intrudes on a new word or not LDR R6, [R2, #spHeight] ; Find total number of words extra required for image ADD R6, R6, #1 MUL R5, R6, R5 LDR R6, [R2, #spImage] ; More room is required if there is also a mask LDR R0, [R2, #spTrans] MOV R7, R5 ; No mask, so only 1 times the extra space is needed CMP R6, R0 BEQ skip_past ; No mask, so skip the next, mask-only, bit. ;There is a mask, so more memory needs to be allocated... LDR R8, [R2, #spMode] ; MOVS R8, R8, LSR #27 ; Ah, but is it a new or old format sprite? MOVEQ R7, R5, LSL #1 ; Old format, so 2 times the extra space is needed, DebugIf EQ,ag,"Old format mask, so R7,R5 are",R7,R5 BEQ skip_past ; and we can skip the new format gumph Push "R5-R6,R8" ; Well, it must be new format then! Debug ag,"New format mask." LDR R5, [R2, #spWidth] BL GetMaskspWidth ; Returns R5=width of 1bpp mask, with R8=new spRBit Push "R1-R2" LDR R0, [R2, #spMode] MOV R1, #VduExt_Log2BPP SWI XOS_ReadModeVariable Debug id,"Read mode variable log2bpp for mode:",R2,R0 ADD R5, R8, R4, LSR R2 ; R5 = rightmost bit after insertion Pull "R1-R2" MOV R5, R5, LSR #5 ; Convert it back to words LDR R6, [R2, #spHeight] ADD R6, R6, #1 MUL R5, R6, R5 ; R5 = total extra memory required due to mask insertions Debug ag,"Extra space required for mask (words)=",R5 ADD R7, R7, R5 ; Add this onto the memory required for the sprite insertions Debug ag,"Total space required (words)=",R7 Pull "R5-R6,R8" ; ; Check there is enough spare room for the extra columns skip_past Debug ag,"Here, R7 = total space required (words) =",R7 Debug ag," R5 = sprite space requird (words) =",R5 MOV R0, R7 ; Don't take our R7 value away! LDR R8, [R1, #saFree] ; Get last byte required ADD R7, R8, R7, LSL #2 LDR R8, [R1, #saEnd] ; Check it is inside the sprite area Debug id,"NewFree,End=",r7,r8 CMP R7, R8 BGT no_room_to_insert ; If it isn't then give an error MOV R7, R0 ; Grab our R7 value back ; ; Start insertion stage by moving the mask and rest of sprites above expanded image Debug id, "Inserting n bits starting at:",R4,R3 Debug id, "Requires extra memory of words:",R5 MOV R0, R5, LSL#2 ; Bytes to move memory up by (ie amount to be inserted in image) LDR R9, [R2, #spTrans] ; Memory to move up (start) CMP R9, R6 ; If no mask then insert before next sprite LDREQ R9, [R2, #spNext] ADD R9, R9, R2 LDR R10, [R1, #saFree] ; Memory to move up (end) ADD R10, R10, R1 BL move_memory_up Debug ag,"Moved memory up above image insertion point." ; ; Now insert columns into the image Push "R1,R5" LDR R5, [R2, #spHeight] LDR R1, [R2, #spWidth] ; Required for the insert_columns routine Debug ag,"Inserting columns in data. Height (lines), width (words) =",R5,R1 BL insert_columns_in_data ; Insert R4 bit columns in image R6 at column R3. No rows-1 = R5 Debug ag,"Inserted columns in image." Pull "R1,R5" ; ; Adjust the pointers MOV R9, R7 ; Again, keep our R7 safe LDR R7, [R2, #spNext] ; Adjust offset to next sprite ADD R7, R7, R0 STR R7, [R2, #spNext] LDR R7, [R1, #saFree] ; Adjust offset to free block of sprite area ADD R7, R7, R0 STR R7, [R1, #saFree] LDR R7, [R2, #spTrans] ; If no mask then don't adjust the mask pointer Push R4 CMP R6, R7 BEQ %FT99 ; Skip the next bit if no mask! ADD R6, R7, R0 STR R6, [R2, #spTrans] MOV R7, R9 ; Again, grab our R7 back ; ; Move other sprites up beyond expanded mask Debug ag,"Well, we'd better do the mask now..." Debug ag,"R7 and R5 are",R7,R5 SUB R0, R7, R5 ; R0 is the amount to move the mask by (total-sprite) MOV R0, R0, LSL #2 ; Words to bytes conversion Debug ag,"So, amount (bytes) to move mask up by is",R0 LDR R9, [R2, #spNext] ; Memory to move up (start) ADD R9, R9, R2 LDR R10, [R1, #saFree] ; Memory to move up (end) ADD R10, R10, R1 BL move_memory_up Debug ag,"Moved memory up above mask insertion point." ; ; Insert columns into the mask LDR R7, [R2, #spRBit] ; Keep spRBit safe! Push "R1, R7-R8" LDR R5, [R2, #spMode] MOVS R5, R5, LSR #27 ; New or old format sprite? LDREQ R1, [R2, #spWidth] ; Old format DebugIf EQ,ag,"Old format sprite" BEQ next_bit ; Skip the next chunk if sprite is old format Debug ag,"New format sprite" Push "R0,R2" LDR R0, [R2, #spMode] MOV R1, #VduExt_Log2BPP SWI XOS_ReadModeVariable Debug id,"Read mode variable log2bpp for mode:",R2,R0 MOV R4, R4, LSR R2 ; R4 converted to 1 bpp MOV R3, R3, LSR R2 Pull "R0,R2" LDR R5, [R2, #spWidth] BL GetMaskspWidth Debug ag,"spWidth of mask is",R5 Debug ag,"spRBit of mask is",R8 MOV R1, R5 ; Needed for insert_columns routine STR R8, [R2, #spRBit] next_bit LDR R5, [R2, #spHeight] Debug ag,"just before inserting columns, spWidth of mask is",R1 Debug ag,"just before inserting columns, spRBit of mask is",R8 BL insert_columns_in_data ; Insert R4 bit columns in mask R6 at column R3. No rows-1 = R5 Debug ag,"Inserted columns in mask." Pull "R1, R7-R8" STR R7, [R2, #spRBit] ; ; Adjust the pointers LDR R7, [R2, #spNext] ; Adjust offset to next sprite ADD R7, R7, R0 STR R7, [R2, #spNext] LDR R7, [R1, #saFree] ; Adjust offset to free block of sprite area ADD R7, R7, R0 STR R7, [R1, #saFree] ; ; Exit 99 ; ; Change data in the sprite block Pull R4 LDR R9, [R2, #spRBit] ; Work out right-most bit after insertion ADD R9, R4, R9 LDR R10, [R2, #spWidth] ; R10 = words used -1 ADD R10, R10, R9, LSR #5 STR R10, [R2, #spWidth] AND R9, R9, #31 ; R9 = last bit used STR R9, [R2, #spRBit] CLRV Pull "R1-R11,PC" ; ---------------------------------------------------------- ; Move the memory from [R9+R0 to R10] down to [R9 to R10-R0] move_memory_down Push "R1,R3,R9,R14" ADD R1, R9, R0 Debug id,"Moving memory down from,to,finish:",R1,R9,R10 01 CMP R1, R10 BGE %FT02 LDR R3, [R1], #4 STR R3, [R9], #4 B %BT01 02 Debug id,"Moved memory down. From,to,finish are now:",R1,R9,R10 Pull "R1,R3,R9,PC" ; -------------------------------------------------------- ; Move the memory from [R9 to R10] up to [R9+R0 to R10+R0] move_memory_up Push "R1,R3,R4,R9,R14" ADD R1, R10, R0 Debug id,"Moving memory up from,to,finish:",R10,R1,R9 CMP r9, r10 01 LDRCC R3, [R10, #-4]! STRCC R3, [R1, #-4]! CMP r9, r10 BCC %BT01 MOV lr, #0 CMP r9, r1 02 STRCC lr, [r1, #-4]! CMP r9, r1 BCC %BT02 Debug id,"Moved memory up. From,to,finish are now:",R10,R1,R9 Pull "R1,R3,R4,R9,PC" ; -------------------------------------------------------- ; Delete columns from an image/mask delete_columns_from_data ; R0 = Width of image/mask on entry, change in size on exit ; R5 = Number of rows in mask ; R6 = Source for deletion ; R8 = spRBit Push "R1-R11,R14" Push R0 ;push it separately Push R8 ;this separate too MOV R7, R6 ; Destination for deletion = source Debug id,"Start of line with R0, start, end, source, dest, R8:",R0,R3,R4,R6,R7,R8 ; ; Now for all the rows... 01 ; ; Counter to see how many bits have been copied MOV R10, #0 ; ; Transfer source to destination until at first word in the row to worry about SUBS R9, R3, #32 02 BMI %FT99 LDR R8, [R6], #4 ; Copy whole word from source to destination STR R8, [R7], #4 ADD R10, R10, #32 ; Increase 'bits copied' by 1 word = 32 bits SUBS R9, R9, #32 ; Decrement counter by 1 word = 32 bits B %BT02 ; Loop until all the whole words have been done ; ; Now load the source word at the word including the first column to delete 99 LDR R8, [R6] ; R8 = word including first column to delete RSB R9, R9, #0 ; R9 = number of unwanted bits in R8 MOV R8, R8, LSL R9 ; Clear the unwanted bits MOV R8, R8, LSR R9 ; ; Skip forward along the source until at the last column to delete SUB R10, R4, R10 ; R10 = bits left before last bit to copy in row 02 CMP R10, #32 ; If less than 32 then already at the right place BLT %FT99 ADD R6, R6, #4 ; Else move on the source pointer SUB R10, R10, #32 ; and remove 1 word from the bits left counter B %BT02 ; ; Now at the word which includes the last column to delete. Bit twiddling from now on 99 ; ; R8 = combination of word including first column to delete and last column to delete ; LDR R11, [R6], #4 MOV R11, R11, LSR R10 ; Remove unwanted bits from the front MOV R11, R11, LSR #1 RSB R9, R9, #32 ; Shift it up past the 32-R9 bits correct in R8 ORR R8, R8, R11, LSL R9 ; ; If new R9=bottom 5 bits of R3 is bigger than R4 then we need to store this word and move on Debug id,"Middle with R9,R10,R6,R7",R9,R10,R6,R7 CMP R9, R10 ; Did the last shift shift bits out of the top of R8? STRGT R8, [R7],#4 ; If so then store the word RSBGT R9, R9, #32 ; Get bits shifted out into bottom of R8 MOVGT R8, R11, LSR R9 ADDGT R9, R9, R10 ; R9 = number of valid bits in R8 RSBGT R9, R9, #31 ADDLE R9, R9, #31 ; Else R9 = number of valid bits in R8 SUBLE R9, R9, R10 ; ; Now we have considered all the words from the start of the row to the one including the last deleted column MOV R10, R4, LSR #5 ; R10 = number of source words examined - 1 LDR R0, [R13, #4] ; Read R0 directly off the stack Debug id,"R0 read off stack as ",R0 MOV R11, R0 ; R11 = number of source words in a row - 1 02 CMP R10, R11 ; While source words examined < source words in a row BGE %FT99 LDR R0, [R6], #4 ; R0 = next source word ORR R8, R8, R0, LSL R9 ; Add in bottom bits above the R9 valid bits STR R8, [R7], #4 ; Store R8 in destination RSB R9, R9, #32 ; New R8 = top R9 bits of R0 MOV R8, R0, LSR R9 RSB R9, R9, #32 ADD R10, R10, #1 ; Source words examined ++ B %BT02 ; End while ; ; Finished loop. Any valid bits left over? 99 LDR R10, [R13] ; read R8 off the stack into R10 Debug id,"Read R8 off stack into R10 as",R10 RSB R10, R10, #31 CMP R9, R10 STRGT R8, [R7], #4 Debug id,"End of line with line, valid bits, data, source, dest:",R5,R9,R8,R6,R7 ; ; Loop for all the rows in the sprite image/mask SUBS R5, R5, #1 BPL %BT01 ; ; Finished all the deletion. Note it must still shuffle down the memory from the end of ; the old image/mask to the end of the new image/mask Pull R8 Pull R0 ;Need to do this to restore stack SUB R0, R6, R7 MOV R9, R7 LDR R10, [R1, #saFree] ADD R10, R10, R1 BL move_memory_down ; ; Return R0 = change in size of data Pull "R1-R11,PC" ; -------------------------------------------------------- ; Insert columns from an image/mask insert_columns_in_data ; R1 = spWidth ; R5 = Number of rows in mask/image - 1 ; R6 = Offset from R2 of source for insertion ; R3 = bit column to insert before ; R4 = number of columns to insert ; R0 = change in length of image/mask in bytes after insertion Push "R0-R12,R14" Debug id,"Entry:R0,R3,R4,R5,R6",R0,R3,R4,R5,R6 ; ; Get R6 = source pointer to just after the end of the last row ADD R9, R5, #1 MOV R10, R1 ADD R10, R10, #1 MOV R10, R10, LSL #2 ;R10 = spWidth in bytes MLA R6, R10, R9, R6 ; ; Get R7 = destination pointer to just after the end of the finished sprite ADD R6, R6, R2 ADD R7, R6, R0 Debug id,"Start of line with start,number, source, dest:",R3,R4,R6,R7 ; ; Make R3 be the bit column in the destination just after the end of the inserted columns ADD R3, R3, R4 ; ; Now for all the rows... 02 ; ; R10 = Bit number of start of destination word pointed at [R7-4]. R11 = 32- (new RBit after insertion + 1) = waste bits in word MOV R10, R1 LDR R11, [R2, #spRBit] ADD R10, R11, R10, LSL #5 ADD R10, R10, R4 AND R11, R10, #31 ADD R11, R11, #1 RSB R11, R11, #32 BIC R10, R10, #31 ; ; R9 = number of bits in R8 which will be valid LDR R9, [R2, #spRBit] ADD R9, R9, #1 ; ; Get the source word on the current line into R8 Its bottom R9 bits are needed/valid. Debug id,"Entry to first loop.source,dest,flag,r9,r10,r11:",R6,R7,R12,R9,R10,R11 01 ; Registers have the following meaning at this point: ; r3 = 1st bit column after inserted section ; r4 = width of inserted section ; r6 = source word + 4 ; r7 = destination word + 4 ; r9 = number of LSBits at r6 unused as yet (1 to 32) ; r10 = 1st column of destination word ; r11 = amount of MSBits to zero out of destination word LDR R8, [R6, #-4]! ; ; Make R8 have its top R9 bits valid, all other bits 0 RSB R9, R9, #32 ; R9 = 32 - x MOV R8, R8, LSL R9 ; Shifts bits [0,x-1] up to [32-x,32-x+x-1]=[32-x,31] RSB R9, R9, #32 ; Restore R9 ; ; Read in the bits from the word before it, to make all of R8 valid (ignores LH wastage) LDR R14, [R6, #-4] ORR R8, R8, R14, LSR R9 ; ; R8 now contains the last 32 bits of pixel bit data from the row of the sprite ; Shift it right to allow for RH wastage in destination sprite MOV R8, R8, LSR R11 ; ; If we have shifted out some of this word then move source ; pointer forward again to reread this word next time ADD R9, R9, R11 CMP R9, #32 ADDGT R6, R6, #4 ; Have shifted R14-32 bits out. Hence move source pointer back SUBGT R9, R9, #32 ; so we reread it next time. ; ; Loop until we have got a word which has some bits of inserted columns in it CMP R3, R10 STRLE R8, [R7, #-4]! SUBLE R10, R10, #32 MOVLE R11, #0 BLE %BT01 Debug id,"First loop complete.source,dest,flag,r10,R3,R9:",R6,R7,R12,R10,R3,R9 ; Registers have the following meaning at this point: ; r3 = 1st bit column after inserted section ; r4 = width of inserted section ; r6 = source word ; r7 = destination word ; r8 = 32 source bits extracted and ready to use from previous step aligned for destination ; r9 = number of LSBits at r6 unused as yet (1 to 32) ; r10 = 1st column of destination word ; Mask off bottom (r3 AND 31) bits for hole ANDS r14, r3, #31 MOVEQ r14, #32 MOV r8, r8, LSR r14 MOV r8, r8, LSL r14 ; Move back a word if all of this word has been masked off ADD r9, r9, r14 CMP r9, #32 ADDGT r6, r6, #4 ; Remove the bits which have been blanked from the number of bits to insert SUB r14, r4, r14 ADD r14, r14, #32 B %FT03 01 STR R8, [R7, #-4]! ; Store another word MOV R8, #0 SUB R10, R10, #32 03 SUBS R14, R14, #32 ; Decrease counter of bits inserted BGT %BT01 SUB r14, r3, r4 ; start column of insertion ANDS r14, r14, #31 ; distance into source word ; If extracts at least a bit from source word then do so RSBNE r14, r14, #32 LDRNE r11, [r6, #-4]! MOVNE r11, r11, LSL r14 ORRNE r8, r8, r11, LSR r14 ; Store it away STR r8, [r7, #-4]! SUBS r10, r10, #32 ; Keep copying words of data until we have finished the row 01 BLT %FT99 LDR R8, [R6, #-4]! STR R8, [R7,#-4]! SUBS R10, R10, #32 B %BT01 ; ; Finished a row, so loop for all rows 99 Debug id,"Finished Row with source,dest:",R5,R6,R7 SUBS R5, R5, #1 BPL %BT02 ; ; Finished all the rows. Exit time. Debug id,"Finished the rows with source,dest:",R6,R7 Pull "R0-R12,PC" ; ***************************************************************************** ; ; GetMaskspWidth - convert spWidth for data to spWidth for mask (1bpp masks) ; ; NOTE: This routine should be identical to the same routine in VduGrafH except it does ; not return the updated PSR ; ; Internal routine. ; ; in: R5 = spWidth (ie width in words-1) ; (expects R2->sprite) ; ; out: R5 = spWidth (words -1) for mask data ; R8 = Last bit (spRBit) used in mask data ; should only be called for new format sprites, but will cope with old too GetMaskspWidth ROUT Push "R0, LR" Debug ag,"Entered GetMaskspWidth with R5,R8",R5,R8 LDR LR, [R2, #spMode] ; fetch the sprite mode MOVS LR, LR, LSR #27 ; isolate the sprite type and test for =0 Pull "R0, PC",EQ ; if an old format sprite, return R5 unchanged ; treat any T>max sprites as 32bpp CMP LR, #SpriteType_MAX MOVCS LR, #SpriteType_Substitute ; bugfix 9/8/93: get log2bpp this way ADRL R0, NSM_bpptable LDRB LR, [R0, LR] ; get the log2bpp to LR RSB LR, LR, #5 ; and change to 5-log2bpp MOV R5, R5, LSL LR ; number of pixels for full words RSB LR, LR, #5 ; now switch back to log2bpp LDR R0, [R2, #spRBit] ADD R0, R0, #1 ADD R5, R5, R0, LSR LR ANDS LR, R5, #&1F ; fit exactly in a number of words ? SUB R8, LR, #1 ; alter the last bit used for the mask data ; fix bug MED-01130.... AND R8, R8, #&1F ; ....bring back into range 00-1F (may be -1 here) MOVNE LR, #1 ; if not, add an extra word ADD R5, LR, R5, LSR #5 ; add the whole number of words SUB R5, R5, #1 ; returns as words-1 Debug ag,"Left GetMaskspWidth with R5,R8",R5,R8 Pull "R0, PC" NSM_bpptable ; note, yes - I know this could be type-1, but at some point some new type ; will break the relationship so it's a table from day 1 to cope with this DCB 99, 0, 1, 2, 3, 4, 5 ; T= 0 1 2 3 4 5 6 ; cols= old, 2, 4, 16, 256, 32k, 16M ALIGN END