; 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. ; ; > VduPal20 ; mjs Sep 2000 ; ; not used any more, since kernel/HAL split ; vdupalxx is the file now used for generic palette programming ; Palette programming for VIDC20 ; ***************************************************************************** ; 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 ASSERT paletteV_BulkRead = 7 ASSERT paletteV_BulkWrite = 8 ASSERT paletteV_GammaCorrection = 9 [ LCDInvert ASSERT paletteV_LCDInvert = 10 ] [ StorkPowerSave ASSERT paletteV_VIDCDisable = 12 ASSERT paletteV_VIDCRestore = 13 ] 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 BEQ PV_BulkRead CMP r4, #9 BCC PV_BulkWrite BEQ PV_GammaCorrect [ LCDInvert CMP r4, #11 BCC PV_LCDInvert ] [ StorkPowerSave MOVEQ pc, lr CMP r4, #13 BCC PV_VIDCDisable BEQ PV_VIDCRestore MOVEQ pc, lr ] 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-7 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 ADDS r2, r2, r1 ; r2 -> start of table BICMI pc, r2, #&80000000 ; if negative then it's a routine ADD r5, r5, r1 ; r5 -> end of table BIC r5, r5, #&80000000 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..255 are initialised MOV r3, #0 ; set unused (and border) to black MOV r4, #0 ; no flashing 20 CMP r0, #256 BHS FinishDefault BL UpdateSettingStraightRGB ADD r0, r0, #1 B %BT20 FinishDefault MOV r2, #0 ; set border to black (and setup colours 2,3 in BBC gap modes) 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) :OR: &80000000 ; 256 (VIDC10 compatible) - use routine & paldatT-paldptab ; teletext mode & paldatHR-paldptab ; Hi-res mono mode & (paldat16-paldptab) :OR: &80000000 ; 16 bpp - use routine & (paldat32-paldptab) :OR: &80000000 ; 32 bpp (or 256 greys - they're identical!) - use routine & 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 ; Routine to initialise palette for VIDC10-compatible 8bpp modes ; Note this must still be in between paldat4 and paldatT paldat8 ROUT MOV r1, #3 ; set both halves of palette MOV r0, #0 ; starting index 10 AND r2, r0, #3 ; get tint bits ORR r2, r2, r2, LSL #4 ; and duplicate into bits 8,9,12,13,16,17,20,21,24,25,28,29 ORR r2, r2, r2, LSL #8 ORR r2, r2, r2, LSL #16 BIC r2, r2, #&FF TST r0, #4 ORRNE r2, r2, #&00004400 TST r0, #8 ORRNE r2, r2, #&44000000 TST r0, #&10 ORRNE r2, r2, #&00008800 TST r0, #&20 ORRNE r2, r2, #&00440000 TST r0, #&40 ORRNE r2, r2, #&00880000 TST r0, #&80 ORRNE r2, r2, #&88000000 BL UpdateSettingAndVIDC ADD r0, r0, #1 TEQ r0, #&100 BNE %BT10 B FinishDefault 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 paldat16 ROUT ADR r5, paldat16tab palmetatab MOV r1, #3 ; set both halves of palette MOV r0, #0 ; starting index 10 MOV r8, r5 MOV r2, #0 MOV r6, r0 20 LDR r7, [r8], #4 MOVS r6, r6, LSR #1 ORRCS r2, r2, r7 BNE %BT20 BL UpdateSettingAndVIDC ADD r0, r0, #1 TEQ r0, #&100 BNE %BT10 B FinishDefault paldat16tab & &00000800 ; palette bit 0 & &00081000 ; 1 & &08102100 ; 2 & &10214200 ; 3 & &21428400 ; 4 & &42840000 ; 5 & &84000000 ; 6 & &00000000 ; 7 paldat32 ROUT ADR r5, paldat32tab B palmetatab paldat32tab & &01010100 ; palette bit 0 & &02020200 ; 1 & &04040400 ; 2 & &08080800 ; 3 & &10101000 ; 4 & &20202000 ; 5 & &40404000 ; 6 & &80808000 ; 7 paldatend ; ***************************************************************************** ; PaletteV call to set palette in bulk ; in: R0 => list of colours, or 0 ; R1 = colour type (16,17,18,24,25) in b24-31 & number to do in b23-b00 ; R2 => list of palette entries (both flash states if 16, one if 17/18) ; R4 = PaletteV reason code ; ; out: R4 = 0, claim vector if recognised ; otherwise preserve R4 and pass on PV_BulkWrite ROUT Push "R0-R3,R5-R11" ; pc already stacked ;register usage: ;[R6] colour list ;R7 colour type ;R8 max number ;[R9] palette entries ;R10 loop counter ;R11 colour number MOV R7,R1,LSR #24 BIC R8,R1,#&FF000000 MOV R6,R0 MOV R9,R2 MOV R10,#0 10 TEQ R6,#0 MOVEQ R11,R10 LDRNE R11,[R6],#4 TEQ R7,#16 TEQNE R7,#17 MOVEQ R0,R11 MOVEQ R1,#1 LDREQ R2,[R9],#4 BLEQ UpdateNormalColour TEQ R7,#16 TEQNE R7,#18 MOVEQ R0,R11 MOVEQ R1,#2 LDREQ R2,[R9],#4 BLEQ UpdateNormalColour TEQ R7,#24 MOVEQ R0,R11 LDREQ R2,[R9],#4 BLEQ BorderColour TEQ R7,#25 MOVEQ R0,R11 LDREQ R2,[R9],#4 BLEQ PointerColour ADD R10,R10,#1 CMP R10,R8 BCC %BT10 MOV R4,#0 Pull "R0-R3,R5-R11,PC" ; ***************************************************************************** ; 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 ; ;amg 19/4/93 - change this routine to make all the calls subroutines rather ; than branches. Although it will slow this down a bit, it makes the bulk ; write a lot simpler and involves less duplication of mungeing code. PV_SetPalette ROUT Push "r0-r3" TEQ r1, #16 ; if 16 then set both colours MOVEQ r1, #3 BEQ Call_UpdateNormalColour TEQ r1, #17 ; elif 17 then set 1st colour MOVEQ r1, #1 BEQ Call_UpdateNormalColour TEQ r1, #18 ; elif 18 then set 2nd colour MOVEQ r1, #2 BEQ Call_UpdateNormalColour TEQ r1, #24 ; elif 24 then border colour BEQ Call_BorderColour TEQ r1, #25 ; elif 25 then pointer colour BEQ Call_PointerColour 10 Pull "r0-r3" MOV pc, lr ; else not defined Call_UpdateNormalColour BL UpdateNormalColour Pull "r0-r3,pc" BorderInitEntry Push "r0-r3,lr" ; entry used in default palette setting Call_BorderColour BL BorderColour Pull "r0-r3,pc" Call_PointerColour BL PointerColour Pull "r0-r3,pc" ; ***************************************************************************** UpdateNormalColour ROUT Push "LR" LDR lr, [WsPtr, #DisplayNColour] ; get the mask TEQ lr, #63 ; is it brain-damaged VIDC10-compatible 256 colour mode? BEQ %FT10 AND r0, r0, lr ; and mask it off AND r0, r0, #255 ; definitely no more than 256 palette entries BL UpdateSettingAndVIDC 05 MOV r4, #0 ; indicate successful PaletteV op Pull "pc" 10 AND r0, r0, #15 ; starting palette entry 20 LDR r3, =&88CC8800 ; r3 = bits controlled by bits 4..7 of pixel value BIC r2, r2, r3 TST r0, #&10 ; test bit 4 (r3,7) ORRNE r2, r2, #&00008800 TST r0, #&20 ; test bit 5 (g2,6) ORRNE r2, r2, #&00440000 TST r0, #&40 ; test bit 6 (g3,7) ORRNE r2, r2, #&00880000 TST r0, #&80 ; test bit 7 (b3,7) ORRNE r2, r2, #&88000000 BL UpdateSettingAndVIDC ADD r0, r0, #&10 CMP r0, #&100 BCC %BT20 B %BT05 BorderColour ROUT Push "LR" MOV r0, #&40000000 ; pseudo-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, #Flag_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 "pc" PointerColour ROUT Push "LR" ANDS r0, r0, #3 ; force pointer colour number in range 1..3 BEQ %FT10 ; zero is invalid MOV r0, r0, LSL #28 ; move up to top nybble ORR r0, r0, #&40000000 ; form pseudo-palette-index MOV r1, #3 BL UpdateSettingAndVIDC 10 MOV r4, #0 ; indicate successful PaletteV op Pull "pc" ; UpdateSettingStraightRGB ; ; in: r0 = logical colour (border = 4 << 28, pointer colours = 5,6,7 << 28) ; r1 = bit mask of which flash states to update (bit 0 set => 1st, bit 1 set => 2nd) ; r3 = SBGR ; r4 = SBGR to EOR with to go from 1st to 2nd flash state ; out: r0,r1,r2,r4 preserved ; r3 corrupted UpdateSettingStraightRGB EntryS "r2,r5,r6,r7" ANDS r5, r3, #1 :SHL: 12 ; get supremacy bit in 1st colour MOVNE r5, #1 :SHL: 27 ; put in r5 in new position AND r6, r3, #&FF0 ; r6 = 00000BG0 ORR r5, r5, r6, LSL #8 ; r5 = 0s0BG000 AND r6, r3, #&0FF ; r6 = 000000GR ORR r5, r5, r6, LSL #4 ; r5 = 0s0BGGR0 AND r6, r3, #&00F ; r6 = 0000000R ORR r5, r5, r6 ; r5 = 0s0BGGRR AND r6, r3, #&F00 ; r6 = 00000B00 ORR r3, r5, r6, LSL #12 ; r3 = 0sBBGGRR ANDS r5, r4, #1 :SHL: 12 ; get supremacy bit in EOR mask MOVNE r5, #1 :SHL: 27 ; put in r5 in new position AND r6, r4, #&FF0 ; r6 = 00000BG0 ORR r5, r5, r6, LSL #8 ; r5 = 0s0BG000 AND r6, r4, #&0FF ; r6 = 000000GR ORR r5, r5, r6, LSL #4 ; r5 = 0s0BGGR0 AND r6, r4, #&00F ; r6 = 0000000R ORR r5, r5, r6 ; r5 = 0s0BGGRR AND r6, r4, #&F00 ; r6 = 00000B00 ORR r4, r5, r6, LSL #12 ; r5 = 0sBBGGRR B UpdateSettingCommon ; UpdateSettingAndVIDC ; ; in: r0 = logical colour (border = 4 << 28, pointer colours = 5,6,7 << 28) ; r1 = bit mask of which flash states to update (bit 0 set => 1st, bit 1 set => 2nd) ; r2 = BBGGRRS0 ; ; out: r0, r1, r2 preserved ; r3, r4 corrupted ; UpdateSettingAndVIDC ALTENTRY ;amg: changed to handle 4 bits of supremacy MOV r3, r2, LSR #8 ; r3 = 00bbggrr ANDS r2, r2, #&F0 ; r2 = 000000s0 ORRNE r3, r3, r2, LSL #20 ; r3 = 0sbbggrr MOV r4, #0 ; indicate no EORing between parts ; ... and drop thru to ; UpdateSettingCommon ; ; in: r0 = logical colour (border = 4 << 28, pointer colours = 5,6,7 << 28) ; r1 = bit mask of which flash states to update (bit 0 set => 1st, bit 1 set => 2nd) ; r3 = 0sBBGGRR (s in bits 24-27) ; r2, r5, r6, r7, lr stacked ; ; out: r0, r1, r2, r4 preserved ; r3 corrupted ; UpdateSettingCommon ROUT PHPSEI ; protect against IRQs Push "r0, r8, r9" MOV r7, #VIDC TST r0, #&40000000 ; if border or pointer ORRNE r3, r3, r0 ; then merge with RGB MOVNE r0, r0, LSR #28 ; and make r0 into index for soft copy ADDNE r0, r0, #(256-4) ; ie 256, 257, 258 or 259 ORREQ r5, r0, #VIDCPalAddress ; else set up palette index register STREQ r5, [r7] LDRB r5, [WsPtr, #ScreenBlankFlag] TEQ r5, #0 MOVNE r5, #&0FFFFFFF ; bits to knock out if blanked (EBBGGRR) 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 LDR r2, [WsPtr, #FirPalAddr] ADD r8, r2, #(256+1+3)*4*4 ; r8 -> rgb transfer tables STR r3, [r2, r0, LSL #2]! ; store in logical colour and write back pointer AND r6, r3, #&FF ; r6 = red LDRB r6, [r8, r6] ; r6 = gamma(red) ADD r8, r8, #&100 ; r8 -> green transfer AND r9, r3, #&FF00 ; r9 = green << 8 LDRB r9, [r8, r9, LSR #8] ; r9 = gamma(green) ORR r6, r6, r9, LSL #8 ; r6 = gamma(red) + (gamma(green)<<8) ADD r8, r8, #&100 ; r8 -> blue transfer AND r9, r3, #&FF0000 ; r9 = blue << 16 LDRB r9, [r8, r9, LSR #16] ; r9 = gamma(blue) ORR r6, r6, r9, LSL #16 ; r6 = gamma(red) + (gamma(green)<<8) + (gamma(blue)<<16) AND r9, r3, #&FF000000 ; knock out rgb from original ORR r6, r6, r9 ; and or in new bits STR r6, [r2, #(256+1+3)*4*2] ; store in physical copy BICCS r6, r6, r5 ; knock out bits for blanking [ LCDSupport Push "lr", CS BLCS Poke_VIDC Pull "lr", CS | STRCS r6, [r7] ; poke VIDC if setting 1st colour and in 1st state ] 10 EOR r3, r3, r4 ; toggle requested bits for 2nd half TST r1, #2 BEQ %FT20 ; skip if not setting 2nd colour LDR r2, [WsPtr, #SecPalAddr] ADD r8, r2, #(256+1+3)*4*3 ; r8 -> rgb transfer tables STR r3, [r2, r0, LSL #2]! ; store in logical copy and write back AND r6, r3, #&FF ; r6 = red LDRB r6, [r8, r6] ; r6 = gamma(red) ADD r8, r8, #&100 ; r8 -> green transfer AND r9, r3, #&FF00 ; r9 = green << 8 LDRB r9, [r8, r9, LSR #8] ; r9 = gamma(green) ORR r6, r6, r9, LSL #8 ; r6 = gamma(red) + (gamma(green)<<8) ADD r8, r8, #&100 ; r8 -> blue transfer AND r9, r3, #&FF0000 ; r9 = blue << 16 LDRB r9, [r8, r9, LSR #16] ; r9 = gamma(blue) ORR r6, r6, r9, LSL #16 ; r6 = gamma(red) + (gamma(green)<<8) + (gamma(blue)<<16) AND r9, r3, #&FF000000 ; knock out rgb from original ORR r6, r6, r9 ; and or in new bits STR r6, [r2, #(256+1+3)*4*2] ; store in physical copy BICCC r6, r6, r5 ; knock out bits for blanking [ LCDSupport Push "lr", CC BLCC Poke_VIDC Pull "lr", CC | STRCC r6, [r7] ; poke VIDC if setting 2nd colour and in 2nd state ] 20 PLP Pull "r0, r8, r9" EXITS ; restore registers, claim vector ; ***************************************************************************** ; ; PV_BulkRead - Read multiple palette entries with one call ; ; in: R0 => list of colours wanted, or 0 to start with first and increment ; R1 = b24-b31 - colour type: 16/17/18/24/25 ; b00-b23 - number of colours to do ; ; R2 => memory for first flash state colours (and second if R3=0) ; R3 => memory for second flash state colours (if 0, intermingle with R2 instead) ; ; out: all preserved (R4 set to 0 to show call handled) ; flags used to control routine PV_BR_WantFirst * 1 ; doing 16 or 17 PV_BR_WantSecond * 2 ; doing 16 or 18 PV_BR_HaveList * 4 ; we have a list of colours PV_BR_TwoLists * 8 ; we have two output areas (R2 & R3 valid) PV_BR_Border * 16 ; doing 24 PV_BR_Mouse * 32 ; doing 25 PV_BulkRead ROUT Push "R0-R3,R6-R11" ; return addr already stacked MOV R6,R1,LSR #24 ; isolate the colour type MOV R7,#(PV_BR_WantFirst + PV_BR_WantSecond) CMP R6,#17 ; do we want both flash states ? BICEQ R7,R7,#PV_BR_WantSecond ; if 17 only want first flash state CMP R6,#18 BICEQ R7,R7,#PV_BR_WantFirst ; if 18 only want second flash state CMP R6,#24 ORREQ R7,R7,#PV_BR_Border ORRGT R7,R7,#PV_BR_Mouse ;now set up other control flags CMP R0,#0 ORRNE R7,R7,#PV_BR_HaveList ; we have a list of colours CMP R3,#0 ORRNE R7,R7,#PV_BR_TwoLists ; we have two output areas ;set up a mask for the number of colours LDR R8,[WsPtr,#DisplayNColour] TEQ R8,#63 MOVEQ R8,#255 ; deal with braindamaged 8BPP case ;the mouse has colours 1-3 TST R7,#PV_BR_Mouse MOVNE R8,#3 ;take the colour type off the top of R1, leaving #colours wanted BIC R1,R1,#&FF000000 ; register usage: ; [R0]: colour list ; R1: number of colours ; [R2]: first flash state list ; [R3]: second flash state list ; R7: control flags ; R8: mask for colour number ; R9: loop counter ; R10: misc ; LR: misc MOV R9,#0 30 TST R7,#PV_BR_HaveList LDRNE LR,[R0],#4 MOVEQ LR,R9 ; LR = wanted colour number AND LR,LR,R8 ; ensure it is sensible TST R7,#PV_BR_Border MOVNE LR,#256 ; border is stored as colour 256 TST R7,#PV_BR_Mouse BEQ %FT40 TEQ LR,#0 BEQ %FT50 ;colour 0 is invalid ADD LR,LR,#256 ;bring into range (257-259) 40 TST R7,#PV_BR_WantFirst LDRNE R10,[WsPtr,#FirPalAddr] LDRNE R10,[R10,LR,LSL#2] ; xsbbggrr - could be 4 sup. bits MOVNE R11,R10,LSL #8 ; bbggrr00 ANDNE R10,R10,#&0F000000 ; 0s000000 ORRNE R11,R11,R10,LSR #20 ; bbggrrs0 STRNE R11,[R2],#4 TST R7,#PV_BR_WantSecond BEQ %FT60 ; have to use a branch here - another TST coming up LDR R10,[WsPtr,#SecPalAddr] LDR R10,[R10,LR,LSL#2] ; xsbbggrr MOV R11,R10,LSL #8 ; bbggrr00 ANDNE R10,R10,#&0F000000 ; 0s000000 ORR R11,R11,R10,LSR #20 ; bbggrrs0 TST R7,#PV_BR_TwoLists STREQ R11,[R2],#4 STRNE R11,[R3],#4 60 ADD R9,R9,#1 CMP R9,R1 BCC %BT30 50 MOV R4,#0 Pull "R0-R3,R6-R11,PC" ; return addr already stacked ; ***************************************************************************** ; ; 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 bits 4-7 ; R3 = second flash setting (BBGGRRS0), supremacy bits 4-7 ; PV_ReadPalette ROUT Push "r10,r11" LDR r10, [WsPtr, #DisplayNColour] ; logical colours in this mode -1 TEQ r10, #63 ; if bodgy 256 colour mode MOVEQ r10, #255 ; then use AND mask of 255 TEQ r1, #24 ; is it reading border palette MOVEQ r11, #&100 ; 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 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, #&100 ; set up correct index 10 ; note no need to fudge 256-colour modes, since we have the correct full 256 entry palette ; bjga: changed to handle 4 bits of supremacy (BulkRead already does) LDR r10, [WsPtr, #FirPalAddr] LDR r10, [r10, r11, LSL #2] ; r10 := 1st XSBBGGRR MOV r2, r10, LSL #8 ; r2 := 1st BBGGRR00 AND r10, r10, #&0F000000 ; r10 := 1st 0S000000 ORR r2, r2, r10, LSR #20 ; r2 := 1st BBGGRRS0 LDR r10, [WsPtr, #SecPalAddr] LDR r10, [r10, r11, LSL #2] ; r10 := 2nd XSBBGGRR MOV r3, r10, LSL #8 ; r3 := 2nd BBGGRR00 AND r10, r10, #&0F000000 ; r10 := 2nd 0S000000 ORR r3, r3, r10, LSR #20 ; r3 := 2nd BBGGRRS0 99 MOV r4, #0 Pull "r10, r11, pc" ; ***************************************************************************** ; ; PV_1stFlashState - PaletteV routine to set first flash state ; PV_1stFlashState ROUT Push "r0-r3" LDR r0, [WsPtr, #FirPalAddr] DoR0Flash MOV r1, #256 ; just update normal palette DoAllUpdate ADD r0, r0, #(256+1+3)*4*2 ; move pointer to physical palette copy ADD r1, r0, r1, LSL #2 MOV r2, #VIDC MOV r3, #VIDCPalAddress + 0 ; initialise palette address to 0 PHPSEI ; disable IRQs round this bit STR r3, [r2] LDRB r4, [WsPtr, #ScreenBlankFlag] TEQ r4, #0 ; if unblanked, leave all bits alone MOVNE r4, #&0FFFFFFF ; blanked, knock off all bits, except register bits 10 LDR r3, [r0], #4 BIC r3, r3, r4 [ LCDSupport Push "r6,r7,r14" MOV r6, r3 MOV r7, r2 BL Poke_VIDC Pull "r6,r7,r14" | STR r3, [r2] ] TEQ r0, r1 BNE %BT10 PLP MOV r4, #0 Pull "r0-r3, pc" ; ***************************************************************************** ; ; PV_2ndFlashState - PaletteV routine to set second flash state ; PV_2ndFlashState ROUT Push "r0-r3" LDR r0, [WsPtr, #SecPalAddr] 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 LDRCS r0, [WsPtr, #FirPalAddr] ; FlashState = 1 => 1st state, 0 => 2nd state LDRCC r0, [WsPtr, #SecPalAddr] MOV r1, #260 ; update normal palette and border/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 MOV r4, #VIDC LDRB r0, [WsPtr, #ScreenBlankDPMSState] BCC %FT50 ; blanking TST r0, #1 ; if hsyncs should be off, LDRNE r1, =HorizSyncWidth + ((1:SHL:14) -1) ; maximum value in h.sync width register STRNE r1, [r4] TST r0, #2 ; if vsyncs should be off, LDRNE r1, =VertiSyncWidth + ((1:SHL:13) -1) ; maximum value in v.sync width register STRNE r1, [r4] LDR r1, [WsPtr, #VIDCExternalSoftCopy] AND r0, r0, #3 TEQ r0, #3 ; if both syncs off BICEQ r1, r1, #Ext_HSYNCbits :OR: Ext_VSYNCbits ORREQ r1, r1, #Ext_InvertHSYNC :OR: Ext_InvertVSYNC ; set sync signals to low (less power) BIC r1, r1, #Ext_DACsOn ; turn off the DACs STR r1, [r4] MOV r0, #(0 :SHL: 10) :OR: (3 :SHL: 8) ; blank: video DMA off, continuous refresh B %FT60 50 ; unblanking LDR r1, [WsPtr, #VIDCExternalSoftCopy] STR r1, [r4] ; restore DACs and sync type TST r0, #1 ; if hsyncs were turned off, LDRNE r1, [WsPtr, #HSWRSoftCopy] ; then restore from soft copy STRNE r1, [r4] TST r0, #2 ; if vsyncs were turned off, LDRNE r1, [WsPtr, #VSWRSoftCopy] ; then restore from soft copy STRNE r1, [r4] MOV r0, #(1 :SHL: 10) :OR: (0 :SHL: 8) ; unblank: video DMA on, no refresh 60 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" ; ***************************************************************************** ; ; PV_GammaCorrect - Update gamma correction tables ; ; in: r0 -> red table ; r1 -> green table ; r2 -> blue table ; ; out: r4 = 0 PV_GammaCorrect ROUT Push "r0-r3,r5-r8" LDR r4, [WsPtr, #FirPalAddr] ADD r4, r4, #(256+1+3)*4*4 ; point to gamma tables ADD r3, r4, #256 10 LDR lr, [r0], #4 STR lr, [r4], #4 TEQ r4, r3 BNE %BT10 ADD r3, r4, #256 20 LDR lr, [r1], #4 STR lr, [r4], #4 TEQ r4, r3 BNE %BT20 ADD r3, r4, #256 30 LDR lr, [r2], #4 STR lr, [r4], #4 TEQ r4, r3 BNE %BT30 ; now go through the logical palette, recomputing the physical from it using the new tables SUB r0, r4, #3*256 ; r0 -> red table SUB r1, r4, #2*256 ; r1 -> green table SUB r2, r4, #1*256 ; r2 -> blue table LDR r4, [WsPtr, #FirPalAddr] ; r4 -> start of logical palette ADD r5, r4, #260*4*2 ; r5 -> start of physical palette MOV r6, r5 ; r6 = r5 = end of logical palette 40 LDR r7, [r4], #4 ; get word AND r8, r7, #&FF ; r8 = red LDRB r8, [r0, r8] ; r8 = gamma(red) AND lr, r7, #&FF00 ; lr = green << 8 LDRB lr, [r1, lr, LSR #8] ; lr = gamma(green) ORR r8, r8, lr, LSL #8 ; r8 = gamma(red) + (gamma(green)<<8) AND lr, r7, #&FF0000 ; lr = blue << 16 LDRB lr, [r2, lr, LSR #16] ; lr = gamma(blue) ORR r8, r8, lr, LSL #16 ; r8 = gamma(red) + (gamma(green)<<8) + (gamma(blue)<<16) AND lr, r7, #&FF000000 ; lr = other bits ORR r8, r8, lr ; r8 = gamma-corrected combined value STR r8, [r5], #4 ; store word TEQ r4, r6 BNE %BT40 BL UpdateAllPalette MOV r4, #0 Pull "r0-r3,r5-r8, pc" [ LCDInvert ; ***************************************************************************** ; ; PV_LCDInvert - Invert the LCD palette ; ; in: r0 = inversion state to use (0=uninverted, 1=inverted) ; ; out: r4 = 0 PV_LCDInvert ROUT MOV r4, #0 STRB r0, [r4, #LCD_Inverted] BL UpdateAllPalette MOV r4, #0 Pull "pc" ] [ StorkPowerSave ; ***************************************************************************** PV_VIDCDisable ROUT Push "r2" MOV r4, #VIDC LDR r2, =&C0000003 ;dac off, ereg set to external LUT STR r2, [r4] LDR r2, =&D0004000 ;Vclk off, Pcomp=0 STR r2, [r4] LDR r2, =&E0004049 ;PoDown, Hclk STR r2, [r4] MOV r4, #0 Pull "r2, pc" ; ***************************************************************************** PV_VIDCRestore ROUT Push "r2,r3,R8" MOV r3, #VIDC LDR r2, [WsPtr, #VIDCControlSoftCopy] ;restore from soft copy STR r2, [r3] LDR r2, [WsPtr, #VIDCExternalSoftCopy] ;restore from soft copy STR r2, [r3] LDR r2, [WsPtr, #VIDCFSynSoftCopy] ;restore from soft copy [ 1 = 1 LDR R8, =FSyn_ResetValue ; set test bits on, and r > v STR R8, [R3] ; we may need some delay in here... LDR R8, =FSyn_ClearR :OR: FSyn_ClearV :OR: FSyn_ForceLow :OR: FSyn_ForceHigh ORR R2, R2, R8 BIC R2, R2, #FSyn_ForceHigh ; force test bits on, except this one STR R2, [R3] ; we may also need some delay in here... BIC R2, R2, R8 ; remove test bits ] STR r2, [r3] MOV r4, #0 Pull "r2,r3,R8, pc" ] ; ***************************************************************************** ; ; Poke_VIDC ; ; in: r6 = CRT palette VIDC entry &AeBbGgRr (where A is the VIDC register 'address') ; r7 = address to poke ; ; out: all registers preserved ; ; NOTE: If LCD_Active in the KernelWS != 0, the value bunged into VIDC is the ; value required by the greyscaler to approximate the luminance of r6 on entry. Poke_VIDC EntryS "r0-r4" [ :LNOT: STB MOV r0, #0 LDRB r0, [r0, #LCD_Active] CMP r0, #0 STREQ r6,[r7] ;Ho hum, it's a CRT, so no mucking about EXITS EQ ] MOV r0, #&0f AND r4, r0, r6, LSR #28 ;r4 = VIDC register 'address' (in bottom 4 bits) MOV r0, #&ff AND r2, r0, r6, LSR #16 ;r2 = blue AND r1, r0, r6, LSR #8 ;r1 = green ADD r2, r2, r1, LSL #2 ;r2 = 4green + blue AND r1, r0, r6 ;r1 = red ADD r2, r2, r1, LSL #1 ;r2 = 4green + 2red + blue - _Very_ approx CIE weightings! [ :LNOT: STB MOV r0, #0 LDRB r0, [r0, #LCD_Inverted] CMP r0, #0 MOVNE r0, #255 RSBNE r0, r0, r0, LSL #3 ;Move 1785 into R0 RSBNE r2, r2, r0 ] ADR r3, NewPalTab ; perform binary chop using table (lifted from PortableA4 module, with added comments) LDR r0, [r3, #8*4] ;read the middle table value CMP r2, r0 ADDCC r1, r3, #0*4 ADDCS r1, r3, #8*4 LDR r0, [r1, #4*4] CMP r2, r0 ADDCS r1, r1, #4*4 LDR r0, [r1, #2*4] CMP r2, r0 ADDCS r1, r1, #2*4 LDR r0, [r1, #1*4] CMP r2, r0 ADDCS r1, r1, #1*4 SUB r3, r1, r3 MOV r2, r3, LSR #2 ;R2 is now in the range 0-14 CMP r2, #7 ADDGT r2, r2, #1 ;Now R2 in range 0-7,9-15 AND r2, r2, #&0f ;Just to be on the safe side.... ORR r2, r2, r2, LSL #8 ORR r2, r2, r2, LSL #16 ;Now &0x0x0x0x (where x is 0-7,9-15) ORR r2, r2, r4, LSL #28 ;Now &Ax0x0x0x (A is the VIDC address) STR r2, [r7] ;And into the VIDC we go! EXITS NewPalTab DCD 0, 119, 238, 357, 476, 595, 714, 833, 953, 1072, 1191, 1310, 1429, 1548, 1667, -1 END