;*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 = PALETTE.ASM
;*
;* DESCRIPTIVE NAME = Palette Management Functions
;*
;*
;* VERSION      V2.0
;*
;* DATE
;*
;* DESCRIPTION  This file contains most of the new DDI functions to support
;*              the OS/2 palette manager, including functions to create,
;*              delete, modify, and query palettes and palette data.
;*
;* FUNCTIONS    DeviceCreatePalette
;*              DeviceAnimatePalette
;*              DeviceSetPaletteEntries
;*              InnerSetPaletteEntries
;*              GetPaletteMemory
;*              FreePaletteMemory
;*              DeviceDeletePalette
;*              InnerDeletePalette
;*              CountFreeSlots
;*              RealizePalette
;*              RealizeDefaultPalette
;*              ReduceDefaultPaletteSize
;*              IncreaseDefaultPaletteSize
;*              RemoveUsedMarkings
;*              StoreAndRemoveUsedMarkings
;*              RestoreUsedMarkings
;*              InnerRealizePalette
;*              ClosestHWPaletteMatch
;*              ExactHWPaletteMatch
;*              rgb2_diff
;*              UpdateColors
;*              QueryHWPaletteInfo
;*              QueryPaletteRealization
;*              DeviceResizePalette
;*              NearestPaletteIndex
;*              HWPaletteChanged
;*              ChangedPalette
;*              ChangedColorTable
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   04/15/93              67399  Port XGA defect 65655.
;*   04/15/93              67399  Port XGA support for more than 256 colors.
;*   04/16/93              67399  Port XGA defect 67450.
;*   04/28/93              68056  Port XGA defect 68056.
;*
;*****************************************************************************/

        .386
        .MODEL FLAT,SYSCALL
        ASSUME  SS:FLAT, DS:FLAT, CS:FLAT, ES:FLAT

        .xlist

INCL_DDIMISC            equ                      1
INCL_GRE_BITMAPS        equ                      1
INCL_GPIBITMAPS         equ                      1
INCL_GPILOGCOLORTABLE   equ                      1
INCL_GRE_PALETTE        equ                      1
INCL_GRE_COLORTABLE     equ                      1
INCL_DEV                equ                      1
INCL_DDICOMFLAGS        equ                      1
INCL_WINPALETTE         equ                      1
INCL_WINSYS             equ                      1
        include pmgre.inc
DINCL_ENABLE            equ                      1
DINCL_BITMAP            equ                      1
DINCL_CLR_TBL           equ                      1
        include driver.inc
        include extern.inc
        include protos.inc
        include assert.mac
        include palette.inc
        include seamless.inc
        .list

;/*
;** Extern Protos for this file
;*/

externdef       AVIOColorTable:RGB2
externdef       AVIOXlate256:DWORD
externdef       AVIOXlate128:DWORD
externdef       AVIOXlate64:DWORD
externdef       AVIOXlate32:DWORD
externdef       AVIOXlate16:DWORD
externdef       pAVIOColorXlate:DWORD

eddc_ResetLogColorTable                 PROTO SYSCALL,
        hddc            :PDDC

LoadPaletteEntries                      PROTO SYSCALL,
        start           :ULONG,
        count           :ULONG,
        lpPaletteEntries:DWORD

NearestDirectDefaultPhysicalIndex       PROTO SYSCALL,
        rgb             :RGB2

OEMUpdateColors                         PROTO SYSCALL,
        pVisRects       :PRECTL,
        pMappingVector  :PBYTE

;/*
;** Protos for this file
;*/

ChangedPalette                          PROTO SYSCALL,
        pPalette        :PDEVPAL

ClosestHWPaletteMatch                   PROTO SYSCALL,
        rgb             :RGB2

CountFreeSlots PROTO SYSCALL

ExactHWPaletteMatch                     PROTO SYSCALL,
        rgb             :RGB2

FreePaletteMemory                       PROTO SYSCALL,
        hdevpal         :PDEVPAL

GetPaletteMemory                        PROTO SYSCALL,
        hdevpal         :PDEVPAL,
        ppalinfo        :DWORD          ;          

HWPaletteChanged                        PROTO SYSCALL

IncreaseDefaultPaletteSize              PROTO SYSCALL

InnerDeletePalette                      PROTO SYSCALL,
        hdevpal         :PDEVPAL

InnerRealizePalette                     PROTO SYSCALL,
        hddc            :PDDC,
        pflType         :PULONG,
        pcSlotsChanged  :PULONG

InnerSetPaletteEntries                  PROTO SYSCALL,
        hdevpal         :PDEVPAL,
        ulStart         :ULONG,
        cclr            :ULONG,
        pclr            :PULONG

RealizeDefaultPalette                   PROTO SYSCALL,

ReduceDefaultPaletteSize                PROTO SYSCALL

RemoveUsedMarkings                      PROTO SYSCALL

RestoreUsedMarkings                     PROTO SYSCALL

StoreAndRemoveUsedMarkings              PROTO SYSCALL

UpdateColors                            PROTO SYSCALL,
        hdc             :HDC,
        hddc            :PDDC,
        FunN            :ULONG

PFNDefGetVisRects TYPEDEF PROTO SYSCALL,
        hdcTemp        :DWORD,
        prclVis        :DWORD,
        Control        :DWORD,
        arclBuf        :DWORD,
        arclBuf        :DWORD,
        NGreGetVisRects :DWORD


EXTERNDEF SM_WINDRV:_SM_WINDRV

.DATA

;/*
;** These are used by eddb_CreatePalMapping to keep track of the
;** current source and destination palettes used in the current
;** palette-palette mapping.  The palette pointers are PVOIDs because
;** they may point to either a DEVPAL (real palette manager palettes)
;** or an array of RGBs (a device default palette).
;*/

RGB2NULL RGB2    <0, 0, 0, 0>

GlobalPalCount          ULONG  0
usGlobalOptimizeID      ULONG  1
hForeGroundPal          PDEVPAL FullSizeDeviceDefaultPalette
HWPalette               RGB2    HW_PAL_SIZE     DUP (<>)
fForeGroundOverwrote    ULONG  FALSE
UCMapping               BYTE    HW_PAL_SIZE     DUP (?)
ulFreeSlotsLastTime     DWORD   0         ;This was static

ifndef IBMJ        ;IBMJ
.CODE
else  ;IBMJ        ;IBMJ
_PaletteSupport SEGMENT DWORD PUBLIC FLAT 'CODE'
endif ;IBMJ        ;IBMJ
;/***************************************************************************
;*
;* FUNCTION NAME = DeviceCreatePalette
;*
;* DESCRIPTION   = If hdevpal is zero, then ppalinfo points to a paletteinfo
;*                 structure, which must be set into a new palette whose
;*                 handle is returned.  The new palette is then selected
;*                 into the DC.  If hdevPal is non-zero, then ppalinfo is
;*                 ignored:  the palette is selected into the DC.
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX
;*                 Registers Destroyed:
;*                        EAX,EDX,ECX
;*
;* INPUT         = hdc        DC Handle
;*                 ppalinfo   table of palette data
;*                 hdevpal    device palette handle (NULL if new)
;*                 pdc        device display context handle
;*                 FunN       function number
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = hdevpal
;* RETURN-ERROR  = ERROR_NEG
;*
;*            PSEUDOCODE
;*
;*  if (hdevpal == 0)
;*  {
;*      Get new palette
;*      Clear palette
;*      Set palette entries
;*  }
;*  call eddc_ResetLogColorTable() to tidy up DC state
;*  Select palette into DC
;*  Increment palette usage count
;*
;**************************************************************************/

DeviceCreatePalette PROC SYSCALL USES ESI EDI,
        hdc             :HDC,
        ppalinfo        :DWORD,
        hdevpal         :PDEVPAL,
        hddc            :PDDC,
        FunN            :ULONG

;/*
;** Get driver semaphore and perform entry checks
;*/

        cld
        ddc?    hddc

        mov     edx,hddc
        INVOKE  enter_driver

        mov     eax,ERROR_NEG
        jc      dcp_exit_no_lock                 ;error logged

ifdef FIREWALLS

;/*
;** this test is firewalled since the 8514 driver claims that the
;** engine will have already done the test
;**
;** If the function is being called within an area or path
;** definition then we raise an error and leave immediately.
;**
;** We have been called within an area definition
;*/

        no_path_area    dcp_exit_error,both

endif ;/* FIREWALLS */

;/*
;** Load 'em up
;*/

        mov     esi,ppalinfo
        mov     edi,hdevpal

;/*
;**    if ( !hdevpal )
;*/

        cmp     edi,0
        jne     end_if1

;/*
;**    {
;**        /**************************************************************/
;**        /* check the data is in the right format                      */
;**        /**************************************************************/
;**        if (ppalinfo->ulFormat != LCOLF_CONSECRGB)
;*/

        cmp     [esi].PALETTEINFO.palinfo_ulFormat,LCOLF_CONSECRGB
        jne     dcp_exit_error

;/*
;**        {
;**            ExitDriver(pdcArg, FunN, EDF_STANDARD);
;**            return( ERROR_NEG );
;**        }
;**
;**        /**************************************************************/
;**        /* Create a new palette and copy in the palinfo.              */
;**        /**************************************************************/
;**        hdevpal = GetPaletteMemory();
;*/

        INVOKE  GetPaletteMemory,
                edi,
                esi

        mov     edi,eax

;/*
;**        if ((LONG)hdevpal == ERROR_NEG)
;*/

        cmp     edi,ERROR_NEG
        je      dcp_exit_error

;/*
;**        {
;**            ExitDriver(pdcArg, FunN, EDF_STANDARD);
;**            return( ERROR_NEG );
;**        }
;**
;**        /**************************************************************/
;**        /* update our global palette count                            */
;**        /**************************************************************/
;**
;**        GlobalPalCount++;
;*/

        inc     GlobalPalCount

;/*
;**        /**************************************************************/
;**        /* totally clear the palette memory                           */
;**        /* this initializes usage count to 0, max index to 0          */
;**        /*   and all entries to RGB 0 (black)                         */
;**        /**************************************************************/
;**        memset( hdevpal, 0, sizeof(DEVPAL));
;*/

        .errnz  sizeof DEVPAL and 3

        mov     ecx,sizeof DEVPAL / 4
        mov     eax,0
        rep     stosd
        sub     edi,sizeof DEVPAL

;/*
;**        /**************************************************************/
;**        /* store the user flags for this palette                      */
;**        /* and indicate palette has changed since it was realized     */
;**        /**************************************************************/
;**        hdevpal->usFlags = (USHORT)(ppalinfo->flCmd | PAL_CHANGED);
;*/

        mov     eax,[esi].PALETTEINFO.palinfo_flCmd
        or      eax,PAL_CHANGED
        mov     [edi].DEVPAL.usFlags,eax

;/*
;**        /**************************************************************/
;**        /* Set colors into palette                                    */
;**        /**************************************************************/
;**        InnerSetPaletteEntries( hdevpal,
;**                                0L,           /* start is always zero */
;**                                ppalinfo->cclr,
;**                                (PULONG)ppalinfo->argb);
;*/

        INVOKE  InnerSetPaletteEntries,
                edi,            ;hdevpal
                0,
                [esi].PALETTEINFO.palinfo_cclr,
                ADDR [esi].PALETTEINFO.palinfo_argb

;/*
;**        /**************************************************************/
;**        /* we have a palette so store its maximum index               */
;**        /**************************************************************/
;**        hdevpal->usMax = (USHORT)ppalinfo->cclr - (USHORT)1;
;*/

        mov     eax,[esi].PALETTEINFO.palinfo_cclr
        dec     eax
        mov     [edi].DEVPAL.usMax,eax

;/*
;**        /**************************************************************/
;**        /* The min operation does not work in this case due to a      */
;**        /* compiler     getting its optimization       when trying    */
;**        /* to be clever with multiples of 256.                        */
;**        /**************************************************************/
;**        if (ppalinfo->cclr < LARGEST_PAL)
;**        {
;**            hdevpal->usCountStored = (USHORT)ppalinfo->cclr;
;**        }
;**        else
;**        {
;**            hdevpal->usCountStored = (USHORT)LARGEST_PAL;
;**        }
;*        /* Defect 63839 - Support for > 256 entry logical palettes  */
;*        hdevpal->usCountStored = (USHORT)ppalinfo->cclr;
;*/


        inc     eax
;                  cmp     eax,LARGEST_PAL

;                  jbe     @F                      ; @DMS was below only
;                  mov     eax,LARGEST_PAL
;             
        mov     [edi].DEVPAL.usCountStored,eax

;/*
;**        /**************************************************************/
;**        /* We must make sure that the first realize call is not       */
;**        /* optimized out by setting the local optimization identifier */
;**        /* to a different number to the global optimization           */
;**        /* identifier. (We do not have to use -1, but it is as good   */
;**        /* as any other value!)                                       */
;**        /**************************************************************/
;**        hdevpal->usLocalOptimizeID = usGlobalOptimizeID-(SHORT)1;
;*/

        mov     eax,usGlobalOptimizeID
        dec     eax
        mov     [edi].DEVPAL.usLocalOptimizeID,eax
end_if1:

;/*
;**    }
;**
;**    /******************************************************************/
;**    /* Select palette into the DC.                                    */
;**    /* First, reset the DC to default color table.                    */
;**    /******************************************************************/
;**    eddc_ResetLogColorTable();
;**        INVOKE  eddc_ResetLogColorTable,
;**                hddc
;*/

        INVOKE  eddc_ResetLogColorTable,
                hddc
;/*
;**    /******************************************************************/
;**    /* Set the palette handle into our dc.                            */
;**    /******************************************************************/
;**    pdc->Palette      = hdevpal;
;*/

        mov     esi,hddc
        mov     [esi].DDC.ddc_npdevpal,edi

;/*
;**    pdc->DCIColFormat = LCOLF_PALETTE;
;*/

        and     [esi].DDC.ddc_fbClrTbl,NOT (DDC_PALETTE+DDC_LOG_CLR_TBL+DDC_RGB_MODE)
        or      [esi].DDC.ddc_fbClrTbl,DDC_PALETTE

;/*
;**    /******************************************************************/
;**    /* we will be using this palette so increment the usage count     */
;**    /******************************************************************/
;**    hdevpal->cUsage++;
;*/

        inc     [edi].DEVPAL.cUsage

;/*
;**    return (ULONG)hdevpal;
;*/

        mov     eax,edi
        jmp     dcp_exit
dcp_exit_error:
        mov     eax,ERROR_NEG
dcp_exit:

;/*
;**    ExitDriver(pdcArg, FunN, EDF_STANDARD);
;*/

        INVOKE  leave_driver
dcp_exit_no_lock:
        ret
DeviceCreatePalette ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = DeviceAnimatePalette
;*
;* DESCRIPTION   = Modify the colors in a palette.  The changes will be
;*                 reflected immediately for each animated index which has
;*                 a hardware slot.  The only logical colors that can
;*                 possibly be affected by this call are those already
;*                 marked as PC_RESERVED in the logical palette, by either
;*                 DeviceCreatePalette or DeviceSetPaletteEntries.  The
;*                 only physical colors that can be affected are those that
;*                 have been assigned hardware slots by RealizePalette.
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX
;*                 Registers Destroyed:
;*                        EAX,EDX,ECX
;*
;* INPUT         = hdc         DC handle
;*                 hdevpal     device palette handle
;*                 ulFormat    format - must be LCOLF_CONSECRGB
;*                 ulStart     first palette entry to change
;*                 cclr        count of palette entries to change
;*                 pclr        pointer to table of new RGB2 palette entries
;*                 hddc      device DC handle
;*                 FunN      function number and COM flags
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = count of hardware palette slots changed
;* RETURN-ERROR  =  PAL_ERROR
;*
;**************************************************************************/

DeviceAnimatePalette PROC SYSCALL USES ESI EDI EBX,
        hdc             :HDC,
        hdevpal         :PDEVPAL,
        ulFormat        :ULONG,
        ulStart         :ULONG,
        cclr            :ULONG,
        pclr            :PULONG,
        hddc            :PDDC,
        FunN            :ULONG

LOCAL   Changed         :ULONG,
        rgb             :RGB2,
        firstindex      :ULONG,
        lastindex       :ULONG,
        hwIndex         :ULONG

;/*
;** Get driver semaphore and perform entry checks
;*/
        cld
        ddc?    hddc

        mov     edx,hddc
        INVOKE  enter_driver

        mov     eax,PAL_ERROR
        jc      dap_exit_no_lock                 ;error logged

ifdef FIREWALLS

;/*
;** this test is firewalled since the 8514 driver claims that the
;** engine will have already done the test
;**
;** If the function is being called within an area or path
;** definition then we raise an error and leave immediately.
;**
;** We have been called within an area definition
;*/

        no_path_area    dap_exit_error,both

endif ;/* FIREWALLS */

ifdef FIREWALLS

;/*
;**    if (hdevpal != pdc->Palette)
;**    {
;**        DebugOutput("Device Animate palette: hdevpals do not agree...\n\r");
;**        if (!hdevpal)
;**        {
;**            DebugOutput("NULL hdevpal - using DC hdevpal...\n\r");
;**            hdevpal = pdc->Palette;
;**        }
;**    }
;*/

        assert  edx,E,hddc

        mov     eax,[edx].DDC.ddc_npdevpal
        cmp     eax,hdevpal
        je      same_pals
        mov     hdevpal,eax
        DebugMsg2       <Device Animate palette: hdevpals do not agree...>
same_pals:

endif ;/* FIREWALLS */

;/*
;** We can only animate if we have been passed RGBs in consecutive
;** formate, and the palette has been realized since the last
;** palette was realized in the foreground (ie. we can guarantee
;** that the mappings we have within the palette structure are
;** still valid.
;*/

;/*
;**    if (   (ulFormat == LCOLF_CONSECRGB)
;**        && (hdevpal->usLocalOptimizeID == usGlobalOptimizeID) )
;**    {
;*/

        cmp     ulFormat,LCOLF_CONSECRGB
        jne     dap_exit_error
        mov     eax,hdevpal
        mov     eax,[eax].DEVPAL.usLocalOptimizeID
        cmp     eax,usGlobalOptimizeID
        jne     dap_exit_error

;/*
;** initialize return value
;*/

        mov     Changed,0

;/*
;**       /**************************************************************/
;**       /* set our range of HW slots changed to initial values        */
;**       /* (the first HW slot changed will always update these values)*/
;**       /**************************************************************/
;**       firstindex = SizeOfHWPalette;
;**       lastindex  = 0;
;*/


        mov     eax,SizeOfHWPalette
        mov     firstindex,eax
        mov     lastindex,0

