; 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.VduGrafK ; ; ARTHUR OPERATING SYSTEM - Vdu Drivers ; ======================= ; ; Vdu driver code - Sprite stuff ; ; Author R C Manby ; Date 5.3.87 ; ; ***************************************************************************** ; ; ScreenSave - Save screen within graphics window as a sprite file ; ; External routine ; ; in: R2 -> file name ; R3 = 0/1 => exclude/include palette data ; ScreenSave ROUT Push R14 SWI XOS_RemoveCursors [ {TRUE} GraphicsMode R0 BNE %FT20 | LDR R0, [WsPtr, #NPix] CMP R0, #0 BEQ %FT20 ; quit with error if not graphics mode ] ; build a temporary sprite area header ADD R1, WsPtr, #ScrSavAreaCB MOV R4, #&7FFFFFFF ; size, very large MOV R5, #1 ; one sprite LDR R6, =(ScrSavSpriteCB-ScrSavAreaCB) ;saFirst MOV R7, R6 ; saFree=saFirst STMIA R1, {R4-R7} ADD R11, WsPtr, #GWLCol ; R4 ,R5 ,R6 ,R7 LDMIA R11, {R4,R5,R6,R7} ; wL ,wB ,wR ,wT LDR R0, [WsPtr, #ModeNo] STR R0, [WsPtr, #SGetMode] ; needs setting up before CreateHeader Push R2 ; preserve file name pointer ; if it is a mode selector mode with >256 colours force it to have no ; palette. CreateHeader will deal with <=256. LDR R2, [WsPtr, #Log2BPP] CMP R2, #4 MOVCS R3, #0 ; amg 25th May 1994. The above is no longer completely true. We still ; don't allow palettes on 16/32bpp. Below that (whether new or old ; format of sprite) palettes are now allowed. No actual code change ; here, but CreateHeader has been changed. ADR R2, ScrSavSpriteName ; R3 ,R4,R5,R6,R7 BL CreateHeader ; In : Palette,sl,sb,sr,st ADDVS sp, sp, #4 ; (if error, junk stacked filename ptr and exit) BVS %FT35 ; Out: ImageSize ; now add the sprite to the sprite area LDR R3, [R2, #spNext] ; total size of new sprite LDMIA R1, {R4,R5,R6,R7} ; saEnd,saNumber,saFirst,saFree ADD R7, R7, R3 ; new saFree MOV R4, R7 STMIA R1, {R4,R5,R6,R7} ; Create file to prevent "Can't extend" [ AssemblingArthur :LOR: Module MOV R0, #OSFile_CreateStamp LDR R1, [R13, #0] ; R1 -> filename LDR R2, =&FF9 ; Type=SpriteFile MOV R3, #0 ; Junk MOV R4, #0 SUB R5, R7, #4 ; File size (ie exclude saEnd) SWI XOS_File | CLRV ] Pull R1 BVS %FT30 ; OpenUp file and save the Sprite area and sprite headers [ AssemblingArthur :LOR: Module MOV R0, #open_update :OR: open_mustopen :OR: open_nodir | MOV R0, #open_write ] SWI XOS_Find BVS %FT30 MOV R1, R0 MOV R0, #2 ; write bytes to file LDR R2, =(ScrSavAreaCB+saNumber) ADD R2, R2, WsPtr LDR R3, =(ScrSavSpriteCB+spImage) LDR R3, [WsPtr, R3] ADD R3, R3, #(SpriteAreaCBsize-saNumber) MOV R4, #0 SWI XOS_GBPB BVS %FT40 ; FileSwitchGotYa ! Push R1 LDR R0, [WsPtr, #GWLCol] LDR R1, [WsPtr, #GWTRow] BL ScreenAddr ; R2 = ScrAdr of TopL of area Pull R1 LDR R5, [WsPtr, #SGetWidth] ADD R5, R5, #1 MOV R5, R5, LSL #2 ; width (bytes) LDR R6, [WsPtr, #SGetHeight] ; height-1 LDR R7, [WsPtr, #LineLength] SUBS R7, R7, R5 ; zero then can do as one lump MLAEQ R5, R6, R5, R5 ; R5 = R5*(R6+1) MOVEQ R6, #0 ; only one chunk to do ; ; R0 ,R1 ,R2 ,R3 ,R4 ,R5 ,R6 ,R7 ; ,Handle,ScrAdr,Size , ,Width,RowCnt,RowOfSt 10 MOV R0, #2 MOV R3, R5 SWI XOS_GBPB BVS %FT40 ; something went wrong ADD R2, R2, R7 ; step to next screen line SUBS R6, R6, #1 BGE %BT10 MOV R0, #0 ; close file SWI XOS_Find BVS %FT30 SWI XOS_RestoreCursors Pull R14 RETURNVC ; no error, return VC 20 ADRL R0, SpriteErr_NotGraphics [ International BL TranslateError | SETV ] B %FT30 40 ; return point after an error STR R0, [WsPtr, #RetnReg0] ; R0 ptr to message, R1 file handle MOV R0, #0 ; close file SWI XOS_Find 30 ; return point after an error STRVS R0, [WsPtr, #RetnReg0] ; R0 ptr to message 35 SWI XOS_RestoreCursors Pull R14 RETURNVS ScrSavSpriteName = "screendump", 0 ALIGN LTORG ; ***************************************************************************** ; ; ScreenLoad - Plot sprite file directly into graphics window ; ; External routine ; ; in: R2 -> file name ; ScreenLoad ROUT Push R14 SWI XOS_RemoveCursors MOV R0, #open_read+open_mustopen+open_nodir MOV R1, R2 SWI XOS_Find BVS %FT80 STR R0, [WsPtr, #ScrLoaHandle] MOV R1, R0 MOV R0, #4 ; read areaCB from file ADD R2, WsPtr, #ScrLoaAreaCB+saNumber MOV R3, #(SpriteAreaCBsize-saNumber) MOV R4, #0 SWI XOS_GBPB BVS %FT70 ; FileSwitchGotYa ! MOV R0, #3 ; read spriteCB from file ADD R2, WsPtr, #ScrLoaSpriteCB MOV R3, #SpriteCBsize ADD R3, R3, #MaxSpritePaletteSize LDR R4, [WsPtr, #(ScrLoaAreaCB+saFirst)] SUB R4, R4, #4 SWI XOS_GBPB BVS %FT70 ADD R2, WsPtr, #ScrLoaSpriteCB BL WritePaletteFromSprite ; mode change (if needed) ;branch to 75 rather than 70 because RetnRegR0 is already set up BVS %FT75 ; and palette setting [ {TRUE} GraphicsMode R0 BNE %FT60 | LDR R0, [WsPtr, #NPix] CMP R0, #0 BEQ %FT60 ; quit with error if not graphics mode ] ; now check for being able to do it all at once ADD R0, WsPtr, #GWLCol ; R3=GWLCol; R4=GWBRow LDMIA R0, {R3-R6} ; R5=GWRCol; R6=GWTRow ADD R0, WsPtr, #ScrLoaSpriteCB ADD R0, R0, #spWidth ; R7=width-1; R8=height-1 LDMIA R0, {R7-R10} ; R9=LBit; R10=RBit SUB R5, R5, R3 ; R5 = window width LDR R0, [WsPtr, #XWindLimit] TEQ R0, R5 ; if window width=full screen TEQEQ R9, #0 ; and LBit=0 TEQEQ R10, #31 ; and RBit=31 BNE %FT05 ADD R5, R5, #1 ; R5 = screen width in pixels ADD R7, R7, #1 ; R7 = sprite width in words LDR R0, [WsPtr, #NPix] MLA R0, R7, R0, R7 ; R0 = width*(npix+1) TEQ R0, R5 ; and spritewidth=full screen BNE %FT05 [ {TRUE} LDR R14, [WsPtr, #Log2BPC] MOV R1, R5, LSL R14 ; bit size of 1 row of pixels MOV R1, R1, LSR #3 ; byte size of 1 row of pixels LDR R14, [WsPtr, #LineLength] ; LineLength (in bytes) TEQ R1, R14 ; if they differ (eg interlaced mode) BNE %FT05 ; then we can't optimise ] ; we know we can do it all in one chunk ; work out screen address and sprite offset LDR R1, [WsPtr, #CursorFlags] ; if computing clip box TST R1, #ClipBoxEnableBit Push "R0-R4", NE BLNE SetClipBoxToFullScreen ; then set to full screen Pull "R0-R4", NE ; above routine preserves PSR MOV R7, R7, LSL #2 ; R7 = line width in bytes ADD R1, R8, R4 ; R1 = height-1 + GWBRow = YT SUBS R9, R1, R6 ; if YT > GWTRow then ; start at row (YT-GWTRow) MOVHI R1, R6 ; and YT=GWTRow, else MOVLS R9, #0 ; start at row 0 (and YT=YT) LDR R0, [WsPtr, #ScrLoaAreaCB+saFirst] ADD R2, WsPtr, #ScrLoaSpriteCB LDR R2, [R2, #spImage] ADD R0, R0, R2 SUB R0, R0, #4 ; R0=offset into file of image MLA R4, R7, R9, R0 ; add on vertical wastage*width SUB R9, R8, R9 ; R9 = height-1-wastage MLA R9, R7, R9, R7 ; number of bytes to transfer MOV R0, #0 BL ScreenAddr ; R2 := screen address MOV R3, R9 LDR R1, [WsPtr, #ScrLoaHandle] MOV R0, #3 ; read from this position SWI XOS_GBPB BVS %FT70 ; if error B %FT52 ; no error ; can't do it all at once; R3 = GWLCol, R4 = GWBRow 05 ADD R2, WsPtr, #ScrLoaSpriteCB ; point at the spriteCB MOV R5, #0 BL GenSpritePlotParmBlk ; "plotting" at (GWLCol,GWBRow) BVS %FT55 ; off screen (not an error) ADD R2, WsPtr, #ScrLoaSpriteCB LDR R4, [WsPtr, #SPltMemAdr] ; convert MemAdr into LDR R5, [WsPtr, #ScrLoaAreaCB+saFirst] SUB R4, R4, #4 SUB R4, R4, R2 ADD R4, R4, R5 STR R4, [WsPtr, #ScrLoaFilPtr] ; file ptr LDR R4, [R2, #spWidth] ; convert spWidth into ADD R4, R4, #1 MOV R4, R4, LSL #2 STR R4, [WsPtr, #ScrLoaFilOfst] ; file ptr offset LDR R4, [WsPtr, #SPltColCnt] ADD R4, R4, #2 MOV R4, R4, LSL #2 STR R4, [WsPtr, #ScrLoaBytes] ADD R4, WsPtr, #ScrLoaBuffer STR R4, [WsPtr, #SPltMemAdr] STR R4, [WsPtr, #ScrLoaBufAdr] 10 ; read row from file ADD R1, WsPtr, #ScrLoaHandle LDMIA R1, {R1,R2,R3,R4} ; Handle,BufAdr,Bytes,FilPtr MOV R0, #3 SWI XOS_GBPB BVS %FT70 ADD R0, WsPtr, #SPltScrAdr LDMIA R0, {R0-R1,R5-R7} ; R0 ,R1 , R5 ,R6 ,R7 ; ScrAdr,ColCnt, BufAdr,ShftR,ShftL LDMIA R5, {R2,R3} ; plot the first (leftmost) word ADD R5, R5, #4 ShiftR R2,R3, R6,R7 ; shift R3,R2 right R6 places ; we only need result word R2 LDR R3, [WsPtr, #SPltLMask] ; on leftmost word, mask down AND R2, R2, R3 ; to just the required pixels LDR R4, [R0] ; plot 1 word BIC R4, R4, R3 ORR R4, R4, R2 STR R4, [R0], #4 SUBS R1, R1, #1 BLT %FT50 ; if all plotted, try next scanline ; else try for blocks of 4 SUBS R1, R1, #4 BLT %FT30 20 ;R0 ,R1 ,R5 ,R6 ,R7 ;ScrAdr,ColCnt, ,BufAdr,ShftR,ShftL LDMIA R5, {R2,R3,R8-R10} ; 5 words needed, gives 4 after shift ADD R5, R5, #16 ; advance source ptr 4 words ShiftR R2,R3, R6,R7 ; shift R4-R0 right R6 bits ShiftR R3,R8, R6,R7 ; we only want result words R3-R0 ShiftR R8,R9, R6,R7 ShiftR R9,R10,R6,R7 STMIA R0!, {R2,R3,R8-R9} ; write 4 words back to screen SUBS R1, R1, #4 BGE %BT20 30 ; try 1 word at a time ADDS R1, R1, #4 ;R0 ,R1 , R5 ,R6 ,R7 ;ScrAdr,ColCnt, BufAdr,ShftR,ShftL ; ; If EQ this is rightmost word BEQ %FT45 40 LDMIA R5, {R2,R3} ADD R5, R5, #4 ShiftR R2,R3, R6,R7 ; shift R3,R2 right R6 places ; we only need result word R2 STR R2, [R0], #4 SUBS R1, R1, #1 BGT %BT40 45 LDMIA R5, {R2,R3} ADD R5, R5, #4 ShiftR R2,R3, R6,R7 ; shift R3,R2 right R6 places ; we only need result word R2 LDR R3, [WsPtr, #SPltRMask] ; rightmost word, so mask down to AND R2, R2, R3 ; just the required pixels LDR R4, [R0] BIC R4, R4, R3 ORR R4, R4, R2 STR R4, [R0], #4 50 ; now try the next scanline ADD R11, WsPtr, #SPltWidth LDMIA R11, {R1,R2,R3,R4} ; Width,Height,ScrOff,MemOff ADD R5, R0, R3 SUBS R2, R2, #1 STMIA R11, {R1,R2,R3,R4,R5} ; Width,Height,ScrOff,MemOff,ScrAdr ADD R11, WsPtr, #ScrLoaHandle ; R1 ,R2 ,R3 ,R4 ,R5 LDMIA R11, {R1,R2,R3,R4,R5} ; Handle,BufAdr,Bytes,FilPtr,FilOfst ADD R4, R4, R5 STR R4, [WsPtr, #ScrLoaFilPtr] BGE %BT10 ; plot next scanline 52 MOV R0, #0 ; close file SWI XOS_Find BVS %FT80 55 SWI XOS_RestoreCursors Pull R14 RETURNVC 60 ADRL R0,SpriteErr_NotGraphics [ International BL TranslateError ] 70 ; return point after an error STR R0, [WsPtr, #RetnReg0] ; R0 ptr to message, R1 file handle 75 MOV R0, #0 ; close file SWI XOS_Find 80 ; error, file not open STRVS R0, [WsPtr, #RetnReg0] SWI XOS_RestoreCursors Pull R14 RETURNVS END