;*DDK*************************************************************************/
;
; COPYRIGHT (C) Microsoft Corporation, 1989
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/
        page    ,132
;/*****************************************************************************
;*
;* SOURCE FILE NAME = REALPAL.ASM
;*
;* DESCRIPTIVE NAME = RealizePalette function
;*
;*
;* VERSION      V2.0
;*
;* DATE         08/31/89
;*
;* DESCRIPTION  This file contains the API-level function RealizePalette and   
;*              its supporting subroutines.
;*
;* FUNCTIONS    
;*              
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   12/07/88                     Ron Gery [rong] Wrote first version
;*                                for Windows.
;*   08/31/89                     Author:  Bob Grudem [bobgru]
;*                                Bob Grudem [bobgru] Ported to PM.
;*   09/06/89                     Bob Grudem [bobgru] Ported to PM.
;*   03/23/90                     Bob Grudem [bobgru] Ptr sm02561:  Maintains
;*                                and uses array of hw slot owners.
;*                                Bob Grudem [bobgru] Ptr sm02561:  Cleans out
;*                                hw slots not owned by restricted default
;*                                palette when switching into restricted mode.
;*   04/16/90                     Bob Grudem [bobgru] Ptr hm00952:  Sets
;*                                restricted default palette colors into
;*                                hardware when switching modes, regardless of
;*                                foreground status of palette.
;*   10/05/90                     Bob Grudem [bobgru] Took out
;*                                the adevpalOwner stuff, in
;*                                favor of palette realization id's
;*
;*****************************************************************************/

        .286p
        .xlist

        include cmacros.inc
INCL_DDIMISC            equ                      1
INCL_GRE_BITMAPS        equ                      1
INCL_GPIBITMAPS         equ                      1
INCL_GPILOGCOLORTABLE   equ                      1
INCL_GRE_PALETTE        equ                      1
INCL_DEV                equ                      1
INCL_DDICOMFLAGS        equ                      1
        include pmgre.inc
DINCL_BITMAP            equ                      1
        include driver.inc
        include njmp.mac
        include assert.mac
        include palette.inc
        .list

        CPUMode 386

        ??_out  realpal

        errcode <INV_IN_PATH,INV_IN_AREA>

        externFP        far_enter_driver
        externFP        far_leave_driver

sBegin  Data

globalW npdevpalFore,0                            ;current foreground palette
globalB fbPal,0
globalW cPals,0
globalW idRealization,1

        externD         phwpal                    ;palsup.asm
        externB         devpalDefault            ;palsup.asm
        externB         fbPalMap                 ;palmap.asm
        externB         palsegDefPal             ;palsup.asm

sEnd    Data

sBegin  PalSeg
        assumes cs,PalSeg

        externW PalSegData

ifdef FIREWALLS
        externNP        validate_hdevpal
endif
        externNP        SetHWPalette
        externNP        rgb_to_ipc_with_hwpal

