; 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.VduDriver ; ; ARTHUR OPERATING SYSTEM - Vdu Drivers ; ======================= ; ; Vdu driver code - Vdu queue, mode, default windows etc. ; ; Author R C Manby ; Date 5.9.86 ; GBLL NewStyleEcfs NewStyleEcfs SETL {TRUE} GBLL DoVdu23_0_12 DoVdu23_0_12 SETL {FALSE} GBLL BleedinDaveBell BleedinDaveBell SETL {TRUE} GBLL LCDPowerCtrl LCDPowerCtrl SETL {TRUE} :LAND: :LNOT: STB GET s.vdu.VduDecl GET s.vdu.VduGrafDec MACRO HostVdu Push "R0,R14" LDR R0, [R0, -R0] TEQ R0, #0 ADREQ R0, %FT01 SWIEQ OS_CLI Pull "R0,R14" B %FT02 01 = "HOSTVDU", 0 ALIGN 02 MEND MACRO Print $string Push "R0,R14" LDR R0, [R0, -R0] TEQ R0, #0 BNE %FT01 SWI OS_WriteS = "$string", 0 ALIGN SWI OS_ReadC Pull "R0,R14",CS SWICS OS_BreakPt SWI OS_NewLine 01 Pull "R0,R14" MEND MACRO RMVT $var, $BW [ "$BW"="B" = (wk$var-wkstart)*2 | [ "$BW"="W" = (wk$var-wkstart)*2 +1 | .... Invalid option on RMVT .... ] ] MEND MACRO RVVT $var ASSERT ($var >= 0) :LAND: ($var < &400) :LAND: (($var :AND: 3)=0) = $var :SHR: 2 MEND MACRO IssueService BL Issue_Service MEND MACRO MALIGN $length, $phase LCLA temp LCLS string temp SETA .-ArthurVduDriver [ "$phase"="" string SETS "ALIGN $length" | string SETS "ALIGN $length, $phase" ] $string temp SETA .-ArthurVduDriver-temp [ temp=0 ! 0, string :CC: " fitted exactly" | ! 0, string :CC: " wasted " :CC: :STR: temp ] MEND ; Macro to load up video bandwidth and video memory size MACRO GetBandwidthAndSize $bw, $size [ HAL MOV $size, #0 MOV $bw, #100*1024*1024 LDR $size, [$size, #VideoSize] ! 0, "Sort out GetBandwidthAndSize" | MOV $size, #0 LDR $bw, [$size, #VideoBandwidth] ; load bandwidth LDR $size, [$size, #VideoSize] ; and total amount of video RAM ] MEND ; ***************************************************************************** ; Vdu status bits Vdu2ModeBitPosn * 0 Vdu2Mode * 1 :SHL: Vdu2ModeBitPosn Windowing * 1 :SHL: 3 Shadowing * 1 :SHL: 4 ; ***************************************************************************** ArthurVduDriver ; ***************************************************************************** ; ; VduInit - Once only initialisation of Vdu drivers eg after Break ; ======= ; VduInit ROUT Push R14 MOV R0, #0 STRB R0, [R0, #OsbyteVars + :INDEX: VDUqueueItems] ;purge queue STRB R0, [WsPtr, #ScreenBlankFlag] ; not blanked STR R0, [WsPtr, #CursorCounter] STR R0, [WsPtr, #CursorDesiredState] STR R0, [WsPtr, #VduStatus] STRB R0, [WsPtr, #PointerShapeNumber] ; make sure pointer off STR R0, [WsPtr, #PointerShapeLA] ; no shape passed to HAL yet STR R0, [WsPtr, #CursorStack] ; 0 bits => on STR R0, [WsPtr, #VduSaveAreaPtr] ; indicate no save area yet STR R0, [WsPtr, #ClipBoxEnable] ; no clip box calculating STRB R0, [WsPtr, #ExternalFramestore] Push "r4, r9, r12" mjsAddressHAL MOV r4, r12 ; temp WsPtr mjsCallHAL HAL_Video_Features STR r0, [r4, #HALVideoFeatures] [ :LNOT:UseGraphicsV mjsCallHAL HAL_Video_PixelFormats STR r0, [r4, #HWPixelFormats] mjsCallHAL HAL_Video_BufferAlignment STR r0, [r4, #HWBufferAlign] ] Pull "r4, r9, r12" ;;; sort this out! ! 0, "mjsHAL not doing anything useful with HAL_Video_BufferAlignment" ! 0, "mjsHAL not dealing with lack of h/w pointer" LDR R0, =RangeC+SpriteReason_SwitchOutputToSprite STR R0, [WsPtr, #SpriteMaskSelect] MOV R0, #InitialCursorFlags ; TMD 25/9/86 STR R0, [WsPtr, #CursorFlags] ADRL R0, NUL ; point to MOV PC,R14 STR R0, [WsPtr, #WrchNbit] ; just in case ... ADRL R0, ExportedHLine STR R0, [WsPtr, #HLineAddr] ADD R0, WsPtr, #FgEcfOraEor STR R0, [WsPtr, #GcolOraEorAddr] MOV R0, #maxmode STR R0, [WsPtr, #MaxMode] ; constant now LDROSB R0, LastBREAK ; is it a hard reset ? TEQ R0, #0 BEQ %FT10 ; [no, don't reset font] ; allocate buffer for Tim's whizzy text expansion. This now lives ; in the system heap, unless the claim request fails. If the request ; fails then the pointer points at the original buffer in the Vdu ; driver workspace. ; This allows the user to access depths upto 16 bit per pixel before ; strings things things become afoot at the Circle K. LDR R3, =TextExpandArea_Size BL ClaimSysHeapNode ; allocate buffer for heap data ADDVS R2, WsPtr, #TextExpand STR R2, [WsPtr, #TextExpandArea] LDR R3, =ModeSelector_MaxSize+4 ; get block for two overlapping copies BL ClaimSysHeapNode ; of mode selector, 1 word apart STR R2, [WsPtr, #KernelModeSelector] ; now reset soft font from hard font MOV R1, #1 ; start at character 1*32 STRB R1, [WsPtr, #ScreenMemoryClaimed] ; can't claim memory till a mode change MOV R2, #7 ; copy 7 pages BL DoResetFont [ :LNOT: HAL ; ; mjsHAL - temporary workspace while semi HALised code still in kernel ; MOV r3, #mjs_thalwk_size BL ClaimSysHeapNode ; this had better succeed! LDR r4, =mjs_tempHALworkspace STR r2, [r4, #0] BL mjs_tempHALworkspace_init ; ] ;initialise the 6 pointer shape pointers and blocks ;(shape buffers are 6 * &100 starting at CursorData) ; ADD r0, WsPtr, #PointerShapes LDR r2, =CursorData MOV r3, #6 ADD r4, WsPtr, #PointerShapeBlocks 02 STR r4, [r0] ; attach pointer to block STR r2, [r4, #PointerBuffLA] Push "r0-r2" MOV r1, #0 STRB r1, [r4, #PointerWidth] ; zero width STRB r1, [r4, #PointerHeight] ; zero height (no shape) SUB sp, sp, #3*4 ; room for one entry of OS_Memory page block MOV r1, sp STR r2, [r1, #4] ; provide logical address MOV r2, #1 MOV r0, #&2200 ; convert logical to physical address SWI XOS_Memory LDR r2, [r1, #8] ; read physical address STR r2, [r4, #PointerBuffPA] ADD sp, sp, #3*4 Pull "r0-r2" ADD r4, r4, #PointerBlkSize ADD r2, r2, #&100 ADD r0, r0, #4 SUBS r3, r3, #1 BNE %BT02 ; palette space (256 normal + 1 border + 3 pointer = 260), and allowing for Gamma Correction ; this space is: blank palette, 260 words ; logical and physical copies of both flash states, 260*4 words ; 3 lookup tables for r,g,b mapping, 3*256 bytes ; LDR r3, =Pal_Blocksize BL ClaimSysHeapNode ; this had better succeed! ASSERT :INDEX:Pal_Blank = 0 STR r2, [WsPtr, #BlankPalAddr] ADD r3, r2, #Pal_LogFirst STR r3, [WsPtr, #FirPalAddr] ADD r3, r2, #Pal_LogSecond STR r3, [WsPtr, #SecPalAddr] ; initialise blank palette to all solid black MOV r3, #0 MOV r4, #PalEntries 04 STR r3, [r2], #4 SUBS r4, r4, #1 BNE %BT04 ADD r2, r2, #Pal_RTable-(Pal_Blank+4*PalEntries) ; r2 -> rgb tables ; initialise red, green and blue transfer function tables to 1-1 mapping MOV r0, #0 05 STRB r0, [r2, #Pal_STable-Pal_RTable] ; store in supremacy table STRB r0, [r2, #Pal_BTable-Pal_RTable] ; store in blue table STRB r0, [r2, #Pal_GTable-Pal_RTable] ; store in green table STRB r0, [r2], #1 ; store in red table, and advance ADD r0, r0, #1 CMP r0, #256 BCC %BT05 10 BL SpriteInit LDR R14, [WsPtr, #ScreenEndAddr] LDR R0, [WsPtr, #TotalScreenSize] RSB R0, R0, R14 STR R0, [WsPtr, #DisplayStart] BL SetDisplayScreenStart STR R0, [WsPtr, #ScreenStart] STR R0, [WsPtr, #CursorAddr] STR R0, [WsPtr, #InputCursorAddr] Pull PC LTORG ; ***************************************************************************** ; ; InitialiseMode - Select mode number given by ModeNo variable ; ; Called by MOS once before initialisation, and then afterwards ; before printing "RISC OS ..." ; ; in: - ; out: All registers may be corrupted (except R13_svc !) ; InitialiseMode Entry [ SoftResets MOV r0, #&FD ; read last reset type MOV r1, #0 MOV r2, #&FF SWI XOS_Byte CMP r1, #SoftReset LDREQ r0, =VduDriverWorkSpace+ModeNo LDREQ r0, [r0] ; use previous mode if a soft reset MOVNE r0, #1 ; otherwise read configured mode SWINE XOS_ReadSysInfo | MOV r0, #1 ; no need to check for soft reset, SWI XOS_ReadSysInfo ; always use configured value ] MOV r1, r0 MOV r0, #ScreenModeReason_SelectMode SWI XOS_ScreenMode EXIT VC MOV r0, #114 ; failed, so get rid of any shadow MOV r1, #1 SWI XOS_Byte SWI XOS_WriteI+22 SWIVC XOS_WriteI+0 ; and if we can't get mode 0, we're really fooked!!! EXIT ; ;------------------------------------------------------------------------------ ; ; Vdu - Main VDU driver entry point ; === Queue up bytes and dispatch via JVec ; ; in: R0 = character to be printed ; ; out: C=1 <=> send character to printer if enabled ; Vdu ROUT MOV R11, #0 ; NB used later in Vdu07 as well LDRB R10, [R11, #OsbyteVars + :INDEX: VDUqueueItems] MOVS R9, R10, LSL #24 ; move up to top byte (for sign extend) BEQ Vdu07 ; not queueing, then start Vdu sequence ; *****Comment made by DJS: Changing this to fall through if not queueing ; and branch if queueing might be a good idea - it would speed up all ; printable characters and simple cursor movements. LDR R8, [WsPtr, #QOffset] STRB R0, [R8, R9, ASR #24] ; add byte to queue ADD R10, R10, #1 ; move on pointer STRB R10, [R11, #OsbyteVars + :INDEX: VDUqueueItems] CMP R10, #&100 ; finished sequence ? MOVCC PC, R14 ; no, then return (no printing) Push "R0, R14" BL PreWrchCursor ; exits with R6 = CursorFlags Pull "R0" 05 [ No26bitCode ADR R14, VduPrintExit | MOV R14, PC ADD R14, R14, #(VduPrintExit-%BT05-8) ; push address of SEC exit ; (with flags) ] Push R14 BL Vdu05 BL PostWrchCursor CLC ; also clears V Pull "R14,PC" VduPrintExit ; exit used if print required BL PostWrchCursor SEC ; also clears V Pull PC ; ***************************************************************************** Vdu05 ROUT TST R6, #VduDisabled ; VDU enabled ? LDREQ PC, [WsPtr, #JVec] ; yes, then do it (no printing) ; Queue sequence has just completed, but VDU is disabled ; Only interesting case is VDU 1 (SOH), which must still print ; the character if the printer is enabled LDR R10, [WsPtr, #JVec] ADR R11, SOH TEQ R10, R11 ; JVec -> SOH ? MOVNE PC, R14 ; no, then return (no printing) SOH LDR R1, [WsPtr, #VduStatus] ; in VDU 2 mode ? TST R1, #Vdu2Mode MOVEQ PC, R14 ; no, then return Push R14 BL MOSDoPrint Pull PC, VC ; good exit, so return Pull R14 ; bad exit, return with error B VduBadExit ; ***************************************************************************** Vdu07 ROUT AND R0, R0, #&FF ; Only look at bottom byte! CMP R0,#127 ;If DELETE, change R0 to 32 and MOVEQ R0,#32 ; drop through to control char code CMPNE R0,#31 ;Otherwise, branch to printable char BHI Vdu20 ; code if not a control char ; *****Further desirable change: Make printable characters fall through, ; control characters take the branch - speeding up printable characters is ; important! ADR R10, VduJTb ; Address of beginning of jump table LDR R9, [R10, R0, LSL #2] ; Get routine address from VduJTB STR R9, [WsPtr, #JVec] ; save address ADD R10, R10, #(VduQTb-VduJTb) LDRB R9, [R10, R0] ; Pick up QQ + length of queue RSBS R10, R9, #QQ ; -(length of queue) & test if none STRNEB R10, [R11, #OsbyteVars + :INDEX: VDUqueueItems] ; yes, then set up Osbyte variable ADDNE R9, R9, WsPtr STRNE R9, [WsPtr, #QOffset] ; and QOffset MOVNE PC, R14 Push "R0,R14" BL PreWrchCursor ; exits with R6 = CursorFlags Pull "R0" 10 MOV R14, PC ADD R14, R14, #(VduPrintExit-%BT10-8) ; push address of SEC exit ; (with flags) Push R14 BL Vdu10 BL PostWrchCursor CLC ; also clears V Pull "R14,PC" ; ; This is the only byte of a single byte Vdu sequence ; ; R6 = CursorFlags ; R11 = 0 (used to index VDUqueueItems) ; Vdu10 ROUT TST R6, #CursorsSplit ; are we cursor editing ? BNE Vdu15 Vdu10Continue ; TMD 31/7/87; bug fixed here - chars 8 to 13 should still go to printer if ; enabled, even if VDU is disabled CMP R0, #8 ; is char in range 8-13 ? RSBCSS R1, R0, #13 ; if so then we want to print it LDRCS R1, [WsPtr, #VduStatus] MOVCSS R1, R1, LSR #(Vdu2ModeBitPosn +1) ; providing printer enabled Pull R14, CS ; so pull old R14 TST R6, #VduDisabled ; are we disabled LDREQ PC, [WsPtr, #JVec] ; enabled, so go get em floyd ! TEQ R0, #6 ; disabled, so is it ACK (enable VDU) BICEQ R6, R6, #VduDisabled STREQ R6, [WsPtr, #CursorFlags] NUL ;Does nothing ESC ;Does nothing MOV PC, R14 ; return anyway ; ***************************************************************************** Vdu15 TEQ R0, #13 ; and is it a carriage return ? BNE Vdu10Continue Push "R0, R14" BIC R6, R6, #CursorsSplit ; then stop cursor editing STR R6, [WsPtr, #CursorFlags] MOV R1, #1 ; restore old Reg10Copy BL CursorOnOff Pull "R0, R14" B Vdu10Continue ; ***************************************************************************** Vdu20 ROUT Push "R0,R14" BL PreWrchCursor ; exits with R6 = CursorFlags Pull "R0" 05 MOV R14, PC ADD R14, R14, #(VduPrintExit-%BT05-8) ; push address of SEC exit ; (with flags) Push R14 BL TimWrch BL PostWrchCursor CLC ; also clears V Pull "R14,PC" ; ***************************************************************************** VduJTb ; Table of addresses & NUL ; Does nothing & SOH ; Next char to printer only & STX ; Enable printer & ETX ; Disable printer & EOT ; Write text at text cursor & ENQ ; Write text at graphics cursor & NUL ; Enable VDU drivers & BEL ; Beep & BS ; Cursor left & HT ; Cursor right & VduLF ; Cursor down & VT ; Cursor up & FF ; Clear text area (CLS) & VduCR ; Carriage return & SO ; Page mode on & SI ; Page mode off & DLE ; Clear graphics area (CLG) & DC1 ; Define text colour (COLOUR) & DC2 ; Define graphics colour and action (GCOL) & DC3 ; Define logical colour & VDU20 ; Restore default logical colours & NAK ; Disable VDU drivers & SYN ; Select screen mode (MODE) & ETB ; Reprogram display character (VDU23,...) & CAN ; Define graphics window & EM ; (PLOT k,x,x,y,y) & DefaultWindows ; Restore default windows & ESC ; Does nothing & FS ; Define text window & GS ; Define graphics origin & RS ; Home cursor to "top left" & US ; Move text cursor (TAB x,y) & Delete ; Delete character (127) ASSERT QQ+9 < 256 VduQTb ; QQ + length of queue for each of the above DCB QQ+0, QQ+1, QQ+0, QQ+0, QQ+0, QQ+0, QQ+0, QQ+0 DCB QQ+0, QQ+0, QQ+0, QQ+0, QQ+0, QQ+0, QQ+0, QQ+0 DCB QQ+0, QQ+1, QQ+2, QQ+5, QQ+0, QQ+0, QQ+1, QQ+9 DCB QQ+8, QQ+5, QQ+0, QQ+0, QQ+4, QQ+4, QQ+0, QQ+2 DCB QQ+0 ; (delete) ALIGN ; ***************************************************************************** WrchNbitTab & Wrch1bit-WrchNbitTab & Wrch2bit-WrchNbitTab & Wrch4bit-WrchNbitTab & Wrch8bit-WrchNbitTab & Wrch16bit-WrchNbitTab & Wrch32bit-WrchNbitTab WrchNbitDoubleTab & Wrch1bitDouble-WrchNbitDoubleTab CursorNbitTab & Cursor1bit-CursorNbitTab & Cursor2bit-CursorNbitTab & Cursor4bit-CursorNbitTab & Cursor8bit-CursorNbitTab & Cursor16bit-CursorNbitTab & Cursor32bit-CursorNbitTab ; table of susbstitute mode numbers to cater for hardware that might ; not support all of 1,2,4,8 bpp (bits per pixel) modes ; ; indexed by mode number (0..49), pairs of byte values: ; bpp = bits per pixel of this mode number ; promo = promoted mode number (0..49), or &FF if none ; ; promoted number is: ; 1) same resolution at next higher bpp (up to 8), if available, or ; 2) similar resolution at 8 bpp (8 bpp should be available on most h/w) ; ModePromoTable ; ; bpp promo mode no. ; DCB 1, 8 ; 0 DCB 2, 9 ; 1 DCB 4, 10 ; 2 DCB 1, 15 ; 3 DCB 1, 1 ; 4 DCB 2, 2 ; 5 DCB 1, 13 ; 6 [ TTX256 DCB 8, &FF ; 7 | DCB 4, 13 ; 7 ] DCB 2, 12 ; 8 DCB 4, 13 ; 9 DCB 8, &FF ; 10 DCB 2, 14 ; 11 DCB 4, 15 ; 12 DCB 8, &FF ; 13 DCB 4, 15 ; 14 DCB 8, &FF ; 15 DCB 4, 24 ; 16 DCB 4, 24 ; 17 DCB 1, 19 ; 18 DCB 2, 20 ; 19 DCB 4, 21 ; 20 DCB 8, &FF ; 21 DCB 4, 36 ; 22 DCB 1, 28 ; 23 DCB 8, &FF ; 24 DCB 1, 26 ; 25 DCB 2, 27 ; 26 DCB 4, 28 ; 27 DCB 8, &FF ; 28 DCB 1, 30 ; 29 DCB 2, 31 ; 30 DCB 4, 32 ; 31 DCB 8, &FF ; 32 DCB 1, 34 ; 33 DCB 2, 35 ; 34 DCB 4, 36 ; 35 DCB 8, &FF ; 36 DCB 1, 38 ; 37 DCB 2, 39 ; 38 DCB 4, 40 ; 39 DCB 8, &FF ; 40 DCB 1, 42 ; 41 DCB 2, 43 ; 42 DCB 4, 28 ; 43 DCB 1, 45 ; 44 DCB 2, 46 ; 45 DCB 4, 15 ; 46 DCB 8, &FF ; 47 DCB 4, 49 ; 48 DCB 8, &FF ; 49 DCB 1, 51 ; 50 DCB 2, 52 ; 51 DCB 4, 53 ; 52 DCB 8, &FF ; 53 ASSERT (.-ModePromoTable)=(NumModes*2) ; ALIGN ; ***************************************************************************** ; ; SYN - Perform MODE change ; ; External routine ; ; in: Vdu queue contains mode number ; SYN ROUT ; Select screen mode (MODE) Push lr LDRB R2, [WsPtr, #QQ] ; Read mode number from queue BL ModeChangeSub Pull lr MOVVC pc, lr ; if no error, exit to Vdu ; (which calls PostWrchCursor) ; else drop thru into ... VduBadExit ; jumped to if an error in VDU code Push R0 ; save error pointer BL PostWrchCursor SETV Pull "R0, R14,PC" ModeChangeSub ROUT Push lr ;If its a common mode number (0..49) consider a possible mode number ;substitution, if hardware does not support given bits per pixel. ;We are vaguely assuming h/w supports at least 8 bpp, otherwise we may ;not be able to find a usable mode number, and later code may not handle ;that well. This is probably ok, 8 bpp is almost universal. ; CMP r2, #256 BHS mchsub_3 AND r1, r2, #&7F CMP r1, #NumModes ; mode number BHS mchsub_3 Push "r3, r4" [ UseGraphicsV Push "r0-r2" MOV r4, #GraphicsV_DisplayFeatures BL CallGraphicsV TEQ r4, #0 MOVEQ r4, r1 MOVNE r4, #2_111111 Pull "r0-r2" | LDR r4, [WsPtr, #HWPixelFormats] ; bits 0 to 3 set for 1,2,4,8 bpp supported ] ADR lr, ModePromoTable ; table of mode promotions mchsub_1 MOV r1, r1, LSL #1 LDRB r3, [lr, r1] ; bpp for this mode number (1,2,4,8) TST r3, r4 ; supported in h/w? ANDNE r2, r2, #&80 ; if yes, take mode number that passed ORRNE r2, r2, r1, LSR #1 BNE mchsub_2 ADD r1, r1, #1 ; else look for promotion LDRB r1, [lr, r1] ; new mode number CMP r1, #&FF ; &FF if none BNE mchsub_1 ;alright, dont panic, just try to get a VGA-like mode of any bpp, if not tried already CMP r1, #28 ; VGA 8 bpp MOVNE r1, #25 ; VGA 1 bpp BNE mchsub_1 mchsub_2 Pull "r3, r4" ; mchsub_3 MOV R1, #Service_PreModeChange IssueService TEQ R1, #0 ; was service claimed ? BNE %FT03 ; no, so continue CMP R0, #0 ; service claimed; generate error ? Pull PC, EQ ; no, just exit (V=0 from CMP) B %FT07 ; yes, then generate error 03 MOV R0, R2 ; put mode (possibly changed) in R0 MOV R2, R0, LSR #7 ; R2 = 0/1 if bit 7 of mode clear/set CMP r2, #2 ; if mode number >= 256 then mode selector MOVCS r2, #0 ; so no shadow LDROSB R1, Shadow TEQ R1, #0 ; if shadow 0 then force shadow mode MOVEQ R2, #1 BL FindOKMode ; out: R1 = mode we are going to use BVS %FT07 TEQ R0, R1 ; if substitute mode MOVNE R2, #0 ; then don't use shadow CMP r1, #&100 BICCC r10, r1, #&80 MOVCS r10, r1 MOV R11, R10 BL PushModeInfo BVS %FT07 ; [probably duff mode selector] LDR R11, [R13, #wkScreenSize] ; get screen size for this mode LDR R9, [WsPtr, #TotalScreenSize] ; maximum allowed amount Push R1 ; save proper mode RSBS R1, R9, R11, LSL R2 ; extra amount we need BLS %FT08 ; enough memory, so skip [ UseGraphicsV LDRB R0, [WsPtr, #ExternalFramestore] TEQ R0, #0 BNE %FT06 ; can't grow an external framestore ] ; try to extend the amount of screen memory ! 0, "Need to fix ModeChangeSub to not leave CursorAddr, etc. pointing to unmapped pages during DA resize. Causes bad stuff should an abort occur/screen output be attempted!" ; Note that even enlarging the DA can leave the pointers in a bad state, due to the way the screen DA handler shuffles down/unmaps the lower mapping of VRAM before the higher copy is enlarged MOV R0, #2 ; expand screen memory SWI XOS_ChangeDynamicArea BVC %FT08 06 ADD R13, R13, #PushedInfoSize + 1*4 ; junk stacked info + mode no. ADR R0, ErrorBlock_BadMODE [ International BL TranslateError ] 07 SETV ; indicate error Pull PC [ STB TV_Mode_string = "TV_Mode", 0 ALIGN ] ; valid mode and enough memory 08 Pull R0 ; restore mode we are using CMP r0, #&100 ; if not mode selector BICCC r0, r0, #&80 ; then knock off shadow bit BCC %FT12 ; it's a mode selector, so copy it to our static mode selector block LDR r1, [WsPtr, #KernelModeSelector] ; point at block SUBS r3, r0, r1 ; if r0 -> 1st mode block position TEQNE r3, #4 ; or r0 -> 2nd mode block position MOVEQ r1, r0 ; then use it in place BEQ %FT09 LDR r3, [WsPtr, #DisplayModeNo] ; else check if current mode is a mode selector SUB r3, r3, r1 ; r3 = offset from start of block CMP r3, #8 ; if 0 or 4 EORCC r3, r3, #4 ; then make 4 or 0 (ie toggle between them) ADDCC r1, r1, r3 ; and add on base ASSERT (ModeSelector_ModeVars+4) :AND: 7 = 0 09 MOV r3, #0 10 LDR r6, [r0, r3] ; copy 1st word - after fixed bit this will be previous var value STR r6, [r1, r3] ADD r3, r3, #4 LDR r6, [r0, r3] ; copy 2nd word - after fixed bit this will be next var index STR r6, [r1, r3] ADD r3, r3, #4 CMP r3, #ModeSelector_ModeVars + 4 ; only exit if we've done the essential bit CMPCS r6, #-1 ; AND we've had a -1 as the var index (NOT as the value) CMPCC r3, #ModeSelector_MaxSize ; OR we've gone off the end of our block BCC %BT10 ; [we haven't, so loop] CMP r3, #ModeSelector_MaxSize ; if we did go off the end MOVCS r6, #-1 STRCS r6, [r1, #ModeSelector_MaxSize-4] ; then terminate it properly MOV r0, r1 ; point at static block 12 STR R0, [WsPtr, #DisplayModeNo] ; store the new display mode ; now issue Service_ModeChanging MOV R1, #Service_ModeChanging BL IssueModeService [ {FALSE} ;;; LCDPowerCtrl :LAND: :LNOT: STB ;;; mjsHAL no LCD support ;Switch LCD off here if it is _not_ an LCD mode MOV R3, #0 LDRB R3, [R3, #LCD_Active] ANDS R0, R3, #&7F ;Pick out the lcd mode bits, ignoring the single/dual panel bit Push "r0-r1" MOVEQ R0, #0 LDREQ R1, =:NOT:(PortableControl_LCDEnable :OR: PortableControl_BacklightEnable) SWIEQ XPortable_Control Pull "r0-r1" ] ; R13 -> mode variables 13 LDR R3, [R13, #wkScreenSize] STR R3, [WsPtr, #ScreenSize] ; store screensize BEFORE calling ; ConvertBankToAddress (was a bug!) [ UseGraphicsV Push "r0-r4" MOV r4, #GraphicsV_FramestoreAddress BL CallGraphicsV TEQ r4, #0 BNE %FT581 MOV r1, r1, LSR #20 ; round size down to 1MB MOV r2, r1, LSL #20 ADD r0, r0, #1:SHL:20 ; round addr up to 1MB SUB r0, r0, #1 MOV r0, r0, LSR #20 ; (because of OS_Memory 13 limits) MOV r1, r0, LSL #20 MOV r0, #13 ; map in permanently ORR r0, r0, #1:SHL:8 ; buffered, uncached ORR r0, r0, #1:SHL:16+1:SHL:17 ; doubly map, access permission specified SWI XOS_Memory BVS %FT581 STR r2, [WsPtr, #TotalScreenSize] ADD r3, r3, r2 STR r3, [WsPtr, #ScreenEndAddr] MOV r14, #1 B %FT582 581 MOV r0, #128+2 SWI XOS_ReadDynamicArea STRVC r1, [WsPtr, #TotalScreenSize] ADDVC r0, r0, r1 STRVC r0, [WsPtr, #ScreenEndAddr] MOV r14, #0 582 Pull "r0-r4" STRB r14, [WsPtr, #ExternalFramestore] ] TEQ R2, #0 ; Shadowing or not ? LDR R3, [WsPtr, #VduStatus] BICEQ R3, R3, #Shadowing ORRNE R3, R3, #Shadowing STR R3, [WsPtr, #VduStatus] STRB R2, [WsPtr, #ScreenMemoryClaimed] ; only allow ADFS to claim ; if non-shadow (simplifies things!) BL ConvertBankToAddress ; R3 := default start for this bank STR R3, [WsPtr, #DriverBankAddr] STR R3, [WsPtr, #DisplayBankAddr] MOV R6, #0 STRB R6, [R6, #OsbyteVars + :INDEX:MemDriver] ; indicate default STRB R6, [R6, #OsbyteVars + :INDEX:MemDisplay] ; for both of these LDR R6, [R13, #wkModeFlags] STR R6, [WsPtr, #DisplayModeFlags] MOV R2, #wkend-wkdispstart ; number of bytes to do ADD R1, R13, #wkdispstart ADD R4, WsPtr, #PalIndex ; first display mode variable 15 LDR R3, [R1], #4 ; copy variables STR R3, [R4], #4 SUBS R2, R2, #4 ; loop until all done BNE %BT15 ; now set up other mode variables by calling SwitchOutput ADD R3, WsPtr, #VduSaveArea+InitFlag STR R2, [R3] ; indicate uninitialised (R2=0) TST R6, #Flag_Teletext MOVNE R3, #0 ; if teletext, then no save area MOVEQ R3, #1 ; else MOS's save area MOV R1, #0 ; just in case MOV R0, #SpriteReason_SwitchOutputToSprite SWI XOS_SpriteOp ; now create other variables from simple ones LDR R3, [WsPtr, #NColour] STR R3, [WsPtr, #DisplayNColour] ASSERT YWindLimit = XWindLimit +4 ASSERT DisplayYWindLimit = DisplayXWindLimit +4 ADD R0, WsPtr, #XWindLimit LDMIA R0, {R3, R4} ADD R0, WsPtr, #DisplayXWindLimit STMIA R0, {R3, R4} ASSERT YEigFactor = XEigFactor +4 ASSERT DisplayYEigFactor = DisplayXEigFactor +4 ADD R0, WsPtr, #XEigFactor LDMIA R0, {R3, R4} ADD R0, WsPtr, #DisplayXEigFactor STMIA R0, {R3, R4} ASSERT Log2BPP = Log2BPC +4 ADD R0, WsPtr, #Log2BPC LDMIA R0, {R0, R1} ; R0 = Log2BPC; R1 = Log2BPP SUB R3, R3, R0 ; adjust XEig for double pixels ADD R3, R3, R1 STR R3, [WsPtr, #PointerXEigFactor] LDR R3, [R13, #wkModeFlags] STR R3, [WsPtr, #ModeFlags] ; finished doing other variables [ :LNOT:UseGraphicsV Push "R0-R3, R9, R12" ; preserve registers ready to make HAL call later ADD R0, R13, #wkwordsize+6*4 ; R0 -> VIDCList3 (we have just pushed 6 regs) | ADD R0, R13, #wkwordsize ; R0 -> VIDCList3 ] ;adjust vertical porch parameters in VIDCList3 for TVVertical (from *TV) ; LDROSB R1, TVVertical MOV R1, R1, LSL #24 ; sign extend to 32 bits MOV R1, R1, ASR #24-3 ; and multiply by 8 LDR R2, [WsPtr, #ModeFlags] TST R2, #Flag_GapMode ; gap mode ? ADDNE R1, R1, R1, ASR #2 ; add on 2 rows if so TST R2, #Flag_DoubleVertical ; if double vertical ADDNE R1, R1, R1 ; then double it LDR R2, [R0, #VIDCList3_VertiBackPorch] SUBS R2, R2, R1 MOVMI R2, #0 STR R2, [R0, #VIDCList3_VertiBackPorch] ;subtract from back porch, clamp at 0 LDR R2, [R0, #VIDCList3_VertiFrontPorch] ADDS R2, R2, R1 MOVMI R2, #0 STR R2, [R0, #VIDCList3_VertiFrontPorch] ;add to front porch, clamp at 0 ;remember pixel rate (kHz) and border settings from VIDCList3 ; LDR R2, [R0, #VIDCList3_PixelRate] STR R2, [WsPtr, #PixelRate] LDR R2, [R0, #VIDCList3_HorizLeftBorder] STR R2, [WsPtr, #BorderL] LDR R2, [R0, #VIDCList3_VertiBottomBorder] STR R2, [WsPtr, #BorderB] LDR R2, [R0, #VIDCList3_HorizRightBorder] STR R2, [WsPtr, #BorderR] LDR R2, [R0, #VIDCList3_VertiTopBorder] STR R2, [WsPtr, #BorderT] ;remember DPMSState (if specified) from VIDCList3 ; MOV R2, #0 ; DPMSState = 0 if not specified in list ADD R1, R0, #VIDCList3_ControlList 20 LDR R3, [R1], #8 ; loop over the control parameter list CMP R3, #-1 BEQ %FT30 ; didn't find the DPMSState entry TEQ R3, #ControlList_DPMSState BNE %BT20 ; next control parameter LDR R2, [R1, #-4] ; read DPMSState value AND R2, R2, #3 ; only bits 0,1 valid 30 STRB R2, [WsPtr, #ScreenBlankDPMSState] ;kernel/HAL split - call the HAL to program video controller for mode, ; [ UseGraphicsV MOV R4, #GraphicsV_SetMode BL CallGraphicsV | mjsAddressHAL mjsCallHAL HAL_Video_SetMode Pull "R0-R3, R9, R12" ; restore registers after HAL call ] ADD R13, R13, #PushedInfoSize ; junk stacked data ; for backward compatibility, show that video DMA is enabled in ; MEMC soft copy (DON'T call OS_UpdateMEMC, which would also ; make redundant call to HAL) ; SavePSR R2 MOV R0, #0 WritePSRc SVC_mode+I_bit+F_bit, R14 LDR R1, [R0, #MEMC_CR_SoftCopy] ORR R1, R1, #(1 :SHL: 10) STR R1, [R0, #MEMC_CR_SoftCopy] RestPSR R2 BL SetVendDefault LDR R1, [WsPtr, #ScreenEndAddr] ; need to reload cos corrupt LDR R2, [WsPtr, #TotalScreenSize] SUB R0, R1, R2 ; R0 = Vstart BL SetVstart MOV R0, #0 STRB R0, [WsPtr, #PointerShapeNumber] STR R0, [WsPtr, #TeletextOffset] STR R0, [WsPtr, #CursorStack] ; restore cursor on a mode BL PalInit ; set default palette BL UnblankScreen BL SetMouseRectangle BL FF [ {FALSE} ;;; LCDPowerCtrl :LAND: :LNOT: STB ;;; mjsHAL no LCD support ;Switch the LCD on if LCD mode Push "r0" MOV R1, #0 LDRB R1, [R1, #LCD_Active] ANDS R1, R1, #&7F ;Check the LCD mode bits only, not the single/dual panel bit LDRNE R0, =(PortableControl_LCDEnable :OR: PortableControl_BacklightEnable) LDRNE R1, =:NOT:(PortableControl_LCDEnable :OR: PortableControl_BacklightEnable) SWINE XPortable_Control Pull "r0" ] MOV R1, #Service_ModeChange BL IssueModeService CLRV ; indicate no error Pull PC ; return to caller MakeErrorBlock BadMODE LTORG ; The following symbols, apart from being used in NColourTable, ; are also used in constructing mode selectors for mode numbers in VduModes NColour_0 * 1 NColour_1 * 3 NColour_2 * 15 NColour_3 * 63 NColour_4 * &FFFF NColour_5 * &FFFFFFFF GET s.vdu.VduModes ; ***************************************************************************** ; ; IssueModeService - Issue service (either ModeChanging or ModeChange) ; ; in: R1 = service code ; ; out: R1 corrupted ; IssueModeService Entry "r2,r3" BL ReadMonitorType LDR r2, [WsPtr, #DisplayModeNo] IssueService EXIT ; ***************************************************************************** ; ; PushModeInfo - Push appropriate mode table and video controller params ; onto stack, having generated it by possibly issuing service ; ; in: R10 = mode to try for ; R11 = mode to use if service not claimed ; R10 and R11 should have bit 7 CLEAR (if mode numbers) ; ; out: If r10 is an invalid mode selector or invalid new format sprite word then ; V=1 ; r0 -> error ; stack flat (no pushed info) ; else ; V=0 ; Stack holds a mode table (size wkwordsize) and VIDCList ; type 3 (size VIDCList3Size) (total size PushedInfoSize) ; endif ; All other registers preserved ; PushModeInfoAnyMonitor ROUT SUB sp, sp, #PushedInfoSize Push "r2-r4,r7-r11, lr" MOV r3, #-1 MOV r7, #-1 ; indicate no VIDC stuff necessary CMP r10, #&100 ; is it a mode selector BCS PushModeInfoCommonNoService BranchIfKnownMode r10, PushModeInfoCommonNoService B PushModeInfoCommon PushModeInfo ROUT SUB sp, sp, #PushedInfoSize Push "r2-r4,r7-r11, lr" MOV r7, #0 ; indicate VIDC stuff IS necessary BL ReadMonitorType PushModeInfoCommon MOV r2, r10 ; r2 = original mode BL OfferModeExtension BEQ %FT30 ; [service claimed] CMP r2, #&100 ; service not claimed - check if mode selector MOVCC r10, r11 ; unrecognised mode number, so use substitute BCC PushModeInfoCommonNoService ; service not claimed and it's a mode selector - return error "Screen mode not available" ADR r0, ErrorBlock_ModeNotAvailable [ International BL TranslateError ] B %FT40 MakeErrorBlock ModeNotAvailable 30 TEQ r4, #0 ; if r4 returned zero, then a mode selector was used ; either initially or after translation from mode number BEQ %FT35 ; so no ws list LDR r2, [r4, #4]! ; else if claimed, then find ws base mode CMP r2, #&100 ; if ws base mode is a mode selector, it's invalid ANDCC r2, r2, #&7F ; else knock off shadow bit BCC %FT35 MOV r10, r11 ; invalid ws base mode, so pretend service not responded to ; and drop thru to PushModeInfoCommonNoService PushModeInfoCommonNoService MOV r2, r10 ; else use provided mode MOV r3, #0 MOV r4, #0 35 ADD r9, sp, #9*4 ; adjust for pushed registers CMP r2, #&100 BCC %FT45 BL GenerateModeSelectorVars ; also copes with new sprite mode word BVC %FT55 ; we got an error 40 SETV Pull "r2-r4,r7-r11,lr" ; restore registers ADD sp, sp, #PushedInfoSize ; junk stack frame MOV pc, lr ; exit VS, r0 -> error 45 ADRL r14, Vwstab LDR r10, [r14, r2, LSL #2] ADD r14, r14, r10 ; r14 -> mode table MOV r10, #wkwordsize-4 50 LDR r2, [r14, r10] STR r2, [r9, r10] SUBS r10, r10, #4 BCS %BT50 ; now change any variables specified in workspace block or mode selector overrides 55 TEQ r4, #0 ; if service was claimed ADDNE r4, r4, #4 ; then skip ws base mode BLNE ProcessModeVarPairs ; special VIDCListType3 widgetry ; 1) Set SyncPol_Interlace (according to TVInterlace) if not already specified ; 2) check for the interlaced flag in the control parameters - if set, set the interlaced ; flag in the mode flags TEQ r3, #0 ; do we have a VIDC list? BEQ %FT58 LDR r2, [r3, #0] ; is it type 3? (actually, it always should be now) TEQ r2, #3 BNE %FT58 LDR r10, [r3, #VIDCList3_SyncPol] TST r10, #SyncPol_InterlaceSpecified BNE %FT56 ; Interlace already specified LDROSB R14, TVInterlace TST R14, #1 ORRNE R10, R10, #SyncPol_InterlaceSpecified ; specify as non-interlaced ORREQ R10, R10, #(SyncPol_InterlaceSpecified+SyncPol_Interlace) ; specify as interlaced STR R10, [r3, #VIDCList3_SyncPol] 56 ADD r10, r3, #VIDCList3_ControlList 57 LDR r14, [r10], #8 ; loop over the control parameter list CMP r14, #-1 BEQ %FT58 ; didn't find the interlaced entry - not interlaced TEQ r14, #ControlList_Interlaced BNE %BT57 ; check the next one then LDR r14, [r10, #-4] ; read value TEQ r14, #0 BEQ %FT58 ; if zero, not interlaced ; it's interlaced LDR r14, [r9, #wkModeFlags] ORR r14, r14, #Flag_InterlacedMode STR r14, [r9, #wkModeFlags] 58 [ UseGraphicsV Push "r0-r2,r4" MOV r4, #GraphicsV_DisplayFeatures BL CallGraphicsV ; claim or release falsevsync vector if vsyncs supported/not supported Push "r0" TST r0, #1<<4 ; NE = VSyncs not generated? MOV a1, #TickerV LDR a2, =FalseVsyncIRQ LDR a3, =OsbyteVars BEQ %ft2 SWI XOS_Claim B %ft1 2 SWI XOS_Release 1 Pull "r0" TST r0, #1 ; bit 0 is h/w scroll support Pull "r0-r2,r4" | LDR r14, [WsPtr, #HALVideoFeatures] TST r14, #1 ; bit 0 is h/w scroll support ] LDREQ r14, [r9, #wkModeFlags] ORREQ r14, r14, #Flag_HardScrollDisabled STREQ r14, [r9, #wkModeFlags] ; hopefully, R7 is still set from up there to be NZ if no VIDC stuff necessary CMP r7, #0 Pull "r2-r4,r7-r11, pc", NE ; if no VIDC stuff required, exit (NB V=0 from CMP) ; mjs Kernel/HAL split ; pushed video controller info is now hardware independent, it is a VIDCList type 3 TEQ R3, #0 ; if no module claimed service MOVEQ R2, R11 ; then use provided mode BEQ %FT62 59 ADD R14, R9, #wkwordsize ; R14 -> space for VIDCList3 MOV R10, #VIDCList3Size ; its a VIDCList3, R10 is max room we have 60 LDR R8, [R3], #4 ; copy list SUBS R10, R10, #4 MOVEQ R8, #-1 ; emergency terminate (source list too long) STR R8, [R14], #4 CMP R8, #-1 BNE %BT60 CLRV Pull "R2-R4,R7-R11, PC" ; done 62 ; arrive here if service not claimed, R2 = provided mode number BL ReadMonitorType ; get monitor type in R3 CMP R3, #NumMonitorTypes ; monitor type must be in range CMPCC R2, #NumModes ; and mode must be in range MOVCC R11, #NumModes MLACC R11, R3, R11, R2 ; then form monitortype*numberofmodes + modenumber MOVCS R11, #0 ; if illegal then use mode 0 monitortype 0 64 ADRL R14, BigVIDCTable ; point to big table LDR R11, [R14, R11, LSL #2] ; and load offset CMP R11, #-1 ; if table offset is valid ADDCC R3, R14, R11 ; then add to table address (R3 -> VIDCList3 from table) BCC %BT59 ; copy it and exit MOV R11, #0 ; desperate again, use mode 0 monitortype 0 (this had better have valid entry) B %BT64 ; ***************************************************************************** ; ; GenerateModeSelectorVars - Work out mode variables from mode selector ; or new format sprite mode word ; ; Note: the algorithms used to generate these variables are duplicated in ; s.vdu.vduswis in the OS_ReadModeVariable code. ; in: r2 = new format sprite word or pointer to mode selector ; r9 -> stack frame to store vars in ; ; out: If valid then ; V=0 ; r0 preserved ; else ; V=1 ; r0 -> error ; endif ; All other registers preserved ; GenerateModeSelectorVars Entry "r0,r1,r3-r8,r10-r12" ASSERT ModeSelector_Flags = 0 ASSERT ModeSelector_XRes = 4 ASSERT ModeSelector_YRes = 8 ASSERT ModeSelector_PixelDepth = 12 TST r2, #1 ; is it a new format sprite mode word? BNE %FT50 ; [yes, so skip] MOV r0, r2 BL ValidateModeSelector BVS %FT95 ; invalid - return error LDMIB r2, {r4-r6} ; r4 = xres; r5 = yres; r6 = pixdepth STR r6, [r9, #wkLog2BPC] ; log2bpc = log2bpp = pixdepth STR r6, [r9, #wkLog2BPP] ADR lr, NColourTable LDR lr, [lr, r6, LSL #2] ; load NColour value STR lr, [r9, #wkNColour] ADR lr, PalIndexTable LDRB lr, [lr, r6] STR lr, [r9, #wkPalIndex] ADR lr, ECFIndexTable LDRB lr, [lr, r6] STR lr, [r9, #wkECFIndex] MOV lr, #0 STR lr, [r9, #wkYShftFactor] ; yshftfactor = 0 (obsolete) STR lr, [r9, #wkModeFlags] ; modeflags = 0 [ RogerEXEY ; TMD 09-Dec-93 ; New algorithms for xeig, yeig from Roger: ; xeig = 1: yeig = 1 ; if yres> 3) -1 STR r7, [r9, #wkScrRCol] RSB r7, lr, r5, LSR #3 ; scrbrow = (yres >> 3) -1 STR r7, [r9, #wkScrBRow] SUB r7, r4, #1 STR r7, [r9, #wkXWindLimit] ; xwindlimit = xres-1 SUB r7, r5, #1 STR r7, [r9, #wkYWindLimit] ; ywindlimit = yres-1 MOV r7, r4, LSL r6 ; r7 = xres << pixdepth MOV lr, r7, LSR #3 STR lr, [r9, #wkLineLength] ; linelen = (xres << pixdepth) >> 3 MUL r7, r5, r7 ; r7 = (xres * yres) << pixdepth MOV lr, r7, LSR #3 STR lr, [r9, #wkScreenSize] ; screensize = ((xres * yres) << pixdepth) >> 3 ADD r4, r2, #ModeSelector_ModeVars ; now do pairs of mode variables BL ProcessModeVarPairs CLRV EXIT ; store info for new format sprite word in stack frame 50 MOV r0, #0 STR r0, [r9, #wkYShftFactor] ; yshftfactor = 0 STR r0, [r9, #wkModeFlags] ; modeflags = 0 MOV r0, r2, LSR #27 ; get type CMP r0, #SpriteType_MAX ; check for legality - NB type 0 is illegal because r2>=&100 MOVCS r0, #SpriteType_Substitute ; substitute if unknown ADRL lr, NSM_bpptable-4 LDR r0, [lr, r0, LSL #2] ; get the bpp from table STR r0, [r9, #wkLog2BPC] STR r0, [r9, #wkLog2BPP] ADR r1, NColourTable LDR r1, [r1, r0, LSL #2] STR r1, [r9, #wkNColour] ADR r1, PalIndexTable LDRB r1, [r1, r0] STR r1, [r9, #wkPalIndex] ADR r1, ECFIndexTable LDRB r1, [r1, r0] STR r1, [r9, #wkECFIndex] MOV r1, r2, LSL #(31-13) MOV r1, r1, LSR #(31-13)+1 ; extract xdpi (bits 1..13) TEQ r1, #180 ; 180 => xeig=0 MOVEQ r1, #0 BEQ %FT70 TEQ r1, #22 ; 22/23 => xeig=3 TEQNE r1, #23 MOVEQ r1, #3 BEQ %FT70 TEQ r1, #(45 :SHL: 2), 2 ; check if 45 (EQ,CC if so) CMPNE r1, #90 ; or 90 (EQ,CS if so) BNE %FT80 MOVCC r1, #2 ; 45 => xeig=2 MOVCS r1, #1 ; 90 => xeig=1 70 STR r1, [r9, #wkXEigFactor] MOV r1, r2, LSL #(31-26) MOV r1, r1, LSR #(31-26)+14 ; extract ydpi (bits 14..26) TEQ r1, #180 ; 180 => yeig=0 MOVEQ r1, #0 BEQ %FT71 TEQ r1, #22 ; 22/23 => yeig=3 TEQNE r1, #23 MOVEQ r1, #3 BEQ %FT71 TEQ r1, #(45 :SHL: 2), 2 ; check if 45 (EQ,CC if so) CMPNE r1, #90 ; or 90 (EQ,CS if so) BNE %FT80 MOVCC r1, #2 ; 45 => yeig=2 MOVCS r1, #1 ; 90 => yeig=1 71 STR r1, [r9, #wkYEigFactor] CLRV EXIT 80 ADR r0, ErrorBlock_Sprite_BadDPI 90 [ International BL TranslateError ] 95 STR r0, [sp] ; update saved r0 SETV ; indicate error EXIT NColourTable & NColour_0, NColour_1, NColour_2 & NColour_3, NColour_4, NColour_5 PalIndexTable = 0, 1, 2, 3, 6, 7 ALIGN ; makes ECFIndexTable more accessible ECFIndexTable = 4, 2, 3, 5, 5, 5 ALIGN MakeErrorBlock BadPixelDepth MakeErrorBlock Sprite_BadDPI ; ***************************************************************************** ; ; ValidateModeSelector - Check a mode selector is valid ; ; in: r0 -> mode selector ; ; out: If OK, then ; V=0 ; All registers preserved ; else ; V=1 ; r0 -> error ; All other registers preserved ; endif ; ValidateModeSelector Entry LDR lr, [r0, #ModeSelector_Flags] AND lr, lr, #ModeSelectorFlags_FormatMask TEQ lr, #ModeSelectorFlags_ValidFormat ADRNE r0, ErrorBlock_BadMSFlags BNE %FT90 LDR lr, [r0, #ModeSelector_PixelDepth] CMP lr, #6 ADRCS r0, ErrorBlock_BadPixelDepth BCS %FT90 CLRV EXIT 90 [ International BL TranslateError ] SETV EXIT MakeErrorBlock BadMSFlags ; ***************************************************************************** ; ; ProcessModeVarPairs - Modify stacked variable info from ; mode variable (index, value) pairs ; ; Internal routine used to do Service_ModeExtension workspace lists and ; mode selectors ; ; in: r4 -> first pair (may be none) ; r9 -> stack frame ; ; out: All registers preserved ProcessModeVarPairs Entry "r4, r8, r10" ADRL r14, RMVTab 10 LDR r10, [r4], #4 ; get next entry in ws table CMP r10, #-1 EXIT EQ ; no more to do CMP r10, #(SWIRVVTabModeEnd-SWIRVVTab) ; is it a mode variable ? BCS %BT10 ; no, then ignore LDRB r10, [r14, r10] ; load index out of RMVTab MOVS r10, r10, LSR #1 ; shift byte/word flag into carry LDR r8, [r4], #4 ; load value STRCCB r8, [r9, r10] ; either store byte STRCS r8, [r9, r10] ; or store word B %BT10 ; ***************************************************************************** ; ; OfferModeExtension - Issue mode extension service ; ; in: R2 = mode specifier ; ; out: EQ => service claimed, R3 -> VIDC list, R4 -> workspace list ; NE => service not claimed, R3,R4 preserved ; All other registers preserved ; OfferModeExtensionAnyMonitor ROUT MOV r3, #-1 OfferModeExtension ROUT Push "r1,r2,r4,r5,r14" ; TMD 10-Jan-94 - added code here to check for erroneous passing in of a sprite mode word. ; This prevents data aborts when modules try to index off a bad address. ; ; We could have done OS_ValidateAddress, but that would be rather slow, and mode selectors ; are of indeterminate length. ; ; If we detect one of these, we pretend the service wasn't claimed. Hopefully this should ; ensure that the mode change returns an error. ; Fixes bug MED-00483. BICS r14, r2, #&FF ; NE if not a mode number TSTNE r2, #3 ; NE if not a mode number, but invalid mode selector Pull "r1,r2,r4,r5,pc", NE ; so exit NE, pretending that service not claimed GetBandwidthAndSize r4, r5 MOV r1, #Service_ModeExtension IssueService TEQ r1, #0 ; if service claimed CMPNE r3, #-1 ; or if "don't care" monitortype BEQ %FT90 ; then we can't do any more CMP r2, #&100 ; if it's a mode selector BCS %FT90 ; then we can't help them either BranchIfNotKnownMode r2, %FA90 ; if we don't recognise screen mode number we can't either ; it is a known numbered mode, so create a mode selector on the stack that we can pass to service Push "r6,r7" SUB sp, sp, #ModeSelector_ModeVars+4 ; make room for block including terminator MOV r6, #ModeSelectorFlags_ValidFormat STR r6, [sp, #ModeSelector_Flags] ADRL r6, FrameRateTable LDRB r6, [r6, r2] STR r6, [sp, #ModeSelector_FrameRate] ADRL r6, Vwstab LDR r14, [r6, r2, LSL #2] ADD r6, r6, r14 LDR r14, [r6, #wkLog2BPP] STR r14, [sp, #ModeSelector_PixelDepth] ; pixdepth = log2bpp LDR r7, [r6, #wkLog2BPC] SUB r14, r7, r14 ; r14 = log2bpc-log2bpp LDR r7, [r6, #wkXWindLimit] ADD r7, r7, #1 MOV r7, r7, LSL r14 STR r7, [sp, #ModeSelector_XRes] LDR r7, [r6, #wkYWindLimit] ADD r7, r7, #1 STR r7, [sp, #ModeSelector_YRes] MOV r7, #-1 STR r7, [sp, #ModeSelector_ModeVars] MOV r2, sp IssueService TEQ r1, #0 BEQ %FT10 ; service was claimed ; not claimed, so try again with -1 as frame rate MOV r7, #-1 STR r7, [sp, #ModeSelector_FrameRate] IssueService TEQ r1, #0 10 ADD sp, sp, #ModeSelector_ModeVars+4 ; junk mode selector Pull "r6, r7" 90 CMP r2, #&100 ; if we started or ended up with a mode selector MOVCS r4, #0 ; then return r4 = 0 (if claimed) TEQ r1, #0 STREQ r4, [sp, #2*4] ; if service claimed, then return r4 from service, else preserve it Pull "r1,r2,r4,r5,pc" [ STB svc_PortMan TEQ R0, #0 ; PortManager starting MOVNE PC, LR [ {TRUE} ;;;mjsHAL - may need sorting/HAL split ;;; for now, switched out coz kernel doesn't have VIDCControlSoftCopy any more! ;;; ! 0, "mjsHAL - svc_PortMan currently broken by kernel/HAL split" MOV PC, LR | ; When PortManager restarts, we need to put TV_Mode back. PortMan defaults to ; output high, but we don't know polarity of bit, so must set either way. Entry "r0-r1, WsPtr" VDWS WsPtr LDR R0, [WsPtr, #VIDCControlSoftCopy] ; get saved VIDC control register AND R0, R0, #CR_VCLK :OR: CR_HCLK :OR: CR_RCLK TEQ R0, #CR_HCLK ; are we using HCLK? MOVNE R0, #1 ; no: TV_Mode = 0 MOVEQ R0, #3 ; yes: TV_Mode = 1 addr R1, TV_Mode_string SWI XPortMan_AccessBit EXIT ] ] ; ***************************************************************************** ; ; ETB - Redefine character ; === & other stuff ; ; VDU 23,0,r,v,0| Talk to 6845 ! ; VDU 23,1,n,m,r,g,b| Program cursor ; VDU 23,2,n1..n8 Ecf pattern 1 ; VDU 23,3,n1..n8 Ecf pattern 2 ; VDU 23,4,n1..n8 Ecf pattern 3 ; VDU 23,5,n1..n8 Ecf pattern 4 ; VDU 23,6,n1..n8 Dot dash line style ; VDU 23,7,m,d,z| Scroll window directly ; VDU 23,8,t1,t2,x1,y1,x2,y2| Clear block ; VDU 23,9,n| Set 1st flash time ; VDU 23,10,n| Set 2nd flash time ; VDU 23,11| Default Ecf patterns ; VDU 23,12,n1..n8 Ecf pattern 1 (simple setting) ; VDU 23,13,n1..n8 Ecf pattern 2 (simple setting) ; VDU 23,14,n1..n8 Ecf pattern 3 (simple setting) ; VDU 23,15,n1..n8 Ecf pattern 4 (simple setting) ; VDU 23,16,x,y| Cursor movement control ; VDU 23,17,c,t| Set colour tints, ECF info, char sizes ; ; ETB LDRB R0, [WsPtr, #QQ+0] CMP R0, #32 ; defining a normal character ? BCS DefineChar LDR R2, [PC, R0, LSL #2] ADD PC, PC, R2 ; enters routine with R0 => byte after 23 ETBtab & Vdu23_0-ETBtab-4 & Vdu23_1-ETBtab-4 & ComplexEcfPattern-ETBtab-4 & ComplexEcfPattern-ETBtab-4 & ComplexEcfPattern-ETBtab-4 & ComplexEcfPattern-ETBtab-4 & LineStyle-ETBtab-4 & Vdu23_7-ETBtab-4 & Vdu23_8-ETBtab-4 & Vdu23_9-ETBtab-4 & Vdu23_10-ETBtab-4 & DefaultEcfPattern-ETBtab-4 & SimpleEcfPattern-ETBtab-4 & SimpleEcfPattern-ETBtab-4 & SimpleEcfPattern-ETBtab-4 & SimpleEcfPattern-ETBtab-4 & Vdu23_16-ETBtab-4 & Vdu23_17-ETBtab-4 & Vdu23_18-ETBtab-4 & Vdu23_19-ETBtab-4 & Vdu23_20-ETBtab-4 & Vdu23_21-ETBtab-4 & Vdu23_22-ETBtab-4 & Vdu23_23-ETBtab-4 & Vdu23_24-ETBtab-4 & Vdu23_25-ETBtab-4 & Vdu23_26-ETBtab-4 & Vdu23_27-ETBtab-4 & Vdu23_28-ETBtab-4 & Vdu23_29-ETBtab-4 & Vdu23_30-ETBtab-4 & Vdu23_31-ETBtab-4 ; NB All other labels for Vdu23 are in TMD files so I don't have to pester RCM ;Vdu23_18 ; Assigned to Teletext operations Vdu23_19 Vdu23_20 Vdu23_21 Vdu23_22 Vdu23_23 Vdu23_24 Vdu23_25 Vdu23_26 ; Vdu23_27 ; Assigned to Richard (well some of it, anyway) Vdu23_28 Vdu23_29 Vdu23_30 Vdu23_31 UnknownVdu23 ; R0 already contains first parameter to VDU23 MOV R10, #UKVDU23V Push "WsPtr, R14" ; calling a vector corrupts R12 BL VduQQVec ; so we have to preserve it Pull "WsPtr, PC", VC ; before we return to PostWrchCursor ; error in UKVDU23 vector, so go to vdu error exit Pull "WsPtr, R14" B VduBadExit ; ***************************************************************************** ; ; DLE ; CLG - Clear graphics window ; === ; ; On exit, R0..R11 corrupt ; DLE CLG ROUT GraphicsMode R0 MOVNE PC,LR ; check for graphics mode (changed by DDV 15/9/92) ADD R0, WsPtr, #BgEcfOraEor ; point at background colour STR R0, [WsPtr, #GColAdr] ADD R11, WsPtr, #GWLCol ; load window coordinates into LDMIA R11, {R0-R3} ; RectFill's parameter space LDR R6, [WsPtr, #CursorFlags] ; if clip box is not enabled TST R6, #ClipBoxEnableBit ; then goto code directly BEQ RectFillA Push R14 ; else merge graphics window (in R0-R3) BL MergeClipBox ; with clip box Pull R14 B RectFillA ; ***************************************************************************** ; ; DC2 ; GCol - Set Graphics action and colour ; ==== ; ; On entry, R0 holds GCol action ; R1 holds GCol colour, 0..127 means program fg ; 128..255 means program bg ; ; In 256-colour modes, the extra colours are accessed via TINT ; DC2 GCol ROUT LDRB R0, [WsPtr, #QQ+0] ; GCol action, eg store, eor etc. LDRB R1, [WsPtr, #QQ+1] ; GCol colour LDR R2, [WsPtr, #NColour] ; number of colours-1 TST R1, #&80 AND R1, R1, R2 ; limit colour to range available STREQ R0, [WsPtr, #GPLFMD] ; GCOL(a,0..127) is foreground STREQ R1, [WsPtr, #GFCOL] STRNE R0, [WsPtr, #GPLBMD] ; GCOL(a,128..255) is background STRNE R1, [WsPtr, #GBCOL] ; drop into SetColour to.... ; SetColour - Setup FgEcf & BgEcf, used after GCOL or setting of Ecfs ; ========= or default palette (does a gcol). SetColour Push R14 LDR R1, [WsPtr, #GPLFMD] ; setup FgEcf, maybe solid or Ecf LDR R0, [WsPtr, #GFCOL] ADD R2, WsPtr, #FgEcf LDR R3, [WsPtr, #GFTint] ; tint only used in 256 colour modes ADD R4, WsPtr, #FgPattern ; used if OS_SetColour call BL SetCol10 LDR R1, [WsPtr, #GPLBMD] ; and BgEcf LDR R0, [WsPtr, #GBCOL] ADD R2, WsPtr, #BgEcf LDR R3, [WsPtr, #GBTint] ADD R4, WsPtr, #BgPattern ; used if OS_SetColour call BL SetCol10 ADD R0, WsPtr, #FgEcf ; setup FgEcfOraEor ADD R1, WsPtr, #BgEcf ADD R2, WsPtr, #FgEcfOraEor LDR R3, [WsPtr, #GPLFMD] BL SetCol60 ADD R0, WsPtr, #BgEcf ; and BgEcfOraEor ADD R1, WsPtr, #FgEcf ADD R2, WsPtr, #BgEcfOraEor LDR R3, [WsPtr, #GPLBMD] BL SetCol60 ADD R0, WsPtr, #BgEcf ; and BgEcfStore ADD R1, WsPtr, #FgEcf ADD R2, WsPtr, #BgEcfStore MOV R3, #0 BL SetCol60 Pull PC ; SetCol10 - Internal to SetColour ; Build up an Ecf, given action and colour numbers ; ; On entry, R0 holds colour (0..255, where 127..255 means 0..127) ; R1 holds action (may indicate ecf) ; R2 holds address to write data (FgEcf or BgEcf) ; R3 holds tint information (only used in 256 colour modes) ; R4 holds pointer to suitable pattern table for OS_SetColour call SetCol10 ROUT ANDS R1, R1, #&F0 ; actions >=16 mean Ecf BNE SetCol30 Push R14 LDR R4, [WsPtr, #NColour] ; else use given colour number AND R0, R0, R4 AND R0, R0, #63 ; another bodge in the house of bodges TST R4, #&F0 ; if 256 colour (ie 8bpp) BLNE AddTintToColour ; then combine tint with colour ; R0 contains colour number for current mode LDR LR, [WsPtr, #BitsPerPix] 10 TEQ LR, #32 ORRNE R0, R0, R0, LSL LR ; replicate again MOVNE LR, LR, LSL #1 ; doubling the shift for each pass BNE %BT10 STR R0, [R2] STR R0, [R2, #4] STR R0, [R2, #8] STR R0, [R2, #12] STR R0, [R2, #16] STR R0, [R2, #20] STR R0, [R2, #24] STR R0, [R2, #28] Pull "PC" ; R1 = ecf number as 16,32,48,64,80,96 ; R2 -> destination ; R4 -> pattern block (if R1 =96!) SetCol30 CMP R1, #96 ; special internal plot? MOVCS R0, R4 ; yes, so point at pattern to be copied MOVCS R3, #1 ; col step =1 MOVCS R4, #0 ; row step =0 (already there!) BCS SetCol35 CMP R1, #80 ; 80 => giant ecf (>80 does same) ADDCS R0, WsPtr, #Ecf1 ; then point at ecf0 MOVCS R3, #8 ; col step=8 MOVCS R4, #(1-8*4) ; row step, back to 1st ecf on 1 byte BCS SetCol35 ADD R0, WsPtr, #(Ecf1-8) ADD R0, R0, R1, LSR #1 ; else point R0 at Ecf1,2,3 or 4 LDR R4, [WsPtr, #BitsPerPix] ; if BitsPerPix <> 'fudged' BitsPerPix LDR R5, [WsPtr, #BytesPerChar] TEQ R4, R5 BNE SetCol52 ; then double up the pixels ; else its a normal Ecf MOV R3, #0 ; col step=0, same byte each coloum MOV R4, #1 ; row step=1 SetCol35 MOV R5, #8 ; do 8 rows SetCol40 MOV R6, #4 ; of 4 columns SetCol50 LDRB R7, [R0], R3 ; read from source & move by col step STRB R7, [R2], #1 ; write to dest, update dest pointer SUBS R6, R6, #1 BNE SetCol50 ADD R0, R0, R4 ; step source pointer to next row SUBS R5, R5, #1 BNE SetCol40 MOV PC, R14 ; Double up the pixels for Mode2 etc ; ; R0 points to Ecf(n) ; R2 points to destination ; ; Uses ; ; R3 - NColour used as PixMsk ; R4 - BitsPerPix ; R5 - BytesPerChar (unused) ; R6 - byte cntr 7..0 ; R7 - source byte ; R8 - ExtrtShftFact ; R9 - InsrtShftFact ; R10 - result word ; R11 - temp SetCol52 LDR R3, [WsPtr, #NColour] ; mask for extracting pixels from ecf TST R3, #&F0 ; ** if 256 colour mode MOVNE R3, #&FF ; ** then use &FF (TMD 25-Mar-87) LDR R4, [WsPtr, #BitsPerPix] MOV R6, #7 ; 8 bytes/rows to do SetCol54 LDRB R7, [R0, R6] ; get byte of Ecf(n) RSB R8, R4, #8 RSB R9, R4, #32 MOV R10, #0 ; clear result word SetCol57 AND R11, R3, R7, ROR R8 ; extract 1 pixel from Ecf ORR R10, R10, R11, LSL R9 ; double it into result word SUB R9, R9, R4 ORR R10, R10, R11, LSL R9 SUB R8, R8, R4 AND R8, R8, #7 SUBS R9, R9, R4 BGE SetCol57 ; process next pixel in result word STR R10, [R2, R6, LSL #2] ; write expanded word to (Fg/Bg)Ecf SUBS R6, R6, #1 BGE SetCol54 ; process next row/byte MOV PC, R14 ; Tables of full colours for 2,4 & 16 colour modes (256 colour modes ; use colour number directly). ; ; N.B. these are tables of bytes TBFullCol = &FF ; not used - remove sometime ; (DJS comment: don't bother!) = &00, &FF ; 2 colour mode = &00, &55, &AA, &FF ; 4 colour mode = &FF, &FF, &FF, &FF ; not used but cannot be removed = &FF, &FF, &FF, &FF ; (8 colour mode!) = &00, &11, &22, &33 ; 16 colour mode = &44, &55, &66, &77 = &88, &99, &AA, &BB = &CC, &DD, &EE, &FF ALIGN ; ***************************************************************************** ; ; SetCol60 - Build up an ecf, ORed and EORed appropriate to GCOL action ; ; Internal to SetColour ; ; in: R0 -> ecf colour (FgEcf/BgEcf) ; R1 -> transparent colour (BgEcf/FgEcf) ; R2 -> destination FgEcfOraEor/BgEcfOraEor/BgEcfStore ; R3 = gcol action number (may indicate ecf) ; ; uses: R4 = index into ecf (7..0) ; R5 = ecf colour word ; R6 = transparency mask, set to &FFFFFFFF for NO transparency ; R7 -> zgoo..zgee for gcol action ; R8 = mask for pixel under examination ; R9 = shift factor to move mask to next pixel (BytesPerChar) ; R10, R11 temporary ; SetCol60 ROUT MOV R4, #7 ; 7..0 words to process AND R3, R3, #&F ; extract action bits AND R11, R3, #7 ; 0-7 Store etc ; 8-15 ditto with transparency MOV R11, R11, LSL #2 ; 4 bits for each LDR R7, =TBscrmasks MOV R7, R7, ROR R11 ; relevant bits are in top 4 AND R7, R7, #&F0000000 ; isolate these bits (N,Z,C,V) SetCol70 LDR R5, [R0, R4, LSL #2] ; get ecf word TST R3, #8 ; if action < 8 MOVEQ R6, #&FFFFFFFF BEQ SetCol90 ; then not transparent ; else build transparency mask LDR R8, [WsPtr, #RAMMaskTb] ; fetch mask for leftmost pixel LDR R9, [WsPtr, #BytesPerChar] ; shift factor for next pixel LDR R6, [R1, R4, LSL #2] ; get 'transparent' colour EOR R6, R6, R5 SetCol80 TST R6, R8 ; if pixels the same, ; then it's transparent ORRNE R6, R6, R8 ; else set mask to plot it MOVS R8, R8, LSL R9 BNE SetCol80 SetCol90 MSR CPSR_f, R7 ; put bits into N, Z, C, V ; OO,EO,OE,EE MOVCC R10, R5 ; if ORing with &00000000 MOVCS R10, #&FFFFFFFF ; if ORing with &FFFFFFFF MVNVS R10, R10 ; if EORing with &FFFFFFFF ; MOVPL R5, R5 ; if ORing with &00000000 MOVMI R5, #&FFFFFFFF ; if ORing with &FFFFFFFF MVNEQ R5, R5 ; if EORing with &FFFFFFFF ; now R5 = OR mask, R10 = EOR mask AND R5, R5, R6 ; then clear 'transparent' AND R10, R10, R6 ; pixels LDR R11, [WsPtr, #ECFShift] MOV R5, R5, ROR R11 ; rotate OR and EOR masks MOV R10, R10, ROR R11 ; to correct for ECF X origin LDR R11, [WsPtr, #ECFYOffset] ADD R11, R11, R4 ; add on ECF Y offset AND R11, R11, #7 ; and wrap ADD R11, R2, R11, LSL #3 STMIA R11, {R5, R10} ; write to (Fg/Bg)EcfOraEor SUBS R4, R4, #1 BCS SetCol70 MOV PC, R14 ; ***************************************************************************** ; ; AddTintToColour - in 256 colour modes ; ; Internal to SetColour (derived from TMD's FudgeColour) ; ; in: R0 = colour (0..255), where 6 LSBits are used ; R3 = tint ; ; out: R0 holds colour byte with tint added ; R1-R3 preserved ; R4 undefined ; PSR preserved ; ! 0,"WARNING: AddTintToColour returns > 8 bit values now, check ECF handling!" AddTintToColour Push "R3,LR" AND R0, R0, #63 ; extract suitable set of bits AND R3, R3, #192 ; and another set ORR R0, R0, R3 BL ConvertGCOLToColourNumber Pull "R3,PC" ; ***************************************************************************** ; ; CAN - Define graphics window ; ; External routine ; ; in: The window is given by bytes in the vdu queue, as follows :- ; QQ+0 = leftLo ; QQ+1 = leftHi ; QQ+2 = bottomLo ; QQ+3 = bottomHi ; QQ+4 = rightLo ; QQ+5 = rightHi ; QQ+6 = topLo ; QQ+7 = topHi ; ; These are relative to the current graphics origin. ; The resultant window must obey the following rules :- ; RCol >= LCol ; TRow >= BRow ; LCol >= 0 ; BRow >= 0 ; YWindLimit >= TRow ; XWindLimit >= RCol ; CAN ROUT Push R14 ADD R8, WsPtr, #GCsX ; save ECursor away, cos EIG changes it LDMIA R8, {R6, R7} ; and we don't want it to! ; *****Change made by DJS ; Original code was: ; LDRB R0, [WsPtr, #QQ+5] ; rightHi ; LDRB R1, [WsPtr, #QQ+4] ; rightLo ; PackXtnd R0,R0,R1 ; pack 2 bytes and sign extend ; ; LDRB R1, [WsPtr, #QQ+7] ; topHi ; LDRB R2, [WsPtr, #QQ+6] ; topLo ; PackXtnd R1,R1,R2 ; pack 2 bytes and sign extend LoadCoordPair R0, R1, WsPtr, QQ+4 ;Get top right point ; *****End of change made by DJS MOV R2, #&FF ; convert external-to-internal BL EIG ; as absolute coordinates MOV R4, R0 ; move internal version of top right MOV R5, R1 ; out of harm's way ; *****Change made by DJS ; Original code was: ; LDRB R0, [WsPtr, #QQ+1] ; leftHi ; LDRB R1, [WsPtr, #QQ+0] ; leftLo ; PackXtnd R0,R0,R1 ; pack 2 bytes and sign extend ; ; LDRB R1, [WsPtr, #QQ+3] ; bottomHi ; LDRB R2, [WsPtr, #QQ+2] ; bottomLo ; PackXtnd R1,R1,R2 ; pack 2 bytes and sign extend LoadCoordPair R0, R1, WsPtr, QQ+0 ;Get bottom left point ; *****End of change made by DJS MOV R2, #&FF ; convert external-to-internal BL EIG ; as absolute coordinates ; For a valid window, the following must be true CMP R4, R0 ; RCol >= LCol CMPGE R5, R1 ; TRow >= BRow CMPGE R0, #0 ; LCol >= 0 CMPGE R1, #0 ; BRow >= 0 LDRGE R2, [WsPtr, #YWindLimit] ; YWindLimit >= TRow CMPGE R2, R5 LDRGE R2, [WsPtr, #XWindLimit] ; XWindLimit >= RCol CMPGE R2, R4 ADD R2, WsPtr, #GWLCol STMGEIA R2, {R0,R1, R4,R5} ; if the new window is OK, update it STMIA R8, {R6, R7} ; restore ECursor (EIG corrupted it) Pull PC ; ***************************************************************************** ; ; DefaultWindows - Restore default windows ; ; External routine, and called by mode change + switch output to sprite ; ; Set default text and graphics windows, ; Clear graphics origin and both cursors ; DefaultWindows ROUT Push R14 MOV R0, #0 MOV R1, #0 ADD R4, WsPtr, #GWLCol ASSERT YWindLimit = XWindLimit +4 ADD R2, WsPtr, #XWindLimit LDMIA R2, {R2,R3} ; R2 := XWindLimit; R3 := YWindLimit STMIA R4, {R0-R3} ; zero GWLCol, GWBRow ; GWRCol:=XWindLimit; GWTRow:=YWindLimit MOV R3, #0 LDR R1, [WsPtr, #ScrBRow] LDR R2, [WsPtr, #ScrRCol] ADD R4, WsPtr, #TWLCol ; zero TWLCol, TWTRow STMIA R4!, {R0-R3} ; TWRCol := ScrRCol; TWBRow := ScrBRow MOV R1, #0 MOV R2, #0 STMIA R4!, {R0-R3} ; zero OrgX, OrgY, GCsX, GCsY STMIA R4!, {R0-R3} ; zero OlderCsX, OlderCsY, OldCsX, OldCsY STMIA R4!, {R0-R3} ; zero GCsIX, GCsIY, NewPtX, NewPtY LDR R0, [WsPtr, #VduSprite] TEQ R0, #0 LDR R0, [WsPtr, #VduStatus] ; if not outputting to sprite BICEQ R0, R0, #Windowing ; then indicate no text window ORRNE R0, R0, #Windowing ; else indicate is text window STR R0, [WsPtr, #VduStatus] BL HomeVdu4 ; home TEXT cursor ; (even in VDU 5 mode) Pull PC ; ***************************************************************************** ; ; GS - Define graphics origin ; ; External routine ; ; in: The origin is given by bytes in the vdu queue, as follows :- ; QQ+0 = xLo ; QQ+1 = xHi ; QQ+2 = yLo ; QQ+3 = yHi ; ; The coordinates are in external 16 bit form. ; This does not move the windows, but does move the graphics cursor ; GS ROUT Push R14 ; *****Change made by DJS ; Original code was: ; LDRB R0, [WsPtr, #QQ+1] ; xHi ; LDRB R1, [WsPtr, #QQ+0] ; xLo ; PackXtnd R0,R0,R1 ; pack 2 bytes and sign extend ; LDRB R1, [WsPtr, #QQ+3] ; yHi ; LDRB R2, [WsPtr, #QQ+2] ; yLo ; PackXtnd R1,R1,R2 ; pack 2 bytes and sign extend LoadCoordPair R0, R1, WsPtr, QQ+0 ; *****End of change made by DJS ADD R2, WsPtr, #OrgX STMIA R2, {R0,R1} ; write the new origin BL IEG ; update external cursor Pull PC LTORG ;------------------------------------------------------------------------------ ; ; OS_SetColour implementation ; ------------ ; ; This call can be used to change the current GCOL/pattern table used for ; plotting with the VDU primitives. ; ; in R0 = flags / logical operation ; bit 0-3 = logical operation ; bit 4 = set => bg, else fg flag ; bit 5 = set => pattern block supplied ; bit 6 = set => set text colour ; bit 7 = set => read colour ; R1 = colour number / -> pattern block to use ; out - ; ;------------------------------------------------------------------------------ setcol_LogicOpMask * &0F setcol_FgBgFlag * &10 setcol_PatternFlag * &20 setcol_TextColour * &40 setcol_ReadFlag * &80 ASSERT WsPtr > 9 SWISetColour ROUT Push "R0-R9,WsPtr,R14" VDWS WsPtr ; Obtain base of the VDU driver workspace TST R0, #setcol_ReadFlag ; Are we reading? BNE %FT75 TST R0, #setcol_TextColour ; Are we changing the text colour? BNE %FT70 AND R2, R0, #setcol_LogicOpMask ; Get the logical operation ORR R2, R2, #&60 ; Mark as being a special kind of pattern TST R0, #setcol_FgBgFlag STREQ R2, [WsPtr, #GPLFMD] ; Store the relevant logical operation away for fg/bg STRNE R2, [WsPtr, #GPLBMD] ADDEQ R3, WsPtr, #FgPattern ADDNE R3, WsPtr, #BgPattern ; Setup the pointer to a store for the pattern TST R0, #setcol_PatternFlag ; Did the caller specify a pattern block? BNE %FT50 ; Yes so don't try to expand colour value to pattern MOV R2, #1 LDR R4, [WsPtr, #Log2BPP] ; Get the Log2 depth of the mode MOV R4, R2, ASL R4 ; R4 = bits per pixel RSB R2, R2, R2, LSL R4 ; Get a mask to extract only meaningful bits from word AND R1, R1, R2 ; Extract bits suitable for this depth of mode 10 TEQ R4, #32 ; Do we need to do any more replication ORRNE R1, R1, R1, LSL R4 ; Yes so or word with itself shifted MOVNE R4, R4, LSL #1 ; and double amount to shift next time BNE %BT10 MOV R2, #8 20 STR R1, [R3], #4 ; now copy word 8 times into block SUBS R2, R2, #1 BNE %BT20 B %FT60 50 LDMIA R1,{R0,R2,R4-R9} STMIA R3,{R0,R2,R4-R9} ; Copy the pattern into the buffer (assumes word aligned) 60 BL SetColour ; And then setup the internal GCOL tables 65 Pull "R0-R9,WsPtr,R14" ExitSWIHandler 70 TST R0, #setcol_FgBgFlag ; Store the foreground or background colour? STREQ R1, [WsPtr, #TextFgColour] STRNE R1, [WsPtr, #TextBgColour] LDR R0, [WsPtr, #CursorFlags] ; Indicate the text colour needs re-computing! ORR R0, R0, #TEUpdate STR R0, [WsPtr, #CursorFlags] B %BT65 ; Leave gracefully .... 75 ; Reading the colour... TST R0, #setcol_TextColour BEQ %FT80 ; Reading text colour TST R0, #setcol_FgBgFlag LDREQ R1, [WsPtr, #TextFgColour] LDRNE R1, [WsPtr, #TextBgColour] BIC R0, R0, #setcol_PatternFlag :OR: setcol_ReadFlag 77 ; Standard exit for reading the colour STMIA SP, {R0,R1} B %BT65 80 ; Reading graphics colour TST R0, #setcol_FgBgFlag LDREQ R2, [WsPtr, #GPLFMD] ; Get the relevant logical operation for fg/bg LDRNE R2, [WsPtr, #GPLBMD] ; SetColour setting - copy block ADDEQ R3, WsPtr, #FgEcf ADDNE R3, WsPtr, #BgEcf ; Copy the pattern to the user's buffer LDMIA R3,{R0,R3,R4-R9} STMIA R1,{R0,R3,R4-R9} ; Construct a suitable reason code AND R0, R2, #setcol_LogicOpMask ORRNE R0, R0, #setcol_FgBgFlag ORR R0, R0, #setcol_PatternFlag B %BT77 END