; Copyright 2000 Pace Micro Technology plc ; ; 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. ; ; vdupalxx ; mjs Sep 2000 ; ; Palette programming for generic video controller, delegating h/w ; specifics to HAL calls. Think of any 'VIDC' references here as for a ; generic video controller. ; Format of a 32-bit palette entry in soft palette tables (eg. FirPalAddr) and ; for calls to HAL is: ; ; BBGGRRSS ; ; ie. 8-8-8-8 bits for Blue-Green-Red-Supremacy ; 'Supremacy' is expected to be 0=solid .. 255=transparent ; [pre-HAL, Medusa kernels used a soft palette format of 0SBBGGRR, being VIDC20-ish] ; ; soft palette tables are indexed by 0..259, where: ; ; 0..255 are normal (display) palette entries ; type 0, index 0..255 for HAL calls ; 256 is border entry ; type 1, index 0 for HAL calls ; 257..259 are pointer palette entries ; type 2, index 1..3 for HAL calls (HAL index 0 assumed to ; correspond to transparent, and not used) ; ***************************************************************************** ; 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 ASSERT paletteV_LCDInvert = 10 ASSERT paletteV_VIDCDisable = 12 ASSERT paletteV_VIDCRestore = 13 ASSERT paletteV_ReadGammaCorrection = 14 ASSERT paletteV_ReadSupremacyTransfer = 15 ASSERT paletteV_SetSupremacyTransfer = 16 MOSPaletteV ROUT CMP r4, #16 ADDLS pc, pc, r4, LSL #2 MOV pc, lr ; reason code not known, so pass it on MOV pc, lr ; 0 B PV_ReadPalette ; 1 B PV_SetPalette ; 2 B PV_1stFlashState ; 3 B PV_2ndFlashState ; 4 B PV_SetDefaultPalette ; 5 B PV_BlankScreen ; 6 B PV_BulkRead ; 7 B PV_BulkWrite ; 8 B PV_GammaCorrect ; 9 MOV pc, lr ; 10 (was PV_LCDInvert) MOV pc, lr ; 11 B PV_VIDCDisable ; 12 B PV_VIDCRestore ; 13 B PV_ReadGammaCorrect ; 22 B PV_ReadSupremacyXfer ; 23 B PV_SetSupremacyXfer ; 24 ; ***************************************************************************** PV_SetDefaultPalette ROUT Push "r0-r3,r5-r9" LDR r0, [WsPtr, #DisplayModeFlags] TST r0, #ModeFlag_GreyscalePalette BNE %FT30 05 BL GetPalIndex ; the new index 0-6 ADR r1, paldptab LDR r2, [r1, r6, LSL #2] ; offset from r1 to start of table ADD r6, r6, #1 ; point to next item LDR r5, [r1, r6, LSL #2] ; offset from r1 to end of table +1 TST r2, #&80000000 ; if bit 31 set, it's a routine BIC r2, r2, #&80000000 ; clear that flag ADD r2, r2, r1 ; r2 -> start of table MOVNE pc, r2 ; or call routine BIC r5, r5, #&80000000 ; clear routine flag 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..255 are initialised 15 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 30 ; Check that we know how to generate a greyscale palette for this mode ASSERT ModeFlag_DataFormatFamily_RGB = 0 TST r0, #ModeFlag_DataFormatFamily_Mask ; Must be RGB BNE %BT05 LDR r6, [WsPtr, #DisplayNColour] CMP r6, #63 ; not possible in VIDC10 256 colour BEQ %BT05 LDR r0, [WsPtr, #Log2BPP] CMP r0, #3 ; Must be <= 256 colour CMPLS r6, #255 ; Check both values to be sure BHI %BT05 MOV r1, #3 MOV r2, #0 ADR r5, greyscale_mult LDR r5, [r5, r0, LSL #2] MOV r0, #0 35 MUL r2, r0, r5 BL UpdateNormalColour SUBS r6, r6, #1 ADD r0, r0, #1 BGE %BT35 B %BT15 FinishDefault MOV r2, #0 ; set border to black (and setup colours 2,3 in BBC gap modes) BL BorderInitEntry ; Ensure software pointer palette is refereshed LDR r4, [WsPtr, #GraphicsVFeatures] TST r4, #GVDisplayFeature_HardwarePointer LDREQB r4, [WsPtr, #SWP_Callback] TEQEQ r4, #0 BLEQ RegisterSoftwarePointerCallback MOV r4, #0 ; indicate PaletteV operation complete Pull "r0-r3,r5-r9,pc" ; restore registers and claim vector LTORG greyscale_mult DCD &FFFFFF00 ; 1bpp DCD &55555500 ; 2bpp DCD &11111100 ; 4bpp DCD &01010100 ; 8bpp ; ***************************************************************************** ; 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 & (paldatLin-paldptab) :OR: &80000000 ; 16bpp, 32bpp, 256 greys - use routine & 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 ; 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 ; Linear / greyscale palette or gamma table paldatLin ROUT ADR r5, paldatLintab 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 paldatLintab [ DefaultSupremacy & &01010101 ; palette bit 0 & &02020202 ; 1 & &04040404 ; 2 & &08080808 ; 3 & &10101010 ; 4 & &20202020 ; 5 & &40404040 ; 6 & &80808080 ; 7 | & &01010100 ; palette bit 0 & &02020200 ; 1 & &04040400 ; 2 & &08080800 ; 3 & &10101000 ; 4 & &20202000 ; 5 & &40404000 ; 6 & &80808000 ; 7 ] 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 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+4 LDREQ R2,[R9],#4 BLEQ UpdateNormalColour TEQ R7,#16 TEQNE R7,#18 MOVEQ R0,R11 MOVEQ R1,#2+4 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 ; Update greyscale palette mode flag as appropriate LDR r2, [WsPtr, #DisplayNColour] CMP r7, #19 CMPLO r2, #256 BHS %FT90 PHPSEI LDR r7, [WsPtr, #DisplayModeFlags] CMP r2, #63 LDR r5, [WsPtr, #FirPalAddr] MOVEQ r2, #255 LDR r6, [WsPtr, #SecPalAddr] BIC r7, r7, #ModeFlag_GreyscalePalette 30 LDR r8, [r5], #4 LDR r9, [r6], #4 EOR r8, r8, r8, LSL #8 EOR r9, r9, r9, LSL #8 CMP r8, #&10000 CMPLO r9, #&10000 BHS %FT40 SUBS r2, r2, #1 BGE %BT30 ORR r7, r7, #ModeFlag_GreyscalePalette 40 STR r7, [WsPtr, #DisplayModeFlags] ; Update live ModeFlags if not redirected to sprite LDR r8, [WsPtr, #VduSprite] TEQ r8, #0 STREQ r7, [WsPtr, #ModeFlags] PLP 90 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 = BBGGRRSS ; 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 LDR r4, [WsPtr, #GraphicsVFeatures] TST r4, #GVDisplayFeature_HardwarePointer LDREQB r4, [WsPtr, #SWP_Callback] TEQEQ r4, #0 LDREQB r4, [WsPtr, #DisplayLog2BPP] TSTEQ r4, #&FC ; Callback only needed here for <=8bpp BLEQ RegisterSoftwarePointerCallback 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, #256 ; 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, #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 "pc" PointerColour ROUT Push "LR" ANDS r0, r0, #3 ; force pointer colour number in range 1..3 BEQ %FT10 ; zero is invalid ADD r0, r0, #256 ; index in range 257..259 MOV r1, #3 BL UpdateSettingAndVIDC 10 LDR r4, [WsPtr, #GraphicsVFeatures] TST r4, #GVDisplayFeature_HardwarePointer LDREQB r4, [WsPtr, #SWP_Callback] TEQEQ r4, #0 BLEQ RegisterSoftwarePointerCallback MOV r4, #0 ; indicate successful PaletteV op Pull "pc" ; UpdateSettingStraightRGB ; ; in: r0 = index (0..255 for normal, 256 for border, 257..259 for pointer) ; r1 = bit mask of which flash states to update (bit 0 set => 1st, bit 1 set => 2nd) ; bit 2 set to suppress greyscale palette check ; 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 (s) in 1st colour MOVNE r5, #&FF ; r5 = 000000SS AND r6, r3, #&FF0 ; r6 = 00000BG0 ORR r5, r5, r6, LSL #16 ; r5 = 0BG000SS AND r6, r3, #&0FF ; r6 = 000000GR ORR r5, r5, r6, LSL #12 ; r5 = 0BGGR0SS AND r6, r3, #&00F ; r6 = 0000000R ORR r5, r5, r6, LSL #8 ; r5 = 0BGGRRSS AND r6, r3, #&F00 ; r6 = 00000B00 ORR r3, r5, r6, LSL #20 ; r3 = BBGGRRSS ANDS r5, r4, #1 :SHL: 12 ; get supremacy bit (s) in EOR mask MOVNE r5, #&FF ; r5 = 000000SS AND r6, r4, #&FF0 ; r6 = 00000BG0 ORR r5, r5, r6, LSL #16 ; r5 = 0BG000SS AND r6, r4, #&0FF ; r6 = 000000GR ORR r5, r5, r6, LSL #12 ; r5 = 0BGGR0SS AND r6, r4, #&00F ; r6 = 0000000R ORR r5, r5, r6, LSL #8 ; r5 = 0BGGRRSS AND r6, r4, #&F00 ; r6 = 00000B00 ORR r4, r5, r6, LSL #20 ; r4 = BBGGRRSS B UpdateSettingCommon ; UpdateSettingAndVIDC ; ; in: r0 = index (0..255 for normal, 256 for border, 257..259 for pointer) ; r1 = bit mask of which flash states to update (bit 0 set => 1st, bit 1 set => 2nd) ; bit 2 set to suppress greyscale palette check ; r2 = BBGGRRSS ; ; out: r0, r1, r2 preserved ; r3, r4 corrupted ; UpdateSettingAndVIDC ALTENTRY MOV r3, r2 MOV r4, #0 ; indicate no EORing between parts ; ... and drop thru to ; UpdateSettingCommon ; ; in: r0 = index (0..255 for normal, 256 for border, 257..259 for pointer) ; r1 = bit mask of which flash states to update (bit 0 set => 1st, bit 1 set => 2nd) ; bit 2 set to suppress greyscale palette check ; r3 = BBGGRRSS ; r4 = BBGGRRSS to EOR with to go from 1st to 2nd flash state ; r2, r5, r6, r7, lr stacked ; ; out: r0, r1, r2, r4 preserved ; r3 corrupted ; UpdateSettingCommon ROUT PHPSEI ; protect against IRQs Push "r8, r9" LDRB r5, [WsPtr, #ScreenBlankFlag] TEQ r5, #0 MOVNE r5, #&FFFFFFFF ; 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 LDR r2, [WsPtr, #FirPalAddr] ADD r8, r2, #Pal_RTable-Pal_LogFirst ; r8 -> rgb transfer tables STR r3, [r2, r0, LSL #2]! ; store in logical colour and write back pointer AND r6, r3, #&0000FF00 ; r6 = red << 8 LDRB r6, [r8, r6, LSR #8] ; r6 = gamma(red) ADD r8, r8, #&100 ; r8 -> green transfer AND r9, r3, #&00FF0000 ; r9 = green << 16 LDRB r9, [r8, r9, LSR #16] ; 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, #&FF000000 ; r9 = blue << 24 LDRB r9, [r8, r9, LSR #24] ; r9 = gamma(blue) ORR r6, r6, r9, LSL #16 ; r6 = gamma(red) + (gamma(green)<<8) + (gamma(blue)<<16) ADD r8, r8, #&100 ; r8 -> supremacy transfer AND r9, r3, #&000000FF ; r9 = supremacy LDRB r9, [r8, r9] ; r9 = transfer(supremacy) ORR r6, r9, r6, LSL #8 ; r6 = gamma(rgb) + transfer(supremacy) STR r6, [r2, #Pal_PhysFirst-Pal_LogFirst] ; store in physical copy BCC %FT10 ; only hit hardware if flash state = first ;;; mjs ;;; Pre HAL code had possible LCD greyscale munging, not supported in interim s.vduhint code ;;; Push "r0-r2,r4,lr" LDR r4, [WsPtr, #CurrentGraphicsVDriver] MOV r4, r4, LSL #24 ORR r4, r4, #GraphicsV_WritePaletteEntry BIC r1, r6, r5 ; r1 = palette colour after knocking out blanking bits AND r2, r0, #255 ; reduced index (0..255 normal, 0 border, 1..3 pointer) CMP r0, #256 ; HI if pointer MOVLS r0, r0, LSR #8 ; type 0=normal, 1=border MOVHI r0, #2 ; type 2=pointer BL CallGraphicsV Pull "r0-r2,r4,lr" 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, #Pal_RTable-Pal_LogSecond ; r8 -> rgb transfer tables STR r3, [r2, r0, LSL #2]! ; store in logical copy and write back AND r6, r3, #&0000FF00 ; r6 = red << 8 LDRB r6, [r8, r6, LSR #8] ; r6 = gamma(red) ADD r8, r8, #&100 ; r8 -> green transfer AND r9, r3, #&00FF0000 ; r9 = green << 16 LDRB r9, [r8, r9, LSR #16] ; 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, #&FF000000 ; r9 = blue << 24 LDRB r9, [r8, r9, LSR #24] ; r9 = gamma(blue) ORR r6, r6, r9, LSL #16 ; r6 = gamma(red) + (gamma(green)<<8) + (gamma(blue)<<16) ADD r8, r8, #&100 ; r8 -> supremacy transfer AND r9, r3, #&000000FF ; r9 = supremacy LDRB r9, [r8, r9] ; r9 = transfer(supremacy) ORR r6, r9, r6, LSL #8 ; r6 = gamma(rgb) + transfer(supremacy) STR r6, [r2, #Pal_PhysSecond-Pal_LogSecond] ; store in physical copy BCS %FT20 ; only hit hardware if flash state = second ;;; mjs ;;; Pre HAL code had possible LCD greyscale munging, not supported in interim s.vduhint code ;;; Push "r0-r2,r4,lr" LDR r4, [WsPtr, #CurrentGraphicsVDriver] MOV r4, r4, LSL #24 ORR r4, r4, #GraphicsV_WritePaletteEntry BIC r1, r6, r5 ; r1 = palette colour after knocking out blanking bits AND r2, r0, #255 ; reduced index (0..255 normal, 0 border, 1..3 pointer) CMP r0, #256 ; HI if pointer MOVLS r0, r0, LSR #8 ; type 0=normal, 1=border MOVHI r0, #2 ; type 2=pointer BL CallGraphicsV Pull "r0-r2,r4,lr" 20 ; Update greyscale palette mode flag as appropriate ; NOTE - relies on r3 being 2nd flash state LDR r2, [WsPtr, #DisplayNColour] CMP r0, #256 CMPLO r2, #256 CMPLO r1, #4 BHS %FT90 EOR r4, r3, r4 ; r4 = 1st flash state, r3 = 2nd EOR r8, r3, r3, LSL #8 EOR r9, r4, r4, LSL #8 TST r1, #1 MOVEQ r9, #0 ; treat unmodified flash states as greyscale - the full check below will sort things out properly if required TST r2, #1 MOVEQ r8, #0 CMP r8, #&10000 CMPLO r9, #&10000 ; LO -> palette potentially greyscale, HS -> definitely not greyscale LDR r7, [WsPtr, #DisplayModeFlags] BICHS r7, r7, #ModeFlag_GreyscalePalette BHS %FT40 TST r7, #ModeFlag_GreyscalePalette BNE %FT90 ; Check the full palette for greyscaleness CMP r2, #63 LDR r5, [WsPtr, #FirPalAddr] MOVEQ r2, #255 LDR r6, [WsPtr, #SecPalAddr] 30 LDR r8, [r5], #4 LDR r9, [r6], #4 EOR r8, r8, r8, LSL #8 EOR r9, r9, r9, LSL #8 CMP r8, #&10000 CMPLO r9, #&10000 BHS %FT90 SUBS r2, r2, #1 BGE %BT30 ORR r7, r7, #ModeFlag_GreyscalePalette 40 STR r7, [WsPtr, #DisplayModeFlags] ; Update live ModeFlags if not redirected to sprite LDR r8, [WsPtr, #VduSprite] TEQ r8, #0 STREQ r7, [WsPtr, #ModeFlags] 90 PLP Pull "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 R11,[R10,LR,LSL#2] ; BBGGRRSS 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 R11,[R10,LR,LSL#2] ; BBGGRRSS 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 (BBGGRRSS) ; R3 = second flash setting (BBGGRRSS) ; 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 LDR r10, [WsPtr, #FirPalAddr] LDR r2, [r10, r11, LSL #2] ; r2 := 1st BBGGRRSS LDR r10, [WsPtr, #SecPalAddr] LDR r3, [r10, r11, LSL #2] ; r3 := 2nd BBGGRRSS 99 MOV r4, #0 Pull "r10, r11, pc" ; ***************************************************************************** ; ; PV_1stFlashState - PaletteV routine to set first flash state ; PV_1stFlashState ROUT Entry "r0-r3" LDRB r1, [WsPtr, #ScreenBlankFlag] TEQ r1, #0 LDREQ r1, [WsPtr, #FirPalAddr] ADDEQ r1, r1, #Pal_PhysFirst - Pal_LogFirst ; move pointer to physical palette copy LDRNE r1, [WsPtr, #BlankPalAddr] DoR0Flash LDR r0, [WsPtr, #DisplayNColour] CMP r0, #256 EXIT HS ; In > 256 colour modes, this is gamma (which shouldn't flash) MOV r0, #0 ; type 0 (normal) MOV r2, #0 ; start at entry 0 MOV r3, #256 ; 256 entries LDR r4, [WsPtr, #CurrentGraphicsVDriver] MOV r4, r4, LSL #24 ORR r4, r4, #GraphicsV_WritePaletteEntries BL CallGraphicsV EXIT ; ***************************************************************************** ; ; PV_2ndFlashState - PaletteV routine to set second flash state ; PV_2ndFlashState ROUT ALTENTRY LDRB r1, [WsPtr, #ScreenBlankFlag] TEQ r1, #0 LDREQ r1, [WsPtr, #SecPalAddr] ADDEQ r1, r1, #Pal_PhysFirst-Pal_LogFirst ; move pointer to physical palette copy LDRNE r1, [WsPtr, #BlankPalAddr] B DoR0Flash ; ***************************************************************************** ; ; UpdateAllPalette - Update all VIDC palette entries ; UpdateAllPalette ROUT Entry "r0-r4, r9-r11" ;sort out which palette to use LDROSB r0, FlashState CMP r0, #1 LDRCS r1, [WsPtr, #FirPalAddr] ; FlashState = 1 => 1st state, 0 => 2nd state LDRCC r1, [WsPtr, #SecPalAddr] ADD r1, r1, #Pal_PhysFirst-Pal_LogFirst ; move pointer to physical palette copy LDRB r10, [WsPtr, #ScreenBlankFlag] TEQ r10, #0 LDRNE r1, [WsPtr, #BlankPalAddr] ; blank palette after all ; ADD r10, r1, #256*4 ; pointer to border colour PHPSEI r11 ; disable IRQs round this bit ;first, the normal colours MOV r0, #0 ; type 0 (normal) MOV r2, #0 ; start at entry 0 MOV r3, #256 ; 256 entries LDR r9, [WsPtr, #CurrentGraphicsVDriver] MOV r9, r9, LSL #24 ORR r4, r9, #GraphicsV_WritePaletteEntries BL CallGraphicsV ;next, border colour LDR r1, [r10] ; border colour MOV r0, #1 ; type 1 MOV r2, #0 ; index 0 ORR r4, r9, #GraphicsV_WritePaletteEntry BL CallGraphicsV ;finally, pointer colours ADD r1, r10, #4 ; pointer to pointer colours (oh yes) MOV r0, #2 ; type 2 MOV r2, #1 ; start at index 1 MOV r3, #3 ; 3 entries ORR r4, r9, #GraphicsV_WritePaletteEntries BL CallGraphicsV ; PLP r11 EXIT ; ***************************************************************************** ; ; 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, r9" LDRB r3, [WsPtr, #ScreenBlankFlag] CMP r0, #1 BHI %FT99 ; just reading TEQ r0, r3 ; changing to same state? BEQ %FT99 ; if so, do nothing AND r0, r0, #1 STRB r0, [WsPtr, #ScreenBlankFlag] ; update new state LDRB r1, [WsPtr, #ScreenBlankDPMSState] AND r1, r1, #3 LDR r4, [WsPtr, #CurrentGraphicsVDriver] MOV r4, r4, LSL #24 ORR r4, r4, #GraphicsV_SetBlank BL CallGraphicsV ; for backward compatibility, show video DMA state in ; MEMC soft copy (DON'T call OS_UpdateMEMC, which would also ; make redundant call to HAL) ; SavePSR r2 LDR r9, =ZeroPage WritePSRc SVC_mode+I_bit+F_bit, r14 LDR r1, [r9, #MEMC_CR_SoftCopy] TEQ r0, #1 BICEQ r1, r1, #(1 :SHL: 10) ORRNE r1, r1, #(1 :SHL: 10) STR r1, [r9, #MEMC_CR_SoftCopy] RestPSR r2 BL UpdateAllPalette ; update all palette, including border + pointer 99 MOV r0, r3 MOV r4, #0 Pull "r1-r3, r9, pc" ; ***************************************************************************** ; ; PV_ReadGammaCorrect - Read gamma correction tables ; ; in: r0 -> red table ; r1 -> green table ; r2 -> blue table ; ; out: r4 = 0 PV_ReadGammaCorrect ROUT Push "r0-r3" LDR r4, [WsPtr, #FirPalAddr] ADD r4, r4, #Pal_RTable-Pal_LogFirst; point to gamma tables ADD r3, r4, #256 10 LDR lr, [r4], #4 STR lr, [r0], #4 TEQ r4, r3 BNE %BT10 ASSERT Pal_GTable = Pal_RTable+256 ADD r3, r4, #256 20 LDR lr, [r4], #4 STR lr, [r1], #4 TEQ r4, r3 BNE %BT20 ASSERT Pal_BTable = Pal_GTable+256 ADD r3, r4, #256 30 LDR lr, [r4], #4 STR lr, [r2], #4 TEQ r4, r3 BNE %BT30 MOV r4, #0 Pull "r0-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" LDR r4, [WsPtr, #FirPalAddr] ADD r4, r4, #Pal_RTable-Pal_LogFirst; point to gamma tables ADD r3, r4, #256 10 LDR lr, [r0], #4 STR lr, [r4], #4 TEQ r4, r3 BNE %BT10 ASSERT Pal_GTable = Pal_RTable+256 ADD r3, r4, #256 20 LDR lr, [r1], #4 STR lr, [r4], #4 TEQ r4, r3 BNE %BT20 ASSERT Pal_BTable = Pal_GTable+256 ADD r3, r4, #256 30 LDR lr, [r2], #4 STR lr, [r4], #4 TEQ r4, r3 BNE %BT30 BL RecomputeLogicalPalette MOV r4, #0 Pull "r0-r3, pc" ; go through the logical palette, recomputing the physical from it using the new tables ; ; out: r0-r4 corrupted RecomputeLogicalPalette ROUT Push "r5-r8, lr" LDR r4, [WsPtr, #FirPalAddr] ; r4 -> start of logical palette ADD r5, r4, #Pal_PhysFirst-Pal_LogFirst ; r5 -> start of physical palette MOV r6, r5 ; r6 = r5 = end of logical palette ADD r0, r4, #Pal_RTable-Pal_LogFirst; r0 -> red table ADD r1, r4, #Pal_GTable-Pal_LogFirst; r1 -> green table ADD r2, r4, #Pal_BTable-Pal_LogFirst; r2 -> blue table ADD r3, r4, #Pal_STable-Pal_LogFirst; r3 -> supremacy table 40 LDR r7, [r4], #4 ; get word AND r8, r7, #&0000FF00 ; r8 = red << 8 LDRB r8, [r0, r8, LSR #8] ; r8 = gamma(red) AND lr, r7, #&00FF0000 ; lr = green << 16 LDRB lr, [r1, lr, LSR #16] ; lr = gamma(green) ORR r8, r8, lr, LSL #8 ; r8 = gamma(red) + (gamma(green)<<8) AND lr, r7, #&FF000000 ; lr = blue << 24 LDRB lr, [r2, lr, LSR #24] ; lr = gamma(blue) ORR r8, r8, lr, LSL #16 ; r8 = gamma(red) + (gamma(green)<<8) + (gamma(blue)<<16) AND lr, r7, #&000000FF ; lr = supremacy LDRB lr, [r3, lr] ; lr = transfer(supremacy) ORR r8, lr, r8, LSL #8 ; r8 = gamma-corrected BBGGRRSS value STR r8, [r5], #4 ; store word TEQ r4, r6 BNE %BT40 BL UpdateAllPalette Pull "r5-r8, pc" ; ***************************************************************************** ; ; PV_ReadSupremacyXfer - Read supremacy transfer table ; ; in: r0 -> supremacy table ; ; out: r4 = 0 PV_ReadSupremacyXfer ROUT Push "r0,r3" LDR r4, [WsPtr, #FirPalAddr] ADD r4, r4, #Pal_STable-Pal_LogFirst; point to supremacy table ADD r3, r4, #256 10 LDR lr, [r4], #4 STR lr, [r0], #4 TEQ r4, r3 BNE %BT10 MOV r4, #0 Pull "r0,r3, pc" ; ***************************************************************************** ; ; PV_SetSupremacyXfer - Read supremacy transfer table ; ; in: r0 -> supremacy table ; ; out: r4 = 0 PV_SetSupremacyXfer ROUT Push "r0-r3" LDR r4, [WsPtr, #FirPalAddr] ADD r4, r4, #Pal_STable-Pal_LogFirst; point to supremacy table ADD r3, r4, #256 10 LDR lr, [r0], #4 STR lr, [r4], #4 TEQ r4, r3 BNE %BT10 BL RecomputeLogicalPalette MOV r4, #0 Pull "r0-r3, pc" ; ***************************************************************************** PV_VIDCDisable ROUT Push "r0-r3, r9, r12" MOV r0, #1 AddressHAL CallHAL HAL_VideoSetPowerSave MOV r4, #0 Pull "r0-r3, r9, r12, pc" ; ***************************************************************************** PV_VIDCRestore ROUT Push "r0-r3, r9, r12" MOV r0, #0 AddressHAL CallHAL HAL_VideoSetPowerSave MOV r4, #0 Pull "r0-r3, r9, r12, pc" END