;/***************************************************************************
;*
;* FUNCTION NAME = MatchAPal
;*
;* DESCRIPTION   = 
;*
;*     This function maps the logical palette into the hardware palette.
;*     It looks at each color in turn and determines if it exactly matches
;*     a color already there.  If not and space is available, it takes
;*     over a new slot.  If not and space is not available, it assigns
;*     the color to its nearest match.
;*  
;*     Once a palette has been realized in the foreground, its mapping is
;*     saved until the palette data changes.  For subsequent foreground
;*     realizations, the precomputed mapping is used.
;*  
;*   palseg_fs flags:
;*   ----------------
;*   PR_REREALIZE  Will be set for any palette which has changed since the
;*                 last realization (also set for new palettes).
;*  
;*   PR_OVERRIDE_DEFAULTS
;*                 This palette can override the reserved default colors when
;*                 it comes to the foreground.  It will only take these colors
;*                 if needed.
;*  
;*   wForeBack flags for MatchAPal:
;*   ------------------------------
;*   FB_FORE       Realize as foreground.
;*   FB_NEW        Realize from scratch, i.e. match each logical palette
;*                   color with a slot in the hardware palette.
;*   FB_OVERRIDE   Allow the palette to overwrite the default colors.
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES,FLAGS
;*                 Registers Preserved:
;*                       SI,DI,BP,DS
;*                 Calls: 
;*                       SetHWPalette
;*                       rgb_to_ipc_with_hwpal
;*
;* INPUT         = DS = Data 
;* OUTPUT        = AX = number of colors matched (hardware slots changed)
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc   MatchAPal,<NEAR,PUBLIC,NODATA>,<si,di,ds>

        parmW   npdevpal
        parmW   fsType
        parmD   pcclr

        localW  wForeBack
        localW  pStartFill
        localW  LastUsableEntry
        localB  fNotOverwritable
        localW  cCounter
        localW  nPhysChanged                     ; number of changes in physical palette
        localW  nMapChanged                      ; number of color-mapping changes
        localW  nDefaultChanged ; number of default colors reinstated
        localW  cSpread                          ; usMax + 1
        localD  phwpalMine
        localD  pPalSeg
cBegin
        cld
        mov     bx,npdevpal
        devpal? bx,SHORT

;/*
;** Determine some details about the type of palette realization, and
;** manage some flags.
;**
;** if foreground
;** {
;**     ax |= FB_FORE
;**     if palette can override defaults
;**         ax |= FB_OVERRIDE
;**     if PR_REREALIZE
;**         ax |= FB_NEW
;** }
;** clear PR_REREALIZE
;** if PR_CUR_VALID
;**     set PR_PREV_VALID
;** set PR_CUR_VALID
;*/

        les     di,[bx].devpal_pPalSeg
        assumes es,nothing
        mov     cx,es:[di].palseg_fs              ;will use this a lot

        xor     ax,ax                             ;assume background
        test    fsType,RP_FOREGROUND              ;background?
        jz      map_match_the_pal                 ;if yes, must realize it

        or      ax,FB_FORE
        test    cx,PR_OVERRIDE_DEFAULTS
        jz      map_no_default_override
        or      ax,FB_OVERRIDE
map_no_default_override:

        test    cx,PR_REREALIZE                   ;anything new since realized?
        jnz     map_new_realization               ;if yes, must rerealize
        test    cx,PR_BFORE_VALID                 ;foreground indices ok?
        jnz     map_match_the_pal                 ;if yes, use them
map_new_realization:
        or      ax,FB_NEW                          ;new realization
        or      cx,PR_BFORE_VALID                 ;bFore values ok after this

map_match_the_pal:
        test    cx,PR_BCUR_VALID
        jz      map_set_bcur_valid
        or      cx,PR_BPREV_VALID                 ;this is the second realization
map_set_bcur_valid:
        or      cx,PR_BCUR_VALID
        and     cx,not PR_REREALIZE               ;changes assimilated

        mov     es:[di].palseg_fs,cx              ;store new palette status flags
        mov     wForeBack,ax                       ;store MatchAPal directives

;/*
;** We use a global counter to help reduce redundant palette realizations.
;** Each time a new foreground palette is realized (or rerealized after
;** being in the background), the global counter is incremented, and the
;** palette counter is set to the global one.  When a palette is realized
;** in the background, its id is set to the global one.
;**
;** There are certain conditions under which we will not realize the palette,
;** saving a lot of time:
;**
;** 1) If the palette realization id is the same as the global one, and
;**    the palette is being realized in the background.  This indicates that
;**    the palette has already been so realized since the last foreground
;**    realization, so just leave the mapping the way it is.
;**
;** 2) If the palette realization id is the same as the global one, the
;**    palette is being realized in the foreground, but it's already the
;**    foreground palette.  We can leave the mapping the way it is.
;*/

        mov     ax,idRealization
        cmp     ax,[bx].devpal_idRealization
        jne     map_do_it                         ;different id ==> must rerealize
        test    wForeBack,FB_NEW
        jnz     map_do_it                         ;palette changed ==> must rerealize
        test    wForeBack,FB_FORE
        jz      map_no_work                       ;bg, same id ==> then no work
        cmp     npdevpalFore,bx
        jne     map_do_it                         ;fg, same id, already fg ==> no work