;/*
;**       /**************************************************************/
;**       /* pclr points at an array of RGB2 structures                 */
;**       /**************************************************************/
;**       while ((cclr != 0) && (ulStart < LARGEST_PAL))
;        /* Defect 63839 - Remove 256 entry logical palette limit      */
;        while ((cclr != 0) && (ulStart < hdevpal->usCountStored))
;**       {
;*/

        mov     eax,cclr
        cmp     eax,0
        je      dap_while_loop_quit

;/*
;** eax = ulStart + cclr - LARGEST_PAL
;*/

        mov     esi,pclr
        ASSUME  esi:PTR RGB2
        mov     edi,hdevpal
        ASSUME  edi:PDEVPAL

        mov     ebx,ulStart
        add     eax,ebx
;                  sub     eax,LARGEST_PAL
        sub     eax,[edi].usCountStored  ;          

        jbe     @F


;/*
;**  adjust the count
;*/

        sub     cclr,eax
        jbe     dap_while_loop_quit
@@:
;                  mov     esi,pclr
;                  ASSUME  esi:PTR RGB2
;                  mov     edi,hdevpal
;                  ASSUME  edi:PDEVPAL

;/*
;** ebx already = ulStart
;*/


        .errnz  sizeof PALENTRY-8

        lea     edx,[edi + ebx * 8].entries

;/*
;** EDX now points to hdevpal->entries[ulStart]
;*/

dap_while_loop:

;/*
;**           /**********************************************************/
;**           /* only process reserved new entries which are not also   */
;**           /* explicit entries, and which were also previously       */
;**           /* reserved                                               */
;**           /**********************************************************/
;**           if ( ((*(PRGB2)pclr).fcOptions & PC_RESERVED) &&
;**               !((*(PRGB2)pclr).fcOptions & PC_EXPLICIT) &&
;**               (hdevpal->entries[ulStart].rgb.fcOptions & PC_RESERVED))
;**           {
;*/

                test    [esi].rgb2_fcOptions,PC_RESERVED
                jz      dap_entry_not_reserved
                test    [esi].rgb2_fcOptions,PC_EXPLICIT
                jnz     dap_entry_not_reserved


                test    [edx].PALENTRY.rgb.rgb2_fcOptions,PC_RESERVED
                jz      dap_entry_not_reserved

;/*
;**               /******************************************************/
;**               /* this value satisfies the tests so we are going to  */
;**               /* update the palette                                 */
;**               /******************************************************/
;**
;**               /******************************************************/
;**               /* get the passed rgb2 value                          */
;**               /******************************************************/
;**               rgb = *(PRGB2)pclr;
;*/


                mov     ecx,DWORD PTR [esi]
                mov     rgb,ecx

;/*
;**               /******************************************************/
;**               /* set our flag to say this index is used             */
;**               /******************************************************/
;**               rgb.rgb2_fcOptions |= PC_USED;
;**               hdevpal->entries[ulStart].rgb = rgb;
;*/


                or      rgb.rgb2_fcOptions,PC_USED
                mov     ecx,rgb
                mov     [edx].PALENTRY.rgb,ecx

;/*
;**               /******************************************************/
;**               /* If the h/w palette entry is PC_RESERVED then       */
;**               /* change the HWPalette entry.                        */
;**               /******************************************************/
;**               hwIndex = hdevpal->entries[ulStart].bCurrent;
;*/


                mov     eax,0
                mov     al,[edx].PALENTRY.bCurrent

;/*
;**               if ( HWPalette[hwIndex].rgb2_fcOptions & PC_RESERVED )
;**               {
;**                       HWPalette is an array of RGB2 structures
;*/

                        .errnz  sizeof RGB2 - 4
                        lea     ebx,HWPalette[eax*4]
                        test    [ebx].RGB2.rgb2_fcOptions,PC_RESERVED
                        jz      dap_slot_not_reserved

;/*
;**                    /**************************************************/
;**                    /* this entry has a hardware slot allocated, so   */
;**                    /* write the new value there                      */
;**                    /**************************************************/
;**                       HWPalette[hwIndex] = rgb;
;*/

                        mov     DWORD PTR [ebx],ecx

;/*
;** update the change count
;*/

                        inc     Changed

;/*
;**                    /**************************************************/
;**                    /* keep the range of HW slots changed up to date  */
;**                    /**************************************************/
;**                    if (hwIndex > lastindex)
;**                    {
;**                        lastindex = hwIndex;
;**                    }
;*/

;/*
;** eax still has hwIndex
;*/

                        cmp     eax,lastindex
                        jbe     @F
                        mov     lastindex,eax
@@:

;/*
;**                    if (hwIndex < firstindex)
;**                    {
;**                        firstindex = hwIndex;
;**                    }
;*/

                        cmp     eax,firstindex
                        jae     @F
                        mov     firstindex,eax
@@:

;/*
;**                } /* ...if HWPalette slot reserved */
;*/

dap_slot_not_reserved:

;/*
;**               /******************************************************/
;**               /* mark palette as having changed.                    */
;**               /******************************************************/
;**               hdevpal->usFlags |= PAL_CHANGED;
;*/


                or      [edi].usFlags,PAL_CHANGED

;/*
;**            } /* ... if palette entry reserved */
;*/

dap_entry_not_reserved:

;/*
;**            /**********************************************************/
;**            /* move to consider the next entry                        */
;**            /**********************************************************/
;**            cclr--;
;**            ulStart++;
;**            pclr++;
;** ESI is pclr
;** bump EDX to next hdevpal->entries[ulStart]
;*/


                add     edx,sizeof PALENTRY
                add     esi,sizeof RGB2
                dec     cclr; 
                jne     dap_while_loop

;/*
;**        }
;*/

dap_while_loop_quit:
        ASSUME  esi:NOTHING

;/*
;**       /**************************************************************/
;**       /* now pass any changed entries through to the hardware       */
;**       /**************************************************************/
;**       if (Changed)
;**       {
;*/

        cmp     Changed,0
        je      no_changed_entries

;/*
;**           /**********************************************************/
;**           /* Just pass on the range of the HW palette which includes*/
;**           /* all the slots that we changed                          */
;**           /**********************************************************/
;**           LoadPaletteEntries(firstindex,
;**                              lastindex - firstindex + 1,
;**                              &HWPalette[firstindex]);
;*/


                mov     eax,firstindex
                mov     ecx,lastindex
                sub     ecx,eax
                inc     ecx

;/*
;** ecx = lastindex - firstindex + 1
;** HWPalette is an array of RGB2 structures
;*/

                .errnz  sizeof RGB2 - 4
                lea     ebx,HWPalette[eax*4]

                INVOKE  LoadPaletteEntries,
                        firstindex,
                        ecx,
                        ebx

;/*
;**           /**********************************************************/
;**           /* Pass the information that the h/w palette changed on   */
;**           /* to the palette mapping caching code                    */
;**           /**********************************************************/
;*/

            INVOKE      HWPaletteChanged

;/*
;**       }
;*/

no_changed_entries:

;/*
;**       /**************************************************************/
;**       /* If the logical palette changed pass this information on to */
;**       /* the palette mapping caching code                           */
;**       /**************************************************************/
;**        if (hdevpal->usFlags & PAL_CHANGED)
;**        {
;*/

        test    [edi].usFlags,PAL_CHANGED

        assert  edi,E,hdevpal

        jz      no_logpal_change
                INVOKE  ChangedPalette,
                        edi             ;hdevpal

;/*
;**        }
;*/

no_logpal_change:

;/*
;**    } /* ... LCOLF_CONSECRGB */
;**    else /* error */
;**    {
;**        /* Defect 65655 - We must log the error                       */
;**        LogError(PMERR_PALETTE_BUSY);
;**        ExitDriver(pdcArg, FunN, EDF_STANDARD | EDF_DONT_CLEAN);
;**        return( PAL_ERROR );
;**    }

;/*    /******************************************************************/
;**    /* Release driver semaphore                                       */
;**    /******************************************************************/
;**        return(Changed);
;*/

        mov     eax,Changed
        jmp     dap_exit

dap_exit_error:
        mov     eax,PAL_ERROR
dap_exit:
        INVOKE  leave_driver
dap_exit_no_lock:
        ret
DeviceAnimatePalette ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = DeviceSetPaletteEntries
;*
;* DESCRIPTION   = This sets entries in the logical palette structure.  It is
;*                 an error to try and set entries outside the range of the
;*                 palette.
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX
;*                 Registers Destroyed:
;*                        EAX,EDX,ECX
;*
;* INPUT         = hdc       DC handle
;*                 hdevpal   device palette handle
;*                 ulFormat  format - must be LCOLF_CONSECRGB
;*                 ulStart   first palette entry to change
;*                 cclr      count of palette entries to change
;*                 pclr      pointer to table of new RGB2 palette entries
;*                 pdc       device DC handle
;*                 FunN      function number and COM flags
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = TRUE
;* RETURN-ERROR  = FALSE
;*
;**************************************************************************/

DeviceSetPaletteEntries PROC SYSCALL,
        hdc             :HDC,
        hdevpal         :PDEVPAL,
        ulFormat        :ULONG,
        ulStart         :ULONG,
        cclr            :ULONG,
        pclr            :PULONG,
        hddc            :PDDC,
        FunN            :ULONG

;/*
;** Get driver semaphore and perform entry checks
;*/

        cld
        ddc?    hddc

        mov     edx,hddc
        INVOKE  enter_driver

        mov     eax,0
        jc      dspe_exit_no_lock                ;error logged

ifdef FIREWALLS
;/*
;** this test is firewalled since the 8514 driver claims that the
;** engine will have already done the test
;**
;** If the function is being called within an area or path
;** definition then we raise an error and leave immediately.
;**
;*/

        no_path_area    dspe_exit_error,both

endif ;/* FIREWALLS */

;/*
;**    /******************************************************************/
;**    /* it is an error to use this function to increase the size of a  */
;**    /* palette                                                        */
;**    /******************************************************************/
;**    if ((ulStart + cclr - 1) > hdevpal->usMax)
;*/

        mov     eax,ulStart
        add     eax,cclr
        dec     eax
        mov     edx,hdevpal
        cmp     eax,[edx].DEVPAL.usMax
        jbe     size_ok

;/*
;**    {
;*/


                mov     eax,PMERR_INV_COLOR_INDEX
                save_error_code
                DebugMsg2       <Invalid count>
                mov     eax,0
                jmp     dspe_exit

;/*
;**    }
;*/

size_ok:

;/*
;**    /******************************************************************/
;**    /* the only valid format is LCOLF_CONSECRGB                       */
;**    /******************************************************************/
;**    if (ulFormat != LCOLF_CONSECRGB)
;*/

        cmp     ulFormat,LCOLF_CONSECRGB
        je      format_ok

;/*
;**    {
;*/

        jmp     dspe_exit_error

;/*
;**    }
;*/

format_ok:

;/*
;** every thing is hunky-dory so go and do the work
;*/

        INVOKE  InnerSetPaletteEntries,
                hdevpal,
                ulStart,
                cclr,
                pclr

;/*
;**    /******************************************************************/
;**    /* Release driver semaphore                                       */
;**    /******************************************************************/
;**    return(TRUE);
;*/

        mov     eax,1
        jmp     dspe_exit

dspe_exit_error:
        mov     eax,0
dspe_exit:
        INVOKE  leave_driver
dspe_exit_no_lock:
        ret
DeviceSetPaletteEntries ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = InnerSetPaletteEntries
;*
;* DESCRIPTION   = Called from DevSetPaletteEntries, and CreatePalette.
;*                 This function actually sets the entries in the logical
;*                 palette.  It assumes that all error checking has been done
;*                 by the calling routine.
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX
;*                 Registers Destroyed:
;*                        EAX,EDX,ECX
;*
;* INPUT         = hdevpal         :PDEVPAL,
;*                 ulStart         :ULONG,
;*                 cclr            :ULONG,
;*                 pclr            :PULONG
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

InnerSetPaletteEntries PROC SYSCALL USES ESI EBX,
        hdevpal         :PDEVPAL,
        ulStart         :ULONG,
        cclr            :ULONG,
        pclr            :PULONG

LOCAL   rgb             :RGB2

;/*
;**    while (cclr && ulStart < LARGEST_PAL)
;**    /* Defect 63839 - Support for > 256 entry logical palettes */
;**    while (cclr)
;**    {
;*/

        mov     ecx,cclr
        mov     eax,ecx
        cmp     eax,0
        je      ispe_while_loop_quit

;/*
;** eax = ulStart + cclr - LARGEST_PAL
;*/

        mov     ebx,ulStart
;                  add     eax,ebx
;                  sub     eax,LARGEST_PAL
;                  jl      @F

;/*
;** adjust the count
;*/

;                  sub     ecx,eax
;                  jle     ispe_while_loop_quit
;             
        mov     esi,hdevpal

;/*
;** ebx already = ulStart
;*/

        .errnz  sizeof PALENTRY-8
        lea     edx,[esi + ebx * 8].DEVPAL.entries

;/*
;** EDX now points to hdevpal->entries[ulStart]
;*/


        mov     ebx,pclr

;/*
;** ebx points to an array of RGB2's
;*/

ispe_while_top:

;/*
;**       /**************************************************************/
;**       /* get the passed rgb2 value                                  */
;**       /**************************************************************/
;**       rgb = *(PRGB2)pclr++;
;*/

        mov     eax,[ebx]

        rol     eax,8           ;shift rgb2_fcOptions into al
        add     ebx,sizeof RGB2

;/*
;**       if (!(hdevpal->entries[ulStart].rgb.rgb2_fcOptions & PC_USED))
;*/

        test    [edx].PALENTRY.rgb.rgb2_fcOptions,PC_USED
        jnz     not_new

;/*
;**        {
;**            /**********************************************************/
;**            /* this was not previously used, so it must be new        */
;**            /**********************************************************/
;**            rgb.rgb2_fcOptions |= PC_NEW;
;*/

                or      al,PC_NEW

;/*
;**        }
;*/

not_new:

;/*
;**       /**************************************************************/
;**       /* this entry is now used                                     */
;**       /**************************************************************/
;**       rgb.rgb2_fcOptions |= PC_USED;
;*/


        or      al,PC_USED

;/*
;**       /**************************************************************/
;**       /* save away the rgb value with adjusted flags                */
;**       /**************************************************************/
;**       hdevpal->entries[ulStart].rgb = rgb;
;*/


        ror     eax,8           ;shift rgb2_fcOptions back
        mov     [edx].PALENTRY.rgb,eax

        add     edx,sizeof PALENTRY

;/*
;**       cclr--;
;*/

        dec     ecx

;/*
;**       ulStart++;
;*/


        jne     ispe_while_top
ispe_while_loop_quit:

;/*
;**    }
;**
;**    /******************************************************************/
;**    /* mark palette as having changed.                                */
;**    /******************************************************************/
;**    hdevpal->usFlags |= PAL_CHANGED;
;*/

        mov     esi,hdevpal
        or      [esi].DEVPAL.usFlags,PAL_CHANGED
        INVOKE  ChangedPalette,
                esi             ;hdevpal
        ret
InnerSetPaletteEntries ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = GetPaletteMemory
;*
;* DESCRIPTION   = Get a block of memory for a palette structure.  We may
;*                 wish to make this routine get enough memory for several
;*                 palettes at once (see the 8514 driver) but for now its as
;*                 simple as possible
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX
;*                 Registers Destroyed:
;*                        EAX,EDX,ECX
;*
;* INPUT         = hdevpal  :PDEVPAL
;*                 ppalinfo :DWORD
;*
;* OUTPUT        = hdevpal
;*
;* RETURN-NORMAL = ERROR_NEG
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

GetPaletteMemory PROC SYSCALL USES edx,
        hdevpal  :PDEVPAL,
        ppalinfo :DWORD          ;          

;                  mov     eax,sizeof DEVPAL
        mov     ebx,ppalinfo
        mov     eax,[ebx].PALETTEINFO.palinfo_cclr
        dec     eax
        mov     ebx,sizeof PALENTRY
        mul     ebx
        add     eax,sizeof DEVPAL
        lea     ebx,hdevpal

;/*
;**    hdevpal = AllocateMemory( sizeof(DEVPAL),
;**                              MT_PALETTE,
;**                              MO_SHARED );
;*/

        INVOKE  private_alloc

;/*
;**    if (hdevpal == NULL)
;*/

        cmp     ecx,0
        jz      gpm_ok

;/*
;**    {
;**        /**************************************************************/
;**        /* The allocation failed.                                     */
;**        /**************************************************************/
;**       return( (PDEVPAL)ERROR_NEG );
;*/

        mov     eax,ERROR_NEG
        jmp     gpm_exit

;/*
;**    }
;*/

gpm_ok:

;/*
;**       return( hdevpal );
;*/

        mov     eax,hdevpal
gpm_exit:
        ret
GetPaletteMemory ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = FreePaletteMemory
;*
;* DESCRIPTION   = free a palette structure
;*
;*                 we may want to save the memory for reuse later
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX
;*                 Registers Destroyed:
;*                        EAX,EDX,ECX
;*
;* INPUT         = hdevpal :PDEVPAL
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

FreePaletteMemory PROC SYSCALL,
        hdevpal :PDEVPAL

;/*
;**       FreeMemory(hdevpal);
;*/

        mov     ecx,hdevpal
        INVOKE  private_free
        ret

FreePaletteMemory ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = DeviceDeletePalette
;*
;* DESCRIPTION   = Delete the passed palette (ie. delete it from the current DC)
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX
;*                 Registers Destroyed:
;*                        EAX,EDX,ECX
;*
;* INPUT         = hdc             DC Handle
;*                 hdevpal         device palette handle
;*                 pdc             device display context handle
;*                 FunN          function number
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = OK
;* RETURN-ERROR  = ERROR_ZERO
;*
;**************************************************************************/

DeviceDeletePalette PROC SYSCALL,
        hdc     :HDC,
        hdevpal :PDEVPAL,
        hddc  :PDDC,
        FunN    :ULONG

;    /******************************************************************/
;    /* Get driver semaphore and perform entry checks                  */
;    /******************************************************************/
        cld
        ddc?    hddc

        mov     edx,hddc
        INVOKE  enter_driver

        mov     eax,0
        jc      ddp_exit_no_lock                 ;error logged

ifdef FIREWALLS

;/*
;** this test is firewalled since the 8514 driver claims that the
;** engine will have already done the test
;**
;** If the function is being called within an area or path
;** definition then we raise an error and leave immediately.
;**
;*/

        no_path_area    ddp_exit_error,both

endif ;/* FIREWALLS */

;/*
;**    /******************************************************************/
;**    /* Reset the dc to default color table.                           */
;**    /******************************************************************/
;**        INVOKE  eddc_ResetLogColorTable,
;**                hddc
;*/

        INVOKE  eddc_ResetLogColorTable,
                hddc

;/*
;**       pdc->DCIColFormat = LCOLF_DEFAULT;
;*/

        and      [edx].DDC.ddc_fbClrTbl,not(DDC_PALETTE+DDC_RGB_MODE+DDC_LOG_CLR_TBL)

ifdef FIREWALLS

;/*
;**    if (hdevpal != pdc->Palette)
;**    {
;**        DebugOutput("Device Delete palette: hdevpals do not agree...\n\r");
;**        if (!hdevpal)
;**        {
;**            DebugOutput("NULL hdevpal - using DC hdevpal...\n\r");
;**            hdevpal = pdc->Palette;
;**        }
;**    }
;*/

        assert  edx,E,hddc

        mov     eax,[edx].DDC.ddc_npdevpal
        cmp     eax,hdevpal
        je      same_pals
        mov     hdevpal,eax
        DebugMsg2       <Device Animate palette: hdevpals do not agree...>
same_pals:
endif ;/* FIREWALLS */


;/*
;** actually do the delete palette operation
;*/

        INVOKE  InnerDeletePalette,
                hdevpal

        assert  edx,E,hddc

;/*
;**       pdc->Palette = NULL;
;*/

        mov     [edx].DDC.ddc_npdevpal,0

;/*
;**    /******************************************************************/
;**    /* Release driver semaphore                                       */
;**    /******************************************************************/
;**       return(OK);
;*/

        mov     eax,1
        jmp     ddp_exit

ddp_exit_error:
        mov     eax,0
ddp_exit:
        INVOKE  leave_driver
ddp_exit_no_lock:
        ret
DeviceDeletePalette ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = InnerDeletePalette
;*
;* DESCRIPTION   = Inner delete palette decrements the palette usage count,
;*                 and if necessary frees up memory occupied by the palette
;*                 It is called from DeviceDeletePalette, and also if
;*                 necessary by Firewalled code in DisableDC and RestoreDC.
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX
;*                 Registers Destroyed:
;*                        EAX,EDX,ECX
;*
;* INPUT         = hdevpal         device palette handle to delete
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

InnerDeletePalette PROC SYSCALL USES EDX,
        hdevpal :PDEVPAL

;/*
;**    /******************************************************************/
;**    /* Decrement usage count                                          */
;**    /******************************************************************/
;**    if ( !(--hdevpal->cUsage) )
;*/

        mov     edx,hdevpal
        dec     [edx].DEVPAL.cUsage
        jnz     still_in_use

;/*
;**    {
;**        /**************************************************************/
;**        /* now zero. Destroy this palette.                            */
;**        /**************************************************************/
;*/

        dec     GlobalPalCount

        INVOKE  FreePaletteMemory,
                edx

;/*
;**        /**************************************************************/
;**        /* Check foreground palette                                   */
;**        /**************************************************************/
;**        if ( hForeGroundPal == hdevpal )
;*/

        mov     edx,hdevpal
        cmp     edx,hForeGroundPal
        jne     @F

;/*
;**        {
;**            hForeGroundPal = NULL;
;*/

                mov     hForeGroundPal,0

;/*
;**        }
;*/

@@:

;/*
;** Invalidate the palette mapping cache if it uses this palette.
;*/

        INVOKE  ChangedPalette,
                edx

;/*
;**   }
;*/

still_in_use:
        ret
InnerDeletePalette ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = CountFreeSlots
;*
;* DESCRIPTION   = counts unused slots in a palette
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX
;*                 Registers Destroyed:
;*                        EAX,EDX,ECX
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

CountFreeSlots PROC SYSCALL USES ESI

;/*
;**    ulFreeSlots = 0;
;*/

        mov     eax,0

;/*
;**    for (i = 0; i < HW_PAL_SIZE; i++)
;*/

        mov     ecx,HW_PAL_SIZE
        lea     esi,HWPalette

;/*
;**    {
;*/

cfs_loop:

;/*
;**       HWPalette is an array of RGB2 structures
;**       if (!(HWPalette[i].rgb2_fcOptions & (PC_USED | PC_DEFAULT)))
;**       {
;**           ulFreeSlots++;
;**       }
;*/

                .errnz  sizeof RGB2-4
                test    [esi].RGB2.rgb2_fcOptions,PC_USED+PC_DEFAULT
                jnz     @F
                inc     eax
@@:
                add     esi,sizeof RGB2
                dec     ecx
                jnz     cfs_loop

;/*
;**    }
;**    return(ulFreeSlots);
;*/

        ret
CountFreeSlots ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = RealizePalette
;*
;* DESCRIPTION   = Realize palette is the heart of the Palette Manager.
;*                 It takes a logical palette and assigns it slots in the
;*                 hardware palette.  Realizing a palette only works on a
;*                 device DC.
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX
;*                 Registers Destroyed:
;*                        EAX,EDX,ECX
;*
;* INPUT         = hdc             DC handle
;*                 pflType         specifies foreground or not, and we use it to
;*                                 return whether the default colors have changed
;*                 pcSlotsChanged  pointer to returned count of h/w slots changed
;*                 pdc             device DC handle
;*                 FunN            function and COM_ bits
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = number of mappings which changed
;* RETURN-ERROR  = PAL_ERROR
;*
;**************************************************************************/

RealizePalette PROC SYSCALL USES ESI EDI EBX,
        hdc             :HDC,
        pflType         :PULONG,
        pcSlotsChanged  :PULONG,
        hddc            :PDDC,
        FunN            :ULONG

LOCAL   cMappingsChanged:ULONG

;/*
;** Get driver semaphore and perform entry checks.
;*/

        cld
        ddc?    hddc

        mov     edx,hddc
        INVOKE  enter_driver

        mov     eax,0
        jc      rp_exit_no_lock                  ;error logged

;/*
;**    /******************************************************************/
;**    /* initialize return values in case we bail out early             */
;**    /* return values of zero means nothing in the H/W palette changed */
;**    /******************************************************************/
;**    *pcSlotsChanged  = 0;
;*/

        mov     ebx,pcSlotsChanged
        mov     DWORD PTR [ebx],0

;/*
;**    cMappingsChanged = 0;
;*/

        mov     cMappingsChanged,0

;/*
;**    /******************************************************************/
;**    /* NB. we dont firewall the path/area test because the 8514 does  */
;**    /* not                                                            */
;**    /* (it could be due to the fact that RealizePalette is called by  */
;**    /* pmwin not the GPI level)                                       */
;**    /******************************************************************/
;**    /******************************************************************/
;**    /* If the function is being called within an area or path         */
;**    /* definition then we raise an error and leave immediately.       */
;**    /******************************************************************/
;*/

        no_path_area    rp_exit_error,both

;/*
;**    /******************************************************************/
;**    /* Realize palette only does anything on a device DC.             */
;**    /* If a logical color table is currently realized it overrides    */
;**    /* any realize palette calls (RealizeLCT should only happen       */
;**    /* when the app is maximized and in the foreground, so we have to */
;**    /* make the assumption that any app that has done this knows      */
;**    /* what it is doing).                                             */
;**    /******************************************************************/
;**    if (pdc->DCIDCType == OD_DIRECT &&
;**        !ColorTableRealized)
;**        cmp     [edx].DDC.DCIDCType,OD_DIRECT
;**        jne     rp_skip_it
;*/

        test    [edx].DDC.ddc_fb,DDC_DEVICE
        jz      rp_skip_it
        cmp     ColorTableRealized,0
        jne     rp_skip_it

;/*
;**   {
;**        /**************************************************************/
;**        /* If this DC has a palette associated with it then we must   */
;**        /* realize it.  If it does not have a palette associated with */
;**        /* it then we must realize the default palette.  Realizing    */
;**        /* the default palette only needs to be done if the DC is in  */
;**        /* the foreground because if we were in the background then   */
;**        /* we would not be able to write to the slots which had been  */
;**        /* changed anwyay.  DCs in the background must just assume    */
;**        /* that the default palette is realized.                      */
;**        /**************************************************************/
;**        if (pdc->DCIColFormat == LCOLF_PALETTE)
;**        {
;*/

        test    [edx].DDC.ddc_fbClrTbl,DDC_PALETTE
        jz      no_pal_associated
ifdef FIREWALLS

;/*
;**            if (pdc->Palette == NULL)
;**            {
;**                haltproc();
;**            }
;*/

                assert  [edx].DDC.ddc_npdevpal,NE,0

endif ;/* FIREWALLS */

;/*
;**            /**********************************************************/
;**            /* InnerRealizePalette is responsible for realizing a     */
;**            /* proper palette manager palette (ie. not the default    */
;**            /* palette).  It will change the HW slots and markings as */
;**            /* required.                                              */
;**            /**********************************************************/
;**            cMappingsChanged = InnerRealizePalette(pflType,pcSlotsChanged);
;*/

                INVOKE  InnerRealizePalette,
                        hddc,
                        pflType,
                        pcSlotsChanged

                mov     cMappingsChanged,eax

;/*
;**            /**********************************************************/
;**            /* Make sure that the next time we realize the default    */
;**            /* palette in the foreground we do not increase the size  */
;**            /* of the default palette if we have just realized in the */
;**            /* foreground.  (See below).                              */
;**            /**********************************************************/
;**            if (*pflType & RP_FOREGROUND)
;*/

                mov     eax,pflType
                test    DWORD PTR[eax],RP_FOREGROUND
                jz      skip_else

;/*
;**            {
;**                ulFreeSlotsLastTime = 0;
;*/

                mov     ulFreeSlotsLastTime,0

;/*
;**            }
;*/

                jmp     skip_else

;/*
;**        }
;*/

no_pal_associated:

;/*
;**        /**************************************************************/
;**        /* no palette means 'realize' the default palette             */
;**        /* this only makes sense in the foreground                    */
;**        /* (in the background we must always assume the default       */
;**        /* palette is realized)                                       */
;**        /**************************************************************/
;**        else if (*pflType & RP_FOREGROUND)
;*/

        mov     eax,pflType
        mov     eax,DWORD PTR[eax]
        test    eax,RP_FOREGROUND
        jz      @F

;/*
;**        {
;**            /**********************************************************/
;**            /* Only realize the default palette if it was not the     */
;**            /* last palette realized or there are enough free slots   */
;**            /* to increase the size of the default palette and there  */
;**            /* were also enough free slots the time before.  This     */
;**            /* helps stop us from being premature in the (rare) case  */
;**            /* of the foreground application using a cached PS,       */
;**            /* responding to realize messages by repainting, and      */
;**            /* realizing the default palette within its paint         */
;**            /* routine!                                               */
;**            /**********************************************************/
;**            ulFreeSlots = CountFreeSlots();
;*/

                INVOKE  CountFreeSlots
                mov     edi,eax
                mov     esi,ulDirectDeviceDefaultPaletteSize

;/*
;**            if (  (hForeGroundPal != (PDEVPAL)DirectDeviceDefaultPalette)
;**               || (ulDirectDeviceDefaultPaletteSize <= ulFreeSlotsLastTime))
;*/

                mov     eax,DirectDeviceDefaultPalette
                cmp     eax,hForeGroundPal
                jne     realize_it
                cmp     esi,ulFreeSlotsLastTime
                ja      dont_realize
realize_it:

;/*
;**            {
;**                StoreAndRemoveUsedMarkings();
;*/

                INVOKE  StoreAndRemoveUsedMarkings

;/*
;**                if (ulDirectDeviceDefaultPaletteSize <= ulFreeSlots)
;**----------------------------------------------------------------------
;** Now:
;**               ebx = pcSlotsChanged
;**               esi = ulDirectDeviceDefaultPaletteSize
;**               edi = ulFreeSlots
;**----------------------------------------------------------------------
;*/

                cmp     esi,edi
                ja      rdl_else

;/*
;**               {
;**                    do
;*/

realize_doloop:

;/*
;**                    {
;**                        ulFreeSlots -= ulDirectDeviceDefaultPaletteSize;
;*/

                        sub     edi,esi

;/*
;**                        *pcSlotsChanged = IncreaseDefaultPaletteSize();
;*/

                        INVOKE  IncreaseDefaultPaletteSize
                        mov     DWORD PTR [ebx],eax
                        mov     esi,ulDirectDeviceDefaultPaletteSize

;/*
;**                    } while (ulDirectDeviceDefaultPaletteSize <= ulFreeSlots);
;*/

                cmp     esi,edi
                jbe     realize_doloop

                jmp     rdl_end_else

;/*
;**                }
;*/

rdl_else:

;/*
;**                else
;**                {
;**                    *pcSlotsChanged = RealizeDefaultPalette();
;*/

                        INVOKE  RealizeDefaultPalette
                        mov     DWORD PTR [ebx],eax

;/*
;**                }
;*/

rdl_end_else:

;/*
;**                hForeGroundPal = (PDEVPAL)DirectDeviceDefaultPalette;
;*/

                mov     eax,DirectDeviceDefaultPalette
                mov     hForeGroundPal,eax

;               inc     usGlobalOptimizeID

ifdef   SEAMLESS

;/*
;**                /******************************************************/
;**                /* Update the seamless palette changed time stamp to  */
;**                /* indicate         palette mappings could now be     */
;**                /* invalid.                                           */
;**                /******************************************************/
;**                SeamlessData.ulLastPalUpdate++;
;*/

                inc     SM_WINDRV.ulLastPalUpdate
endif

;/*
;**                /******************************************************/
;**                /* If we had to change some of the HW slots in order  */
;**                /* to realize the default palette then we must clear  */
;**                /* all of the PC_USED slot markings ready for other   */
;**                /* palettes to be re-realized.  (When we return the   */
;**                /* number of slots changed as non-zero realize        */
;**                /* messages are sent to all the other windows).       */
;**                /******************************************************/
;**                if (*pcSlotsChanged)
;*/

                cmp     DWORD PTR [ebx],0
                jz      @F

;/*
;**                {
;**                    /* Defect 65655 - Only update usGlobalOptimizeID  */
;**                    /* if the state of the HW palette has changed     */
;/*
;**                    usGlobalOptimizeID++;
;*/

                       inc     usGlobalOptimizeID       ;          
;/*
;**                    RemoveUsedMarkings();
;*/

                        INVOKE  RemoveUsedMarkings

;/*
;**                    *pflType |= RP_DEFAULTSCHANGED;
;*/

                        mov     eax,pflType
                        or      DWORD PTR [eax],RP_DEFAULTSCHANGED

;/*
;**                }
;*/

@@:

;/*
;**            }
;*/

dont_realize:

;/*
;**            /**********************************************************/
;**            /* Keep a copy of the number of free slots to help us to  */
;**            /* decide when to increase the default palette size.      */
;**            /**********************************************************/
;**            ulFreeSlotsLastTime = ulFreeSlots;
;*/

                mov     ulFreeSlotsLastTime,edi

;/*
;**        }
;*/

skip_else:

;/*
;**        /**************************************************************/
;**        /* If we have made some changes to the HW palette...          */
;**        /**************************************************************/
;**        if (*pcSlotsChanged)
;*/

        cmp     DWORD PTR [ebx],0
        jz      hwpal_nochange

;/*
;**        {
;**            /**********************************************************/
;**            /* Update the values in the real HW palette.              */
;**            /**********************************************************/
;**            LoadPaletteEntries(0, HW_PAL_SIZE, HWPalette );
;**
;*/

                INVOKE  LoadPaletteEntries,
                        0,
                        HW_PAL_SIZE,
                        ADDR HWPalette

;/*
;**            /**********************************************************/
;**            /* Invalidate the palette-palette mapping table if        */
;**            /* necessary.                                             */
;**            /**********************************************************/
;**            HWPaletteChanged();
;*/

                INVOKE  HWPaletteChanged

;/*
;**        }
;*/

hwpal_nochange:

        mov     edx,hddc

;/*
;**        if (  (pdc->DCIColFormat != LCOLF_PALETTE)
;**           && (*pflType & RP_FOREGROUND)
;**           && (*pcSlotsChanged == 0) )
;*/


        test    [edx].DDC.ddc_fbClrTbl,DDC_PALETTE
        jnz     real_fore_size_changed
        mov     eax,pflType
        test    DWORD PTR [eax],RP_FOREGROUND
        jz      real_fore_size_changed
        cmp     DWORD PTR [ebx],0
        jne     real_fore_size_changed

;/*
;**        {
;**            /**********************************************************/
;**            /* We were asked to realize  the default palette in the   */
;**            /* foreground but did not increase the default palette    */
;**            /* size.  At this point we do something cunning.  We      */
;**            /* return that there have been HW slots changed but no    */
;**            /* mapping changes.  This means that realize messages     */
;**            /* will be sent to all of the other         but no        */
;**            /* repainting will be required.  This way we will get     */
;**            /* realize calls from any palettes still being used.      */
;**            /* This stops us from trying to increase the default      */
;**            /* palette size next time round if it is not appropriate. */
;**            /**********************************************************/
;**            if (ulDirectDeviceDefaultPaletteSize != 256)
;*/

                cmp     ulDirectDeviceDefaultPaletteSize,256
                je      @F

;/*
;**            {
;**                *pcSlotsChanged = 1;
;*/

                mov     DWORD PTR [ebx],1

;/*
;**            }
;*/

@@:

;/*
;**        }
;*/

real_fore_size_changed:

;/*
;**    }
;*/

rp_skip_it:

;/*
;**    /******************************************************************/
;**    /* Chose the appropriate AVIO color table for this size default   */
;**    /* palette.                                                       */
;**    /******************************************************************/
;**    switch (ulDirectDeviceDefaultPaletteSize)
;*/

        mov     eax,ulDirectDeviceDefaultPaletteSize
        mov     edi,0

;/*
;**    {
;**        case 256:
;*/

        cmp     eax,256
        jne     @F

;/*
;**            pAVIOColorXlate = AVIOXlate256;
;**            break;
;*/

        lea     edi,AVIOXlate256
        jmp     end_switch

;/*
;**        case 128:
;*/

@@:
        cmp     eax,128
        jne     @F

;/*
;**            pAVIOColorXlate = AVIOXlate128;
;**            break;
;*/

        lea     edi,AVIOXlate128
        jmp     end_switch

;/*
;**        case 64:
;*/

@@:
        cmp     eax,64
        jne     @F

;/*
;**            pAVIOColorXlate = AVIOXlate64;
;**            break;
;*/

        lea     edi,AVIOXlate64
        jmp     end_switch

;/*
;**        case 32:
;*/

@@:
        cmp     eax,32
        jne     @F

;/*
;**            pAVIOColorXlate = AVIOXlate32;
;**            break;
;*/

        lea     edi,AVIOXlate32
        jmp     end_switch

;/*
;**        case 16:
;*/

@@:
        cmp     eax,16
        jne     end_switch

;/*
;**            pAVIOColorXlate = AVIOXlate16;
;*/

        lea     edi,AVIOXlate16

;/*
;**            break;
;*/

end_switch:
        mov     pAVIOColorXlate,edi

;/*
;**    }
;**
;**    /******************************************************************/
;**    /* The physical indices in the AVIO table may never have been     */
;**    /* set up.                                                        */
;**    /******************************************************************/
;**    if (pAVIOColorXlate[0] == CLR_NOPHYINDEX)
;*/

        cmp     DWORD PTR [edi],CLR_NOPHYINDEX
        jne     clr_ok

;/*
;**    {
;*/

        mov     ebx,0
        jmp     avio_loop_enter
avio_loop_top:

;/*
;**        for (i=0; i < AVIO_PALETTE_SIZE; i++)
;**        {
;**            pAVIOColorXlate[i] =
;**                   NearestDirectDefaultPhysicalIndex(AVIOColorTable[i]);
;*/




        INVOKE  NearestDirectDefaultPhysicalIndex,
        AVIOColorTable[ebx*sizeof RGB2]

        mov     DWORD PTR [edi+(ebx*sizeof ULONG)],eax
        inc     ebx
avio_loop_enter:
        cmp     ebx,AVIO_PALETTE_SIZE
        jb      avio_loop_top

;/*
;**        }
;**    }
;*/

clr_ok:


;/*
;** If the mappings have changed then we must indicate this to the
;** palette->palette mapping cache code.
;*/

        mov     esi,cMappingsChanged

;/*
;**    if (cMappingsChanged)
;*/

        cmp     esi,0
        je      @F

;/*
;**    {
;**        ChangedPalette(pdc->Palette);
;*/

        mov     edx,hddc
        INVOKE  ChangedPalette,
                [edx].DDC.ddc_npdevpal

;/*
;**    }
;*/

@@:

;/*
;**    /******************************************************************/
;**    /* Release driver semaphore                                       */
;**    /******************************************************************/
;**       return(cMappingsChanged);
;*/

        mov     eax,esi
        jmp     rp_exit

rp_exit_error:
        mov     eax,PAL_ERROR
rp_exit:
        INVOKE  leave_driver
rp_exit_no_lock:
        ret
RealizePalette ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = RealizeDefaultPalette
;*
;* DESCRIPTION   = This routine puts the default entries back in the h/w
;*                 palette, and returns the number of h/w entries changed
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX
;*                 Registers Destroyed:
;*                        EAX,EDX,ECX
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = number of h/w entries changed
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

RealizeDefaultPalette PROC SYSCALL USES ESI EDI EBX

;/*
;** LOCAL   i               :ULONG,
;**         slotchanges     :ULONG
;** ecx is i
;** ebx is slotchanges
;*/


;/*
;**    slotchanges = 0;
;*/

        mov     ebx,0

;/*
;** The size of the default palette is dependent on the number of
;** HW palette slots that have been allocated to be used by real
;** palette mananger palettes.  The size of the default palette is
;** always one of 16, 32, 64, 128, or 256 so that mixes of the
;** colors in the default palette can not be changed by changes in
;** other palettes.  If the default palette is not 256 entries
;** then it is split between the start and end of the HW palette.
;*/

        ASSUME  edi:NOTHING

        mov     ecx,ulDirectDeviceDefaultPaletteSize
        shr     ecx,1
        jz      end_while
        mov     edx,ecx                 ;save for later
        mov     esi,DirectDeviceDefaultPalette
        lea     edi,HWPalette
top_for:

;/*
;**    for (i=0; i < ulDirectDeviceDefaultPaletteSize/2; i++)
;**    {
;*/


;/*
;**        if (!(HWPalette[i].rgb2_fcOptions & PC_DEFAULT))
;*/

        test    [edi].RGB2.rgb2_fcOptions,PC_DEFAULT
        jnz     its_pcdefault

;/*
;**        {
;**            /**************************************************/
;**            /* this entry is currently not default            */
;**            /* so reload it and count the change to the h/w   */
;**            /**************************************************/
;**            slotchanges++;
;*/

                inc     ebx

;/*
;**            HWPalette[i] = DirectDeviceDefaultPalette[i];
;*/

                .errnz  sizeof RGB2 - 4
                mov     eax,DWORD PTR [ESI]
                mov     DWORD PTR [EDI],eax

;/*
;**        }
;*/

its_pcdefault:
        add     esi,sizeof RGB2
        add     edi,sizeof RGB2
        dec     ecx
        jnz     top_for

;/*
;**    }
;*/

end_for:

;/*
;**    /**********************************************************/
;**    /* now the values at the end of the table                 */
;**    /**********************************************************/
;**    while (i<ulDirectDeviceDefaultPaletteSize)
;*/

        mov     ecx,edx
        lea     edi,HWPalette[HW_PAL_SIZE * sizeof RGB2]
        .errnz  sizeof RGB2 - 4
        shl     edx,2
        sub     edi,edx
top_while:

;/*
;**    {
;**        /**************************************************************/
;**        /* This define is to make the conditional statement and the   */
;**        /* following assignment more readable.                        */
;**        /* Note that j depends on i, so changes for each pass of the  */
;**        /* loop.                                                      */
;**        /**************************************************************/
;** #define j (HW_PAL_SIZE-ulDirectDeviceDefaultPaletteSize+i)
;**
;**        if (!(HWPalette[j].rgb2_fcOptions & PC_DEFAULT))
;**        {
;*/

        test    [edi].RGB2.rgb2_fcOptions,PC_DEFAULT
        jnz     @F

;/*
;**            /**************************************************/
;**            /* this entry is currently not default            */
;**            /* so reload it and count the change to the h/w   */
;**            /**************************************************/
;**            slotchanges++;
;*/

                inc     ebx

;/*
;**            HWPalette[j] = DirectDeviceDefaultPalette[i];
;*/

                mov     eax,DWORD PTR [ESI]
                mov     DWORD PTR [EDI],eax

;/*
;**        }
;*/

@@:

;/*
;** #undef j
;**        i++;
;*/

        add     esi,sizeof RGB2
        add     edi,sizeof RGB2
        dec     ecx
        jnz     top_while

;/*
;**    }
;*/

end_while:
ifdef SEAMLESS

;/*
;**    /******************************************************************/
;**    /* If we are realizing the 16 entry default palette then we must  */
;**    /* also fudge in the middle 4         system colors.  (See        */
;**    /* fudgepal.c)                                                    */
;**    /******************************************************************/
;**    if (ulDirectDeviceDefaultPaletteSize == 16)
;*/

        cmp     ulDirectDeviceDefaultPaletteSize,16
        jne     seam_end
        lea     esi,HWPalette
        lea     edi,WindowsDefaultSysColors
        ASSUME  ESI:PTR RGB2

;/*
;**    {
;**        if (!(HWPalette[8].fcOptions & PC_DEFAULT))
;*/

        test    [esi+(8*sizeof RGB2)].rgb2_fcOptions,PC_DEFAULT
        jnz     seam_1

;/*
;**        {
;**            slotchanges++;
;*/

        inc     ebx

;/*
;**            HWPalette[8] = WindowsDefaultSysColors[8];
;*/

        mov     eax,DWORD PTR [edi+(8*sizeof RGB2)]
        mov     DWORD PTR [esi+(8*sizeof RGB2)],eax

;/*
;**        }
;*/

seam_1:

;/*
;**        if (!(HWPalette[9].fcOptions & PC_DEFAULT))
;*/

        test    [esi+(9*sizeof RGB2)].rgb2_fcOptions,PC_DEFAULT
        jnz     seam_2

;/*
;**        {
;**            slotchanges++;
;*/

        inc     ebx

;/*
;**            HWPalette[9] = WindowsDefaultSysColors[9];
;*/

        mov     eax,DWORD PTR [edi+(9*sizeof RGB2)]
        mov     DWORD PTR [esi+(9*sizeof RGB2)],eax

;/*
;**        }
;*/

seam_2:

;/*
;**        if (!(HWPalette[246].fcOptions & PC_DEFAULT))
;*/

        test    [esi+(246*sizeof RGB2)].rgb2_fcOptions,PC_DEFAULT
        jnz     seam_3

;/*
;**        {
;**            slotchanges++;
;*/

        inc     ebx

;/*
;**            HWPalette[246] = WindowsDefaultSysColors[10];
;*/

        mov     eax,DWORD PTR [edi+(10*sizeof RGB2)]
        mov     DWORD PTR [esi+(246*sizeof RGB2)],eax

;/*
;**        }
;*/

seam_3:

;/*
;**        if (!(HWPalette[247].fcOptions & PC_DEFAULT))
;*/

        test    [esi+(247*sizeof RGB2)].rgb2_fcOptions,PC_DEFAULT
        jnz     seam_end

;/*
;**        {
;**            slotchanges++;
;*/

        inc     ebx

;/*
;**            HWPalette[247] = WindowsDefaultSysColors[11];
;*/

        mov     eax,DWORD PTR [edi+(11*sizeof RGB2)]
        mov     DWORD PTR [esi+(247*sizeof RGB2)],eax

;/*
;**        }
;*/

seam_end:

;/*
;**    }
;*/

endif   ;SEAMLESS

;/*
;**    /******************************************************************/
;**    /* return the number of h/w slot entries that were changed        */
;**    /******************************************************************/
;**       return (slotchanges);
;*/

        mov     eax,ebx
        ret
RealizeDefaultPalette ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = ReduceDefaultPaletteSize
;*
;* DESCRIPTION   = This routine reduces the size of the default palette by a
;*                 factor of two, to a minimum size of 16 entries.
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX
;*                 Registers Destroyed:
;*                        EAX,EDX,ECX
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ReduceDefaultPaletteSize PROC SYSCALL USES EDI EBX

LOCAL   ulSlotsChanged  :ULONG

;/*
;** i               :ULONG,
;** ecx/ebx is i
;*/


        ASSUME  edi:NOTHING

;/*
;** Work out how many slots we will now allocate to the device
;** default palette and which palette to use.
;*/

        mov     ecx,ulDirectDeviceDefaultPaletteSize

;/*
;**    if (ulDirectDeviceDefaultPaletteSize == 256)
;**    {
;*/

        cmp     ecx,256
        jne     @F
        DebugMsg2       <ReduceDefaultPaletteSize 256-128 >

;/*
;**        ulDirectDeviceDefaultPaletteSize = 128;
;**        DirectDeviceDefaultPalette = Reduced128DeviceDefaultPalette;
;**        DefaultDirectLogicalColorTable = DefaultEightBppTable128;
;*/

        mov     ulDirectDeviceDefaultPaletteSize,128

        lea     eax,Reduced128DeviceDefaultPalette
        mov     DirectDeviceDefaultPalette,eax

        lea     eax,DefaultEightBppTable128
        mov     DefaultDirectLogicalColorTable,eax

        jmp     end_ifs

;/*
;**    }
;**    else if (ulDirectDeviceDefaultPaletteSize == 128)
;*/

@@:
        cmp     ecx,128
        jne     @F
        DebugMsg2       <ReduceDefaultPaletteSize 128-64>

;/*
;**    {
;**        ulDirectDeviceDefaultPaletteSize = 64;
;**        DirectDeviceDefaultPalette = Reduced64DeviceDefaultPalette;
;**        DefaultDirectLogicalColorTable = DefaultEightBppTable64;
;*/

        mov     ulDirectDeviceDefaultPaletteSize,64

        lea     eax,Reduced64DeviceDefaultPalette
        mov     DirectDeviceDefaultPalette,eax

        lea     eax,DefaultEightBppTable64
        mov     DefaultDirectLogicalColorTable,eax

        jmp     end_ifs

;/*
;**    }
;**    else if (ulDirectDeviceDefaultPaletteSize == 64)
;*/

ifndef SEAMLESS

;/*
;** Skip the 32 entry palette when seamless because it does not    */
;** fit well with         system colors and DCR 1590.              */
;*/

@@:
        cmp     ecx,64
        jne     @F
        DebugMsg2       <ReduceDefaultPaletteSize 64-32 >

;/*
;**    {
;**        ulDirectDeviceDefaultPaletteSize = 32;
;**        DirectDeviceDefaultPalette = Reduced32DeviceDefaultPalette;
;**        DefaultDirectLogicalColorTable = DefaultEightBppTable32;
;*/

        mov     ulDirectDeviceDefaultPaletteSize,32

        lea     eax,Reduced32DeviceDefaultPalette
        mov     DirectDeviceDefaultPalette,eax

        lea     eax,DefaultEightBppTable32
        mov     DefaultDirectLogicalColorTable,eax

        jmp     end_ifs

;/*
;**    }
;**    else if (ulDirectDeviceDefaultPaletteSize == 32)
;*/

endif   ;!SEAMLESS
@@:
        cmp     ecx,32
        jne     @F
        DebugMsg2       <ReduceDefaultPaletteSize 32-16 >

;/*
;**    {
;**        ulDirectDeviceDefaultPaletteSize = 16;
;**        DirectDeviceDefaultPalette = Reduced16DeviceDefaultPalette;
;**        DefaultDirectLogicalColorTable = DefaultEightBppTable16;
;*/

        mov     ulDirectDeviceDefaultPaletteSize,16

        lea     eax,Reduced16DeviceDefaultPalette
        mov     DirectDeviceDefaultPalette,eax

        lea     eax,DefaultEightBppTable16
        mov     DefaultDirectLogicalColorTable,eax

        jmp     end_ifs

;/*
;**    }
;**    else
;*/

@@:

;/*
;**    {
;**        /**************************************************************/
;**        /* If the size of the default palette is not 32, 64, 128, or  */
;**        /* 256 then something has gone wrong! The best we can do is   */
;**        /* just guess and use the smallest possible default palette.  */
;**        /**************************************************************/
;**        ulDirectDeviceDefaultPaletteSize = 16;
;**        DirectDeviceDefaultPalette = Reduced16DeviceDefaultPalette;
;**        DefaultDirectLogicalColorTable = DefaultEightBppTable16;
;*/

        DebugMsg2       <ReduceDefaultPaletteSize 16-INVALID>
        mov     ulDirectDeviceDefaultPaletteSize,16

        lea     eax,Reduced16DeviceDefaultPalette
        mov     DirectDeviceDefaultPalette,eax

        lea     eax,DefaultEightBppTable16
        mov     DefaultDirectLogicalColorTable,eax
ifdef FIREWALLS

;/*
;**       haltproc();
;*/

        DebugMsg2       <ERROR: Default Palette is invalid size!!! >
        ;int 3
endif ;/* FIREWALLS */

;/*
;**    }
;*/


end_ifs:


;/*
;** Clear all of the PC_DEFAULT flags in the copy of the HW
;** palette so that RealizeDefaultPalette will overwrite the
;** previous default palette slots with the new values.
;*/

        mov     ecx,HW_PAL_SIZE
        lea     edi,HWPalette

;/*
;**    for (i = 0; i < HW_PAL_SIZE; i++)
;*/

for1_top:

;/*
;**    {
;**        HWPalette[i].rgb2_fcOptions &= ~PC_DEFAULT;
;*/


        and     [edi].RGB2.rgb2_fcOptions,NOT PC_DEFAULT
        add     edi,sizeof RGB2
        dec     ecx
        jnz     for1_top

;/*
;**    }
;*/

for1_end:

;/*
;**    ulSlotsChanged = RealizeDefaultPalette();
;*/

        INVOKE  RealizeDefaultPalette

        mov     ulSlotsChanged,eax

;/*
;** Now go through the direct device special color table and       */
;** recalculate all the system and special colors.                 */
;*/

        mov     ebx,SPECIAL_COL_TAB_SIZE
        lea     edi,DirectSpecialColorTable

;/*
;**    for (i = 0; i < SPECIAL_COL_TAB_SIZE; i++)
;*/

for2_top:

;/*
;**    {
;**        if (DirectSpecialColorTable[i].PhyIndex != CLR_NOPHYINDEX)
;*/

        cmp     [edi].COLORTABLETYPE.PhyIndex,CLR_NOPHYINDEX
        je      @F

;/*
;**        {
;**            DirectSpecialColorTable[i].PhyIndex =
;**                        NearestDirectDefaultPhysicalIndex(
;**                                DirectSpecialColorTable[i].LogRGB);
;*/


                INVOKE  NearestDirectDefaultPhysicalIndex,
                        [edi].COLORTABLETYPE.LogRGB

                mov     [edi].COLORTABLETYPE.PhyIndex,eax
@@:

;/*
;**        }
;*/

        add     edi,sizeof COLORTABLETYPE
        dec     ebx
        jnz     for2_top

;/*
;**    }
;*/

for2_end:

;/*
;**       return(ulSlotsChanged);
;*/

        mov     eax,ulSlotsChanged
        ret
ReduceDefaultPaletteSize ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = IncreaseDefaultPaletteSize
;*
;* DESCRIPTION   = This routine reduces the size of the default palette by a
;*                 factor of two, to a minimum size of 16 entries.
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX
;*                 Registers Destroyed:
;*                        EAX,EDX,ECX
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

IncreaseDefaultPaletteSize PROC SYSCALL USES EDI EBX

LOCAL   ulSlotsChanged :ULONG

;/*
;**    i              :ULONG,
;**
;**    /******************************************************************/
;**    /* Work out how many slots we will now allocate to the device     */
;**    /* default palette and which palette to use.                      */
;**    /******************************************************************/
;**    if (ulDirectDeviceDefaultPaletteSize == 128)
;*/

        mov     ecx,ulDirectDeviceDefaultPaletteSize
        cmp     ecx,128
        jne     @F
        DebugMsg2       <IncreaseDefaultPaletteSize 128-256 >

;/*
;**    {
;**        ulDirectDeviceDefaultPaletteSize = 256;
;**        DirectDeviceDefaultPalette = FullSizeDeviceDefaultPalette;
;**        DefaultDirectLogicalColorTable = DefaultEightBppTable256;
;*/

        mov     ulDirectDeviceDefaultPaletteSize,256

        lea     eax,FullSizeDeviceDefaultPalette
        mov     DirectDeviceDefaultPalette,eax

        lea     eax,DefaultEightBppTable256
        mov     DefaultDirectLogicalColorTable,eax

        jmp     end_ifs

;/*
;**    }
;**    else if (ulDirectDeviceDefaultPaletteSize == 64)
;*/

@@:
        cmp     ecx,64
        jne     @F
        DebugMsg2       <IncreaseDefaultPaletteSize 64-128 >

;/*
;**    {
;**        ulDirectDeviceDefaultPaletteSize = 128;
;**        DirectDeviceDefaultPalette = Reduced128DeviceDefaultPalette;
;**        DefaultDirectLogicalColorTable = DefaultEightBppTable128;
;*/

        mov     ulDirectDeviceDefaultPaletteSize,128

        lea     eax,Reduced128DeviceDefaultPalette
        mov     DirectDeviceDefaultPalette,eax

        lea     eax,DefaultEightBppTable128
        mov     DefaultDirectLogicalColorTable,eax

        jmp     end_ifs
ifndef SEAMLESS

;/*
;**    /******************************************************************/
;**    /* Skip the 32 entry palette when seamless because it does not    */
;**    /* fit well with         system colors and DCR 1590.              */
;**    /******************************************************************/
;**    }
;**    else if (ulDirectDeviceDefaultPaletteSize == 32)
;*/

@@:
        cmp     ecx,32
        jne     @F
        DebugMsg2       <IncreaseDefaultPaletteSize 32-64 >

;/*
;**    {
;**        ulDirectDeviceDefaultPaletteSize = 64;
;**        DirectDeviceDefaultPalette = Reduced64DeviceDefaultPalette;
;**        DefaultDirectLogicalColorTable = DefaultEightBppTable64;
;*/

        mov     ulDirectDeviceDefaultPaletteSize,64

        lea     eax,Reduced64DeviceDefaultPalette
        mov     DirectDeviceDefaultPalette,eax

        lea     eax,DefaultEightBppTable64
        mov     DefaultDirectLogicalColorTable,eax

        jmp     end_ifs

;/*
;**    }
;*/

endif ;!SEAMLESS

;/*
;**    else if (ulDirectDeviceDefaultPaletteSize == 16)
;*/

@@:
        cmp     ecx,16
        jne     @F
        DebugMsg2       <IncreaseDefaultPaletteSize 16-32 >

;/*
;**    {
;*/

ifndef SEAMLESS

;/*
;**        ulDirectDeviceDefaultPaletteSize = 32;
;**        DirectDeviceDefaultPalette = Reduced32DeviceDefaultPalette;
;**        DefaultDirectLogicalColorTable = DefaultEightBppTable32;
;*/

        mov     ulDirectDeviceDefaultPaletteSize,32

        lea     eax,Reduced32DeviceDefaultPalette
        mov     DirectDeviceDefaultPalette,eax

        lea     eax,DefaultEightBppTable32
        mov     DefaultDirectLogicalColorTable,eax

else

;/*
;**        ulDirectDeviceDefaultPaletteSize = 64;
;**        DirectDeviceDefaultPalette = Reduced64DeviceDefaultPalette;
;**        DefaultDirectLogicalColorTable = DefaultEightBppTable64;
;*/

        mov     ulDirectDeviceDefaultPaletteSize,64

        lea     eax,Reduced64DeviceDefaultPalette
        mov     DirectDeviceDefaultPalette,eax

        lea     eax,DefaultEightBppTable64
        mov     DefaultDirectLogicalColorTable,eax

endif ;!SEAMLESS
        jmp     end_ifs

;/*
;**    }
;**    else
;*/

@@:

;/*
;**    {
;**        /**************************************************************/
;**        /* If the size of the default palette is not 16, 32, 64, or   */
;**        /* 128 then something has gone wrong!  The best we can do is  */
;**        /* just guess and use the largest possible default palette.   */
;**        /**************************************************************/
;**        ulDirectDeviceDefaultPaletteSize = 256;
;**        DirectDeviceDefaultPalette = FullSizeDeviceDefaultPalette;
;**        DefaultDirectLogicalColorTable = DefaultEightBppTable256;
;*/

        DebugMsg2       <IncreaseDefaultPaletteSize INVALID-256 >
        mov     ulDirectDeviceDefaultPaletteSize,256

        lea     eax,FullSizeDeviceDefaultPalette
        mov     DirectDeviceDefaultPalette,eax

        lea     eax,DefaultEightBppTable256
        mov     DefaultDirectLogicalColorTable,eax
ifdef FIREWALLS

;/*
;**        haltproc();
;*/

        DebugMsg2       <ERROR: Default Palette is invalid size!!! >

endif ;/* FIREWALLS */

;/*
;**    }
;*/

end_ifs:

;/*
;** Clear all of the PC_DEFAULT flags in the copy of the HW
;** palette so that RealizeDefaultPalette will overwrite the
;** previous default palette slots with the new values.
;*/

        mov     ecx,HW_PAL_SIZE
        lea     edi,HWPalette

;/*
;**    for (i = 0; i < HW_PAL_SIZE; i++)
;*/

for1_top:

;/*
;**    {
;**        HWPalette[i].rgb2_fcOptions &= ~PC_DEFAULT;
;*/

        and     [edi].RGB2.rgb2_fcOptions,NOT PC_DEFAULT
        add     edi,sizeof RGB2
        dec     ecx
        jnz     for1_top

;/*
;**    }
;*/

for1_end:

;/*
;**    ulSlotsChanged = RealizeDefaultPalette();
;*/

        INVOKE  RealizeDefaultPalette
        mov     ulSlotsChanged,eax

;/*
;** Now go through the direct device special color table and
;** recalculate all the system and special colors.
;*/

        mov     ebx,SPECIAL_COL_TAB_SIZE
        lea     edi,DirectSpecialColorTable

;/*
;**    for (i = 0; i < SPECIAL_COL_TAB_SIZE; i++)
;*/

for2_top:

;/*
;**    {
;**        if (DirectSpecialColorTable[i].PhyIndex != CLR_NOPHYINDEX)
;*/

        cmp     [edi].COLORTABLETYPE.PhyIndex,CLR_NOPHYINDEX
        je      no_phy

;/*
;**        {
;**            DirectSpecialColorTable[i].PhyIndex =
;**                        NearestDirectDefaultPhysicalIndex(
;**                                DirectSpecialColorTable[i].LogRGB);
;*/

                INVOKE  NearestDirectDefaultPhysicalIndex,
                        [edi].COLORTABLETYPE.LogRGB

                mov     [edi].COLORTABLETYPE.PhyIndex,eax
no_phy:

;/*
;**        }
;*/

        add     edi,sizeof COLORTABLETYPE
        dec     ebx
        jnz     for2_top

;/*
;**    }
;*/

for2_end:

;/*
;**       return(ulSlotsChanged);
;*/

        mov     eax,ulSlotsChanged
        ret
IncreaseDefaultPaletteSize ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = RemoveUsedMarkings
;*
;* DESCRIPTION   = Marks all h/w palette entries as unused by any palettes.
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX,EDX
;*                 Registers Destroyed:
;*                        EAX,ECX
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

RemoveUsedMarkings PROC SYSCALL

;/*
;** LOCAL   i:ULONG
;*/

        DebugMsg2       <RemoveUsedMarkings>
        mov     ecx,HW_PAL_SIZE
        lea     eax,HWPalette

;/*
;**    for (i=0; i<HW_PAL_SIZE; i++)
;*/

for_top:

;/*
;**    {
;**        HWPalette[i].rgb2_fcOptions &= ~PC_USED;
;*/

        and     [eax].RGB2.rgb2_fcOptions,NOT PC_USED
        add     eax,sizeof RGB2
        dec     ecx
        jnz     for_top

;/*
;**    }
;*/

        ret
RemoveUsedMarkings ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = StoreAndRemoveUsedMarkings
;*
;* DESCRIPTION   = Copies PC_USED flags to PC_OLD flags and clears PC_USED
;*                 flags so that HW palette entries appear unused by any
;*                 palette, but the usages can be restored by a call to
;*                 RestoreUsedMarkings.
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX,EDX
;*                 Registers Destroyed:
;*                        EAX,ECX
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

StoreAndRemoveUsedMarkings PROC SYSCALL

;/*
;** LOCAL   i:ULONG
;*/

        DebugMsg2       <StoreAndRemoveUsedMarkings>
        mov     ecx,HW_PAL_SIZE
        lea     eax,HWPalette

;/*
;**    for (i=0; i<HW_PAL_SIZE; i++)
;*/

for_top:

;/*
;**    {
;**        if (HWPalette[i].rgb2_fcOptions & PC_USED)
;*/

        test    [eax].RGB2.rgb2_fcOptions,PC_USED
        jz      @F

;/*
;**        {
;**            HWPalette[i].rgb2_fcOptions |= PC_OLD;
;*/

        or      [eax].RGB2.rgb2_fcOptions,PC_OLD

;/*
;**            HWPalette[i].rgb2_fcOptions &= ~PC_USED;
;*/

        and     [eax].RGB2.rgb2_fcOptions,NOT PC_USED
        jmp     end_else

;/*
;**        }
;**        else
;*/

@@:

;/*
;**        {
;**            HWPalette[i].rgb2_fcOptions &= ~PC_OLD;
;*/

        and     [eax].RGB2.rgb2_fcOptions,NOT PC_OLD
end_else:

;/*
;**        }
;*/

        add     eax,sizeof RGB2
        dec     ecx
        jnz     for_top

;/*
;**    }
;*/

        ret
StoreAndRemoveUsedMarkings ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = RestoreUsedMarkings
;*
;* DESCRIPTION   = Copies PC_OLD flags to PC_USED flags.  This restores the
;*                 usage status of the HW palette back to what is was when
;*                 the last call to StoreAndRemoveUsedMarkings.
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX,EDX
;*                 Registers Destroyed:
;*                        EAX,ECX
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

RestoreUsedMarkings PROC SYSCALL

;/*
;** LOCAL   i:ULONG
;*/


        DebugMsg2       <RestoreUsedMarkings>
        mov     ecx,HW_PAL_SIZE
        lea     eax,HWPalette

;/*
;**    for (i=0; i<HW_PAL_SIZE; i++)
;*/

for_top:

;/*
;**    {
;**        if (HWPalette[i].rgb2_fcOptions & PC_OLD)
;*/

        test    [eax].RGB2.rgb2_fcOptions,PC_OLD
        jz      @F

;/*
;**        {
;**            HWPalette[i].rgb2_fcOptions |= PC_USED;
;*/

                or      [eax].RGB2.rgb2_fcOptions,PC_USED
@@:

;/*
;**        }
;*/

        add     eax,sizeof RGB2
        dec     ecx
        jnz     for_top

;/*
;**    }
;*/

        ret
RestoreUsedMarkings ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = InnerRealizePalette
;*
;* DESCRIPTION   = InnerRealizePalette is responsible for realizing a
;*                 proper Palette Manager palette (ie not the device
;*                 default palette).  Validity checks (such as is this a
;*                 device DC) have already been done.
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX
;*                 Registers Destroyed:
;*                        EAX,ECX,EDX
;*
;* INPUT         = pflType         specifies foreground or not, and also used
;*                                 to return whether the default colors have
;*                                 changed
;*                 pcSlotsChanged  pointer to returned count of h/w slots
;*                                 changed
;*
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = number of mappings which changed
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

InnerRealizePalette PROC SYSCALL USES EBX ESI EDI,
        hddc            :PDDC,
        pflType         :PULONG,
        pcSlotsChanged  :PULONG

LOCAL   localflags      :ULONG,
        MappingsChanged :ULONG,
        HWSlotsChanged  :ULONG,
        DefaultsChanged :ULONG,
        palcount        :ULONG,
        entry           :ULONG,
        slot            :ULONG,
        bNoFreeSlotAfter:BYTE,
        bNoFreeSlotBefore:BYTE

        HWPalSlot       TEXTEQU <edi>
        Entries_Entry   TEXTEQU <esi>

ifdef DEBUG2
        DebugMsg2       <InnerRealizePalette>
endif

;/*
;**    /******************************************************************/
;**    /* to prevent lots of segment loads to get at the palette flags   */
;**    /* we bring them in locally                                       */
;**    /******************************************************************/
;**    localflags = pdc->Palette->usFlags;
;*/

        mov     eax,hddc
        mov     ebx,[eax].DDC.ddc_npdevpal

        ASSUME  EBX:PDEVPAL

        mov     eax,[ebx].usFlags
        mov     localflags,eax

;/*
;** Assumptions:
;**       ebx = pdc->Palette
;*/

;/*
;**
;** The flags which we will look at during the realize operation
;** in order to decide exactly what to do are:
;**
;**  *pflType & RP_FOREGROUND
;**      - the palette is being realized in the foreground.
;**
;**  localflags & PAL_CHANGED
;**      - the palette needs to be realized (ie the current
;**        mappings are not upto date).
;**
;**  localflags & PAL_CURRENT_OK
;**      - the current mapping is valid (but not necessarily upto
;**        date).
;**
;**  localflags & PAL_PREVIOUS_OK
;**      - the previous mapping is valid (but not necessarily upto
;**        date).
;**
;**  localflags & LCOL_OVERRIDE_DEFAULT_COLORS
;**      - the palette can overide the entries in the default
;**      palette.
;**
;**
;*/


;/*
;**    /******************************************************************/
;**    /* Initialize the counts of changed made to zero.                 */
;**    /******************************************************************/
;**    MappingsChanged = HWSlotsChanged = DefaultsChanged = 0;
;*/

        mov     eax,0
        mov     MappingsChanged,eax
        mov     HWSlotsChanged,eax
        mov     DefaultsChanged,eax

;/*
;**
;** Now we must consider the global and local optimization
;** identifiers.
;**
;** Each time a palette is realized in the foreground the global
;** optimization identifier is incremented.  Each time a palette
;** is realized (whether in the foreground or the background) its
;** local optimization identifier is set to the global
;** optimization identifier.
;**
;** There are certain conditions under which we will not realize
;** the palette if its entries have not changed, saving a lot
;** of time:
;**
;** 1) If the palette is being realized in the background, and the
;**    local optimization id is the same as the global one.
;**    This indicates that the palette has already been realized
;**    since the last foreground realization, so just leave the
;**    mapping the way it is.
;**
;** 2) If the palette is being realized in the foreground, the
;**    local optimization id is the same as the global one, and
;**    the palette is already the foreground one.
;**
;**
;*/

        mov     ecx,pflType

;/*
;**
;** Assumptions:
;**       ebx = pdc->Palette
;**       ecx = pflType
;**
;**    if (!(localflags & PAL_CHANGED) &&
;**        pdc->Palette->usLocalOptimizeID == usGlobalOptimizeID)
;*/

        test    localflags,PAL_CHANGED
        jnz     local_op_ne_global
        mov     eax,usGlobalOptimizeID
        cmp     [ebx].usLocalOptimizeID,eax
        jne     local_op_ne_global

;/*
;**    {
;**        /**************************************************************/
;**        /* The palette is unchanged and the optimization identifiers  */
;**        /* are equal.                                                 */
;**        /**************************************************************/
;**        if (!(*pflType & RP_FOREGROUND) ||
;**            (pdc->Palette == hForeGroundPal))
;*/

        test    DWORD PTR [ecx],RP_FOREGROUND
        jz      no_need_to_realize
        cmp     ebx,hForeGroundPal
        je      no_need_to_realize

;/*
;**        {
;**            /**********************************************************/
;**            /* We are realizing in the background, or the palette is  */
;**            /* already the forground one anyway so there is no need   */
;**            /* to do any realization.                                 */
;**            /**********************************************************/
;**            goto no_need_to_realize
;**        }
;*/

local_op_ne_global:

;/*
;**    }
;*/

;/*
;**    /******************************************************************/
;**    /* looks like we'll have to realize this palette in some form     */
;**    /******************************************************************/
;**    if (*pflType & RP_FOREGROUND)
;*/

        test    DWORD PTR [ecx],RP_FOREGROUND
        jz      @F

;/*
;**    {
;**        /**************************************************************/
;**        /* this is in the forground, so update our global info        */
;**        /**************************************************************/
;**        hForeGroundPal = pdc->Palette;
;*/

        mov     hForeGroundPal,ebx

;/*
;**        usGlobalOptimizeID++;
;*/

        inc     usGlobalOptimizeID
ifdef SEAMLESS

;/*
;**        /**************************************************************/
;**        /* Update the seamless palette changed time stamp to indicate */
;**        /*         palette mappings could now be invalid.             */
;**        /**************************************************************/
;**        SeamlessData.ulLastPalUpdate++;
;*/

        inc     SM_WINDRV.ulLastPalUpdate

endif
@@:

;/*
;**    }
;**
;** Assumptions:
;**       ebx = pdc->Palette
;**       ecx = nothing
;**
;*/


;/*
;**    /******************************************************************/
;**    /* store the usGlobalOptimizeID value in the palette              */
;**    /******************************************************************/
;**    pdc->Palette->usLocalOptimizeID = usGlobalOptimizeID;
;*/

        mov     eax,usGlobalOptimizeID
        mov     [ebx].usLocalOptimizeID,eax

;/*
;**    /******************************************************************/
;**    /* get the number of logical palette entries to consider          */
;**    /******************************************************************/
;**    palcount = pdc->Palette->usCountStored;
;*/

        mov     eax,[ebx].usCountStored
        mov     palcount,eax

;/*
;**    /******************************************************************/
;**    /* if the current values are valid, copy them to the previous     */
;**    /* values                                                         */
;**    /******************************************************************/
;**    if (localflags & PAL_CURRENT_OK)
;*/

        test    localflags,PAL_CURRENT_OK
        jz      loop1_end

;/*
;**    {
;*/

        mov     ecx,palcount
        lea     Entries_Entry,[ebx].entries

        ASSUME  Entries_Entry:PPALENTRY

;/*
;**        for (entry=0; entry<palcount; entry++)
;*/

loop1_top:

;/*
;**        {
;**            pdc->Palette->entries[entry].bPrevious =
;**                                   pdc->Palette->entries[entry].bCurrent;
;*/

        mov     al,[Entries_Entry].bCurrent
        mov     [Entries_Entry].bPrevious,al

        add     Entries_Entry,sizeof PALENTRY
        dec     ecx
        jnz     loop1_top

;/*
;**        }
;*/

loop1_end:

;/*
;**    }
;*/


;/*
;**
;** We must now map the palette to the real HW palette...
;**
;**      if palette is being realized in the foreground then
;**         mark all HW palette slots as previously unused
;**         mark all used HW palette slots as previously used
;**         mark all HW palette slots as currently unused
;**      endif
;**      for each entry in palette
;**        if entry is marked as explict
;**          goto next_entry
;**        endif
;**        if we have an existing mapping
;**          if existing mapping gives exact slot
;**            if reserved/no_collapse/used flags do not clash
;**              use this existing mapping
;**              goto next_entry
;**            endif
;**          endif
;**        endif
;**        if entry is not marked as reserved or no_collapse
;**          for each hw slot
;**            if entry is exact match
;**              make mapping to this slot
;**              goto next_entry
;**            endif
;**          endfor
;**        endif
;**        if current foreground palette is the default
;**          if there were free slots when default realized
;**            make mapping to old free slot
;**            goto next_entry
;**          endif
;**        else if there are free hw slots
;**          make mapping to free slot
;**          goto next_entry
;**        endif
;**        if size of default palette can be reduced
;**          reduce default palette size
;**          make mapping to new free slot
;**        else if in foreground and overide defaults is enabled
;**          overwrite one of the default palette slots
;**        else
;**          make mapping to nearest color slot
;**        endif
;**        endif
;** next_entry:
;**      endfor
;**      if palette is being realized in the foreground
;**        if no HW palette slots were changed during realization
;**          mark previously used HW slots as currently used
;**        endif
;**      endif
;**
;**
;*/

;/*
;**    /******************************************************************/
;**    /* If the palette is being realized in the foreground...          */
;**    /******************************************************************/
;**    if (*pflType & RP_FOREGROUND)
;*/

        mov     ecx,pflType
        test    DWORD PTR [ecx],RP_FOREGROUND
        jz      not_being_real_in_fore

ifdef DEBUG2
        DebugMsg2       <Pal being realized in FOREGROUND>
endif

;/*
;**    {
;**        /**************************************************************/
;**        /* If the last foreground palette overwrote any of the        */
;**        /* default palette colors then we need to reinstate them.     */
;**        /**************************************************************/
;**        if (fForeGroundOverwrote)
;*/

        cmp     fForeGroundOverwrote,0
        jz      @F
ifdef DEBUG2
        DebugMsg2       <FOREGROUND was Overwritten>
endif

;/*
;**        {
;**            DefaultsChanged = RealizeDefaultPalette();
;*/

        INVOKE  RealizeDefaultPalette
        mov     DefaultsChanged,eax

;/*
;**            /**********************************************************/
;**            /* currently none of the default colors are overwritten   */
;**            /**********************************************************/
;**            fForeGroundOverwrote = FALSE;
;*/

        mov     fForeGroundOverwrote,FALSE
ifdef DEBUG2
        DebugMsg2       <FOREGROUND no longer Overwritten>
endif
@@:

;/*
;**        }
;**
;**        /**************************************************************/
;**        /* Clear all the HW palette slot PC_USED markings.  (But      */
;**        /* remember what they were so we can restore them later if    */
;**        /* realizing this palette makes no changes that will effect   */
;**        /* any of the palettes which are already realized).           */
;**        /**************************************************************/
;**        StoreAndRemoveUsedMarkings();
;*/

        INVOKE  StoreAndRemoveUsedMarkings

;/*
;**    }
;*/

not_being_real_in_fore:
set_up_realize_loop:

;/*
;**    /******************************************************************/
;**    /* Initialize out search range used when we are looking for empty */
;**    /* slots in the HW palette.                                       */
;**    /******************************************************************/
;**    bNoFreeSlotBefore = (BYTE)(ulDirectDeviceDefaultPaletteSize/2);
;*/

        mov     eax,ulDirectDeviceDefaultPaletteSize
        shr     eax,1
        mov     bNoFreeSlotBefore,al
        assert  EAX,LE,0ffh

;/*
;**    bNoFreeSlotAfter  = (BYTE)(255-(ulDirectDeviceDefaultPaletteSize/2));
;*/

        mov     ah,255
        sub     ah,al
        mov     bNoFreeSlotAfter,ah

;/*
;**
;** Loop through processing each entry in the logical palette.
;*/
        mov     eax,palcount
        mov     entry,eax
        lea     Entries_Entry,[ebx].entries

;/*
;**    for (entry=0; entry<palcount; entry++)
;*/

loop2_top:

;/*
;**    {
;**        /**************************************************************/
;**        /* If the palette entry is marked as PC_EXPLICIT then it is   */
;**        /* a direct index into the HW palette and no matching is      */
;**        /* required.                                                  */
;**        /**************************************************************/
;**        if (pdc->Palette->entries[entry].rgb.rgb2_fcOptions & PC_EXPLICIT)
;*/

        test    [Entries_Entry].rgb.rgb2_fcOptions,PC_EXPLICIT
        jz      @F
ifdef DEBUG2
        DebugMsg2       <PC_EXPLICIT Slot>
endif

;/*
;**        {
;**            /**********************************************************/
;**            /* we just use the RGB value as the hw slot, but since    */
;**            /* the index is only one byte we just get the bBlue byte  */
;**            /**********************************************************/
;**            slot = pdc->Palette->entries[entry].rgb.bBlue;
;*/

                mov     eax,0
                mov     al,[Entries_Entry].rgb.rgb2_bBlue
                mov     slot,eax
                jmp     got_explicit_slot
@@:

;/*
;**        }
;**
;**        /**************************************************************/
;**        /* The palette entry is not marked as PC_EXPLICIT we will try */
;**        /* to find an existing entry in the palette which matches the */
;**        /* color we are looking for exactly. If we had a previous     */
;**        /* mapping for this palette then we will first try looking    */
;**        /* at the slot that the entry was last mapped to.             */
;**        /**************************************************************/
;**        if (localflags & PAL_CURRENT_OK)
;*/

        test    localflags,PAL_CURRENT_OK
        jz      end_ifs
ifdef DEBUG2
        DebugMsg2       <PAL_CURRENT_OK Slot>
endif

;/*
;**        {
;**            slot = pdc->Palette->entries[entry].bCurrent;
;*/

                mov     eax,0
                mov     al,[Entries_Entry].bCurrent
                mov     slot,eax

;/*
;**            /**********************************************************/
;**            /* We can only use the existing mapping if the colors are */
;**            /* an exact match and if the HW slot is currently not     */
;**            /* either the HW slot or the palette entry are marked as */
;**            /* reserved.                                              */
;**            /**********************************************************/
;**            if (   (HWPalette[slot].bRed   ==
;**                               pdc->Palette->entries[entry].rgb.bRed)
;**                && (HWPalette[slot].bGreen ==
;**                               pdc->Palette->entries[entry].rgb.bGreen)
;**                && (HWPalette[slot].bBlue  ==
;**                               pdc->Palette->entries[entry].rgb.bBlue))
;*/


                lea     HWPalSlot,HWPalette[eax*sizeof RGB2]
                ASSUME  EDI:PTR RGB2
                mov     eax,[HWPalSlot]
                and     eax,RGB_MASK
                mov     edx,[Entries_Entry].rgb
                and     edx,RGB_MASK
                cmp     eax,edx
                jne     end_ifs
ifdef DEBUG2
                DebugMsg2       <Colors Match>
endif

;/*
;**            {
;**                /******************************************************/
;**                /* The colors are an exact match. Now we must check   */
;**                /* that the flags do not clash.                       */
;**                /******************************************************/
;**                if (pdc->Palette->entries[entry].rgb.rgb2_fcOptions
;**                    & (PC_RESERVED | PC_NOCOLLAPSE) )
;*/

                test    [Entries_Entry].rgb.rgb2_fcOptions,PC_RESERVED+PC_NOCOLLAPSE
                jz      do_else
ifdef DEBUG2
                DebugMsg2       <Slot is PC_RESERVED+PC_NOCOLLAPSE>
endif

;/*
;**                {
;**                    /**************************************************/
;**                    /* We want a reserved or nocollapse slot so we    */
;**                    /* can only use the slot if it is not currently   */
;**                    /* being used and it is not part of the default   */
;**                    /* palette.                                       */
;**                    /**************************************************/
;/*                    if (! (HWPalette[slot].rgb2_fcOptions & PC_USED) &&   ;CMVC_59027
;**                        ! (HWPalette[slot].rgb2_fcOptions & PC_DEFAULT) ) ;CMVC_59027
;**                    /**************************************************/
;**                    /* Defect 67450 - The logic was incorrect here.   */
;**                    /* In reality you could to use this slot as long  */
;**                    /* both PC_USED and PC_DEFAULT are not TRUE.  The */
;**                    /* previous code wouldn't use the slot if either  */
;**                    /* flag was ON.  This regression was inflicted    */
;**                    /* when some cleanup work was attempted.          */
;**                    /**************************************************/
;**                    if (!(   (HWPalette[slot].fcOptions & PC_USED)
;**                          && (HWPalette[slot].fcOptions & PC_DEFAULT)))
;**                    /**************************************************/
;**                    /* Defect 68053 - Do not use the slot if it is    */
;**                    /* reserved for one of the system colors.         */
;**                    /**************************************************/
;**                    if (!(HWPalette[slot].fcOptions & PC_DEFAULT))
;*/                    {
;*/

                        mov     al,[HWPalSlot].rgb2_fcOptions
;                       and     al,PC_USED+PC_DEFAULT
                        and     al,PC_DEFAULT                   ;          
;                       xor     al,PC_USED+PC_DEFAULT           ;          
                        jnz      end_ifs                        ;          
;                       jz      end_ifs                         ;          
;/*
;**                    {
;**                      /**********************************************/
;**                      /* MEB 11/20/92                               */
;**                      /* If we are changing the flags here then we  */
;**                      /* must consider this a changed h/w slot,     */
;**                      /* otherwise if we change nothing but flags   */
;**                      /* and do not indicate that the slots have    */
;**                      /* changed then no repainting will be done.   */
;**                      /* This means that other palette manager apps */
;**                      /* which were previously mapping to these     */
;**                      /* slots will still be doing so, and as we    */
;**                      /* may just have made them animating this is  */
;**                      /* not a good idea!                           */
;**                      /**********************************************/
;**                      if ((HWPalette[slot].fcOptions
;**                                 & (PC_RESERVED | PC_NOCOLLAPSE) ) !=
;**                          (pdc->Palette->entries[entry].rgb.fcOptions
;**                                 & (PC_RESERVED | PC_NOCOLLAPSE) ) )
;**                      {
;**                          HWSlotsChanged++;
;*/                      }
                        mov     al,[HWPalSlot].rgb2_fcOptions         ;CMVC_59027
                        xor     al,[Entries_Entry].rgb.rgb2_fcOptions ;CMVC_59027
                        and     al,PC_RESERVED+PC_NOCOLLAPSE          ;CMVC_59027
                        jz      @f                                    ;CMVC_59027
                        inc     HWSlotsChanged                        ;CMVC_59027
@@:                                                                   ;CMVC_59027

;/*                        HWPalette[slot].rgb2_fcOptions =
;**                            pdc->Palette->entries[entry].rgb.rgb2_fcOptions;
;*/

ifdef DEBUG2
                DebugMsg2       <Slot not both USED and DEFAULT>
endif

                        mov     al,[Entries_Entry].rgb.rgb2_fcOptions
                        mov     [HWPalSlot].rgb2_fcOptions,al
                        jmp     got_slot

;/*
;**                    }
;**                }
;**                else
;*/

do_else:

;/*
;**                {
;**                    /**************************************************/
;**                    /* We can use the slot so long as it is not both  */
;**                    /* used and reserved.                             */
;**                    /**************************************************/
;**                    if (!(   (HWPalette[slot].rgb2_fcOptions & PC_USED)
;**                          && (HWPalette[slot].rgb2_fcOptions & PC_RESERVED)))
;*/

                        mov     al,[HWPalSlot].rgb2_fcOptions
                        and     al,PC_USED+PC_RESERVED
                        cmp     al,PC_USED+PC_RESERVED
                        je      end_ifs
ifdef DEBUG2
                DebugMsg2       <Slot not both USED and RESERVED>
endif

;/*
;**                    {
;**                        HWPalette[slot].rgb2_fcOptions |= PC_USED;
;*/

;/*                        or      [HWPalSlot].rgb2_fcOptions,PC_USED      ;CMVC_59027
;**                       /**********************************************/ ;CMVC_59027
;**                       /* Unnecessary to mark as used, since         */ ;CMVC_59027
;**                       /* got_slot will always do that for us.       */ ;CMVC_59027
;*/                       /**********************************************/ ;CMVC_59027
                        jmp     got_slot

;/*
;**                    }
;**                }
;**            }
;**        }
;*/

end_ifs:

;/*
;**        /**************************************************************/
;**        /* The palette entry is not marked as PC_EXPLICIT and the     */
;**        /* existing mapping did not give a usuable exactly matching   */
;**        /* slot so we will now search the whole of the palette for    */
;**        /* an exact matching slot. To make the test condition simpler */
;**        /* we will only do this if we do not mind sharing a HW slot   */
;**        /* (ie we are not processing a PC_RESERVED or PC_NOCOLLAPSE   */
;**        /* entry).                                                    */
;**        /**************************************************************/
;**        if (!(  pdc->Palette->entries[entry].rgb.rgb2_fcOptions
;**              & (PC_RESERVED | PC_NOCOLLAPSE) ))
;*/

        test    [Entries_Entry].rgb.rgb2_fcOptions,PC_RESERVED+PC_NOCOLLAPSE
        jnz     end_if1

;/*
;**        {
;**            /**********************************************************/
;**            /* Palette entry is not marked RESERVED or NO_COLLAPSE so */
;**            /* we will try to find an existing entry that matches the */
;**            /* rgb we want.                                           */
;**            /**********************************************************/
;**            slot = ExactHWPaletteMatch(pdc->Palette->entries[entry].rgb);
;*/

ifdef DEBUG2
        DebugMsg2       <Searching for Exact Match>
endif
                INVOKE  ExactHWPaletteMatch,
                        [Entries_Entry].rgb

                mov     slot,eax

;/*
;**            if (slot != PAL_ERROR)
;*/

                cmp     eax,PAL_ERROR
                jne     got_slot

;/*
;**            {
;**                /******************************************************/
;**                /* We found an exact match!                           */
;**                /******************************************************/
;**               goto    got_slot;
;**            }
;*/

end_if1:

;/*
;**        }
;**
;**        /**************************************************************/
;**        /* We did not manage to find an exact match with an existing  */
;**        /* slot so now we will look to see if we can find any free    */
;**        /* slots which we can map onto. If the current foreground     */
;**        /* palette is the default palette then we only want to look   */
;**        /* for slots which were free when the default palette was     */
;**        /* realized.  (This avoids changing the HW palette too much   */
;**        /* when the default palette has been realized as the          */
;**        /* foreground and so the background apps should hopefully get */
;**        /* the slots they had previously and will not have to         */
;**        /* repaint).  If the current foreground palette is not the    */
;**        /* default palette then we want to look for any free slot.    */
;**        /**************************************************************/
;*/

find_free_slot:

;/*
;**        if (hForeGroundPal == (PDEVPAL)DirectDeviceDefaultPalette)
;*/

        mov     eax,DirectDeviceDefaultPalette
        cmp     hForeGroundPal,eax
        jne     do_else2
ifdef DEBUG2
        DebugMsg2       <hForeGroundPal == DirectDeviceDefaultPalette>
endif

;/*
;**        {
;**            while (bNoFreeSlotBefore <= bNoFreeSlotAfter)
;*/

top_while:
                mov     ecx,0
                mov     cl,bNoFreeSlotBefore
                cmp     cl,bNoFreeSlotAfter
                ja      end_if2

;/*
;**            {
;**                if ( HWPalette[bNoFreeSlotBefore].rgb2_fcOptions
;**                     & (PC_DEFAULT | PC_USED | PC_OLD) )
;*/

                test    HWPalette[ecx*sizeof RGB2].rgb2_fcOptions,PC_DEFAULT+PC_USED+PC_OLD
                jz      do_else3

;/*
;**                {
;**                    bNoFreeSlotBefore++;
;*/

                        inc     bNoFreeSlotBefore
                jmp     end_while

;/*
;**                }
;**                else
;*/

do_else3:

;/*
;**                {
;**                    slot = bNoFreeSlotBefore;
;*/

ifdef DEBUG2
                        DebugMsg2       <Found Any free slot>
endif
                        mov     eax,0
                        mov     al,bNoFreeSlotBefore
                        mov     slot,eax

;/*
;**                    bNoFreeSlotBefore++;
;*/

                        inc     bNoFreeSlotBefore

;/*
;**                    HWPalette[slot] = pdc->Palette->entries[entry].rgb;
;*/

                        lea     HWPalSlot,HWPalette[eax*sizeof RGB2]
                        mov     eax,[Entries_Entry].rgb
                        mov     DWORD PTR [HWPalSlot],eax


;/*
;**                    HWSlotsChanged++;
;*/

                        inc     HWSlotsChanged

;/*                  /**************************************************/  ;CMVC_59027
;**                  /* This was a free slot, so we can put the full   */  ;CMVC_59027
;**                  /* options flags that we need in here.            */  ;CMVC_59027
;**                  /**************************************************/  ;CMVC_59027
;**                  HWPalette[slot].fcOptions =                           ;CMVC_59027
;**                      pdc->Palette->entries[entry].rgb2_fcOptions;      ;CMVC_59027
;**                      mov     al,[Entries_Entry].rgb.rgb2_fcOptions      ;CMVC_59027
;*/                      mov     [HWPalSlot].rgb2_fcOptions,al              ;CMVC_59027


;/*
;**                    goto got_slot;
;*/

                        jmp     got_slot

;/*
;**                }
;*/

        jmp     top_while
end_while:

;/*
;**            }
;*/

        jmp     end_if2

;/*
;**        }
;**        else
;*/

do_else2:

;/*
;**        {
;**            while (bNoFreeSlotBefore <= bNoFreeSlotAfter)
;*/

ifdef DEBUG2
        DebugMsg2       <hForeGroundPal <> DirectDeviceDefaultPalette>
endif
ifdef DEBUG2
        DebugMsg2       <Searching for free slot>
endif
top_while2:
                mov     ecx,0
                mov     cl,bNoFreeSlotBefore
                cmp     cl,bNoFreeSlotAfter
                ja      end_while2

;/*
;**            {
;**                if ( HWPalette[bNoFreeSlotBefore].rgb2_fcOptions
;**                     & (PC_DEFAULT | PC_USED) )
;*/

                test    HWPalette[ecx*sizeof RGB2].rgb2_fcOptions,PC_DEFAULT+PC_USED
                jz      do_else23

;/*
;**                {
;**                    bNoFreeSlotBefore++;
;*/

                        inc     bNoFreeSlotBefore
                        jmp     top_while2

;/*
;**                }
;**                else
;*/

do_else23:

;/*
;**                {
;**                    slot = bNoFreeSlotBefore;
;*/

ifdef DEBUG2
                        DebugMsg2       <Found Any free slot2>
endif
                        mov     eax,0
                        mov     al,bNoFreeSlotBefore
                        mov     slot,eax

;/*
;**                    bNoFreeSlotBefore++;
;*/

                        inc     bNoFreeSlotBefore

;/*
;**                    HWPalette[slot] = pdc->Palette->entries[entry].rgb;
;*/

                        lea     HWPalSlot,HWPalette[eax*sizeof RGB2]
                        mov     eax,[Entries_Entry].rgb
                        mov     DWORD PTR [HWPalSlot],eax

;/*
;**                    HWSlotsChanged++;
;*/

                        inc     HWSlotsChanged

;/*                    /**************************************************/  ;CMVC_59027
;**                    /* This was a free slot, so we can put the full   */  ;CMVC_59027
;**                    /* options flags that we need in here.            */  ;CMVC_59027
;**                    /**************************************************/  ;CMVC_59027
;**                    HWPalette[slot].fcOptions =                           ;CMVC_59027
;**                        pdc->Palette->entries[entry].rgb2_fcOptions;      ;CMVC_59027
;**                        mov     al,[Entries_Entry].rgb.rgb2_fcOptions      ;CMVC_59027
;*/                        mov     [HWPalSlot].rgb2_fcOptions,al              ;CMVC_59027

;/*
;**                    goto got_slot;
;*/

                        jmp     got_slot

;/*
;**                }
;*/


        jmp     top_while2
end_while2:

;/*
;**            }
;*/

end_if2:

;/*
;**        }
;**
;**        /**************************************************************/
;**        /* We did not manage to find an exact match with an existing  */
;**        /* slot or an empty slot so now we must consider whether we   */
;**        /* can reduce the size of the default palette in order to     */
;**        /* obtain more empty slots.                                   */
;**        /**************************************************************/
;**        /**************************************************************/
;**        /* If we are in the foreground then we will allow the default */
;**        /* palettte to be reduced to a size of only 16 entries. If we */
;**        /* are in the background then we will not let the default     */
;**        /* palette be reduced below a size of 64 entries.             */
;**        /**************************************************************/
;**        if (   (   (*pflType & RP_FOREGROUND)
;**                && (ulDirectDeviceDefaultPaletteSize > 16) )
;**            || (ulDirectDeviceDefaultPaletteSize > 64) )
;*/

        mov     eax,pflType
        test    DWORD PTR [eax],RP_FOREGROUND
        jz      @F
        cmp     ulDirectDeviceDefaultPaletteSize,16
        ja      doit
@@:
        cmp     ulDirectDeviceDefaultPaletteSize,64
        jbe     skip
doit:

;/*
;**        {
;**            /**********************************************************/
;**            /* We will reduce the size of the default palette and     */
;**            /* allocate a new free slot to this entry.  We will call  */
;**            /* ReduceDefaultPaletteSize to change the size and        */
;**            /* entries in the default palette.  It will also adjust   */
;**            /* ulDirectDeviceDefaultPaletteSize to reflect the new    */
;**            /* allocation of slots available to palette manager       */
;**            /* palettes. We return the RP_DEFAULTSCHANGED flag so     */
;**            /* that PMWIN can send paint messages to all of the       */
;**            /* desktop.                                               */
;**            /**********************************************************/
;**            DefaultsChanged = DefaultsChanged + ReduceDefaultPaletteSize();
;*/

ifdef DEBUG2
        DebugMsg2       <Reducing defaultpalette size>
endif

                INVOKE  ReduceDefaultPaletteSize
                add     DefaultsChanged,eax

;/*
;**           *pflType |= RP_DEFAULTSCHANGED;
;*/

                mov     eax,pflType
                or      DWORD PTR [eax],RP_DEFAULTSCHANGED

;/*
;**            bNoFreeSlotBefore = (BYTE)(ulDirectDeviceDefaultPaletteSize/2);
;*/

                mov     eax,ulDirectDeviceDefaultPaletteSize
                shr     eax,1
                mov     bNoFreeSlotBefore,al

;/*
;**            bNoFreeSlotAfter  = (BYTE)(255-(ulDirectDeviceDefaultPaletteSize/2));
;*/

                mov     ah,255
                sub     ah,al
                mov     bNoFreeSlotAfter,ah

;/*
;**            /**********************************************************/
;**            /* Unfortunately we know we have just done a dirty deed!  */
;**            /* We may have already mapped entries to some of the      */
;**            /* defaults we just changed (both in this palette and in  */
;**            /* previously realized palettes).  If we are in the       */
;**            /* foreground then we can simply start the realize again. */
;**            /* Otherwise we increment to global optimization id to    */
;**            /* make sure when that when the desktop is repainted then */
;**            /* no palette realizations are optimized out.             */
;**            /**********************************************************/
;**            if (*pflType & RP_FOREGROUND)
;*/

                mov     eax,pflType
                test    DWORD PTR [eax],RP_FOREGROUND
                jz      not_fore

;/*
;**            {
;**                RemoveUsedMarkings();
;*/

                INVOKE  RemoveUsedMarkings

;/*
;**                goto set_up_realize_loop;
;*/

                jmp     set_up_realize_loop
not_fore:

;/*
;**            }
;**            usGlobalOptimizeID++;
;*/

                inc     usGlobalOptimizeID
ifdef SEAMLESS

;/*
;**            /**************************************************************/
;**            /* Update the seamless palette changed time stamp to indicate */
;**            /*         palette mappings could now be invalid.             */
;**            /**************************************************************/
;**            SeamlessData.ulLastPalUpdate++;
;*/

        inc     SM_WINDRV.ulLastPalUpdate
endif

;/*
;**            goto find_free_slot;
;*/

                jmp     find_free_slot

skip:

;/*
;**        }
;**
;**        /**************************************************************/
;**        /* We did not manage to find an exact match with an existing  */
;**        /* slot or an empty slot and we could not reduce the size of  */
;**        /* the default palette so now we must see if we can overwrite */
;**        /* one of the entries in the default palette.                 */
;**        /**************************************************************/
;**        if (localflags & LCOL_OVERRIDE_DEFAULT_COLORS)
;*/

        test    localflags,LCOL_OVERRIDE_DEFAULT_COLORS
        jz      skip2
ifdef DEBUG2
        DebugMsg2       <Overwriting Default Colors DANGER!! >
endif

;/*
;**        {
;**            /**********************************************************/
;**            /* First search the bottom half of the default palette to */
;**            /* see if we can find an unused slot.                     */
;**            /**********************************************************/
;*/

                mov     edx,0
                mov     slot,edx
                mov     ecx,ulDirectDeviceDefaultPaletteSize
                shr     ecx,1
                lea     HWPalSlot,HWPalette
top_for10:
                cmp     edx,ecx
                jae     end_for10

;/*
;**            for (slot = 0; slot < (ulDirectDeviceDefaultPaletteSize/2); slot++)
;**            {
;**                if (!(HWPalette[slot].rgb2_fcOptions & PC_USED))
;*/

                        test    [HWPalSlot].rgb2_fcOptions,PC_USED
                        jnz     @F

;/*
;**                {
;*/

ifdef DEBUG2
        DebugMsg2       <Overwriting Default SLOT DANGER (BOTTOM)!! >
endif

;/*
;**                    /**************************************************/
;**                    /* We have found a default slot which is not      */
;**                    /* being used by any of the palette manager       */
;**                    /* palettes so we will overwrite it with the      */
;**                    /* value we want to use. Any non-palette manager  */
;**                    /* DCs using this slot are just unlucky!          */
;**                    /**************************************************/
;**                    HWPalette[slot] = pdc->Palette->entries[entry].rgb;
;*/

                        mov     eax,[Entries_Entry].rgb
                        mov     DWORD PTR [HWPalSlot],eax

;/*
;**                    fForeGroundOverwrote = TRUE;
;*/

                        mov     fForeGroundOverwrote,1

;/*
;**                    HWSlotsChanged++;
;*/

                        inc     HWSlotsChanged

;/*                    HWPalette[slot].fcOptions =                           ;CMVC_59027
;**                        pdc->Palette->entries[entry].rgb2_fcOptions;      ;CMVC_59027
;**                        mov     al,[Entries_Entry].rgb.rgb2_fcOptions      ;CMVC_59027
;*/                        mov     [HWPalSlot].rgb2_fcOptions,al              ;CMVC_59027

;/*
;**                    goto got_slot;
;*/

                        jmp     got_slot
@@:
                inc     edx
                mov     slot,edx
                add     HWPalSlot,sizeof RGB2
                jmp     top_for10

;/*
;**                }
;*/

end_for10:

;/*
;**            }
;**
;**            /**********************************************************/
;**            /* We did not find a free slot in the bottom half of the  */
;**            /* default palette so now search the top half of the      */
;**            /* default palette to see if we can find an unused slot.  */
;**            /**********************************************************/
;**            for (slot = HW_PAL_SIZE-(ulDirectDeviceDefaultPaletteSize/2);
;**                 slot < HW_PAL_SIZE;
;**                 slot++ )
;*/

                mov     edx,HW_PAL_SIZE
                sub     edx,ecx
                mov     slot,edx

                lea     HWPalSlot,HWPalette[edx*sizeof RGB2]
top_for20:
                cmp     edx,HW_PAL_SIZE
                jae     end_for20

;/*
;**            {
;**                if (!(HWPalette[slot].rgb2_fcOptions & PC_USED))
;*/

                        test    [HWPalSlot].rgb2_fcOptions,PC_USED
                        jnz     @F
ifdef DEBUG2
        DebugMsg2       <Overwriting Default SLOT DANGER (TOP)!! >
endif

;/*
;**                {
;**                    /**************************************************/
;**                    /* We have found a default slot which is not      */
;**                    /* being used by any of the palette manager       */
;**                    /* palettes so we will overwrite it with the      */
;**                    /* value we want to use. Any non-palette manager  */
;**                    /* DCs using this slot are just unlucky!          */
;**                    /**************************************************/
;**                    HWPalette[slot] = pdc->Palette->entries[entry].rgb;
;*/

                        mov     eax,[Entries_Entry].rgb
                        mov     DWORD PTR [HWPalSlot],eax

;/*
;**                    fForeGroundOverwrote = TRUE;
;*/

                        mov     fForeGroundOverwrote,1

;/*
;**                    HWSlotsChanged++;
;*/

                        inc     HWSlotsChanged

;/*                    HWPalette[slot].fcOptions =                           ;CMVC_59027
;**                        pdc->Palette->entries[entry].rgb2_fcOptions;      ;CMVC_59027
;**                        mov     al,[Entries_Entry].rgb.rgb2_fcOptions      ;CMVC_59027
;*/                        mov     [HWPalSlot].rgb2_fcOptions,al              ;CMVC_59027

;/*
;**                    goto got_slot;
;*/

                        jmp     got_slot
@@:

;/*
;**                }
;*/

                inc     edx
                mov     slot,edx
                add     HWPalSlot,sizeof RGB2
                jmp     top_for20
end_for20:

;/*
;**            }
;*/

skip2:

;/*
;**        }
;**
;**        /**************************************************************/
;**        /* We did not manage to find an exact match with an existing  */
;**        /* slot or an empty slot and we could not reduce the size of  */
;**        /* the default palette or overwrite any of the entries in the */
;**        /* default palette so we must now try to find the nearest     */
;**        /* possible color match out of the existing entries in the HW */
;**        /* palette.                                                   */
;**        /**************************************************************/
;**
;**        /**************************************************************/
;**        /* We only have to do an exact search if we did not do one    */
;**        /* earlier. ie if the request was for a PC_RESERVED or        */
;**        /* PC_NOCOLLAPSE slot.                                        */
;**        /**************************************************************/
;**        if (pdc->Palette->entries[entry].rgb.rgb2_fcOptions
;**            & (PC_RESERVED | PC_NOCOLLAPSE) )
;*/

                test    [Entries_Entry].rgb.rgb2_fcOptions,PC_RESERVED+PC_NOCOLLAPSE
                jz      do_else6

;/*
;**        {
;**            slot = ExactHWPaletteMatch(pdc->Palette->entries[entry].rgb);
;*/

ifdef DEBUG2
                DebugMsg2       <Its PC_RESERVED or PC_NOCOLLAPSE>
endif
ifdef DEBUG2
                DebugMsg2       <Finding EXACT match>
endif
                INVOKE  ExactHWPaletteMatch,
                        [Entries_Entry].rgb
                mov     slot,eax

;/*
;**            if (slot == PAL_ERROR)
;*/

                cmp     eax,PAL_ERROR
                jne     end_else3

;/*
;**            {
;**                slot = ClosestHWPaletteMatch(pdc->Palette->entries[entry].rgb);
;*/

ifdef DEBUG2
                DebugMsg2       <Finding CLOSEST match>
endif
                        INVOKE  ClosestHWPaletteMatch,
                                [Entries_Entry].rgb
                        mov     slot,eax
                        jmp     end_else3

;/*
;**            }
;**        }
;**        else
;*/

do_else6:

;/*
;**        {
;**            slot = ClosestHWPaletteMatch(pdc->Palette->entries[entry].rgb);
;*/

ifdef DEBUG2
                DebugMsg2       <Its NOT PC_RESERVED or PC_NOCOLLAPSE>
endif
ifdef DEBUG2
                DebugMsg2       <Finding CLOSEST match>
endif
                INVOKE  ClosestHWPaletteMatch,
                        [Entries_Entry].rgb
                mov     slot,eax
end_else3:

;/*
;**        }
;**
;**        if (slot == PAL_ERROR)
;*/

                cmp     eax,PAL_ERROR
                jne     @F

;/*
;**        {
;**            /**********************************************************/
;**            /* All of the HW palette entries are reserved! We will    */
;**            /* just map to slot zero because it is as good as any     */
;**            /* other slot since reserved slots are likely to change   */
;**            /* very quickly (ie. there is no point in looking for a   */
;**            /* nearest color match).                                  */
;**            /**********************************************************/
;**            slot = 0;
;*/

ifdef DEBUG2
        DebugMsg2       <PAL_ERROR: SLOT=0>
endif
                mov     eax,0
                mov     slot,eax
@@:

;/*
;**        }
;**
;*/

got_slot:

;/*
;**        /**************************************************************/
;**        /* We now have a slot to use in our mapping which points to   */
;**        /* a slot in the HW palette that conains the rgb we want to   */
;**        /* map to.  We must set the used flags so that other palettes */
;**        /* do not try to overwrite this slot.  (The exception is the  */
;**        /* case of an explicit entry in which case we do not set the  */
;**        /* used flag because we will always goto got_explicit_slot).  */
;**        /**************************************************************/
;**        HWPalette[slot].rgb2_fcOptions |= PC_USED;
;*/

ifdef DEBUG2
        DebugMsg2       <Got Slot>
endif
        mov     eax,slot
        lea     HWPalSlot,HWPalette[eax*sizeof RGB2]
        or      [HWPalSlot].rgb2_fcOptions,PC_USED
got_explicit_slot:
        assert  eax,E,slot
        assert  EAX,BE,0FFH

;/*
;**        /**************************************************************/
;**        /* Save the slot number as the current mapping.               */
;**        /**************************************************************/
;**        pdc->Palette->entries[entry].bCurrent = (BYTE)slot;
;*/

        mov     [Entries_Entry].bCurrent,al

;/*
;**        /**************************************************************/
;**        /* have we changed a mapping here                             */
;**        /**************************************************************/
;**        if ((pdc->Palette->entries[entry].rgb.rgb2_fcOptions & PC_NEW) ||
;**            (pdc->Palette->entries[entry].bPrevious != (BYTE)slot) )
;*/

                test    [Entries_Entry].rgb.rgb2_fcOptions,PC_NEW
                jnz     doit2
                cmp     [Entries_Entry].bPrevious,al
                jne     doit2
                jmp     skip3

;/*
;**        {
;*/

doit2:
ifdef DEBUG2
        DebugMsg2       <We Changed A Mapping>
endif

;/*
;**            pdc->Palette->entries[entry].rgb.rgb2_fcOptions &= ~PC_NEW;
;*/

                and     [Entries_Entry].rgb.rgb2_fcOptions,NOT PC_NEW

;/*
;**            MappingsChanged++;
;*/

                inc     MappingsChanged
skip3:

;/*
;**        }
;*/

        add     Entries_Entry,sizeof PALENTRY
        dec     entry
        jnz     loop2_top
loop2_end:
        ASSUME  ESI:NOTHING
        ASSUME  EDI:NOTHING

;/*
;**    } /* for each entry in the logical palette */
;*/


no_need_to_realize:

;/*
;**    if (*pflType & RP_FOREGROUND)
;*/

        mov     eax,pflType
        test    DWORD PTR [eax],RP_FOREGROUND
        jz      end_if10

;/*
;**    {
;**        /**************************************************************/
;**        /* At this point if we just realized the foreground palette   */
;**        /* we want to check if we really did make some changes to the */
;**        /* HW palette.  (This is not as unlikely as you might at      */
;**        /* first think - cached DCs palettes are frequently selected  */
;**        /* in and out so appear as new palettes, even if nothing has  */
;**        /* really changed).  If we did not make any changes then we   */
;**        /* optimize things by just returning zero as the number of    */
;**        /* mappings changed so that realize messages are not be sent  */
;**        /* to all of the background windows.                          */
;**        /**************************************************************/
;**        if ((HWSlotsChanged == 0))
;*/

        cmp     HWSlotsChanged,0
        jnz     end_if10

;/*
;**        {
;**            /**********************************************************/
;**            /* We have not made any changes to the HW palette.        */
;**            /* Copy back the old used flags so that we do not loose   */
;**            /* the old palette mappings - pmwin should not send off   */
;**            /* realize messages since no slots have changed.          */
;**            /**********************************************************/
;**            RestoreUsedMarkings();
;*/

ifdef DEBUG2
                DebugMsg2       <No Slots changed>
endif
                INVOKE  RestoreUsedMarkings

;/*
;**        }
;*/

end_if10:

;/*
;**    }
;*/

;/*
;**    /******************************************************************/
;**    /* We must now update the palette flags to indicate the new state */
;**    /* of the palette.                                                */
;**    /******************************************************************/
;**    if (localflags & PAL_CURRENT_OK)
;*/

        test    localflags,PAL_CURRENT_OK
        jz      @F

;/*
;**    {
;**        /**************************************************************/
;**        /* On entry to the routine there was a current mapping so we  */
;**        /* must now set the flag to indicate that the previous        */
;**        /* mapping is now valid.                                      */
;**        /**************************************************************/
;**        localflags |= PAL_PREVIOUS_OK;
;*/

        or      localflags,PAL_PREVIOUS_OK
@@:

;/*
;**    }
;**
;**    /******************************************************************/
;**    /* On exit we always have a valid current mapping and we clear    */
;**    /* the PAL_CHANGED flag to indicate that the palette does not     */
;**    /* need realizing.                                                */
;**    /******************************************************************/
;**    localflags &= ~PAL_CHANGED;
;*/

        and     localflags,NOT PAL_CHANGED

;/*
;**    localflags |= PAL_CURRENT_OK;
;*/

        or      localflags,PAL_CURRENT_OK

;/*
;**
;**    /******************************************************************/
;**    /* Put the flags back in their far pointer place.                 */
;**    /******************************************************************/
;**    pdc->Palette->usFlags = (USHORT)localflags;
;*/

        mov     eax,localflags
        mov     [ebx].usFlags,eax
        ASSUME  EBX:NOTHING


;/*
;**    /**********************************************************/
;**    /* see to the return values                               */
;**    /* NB. 8514 does not seem to include DefaultsChanged in   */
;**    /* its return value                                       */
;**    /**********************************************************/
;**    *pcSlotsChanged = HWSlotsChanged /* + DefaultsChanged */ ;
;*/

        mov     ebx,pcSlotsChanged
        mov     eax,HWSlotsChanged
        mov     DWORD PTR [ebx],eax

;/*
;**       return (MappingsChanged);
;*/

        mov     eax,MappingsChanged
        ret
InnerRealizePalette ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = ClosestHWPaletteMatch
;*
;* DESCRIPTION   = This routine searches the hw palette for the closest
;*                 matching colour.  It does not do a search for an exact
;*                 match before doing the nearest color search because this
;*                 routine should only be called if an exact match has not
;*                 been found by a previous call to ExactHWPaletteMatch.  We
;*                 can never match to a PC_RESERVED HW slot.  If all entries
;*                 are PC_RESERVED then we cannot do a closest match and so
;*                 we return PAL_ERROR.
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX
;*                 Registers Destroyed:
;*                        EAX,ECX,EDX
;*
;* INPUT         = rgb             RGB value to search for
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = index of closest match
;* RETURN-ERROR  = PAL_ERROR (-1) if no match found.
;*
;**************************************************************************/

ClosestHWPaletteMatch PROC SYSCALL USES EBX ESI,
        rgb             :RGB2

;/*
;** {
;**    /******************************************************************/
;**    /* Local variables                                                */
;**    /******************************************************************/
;** LOCAL   Diff            :ULONG,  ;/* difference of current entry */
;**        MinDiff         :ULONG,  ;/* Minimum Difference to date  */
;**        i               :ULONG,  ;/* loop variable               */
;**        Index           :ULONG   ;/* index of closest match      */
;*/


ifdef FIREWALLS

;/*
;**    /******************************************************************/
;**    /* We will do a check for an exact match as a firewall.  The      */
;**    /* convension is that this routine will never be called unless a  */
;**    /* previous call to ExactHWPaletteMatch failed.                   */
;**    /******************************************************************/
;**    if (ExactHWPaletteMatch(rgb) != PAL_ERROR)
;*/

        INVOKE  ExactHWPaletteMatch,
                rgb

        cmp     eax,PAL_ERROR
        je      @F

;/*
;**    {
;**        haltproc();
;*/

        ;INT     3
@@:

;/*
;**    }
;*/

endif ;/* FIREWALLS */

;/*
;**    /******************************************************************/
;**    /* Initialize the minimum differnce we have found so far.         */
;**    /******************************************************************/
;**    MinDiff = 0xFFFFFFFF;
;*/

        mov     ebx,0FFFFFFFFh


;/*
;**    /******************************************************************/
;**    /* We will return PAL_ERROR (-1) if all entries are PC_RESERVED   */
;**    /* and PC_USED.                                                   */
;**    /******************************************************************/
;**    Index = PAL_ERROR;
;*/

        mov     esi,PAL_ERROR

;/*
;**    for (i = 0; i < HW_PAL_SIZE; i++)
;*/

        lea     edx,HWPalette
        mov     ecx,0
        jmp     enter_for1
top_for1:

;/*
;**    {
;**        if (!(HWPalette[i].rgb2_fcOptions & PC_RESERVED))
;*/

        test    [edx].RGB2.rgb2_fcOptions,PC_RESERVED
        jnz     its_reserved

;/*
;**        {
;**            /**********************************************************/
;**            /* this is not reserved so we'll see how close it is      */
;**            /**********************************************************/
;**            /**********************************************************/
;**            /* find the distance between this palette entry and the   */
;**            /* required color                                         */
;**            /**********************************************************/
;**            Diff = rgb2_diff(rgb, HWPalette[i]);
;*/

        INVOKE  rgb2_diff,
                rgb,
                RGB2 PTR [edx]

;/*
;** eax=Diff
;*/


;/*
;**            /**********************************************************/
;**            /* If this is closer than our previous closest then reset */
;**            /* MinDiff and set Index                                  */
;**            /**********************************************************/
;**            if (Diff < MinDiff)
;*/

        cmp     eax,ebx
        jae     not_closer

;/*
;**            {
;**                MinDiff   = Diff;
;*/

        mov     ebx,eax

;/*
;**                Index = i;
;*/

        mov     esi,ecx
not_closer:

;/*
;**            }
;*/

its_reserved:

;/*
;**        }
;*/

        add     edx,sizeof RGB2
        inc     ecx
enter_for1:
        cmp     ecx,HW_PAL_SIZE
        jb      top_for1
end_for1:

;/*
;**    }
;**       return(Index);
;*/

ifdef FIREWALLS
        mov     edx,HWPalette[esi*sizeof RGB2]
        and     edx,RGB_MASK
        mov     eax,rgb
        and     eax,RGB_MASK
        cmp     edx,eax
        jne     no_problem

;/*
;** if the colors match exactly, then there is a problem with
;** ExactHWPaletteMatch !!
;*/

        rip     text,<ClosestHWPaletteMatch - Colors should NOT match exactly!! >
no_problem:
endif ;FIREWALLS
        mov     eax,esi
        ret
ClosestHWPaletteMatch ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = ExactHWPaletteMatch
;*
;* DESCRIPTION   = This routine searches the hw palette for an exact matching
;*                 colour.  We can never match to a PC_RESERVED HW slot.  If
;*                 we do not find an exact match that is not PC_RESERVED then
;*                 we return PAL_ERROR (-1) to indicate that the search for a
;*                 match failed.  We search through the PC_DEFAULT slots
;*                 first, before serching the rest of the palette (note there
;*                 is no guarentee that the default entries are still in
;*                 place so search the defaults backwards since we overwrite
;*                 entries from low to high indices)
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX
;*                 Registers Destroyed:
;*                        EAX,ECX,EDX
;*
;* INPUT         = rgb             RGB value to search for
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = index of closest match
;* RETURN-ERROR  = PAL_ERROR (-1) if no match found.
;*
;**************************************************************************/

ExactHWPaletteMatch PROC SYSCALL USES EBX ESI,
        rgb     :RGB2


;/*
;**    /******************************************************************/
;**    /* Local variables                                                */
;**    /******************************************************************/
;** LOCAL   i:ULONG   ;/* loop variable */
;*/


        mov     edx,rgb
        and     edx,RGB_MASK

;/*
;**    /******************************************************************/
;**    /* First check the top half of the default palette.               */
;**    /******************************************************************/
;**    for (i = 256-(ulDirectDeviceDefaultPaletteSize/2);
;**         i < HW_PAL_SIZE;
;**         i++)
;*/

        mov     ebx,ulDirectDeviceDefaultPaletteSize
        shr     ebx,1
        mov     ecx,256
        sub     ecx,ebx
        lea     ebx,HWPalette[ecx*sizeof RGB2]
top_for1:
        cmp     ecx,HW_PAL_SIZE
        jae     end_for1

;/*
;**    {
;**        if (!(HWPalette[i].rgb2_fcOptions & PC_RESERVED) &&
;**            HWPalette[i].bRed   == rgb.bRed   &&
;**            HWPalette[i].bGreen == rgb.bGreen &&
;**            HWPalette[i].bBlue  == rgb.bBlue )
;*/

        .ERRNZ  RGB2.rgb2_fcOptions - 3
        mov     eax,[ebx]
        test    eax,PC_RESERVED SHL 24
        jnz     skip_reserved
        and     eax,RGB_MASK
        cmp     eax,edx
        je      found_match

;/*
;**        {
;**            return(i);
;**        }
;*/

skip_reserved:
        add     ebx,sizeof RGB2
        inc     ecx
        jmp     top_for1
found_match:
        mov     eax,ecx
        jmp     exact_exit
end_for1:

;/*
;**    }
;**
;**    /******************************************************************/
;**    /* Now check the bottom half of the default palette.              */
;**    /******************************************************************/
;**    for (i = 0; i < (ulDirectDeviceDefaultPaletteSize/2); i++)
;*/

        mov     esi,ulDirectDeviceDefaultPaletteSize
        shr     esi,1
        mov     ecx,0
        lea     ebx,HWPalette
top_for2:
        cmp     ecx,esi
        jae     end_for2

;/*
;**    {
;**        if (!(HWPalette[i].rgb2_fcOptions & PC_RESERVED) &&
;**            HWPalette[i].bRed   == rgb.bRed   &&
;**            HWPalette[i].bGreen == rgb.bGreen &&
;**            HWPalette[i].bBlue  == rgb.bBlue )
;**        {
;*/

        .ERRNZ  RGB2.rgb2_fcOptions - 3
        mov     eax,[ebx]
        test    eax,PC_RESERVED SHL 24
        jnz     skip_reserved2
        and     eax,RGB_MASK
        cmp     eax,edx
        je      found_match

;/*
;**        {
;**            return(i);
;**        }
;*/

skip_reserved2:
        inc     ecx
        add     ebx,sizeof RGB2
        jmp     top_for2
end_for2:

;/*
;**    }
;**
;**    /******************************************************************/
;**    /* Now check the major block of the palette for an exact match.   */
;**    /******************************************************************/
;**    for (i = ulDirectDeviceDefaultPaletteSize/2;
;**         i < (ULONG)(256-(ulDirectDeviceDefaultPaletteSize/2));
;**         i++ )
;*/

        mov     ecx,esi
        mov     esi,256
        sub     esi,ecx
        lea     ebx,HWPalette[ecx*sizeof RGB2]
top_for3:
        cmp     ecx,esi
        jae     end_for3

;/*
;**    {
;**        if (!(HWPalette[i].rgb2_fcOptions & PC_RESERVED) &&
;**            HWPalette[i].bRed   == rgb.bRed   &&
;**            HWPalette[i].bGreen == rgb.bGreen &&
;**            HWPalette[i].bBlue  == rgb.bBlue )
;*/

        mov     eax,[ebx]
        test    eax,PC_RESERVED SHL 24
        jnz     skip_reserved3
        and     eax,RGB_MASK
        cmp     eax,edx
        je      found_match

;/*
;**        {
;**            return(i);
;**        }
;*/

skip_reserved3:
        inc     ecx
        add     ebx,sizeof RGB2
        jmp     top_for3
end_for3:

;/*
;**    }
;**
;**    /******************************************************************/
;**    /* An exact match was not found so return PAL_ERROR (-1).         */
;**    /******************************************************************/
;**       return(PAL_ERROR);
;*/

        mov     eax,PAL_ERROR
exact_exit:
        ret
ExactHWPaletteMatch ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = rgb2_diff
;*
;* DESCRIPTION   = Routine to find the (square of) the euclidian distance
;*                 between 2 RGB values.
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX,ECX,EDX
;*                 Registers Destroyed:
;*                        EAX
;*
;* INPUT         = rgb1            RGB value 1
;*                 rgb2            RGB value 2
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = (square of) distance betwwen 2 RGB values
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

rgb2_diff PROC SYSCALL USES ECX EDX,
        rgb1:RGB2,
        rgb2:RGB2

;/*
;**    /******************************************************************/
;**    /* rgb2_diff calculates a value which is proportional to          */
;**    /* the difference (in RGB space) between the two supplied colors  */
;**    /******************************************************************/
;**
;**    /******************************************************************/
;**    /* Local variables                                                */
;**    /******************************************************************/
;** LOCAL   RedDiff         :DWORD,
;**        GreenDiff       :DWORD,
;**        BlueDiff        :DWORD
;**
;**    /******************************************************************/
;**    /* WARNING if you try and optimize this check that the compiler   */
;**    /* generates the code you think it should                         */
;**    /* (subtraction of BYTEs gives an unsigned SHORT ? ! )            */
;**    /******************************************************************/
;**    #define SQR(X) ((X)*(X))
;*/
;**
;**    RedDiff   = (SHORT)rgb1.bRed   - (SHORT)rgb2.bRed;
;*/

        mov     eax,0
        mov     edx,eax
        mov     al,rgb1.rgb2_bRed
        mov     dl,rgb2.rgb2_bRed
        sub     eax,edx
        mov     edx,eax
        imul    edx
        mov     ecx,eax

;/*
;**    GreenDiff = (SHORT)rgb1.bGreen - (SHORT)rgb2.bGreen;
;*/

        mov     eax,0
        mov     edx,eax
        mov     al,rgb1.rgb2_bGreen
        mov     dl,rgb2.rgb2_bGreen
        sub     eax,edx
        mov     edx,eax
        imul    edx
        add     ecx,eax

;/*
;**    BlueDiff  = (SHORT)rgb1.bBlue  - (SHORT)rgb2.bBlue;
;*/

        mov     eax,0
        mov     edx,eax
        mov     al,rgb1.rgb2_bBlue
        mov     dl,rgb2.rgb2_bBlue
        sub     eax,edx
        mov     edx,eax
        imul    edx
        add     eax,ecx

;/*
;**    return( SQR(RedDiff)   +
;**            SQR(GreenDiff) +
;**            SQR(BlueDiff)   );
;**    #undef SQR
;*/

        ret
rgb2_diff ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = UpdateColors
;*
;* DESCRIPTION   = Changes the h/w indices for the visible area of the DC as an
;*                 alternative to redrawing.  Changes from the previous palette
;*                 realization to the current one.
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX
;*                 Registers Destroyed:
;*                        EAX,ECX,EDX
;*
;* INPUT         = hdc             DC handle
;*                 pdc             device DC handle
;*                 FunN          function and COM_ flags
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = OK
;* RETURN-ERROR  = ERROR_ZERO
;*
;**************************************************************************/

UpdateColors PROC SYSCALL USES EBX,
        hdc     :HDC,
        hddc    :PDDC,
        FunN    :ULONG

LOCAL   i           :ULONG,
        identity    :ULONG,
        PalCount    :ULONG,
        crclClip    :ULONG,
        previous    :BYTE,
        current     :BYTE
LOCAL   VisRects[NUM_VIS_RECTS]         :RECTL
LOCAL   GetVisRectsControl              :RGNRECT


;/*
;**    /******************************************************************/
;**    /* Get driver semaphore and perform entry checks                  */
;**    /******************************************************************/
;*/

        cld
        ddc?    hddc

        mov     edx,hddc
        INVOKE  enter_driver

        mov     eax,0
        jc      uc_exit_no_lock                  ;error logged

;/*
;**    /******************************************************************/
;**    /* NB. we dont firewall the path/area test because the 8514 does  */
;**    /* not                                                            */
;**    /******************************************************************/
;**    /******************************************************************/
;**    /* If the function is being called within an area or path         */
;**    /* definition then we raise an error and leave immediately.       */
;**    /******************************************************************/
;*/

        no_path_area    uc_exit_error,both

;/*
;**    /******************************************************************/
;**    /* we only update colors for device DCs                           */
;**    /* there is no update we can do if the palette does not have      */
;**    /* a previous realization (NB. the default palette never has a    */
;**    /* previous realization)                                          */
;**    /******************************************************************/
;**    if (pdc->DCIDCType == OD_DIRECT &&
;**        pdc->Palette->usFlags & PAL_PREVIOUS_OK)
;**        cmp     [edx].DDC.DCIDCType,OD_DIRECT
;**        jne     end_if1
;**
;** UpdateColors has no effect on a memory DDC.
;**
;*/

        test    [edx].DDC.ddc_fb,DDC_DEVICE
        jz      end_if1
        mov     edx,[edx].DDC.ddc_npdevpal
        test    [edx].DEVPAL.usFlags,PAL_PREVIOUS_OK
        jz      end_if1

;/*
;**    {
;**        /**************************************************************/
;**        /* set up an identity mapping                                 */
;**        /**************************************************************/
;**        identity = TRUE;
;*/

        mov     identity,TRUE

;/*
;**        for (i=0; i<HW_PAL_SIZE; i++)
;*/

        mov     ecx,0
        .erre   HW_PAL_SIZE
top_for1:

;/*
;**        {
;**            UCMapping[i] = (BYTE)i;
;*/

        mov     BYTE PTR UCMapping[ecx],cl
        inc     ecx
        cmp     ecx,HW_PAL_SIZE
        jb      top_for1
end_for1:

;/*
;**        }
;**
;**
;**        /**************************************************************/
;**        /* now fill in the mapping as required                        */
;**        /**************************************************************/
;**        PalCount = pdc->Palette->usCountStored;
;*/

        mov     eax,[edx].DEVPAL.usCountStored
        mov     PalCount,eax

;/*
;**        for (i=0; i<PalCount; i++)
;*/

        mov     eax,0
        mov     ecx,0
        jmp     enter_for2
top_for2:

;/*
;**        {
;**            previous = pdc->Palette->entries[i].bPrevious;
;*/

                mov     al,[edx+ecx*sizeof PALENTRY].DEVPAL.entries.bPrevious

;/*
;**            current  = pdc->Palette->entries[i].bCurrent;
;*/

                mov     bl,[edx+ecx*sizeof PALENTRY].DEVPAL.entries.bCurrent

;/*
;**            if (UCMapping[previous] != current)
;*/

                cmp     UCMapping[eax],bl
                je      end_if10

;/*
;**            {
;**                UCMapping[previous] = current;
;*/

                mov     UCMapping[eax],bl

;/*
;**                identity = FALSE;
;*/

                mov     identity,0
end_if10:

;/*
;**            }
;*/

        inc     ecx
enter_for2:
        cmp     ecx,PalCount
        jb      top_for2
end_for2:

;/*
;**        }
;**        if (!identity)
;*/

        cmp     identity,0
        jnz     end_if1

;/*
;**        {
;**            /**********************************************************/
;**            /* mapping is not the identity so we must actually update */
;**            /* the colors                                             */
;**            /**********************************************************/
;**            /**********************************************************/
;**            /* do the appropriate update into all visible regions     */
;**            /**********************************************************/
;**            GetVisRectsControl.ircStart = 1;
;*/

                mov     GetVisRectsControl.rgnrc_ircStart,1

;/*
;**            GetVisRectsControl.crc = NUM_VIS_RECTS;
;*/

                mov     GetVisRectsControl.rgnrc_crc,NUM_VIS_RECTS

;/*
;**            GetVisRectsControl.usDirection = RECTDIR_LFRT_BOTTOP;
;*/

                mov     GetVisRectsControl.rgnrc_ulDirection,RECTDIR_LFRT_BOTTOP


;/*
;**            do /* for each rectangle comprising the visible region    */
;*/

do_top:
uc_get_next_vis:

;/*
;**            {
;**                /******************************************************/
;**                /* Get some vis region Rectangles from the engine     */
;**                /******************************************************/
;**                pfnGETVISRECTS].Function(
;**                                          pdc->DCIhdc,
;**                                          FNULL,
;**                                          &GetVisRectsControl,
;**                                          VisRects,
;**                                          FNULL,
;**                                          NGreGetVisRects);
;*/

        INVOKE  PFNDefGetVisRects PTR pfnDefGetVisRects,
                hdc,
                0,                              ;lp_rect
                ADDR GetVisRectsControl,        ;lp_ctrl
                ADDR VisRects,                  ;lp_list
                0,                              ;pddcNull
                NGreGetVisRects                 ;NGre...


;/*
;**                if (GetVisRectsControl.crcReturned)
;*/

                        mov     eax,GetVisRectsControl.rgnrc_crcReturned
                        cmp     eax,0
                        je      end_if2

;/*
;**                {
;**                    /**************************************************/
;**                    /* we were given some rectangles                  */
;**                    /**************************************************/
;**                    /**************************************************/
;**                    /* reset the start rectangle for next iteration   */
;**                    /**************************************************/
;**                    GetVisRectsControl.rgnrc_ircStart +=
;**                                         GetVisRectsControl.crcReturned;
;*/

                        add     GetVisRectsControl.rgnrc_ircStart,eax


;/*
;**
;** 8514 has:
;**
;*/

        lea     ebx,VisRects                      ;EBX --> first RECTL
        mov     crclClip,eax
uc_call_loop:
ifdef FIREWALLS
        mov     eax,[ebx].RECTL.rcl_yTop
        cmp     eax,[ebx].RECTL.rcl_yBottom
        jg      @F
        rip     text,<UpdateColors - a null rectangle in Y>
@@:
        mov     eax,[ebx].RECTL.rcl_xRight
        cmp     eax,[ebx].RECTL.rcl_xLeft
        jg      @F
        rip     text,<UpdateColors - a null rectangle in X>
@@:
endif


        INVOKE  OEMUpdateColors,
                ebx,            ;pRectl
                ADDR UCMapping  ;pMappingVector

        add     ebx,sizeof RECTL
        dec     crclClip
        jnz     uc_call_loop
        cmp     GetVisRectsControl.rgnrc_crcReturned,NRECTS
        je      uc_get_next_vis

;/*
;** end 8514
;*/

end_if2:

;/*
;**                }
;**            } while ( GetVisRectsControl.crcReturned );
;**        } /* mapping is not the identity */
;*/

end_if1:

;/*
;**    } /* DC is direct */
;**
;**    /******************************************************************/
;**    /* Release driver semaphore                                       */
;**    /******************************************************************/
;**       return(OK);
;*/

        mov     eax,OK
        jmp     uc_exit

uc_exit_error:
        mov     eax,ERROR_ZERO
uc_exit:
        INVOKE  leave_driver
uc_exit_no_lock:
        ret
UpdateColors ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = QueryHWPaletteInfo
;*
;* DESCRIPTION   = Return the RGB values that are actually in the hardware
;*                 palette.  The order of the returned colors is the same as
;*                 in the hardware, so that programs such as the RTG (Random
;*                 Testcase Generator) can predict the results of color
;*                 mixing, which happens between palette indices.
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX
;*                 Registers Destroyed:
;*                        EAX,ECX,EDX
;*
;* INPUT         = hdc             :HDC,
;*                 ulStart         :ULONG,
;*                 cclr            :ULONG,
;*                 pclr            :PULONG,
;*                 hddc            :PDDC,
;*                 FunN            :ULONG,
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

QueryHWPaletteInfo PROC SYSCALL USES EBX,
        hdc             :HDC,
        ulStart         :ULONG,
        cclr            :ULONG,
        pclr            :PULONG,
        hddc            :PDDC,
        FunN            :ULONG,

LOCAL   i               :ULONG

;/*
;** Get driver semaphore and perform entry checks
;*/

        cld
        ddc?    hddc

        mov     edx,hddc
        INVOKE  enter_driver

        mov     eax,0
        jc      qhp_exit_no_lock                 ;error logged

;/*
;**    /******************************************************************/
;**    /* if the count is zero then we are being asked for the size of   */
;**    /* the palette                                                    */
;**    /* Note: this could be done before an enter driver, but we often  */
;**    /* use enter driver as a convenient place to put a breakpoint...  */
;**    /******************************************************************/
;**    if (cclr == 0)
;*/

        cmp     cclr,0
        jnz     end_if1

;/*
;**    {
;**       INVOKE  leave_driver
;**        return (ULONG)SizeOfHWPalette;
;*/

        mov     eax,SizeOfHWPalette
        jmp     qhp_exit
end_if1:

;/*
;**    }
;**
;**    /******************************************************************/
;**    /* the 8514 returns at once if too many entries are asked for     */
;**    /******************************************************************/
;**    if (cclr + ulStart > SizeOfHWPalette)
;*/

        mov     eax,cclr
        add     eax,ulStart
        cmp     eax,SizeOfHWPalette
        jbe     end_if2

;/*
;**    {
;**       INVOKE  leave_driver
;**        return 0L;
;*/

        mov     eax,0
        jmp     qhp_exit
end_if2:

;/*
;**    }
;*/

;/*
;**    /******************************************************************/
;**    /* now loop to return all the entries                             */
;**    /* only return the RGB and external options (ie strip internal    */
;**    /* PC_ flags)                                                     */
;**    /******************************************************************/
;**    i = cclr;
;*/

        mov     ecx,cclr
        mov     ebx,pclr
        mov     edx,ulStart

;/*
;**    while (i--)
;*/

        cmp     ecx,0
        je      end_while1
top_while1:

;/*
;**    {
;**        *pclr++ = URGB(HWPalette[ulStart]) & RGB_PLUS_MASK;
;*/

                mov     eax,HWPalette[edx*sizeof RGB2]
                and     eax,RGB_PLUS_MASK
                mov     DWORD PTR [ebx],eax
                add     ebx,sizeof ULONG

;/*
;**        ulStart++;
;*/

                inc     edx
                dec     ecx
                jnz     top_while1
end_while1:

;/*
;**    }
;*/

;/*
;**    /******************************************************************/
;**    /* Release driver semaphore                                       */
;**    /******************************************************************/
;**    /******************************************************************/
;**    /* return the number of entries in the array                      */
;**    /******************************************************************/
;**    return(cclr);
;*/

        mov     eax,cclr
qhp_exit:
        INVOKE  leave_driver
qhp_exit_no_lock:
        ret
QueryHWPaletteInfo ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = QueryPaletteRealization
;*
;* DESCRIPTION   = Return the mapping from the logical palette in the DC to
;*                 the hardware palette, as an array of ULONGs.  This
;*                 function gives the RTG the ability to predict the outcome
;*                 of color mixing operations.
;*
;*             NOTE:
;*                 the definition of this routine is so similar to
;*                 QueryHWPalette that it is very strange that the 8514
;*                 implementation of the routines is so different in regards
;*                 to handling 'strange' input combinations However the best
;*                 we can do is assume the 8514 authors know what they are
;*                 doing...
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX
;*                 Registers Destroyed:
;*                        EAX,ECX,EDX
;*
;* INPUT         = hdc             :HDC,
;*                 ulStart         :ULONG,
;*                 cclr            :ULONG,
;*                 pclr            :PULONG,
;*                 hddc            :PDDC,
;*                 FunN            :ULONG
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

QueryPaletteRealization PROC SYSCALL USES EBX EDX EDI,
        hdc             :HDC,
        ulStart         :ULONG,
        cclr            :ULONG,
        pclr            :PULONG,
        hddc            :PDDC,
        FunN            :ULONG

LOCAL   i               :ULONG


;/*
;** Get driver semaphore and perform entry checks
;*/

        cld
        ddc?    hddc

        mov     edx,hddc
        INVOKE  enter_driver

        mov     eax,0
        jc      qpr_exit_no_lock                 ;error logged
        mov     edi,[edx].DDC.ddc_npdevpal

;/*
;**    /******************************************************************/
;**    /* if the count is zero then we are being asked for the size of   */
;**    /* the palette                                                    */
;**    /*                                                                */
;**    /* Note that we subtract ulStart merely because thats what        */
;**    /*      the 8514 driver does...                                   */
;**    /******************************************************************/
;**    if (cclr == 0)
;*/

        mov     eax,[edx].DEVPAL.usMax
        cmp     cclr,0
        jne     end_if1

;/*
;**    {
;**       INVOKE  leave_driver
;**        return (ULONG)pdc->Palette->usMax - ulStart;
;*/

        sub     eax,ulStart
        jmp     qpr_exit
end_if1:

;/*
;**    }
;**
;**    /******************************************************************/
;**    /* unlike QueryHWPalette which returns at once if too many entries*/
;**    /* are asked for, the 8514 retricts the number of entries to      */
;**    /* return as would be expected for this routine                   */
;**    /******************************************************************/
;**    cclr = min(cclr, pdc->Palette->usMax - ulStart +1);
;*/

        sub     eax,ulStart
        ; CMVC 53142
        inc     eax             ; @DMS adjust for zero based array
        cmp     eax,cclr
        jae     @F
        mov     cclr,eax
@@:

;/*
;**    /******************************************************************/
;**    /* now loop to return all the entries                             */
;**    /******************************************************************/
;**    i = cclr;
;*/

        mov     ecx,cclr
        cmp     ecx,0
        je      end_while1
        mov     ebx,pclr
        mov     eax,0
        mov     edx,ulStart     ;@DMS go from user start to end

;/*
;**    while (i--)
;*/

top_while1:

;/*
;**    {
;**        *pclr++ = (ULONG)(pdc->Palette->entries[i].bCurrent);
;*/

        ;mov     al,[edx+ecx*sizeof PALENTRY].DEVPAL.entries.bCurrent
        ;@DMS   move in the positive direction from ulStart
        mov     al,[edi+edx*sizeof PALENTRY].DEVPAL.entries.bCurrent
        mov     DWORD PTR [ebx],eax
        add     ebx,sizeof ULONG
        inc     edx             ; @DMS increment source

;/*
;**        ulStart++;
;*/

        dec     ecx
        jnz     top_while1
end_while1:

;/*
;**    }
;*/

;/*
;**    /******************************************************************/
;**    /* return the number of entries in the array                      */
;**    /******************************************************************/
;**       return(cclr);
;*/

        mov     eax,cclr
qpr_exit:

;/*
;** Release driver semaphore                                       */
;*/

        INVOKE  leave_driver

qpr_exit_no_lock:
        ret
QueryPaletteRealization ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = DeviceResizePalette
;*
;* DESCRIPTION   = Changes the size of a logical palette.
;*
;*                 If reducing the size removed entries are discarded.
;*                 If increasing the size, new entries are set to black.
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX
;*                 Registers Destroyed:
;*                        EAX,ECX,EDX
;*
;* INPUT         = hdc       DC handle
;*                 hdevpal   palette handle
;*                 ulSize    new palette size
;*                 pdc       device DC handle
;*                 FunN      function and COM_ flags
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

DeviceResizePalette PROC SYSCALL USES EBX EDI,
        hdc             :HDC,
        hdevpal         :PDEVPAL,
        ulSize          :ULONG,
        hddc            :PDDC,
        FunN            :ULONG

LOCAL   oldmax      :ULONG,
        ulMax       :ULONG

;/*
;** Get driver semaphore and perform entry checks
;*/

        cld
        ddc?    hddc

        mov     edx,hddc
        INVOKE  enter_driver

        mov     eax,0
        jc      drp_exit_no_lock                 ;error logged

        mov     edx,[edx].DDC.ddc_npdevpal

;/*
;**    /******************************************************************/
;**    /* get old size                                                   */
;**    /******************************************************************/
;**    oldmax = hdevpal->usMax;
;*/

        mov     ebx,hdevpal
        mov     eax,[ebx].DEVPAL.usMax
        mov     oldmax,eax

;/*
;**    /******************************************************************/
;**    /* store the new size                                             */
;**    /******************************************************************/
;**    ulMax = ulSize - 1;
;*/

        mov     eax,ulSize
        dec     eax
        mov     ulMax,eax

;/*
;**    hdevpal->usMax = (USHORT)ulMax;
;*/

        mov     [ebx].DEVPAL.usMax,eax

;/*
;**    /******************************************************************/
;**    /* if the size changed then flag rerealizalion will be needed     */
;**    /******************************************************************/
;**    if (ulMax != oldmax)
;*/

        cmp     eax,oldmax
        je      end_if1

;/*
;**    {
;**        hdevpal->usFlags |= PAL_CHANGED;
;*/

        or      [ebx].DEVPAL.usFlags,PAL_CHANGED

;/*
;**        /**************************************************************/
;**        /* limit the new maximum to the size we actually store        */
;**        /**************************************************************/
;**        ulMax = min(ulMax, LARGEST_PAL - 1);
;**        /* Defect 63839 - Remove 256 entry logical palette limit      */
;**        ulMax = min(ulMax, hdevpal->usCountStored - 1);
;*/

;        mov     eax,[ebx].DEVPAL.usCountStored-1        ;          
;        cmp     ulMax,eax                               ;          
;                  cmp     ulMax,LARGEST_PAL-1
;                  jb      @F
;                  mov     ulMax,LARGEST_PAL-1
@@:

;/*
;**        /**************************************************************/
;**        /* keep the number stored in the palette structure            */
;**        /**************************************************************/
;**        pdc->Palette->usCountStored = (USHORT)(ulMax + 1);
;*/

        mov     eax,ulMax
        inc     eax
;                  mov     [edx].DEVPAL.usCountStored,eax
        mov     [ebx].DEVPAL.usCountStored,eax          ;           use hdevpal
                                                        ;instead of DDC

;/*
;**        /**************************************************************/
;**        /* if the palette has been enlarged then zero any new entries */
;**        /*  this sets colors to black and all flags clear             */
;**        /**************************************************************/
;**        if (oldmax < ulMax)
;*/

                mov     eax,oldmax
                mov     ecx,ulMax
                cmp     eax,ecx
                jbe     end_if2

;/*
;**        {
;**            memset( &hdevpal->entries[oldmax+1],
;**                    0,
;**                    sizeof(PALENTRY) * (ulMax - oldmax));
;*/

                sub     ecx,eax
                .errnz  sizeof PALENTRY-8
                shl     ecx,1

                inc     eax
                lea     edi,[ebx+eax*sizeof PALENTRY].DEVPAL.entries
                mov     eax,0
                rep     stosd
end_if2:

;/*
;**        }
;**
;**        /******************************************************************/
;**        /* Invalidate the palette mapping cache if it uses this palette.  */
;**        /******************************************************************/
;**        ChangedPalette(hdevpal);
;*/

        INVOKE  ChangedPalette,
                hdevpal

end_if1:

;/*
;**    }
;**
;**    /******************************************************************/
;**    /* Release driver semaphore                                       */
;**    /******************************************************************/
;**       return(OK);
;*/

        mov     eax,OK
drp_exit:
        INVOKE  leave_driver
drp_exit_no_lock:
        ret
DeviceResizePalette ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = NearestPaletteIndex
;*
;* DESCRIPTION   = NearestPaletteIndex finds the logical index in the logical
;*                 palette which will give the nearest RGB to the supplied
;*                 RGB value.  The somewhat unexpected parameters are to make
;*                 these the same as eddc_NearestPhysicalColor, so that the
;*                 bitmap conversion code can call either of them indirectly
;*                 as appropriate.
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX
;*                 Registers Destroyed:
;*                        EAX,ECX,EDX
;*
;* INPUT         = hddc            :PDDC,
;*                 RGBColor        :RGB2
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

NearestPaletteIndex PROC SYSCALL USES EBX ECX EDX,
        hddc            :PDDC,
        RGBColor        :RGB2

;/*
;** Local variables
;*/

LOCAL   MinDiff         :ULONG,        ;/* Minimum Difference to date  */
        Index           :ULONG         ;/* index of closest match      */

;/*
;**       i               :ULONG,        ;/* loop variable               */
;**       Diff            :ULONG,        ;/* difference of current entry */
;*/


        mov     edx,hddc
        mov     edx,[edx].DDC.ddc_npdevpal

;/*
;**    /******************************************************************/
;**    /* First check for exact match                                    */
;**    /******************************************************************/
;**    for (i = 0; i < pdc->Palette->usCountStored; i++)
;*/

        mov     ecx,0
        mov     ebx,RGBColor
        and     ebx,RGB_MASK
        jmp     enter_for1
found_it:
        mov     eax,ecx
        jmp     npi_exit

top_for1:
        mov     eax,[edx].DEVPAL.entries[ecx*sizeof PALENTRY].rgb
        and     eax,RGB_MASK
        cmp     eax,ebx
        je      found_it

;/*
;**        {
;**            return(i);
;**        }
;*/

        inc     ecx
enter_for1:
        cmp     ecx,[edx].DEVPAL.usCountStored
        jb      top_for1
end_for1:

;/*
;**    }
;*/


;/*
;**    /******************************************************************/
;**    /* If not found then look for closest                             */
;**    /******************************************************************/
;**    MinDiff = 0xFFFFFFFF;
;*/

        mov     MinDiff,0FFFFFFFFh

;/*
;**    for (i = 0; i < pdc->Palette->usCountStored; i++)
;*/

        mov     ecx,0
        jmp     enter_for2
top_for2:

;/*
;**    {
;**        /**************************************************************/
;**        /* find the distance between this palette entry and the       */
;**        /* required color                                             */
;**        /**************************************************************/
;**        Diff = rgb2_diff(RGBColor, pdc->Palette->entries[i].rgb);
;*/


        INVOKE  rgb2_diff,
                RGBColor,
                [edx].DEVPAL.entries[ecx*sizeof PALENTRY].rgb

;/*
;**        /**************************************************************/
;**        /* If this is closer than our previous closest then reset     */
;**        /* MinDiff and set Index                                      */
;**        /**************************************************************/
;**        if (Diff < MinDiff)
;*/

        cmp     eax,MinDiff
        jae     @F

;/*
;**        {
;**            MinDiff   = Diff;
;*/

                mov     MinDiff,eax

;/*
;**            Index = i;
;*/

                mov     Index,ecx
@@:

;/*
;**        }
;*/

        inc     ecx
enter_for2:
        cmp     ecx,[edx].DEVPAL.usCountStored
        jb      top_for2
end_for2:

;/*
;**    }
;**       return(Index);
;*/

        mov     eax,Index
npi_exit:
        ret
NearestPaletteIndex ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = HWPaletteChanged
;*
;* DESCRIPTION   = This routine should be called whenever the HW palette is
;*                 changed.  It invalidates the palette mapping caching if
;*                 necessary.
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX,EAX,ECX,EDX
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


HWPaletteChanged PROC SYSCALL

;/*
;**    /******************************************************************/
;**    /* If either the current source palette or the current destination*/
;**    /* palette in the mapping is the screen then we must invalidate   */
;**    /* the current palette mapping.                                   */
;**    /******************************************************************/
;**    if ((CurrentSourcePalette == FNULL) || (CurrentDestPalette == FNULL))
;*/

        cmp     CurrentSourcePalette,0
        je      doit
        cmp     CurrentDestPalette,0
        jne     skip

;/*
;**    {
;*/

doit:

;/*
;**        CurrentMappingValid = FALSE;
;*/

        mov     CurrentMappingValid,0
skip:

;/*
;**    }
;*/

        ret
HWPaletteChanged ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = ChangedPalette
;*
;* DESCRIPTION   = This routine should be called whenever a logical palette
;*                 changes or is realized causing a change to its mapping to
;*                 the HW palette or is deleted.  It invalidates the palette
;*                 mapping caching if necessary.
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX,ECX,EDX
;*                 Registers Destroyed:
;*                        EAX
;*
;* INPUT         = NONE
;*
;*
;*
;*
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ChangedPalette PROC SYSCALL,
        pPalette        :PDEVPAL

;/*
;**    /******************************************************************/
;**    /* If either the current source palette or the current destination*/
;**    /* palette in the mapping is the same as the palette just changed */
;**    /* then we must invalidate the current palette mapping.           */
;**    /******************************************************************/
;**    if ((CurrentSourcePalette == pPalette) || (CurrentDestPalette == pPalette))
;*/

        mov     eax,pPalette
        cmp     CurrentSourcePalette,eax
        je      doit
        cmp     CurrentDestPalette,eax
        jne     skip

;/*
;**    {
;*/

doit:

;/*
;**        CurrentMappingValid = FALSE;
;*/

        mov     CurrentMappingValid,0
skip:

;/*
;**    }
;*/

        ret
ChangedPalette ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = ChangedColorTable
;*
;* DESCRIPTION   = This routine should be called whenever a logical color
;*                 table changes.  It invalidates the palette mapping caching
;*                 if necessary.
;*
;*                 Registers Preserved:
;*                        ESI,EDI,EBX,ECX,EDX
;*                 Registers Destroyed:
;*                        EAX
;*
;* INPUT         = pColorTable:PCOLORTABLE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ChangedColorTable PROC SYSCALL,
        pColorTable:PCOLORTABLE

;/*
;**    /******************************************************************/
;**    /* If either the current source palette or the current destination*/
;**    /* in the palette-palette mapping is the same as the color table  */
;**    /* just changed then we must invalidate the current palette       */
;**    /* mapping.                                                       */
;**    /******************************************************************/
;**    if (   (CurrentSourcePalette == pColorTable)
;**        || (CurrentDestPalette == pColorTable) )
;*/

        mov     eax,pColorTable
        cmp     CurrentSourcePalette,eax
        je      doit
        cmp     CurrentDestPalette,eax
        jne     skip

;/*
;**    {
;*/

doit:

;/*
;**        CurrentMappingValid = FALSE;
;*/

        mov     CurrentMappingValid,0
skip:

;/*
;**    }
;*/

        ret
ChangedColorTable ENDP
ifdef  IBMJ        ;IBMJ
_PaletteSupport ENDS
endif ;IBMJ        ;IBMJ
end
