; 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.VduDecl ; ARTHUR OPERATING SYSTEM - Vdu Drivers ; ======================= ; ; Vdu driver workspace and macro declarations ; ; Author R C Manby ; Date 5.9.86 ; GBLL ForceMark ; whether we force start of mark state ForceMark SETL {FALSE} ; of cursor on exit from WRCH GBLL RePlot ; Re-plot cursor after wrch RePlot SETL {TRUE} GBLL UseVLineOnSolidLines ; When TRUE VLine is assembled and used UseVLineOnSolidLines SETL {TRUE} ; to plot vertical solid lines ; ; Register usage ; ============== ; StkPtr RN 13 ;Restore on exit to keep BASIC happy!! Link RN 14 ; ; Manifest constants ; ================== ; [ VIDC_Type = "VIDC20" ; Registers VIDCPalAddress * &10000000 ; used in palette programming LCDOffsetRegister0 * &30000000 LCDOffsetRegister1 * &31000000 HorizCycle * &80000000 HorizSyncWidth * &81000000 HorizBorderStart * &82000000 HorizDisplayStart * &83000000 HorizDisplayEnd * &84000000 HorizBorderEnd * &85000000 HorizCursorStart * &86000000 ; used in pointer programming HorizInterlace * &87000000 VertiCycle * &90000000 VertiSyncWidth * &91000000 ; Needed to set up FSIZE register in IOMD VertiBorderStart * &92000000 ; First register affected by *TV VertiDisplayStart * &93000000 VertiDisplayEnd * &94000000 VertiBorderEnd * &95000000 VertiCursorStart * &96000000 VertiCursorEnd * &97000000 ; Last register affected by *TV VIDCExternal * &C0000000 VIDCFSyn * &D0000000 VIDCControl * &E0000000 VIDCDataControl * &F0000000 ; Pseudo-registers used to return additional information to kernel PseudoRegister_ClockSpeed * &FC000000 ; used to indicate real VIDC rclock speed PseudoRegister_DPMSState * &FD000000 ; used to return desired DPMS state [ ChrontelSupport PseudoRegister_PixelRate * &FE000000 ; used to indicate the required pixel rate ] ; Bits in VCSR, VCER CursorSinglePanel * 0 :SHL: 13 CursorTopPanel * 1 :SHL: 13 CursorBottomPanel * 1 :SHL: 14 CursorStraddle * 3 :SHL: 13 ; Bits in external register Ext_HSYNCbits * 3 :SHL: 16 Ext_InvertHSYNC * 1 :SHL: 16 Ext_CompHSYNC * 2 :SHL: 16 Ext_InvertCompHSYNC * 3 :SHL: 16 Ext_VSYNCbits * 3 :SHL: 18 Ext_InvertVSYNC * 1 :SHL: 18 Ext_CompVSYNC * 2 :SHL: 18 Ext_InvertCompVSYNC * 3 :SHL: 18 Ext_HiResMono * 1 :SHL: 14 Ext_LCDGrey * 1 :SHL: 13 Ext_DACsOn * 1 :SHL: 12 Ext_PedsOn * 7 :SHL: 8 Ext_PedsShift * 8 Ext_ERegShift * 4 Ext_ECKOn * 1 :SHL: 2 Ext_ERegBits * 3 :SHL: 0 Ext_ERegRed * 0 :SHL: 0 Ext_ERegGreen * 1 :SHL: 0 Ext_ERegBlue * 2 :SHL: 0 Ext_ERegExt * 3 :SHL: 0 ; use this for lowest power ; Bits in Frequency Synthesizer Register FSyn_VShift * 8 FSyn_RShift * 0 FSyn_ClearV * 1 :SHL: 15 FSyn_ForceLow * 1 :SHL: 14 FSyn_ClearR * 1 :SHL: 7 FSyn_ForceHigh * 1 :SHL: 6 FSyn_ResetValue * FSyn_ClearV :OR: FSyn_ClearR :OR: FSyn_ForceLow :OR: (63 :SHL: FSyn_RShift) :OR: (0 :SHL: FSyn_VShift) ; value to get PLL working properly ; Bits in Control Register CR_DualPanel * 1 :SHL: 13 CR_Interlace * 1 :SHL: 12 CR_FIFOLoadShift * 8 CR_LBPP0 * 0 :SHL: 5 CR_LBPP1 * 1 :SHL: 5 CR_LBPP2 * 2 :SHL: 5 CR_LBPP3 * 3 :SHL: 5 CR_LBPP4 * 4 :SHL: 5 CR_LBPP5 * 6 :SHL: 5 ; spot the gap! CR_PixelDivShift * 2 CR_VCLK * 0 :SHL: 0 CR_HCLK * 1 :SHL: 0 CR_RCLK * 2 :SHL: 0 ; Bits in Data Control Register DCR_VRAMOff * 0 :SHL: 18 DCR_VRAMDiv1 * 1 :SHL: 18 DCR_VRAMDiv2 * 2 :SHL: 18 DCR_VRAMDiv4 * 3 :SHL: 18 DCR_BusBits * 3 :SHL: 16 DCR_Bus31_0 * 1 :SHL: 16 DCR_Bus63_32 * 2 :SHL: 16 DCR_Bus63_0 * 3 :SHL: 16 DCR_HDis * 1 :SHL: 13 DCR_Sync * 1 :SHL: 12 DCR_HDWRShift * 0 | ; Registers ����������������������������������������������������������� HorizDisplayStart * &8C000000 ; used in mode change code HorizCursorStart * &98000000 ; used in pointer programming VertiBorderStart * &A8000000 ; First register affected by *TV VertiDisplayStart * &AC000000 VertiCursorStart * &B8000000 VertiCursorEnd * &BC000000 ; Last register affected by *TV SoundFrequency * &C0000000 VIDCControl * &E0000000 ; Bits in control register CR_Interlace * &40 ; 0 - no interlace, 64 - interlace CompSync * &80 ; Controls sync signal on CS/VS pin ; 0 - output vertical sync, 128 - composite sync. ; Other bits SupBit * &1000 ; Supremacy bit in palette ] PhysCursorStartAdr * CursorSoundPhysRAM ; Reason codes for generalised DAG interface - independent of MEMC type MEMCDAG_VInit * 0 MEMCDAG_VStart * 1 MEMCDAG_VEnd * 2 MEMCDAG_CInit * 3 MEMCDAG_MaxReason * 3 [ ModeSelectors ; OS_ScreenMode reason codes ScreenModeReason_SelectMode * 0 ScreenModeReason_ReturnMode * 1 ScreenModeReason_EnumerateModes * 2 ScreenModeReason_SelectMonitorType * 3 ScreenModeReason_Limit * 4 ; Mode selector format ^ 0 ModeSelector_Flags # 4 ; flags word ModeSelector_XRes # 4 ; x-resolution in pixels ModeSelector_YRes # 4 ; y-resolution in pixels ModeSelector_PixelDepth # 4 ; pixel depth (=Log2BPP) ModeSelector_FrameRate # 4 ; nominal frame rate (in Hz) ModeSelector_ModeVars # 0 ; start of pairs of (mode var index, value) ModeSelectorFlags_FormatMask * &FF ModeSelectorFlags_ValidFormat * 1 ModeSelector_MaxSize * ModeSelector_ModeVars+(NumModeVars * 8)+4 ; maximum size of a mode selector, with each mode variable overridden ; plus terminator on end ] ; ; Macro Definitions ; ================= ; ; ; Macro Sort - Sort two values into increasing order ; MACRO Sort $lo, $hi CMP $hi, $lo EORLT $lo, $lo, $hi EORLT $hi, $lo, $hi EORLT $lo, $lo, $hi MEND ; ; Macro SortT - Sort two values into increasing order using a temporary reg ; MACRO SortT $lo, $hi, $temp SUBS $temp, $hi, $lo MOVLT $hi, $lo ADDLT $lo, $lo, $temp MEND ; ; Macro CompSwap - Compare and sort a pair of coordinates into ; order of increasing Y ; If Y values equal, sort in order of decreasing X ; MACRO CompSwap $xl,$yl, $xh,$yh CMP $yh, $yl EORLT $yl, $yl, $yh EORLT $yh, $yl, $yh EORLT $yl, $yl, $yh CMPEQ $xl, $xh EORLT $xl, $xl, $xh EORLT $xh, $xl, $xh EORLT $xl, $xl, $xh MEND ; ; Macro CompSwapT - Compare and sort a pair of coordinates into ; order of increasing Y ; If Y values equal, sort in order of decreasing X ; Uses a temporary register ; MACRO CompSwapT $xl,$yl, $xh,$yh, $temp SortT $yl, $yh, $temp CMPEQ $xl, $xh EORLT $xl, $xl, $xh EORLT $xh, $xl, $xh EORLT $xl, $xl, $xh MEND ; ; Macro Difference - rc := ABS(ra-rb) ; ; Test GE/LT for ra>=rb / ra<rb ; MACRO Difference $rc,$ra,$rb SUBS $rc,$ra,$rb RSBLT $rc,$rc,#0 MEND ; ; Macro Least - Select the smallest value (signed) ; MACRO Least $rc,$ra,$rb CMP $ra,$rb [ $rc = $ra | MOVLE $rc,$ra ] [ $rc = $rb | MOVGT $rc,$rb ] MEND ; ; Macro Greatest - Select the largest (signed) value ; MACRO Greatest $rc,$ra,$rb CMP $ra,$rb [ $rc = $ra | MOVGE $rc,$ra ] [ $rc = $rb | MOVLT $rc,$rb ] MEND ; ; Macro PackXtnd - pack 2 bytes into 1 word and sign extend ; MACRO PackXtnd $result,$hi,$lo [ $lo = $result ADD $result,$lo,$hi,LSL #8 MOV $result,$result,LSL #16 MOV $result,$result,ASR #16 | MOV $result,$hi,LSL #24 ORR $result,$lo,$result,ASR #16 ] MEND MACRO LoadCoordPair $x, $y, $basereg, $offset ASSERT $x < $y [ ($offset) :AND: 3 = 2 ADD $x, $basereg, #($offset)-2 LDMIA $x, {$x, $y} ; (Xh,Xl,??,??) (??,??,Yh,Yl) MOV $x, $x, ASR #16 ; (Xs,Xs,Xh,Xl) MOV $y, $y, LSL #16 ; (Yh,Yl, 0, 0) MOV $y, $y, ASR #16 ; (Ys,Ys,Yh,Yl) | [ ($offset) :AND: 3 = 0 LDR $x, [$basereg, #$offset] ; (Yh,Yl,Xh,Xl) | [ ($offset) :AND: 3 = 1 ADD $x, $basereg, #($offset)-1 LDMIA $x, {$x, $y} ; (Yl,Xh,Xl,??) (??,??,??,Yh) MOV $x, $x, LSR #8 ; ( 0,Yl,Xh,Xl) ORR $x, $x, $y, LSL #24 ; (Yh,Yl,Xh,Xl) | ADD $x, $basereg, #($offset)-3 LDMIA $x, {$x, $y} ; (Xl,??,??,??) (??,Yh,Yl,Xh) MOV $x, $x, LSR #24 ; ( 0, 0, 0,Xl) ORR $x, $x, $y, LSL #8 ; (Yh,Yl,Xh,Xl) ] ] MOV $y, $x, ASR #16 ; (Ys,Ys,Yh,Yl) MOV $x, $x, LSL #16 ; (Xh,Xl, 0, 0) MOV $x, $x, ASR #16 ; (Xs,Xs,Xh,Xl) ] MEND ; ; Macro SaveRetAdr - Push R14 to our pseudo stack ; MACRO SaveRetAdr Push R14 MEND ; ; Macro Return - Pull from stack into PC ; MACRO Return $cond LDM$cond.FD StkPtr!, {PC} MEND ; ; Macro SuperMode - Set supervisor mode ; MACRO SuperMode SWI &16 MEND ; ; Macro UserMode - Return to user mode ; MACRO UserMode TEQP PC,#0 ; Return to user mode MOV R0,R0 ; Force a NOP so it works MEND ; ; Macro WINDow - Compare coordinate against graphics window ; ; Test GE/LT for within/outside window ; MACRO WINDow $rx,$ry, $rl,$rb,$rr,$rt ; ASSERT ($rl < $rb) AND ($rb < $rr) AND ($rr < $rt) ADD $rt,WsPtr,#GWLCol LDMIA $rt,{$rl,$rb,$rr,$rt} CMP $rx,$rl CMPGE $rr,$rx CMPGE $ry,$rb CMPGE $rt,$ry MEND ; ; Macro WindowRes - Window a coordinate, giving status word ; ; Result word is as follows: ; ; | | ; 1001 | 1000 | 1010 ; | | ; -----+------+----- GWTRow ; | | ; 0001 | 0000 | 0010 ; | | ; -----+------+----- GWBRow ; | | ; 0101 | 0100 | 0110 ; | | ; ; GWLCol GWRCol ; ; MACRO WindowRes $result, $rx,$ry, $rl,$rb,$rr,$rt ; ASSERT ($rl < $rb) AND ($rb < $rr) AND ($rr < $rt) MOV $result,#0 ADD $rt,WsPtr,#GWLCol LDMIA $rt,{$rl,$rb,$rr,$rt} CMP $rx,$rl ORRLT $result,$result,#1 ;Set bit 0 if X < window CMP $rr,$rx ORRLT $result,$result,#2 ;Set bit 1 if X > window CMP $ry,$rb ORRLT $result,$result,#4 ;Set bit 2 if Y < window CMP $rt,$ry ORRLT $result,$result,#8 ;Set bit 3 if Y > window MEND MACRO $lab EQUB $var ASSERT $var >= &00 ASSERT $var <= &FF $lab = $var MEND MACRO OrrEor $d,$s, $or,$eor ORR $d,$s,$or EOR $d,$d,$eor MEND MACRO ;Scr:=ScrOR(oraANDmsk)EOR(eorANDmsk) OrrEorMASK $scr,$msk, $ora,$eor, $tmp AND $tmp,$msk,$ora ORR $scr,$scr,$tmp AND $tmp,$msk,$eor EOR $scr,$scr,$tmp MEND MACRO ORoreorEORoreor $d,$s, $oo,$eo,$oe,$ee, $tmp OrrEor $tmp,$s, $oo,$eo ORR $d,$d,$tmp OrrEor $tmp,$s, $oe,$ee EOR $d,$d,$tmp MEND MACRO ORoreorEORoreorMASK $d,$s,$m, $oo,$eo,$oe,$ee, $tmp OrrEor $tmp,$s, $oo,$eo AND $tmp,$tmp,$m ORR $d,$d,$tmp OrrEor $tmp,$s, $oe,$ee AND $tmp,$tmp,$m EOR $d,$d,$tmp MEND MACRO ShiftR $d,$e, $r,$rcomp MOV $d,$d,LSR $r ORR $d,$d,$e,LSL $rcomp MEND MACRO ShiftL $d,$e, $r,$rcomp MOV $e,$e,LSL $rcomp ORR $e,$e,$d,LSR $r MEND MACRO BitLOffset $b,$x, $xshftfactor,$npix,$log2bpc AND $b,$x,$npix MOV $b,$b,LSL $log2bpc MEND MACRO BitROffset $b,$x, $xshftfactor,$npix,$log2bpc AND $b,$x,$npix ADD $b,$b,#1 MOV $b,$b,LSL $log2bpc SUB $b,$b,#1 MEND MACRO WordOffset $w,$x, $xshftfactor,$npix,$log2bpc MOV $w,$x,ASR $xshftfactor MEND MACRO OffsetWordAndBit $o,$b,$x,$tmp LDR $tmp,[WsPtr,#XShftFactor] MOV $o,$x,ASR $tmp ;Word offset into scanline LDR $tmp,[WsPtr,#NPix] AND $b,$x,$tmp ;Pixel offset into word LDR $tmp,[WsPtr,#Log2BPC] MOV $b,$b,LSL $tmp ;Bit offset into word MEND MACRO $label ErrorMsg $num,$string $label DCD $num DCB "$string", 0 ALIGN MEND ; ; Macro when given a register will return the state to indicate ; if we are in a graphics mode. Originally lots of code used to simply ; load NPix and look for a null parameter (fair enough in 1-8 bit per pixel) ; but now we look at the mode flags, the choice of a new generation! ; MACRO $label GraphicsMode $scrap $label LDR $scrap, [WsPtr, #ModeFlags] TST $scrap, #Flag_NonGraphic ;NE then non-graphic mode! MEND END