map_no_work:
        xor     ax,ax                             ;no mapping changes, *pcclr already 0
        jmp     map_the_end

;/*
;** We have to realize a palette.  Update the realization id(s) and
;** initialize some local variables.
;*/

map_do_it:
        test    wForeBack,FB_FORE
        jz      map_not_fore
        inc     ax
        mov     idRealization,ax
        mov     npdevpalFore,bx                  ;record new foreground
map_not_fore:
        mov     [bx].devpal_idRealization,ax

        xor     ax,ax
        mov     nMapChanged,ax
        mov     nPhysChanged,ax
        mov     nDefaultChanged,ax

        mov     eax,phwpal                        ;save away so we can access when
        mov     phwpalMine,eax                    ;  DS is busy

        les     di,phwpal                         ;ES:DI --> argbWH
        assumes es,nothing

        lds     si,[bx].devpal_pPalSeg           ;DS:SI --> palseg
        assumes ds,nothing
        mov     pPalSeg.lo,si
        mov     pPalSeg.hi,ds

        palSize cx,ds,si
        mov     cSpread,cx
        mov     cCounter,cx
        xor     bx,bx

;/*
;** Update previous indices with current values.   The bPrev field is used
;** by UpdateColors to know how to convert the previously correct screen
;** pels to the currently correct values.
;**
;** CX     =  count of entries in logical palette
;** BX     =  index to first entry in palseg_argb
;** DS:SI --> logical palette (palseg)
;** ES:DI --> hardware palette (argbHW)
;*/

@@:     mov     al,[si+bx].palseg_apalclr.palclr_bCur
        mov     [si+bx].palseg_apalclr.palclr_bPrev,al
        add     bx,SIZE PALCLR
        loop    @B

        test    wForeBack,FB_FORE                ; foreground or background palette?
        njz     match_back_pal

;*/
;** Foreground palette
;**
;** This is the foreground palette, and all of its colors should be realized.
;**
;** If the palette has not been realized yet, match from scratch.
;**
;** If it has been realized, use the foreground indices to re-establish
;** it in the physical palette.  If entries are already properly set, leave
;** them there.
;**
;** DS:SI --> logical palette
;** ES:DI --> physical palette
;*/

match_fore_pal:

;/*
;** Put the default colors into the hardware palette if they have been
;** overridden by some custom palette.  We don't actually check that the
;** colors were really taken over, just that the previous foreground
;** palette could have done it.  If this palette has the authority to
;** override the defaults, mark it in fbPal.
;*/

        mov     ds,PalSegData
        assumes ds,Data
        test    fbPal,PF_DEF_OVERRIDE
        jz      map_check_new_override
        cCall   RealizeDefaultPalette            ;clears PF_DEF_OVERRIDE in fbPal
        mov     es,phwpalMine.hi
        assumes es,nothing
        mov     nDefaultChanged,ax

map_check_new_override:
        test    wForeBack,FB_OVERRIDE
        jz      map_no_override
        or      fbPal,PF_DEF_OVERRIDE
map_no_override:

        lds     si,pPalSeg
        assumes ds,nothing

        cCall   FreeHWPaletteSlots               ;make all nondefault slots available

        test    wForeBack,FB_NEW                 ;need to rematch colors?
        njnz    match_back_pal

;*/
;** Foreground palette has been previously matched, so we know how to
;** put it back in.  Slam it in there.
;**
;** DS:SI --> logical palette (palseg_apalclr)
;** ES:DI --> physical palette (hwpal)
;*/

        assumes ds,nothing
        assumes es,nothing

rerealize_fore_pal:
ifdef FIREWALLS
        push    ax
        push    ds
        mov     ds,PalSegData
        assumes ds,Data
        mov     ax,es
        cmp     ax,phwpalMine.hi
        jne     map_got_a_problem
        cmp     di,phwpalMine.lo
        je      map_no_problem
map_got_a_problem:
        rip     text,<ES:DI != phwpal>
