; 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.
;
; > VduPalette
;
; ARTHUR OPERATING SYSTEM - Vdu Drivers
; =======================
;
; Vdu driver code - Palette setting (VIDC independent parts)
;
; *****************************************************************************

; Routines above PaletteV
; -----------------------

; *****************************************************************************
;
;       PalInit - Restore default palette for the displayed mode
;
; out:  R6 is preserved (may contain CursorFlags)
;

PalInit ROUT
        MOV     r4, #paletteV_SetDefaultPalette
        B       CallPaletteV

; *****************************************************************************
;
;       UnblankScreen - Unblank screen (called on mode change)
;

UnblankScreen ROUT
        MOV     r0, #0
        MOV     r4, #paletteV_BlankScreen
        B       CallPaletteV

; *****************************************************************************
;
;       DoSetPalette - Entry point for OSWORD 12 (program palette)
;
; in:   R1 -> Control block
;       [R1, #0] = logical colour
;       [R1, #1] = physical colour or action
;       [R1, #2] = red
;       [R1, #3] = green
;       [R1, #4] = blue
;
;       R12 -> VDUWS
;
;       R0-R4, R11, R12 may be corrupted
;
;
DoSetPalette
        Push    "R5-R10,R14"
        BL      SetPal
        Pull    "R5-R10,PC"

; *****************************************************************************
;
;       DC3 - Entry point for VDU 19 (program palette)
;
; in:   QQ+0..QQ+4 contain the parameters in the same format as OSWORD
;

DC3     ROUT
        ADD     R1, WsPtr, #QQ          ; Point R1 at the queued data
                                        ; and drop thru to Palette OSWORD code
SetPal  EntryS
        LDR     R6, [WsPtr, #DisplayModeFlags]
        TST     R6, #ModeFlag_Teletext  ; if teletext mode
        EXITS   NE                      ; then ignore VDU 19

; Now we must check for BBC style colours (VDU 19,n,0..15,...) and map these onto
; 16 or (17 and 18)

        MOV     lr, r1
        LDRB    r0, [lr, #0]            ; r0 = logical colour
        LDRB    r1, [lr, #1]
        ANDS    r2, r1, #&80
        MOVNE   r2, #&FF                ; r2 = supremacy (&00 or &FF)
        BIC     r1, r1, #&80            ; r1 = type of colour
        CMP     r1, #16                 ; r1 < 16 => BBC style colour
        BCS     %FT10

        TST     r1, #1                  ; bit 0 set => red full on
        ORRNE   r2, r2, #&0000FF00
        TST     r1, #2                  ; bit 1 set => green full on
        ORRNE   r2, r2, #&00FF0000
        TST     r1, #4                  ; bit 2 set => blue full on
        ORRNE   r2, r2, #&FF000000

        BL      GetPalIndex
        CMP     r6, #3                  ; only flash colours if PalIndex = 0, 1 or 2
        BICCS   r1, r1, #8

        TST     r1, #8
        MOVEQ   r1, #16
        BEQ     %FT20                   ; not a flashing colour, so just set it once

        MOV     r1, #17                 ; set first flash colour
        BL      CallSetPalette
        MVN     r2, r2                  ; then toggle all bits of R, G and B
        EOR     r2, r2, #&FF            ; (don't toggle supremacy)
        MOV     r1, #18                 ; set second flash colour
        B       %FT20

10
      [ NoARMv6 :LOR: NoUnaligned
        LDRB    r3, [lr, #2]            ; r3 = red
        ORR     r2, r2, r3, LSL #8      ; r2 = &0000RRSS
        LDRB    r3, [lr, #3]            ; r3 = green
        ORR     r2, r2, r3, LSL #16     ; r2 = &00GGRRSS
        LDRB    r3, [lr, #4]            ; r3 = blue
        ORR     r2, r2, r3, LSL #24     ; r2 = &BBGGRRSS
      |
        ; Use unaligned load from ARMv6
        LDR     r3, [lr, #2]            ; r3 = &??BBGGRR
        ORR     r2, r2, r3, LSL #8      ; r2 = &BBGGRRSS
      ]
20
        BL      CallSetPalette
        EXITS


CallSetPalette
        MOV     r4, #paletteV_Set
CallPaletteV
        EntryS  r9
        MOV     r9, #PaletteV
        SWI     XOS_CallAVector
        EXITS


; *****************************************************************************
;
;       GetPalIndex - return index of default palette, for VDU hardware
;
;
;       out: R6 = palette index
;            R3 corrupt
;
GetPalIndex ROUT
        ; Normally maps to log2bpp
        LDRB    R6, [WsPtr, #DisplayLog2BPP]
        CMP     R6, #4
        MOVHI   R6, #4
        MOVHS   PC, LR
        ; BBC gap modes run at lower logical BPP than physical BPP, so palette index needs adjusting too
        LDR     R3, [WsPtr, #DisplayModeFlags]
        TEQ     R6, #0
        TSTNE   R3, #ModeFlag_BBCGapMode
        SUBNE   R6, R6, #1
        ; Hi-res mono & (<=8bpp) teletext have special ones too
        TST     R3, #ModeFlag_Teletext
        MOVNE   R6, #5
        TST     R3, #ModeFlag_HiResMono
        MOVNE   R6, #6
        MOV     PC, LR


; *****************************************************************************
;
;       SWIReadPalette - SWI ReadPalette handler
;
; in:   R0 = logical colour
;       R1 = 16 (read normal colour)
;            24 (read border colour)
;            25 (read cursor colour)
;
; out:  R2 = first flash setting   (B0G0R0PP), supremacy bit 7
;       R3 = second flash setting  (B0G0R0PP), supremacy bit 7
;       R10-R12 corrupted (preserved by Sam), all others preserved
;

SWIReadPalette Entry "r4"
        VDWS    WsPtr
        MOV     r4, #paletteV_Read
        BL      CallPaletteV
        BIC     r2, r2, #&7F            ; knock out any weird bits
        BIC     r3, r3, #&7F
        ORR     r2, r2, r1              ; put in nominal PP field
        ORR     r3, r3, r1
        TEQ     r1, #16                 ; if reading normal colour
        BNE     %FT10
        TEQ     r2, r3                  ; and colours different
        ORRNE   r2, r2, #1              ; then make 1st PP field 17
        ORRNE   r3, r3, #2              ; and 2nd PP field 18
10
        PullEnv
        ExitSWIHandler

; *****************************************************************************
;
;       DoReadPalette - Entry point from OSWORD 11 (read palette)
;
; in:   R1 -> control block
;       [R1, #0] = logical colour to read
;
; out:  [R1, #1] (bits 0..6) = physical colour 0..15 or 16; (bit 7) = supremacy
;       [R1, #2] = red   (in bits 4..7)
;       [R1, #3] = green (-----""-----)
;       [R1, #4] = blue  (-----""-----)
;       R0-R4, R11, R12 can be corrupted
;

DoReadPalette Entry
        MOV     r4, r1                  ; save pointer to block
        LDRB    r0, [r4]                ; r0 = logical colour
        MOV     r1, #16
        SWI     XOS_ReadPalette
        LDROSB  r0, FlashState
        CMP     r0, #1                  ; CS => 1st state, CC => 2nd state
        MOVCC   r2, r3                  ; r2 = current state
      [ NoARMv6 :LOR: NoUnaligned
        MOV     r1, #4
10
        STRB    r2, [r4, #1]!           ; store 4 bytes of data in block, starting R1+1
        MOV     r2, r2, LSR #8
        SUBS    r1, r1, #1
        BNE     %BT10
      |
        ; Use unaligned store from ARMv6
        STR     r2, [r4]
      ]
        EXIT

; *****************************************************************************
;
;       DoFirstFlash - Set palette to first palette setting
;                      Called in either SVC or IRQ mode
;

DoFirstFlash EntryS "r0,r4"
        MOV     r4, #paletteV_1stFlashState
SetFlashState
        MRS     r0, CPSR
        ORR     r1, r0, #I32_bit + SVC_mode     ; to SVC26/32 mode
        MSR     CPSR_c, r1
        Push    "lr"
        BL      CallPaletteV
        Pull    "lr"
        MSR     CPSR_c, r0
        EXITS

; *****************************************************************************
;
;       DoSecondFlash - Set palette to second palette setting
;                       Called in either SVC or IRQ mode
;

DoSecondFlash ALTENTRY
        MOV     r4, #paletteV_2ndFlashState
        B       SetFlashState

        END