; 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. ; ; > VduPal10 ; mjs - not used any more (it's pre-Medusa, for goodness sake) ; Palette programming for VIDC10 (ie VIDC1 or VIDC1a) ; ***************************************************************************** ; PaletteV handler ; ---------------- ; ***************************************************************************** ; ; MOSPaletteV - Default owner of PaletteV ; ASSERT paletteV_Complete = 0 ASSERT paletteV_Read = 1 ASSERT paletteV_Set = 2 ASSERT paletteV_1stFlashState = 3 ASSERT paletteV_2ndFlashState = 4 ASSERT paletteV_SetDefaultPalette = 5 ASSERT paletteV_BlankScreen = 6 MOSPaletteV ROUT CMP r4, #1 MOVCC pc, lr BEQ PV_ReadPalette CMP r4, #3 BCC PV_SetPalette BEQ PV_1stFlashState CMP r4, #5 BCC PV_2ndFlashState BEQ PV_SetDefaultPalette CMP r4, #7 BCC PV_BlankScreen MOV pc, lr ; reason code not known, so pass it on ; ***************************************************************************** PV_SetDefaultPalette ROUT Push "r0-r3,r5-r9" LDR r0, [WsPtr, #PalIndex] ; the new index 0-5 ADR r1, paldptab LDR r2, [r1, r0, LSL #2] ; offset from r1 to start of table ADD r0, r0, #1 ; point to next item LDR r5, [r1, r0, LSL #2] ; offset from r1 to end of table +1 ADD r2, r2, r1 ; r2 -> start of table ADD r5, r5, r1 ; r5 -> end of table MOV r0, #0 ; start at palette index 0 MOV r1, #3 ; set both halves 10 LDR r6, [r2], #4 MOVS r3, r6, LSL #17 ; get 1st half word and set carry if flashing MOV r3, r3, LSR #17 MOVCC r4, #0 LDRCS r4, =&FFF ; flashing so invert 2nd half RGB BL UpdateSettingStraightRGB ADD r0, r0, #1 MOVS r3, r6, LSL #1 ; get 2nd half word and set carry if flashing MOV r3, r3, LSR #17 MOVCC r4, #0 LDRCS r4, =&FFF BL UpdateSettingStraightRGB ADD r0, r0, #1 TEQ r2, r5 BNE %BT10 ; now ensure all palette entries from 0..15 are initialised MOV r3, #0 ; set unused (and border) to black MOV r4, #0 ; no flashing 20 CMP r0, #16 BHS %FT25 BL UpdateSettingStraightRGB ADD r0, r0, #1 B %BT20 25 MOV r2, #0 ; Set border to black (sup 0) BL BorderInitEntry MOV r4, #0 ; indicate PaletteV operation complete Pull "r0-r3,r5-r9,pc" ; restore registers and claim vector LTORG ; ***************************************************************************** ; Table of offsets from paldata_pointer to palette data paldptab & paldat1-paldptab ; 2 Colour Modes & paldat2-paldptab ; 4 & paldat4-paldptab ; 16 & paldat8-paldptab ; 256 & paldatT-paldptab ; teletext mode & paldatHR-paldptab ; Hi-res mono mode & paldatend-paldptab ; end of table marker paldat1 ; Data for 1 bit modes - only necessary to program registers 0 and 1 ; FSBGR DCW &0000 ; 0 Black DCW &0FFF ; 1 White paldat2 ; Data for 2 bit modes - only necessary to program registers 0..3 ; FSBGR DCW &0000 ; 0 Black DCW &000F ; 1 Red DCW &00FF ; 2 Yellow DCW &0FFF ; 3 White paldat4 ; Data for 4 bit modes - program all registers ; Flashing Colours will be needed here ; FSBGR DCW &0000 ; 0 Black DCW &000F ; 1 Red DCW &00F0 ; 2 Green DCW &00FF ; 3 Yellow DCW &0F00 ; 4 Blue DCW &0F0F ; 5 Magenta DCW &0FF0 ; 6 Cyan DCW &0FFF ; 7 White DCW &8000 ; 8 Flashing Black DCW &800F ; 9 Flashing Red DCW &80F0 ; 10 Flashing Green DCW &80FF ; 11 Flashing Yellow DCW &8F00 ; 12 Flashing Blue DCW &8F0F ; 13 Flashing Magenta DCW &8FF0 ; 14 Flashing Cyan DCW &8FFF ; 15 Flashing White paldat8 ; Data for 8 bit modes - Program all registers ; PP field is 16 for all these, cos not true BBC colours ; FSBGR DCW &0000 ; 0 DCW &0111 ; 1 DCW &0222 ; 2 DCW &0333 ; 3 DCW &0004 ; 4 DCW &0115 ; 5 DCW &0226 ; 6 DCW &0337 ; 7 DCW &0400 ; 8 DCW &0511 ; 9 DCW &0622 ; A DCW &0733 ; B DCW &0404 ; C DCW &0515 ; D DCW &0626 ; E DCW &0737 ; F paldatT ; Data for teletext mode DCW &0000 ; 0 Black DCW &000F ; 1 Red DCW &00F0 ; 2 Green DCW &00FF ; 3 Yellow DCW &0F00 ; 4 Blue DCW &0F0F ; 5 Magenta DCW &0FF0 ; 6 Cyan DCW &0FFF ; 7 White ; Colours 8 to 15 have supremacy bit set DCW &1000 ; 8 Supremacy+ Black DCW &100F ; 9 Red DCW &10F0 ; 10 Green DCW &10FF ; 11 Yellow DCW &1F00 ; 12 Blue DCW &1F0F ; 13 Magenta DCW &1FF0 ; 14 Cyan DCW &1FFF ; 15 White paldatHR ; data for Hi-res mono mode DCW &0000 ; Only red gun necessary DCW &0111 ; but setting all three makes DCW &0222 ; reading it more natural DCW &0333 DCW &0444 DCW &0555 DCW &0666 DCW &0777 DCW &0888 DCW &0999 DCW &0AAA DCW &0BBB DCW &0CCC DCW &0DDD DCW &0EEE DCW &0FFF DCW &0000 ; border black DCW &0010 ; fixed pointer colours DCW &0020 DCW &0030 paldatend ; ***************************************************************************** ; PaletteV call to set palette ; in: R0 = logical colour ; R1 = colour type (16,17,18,24,25) ; R2 = BBGGRRS0 ; R4 = PaletteV reason code ; ; out: R4 = 0, claim vector if recognised ; otherwise preserve R4 and pass on ; PV_SetPalette ROUT Push "r0-r3" TEQ r1, #16 ; if 16 then set both colours MOVEQ r1, #3 BEQ UpdateNormalColour TEQ r1, #17 ; elif 17 then set 1st colour MOVEQ r1, #1 BEQ UpdateNormalColour TEQ r1, #18 ; elif 18 then set 2nd colour MOVEQ r1, #2 BEQ UpdateNormalColour TEQ r1, #24 ; elif 24 then border colour BEQ BorderColour TEQ r1, #25 ; elif 25 then pointer colour BEQ PointerColour Pull "r0-r3" MOV pc, lr ; else not defined ; ***************************************************************************** UpdateNormalColour ROUT LDR lr, [WsPtr, #DisplayNColour] ; get the mask AND r0, r0, lr ; and mask it off AND r0, r0, #15 ; maximum 15 BL UpdateSettingAndVIDC MOV r4, #0 ; indicate successful PaletteV op Pull "r0-r3, pc" BorderInitEntry ENTRY "r0-r3" ; entry used in default palette setting BorderColour ROUT LDR r0, [WsPtr, #PalIndex] ; if hi res mono TEQ r0, #5 BICEQ r2, r2, #&00300000 ; then knock out bits 0,1 of green palette MOV r0, #16 ; palette index for border colour MOV r1, #3 ; both colours BL UpdateSettingAndVIDC ; Now test for BBC gap mode (ie 3 or 6) ; if so then set colour 2 to same as border, and colour 3 to inverse LDR lr, [WsPtr, #DisplayModeFlags] TST lr, #ModeFlag_BBCGapMode BEQ %FT10 MOV r0, #2 ; make colour 2 (gap) same as border BL UpdateSettingAndVIDC MOV r0, #3 ; make colour 3 inverse gap MVN r2, r2 ; invert R, G and B EOR r2, r2, #&FF ; but use same supremacy BL UpdateSettingAndVIDC 10 MOV r4, #0 ; indicate successful PaletteV op Pull "r0-r3, pc" PointerColour ROUT LDR r1, [WsPtr, #PalIndex] ; if hi res mono, then don't allow TEQ r1, #5 ; pointer palette changes ANDNES r0, r0, #3 ; force pointer colour number in range 1..3 BEQ %FT10 ; zero is invalid ADD r0, r0, #16 ; form palette index 17..19 MOV r1, #3 BL UpdateSettingAndVIDC 10 MOV r4, #0 ; indicate successful PaletteV op Pull "r0-r3,pc" UpdateSettingAndVIDC ROUT AND r4, r2, #&F0000000 MOV r3, r4, LSR #(28-8) ; move blue to bits 8..11 AND r4, r2, #&00F00000 ORR r3, r3, r4, LSR #(20-4) ; move green to bits 4..7 AND r4, r2, #&0000F000 ORR r3, r3, r4, LSR #(12-0) ; move red to bits 0..3 AND r4, r2, #&00000080 ORR r3, r3, r4, LSL #(12-7) ; move sup to bit 12 CMP r0, #16 ; if not normal colour BCS %FT10 ; then OK for hi-res-mono LDR r4, [WsPtr, #PalIndex] TEQ r4, #5 BEQ UpdateHiResRGB 10 MOV r4, #0 ; indicate no EORing between parts ; and drop thru to ... UpdateSettingStraightRGB ENTRY "r2,r5,r6" PHPSEI ; protect against IRQs ORR r3, r3, r0, LSL #26 ; form VIDC register number at top LDRB r5, [WsPtr, #ScreenBlankFlag] TEQ r5, #0 MOVNE r5, #&00FFFFFF ; bits to knock out if blanked LDROSB r2, FlashState ; 0 => second, 1 => first CMP r2, #1 ; C=0 => second, C=1 => first TST r1, #1 BEQ %FT10 ; skip if not setting 1st colour ADD r2, WsPtr, #FirPalSetting STR r3, [r2, r0, LSL #2] MOVCS r2, #VIDC BICCS r6, r3, r5 ; knock out bits for blanking STRCS r6, [r2] ; poke VIDC if setting 1st colour and in 1st state 10 TST r1, #2 BEQ %FT20 ; skip if not setting 2nd colour ADD r2, WsPtr, #SecPalSetting EOR r3, r3, r4 ; toggle requested bits for 2nd half STR r3, [r2, r0, LSL #2] MOVCC r2, #VIDC BICCC r6, r3, r5 ; knock out bits for blanking STRCC r6, [r2] ; poke VIDC if setting 2nd colour and in 2nd state 20 PLP EXIT ; restore registers, claim vector ; ***************************************************************************** ; ; UpdateHiResRGB - Routine to program normal palette for Hi-Res-Mono display ; ; in: r0 = logical colour ; r1 = mask of which states to update (bit 0 = 1st flash state, bit 1 = 2nd) ; r3 = &0000SBGR ; ; out: r3, r4 may be corrupted ; UpdateHiResRGB ENTRY "r5" PHPSEI Push "lr" LDROSB r5, FlashState TEQ r5, #0 ; 0 => 2nd state, 1 => 1st state MOVNE r5, #VIDC ; 1st state => r5 = VIDC, else = 0 TST r1, #1 ADDNE r4, WsPtr, #FirPalSetting BLNE UpdateOneHiResSetting EOR r5, r5, #VIDC ; 2nd state => r5 = VIDC, else = 0 TST r1, #2 ADDNE r4, WsPtr, #SecPalSetting BLNE UpdateOneHiResSetting Pull "lr" PLP EXIT UpdateOneHiResSetting ENTRY "r1,r2,r6-r9" LDRB lr, [WsPtr, #ScreenBlankFlag] TEQ lr, #0 MOVNE lr, #&00FFFFFF ; if blanked, mask off these bits LDR r2, =&FFF TEQ r0, #0 MOVEQ r1, r3 ; if programming colour 0 then 1st colour is r3 LDREQ r6, [r4, #15*4] ; and 2nd colour is what's in colour 15 LDRNE r1, [r4, #0*4] ; else 1st colour is what's in colour 0 MOVNE r6, r3 ; and 2nd colour is r3 EOR r6, r6, #&008 ; invert bit R3 of colour 15 EOR r6, r6, r1 ; inverted EOR of colours 0 and 15 ANDS r6, r6, #&008 ; just use R3 for black/white MOVNE r6, r2 ; if non-zero make BIC mask full RGB else 0 ANDS r1, r1, #&008 ; if colour 0 = white then make EOR mask full RGB else 0 MOVNE r1, r2 ADD r7, r4, #16*4 ; end of table MOV r8, #0 ; start LDR r2, =&04000111 ; amount to add on each time round 10 BIC r9, r8, r6 ; take value and knock out BIC mask EOR r9, r9, r1 ; then toggle EOR mask STR r9, [r4], #4 ; store in soft copy TEQ r5, #0 ; if updating VIDC BICNE r9, r9, lr ; knock out bits (for blanking) STRNE r9, [r5] ; then do it ADD r8, r8, r2 ; move on to next value TEQ r4, r7 ; if not done all 16 entries BNE %BT10 ; then loop EXIT LTORG ; ***************************************************************************** ; ; PV_ReadPalette - PaletteV read palette handler ; ; in: R0 = logical colour ; R1 = 16 (read normal colour) ; 24 (read border colour) ; 25 (read cursor colour) ; ; out: R2 = first flash setting (BBGGRRS0), supremacy bit 7 ; R3 = second flash setting (BBGGRRS0), supremacy bit 7 ; PV_ReadPalette ROUT Push "r10,r11" LDR r10, [WsPtr, #DisplayNColour] ; logical colours in this mode -1 TEQ r1, #24 ; is it reading border palette MOVEQ r11, #16 ; then set up border index BEQ %FT10 ; and go TEQ r1, #25 ; is it reading pointer palette BEQ %FT05 AND r11, r0, r10 ; no, then force into suitable range AND r11, r11, #15 ; only allow 0..15 LDR r2, [WsPtr, #PalIndex] TEQ r2, #5 ; if hi res mono TEQEQ r11, #1 ; and reading colour 1 MOVEQ r11, #15 ; then read colour 15 instead B %FT10 ; always skip 05 ANDS r11, r0, #3 ; else force logical colour 0..3 BEQ %FT99 ; and 0 is illegal, so do nothing ADD r11, r11, #16 ; set up correct index 10 CMP r11, #16 ; is it normal one (not border/cursor) MOVCSS r3, #0 ; no, then don't fudge colours; Z=1 ; (carry preserved from CMP) ANDCCS r3, r10, #&F0 ; yes, then fudge if 256 colour mode ADD r10, WsPtr, #FirPalSetting LDR r11, [r10, r11, LSL #2]! ; r11 := 1st XX00SBGR BLNE FudgeRGB AND lr, r11, #&F00 ; lr := 1st 00000B00 MOV r2, lr, LSL #20 ; r2 := 1st B0000000 AND lr, r11, #&0F0 ; lr := 1st 000000G0 ORR r2, r2, lr, LSL #16 ; r2 := 1st B0G00000 AND lr, r11, #&00F ; lr := 1st 0000000R ORR r2, r2, lr, LSL #12 ; r2 := 1st B0G0R000 ORR r2, r2, r2, LSR #4 ; r2 := 1st BBGGRR00 AND lr, r11, #&1000 ORR r2, r2, lr, LSR #5 ; r2 := 1st BBGGRRS0 LDR r11, [r10, #SecPalSetting-FirPalSetting] BLNE FudgeRGB AND lr, r11, #&F00 ; lr := 2nd 00000B00 MOV r3, lr, LSL #20 ; r3 := 2nd B0000000 AND lr, r11, #&0F0 ; lr := 2nd 000000G0 ORR r3, r3, lr, LSL #16 ; r3 := 2nd B0G00000 AND lr, r11, #&00F ; lr := 2nd 0000000R ORR r3, r3, lr, LSL #12 ; r3 := 2nd B0G0R000 ORR r3, r3, r3, LSR #4 ; r3 := 2nd BBGGRR00 AND lr, r11, #&1000 ORR r3, r3, lr, LSR #5 ; r3 := 2nd BBGGRRS0 99 MOV r4, #0 Pull "r10, r11, pc" FudgeRGB ROUT [ No26bitCode mrs ,r4, CPSR ] BIC r11, r11, #&C8 ; knock out top bit R, top 2 bits G BIC r11, r11, #&800 ; knock out top bit B TST r0, #&10 ; override top bit of red ORRNE r11, r11, #&8 TST r0, #&20 ; override next to top bit of green ORRNE r11, r11, #&40 TST r0, #&40 ; override top bit of green ORRNE r11, r11, #&80 TST r0, #&80 ; override top bit of blue ORRNE r11, r11, #&800 [ No26bitCode msr ,CPSR_f, r4 | MOVS pc, lr ] ; ***************************************************************************** ; ; PV_1stFlashState - PaletteV routine to set first flash state ; PV_1stFlashState ROUT Push "r0-r3" ADD r0, WsPtr, #FirPalSetting DoR0Flash MOV r1, #15 ; logical colour DoAllUpdate LDRB lr, [WsPtr, #ScreenBlankFlag] TEQ lr, #0 MOVEQ lr, #&FF000000 ; unblanked, just knock off top 8 bits MOVNE lr, #&FFFFFFFF ; blanked, knock off all bits! MOV r2, #VIDC 10 LDR r3, [r0, r1, LSL #2] BIC r3, r3, lr ; get rid of top bits, or all if blanked ORR r3, r3, r1, LSL #26 ; OR in register number STR r3, [r2] ; program VidC SUBS r1, r1, #1 BPL %BT10 MOV r4, #0 Pull "r0-r3, pc" ; ***************************************************************************** ; ; PV_2ndFlashState - PaletteV routine to set second flash state ; PV_2ndFlashState ROUT Push "r0-r3" ADD r0, WsPtr, #SecPalSetting B DoR0Flash ; ***************************************************************************** ; ; UpdateAllPalette - Update all VIDC palette entries ; UpdateAllPalette ENTRY "r0-r3" ; "r0-r3,lr" stacked ready to branch to code LDROSB r0, FlashState CMP r0, #1 ADDCS r0, WsPtr, #FirPalSetting ; FlashState = 1 => 1st state, 0 => 2nd state ADDCC r0, WsPtr, #SecPalSetting MOV r1, #19 ; do 0-15 and border + 3 pointer B DoAllUpdate ; ***************************************************************************** ; ; PV_BlankScreen - Blank/unblank screen ; ; in: R0 = -1 => read blank state ; R0 = 0 => unblank screen ; R0 = 1 => blank screen ; ; out: R0 = old state (0=unblanked, 1=blanked) ; R4 = 0 PV_BlankScreen ROUT Push "r1-r3" LDRB r3, [WsPtr, #ScreenBlankFlag] CMP r0, #1 BHI %FT99 TEQ r0, r3 ; changing to same state? (carry preserved) BEQ %FT99 ; if so, do nothing STRB r0, [WsPtr, #ScreenBlankFlag] ; update new state MOVCC r0, #(1 :SHL: 10) :OR: (0 :SHL: 8) ; unblank: video DMA on, no refresh MOVCS r0, #(0 :SHL: 10) :OR: (3 :SHL: 8) ; blank: video DMA off, continuous refresh MOV r1, #(1 :SHL: 10) :OR: (3 :SHL: 8) ; bits to modify SWI XOS_UpdateMEMC PHPSEI r0, lr ; disable IRQs so we don't get a flash in the middle BL UpdateAllPalette ; update all palette, including border + pointer PLP r0 ; restore old IRQ state 99 MOV r0, r3 MOV r4, #0 Pull "r1-r3, pc" END