map_no_problem:
        pop     ds
        assumes ds,nothing
        pop     ax
endif

        mov     cx,cSpread
        add     si,palseg_apalclr

slam_foreground_palette_loop:
        mov     bl,[si].palclr_bFore
        cmp     [si].palclr_bCur,bl
        je      map_cur_same_as_fore
        mov     [si].palclr_bCur,bl
        inc     nMapChanged
map_cur_same_as_fore:
        xor     bh,bh
        rgbOff  bx

;/*
;**     If it's an explicit color, set nothing.
;*/

        test    [si].palclr_rgb.rgb2_fcOptions,PC_EXPLICIT
        jnz     get_next_source_data

;/*
;** Check to see if this hardware slot is marked as default. If it is,
;** but the palette is allowed to take over default slots, then let it
;** through, otherwise ignore it.
;*/

        test    es:[di+bx].rgb2_fcOptions,PC_DEFAULT
        jz      map_not_default
        test    wForeBack,FB_OVERRIDE
        jz      get_next_source_data
map_not_default:

;/*
;** Check to see if color is already in physical palette.
;*/

        mov     ax,word ptr [si].palclr_rgb.rgb2_bBlue
        mov     dx,word ptr [si].palclr_rgb.rgb2_bRed
        cmp     ax,word ptr es:[di+bx].rgb2_bBlue
        jne     slam_new_fore_color
        cmp     dl,es:[di+bx].rgb2_bRed
        jne     slam_new_fore_color

;/*
;** Check for change of PC_RESERVED state.
;*/

        push    dx
        and     dh,PC_RESERVED
        mov     dl,es:[di+bx].rgb2_fcOptions
        and     dl,PC_RESERVED
        xor     dl,dh
        pop     dx
        jz      fore_entry_slammed

;/*
;** Need to actually set a new color.
;*/

slam_new_fore_color:
        mov     word ptr es:[di+bx].rgb2_bBlue,ax
        mov     word ptr es:[di+bx].rgb2_bRed,dx
        inc     nPhysChanged                      ; an entry actually changed

fore_entry_slammed:
        or      es:[di+bx].rgb2_fcOptions,PC_FOREGROUND

get_next_source_data:
        add     si,SIZE PALCLR                    ; move to next logical entry
        loop    slam_foreground_palette_loop

;/*
;** If any entries have changed, send down a new palette.
;*/

        cmp     nDefaultChanged,0
        jne     set_device_palette
        cmp     nMapChanged,0
        je      no_new_entries

;/*
;** Send down a new palette to the device.
;*/

;/*
;** ES:DI --> argbHW
;*/

        assumes es,nothing

set_device_palette:
        mov     ds,PalSegData
        assumes ds,Data

        farPtr  pEntries,es,di
        cCall   SetHWPalette,<0,SIZE_HW_PAL,pEntries,0>

no_new_entries:
        jmp     MAP_exit

;/*
;** color matching...
;**
;** Either this is a background palette OR a foreground palette that is
;** being realized as new.
;**
;** DS:SI --> logical palette (palseg)
;** ES:DI --> physical palette (hwpal)
;*/

        assumes ds,nothing
        assumes es,nothing

match_back_pal:
        mov     cx,cSpread
        add     si,palseg_apalclr
        mov     pStartFill,di

        mov     ax,SIZE_HW_PAL * (SIZE RGB2)
        add     ax,di                             ; AX = offset beyond last table entry
        mov     LastUsableEntry,ax               ; end of the palette

        mov     fNotOverwritable,(PC_FOREGROUND or PC_DEFAULT)

;/*
;** CX     =  count of colors in spread in logical palette
;** DS:SI --> next logical color to match
;** ES:DI --> argbHW
;*/

match_back_loop:

