; 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.VduGrafL ; ; ARTHUR OPERATING SYSTEM - Vdu Drivers ; ======================= ; ; Vdu driver code - Sprite stuff ; ; Author T M Dobson ; Date 22-Sep-87 ; ; ***************************************************************************** ; ; ReadSaveAreaSize - Read size of a VDU context save area ; ; in: R0 = SpriteReason_ReadSaveAreaSize ; R1 -> sprite area ; R2 -> sprite (0 => screen (possibly)) ; ; out: R3 = size of an area suitable for this sprite ; ReadSaveAreaSize ROUT MOV R3, #MainSize ; I was kidding about it depending STR R3, [WsPtr, #RetnReg3] ; on the sprite! MOV PC, R14 ; ***************************************************************************** ; ; SwitchOutputToSprite - Make VDU(graphics) output go to a sprite ; ; External routine ; ; in: R0 = SpriteReason_SwitchOutputTo ; R1 -> sprite area ; R2 -> sprite (0 => screen) ; R3 -> save area for VDU variables relating to sprite ; 0 => no save area, initialise variables from mode number of sprite ; or display mode number ; 1 => use MOS's save area ; ; First word of save area = 0 => uninitialised save area ; "VOTS" => initialised save area ; else error ; ; From Medusa onwards, things are further complicated here by the fact that ; the sprite may have a new sprite mode word rather than a mode number. When ; the former case occurs calling pushmodeinfoanymonitor doesn't really help ; very much. Instead, when a sprite mode word is given, it will derive or ; fudge all the variables that it is really interested from the sprite mode ; word directly. SwitchOutputToSprite ROUT SwitchOutputToMask ROUT CMP R3, #1 ; check for values 0 and 1 MOVCC R4, #0 ; R3=0 => no save area, so not inited ADDEQ R5, WsPtr, #VduSaveArea ; R3=1 => MOS's area MOVHI R5, R3 ; else user area LDRCS R4, [R5, #InitFlag] ; if is an area, load R4 with init flag LDR R5, VOTS ; compare with initialised identifier TEQ R4, R5 ; if not initialised TEQNE R4, #0 ; and not uninitialised BNE InvalidSaveArea ; no more errors can be generated, so update returned registers ADD R5, WsPtr, #VduOutputCurrentState LDMIA R5, {R6-R9} ADD R5, WsPtr, #RetnReg0 STMIA R5, {R6-R9} Push "R0-R4,R14" ASSERT SpriteMaskSelect = VduOutputCurrentState +0 ASSERT VduSpriteArea = VduOutputCurrentState + 4 ASSERT VduSprite = VduOutputCurrentState + 8 ORR R0, R0, #RangeC ; make R0 into &2nn ADD R5, WsPtr, #VduOutputCurrentState STMIA R5, {R0-R2} BL PreWrchCursor ; remove cursor BL PackVars ; save away current vars into save area ; (if any) Pull "R0-R4" STR R3, [WsPtr, #VduSaveAreaPtr] ; save new save area ptr TEQ R2, #0 ; if switching to screen LDREQ R9, [WsPtr, #DisplayScreenStart] ; then load up new ScreenStart LDREQ R11, [WsPtr, #DisplayModeNo] ; and mode number BEQ %FT20 ; and skip sprite stuff ; do stuff for switching to sprite Push R0 BL RemoveLeftHandWastage ; then remove LH wastage from sprite Pull R0 ; (spLBit := 0) ASSERT spHeight = spWidth +4 ASSERT spLBit = spWidth +8 ASSERT spRBit = spWidth +12 ASSERT spImage = spWidth +16 ASSERT spTrans = spWidth +20 ASSERT spMode = spWidth +24 ADD R5, R2, #spWidth ; R5=width:R6=height:R7=LBit(=0) LDMIA R5, {R5-R11} ; R8=RBit:R9=Image:R10=Trans:R11=Mode TEQ R0, #SpriteReason_SwitchOutputToMask BNE %FT23 MOV R9, R10 ; point at mask instead of image MOVS R0, R11, LSR #27 BEQ %FT23 ; check for old format masks BL GetMaskspWidth ; adjust R5 and R8 to mask dimensions AND R10, R11, #15<<27 TEQ R10, #SpriteType_RISCOS5<<27 BEQ %FT21 TST R11, #&80000000 BIC R11, R11, #&F8000000 ; wipe existing sprite type ORREQ R11, R11, #SpriteType_New1bpp<<27 ; force to 1bpp ORRNE R11, R11, #SpriteType_New8bpp<<27 ; force to 8bpp B %FT23 21 TST R11, #&80000000 AND R11, R11, #&F0 ; preserve DPI fields, modeflags + original type must go ORR R11, R11, #1+(SpriteType_RISCOS5<<27) ; mark as RO5 format ORREQ R11, R11, #SpriteType_New1bpp<<20 ; force to 1bpp ORRNE R11, R11, #SpriteType_New8bpp<<20 ; force to 8bpp 23 ADD R9, R9, R2 ; R9 -> sprite data or mask 20 MOV R10, R11 BL PushModeInfoAnyMonitor STRVS R0, [WsPtr, #RetnReg0] Pull "PC", VS STR R9, [WsPtr, #ScreenStart] STR R11, [WsPtr, #ModeNo] ; new mode number MOV R11, R13 ; If we're switching output to screen, either find our values from the ; pushed mode info or from the saved DisplayXXX values. ; DisplayXXX is needed for any values which might differ from one ; display driver to another, but care is needed because ModeChangeSub ; actually calls us during the mode change to set up some of the ; variables (so need to make sure that any DisplayXXX values are set ; before we get called). ; Also note that we can't replace the above PushModeInfoAnyMonitor call ; with PushModeInfo (to get accurate values for the current display ; driver) because ScreenModes might not be running with the same MDF ; as when the original call was made. TEQ R2, #0 LDREQ R5, [R12, #DisplayLineLength] LDREQ R6, [R11, #wkYWindLimit] LDREQ R7, [R11, #wkXWindLimit] LDREQ R8, [R11, #wkScrRCol] LDREQ R10, [R11, #wkScrBRow] BEQ %FT30 ; OK, we're switching to a sprite, so calculate the above values from ; the sprite header ADD R5, R5, #1 MOV R5, R5, LSL #2 ; R5 = width in bytes ADD R7, R8, R5, LSL #3 ; R7 = LineLength*8 + spRBit SUB R7, R7, #31 ; R7=active area width in bits LDR R8, [R11, #wkLog2BPC] MOV R7, R7, LSR R8 ; R7 = width in pixels MOV R8, R7, LSR #3 ; R8 = width in text columns SUB R7, R7, #1 ; R7 = max value of GWRCol SUB R8, R8, #1 ; R8 = max column number ADD R10, R6, #1 ; R10 = no. of pixel rows MOV R10, R10, LSR #3 ; R10 = number of char rows SUB R10, R10, #1 ; R4 = maximum row number 30 STR R5, [WsPtr, #LineLength] STR R6, [WsPtr, #YWindLimit] STR R7, [WsPtr, #XWindLimit] STR R8, [WsPtr, #ScrRCol] STR R10, [WsPtr, #ScrBRow] LDR R0,[R11, #wkNColour] STR R0,[WsPtr, #NColour] ; copy number of colours -1 ADD R11, R11, #wkmiddle MOV R0, #wkmidend-wkmiddle ; number of bytes to do ADD R1, WsPtr, #YShftFactor ; first mode variable that we do 40 LDR R5, [R11], #4 ; copy byte from mode table STR R5, [R1], #4 ; into word variable SUBS R0, R0, #4 ; decrement count BNE %BT40 ; loop until finished ADD R13, R13, #PushedInfoSize ; junked stacked info ; now create other variables from simple ones LDR R0, [WsPtr, #Log2BPP] LDR R1, [WsPtr, #Log2BPC] LDR R5, [WsPtr, #XEigFactor] LDR R6, [WsPtr, #ModeFlags] TEQ R2, #0 ORRNE R6, R6, #ModeFlag_HardScrollDisabled ; if sprite then disable hard scroll STR R6, [WsPtr, #ModeFlags] ;if switching to a sprite, check for full palette 8bpp, and set modeflags and ;NColour to suit. TEQ R2, #0 BEQ %FT65 ; switching to a sprite ? ADD R7, R2, #spImage ; point R7 at the image/mask start pair LDMIA R7, {R7, LR} ; fetch them CMP R7, LR ; which is lower MOVGT R7, LR ; use the lowest SUB R7, R7, #spPalette ; get the size of the palette CMP R0, #3 BNE %FT51 ; which is 8bpp ? CMP R7, #&800 ; full 8bpp palette ? BNE %FT51 ORR R6, R6, #ModeFlag_FullPalette STR R6, [WsPtr, #ModeFlags] ; set the full palette flag MOV LR, #255 STR LR, [WsPtr, #NColour] ; and set the number of colours 51 LDRB LR, [WsPtr, #SpriteMaskSelect] TEQ LR, #SpriteReason_SwitchOutputToSprite BEQ %FT52 LDR LR, [R2, #spMode] TST LR, #&80000000 ORRNE R6, R6, #ModeFlag_GreyscalePalette+ModeFlag_FullPalette ; alpha masks are 256 greyscale STRNE R6, [WsPtr, #ModeFlags] MOVNE LR, #255 STRNE LR, [WsPtr, #NColour] B %FT65 52 ; Redirecting to sprite image, check for greyscale palette CMP R0, #3 BHI %FT65 TSTEQ R6, #ModeFlag_FullPalette ; 63 colour can't be greyscale TEQNE R7, #0 ; If no palette then (probably) also not greyscale BEQ %FT65 ADD R8, R2, #spPalette 53 LDR LR, [R8], #4 EOR LR, LR, LR, LSL #8 CMP LR, #&10000 BHS %FT65 SUBS R7, R7, #4 BGT %BT53 ORR R6, R6, #ModeFlag_GreyscalePalette STR R6, [WsPtr, #ModeFlags] 65 TST R6, #ModeFlag_DoubleVertical ADREQL R7, WrchNbitTab ; point to correct table ADRNEL R7, WrchNbitDoubleTab LDR R8, [R7, R1, LSL #2] ; get offset to correct code ADD R8, R8, R7 ; convert to absolute address STR R8, [WsPtr, #WrchNbit] ADRL R7, CursorNbitTab LDR R8, [R7, R1, LSL #2] ADD R8, R8, R7 TST R6, #ModeFlag_Teletext ADRNEL R8, CursorTeletext STR R8, [WsPtr, #CursorNbit] TST R6, #ModeFlag_NonGraphic MOVEQ R7, #32 ; if graphic mode MOVEQ R7, R7, LSR R1 ; then = (32 >> lbpc)-1 SUBEQ R7, R7, #1 MOVNE R7, #0 ; else = 0 ;;; NOT REALLY SAFE BET ANYMORE!!! STR R7, [WsPtr, #NPix] RSB R7, R1, #5 ; XShftFactor = 5-log2bpc STR R7, [WsPtr, #XShftFactor] LDR R7, [WsPtr, #YEigFactor] SUBS R7, R5, R7 ; XEigFactor-YEigFactor MOVLT R7, #2 ; X 2 (vert rect) MOVGT R7, #1 ; X>Y => 1 (horz rect) ; else X=Y => 0 (square) STR R7, [WsPtr, #AspectRatio] MOV R8, #1 MOV R7, R8, LSL R0 ; bpp = 1 << lbpp STR R7, [WsPtr, #BitsPerPix] MOV R7, R8, LSL R1 ; bpc = 1 << lbpc STR R7, [WsPtr, #BytesPerChar] [ HiResTTX TST R6, #ModeFlag_Teletext ; in teletext mode MOVNE R7, R7, LSL #1 ; characters are 16 pixels, not 8 ] STR R7, [WsPtr, #CharWidth] TST R6, #ModeFlag_BBCGapMode ; is it a BBC gap mode ? MOVNE R7, #&55 ; yes, then use colour 1 BNE %FT70 TEQ R0, #2 ; if (1<<2=4) bits per pixel MOVEQ R7, #&77 ; then use colour 7 for cursor MOVNE R7, #&FF ; else use colour 15 [ HiResTTX TST R6, #ModeFlag_Teletext ; unless it's 256 colour teletext BEQ %FT70 TEQ R0, #3 MOVEQ R7, #&07 ; in which case still use colour 7 ] 70 ORR R7, R7, R7, LSL #8 ; fill out to whole word ORR R7, R7, R7, LSL #16 STR R7, [WsPtr, #CursorFill] TST R6, #ModeFlag_DoubleVertical MOVEQ R7, #8 ; if single vertical then 8 pixels MOVNE R7, #16 ; if double vertical then 16 pixels STR R7, [WsPtr, #TCharSizeY] TST R6, #ModeFlag_GapMode ADDNE R7, R7, R7, LSR #2 ; make 10 or 20 if gap mode STR R7, [WsPtr, #RowMult] STR R7, [WsPtr, #TCharSpaceY] MOV R8, #8 [ HiResTTX TST R6, #ModeFlag_Teletext MOVNE R8, #16 ] STR R8, [WsPtr, #TCharSizeX] STR R8, [WsPtr, #TCharSpaceX] LDR R8, [WsPtr, #LineLength] MUL R7, R8, R7 STR R7, [WsPtr, #RowLength] ANDS R14, R6, #ModeFlag_Teletext BEQ %FT71 ; Calculate TextOffset necessary to center the text window ; First, Y offset LDR R7, [WsPtr, #RowMult] LDR R14, [WsPtr, #ScrBRow] ADD R14, R14, #1 MUL R14, R7, R14 ; text window height, pixels LDR R7, [WsPtr, #YWindLimit] ADD R7, R7, #1 SUB R14, R7, R14 ; spare rows on screen MOV R14, R14, LSR #1 MUL R14, R8, R14 ; byte offset to start at correct row ; Now, X offset LDR R7, [WsPtr, #TCharSpaceX] LDR R8, [WsPtr, #ScrRCol] ADD R8, R8, #1 MUL R8, R7, R8 ; text window width, pixels LDR R7, [WsPtr, #XWindLimit] ADD R7, R7, #1 SUB R8, R7, R8 ; spare columns on screen MOV R8, R8, LSR #1 LDR R7, [WsPtr, #Log2BPP] MOV R8, R8, LSL R7 ; spare bits on row ADD R14, R14, R8, LSR #3 ; combine with vertical offset BIC R14, R14, #3 ; TTX assumes word alignment 71 STR R14, [WsPtr, #TextOffset] ; finished doing other variables SWI XColourTrans_InvalidateCache ; let ColourTrans know we've changed mode ; so that colours get set up correctly TEQ R4, #0 ; initialising from a save area ? BEQ %FT80 ; no, then set to defaults BL UnpackVars BL AddressCursors BL ValidateVars BL PlainBit BL SetColour LDR R6, [WsPtr, #CursorFlags] ORR R6, R6, #TEUpdate ; TextExpand needs updating STR R6, [WsPtr, #CursorFlags] B %FT90 80 ; *****Change made by DJS ; Original code was: ; MOV R0, #0 ; STR R0, [WsPtr, #ECFShift] ; STR R0, [WsPtr, #ECFYOffset] ; This needed to be changed to make the bottom left of the screen (rather ; than the top left) be the default ECF origin. LDR R0, [WsPtr, #YWindLimit] ADD R0, R0, #1 AND R0, R0, #7 STR R0, [WsPtr, #ECFYOffset] MOV R0, #0 STR R0, [WsPtr, #ECFShift] ; *****End of change made by DJS STR R0, [WsPtr, #ClipBoxEnable] [ ZeroPage <> 0 LDR R0, =ZeroPage ASSERT (ZeroPage :AND: 255) = 0 ] STRB R0, [R0, #OsbyteVars + :INDEX: VDUqueueItems] MOV R0, #8 STR R0, [WsPtr, #GCharSizeX] ; chars are 8x8 by default STR R0, [WsPtr, #GCharSizeY] STR R0, [WsPtr, #GCharSpaceX] ; and with 8x8 spacing STR R0, [WsPtr, #GCharSpaceY] LDR R1, [WsPtr, #ModeFlags] LDR R0, [WsPtr, #CursorFlags] BIC R0, R0, #(ActualState :OR: Vdu5Bit) BIC R0, R0, #(CursorsSplit :OR: PageMode :OR: TeletextMode :OR: ClipBoxEnableBit) TST R1, #ModeFlag_Teletext ; is it teletext ? ORRNE R0, R0, #TeletextMode ; yes, then set bit STR R0, [WsPtr, #CursorFlags] ADRNE LR, %FT85 BNE TeletextInit ; (re-)initialise TTX if appropriate ; Not teletext mode. If we're switching output to screen, then we might ; be in the middle of a mode change from TTX to regular, so free any ; old TTX workspace. LDR R2, [WsPtr, #VduSprite] TEQ R2, #0 BLEQ TeletextFinalise 85 BL InitCursor ; initialise cursor after ; cursorflags BL PlainBit ; also sets up RAMMaskTb BL DefaultColours ; N.B. SetColour is called by both BL DefaultEcfPattern ; of these. BL DefaultLineStyle BL DefaultWindows BL Home 90 ; If we've just switched back to the screen, make sure the greyscale palette flag is accurate. Easiest way is to copy DisplayModeFlags into ModeFlags. LDR R2, [WsPtr, #VduSprite] TEQ R2, #0 LDREQ R2, [WsPtr, #DisplayModeFlags] STREQ R2, [WsPtr, #ModeFlags] BL PostWrchCursor MOV R1, #Service_SwitchingOutputToSprite ; call Ran's service ADD R2, WsPtr, #VduOutputCurrentState LDMIA R2, {R2-R5} ; load the registers that were in R0-R3 on entry IssueService Pull R14 RETURNVC InvalidSaveArea ADRL R0, SpriteErr_InvalidSaveArea [ International Push "lr" BL TranslateError Pull "lr" ] STR R0, [WsPtr, #RetnReg0] RETURNVS VOTS = "VOTS" ; ***************************************************************************** ; Specially saved items ^ 0 InitFlag # 4 ; 0 => uninit, "VOTS" => init SavedSpoolFileH # 1 ; an OSBYTE variable SavedWrchDest # 1 ; --------""-------- SavedVDUqueueItems # 1 ; --------""-------- # 1 ; padding to word align it SavedDataOffset # 0 ; start of compressed data GBLA FirstOffset GBLA NextOffset GBLA CompressedSize MACRO CompStart FirstOffset SETA -1 NextOffset SETA -1 CompressedSize SETA 0 MEND MACRO Compress $v0, $v1, $v2, $v3, $v4, $v5, $v6, $v7 [ "$v0"<>"" Compo $v0 ] [ "$v1"<>"" Compo $v1 ] [ "$v2"<>"" Compo $v2 ] [ "$v3"<>"" Compo $v3 ] [ "$v4"<>"" Compo $v4 ] [ "$v5"<>"" Compo $v5 ] [ "$v6"<>"" Compo $v6 ] [ "$v7"<>"" Compo $v7 ] MEND MACRO Compo $var [ FirstOffset <> -1 [ $var = NextOffset NextOffset SETA ($var)+4 | DCW FirstOffset DCW NextOffset CompressedSize SETA CompressedSize + (NextOffset-FirstOffset) FirstOffset SETA $var NextOffset SETA ($var)+4 ] | FirstOffset SETA $var NextOffset SETA ($var)+4 ] MEND MACRO CompMult $start, $size [ FirstOffset <> -1 [ $start = NextOffset NextOffset SETA $start + $size | DCW FirstOffset DCW NextOffset CompressedSize SETA CompressedSize + (NextOffset-FirstOffset) FirstOffset SETA $start NextOffset SETA $start + $size ] | FirstOffset SETA $start NextOffset SETA $start + $size ] MEND MACRO CompRange $start, $end CompMult $start, ($end+4-$start) MEND MACRO CompEnd [ FirstOffset <> -1 DCW FirstOffset DCW NextOffset CompressedSize SETA CompressedSize + (NextOffset-FirstOffset) ] & -1 MEND CompressionTable CompStart ; CompMult FgEcf, 8*4 ; recreated from GCOLs + ecfs by ; CompMult BgEcf, 8*4 ; call to SetColour Compress GPLFMD, GPLBMD, GFCOL, GBCOL, GWLCol, GWBRow, GWRCol, GWTRow CompRange qqqPad, JVec ; Compress ScreenStart ; worked out from sprite address each time Compress TWLCol, TWBRow, TWRCol, TWTRow CompRange OrgX, NewPtY Compress TForeCol, TBackCol, CursorX, CursorY ; Compress CursorAddr, InputCursorAddr - computed from (Input)CursorX,Y Compress InputCursorX, InputCursorY Compress VduStatus Compress CursorDesiredState, CursorStartOffset, CursorEndOffset Compress CursorCounter, CursorSpeed, Reg10Copy ; Compress CursorFill, CursorNbit - computed from mode variables ; Compress DriverBankAddr - refers to screen always CompRange Ecf1, Ecf4+4 CompMult DotLineStyle, 8 ; Compress ModeNo - stored in sprite itself Compress TFTint, TBTint, GFTint, GBTint ; Compress TotalScreenSize, MaxMode, ScreenEndAddr - refer to screen always Compress CursorFlags, CursorStack Compress ECFShift, ECFYOffset Compress GCharSizeX, GCharSizeY, GCharSpaceX, GCharSpaceY ; Compress TCharSizeX, TCharSizeY ; recomputed from mode number ; Compress TCharSpaceX, TCharSpaceY ; each time ; CompMult FgEcfOraEor, 64 ; recreated from GCOLs and ecfs ; CompMult BgEcfOraEor, 64 ; by call to SetColour ; CompMult BgEcfStore, 64 ; Compress LineDotCnt, LineDotPatLSW, LineDotPatMSW, DotLineLength Compress BBCcompatibleECFs ; Compress WrchNbit - computed from mode number CompRange ClipBoxEnable, ClipBoxTRow CompMult FgPattern, 4*8 CompMult BgPattern, 4*8 Compress TextFgColour Compress TextBgColour CompEnd CompressionTableEnd MainSize * CompressedSize + SavedDataOffset ; N.B. teletext state is not saved ASSERT MainSize <= SaveAreaSize ! 0, "Space free in VDU save area = ":CC::STR:(SaveAreaSize-MainSize) ; ***************************************************************************** ; ; PackVars - Pack variables into save area ; PackVars ROUT CLC ; clear carry - indicate packing PackOrUnpack Push "R0-R4,R14" LDR R0, [WsPtr, #VduSaveAreaPtr] TEQ R0, #0 Pull "R0-R4,PC", EQ ; ptr=0 => no area TEQ R0, #1 ADDEQ R0, WsPtr, #VduSaveArea ; ptr=1 => use MOS's save area BL DoSpecialVars ; process special vars ADD R0, R0, #SavedDataOffset ; move on to compressed data ADR R1, CompressionTable 10 LDR R2, [R1], #4 MVNS R3, R2 ; set Z if it was -1 (end of table) Pull "R0-R4,PC", EQ ; (preserves C) ADD R3, WsPtr, R2, LSR #16 ; R3 = end pointer MOV R2, R2, LSL #16 ADD R2, WsPtr, R2, LSR #16 ; R2 = start pointer 20 LDRCC R4, [R2], #4 ; load a word from vars LDRCS R4, [R0], #4 ; or from save area STRCC R4, [R0], #4 ; store into save area STRCS R4, [R2], #4 ; or into vars TEQ R2, R3 ; end of this block ? BNE %BT20 ; [no, so loop] B %BT10 ; go back for another block ; ***************************************************************************** ; ; UnpackVars - Unpack variables from save area ; UnpackVars ROUT SEC ; set carry - indicate unpacking B PackOrUnpack ; ***************************************************************************** ; ; DoSpecialVars - Pack/unpack special vars: CursorAddr, InputCursorAddr, ; (stored relative to ScreenStart); SpoolFileH, WrchDest, VDUqueueItems ; ; in: R0 -> save area ; ; out: R0 preserved ; R1-R2 corrupted ; Flags preserved ; DoSpecialVars ROUT BYTEWS R1 BCS %FT10 LDRB R2, [R1, #:INDEX: SpoolFileH] STRB R2, [R0, #SavedSpoolFileH] LDRB R2, [R1, #:INDEX: WrchDest] STRB R2, [R0, #SavedWrchDest] LDRB R2, [R1, #:INDEX: VDUqueueItems] STRB R2, [R0, #SavedVDUqueueItems] LDR R1, VOTS ; initialised save area identifier STR R1, [R0, #InitFlag] MOV PC, R14 ; unpack special vars (R1 -> ByteWS) 10 LDRB R2, [R0, #SavedSpoolFileH] STRB R2, [R1, #:INDEX: SpoolFileH] LDRB R2, [R0, #SavedWrchDest] STRB R2, [R1, #:INDEX: WrchDest] LDRB R2, [R0, #SavedVDUqueueItems] STRB R2, [R1, #:INDEX: VDUqueueItems] MOV PC, R14 ; ***************************************************************************** ; ; ValidateVars - Validate unpacked variables (windows, cursor posns) ; ValidateVars ROUT Push R14 ASSERT ScrBRow = ScrRCol + 4 ADD R4, WsPtr, #ScrRCol LDMIA R4, {R4, R5} ; R4 = ScrRCol; R5 = ScrBRow ADD R6, WsPtr, #TWLCol ; R0 = TWLCol; R1 = TWBRow LDMIA R6, {R0-R3} ; R2 = TWRCol; R3 = TWTRow MOV R7, #0 MOV R8, R5 MOV R9, R4 MOV R10, #0 STMIA R6, {R7-R10} ; set up default window BL FSRegs ; and attempt to define text window ASSERT YWindLimit = XWindLimit + 4 ADD R0, WsPtr, #XWindLimit LDMIA R0, {R2, R3} ; R2 = XWindLimit; R3 = YWindLimit ADD R8, WsPtr, #GWLCol ; R4 = GWLCol; R5 = GWBRow LDMIA R8, {R4-R7} ; R6 = GWRCol; R7 = GWTRow CMP R6, R2 ; if GWRCol > XWindLimit CMPLS R7, R3 ; or GWTRow > YWindLimit MOVHI R0, #0 MOVHI R1, #0 STMHIIA R8, {R0-R3} ; then set default graphics window Pull PC END