;/*
;** If it's an explicit index we don't need to do any color matching, just
;** stuff it into palclr_bCur.
;*/

        mov     dx,word ptr [si].palclr_rgb.rgb2_bRed
        mov     ax,word ptr [si].palclr_rgb.rgb2_bBlue
        test    dh,PC_EXPLICIT
        njnz    entry_back_matched
        .errnz  rgb2_fcOptions - rgb2_bRed - 1

        farPtr  rgbIn,dx,ax
        farPtr  pPal,es,di
        save    <es>
        push    dx
        cCall   rgb_to_ipc_with_hwpal,<rgbIn,pPal>
        pop     cx
        test    ch,PC_NOCOLLAPSE
        jnz     imperfect_match
        or      dx,dx
        jz      entry_back_matched_set_fg

;/*
;** Exact match not found.  See if we have room for it.
;**
;** AX = index of nearest match in hardware palette.
;** DS:SI --> apalclr
;** ES:DI --> hardware palette
;*/

imperfect_match:
        mov     bx,pStartFill
        or      bx,bx                              ; any more free entries?
        jz      entry_back_matched_set_fg        ; no, take nearest match

look_for_overwrite:
        mov     dl,fNotOverwritable

look_for_overwritable_loop:
        test    es:[bx].rgb2_fcOptions,dl
        jz      replace_opening

        add     bx,SIZE RGB2
        cmp     bx,LastUsableEntry
        jl      look_for_overwritable_loop

;/*
;** Can we overwrite the default colors?
;*/

        test    dl,PC_DEFAULT                      ; already overwrite defaults?
        jz      all_filled_for_back               ;    yes. no more room

        test    wForeBack,FB_OVERRIDE
        jz      all_filled_for_back

        and     fNotOverwritable,not PC_DEFAULT ; allow override
        mov     bx,phwpalMine.lo
        mov     pStartFill,bx                      ; first entry in table
        assert  bx,NE,0
        jmp     short look_for_overwrite         ; try overwriting again

all_filled_for_back:
        mov     pStartFill,0                       ; table is FULL
        jmp     short entry_back_matched_set_fg ; use matched entry

;/*
;** An overwritable entry was found. Fill it with the new color info.
;** Mark PC_FOREGROUND because we may allow overwriting of PC_DEFAULT and
;** we don't want to pick this slot again.
;*/

replace_opening:
        mov     pStartFill,bx                     ; new start point for search
        add     pStartFill,SIZE RGB2  ; don't need to look at this one again

        mov     ax,word ptr [si].palclr_rgb.rgb2_bBlue
        mov     word ptr es:[bx].rgb2_bBlue,ax
        mov     ax,word ptr [si].palclr_rgb.rgb2_bRed
        mov     word ptr es:[bx].rgb2_bRed,ax

        inc     nPhysChanged                      ; an entry actually changed

;/*
;** Get index of this new location.
;*/

        mov     ax,bx                            
        sub     ax,di
        rgbInd  ax                                ; index that we matched to

;/*
;** We have the closest match to our color in the physical palette.  If the
;** index is the same as what used to be there, don't record it as a change,
;** except if the logical index is being realized for the first time.
;**
;** SI = index into palseg_apalclr
;** AX = index into argbHW to map to
;** ES:DI --> argbHW
;*/

entry_back_matched_set_fg:
        mov     bx,ax
        rgbOff  bx
        or      es:[di+bx].rgb2_fcOptions,PC_FOREGROUND

entry_back_matched:
        mov     [si].palclr_bCur,al              ; set the new index

        test    [si].palclr_rgb.rgb2_fcOptions,PC_NEW
        jnz     map_new_entry
        cmp     al,[si].palclr_bPrev
        je      match_back_next_entry
map_new_entry:
        and     [si].palclr_rgb.rgb2_fcOptions,not PC_NEW
        inc     nMapChanged                             ; one more mapping change

match_back_next_entry:
        add     si,SIZE PALCLR                    ; move to next entry
        dec     cCounter
        nja     match_back_loop

;/*
;** The entire palette is now properly matched, but there are still
;** some loose ends.
;**
;** If foreground palette, we need to set the foreground indices.
;**
;** In any case, we may need to set some new entries in the device's
;** palette.
;*/

finished_back_match:
        test    wForeBack,FB_FORE                ; foregound or background palette?
        jz      see_if_pal_changed

        mov     si,pPalSeg.lo
        mov     cx,cSpread
@@:
        mov     al,[si].palseg_apalclr.palclr_bCur
        mov     [si].palseg_apalclr.palclr_bFore,al
        add     si,SIZE PALCLR
        loop    @B

see_if_pal_changed:
        cmp     nPhysChanged,0                    ; any physical palette changes?
        njne    set_device_palette               ;   yes.  set the new stuff.

;/*
;** Return the number of colors that were put into the physical palette,
;** or the number of mappings that changed from logical to physical.
;** If a logical index is being realized for the first time, it is considered
;** a change.
;*/

MAP_exit:
        mov     ax,nMapChanged
        les     bx,pcclr
        assumes es,nothing
        movzx   ecx,nPhysChanged
        mov     es:[bx],ecx
map_the_end:
cEnd


;/***************************************************************************
;*
;* FUNCTION NAME = RealizePalette
;*
;* DESCRIPTION   = 
;*
;*    This function is the real manager of the hardware palette. It maps
;*    the colors of a logical palette into the hardware palette.
;*
;*    RP_FOREGROUND
;*        Realize this palette in the foreground, i.e. give this palette slots
;*        in the hardware palette if it needs them.  For a non-device ddc, this
;*        option is ignored, i.e. there is no work to do. This is because palette
;*        realization is only necessary when there is contention for palette
;*        slots.
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES,FLAGS
;*                 Registers Preserved:
;*                       SI,DI,BP,DS
;*                 Calls: 
;*                       PrivateRealizePalette
;* 
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = DX:AX = number of entries changed 
;* RETURN-ERROR  = DX:AX = PAL_ERROR                 
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing

        check   RealizePalette,<hdc,flType,pcclr,hddc,ulFunN>

cProc   RealizePalette,<FAR,PUBLIC,NODATA>,<si,di,ds>
        parmD   hdc
        parmD   flType
        parmD   pcclr
        parmD   hddc
        parmD   FunN
        localD  cclr
        localD  pcclr
cBegin

        fw_zero <ds,es>
        mov     ds,PalSegData
        assumes ds,Data

        ddc?    hddc
        assert  flType.hi,E,0                     ;Only pmwin.dll calls us, so assert

RP_OPTIONS = RP_FOREGROUND
        assert  flType.lo,BE,RP_OPTIONS

        xor     eax,eax
        les     bx,pcclr
        assumes es,nothing
        mov     es:[bx],eax

        mov     dx,hddc.lo
        cCall   far_enter_driver
        mov     ax,PAL_ERROR
        njc     rp_exit

        no_path_area    rp_exit_error,both,error

;/*
;** Do we have a device ddc?  If not, exit now.  We only realize palettes
;** when they are selected into device ddc's.
;*/

rp_check_device_ddc:
        xor     ax,ax
        mov     si,hddc.lo
        test    [si].ddc_fb,DDC_DEVICE
        jz      rp_exit                           ;if not device, take return code, leave

;/*
;** Realize the palette.  Check for the default palette, which will be
;** a special case.  If any palette index mappings changed, invalidate
;** the palette mapping cache.
;*/

        mov     bx,[si].ddc_npdevpal
        mov     cx,flType.lo
        test    [si].ddc_fbBelow,DDC_PALETTE
        jnz     rp_do_realize
        or      cx,RP_REALIZE_DEFAULT_PALETTE
        .erre   RP_REALIZE_DEFAULT_PALETTE LT 10000h
rp_do_realize:
        cCall   PrivateRealizePalette,<bx,cx,pcclr>
        or      ax,ax
        jz      rp_exit
        or      fbPalMap,MPMV_INVALID
        jmp     short rp_exit

;/*
;** Exit the function.  If the DDC was in an area or path bracket,
;** AX will contain the error code to save.
;*/

rp_exit_error:
        save_error_code
        mov     ax,PAL_ERROR
rp_exit:
        cCall   far_leave_driver
        cwd
        fw_zero <ds,es>
cEnd

;/***************************************************************************
;*
;* FUNCTION NAME = PrivateRealizePalette
;*
;* DESCRIPTION   = 
;*
;*    This function is the real manager of the hardware palette. It maps
;*    the colors of a logical palette into the hardware palette.
;*
;*    RP_FOREGROUND
;*        Realize this palette in the foreground, i.e. give this palette slots
;*        in the hardware palette if it needs them.  For a non-device ddc, this
;*        option is ignored, i.e. there is no work to do. This is because palette
;*        realization is only necessary when there is contention for palette
;*        slots.
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES,FLAGS
;*                 Registers Preserved:
;*                       SI,DI,BP,DS
;*                 Calls: 
;*                       MatchAPal             
;*                       FreeHWPaletteSlots
;*                       RealizeDefaultPalette
;* 
;* INPUT         = DS = Data 
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = DX:AX = number of entries changed 
;* RETURN-ERROR  = DX:AX = PAL_ERROR                 
;*
;* PSEUDO-CODE   =
;*
;*   {
;*       if (RP_REALIZE_DEFAULT_PALETTE)
;*       {
;*         if background
;*             return 0
;*         FreeHWPaletteSlots()
;*         usRet = RealizeDefaultPalette()
;*         ++idRealization
;*         update npdevpalFore
;*         return (ULONG)usRet
;*       }
;*       else
;*         MatchAPal()
;*   }
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc   PrivateRealizePalette,<NEAR,PUBLIC,NODATA>,<>
        parmW   npdevpal
        parmW   fsType
        parmD   pcclr
cBegin
        test    fsType,RP_REALIZE_DEFAULT_PALETTE
        jz      prp_realize_custom_palette

;/*
;** If the default palette is being realized in the foreground, then stuff
;** its colors back into the hardware palette, if needed.  If it's being
;** realized in the background, then don't touch the hardware, since an
;** overriding palette may be in the foreground.
;**
;** Note that the default palette is assumed to always be realized.  When
;** an overriding palette is in effect, we don't guarantee that the system
;** is usable, for instance, that frame controls are distinguishable.
;*/

        mov     bx,npdevpal
        devpal? bx,SHORT
        xor     ax,ax                             ;default return code
        test    fsType,RP_FOREGROUND
        jz      prp_exit

        push    bx

        les     di,phwpal
        assumes es,nothing
        lds     si,[bx].devpal_pPalSeg
        assumes ds,nothing
        cCall   FreeHWPaletteSlots

        mov     ds,PalSegData
        assumes ds,Data
        cCall   RealizeDefaultPalette

        pop     bx
        inc     idRealization
        mov     npdevpalFore,bx
        jmp     short prp_exit

prp_realize_custom_palette:
        cCall   MatchAPal,<npdevpal,fsType,pcclr>

prp_exit:
        cwd
cEnd

;/***************************************************************************
;*
;* FUNCTION NAME = RealizeDefaultPalette
;*
;* DESCRIPTION   = 
;*
;*    Set the colors of the default palette into the hardware palette. 
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES,FLAGS
;*                 Registers Preserved:
;*                       SI,DI,BP,DS
;*                 Calls: 
;*                       SetHWPalette          
;* 
;* INPUT         = DS = Data 
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = AX = number of slots updated 
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc RealizeDefaultPalette,<NEAR,PUBLIC,NODATA>,<si,di>
        localW  nDefaultChanged ; number of default colors reinstated
cBegin

;/*
;** In the loop the registers are:
;**
;** CX = count
;** BX = index into argbHW
;** DS:SI --> palseg_apalclr[i]
;** DS:DI --> hwpal
;*/

        xor     ax,ax
        mov     nDefaultChanged,ax               ;no changes yet

ifdef FIREWALLS
;/*
;** Avoid a segment load in retail product.
;*/
        mov     ax,ds
        cmp     ax,phwpal.hi
        je      @F
        rip     text,<phwpal.hi != DS>
@@:
endif
        mov     di,phwpal.lo

        mov     si,DataOFFSET palsegDefPal
        palSize cx,ds,si

;/*
;** For each color in the default palette, check to see
;** it's already in the hardware palette.  If it isn't, put it there
;** and keep count of the number of changes.  First check the three
;** bytes of color info, then check for a change of the PC_RESERVED flag.
;*/

rdp_slam_palette_loop:
        mov     ax,word ptr [si].palseg_apalclr.palclr_rgb.rgb2_bBlue
        mov     dx,word ptr [si].palseg_apalclr.palclr_rgb.rgb2_bRed
        mov     bl,[si].palseg_apalclr.palclr_bFore
        xor     bh,bh
        rgbOff  bx
        cmp     ax,word ptr [di+bx].rgb2_bBlue
        jne     rdp_slam_new_color
        cmp     dl,[di+bx].rgb2_bRed
        jne     rdp_slam_new_color

        push    dx
        and     dh,PC_RESERVED
        mov     dl,[di+bx].rgb2_fcOptions
        and     dl,PC_RESERVED
        xor     dl,dh
        pop     dx
        jz      rdp_entry_slammed

rdp_slam_new_color:
        mov     word ptr [di+bx].rgb2_bBlue,ax
        mov     word ptr [di+bx].rgb2_bRed,dx

        inc     nDefaultChanged

rdp_entry_slammed:
        add     si,size PALCLR
        loop    rdp_slam_palette_loop

        and     fbPal,not PF_DEF_OVERRIDE
        mov     ax,nDefaultChanged
        or      ax,ax
        jz      rdp_exit

        farPtr  pEntries,ds,di
        cCall   SetHWPalette,<0,SIZE_HW_PAL,pEntries,0>
        mov     ax,nDefaultChanged

rdp_exit:
cEnd

;/***************************************************************************
;*
;* FUNCTION NAME = FreeHWPaletteSlots
;*
;* DESCRIPTION   = 
;*
;*      Mark all unreserved entries as unused.  This allows background palettes  
;*      to come in afterwards and claim slots not taken by this foreground       
;*      palette.                                                                                Registers Destroyed:
;*
;*                       BX,CX,FLAGS
;*                 Registers Preserved:
;*                       AX,DX,SI,DI,BP,DS,ES
;* 
;* INPUT         = DS:SI --> logical palette (palseg) 
                   ES:DI --> physical palette (hwpal) 
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

cProc FreeHWPaletteSlots,<NEAR,PUBLIC>,<>
cBegin
        mov     bx,di
        add     bx,(NUM_RESERVED_CLRS / 2) * (size RGB2)
        mov     cx,SIZE_HW_PAL - NUM_RESERVED_CLRS

un_use_palette_loop:
        and     es:[bx].rgb2_fcOptions,(not PC_FOREGROUND)
        add     bx,size RGB2
        loop    un_use_palette_loop
cEnd

sEnd    PalSeg

ifdef FIREWALLS
        public  map_no_default_override
        public  map_match_the_pal
        public  map_set_bcur_valid
        public  map_no_work
        public  map_do_it
        public  map_not_fore
        public  match_fore_pal
        public  map_check_new_override
        public  map_no_override
        public  un_use_palette_loop
        public  rerealize_fore_pal
        public  map_got_a_problem
        public  map_no_problem
        public  slam_foreground_palette_loop
        public  map_cur_same_as_fore
        public  slam_new_fore_color
        public  fore_entry_slammed
        public  get_next_source_data
        public  set_device_palette
        public  no_new_entries
        public  match_back_pal
        public  match_back_loop
        public  imperfect_match
        public  look_for_overwrite
        public  look_for_overwritable_loop
        public  all_filled_for_back
        public  replace_opening
        public  entry_back_matched
        public  map_new_entry
        public  match_back_next_entry
        public  finished_back_match
        public  see_if_pal_changed
        public  MAP_exit
        public  map_the_end
        public  rp_check_device_ddc
        public  rp_do_realize
        public  rp_exit_error
        public  rp_exit
        public  prp_exit
        public  rdp_slam_palette_loop
        public  rdp_slam_new_color
        public  rdp_entry_slammed
        public  rdp_exit
endif

end
