;*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.;
;*****************************************************************************/
;/*****************************************************************************
;*
;* SOURCE FILE NAME = EDDCSUBR.ASM
;*
;* DESCRIPTIVE NAME = Color Subroutines
;*
;*
;* VERSION      V2.0
;*
;* DATE
;*
;* DESCRIPTION  Display Device Driver color subroutines
;*
;*
;* FUNCTIONS    InitDefaultColorTables
;*              LogToPhyIndex
;*              NearestDefaultPaletteIndex256
;*              NearestDefaultPaletteIndex128
;*              NearestDefaultPaletteIndex64
;*              NearestDefaultPhysicalColore
;*              InnerNearestDefaultPhysicalIndex
;*              NearestDirectDefaultPhysicalIndex
;*              NearestMemoryDefaultPhysicalIndex
;*              NearestDefaultPhysicalIndex
;*              NearestRealizableIndex
;*              NearestLogicalColor
;*              SearchRealizedLCTPalette
;*              InnerSearchRealizedLCTPalette
;*              PhyToLogIndex
;*              ExactDefaultPhysicalIndex
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   06/01/92                     SEL - Hack/Kludge bmc_eti calls into
;*                                here with no bitmap selected into the DC
;*                                it only makes the call if the DC is
;*                                color and it would take light years to
;*                                fix this any other way that I can think
;*                                of right now.  So here it is.  If you
;*                                don't like it, then fix it yourself
;*   07/09/93              69006  Pointer error.
;*   11/08/93              74744  Port XGA fix for defect 74638.
;*   11/29/93              74744  Add missing conditional jump in
;*                                SearchRealizedLCTPalette
;*
;*****************************************************************************/

        .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
MASM_OUT_OF_MEMORY      EQU                      1
ifndef MASM_OUT_OF_MEMORY
INCL_GPIPRIMITIVES      equ                      1
else
CLR_TRUE                EQU                       0fffffffch
CLR_WHITE               EQU                       0fffffffeh
CLR_FALSE               EQU                       0fffffffbh
CLR_BLACK               EQU                       0ffffffffh
CLR_BACKGROUND          EQU                       000000000h
CLR_NEUTRAL             EQU                       000000007h
endif

        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
        .list


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

;/*
;** Macros
;*/

Add_128 MACRO
        add     eax,128
ENDM


Div_256 MACRO
        shr     eax,8
ENDM


Mul_2 MACRO
        add     eax,eax ;*2
ENDM


Mul_3 MACRO
        mov     edx,eax
        add     eax,eax ;*2
        add     eax,edx ;*3
ENDM


Mul_4 MACRO
        shl     eax,2
ENDM


Mul_5 MACRO
        mov     edx,eax
        shl     eax,2   ;*4
        add     eax,edx ;*5
ENDM


Mul_6 MACRO
        mov     edx,eax
        add     eax,eax ;*2
        add     eax,edx ;*3
        add     eax,eax ;*6
ENDM


Mul_7 MACRO
        mov     edx,eax
        shl     eax,3   ;*8
        sub     eax,edx ;*7
ENDM


Mul_9 MACRO
        mov     edx,eax
        shl     eax,3   ;*8
        add     eax,edx ;*9
ENDM


.CODE

;/***************************************************************************
;*
;* FUNCTION NAME = InitDefaultColorTables
;*
;* DESCRIPTION   = InitDefaultColorTables initialises the HWPalette
;*                 structure,and sets up various global constants such as the
;*                 size of the Palette which depend on the device bpp.  It
;*                 initialises the real h/w from the HWPalette structure.  The
;*                 routine is called by FillPhysicalDeviceBlock which requests
;*                 and releases the enter driver semaphore around it.
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

InitDefaultColorTables PROC SYSCALL USES ESI EDI

;/*
;** Local Variables
;*/

LOCAL   i               :ULONG,                  ;/* general loop variable */
        SpecialIndex    :ULONG

;/*
;**    ;/******************************************************************/
;**    ;/* First clear all the entries in the HWPalette.                  */
;**    ;/* This is statically allocated to be big enough for 256 entries  */
;**    ;/* (as required for 8bpp).                                        */
;**    ;/******************************************************************/
;**    memset (HWPalette, 0, sizeof(HWPalette));
;*/

        .errnz  sizeof RGB2 - 4
        mov     ecx,HW_PAL_SIZE
        mov     eax,0
        lea     edi,HWPalette
        rep     stosd

;/*
;**    ;/******************************************************************/
;**    ;/* Set up the palette and logical color table for the appropriate */
;**    ;/* bpp.                                                           */
;**    ;/* Also set up any global constants for this format.              */
;**    ;/******************************************************************/
;**    if (DDT.BitCount == 8)
;**    {
;**        ;/**************************************************************/
;**        ;/* Eight bits per pel                                         */
;**        ;/**************************************************************/
;**        DefaultDirectLogicalColorTable = DefaultEightBppTable256;
;**        DefaultMemoryLogicalColorTable = DefaultEightBppTable256;
;*/

        lea     eax,DefaultEightBppTable256
        mov     DefaultDirectLogicalColorTable,eax
        mov     DefaultMemoryLogicalColorTable,eax

;/*
;**        cPhysicalColors  = 256;
;**        SizeOfHWPalette  = 256;
;**        MaxLogColorIndex = 255;
;**        fRealizeSupported = TRUE;
;*/

        mov     cPhysicalColors,256
        mov     SizeOfHWPalette,256

;/*
;**        ;/**************************************************************/
;**        ;/* Now set the entries in the SpecialColorTables.             */
;**        ;/**************************************************************/
;**        DirectSpecialColorTable[-CLR_TRUE ].PhyIndex = 0xFF;
;**        DirectSpecialColorTable[-CLR_WHITE].PhyIndex = 0xFF;
;**        MemorySpecialColorTable[-CLR_TRUE ].PhyIndex = 0xFF;
;**        MemorySpecialColorTable[-CLR_WHITE].PhyIndex = 0xFF;
;*/


        lea     edx,DirectSpecialColorTable.PhyIndex

;/*
;** The assembler barfs on negative constants, so put
;** them in this way to make sure it deals with them.
;*/

        mov     eax,CLR_TRUE
        neg     eax
        shl     eax,3
        .errnz  8-sizeof COLORTABLETYPE
        mov     ecx,CLR_WHITE
        neg     ecx
        shl     ecx,3
        .errnz  8-sizeof COLORTABLETYPE

        mov     BYTE PTR [edx+eax],0ffh
        mov     BYTE PTR [edx+ecx],0ffh

        lea     edx,MemorySpecialColorTable.PhyIndex

        mov     BYTE PTR [edx+eax],0ffh
        mov     BYTE PTR [edx+ecx],0ffh

;/*
;**        ;/**************************************************************/
;**        ;/* Now set up the initial device default palette in the       */
;**        ;/* HWPalette. This is the 256 entry device default palette.   */
;**        ;/**************************************************************/
;**        for (i=0; i<256; i++)
;*/

        lea     esi,FullSizeDeviceDefaultPalette
        lea     edi,HWPalette
        mov     ecx,256

;/*
;**        {
;**            HWPalette[i] = FullSizeDeviceDefaultPalette[i];
;*/

        .errnz  4 - sizeof RGB2
        rep     movsd

;/*
;**        }
;**        DirectDeviceDefaultPalette = FullSizeDeviceDefaultPalette;
;**        MemoryDeviceDefaultPalette = FullSizeDeviceDefaultPalette;
;**        ulDirectDeviceDefaultPaletteSize = 256;
;*/

        lea     eax,FullSizeDeviceDefaultPalette
        mov     DirectDeviceDefaultPalette,eax
        mov     MemoryDeviceDefaultPalette,eax
        mov     ulDirectDeviceDefaultPaletteSize,256

;/*
;** the following avio init fragment came from eddefpdb.c - sdv 07/12/92
;**
;**    /******************************************************************/
;**    /* Set up AVIO color lookup table.                                */
;**    /* We currently have a 256 color default palette, so we only set  */
;**    /* up this table.                                                 */
;**    /* We would like to set up the other tables here, but             */
;**    /* unfortunately the lower level color routines are written in    */
;**    /* such a way that you can only find the default color easily     */
;**    /* in the current default hardware palette                        */
;**    /*                                                                */
;**    /* The other tables will be set up as needed when the default     */
;**    /* palette size changes in palette.asm                            */
;**    /******************************************************************/
;*/

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

        lea     edi,AVIOXlate256
        mov     pAVIOColorXlate,edi

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

        mov     ebx,0

avio_color_init_loop:

;/*
;**    {
;**        pAVIOColorXlate[i] =
;**                   NearestDirectDefaultPhysicalIndex(AVIOColorTable[i]);
;*/




        INVOKE  NearestDirectDefaultPhysicalIndex,
        AVIOColorTable[ebx*sizeof RGB2]

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

;/*
;**    }
;*/

;/*
;**    }
;**    else if (DDT.BitCount == 4)
;**    {
;**        ;/**************************************************************/
;**        ;/* Four bits per pel                                          */
;**        ;/**************************************************************/
;**        DefaultDirectLogicalColorTable = DefaultFourBppTable;
;**        DefaultMemoryLogicalColorTable = DefaultFourBppTable;
;**
;**        cPhysicalColors  = 16;
;**        SizeOfHWPalette  = 16;
;**        MaxLogColorIndex = 255;
;**
;**        fRealizeSupported = TRUE;
;**
;**        ;/**************************************************************/
;**        ;/* Now set the entries in the SpecialColorTable.              */
;**        ;/**************************************************************/
;**        DirectSpecialColorTable[-CLR_TRUE ].PhyIndex = 0x0F;
;**        DirectSpecialColorTable[-CLR_WHITE].PhyIndex = 0x0F;
;**        MemorySpecialColorTable[-CLR_TRUE ].PhyIndex = 0x0F;
;**        MemorySpecialColorTable[-CLR_WHITE].PhyIndex = 0x0F;
;**
;**        ;/**************************************************************/
;**        ;/* Now set up the device default palette in the HWPalette.    */
;**        ;/* This is the 16 entry device default palette.               */
;**        ;/**************************************************************/
;**        for (i=0; i < 16; i++)
;**        {
;**            HWPalette[i] = Reduced16DeviceDefaultPalette[i];
;**        }
;**        DirectDeviceDefaultPalette = Reduced16DeviceDefaultPalette;
;**        MemoryDeviceDefaultPalette = Reduced16DeviceDefaultPalette;
;**        ulDirectDeviceDefaultPaletteSize = 16;
;**    }
;**    else ;/* if (DDT.BitCount == 16) */
;**    {
;**        ;/**************************************************************/
;**        ;/* Sixteen bits per pel.                                      */
;**        ;/**************************************************************/
;**        DefaultDirectLogicalColorTable = DefaultSixteenBppTable;
;**        DefaultMemoryLogicalColorTable = DefaultSixteenBppTable;
;**
;**        cPhysicalColors  = 65536;
;**        MaxLogColorIndex = 255;        ;/* unchanged from 8bpp */
;**
;**        fRealizeSupported = FALSE;
;**
;**        ;/**************************************************************/
;**        ;/* Assume we want the XGA 16bpp value.                        */
;**        ;/**************************************************************/
;**        SpecialIndex = 0xFFFF;
;** #ifdef MATROX
;**        if (RunningOnMatrox())
;**        {
;**            ;/**********************************************************/
;**            ;/* Matrox 16bpp is really only 15bpp!                     */
;**            ;/**********************************************************/
;**            SpecialIndex = 0x7FFF;
;**        }
;** #endif ;/* MATROX */
;**
;**        ;/**************************************************************/
;**        ;/* Now set the entries in the SpecialColorTable.              */
;**        ;/**************************************************************/
;**        DirectSpecialColorTable[-CLR_TRUE ].PhyIndex =
;**        DirectSpecialColorTable[-CLR_WHITE].PhyIndex =
;**        MemorySpecialColorTable[-CLR_TRUE ].PhyIndex =
;**        MemorySpecialColorTable[-CLR_WHITE].PhyIndex = SpecialIndex;
;**
;**        ;/**************************************************************/
;**        ;/* 16bpp does not use a palette in our sense of the word, so  */
;**        ;/* we dont set anything into HWPalette.                       */
;**        ;/**************************************************************/
;**    }
;**
;**
;**    ;/******************************************************************/
;**    ;/* Now we write to the palette registers.                         */
;**    ;/* 16bpp XGA needs special palette handling - MATROX does not     */
;**    ;/* have a palette at all.                                         */
;**    ;/******************************************************************/
;**    if (DDT.BitCount != 16)
;**    {
;**        ;/**************************************************************/
;**        ;/* Copy the palette to the hardware.                          */
;**        ;/* This call will automatically take care of any color to     */
;**        ;/* mono mapping required                                      */
;**        ;/**************************************************************/
;**        LoadPaletteEntries(0,
;**                           SizeOfHWPalette,
;**                           HWPalette);
;*/


        INVOKE  LoadPaletteEntries,
                0,
                SizeOfHWPalette,
                ADDR HWPalette

;/*
;**    }
;**    else
;**    {
;** #ifdef MATROX
;**        if (RunningOnXGA())
;**        {
;** #endif ;/* MATROX */
;**            ;/**********************************************************/
;**            ;/* We write values to the XGA palette registers to ensure */
;**            ;/* correct operation at 16bpp, but this is not a palette  */
;**            ;/* as far as the driver is concerned.                     */
;**            ;/**********************************************************/
;**            LoadDirectPalette();
;** #ifdef MATROX
;**        }
;** #endif ;/* MATROX */
;**    }
;** }
;*/

        ret
InitDefaultColorTables ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = LogToPhyIndex
;*
;* DESCRIPTION   = LogToPhyIndex is a color utility routine that, given a
;*                 logical index, will return the correct physical index to
;*                 use taking into account the current mode (index, RGB or
;*                 palette), the current Logical Color Table, the current
;*                 System Color Table, and the current device default palette.
;*
;* INPUT         = pddc     :PDDC
;*                 LogIndex :LONG
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

LogToPhyIndex PROC SYSCALL USES ESI EBX EDI,
        pddc            :PDDC,
        LogIndex        :LONG

;/*
;** {
;**    ;/******************************************************************/
;**    ;/* Local variables.                                               */
;**    ;/******************************************************************/
;*/

LOCAL   PhyIndex        :ULONG,
        ReqRGB          :RGB2,
        fTrueFalse      :BYTE

        mov     esi,pddc
        ddc?    esi
        ASSUME  ESI:PDDC

;/*
;**    ;/******************************************************************/
;**    ;/* This local flag must be FALSE for the default behaviour.       */
;**    ;/******************************************************************/
;**    fTrueFalse = FALSE;
;*/

        mov     fTrueFalse,0

;/*
;**    ;/******************************************************************/
;**    ;/* Check for a system (negative) index                            */
;**    ;/******************************************************************/
;**    if ( LogIndex < 0 )
;*/

        mov     eax,LogIndex
        cmp     eax,0
        jge     not_system_color

;/*
;**    {
;**        ;/**************************************************************/
;**        ;/* Index is negative - either a special colour or a system    */
;**        ;/* colour                                                     */
;**        ;/**************************************************************/
;**        ;/**************************************************************/
;**        ;/* TRUE and FALSE must not be searched for in the palette     */
;**        ;/**************************************************************/
;**        if ( LogIndex == CLR_TRUE ||
;**             LogIndex == CLR_FALSE)
;*/

        mov     ecx,LogIndex
        cmp     ecx,CLR_TRUE
        sete    dl
        cmp     ecx,CLR_FALSE
        sete    dh
        or      dl,dh
        mov     fTrueFalse,dl

;/*
;**        {
;**            fTrueFalse = TRUE;
;**        }
;**
;**        ;/**************************************************************/
;**        ;/* Negate LogIndex to get a positive index we can look it up  */
;**        ;/* in the table                                               */
;**        ;/**************************************************************/
;**        if ( (-LogIndex) < SPECIAL_COL_TAB_SIZE)
;*/

        neg     eax
        cmp     eax,SPECIAL_COL_TAB_SIZE
        jge     invalid_neg_index

;/*
;**        {
;**            if (pdc->DCIDCType == OD_DIRECT)
;*/

                test    [esi].ddc_fb,DDC_DEVICE
                jz      not_device

;/*
;**            {
;**                PhyIndex = DirectSpecialColorTable[-LogIndex].PhyIndex;
;*/

                mov     ecx,DirectSpecialColorTable[eax*8].PhyIndex
                mov     PhyIndex,ecx

;/*
;**                ReqRGB   = DirectSpecialColorTable[-LogIndex].LogRGB;
;*/

                mov     ecx,DirectSpecialColorTable[eax*8].LogRGB
                mov     ReqRGB,ecx
                jmp     done_if1

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

not_device:

;/*
;**            {
;** /**********************************************************************/
;** /* I do not think we should use the special color table phyindex if   */
;** /* the memory DC is not using the default physical palette. But this  */
;** /* is the equivalent of the old code...                               */
;** /**********************************************************************/
;**                PhyIndex = MemorySpecialColorTable[-LogIndex].PhyIndex;
;*/


                mov     ecx,MemorySpecialColorTable[eax*8].PhyIndex
                mov     PhyIndex,ecx

;/*
;**                ReqRGB   = MemorySpecialColorTable[-LogIndex].LogRGB;
;*/

                mov     ecx,MemorySpecialColorTable[eax*8].LogRGB
                mov     ReqRGB,ecx
done_neg_index:

;/*
;**            }
;*/

                jmp     done_index

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

invalid_neg_index:
;/*
;**        {
;**            ;/**********************************************************/
;**            ;/* Invalid negative index                                 */
;**            ;/**********************************************************/
;**            PhyIndex = CLR_NOPHYINDEX;
;*/

                mov     PhyIndex,CLR_NOPHYINDEX

;/*
;**        }
;*/

done_index:
        jmp     done_if1

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

not_system_color:

;/*
;**    {
;**        ;/**************************************************************/
;**        ;/* Value was positive - a 'normal' logical colour.            */
;**        ;/**************************************************************/
;**        ;/**************************************************************/
;**        ;/* Find out what the current mode is.                         */
;**        ;/**************************************************************/
;**        if (pdc->DCIColFormat == LCOLF_PALETTE)
;*/

        test    [esi].ddc_fbClrTbl,DDC_PALETTE
        jz      not_palette

;/*
;**        {
;**            ;/**********************************************************/
;**            ;/* we have a palette                                      */
;**            ;/**********************************************************/
;**            if (LogIndex < (LONG)pdc->Palette->usCountStored)
;*/

        mov     ebx,[esi].ddc_npdevpal
        cmp     eax,[ebx].DEVPAL.usCountStored
        jge     OutOfRange

;/*
;**            {
;**                ;/******************************************************/
;**                ;/* This entry is valid so pick up the RGB from the    */
;**                ;/* palette.                                           */
;**                ;/******************************************************/
;**                ReqRGB   = pdc->Palette->entries[LogIndex].rgb;
;*/

        .ERRNZ  PALENTRY-8
        mov     ecx,[ebx].DEVPAL.entries[eax*8].rgb
        mov     ReqRGB,ecx

;/*
;**
;**                ;/******************************************************/
;**                ;/* The physical index depends if we are drawing to    */
;**                ;/* the screen or to a bitmap.                         */
;**                ;/******************************************************/
;**                if (pdc->DCIDCType == OD_DIRECT)
;*/

        test    [esi].ddc_fb,DDC_DEVICE
        jz      not_direct

;/*
;**                {
;**                    ;/**************************************************/
;**                    ;/* Drawing to the screen means we use the value   */
;**                    ;/* of the slot assigned by RealizePalette.        */
;**                    ;/**************************************************/
;**                    /*
;**                    ** @74638 added the following three lines to check
;**                    ** for an explicit palette entry.
;**                    */
;**
;**                    if (pdc->Palette->entries[LogIndex].rgb.fcOptions & PC_EXPLICIT)
;**                      PhyIndex = LogIndex;
;**                    else
;**                      PhyIndex = pdc->Palette->entries[LogIndex].bCurrent;
;*/

        .ERRNZ  PALENTRY-8
        xor     ecx,ecx
        test    [ebx].DEVPAL.entries[eax*8].rgb.rgb2_fcOptions,PC_EXPLICIT ;          
        jz      @f                                                         ;          
        mov     PhyIndex,eax                                               ;          
        jmp     done_modes                                                 ;          
@@:                                                                        ;          
        mov     cl,[ebx].DEVPAL.entries[eax*8].bCurrent
        mov     PhyIndex,ecx

        jmp     done_modes

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

not_direct:

;/*
;**                {
;**                    ;/**************************************************/
;**                    ;/* Drawing to the bitmap means we use the logical */
;**                    ;/* palette index as our required index            */
;**                    ;/**************************************************/
;**                    PhyIndex = LogIndex;
;*/

        mov     PhyIndex,eax

;/*
;**                }
;*/

        jmp     done_modes

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

OutOfRange:

;/*
;**            {
;**                ;/******************************************************/
;**                ;/* The required index is outside the palette range    */
;**                ;/******************************************************/
;**                PhyIndex = CLR_NOPHYINDEX;
;*/

        mov     PhyIndex,CLR_NOPHYINDEX

;/*
;**            }
;*/

        jmp     done_modes

;/*
;**        }
;**        else if (pdc->DCIColFormat != LCOLF_RGB)
;*/

not_palette:
        test    [esi].ddc_fbClrTbl,DDC_RGB_MODE
        jnz     its_rgb

;/*
;**        {
;**            ;/**********************************************************/
;**            ;/* Mode is index.                                         */
;**            ;/* Get the physical index directly from the LCT.          */
;**            ;/**********************************************************/
;**
;**            ;/**********************************************************/
;**            ;/* Index is positive                                      */
;**            ;/**********************************************************/
;**            if (LogIndex <= (LONG)pdc->DCIHighIndex)
;*/

        cmp     eax,[esi].ddc_ctMax
        jg      too_big

;/*
;**            {
;**                ReqRGB   = pdc->DCIColorTable[LogIndex].LogRGB;
;*/

        .ERRNZ  COLORTABLETYPE-8

        mov     ebx,[esi].ddc_pClrTbl
        mov     ecx,[ebx+(eax*8)].COLORTABLETYPE.LogRGB
        mov     ReqRGB,ecx

;/*
;**                PhyIndex = pdc->DCIColorTable[LogIndex].PhyIndex;
;*/

        mov     ecx,[ebx+(eax*8)].COLORTABLETYPE.PhyIndex
        mov     PhyIndex,ecx

        jmp     done_modes

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

too_big:

;/*
;**            {
;**                PhyIndex = CLR_NOPHYINDEX;
;*/

        mov     PhyIndex,CLR_NOPHYINDEX

;/*
;**            }
;*/

        jmp     done_modes

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

its_rgb:

;/*
;**        {
;**            ;/**********************************************************/
;**            ;/* Mode is RGB so get it directly from the LogIndex.      */
;**            ;/* We dont actually convert it to a physical index here   */
;**            ;/* because there are various ways to do this dependant    */
;**            ;/* on circumstances, so its done below.  We must flag     */
;**            ;/* that we are in RGB mode in case we fall through all the*/
;**            ;/* special cases, so that we ensure we call the default   */
;**            ;/* routine to convert from RGB to physical index.         */
;**            ;/**********************************************************/
;**
;**            if (((PBYTE)&LogIndex)[3]==0)
;*/

        test    eax,0FF000000h
        jnz     option_bits_nonzero

;/*
;**            {
;**                ReqRGB.bBlue  = ((PBYTE)&LogIndex)[0];
;**                ReqRGB.bGreen = ((PBYTE)&LogIndex)[1];
;**                ReqRGB.bRed   = ((PBYTE)&LogIndex)[2];
;*/

        mov     ReqRGB.rgb2_bBlue,al
        mov     ReqRGB.rgb2_bGreen,ah
        ror     eax,16
        mov     ReqRGB.rgb2_bRed,al
        rol     eax,16

;/*
;**            PhyIndex = MODE_WAS_RGB;
;*/

        mov     PhyIndex,MODE_WAS_RGB
        jmp     done_modes

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

option_bits_nonzero:

;/*
;**            {
;**                /******************************************************/
;**                /* If the options bits are not zero then we return    */
;**                /* error.                                             */
;**                /******************************************************/
;**                PhyIndex = CLR_NOPHYINDEX;
;*/

        mov     PhyIndex,CLR_NOPHYINDEX

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

done_modes:
done_if1:

;/*
;**    }
;**
;**    ;/******************************************************************/
;**    ;/* At this point we have the RGB value and possibly the physical  */
;**    ;/* index as well.                                                 */
;**    ;/* Dependant on the bits per pel we massage this information in   */
;**    ;/* different ways.                                                */
;**    ;/******************************************************************/
;**    if (PhyIndex == CLR_NOPHYINDEX)
;*/

        cmp     PhyIndex,CLR_NOPHYINDEX
        jne     @F

;/*
;**    {
;**        ;/**************************************************************/
;**        ;/* Invalid value no no need for further calculation           */
;**        ;/**************************************************************/
;*/

        jmp     done_ifelses

;/*
;**    }
;**    else if (pdc->DCISelListEntry->Inf
;*/

@@:
        mov     ebx,[esi].ddc_npsd      ;          
        cmp     ebx,INVALID_ADDRESS     ;          
        je      @F                      ;          

        test    [ebx].SURFACE.sd_fb,SD_COLOR
        jnz     @F

;/*
;**    {
;**        ;/**************************************************************/
;**        ;/* Target bitmap is 1 bpp so we must only return black or     */
;**        ;/* white.                                                     */
;**        ;/**************************************************************/
;**        PhyIndex = MapRGBToMono(&ReqRGB);
;*/


        MapRGBToMono    ReqRGB,TRASHEDX

        mov     PhyIndex,eax
        jmp     done_ifelses

;/*
;**    }
;**    else if (DDT.BitCount == 16)
;** @@:
;**    {
;**        ;/**************************************************************/
;**        ;/* Map the RGB2 value into an RGB16 value. (16bpp pel value)  */
;**        ;/**************************************************************/
;**        PhyIndex = RGB16FromPRGB2(&ReqRGB);
;**        RGB16FromPRGB2  ReqRGB  ;this is a macro.  Pass in value,not pointer.
;**        mov     PhyIndex,eax
;**
;**        jmp     done_ifelses
;**    }
;**    else if (fRealizeSupported && !fTrueFalse)
;*/

@@:

        cmp     fTrueFalse,0
        jnz     done_ifelses

;/*
;**    {
;**        ;/**************************************************************/
;**        ;/* If we support realization we must take some care here.     */
;**        ;/* True and False are not affected by realization so we       */
;**        ;/* already have the correct values for them.                  */
;**        ;/**************************************************************/
;**        if (ColorTableRealized)
;*/

        cmp     ColorTableRealized,0
        je      not_realized

;/*
;**        {
;**            ;/**********************************************************/
;**            ;/* There is currently a realized color table so we must   */
;**            ;/* search the palette for the required color.             */
;**            ;/* The search is necessary because it may not be us that  */
;**            ;/* is the current realized color table.                   */
;**            ;/**********************************************************/
;**            PhyIndex = SearchRealizedLCTPalette(ReqRGB);
;*/

        INVOKE  SearchRealizedLCTPalette,
                ReqRGB
        mov     PhyIndex,eax

        jmp     done_ifelses

;/*
;**        }
;**        else if (pdc->DCIColStatus & LCOL_REALIZABLE)
;*/

not_realized:
        test    [esi].ddc_fbClrTbl,DDC_REALIZABLE
        jz      done_ifelses

;/*
;**        {
;**/**********************************************************************/
;**/* If no color table is realized then we must surely have black and   */
;**/* white in the HW palette so why don't we use them here...           */
;**/**********************************************************************/
;**            ;/**********************************************************/
;**            ;/* CLR_BLACK and CLR_WHITE need special care here.        */
;**            ;/* In all other cases we already have the correct         */
;**            ;/* PhyIndex (being the index into the default table       */
;**            ;/* picked up from SysColorTable[..].PhyIndex              */
;**            ;/**********************************************************/
;**            if (LogIndex == CLR_BLACK)
;*/

        mov     ebx,[esi].ddc_pClrTbl
        cmp     LogIndex,CLR_BLACK
        jne     test_white

;/*
;**            {
;**                PhyIndex = pdc->DCIColorTable[CLR_NEUTRAL].PhyIndex;
;*/

        .ERRNZ  COLORTABLETYPE-8
        mov     eax,[ebx+CLR_NEUTRAL*8].COLORTABLETYPE.PhyIndex
        mov     PhyIndex,eax
        jmp     done_ifelses

;/*
;**            }
;**            else if (LogIndex == CLR_WHITE)
;*/

test_white:
        cmp     LogIndex,CLR_WHITE
        jne     done_ifelses

;/*
;**            {
;**                PhyIndex = pdc->DCIColorTable[CLR_BACKGROUND].PhyIndex;
;*/

        mov     eax,[ebx+CLR_BACKGROUND*8].COLORTABLETYPE.PhyIndex
        mov     PhyIndex,eax

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

done_ifelses:


;/*
;**    ;/******************************************************************/
;**    ;/* At this stage we have done almost all our massaging to get the */
;**    ;/* correct index.                                                 */
;**    ;/* However the one remaining twist is if we were in RGB mode and  */
;**    ;/* have not already found the physical index then we must call    */
;**    ;/* off to find this.                                              */
;**    ;/******************************************************************/
;**    if (PhyIndex == MODE_WAS_RGB)
;*/

        mov     eax,PhyIndex
        cmp     eax,MODE_WAS_RGB
        jne     @F

;/*
;**    {
;**        PhyIndex = NearestDefaultPhysicalIndex(ReqRGB);
;*/

        INVOKE  NearestDefaultPhysicalIndex,
                esi,
                ReqRGB
@@:

;/*
;**    }
;**
;**    return(PhyIndex);
;*/

        ret
LogToPhyIndex ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = NearestDefaultPaletteIndex256
;*
;* DESCRIPTION   =
;*
;* NearestDefaultPaletteIndex256()
;* -------------------------------
;*  takes an RGB2 value and returns the index of the nearest colour
;*  in the default 256 palette.
;*
;*
;* The default 256 entry palette consists of two parts:
;*
;*           Greys in slots 112 to 143.
;*           Colors in slots 0 to 111, 144 to 255
;*
;* The Colors are made up from:
;*          7 possible R values evenly spaced from 0 -> 255
;*          8 possible G values evenly spaced from 0 -> 255
;*          4 possible B values evenly spaced from 0 -> 255
;*
;* The Greys have 34 equal R,G + B values evenly spread from 0 -> 255
;*      (if you include the 'Colors' BLACK and WHITE)
;*
;* The Maths Involved
;* ------------------
;*
;* With N values spread from 0 to 255, the nearest value to X can be
;* calculated by:
;*
;*      Distance between values :  Dist = 256 / (N - 1)
;*
;*      Index of Nearest Value :   Num  = (X + Dist / 2) / Dist
;*
;*      => Num = (X + (128 / (N - 1))) / (256 / (N - 1))
;*
;*      => Num = (X * (N-1) + 128) / 256
;*
;* The first step in deciding on the nearest palette entry is to
;* decide if we have a Grey or a Color. This is detailed later.
;*
;* If we have a Color
;* -------------------
;*
;* As all colours are made up from a fixed set of R G and B values
;* the nearest colour can be found by first finding the nearest
;* R, G and B values individually.
;*
;* The Nearest R G and B values are:
;*
;*      RNum = (R * 6 + 128) / 256
;*      GNum = (G * 7 + 128) / 256
;*      BNum = (B * 3 + 128) / 256
;*
;* If you ignore the middle grey slots, the slot number corresponding
;* to these values is given by:
;*
;*      Slot = RNum * 32 + GNum * 4 + BNum
;*
;*  This can then be adjusted to allow for the Grey slots:
;*
;*      if (Slot > 111) Slot += 32
;*
;* If we have a Grey
;* -----------------
;*
;* The grey index is given by:
;*
;* ie   Grey = (G * 33 + 128) / 256
;*
;* the slot this maps to is given by
;*
;*      if (Grey == 0)
;*          Slot = 0;       -- ie BLACK
;*      else if (Grey == 33)
;*          Slot = 255;     -- ie WHITE
;*      else
;*          Slot = 111 + Grey
;*
;* Deciding if we have a Grey or Color
;* ------------------------------------
;* We have a Grey if the Grey index corresponding to the R, G and B
;* values are the same:
;*      RGrey = (R * 33 + 128) / 256
;*      GGrey = (G * 33 + 128) / 256
;*      BGrey = (B * 33 + 128) / 256
;*
;* if (RGrey == GGrey == BGrey)
;*      Grey Value
;* else
;*      Color Value
;*
;*
;* INPUT         = NONE
;*
;*
;*
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

NearestDefaultPaletteIndex256 PROC SYSCALL,
        RGBColor       :DWORD

;/*
;** {
;*/

LOCAL   Temp    :ULONG,
        Red     :ULONG,
        Green   :ULONG,
        Blue    :ULONG

        mov     eax,0
        mov     edx,RGBColor

;/*
;**    ULONG   Red   = (*(ULONG*)RGBColor & RED_MASK)   >> 16;
;**    ULONG   Green = (*(ULONG*)RGBColor & GREEN_MASK) >>  8;
;**    ULONG   Blue  = (*(ULONG*)RGBColor & BLUE_MASK);
;*/

        mov     al,[edx].RGB2.rgb2_bBlue
        mov     Blue,eax
        mov     al,[edx].RGB2.rgb2_bGreen
        mov     Green,eax
        mov     al,[edx].RGB2.rgb2_bRed
        mov     Red,eax


;/*
;**    ;/******************************************************************/
;**    ;/* Do we have a grey value or a colour                            */
;**    ;/******************************************************************/
;**    Temp = ( Red * 33 + 128 ) / 256;
;*/

        mov     ecx,eax
        shl     eax,05
        add     eax,ecx
        add     eax,00000080h
        shr     eax,08
        ;mov     edx,33
        ;mul     edx
        ;Add_128
        ;Div_256
        mov     ecx,eax

;/*
;**    if ( (Temp == ( Green * 33 + 128 ) / 256 ) &&
;**         (Temp == ( Blue  * 33 + 128 ) / 256 ) )
;*/

        mov     eax,Green
        mov     edx,eax
        shl     eax,05
        add     eax,edx
        add     eax,00000080h
        shr     eax,08
        cmp     eax,ecx
        jne     not_grey

        mov     eax,Blue
        mov     edx,eax
        shl     eax,05
        add     eax,edx
        add     eax,00000080h
        shr     eax,08
        cmp     eax,ecx
        jne     not_grey

;/*
;**    {
;**        ;/**************************************************************/
;**        ;/* We have a Grey value                                       */
;**        ;/**************************************************************/
;**        if (Temp == 0)
;*/

        mov     eax,0
        cmp     ecx,0
        jne     @F

;/*
;**        {
;**            return(PaletteFudgeTable256[0]);            /* BLACK */
;*/

                mov     al,PaletteFudgeTable256[0]
                jmp     ndpi256_exit
@@:

;/*
;**        }
;**        else if (Temp == 33)
;*/

        cmp     ecx,33
        jne     @F

;/*
;**        {
;**            return(PaletteFudgeTable256[255]);          /* WHITE */
;*/

                mov     al,PaletteFudgeTable256[255]
                jmp     ndpi256_exit
@@:

;/*
;**        }
;**        else
;**        {
;**            return(PaletteFudgeTable256[111 + Temp]);
;*/

                add     ecx,111
                mov     al,PaletteFudgeTable256[ecx]
                jmp     ndpi256_exit

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

not_grey:

;/*
;**    {
;**        ;/**************************************************************/
;**        ;/* We have a Color value                                     */
;**        ;/**************************************************************/
;**        Temp =  ((Red   * 6 + 128) / 256) * 32 +
;**                ((Green * 7 + 128) / 256) * 4  +
;**                ((Blue  * 3 + 128) / 256);
;*/


        mov     eax,Red
        ;Mul_6
        ;Add_128
        ;Div_256
        ;shl     eax,5   ;*32
        lea     eax,[eax+eax*2]
        shl     eax,1
        add     eax,00000080h
        and     eax,0ffffff07h
        shr     eax,03
        mov     ecx,eax

        mov     eax,Green

;/*
;** Mul_7
;** Add_128
;** Div_256
;** Mul_4
;*/

        mov     edx,eax
        shl     eax,03
        sub     eax,edx
        add     eax,00000080h
        and     eax,0ffffff3fh
        shr     eax,06
        add     ecx,eax

        mov     eax,Blue

;/*
;** Mul_3
;** Add_128
;** Div_256
;*/

        lea     eax,[eax+eax*2]
        add     eax,00000080h
        shr     eax,08
        add     ecx,eax

;/*
;**        ;/**************************************************************/
;**        ;/* Adjust for the Grey slots in the centre of the palette     */
;**        ;/**************************************************************/
;**        if (Temp < 112)
;*/

        cmp     ecx,112
        jb      @F

;/*
;**        {
;**            return(PaletteFudgeTable256[Temp]);
;**        }
;**        else
;**        {
;**            return(PaletteFudgeTable256[Temp + 32]);
;*/

        add     ecx,32
@@:
        mov     eax,0
        mov     al,PaletteFudgeTable256[ecx]

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

ndpi256_exit:
        ret
NearestDefaultPaletteIndex256 ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = NearestDefaultPaletteIndex128
;*
;* DESCRIPTION   =
;*
;*      takes an RGB2 value and returns the index of the nearest colour
;*      in the default 128 palette.
;*
;*
;*     The default 128 entry palette consists of two parts:
;*
;*               Greys in slots 60 to 67.
;*               Colors in slots 0 to 59, 68 to 127
;*
;*
;*     The Colors are made up from:
;*              5 possible R values evenly spaced from 0 -> 255
;*              6 possible G values evenly spaced from 0 -> 255
;*              4 possible B values evenly spaced from 0 -> 255
;*
;*     The Greys have 10 equal R,G + B values evenly spread from 0 -> 255
;*          (if you include the 'Colors' BLACK and WHITE)
;*
;*     The maths envolved and the splitting into Greys and Colors is
;*     detailed above in the NearestDefaultPaletteIndex256 function.
;*
;*     If we have a Color
;*     -------------------
;*
;*     The Nearest R G and B values are:
;*
;*          RNum = (R * 4 + 128) / 256
;*          GNum = (G * 5 + 128) / 256
;*          BNum = (B * 3 + 128) / 256
;*
;*     If you ignore the middle grey slots, the slot number corresponding
;*     to these values is given by:
;*
;*          Slot = RNum * 24 + GNum * 6 + BNum
;*
;*     =>   Slot = ((RNum * 4) + GNum) * 6 + BNum
;*
;*      This can then be adjusted to allow for the Grey slots:
;*
;*          if (Slot > 59) Slot += 8
;*
;*     If we have a Grey
;*     -----------------
;*
;*     The grey index is given by:
;*
;*     ie   Grey = (G * 9 + 128) / 256
;*
;*     the slot this maps to is given by
;*
;*          if (Grey == 0)
;*              Slot = 0;       -- ie BLACK
;*          else if (Grey == 9)
;*              Slot = 127;     -- ie WHITE
;*          else
;*              Slot = 59 + Grey
;*
;*
;* INPUT         = RGBColor :DWORD
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

NearestDefaultPaletteIndex128 PROC SYSCALL,
        RGBColor       :DWORD

;/*
;** {
;*/


LOCAL   Temp    :ULONG,
        Red     :ULONG,
        Green   :ULONG,
        Blue    :ULONG

        mov     eax,0
        mov     edx,RGBColor

;/*
;**    ULONG   Red   = (*(ULONG*)RGBColor & RED_MASK)   >> 16;
;**    ULONG   Green = (*(ULONG*)RGBColor & GREEN_MASK) >>  8;
;**    ULONG   Blue  = (*(ULONG*)RGBColor & BLUE_MASK);
;*/

        mov     al,[edx].RGB2.rgb2_bGreen
        mov     Green,eax
        mov     al,[edx].RGB2.rgb2_bBlue
        mov     Blue,eax
        mov     al,[edx].RGB2.rgb2_bRed
        mov     Red,eax

;/*
;**    ;/******************************************************************/
;**    ;/* Do we have a grey value or a colour                            */
;**    ;/******************************************************************/
;**    Temp = ( Red * 9 + 128 ) / 256;
;*/

;/*
;** Mul_9
;*/

        lea     eax,[eax+eax*8]
        Add_128
        Div_256
        mov     ecx,eax

;/*
;**    if ( (Temp == ( Green * 9 + 128 ) / 256 ) &&
;**         (Temp == ( Blue  * 9 + 128 ) / 256 ) )
;*/

        mov     eax,Green

;/*
;** Mul_9
;*/

        lea     eax,[eax+eax*8]
        Add_128
        Div_256
        cmp     eax,ecx
        jne     not_grey

        mov     eax,Blue

;/*
;** Mul_9
;*/

        lea     eax,[eax+eax*8]
        Add_128
        Div_256
        cmp     eax,ecx
        jne     not_grey

;/*
;**    {
;**        ;/**************************************************************/
;**        ;/* We have a Grey value                                       */
;**        ;/**************************************************************/
;**        if (Temp == 0)
;*/

        mov     eax,0
        cmp     ecx,0
        jne     @F

;/*
;**        {
;**            return(PaletteFudgeTable128[0]);            /* BLACK */
;*/

                mov     al,PaletteFudgeTable128[0]
                jmp     ndpi128_exit
@@:

;/*
;**        }
;**        else if (Temp == 9)
;*/

        cmp     ecx,9
        jne     @F

;/*
;**        {
;**            return(PaletteFudgeTable128[127]);          /* WHITE */
;*/

                mov     al,PaletteFudgeTable128[127]
                jmp     ndpi128_exit
@@:

;/*
;**        }
;**        else
;**        {
;**            return(PaletteFudgeTable128[Temp + 59]);
;*/

                add     ecx,59
                mov     al,PaletteFudgeTable128[ecx]
                jmp     ndpi128_exit

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

not_grey:

;/*
;**    {
;**        ;/**************************************************************/
;**        ;/* We have a Color value                                     */
;**        ;/**************************************************************/
;**        Temp =  (((Red   * 4 + 128) / 256) * 6 +
;**                 ((Green * 5 + 128) / 256) ) * 4 +
;**                 ((Blue  * 3 + 128) / 256);
;*/


        mov     eax,Red

;/*
;** Mul_4
;*/

        add     eax,20h
        and     eax,3fffffc0h
        shr     eax,06
        lea     eax,[eax+eax*2]
        shl     eax,03

;/*
;** Add_128
;** Div_256
;** Mul_6
;*/

        mov     ecx,eax

        mov     eax,Green
        lea     eax,[eax+eax*4]
        add     eax,00000080h
        and     eax,0ffffff3fh
        shr     eax,06

;/*
;** Mul_5
;** Add_128
;** Div_256
;** Mul_4
;*/

        add     ecx,eax

        mov     eax,Blue
        lea     eax,[eax+eax*2]
        add     eax,00000080h
        shr     eax,08

;/*
;** Mul_3
;** Add_128
;**  Div_256
;*/

        add     ecx,eax

;/*
;**        ;/**************************************************************/
;**        ;/* Adjust for the Grey slots in the centre of the palette     */
;**        ;/**************************************************************/
;**        if (Temp > 59)
;*/

        cmp     ecx,59
        jbe     @F

;/*
;**        {
;**            return (PaletteFudgeTable128[Temp + 8]);
;*/

        add     ecx,8
@@:
        mov     eax,0
        mov     al,PaletteFudgeTable128[ecx]

;/*
;**        }
;**        else
;**        {
;**            return(PaletteFudgeTable128[Temp]);
;**        }
;**    }
;*/

ndpi128_exit:

        ret
NearestDefaultPaletteIndex128 ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = NearestDefaultPaletteIndex64
;*
;* DESCRIPTION   =
;*
;*  takes an RGB2 value and returns the index of the nearest colour
;*  in the default 64 entry palette.
;*
;*
;* The default 64 entry palette consists of two parts:
;*
;*           Greys in slots 30 to 33.
;*           Colours in slots 0 to 29, 34 to 63
;*
;*
;* The Colours are made up from:
;*          4 possible R values evenly spaced from 0 -> 255
;*          5 possible G values evenly spaced from 0 -> 255
;*          3 possible B values evenly spaced from 0 -> 255
;*
;* The Greys are NOT evenly spread. The easiest method for dealing
;* with the greys is not first ignore them and then do a nearest
;* colour comparison between the RGB passed and each of the 4 Greys
;* available.
;*
;* The maths envolved detailed above in the
;* NearestDefaultPaletteIndex256 function.
;*
;* To find the nearest colour
;* --------------------------
;*
;* The Nearest R G and B values are:
;*
;*      RNum = (R * 3 + 128) / 256
;*      GNum = (G * 4 + 128) / 256
;*      BNum = (B * 2 + 128) / 256
;*
;* If you ignore the middle grey slots, the slot number corresponding
;* to these values is given by:
;*
;*      Slot = RNum * 15 + GNum * 3 + BNum
;*
;* =>   Slot = ((RNum * 5) + GNum) * 3 + BNum
;*
;* INPUT         = RGBColor       :DWORD
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

NearestDefaultPaletteIndex64 PROC SYSCALL,
        RGBColor       :DWORD

;/*
;** {
;*/

LOCAL   ulNearestColour :ULONG,
        ulDiff          :ULONG,
        ulGreyEntry     :ULONG,
        Red             :ULONG,
        Green           :ULONG,
        Blue            :ULONG

        mov     eax,0
        mov     edx,RGBColor

;/*
;**    ULONG   Red   = (*(ULONG*)RGBColour & RED_MASK)   >> 16;
;**    ULONG   Green = (*(ULONG*)RGBColour & GREEN_MASK) >>  8;
;**    ULONG   Blue  = (*(ULONG*)RGBColour & BLUE_MASK);
;*/

        mov     al,[edx].RGB2.rgb2_bGreen
        mov     Green,eax
        mov     al,[edx].RGB2.rgb2_bBlue
        mov     Blue,eax
        mov     al,[edx].RGB2.rgb2_bRed
        mov     Red,eax

;/*
;**    /******************************************************************/
;**    /* Find the nearest colour (ignoring Greys for now)               */
;**    /******************************************************************/
;**    ulNearestColour =  (((Red   * 3 + 128) / 256) * 5  +
;**                       ((Green * 4 + 128) / 256) ) * 3  +
;**                       ((Blue  * 2 + 128) / 256);
;*/


;/*
;** Mul_3
;** Add_128
;** Div_256
;** Mul_5
;*/
        lea     eax,[eax+eax*2]
        add     eax,00000080h
        shr     eax,08
        lea     eax,[eax+eax*4]
        mov     ecx,eax

        mov     eax,Green

;/*
;** Mul_4
;** Add_128
;** Div_256
;** Mul_3
;*/

        lea     eax,[eax+20h]
        and     eax,03fffffc0h
        shr     eax,06
        add     ecx,eax
        lea     ecx,[ecx+ecx*2]

        Mov     eax,Blue

;/*
;** Mul_2
;** Add_128
;** Div_256
;*/
        lea     eax,[eax+40h]
        and     eax,07fffff80h
        shr     eax,07
        add     ecx,eax

;/*
;**    /******************************************************************/
;**    /* Adjust for the Grey slots in the centre of the palette         */
;**    /******************************************************************/
;**    if (ulNearestColour > 29)
;*/

        cmp     ecx,29
        jbe     @F

;/*
;**    {
;**        ulNearestColour += 4;
;*/

        add     ecx,4
@@:
        mov     ulNearestColour,ecx

;/*
;**    }
;**
;**    /******************************************************************/
;**    /* Now see if one of the Greys is actually closer than the colour */
;**    /* we have.                                                       */
;**    /******************************************************************/
;**    ulDiff = rgb2_diff(*RGBColour,
;**         Reduced64DeviceDefaultPalette[PaletteFudgeTable64[ulNearestColour]]);
;*/

        mov     eax,0
        mov     al,PaletteFudgeTable64[ecx]
        mov     edx,RGBColor

        INVOKE  rgb2_diff,
                RGB2 PTR [edx],
                Reduced64DeviceDefaultPalette[eax * sizeof RGB2]

        mov     ulDiff,eax

;/*
;**    for (ulGreyEntry = 30; ulGreyEntry <= 33  ; ulGreyEntry++)
;*/


        mov     ecx,30
top_loop:
        assert  EDX,E,RGBColor


;/*----------------------
;** EDX STILL == RGBColor
;**----------------------
;**    {
;**        /**************************************************************/
;**        /* If difference between this Grey and the passed RGB is less */
;**        /* than the difference between the Colour calculated and the  */
;**        /* passed RGB, then return this Grey.                         */
;**        /**************************************************************/
;**        if (rgb2_diff(*RGBColour,
;**               Reduced64DeviceDefaultPalette[PaletteFudgeTable64[ulGreyEntry]])
;**            < ulDiff)
;*/

        mov     eax,0
        mov     al,PaletteFudgeTable64[ecx]
        INVOKE  rgb2_diff,
                RGB2 PTR [edx],
                Reduced64DeviceDefaultPalette[eax * sizeof RGB2]

        cmp     eax,ulDiff
        jae     @F

;/*
;**        {
;**            /**********************************************************/
;**            /* The passed colour is nearer to this Grey.              */
;**            /**********************************************************/
;**            ulDiff = rgb2_diff(*RGBColour,
;**               Reduced64DeviceDefaultPalette[PaletteFudgeTable64[ulGreyEntry]]);
;*/

        mov     ulDiff,eax

;/*
;**            ulNearestColour = ulGreyEntry;
;*/

        mov     ulNearestColour,ecx

;/*
;**        }
;*/

@@:

;/*
;**    }
;*/

        inc     ecx
        cmp     ecx,33
        jbe     top_loop

;/*
;**    return(PaletteFudgeTable64[ulNearestColour]);
;*/

        mov     ecx,ulNearestColour
        mov     eax,0
        mov     al,PaletteFudgeTable64[ecx]
        ret
NearestDefaultPaletteIndex64 ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = NearestDefaultPhysicalColor
;*
;* DESCRIPTION   = NearestDefaultPhysicalColor finds the RGB in the default
;*                 physical palette which is the closest match to the
;*                 supplied RGB value.
;*
;*
;*
;* INPUT         = pddc           :PDDC
;*                 RGBColor       :RGB2
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

NearestDefaultPhysicalColor PROC SYSCALL USES EBX ECX,
        pddc           :PDDC,
        RGBColor       :RGB2


;/*
;** {
;**    ;/******************************************************************/
;**    ;/* Local variables                                                */
;**    ;/******************************************************************/
;*/

LOCAL   Diff            :ULONG,   ;/* difference of current entry */
        MinDiff         :ULONG,   ;/* Minimum Difference to date  */
        i               :ULONG,   ;/* loop variable               */
        ClosestRGB                 :RGB2,
        ClosestIndex               :ULONG,
        DeviceDefaultPalette       :DWORD,
        ulDeviceDefaultPaletteSize :ULONG

;/*
;**    if (DDT.BitCount == 16)
;**    {
;**        ;/**************************************************************/
;**        ;/* The RGB in the hardware only has a limited number of bits  */
;**        ;/* so adjust the RGB value to the nearest in the hardware.    */
;**        ;/**************************************************************/
;**        ClosestRGB.bRed   = (BYTE)(RGBColor.bRed   & 0xF8);/* 5 red  bits */
;**        ClosestRGB.bBlue  = (BYTE)(RGBColor.bBlue  & 0xF8);/* 5 blue bits */
;** #ifdef MATROX
;**        if (RunningOnMatrox())
;**        {
;**            ;/**********************************************************/
;**            ;/* Matrox 16bpp has just 5 green bits                     */
;**            ;/**********************************************************/
;**            ClosestRGB.bGreen = (BYTE)(RGBColor.bGreen & 0xF8);/* 5 green bits*/
;**        }
;**        else
;** #endif ;/* MATROX */
;**        {
;**            ;/**********************************************************/
;**            ;/* XGA 16bpp has 6 green bits.                            */
;**            ;/**********************************************************/
;**            ClosestRGB.bGreen = (BYTE)(RGBColor.bGreen & 0xFC);/* 6 green bits*/
;**        }
;**        ClosestRGB.fcOptions = 0;
;**
;**        return( ClosestRGB );
;**    }
;**
;**    ;/******************************************************************/
;**    ;/* With palette manager the device default palette for the screen */
;**    ;/* (OD_DIRECT DCs) will change size as HW slots are allocated to  */
;**    ;/* palette manager palettes.  The device default palette for      */
;**    ;/* OD_MEMORY DCs will always be the full size 256 entry palette   */
;**    ;/* at 8 bits per pel.  At 4 bits per pel the device default       */
;**    ;/* palette will always be the 16 entry reduced size device        */
;**    ;/* default palette for both cases.                                */
;**    ;/******************************************************************/
;*/

        mov     edx,pddc

;/*
;**    if (pdc->DCIDCType == OD_DIRECT)
;*/

        test    [edx].DDC.ddc_fb,DDC_DEVICE
        jz      use_memory

;/*
;**    {
;**        DeviceDefaultPalette = DirectDeviceDefaultPalette;
;*/

        mov     ebx,DirectDeviceDefaultPalette

;/*
;**        ulDeviceDefaultPaletteSize = ulDirectDeviceDefaultPaletteSize;
;*/

        mov     eax,ulDirectDeviceDefaultPaletteSize
        jmp     set_DefpalAndSize

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

use_memory:

;/*
;**    {
;**        DeviceDefaultPalette = MemoryDeviceDefaultPalette;
;*/

        mov     ebx,MemoryDeviceDefaultPalette

;/*
;**        ulDeviceDefaultPaletteSize = SizeOfHWPalette;
;*/

        mov     eax,SizeOfHWPalette

set_DefpalAndSize:

;/*
;**    }
;*/

        mov     DeviceDefaultPalette,ebx
        mov     ulDeviceDefaultPaletteSize,eax

;/*
;**       ASSUME  ebx:PRGB2
;**
;**    ;/******************************************************************/
;**    ;/* Note: the VGA uses a cunning algorithm for calculating the     */
;**    ;/* nearest color. Ideally we want to improve our code here in     */
;**    ;/* a similar way.                                                 */
;**    ;/*                                                                */
;**    ;/* Several cunning algorithms coming up ...                       */
;**    ;/*                                                                */
;**    ;/* The routines NearestDefaultPaletteIndex256                     */
;**    ;/*              NearestDefaultPaletteIndex128                     */
;**    ;/*              NearestDefaultPaletteIndex64                      */
;**    ;/* have been created to return the slot number corresponding to   */
;**    ;/* the nearest default palette entry for the 256, 128 and 64      */
;**    ;/* entry palettes.                                                */
;**    ;/*                                                                */
;**    ;/* The other palettes need to have there entries searched for     */
;**    ;/* the nearest value.                                             */
;**    ;/******************************************************************/
;**    if (DDT.BitCount == 8)
;**    {
;**        switch (ulDeviceDefaultPaletteSize)
;*/

        mov     eax,ulDeviceDefaultPaletteSize
        cmp     eax,256
        jne     @F

;/*
;**        {
;**            case 256:
;**                ;/******************************************************/
;**                ;/* Calcultae the slot number of the nearest entry and */
;**                ;/* look up its RGB value.                             */
;**                ;/******************************************************/
;**                ClosestIndex = NearestDefaultPaletteIndex256(&RGBColor);
;*/

        INVOKE  NearestDefaultPaletteIndex256,
                ADDR RGBColor

        jmp     end_switch

;/*
;**                ClosestRGB   = DeviceDefaultPalette[ ClosestIndex ];
;**                ClosestRGB.fcOptions = 0;
;**                return( ClosestRGB );
;**
;**            case 128:
;*/

@@:
        cmp     eax,128
        jne     @F

;/*
;**                ;/******************************************************/
;**                ;/* Calculate the slot number of the nearest entry and */
;**                ;/* look up its RGB value.                             */
;**                ;/******************************************************/
;**                ClosestIndex = NearestDefaultPaletteIndex128(&RGBColor);
;*/

        INVOKE  NearestDefaultPaletteIndex128,
                ADDR RGBColor

        jmp     end_switch

;/*
;**                ClosestRGB   = DeviceDefaultPalette[ ClosestIndex ];
;**                ClosestRGB.fcOptions = 0;
;**                return( ClosestRGB );
;**
;**            case  64:
;*/

@@:
        cmp     eax,64
        jne     @F

;/*
;**                ;/******************************************************/
;**                ;/* Calculate the slot number of the nearest entry and */
;**                ;/* look up its RGB value.                             */
;**                ;/******************************************************/
;**                ClosestIndex = NearestDefaultPaletteIndex64(&RGBColor);
;*/

        INVOKE  NearestDefaultPaletteIndex64,
                ADDR RGBColor

        jmp     end_switch

;/*
;**                ClosestRGB   = DeviceDefaultPalette[ ClosestIndex ];
;**                ClosestRGB.fcOptions = 0;
;**                return( ClosestRGB );
;**        }
;*/

end_switch:
        mov     eax,[ebx+eax*4]
        mov     ClosestRGB,eax
        mov     ClosestRGB.rgb2_fcOptions,0
        mov     eax,ClosestRGB
        jmp     ndpc_exit
@@:

;/*
;**    }
;**
;**    ;/******************************************************************/
;**    ;/* First check for exact match in the device default Palette      */
;**    ;/******************************************************************/
;**    MinDiff = 0xFFFFFFFF;
;*/

        mov     MinDiff,0FFFFFFFFh

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

        mov     ecx,0
top_loop1:
        cmp     ecx,ulDeviceDefaultPaletteSize
        jae     exit_loop1

;/*
;**    {
;**        if ( (URGB(RGBColor) & RGB_MASK) ==
;**             (URGB(DeviceDefaultPalette[i]) & RGB_MASK) )
;*/

        mov     eax,RGBColor
        and     eax,RGB_MASK
        mov     edx,[ebx+ecx*4]
        and     edx,RGB_MASK
        cmp     eax,edx
        jne     endif_1

;/*
;**        {
;**            ClosestRGB = DeviceDefaultPalette[i];
;*/

        mov     eax,[ebx+ecx*4]
        mov     ClosestRGB,eax

;/*
;**            MinDiff = 0;
;*/

        mov     MinDiff,0
        jmp     exit_loop1

;/*
;**            break;
;*/

endif_1:

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

        inc     ecx
        jmp     top_loop1
exit_loop1:

;/*
;**    }
;**
;**    ;/******************************************************************/
;**    ;/* If not found then look for closest                             */
;**    ;/******************************************************************/
;**    if (MinDiff > 0)
;*/

        cmp     MinDiff,0
        je      endif_2

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

        mov     ecx,0
top_loop2:
        cmp     ecx,ulDeviceDefaultPaletteSize
        jae     exit_loop2

;/*
;**        {
;**            ;/**********************************************************/
;**            ;/* Get difference between our colour and the colour at    */
;**            ;/* this index                                             */
;**            ;/**********************************************************/
;**            Diff = rgb2_diff(RGBColor, DeviceDefaultPalette[i]);
;*/

        INVOKE  rgb2_diff,
                RGBColor,
                RGB2 PTR [ebx+ecx*4]

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

        cmp     eax,MinDiff
        jae     endif_3

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

        mov     MinDiff,eax

;/*
;**                ClosestIndex = i;
;*/

        mov     ClosestIndex,ecx
endif_3:

;/*
;**            }
;*/

        inc     ecx
        jmp     top_loop2
exit_loop2:

;/*
;**        }
;**        ;/**************************************************************/
;**        ;/* we need the actual RGB value of the nearest color          */
;**        ;/**************************************************************/
;**        ClosestRGB = DeviceDefaultPalette[ClosestIndex];
;*/

        mov     ecx,ClosestIndex
        mov     eax,[ebx+ecx*4]
        mov     ClosestRGB,eax

endif_2:

;/*
;**    }   ;/* end of perfect match not found                             */
;**
;**    ;/******************************************************************/
;**    ;/* Return the RGB value without any option bits.                  */
;**    ;/******************************************************************/
;**    ClosestRGB.fcOptions = 0;
;*/

        mov     ClosestRGB.rgb2_fcOptions,0

;/*
;**    return( ClosestRGB );
;*/

        mov     eax,ClosestRGB
ndpc_exit:
        ASSUME  ebx:NOTHING
        ret
NearestDefaultPhysicalColor ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = InnerNearestDefaultPhysicalIndex
;*
;* DESCRIPTION   = InnerNearestDefaultPhysicalIndex finds the index of the
;*                 entry in the supplied default physical palette which is the
;*                 closest match to the supplied RGB value.
;*
;*
;* INPUT         = RGBColor :RGB2,
;*                 DeviceDefaultPalette  :DWORD,
;*                 ulDeviceDefaultPaletteSize  :ULONG
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

InnerNearestDefaultPhysicalIndex PROC SYSCALL USES EBX,
        RGBColor                       :RGB2,
        DeviceDefaultPalette            :DWORD,
        ulDeviceDefaultPaletteSize      :ULONG

;/*
;** Local variables
;*/

LOCAL   Diff            :ULONG,          ;/* difference of current entry */
        MinDiff         :ULONG,          ;/* Minimum Difference to date  */
        i               :ULONG,          ;/* loop variable               */
        PhyIndex        :ULONG

;/*
;**    if (DDT.BitCount == 16)
;**    {
;**        ;/**************************************************************/
;**        ;/* 16bpp requires massaging to get from the RGB to the index  */
;**        ;/**************************************************************/
;**        return(RGB16FromPRGB2(&RGBColor));
;**    }
;**
;**    ;/******************************************************************/
;**    ;/* Note: the VGA uses a cunning algorithm for calculating the     */
;**    ;/* nearest color. Ideally we want to improve our code here in     */
;**    ;/* a similar way.                                                 */
;**    ;/*                                                                */
;**    ;/* Several cunning algorithms coming up ...                       */
;**    ;/*                                                                */
;**    ;/* The routines NearestDefaultPaletteIndex256                     */
;**    ;/*              NearestDefaultPaletteIndex128                     */
;**    ;/*              NearestDefaultPaletteIndex64                      */
;**    ;/*                                                                */
;**    ;/* have been created to return the slot number corresponding to   */
;**    ;/* the nearest default palette entry for the 256, 128 and 64      */
;**    ;/* entry palettes.                                                */
;**    ;/*                                                                */
;**    ;/* The other palettes need to have there entries searched for     */
;**    ;/* the nearest value.                                             */
;**    ;/******************************************************************/
;**    if (DDT.BitCount == 8)
;**    {
;**        switch (ulDeviceDefaultPaletteSize)
;**        {
;*/

        mov     eax,ulDeviceDefaultPaletteSize
        cmp     eax,256
        jne     case_128
case_256:

;/*
;**            case 256:
;**                ;/******************************************************/
;**                ;/* Calcultae the slot number of the nearest entry     */
;**                ;/******************************************************/
;**                PhyIndex = NearestDefaultPaletteIndex256(&RGBColor);
;**                return( PhyIndex );
;*/


                INVOKE  NearestDefaultPaletteIndex256,
                        ADDR    RGBColor
                jmp     indpi_exit

case_128:
        cmp     eax,128
        jne     case_64

;/*
;**            case 128:
;**                ;/******************************************************/
;**                ;/* Calculate the slot number of the nearest entry.    */
;**                ;/******************************************************/
;**                PhyIndex = NearestDefaultPaletteIndex128(&RGBColor);
;*/

                INVOKE  NearestDefaultPaletteIndex128,
                        ADDR    RGBColor

;/*
;**
;**                ;/******************************************************/
;**                ;/* Adjust for the 128 slots that belong to palette    */
;**                ;/* manager apps.                                      */
;**                ;/******************************************************/
;**                if (PhyIndex > 63)
;*/

                cmp     eax,63
                jbe     indpi_exit
                add     eax,128
                jmp     indpi_exit

;/*
;**                {
;**                    return(PhyIndex + 128);
;**                }
;**                else
;**                {
;**                    return(PhyIndex);
;**                }
;**
;*/

case_64:
        cmp     eax,64
        jne     case_default

;/*
;**            case  64:
;**                ;/******************************************************/
;**                ;/* Calculate the slot number of the nearest entry     */
;**                ;/******************************************************/
;**                PhyIndex = NearestDefaultPaletteIndex64(&RGBColor);
;*/

                INVOKE  NearestDefaultPaletteIndex64,
                        ADDR    RGBColor
;/*
;** Adjust for the 192 slots that belong to palette
;** manager apps.
;*/

                cmp     eax,31
                jbe     indpi_exit
                add     eax,192
                jmp     indpi_exit

;/*
;**                if (PhyIndex > 31)
;**                {
;**                    return(PhyIndex + 192);
;**                }
;**                else
;**                {
;**                    return(PhyIndex);
;**                }
;**                break;
;**        }
;*/

case_default:

;/*
;**    }
;**    ;/******************************************************************/
;**
;**    ;/******************************************************************/
;**    ;/* First check for exact match in the device default Palette      */
;**    ;/******************************************************************/
;**    MinDiff = 0xFFFFFFFF;
;*/

        mov     eax,0FFFFFFFFh
        mov     MinDiff,eax

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

        mov     ecx,0
        mov     ebx,DeviceDefaultPalette
        jmp     enter_loop1
top_loop1:

;/*
;**    {
;**        if ( (URGB(RGBColor) & RGB_MASK) ==
;**             (URGB(DeviceDefaultPalette[i]) & RGB_MASK))
;*/

                mov     eax,RGBColor
                and     eax,RGB_MASK
                mov     edx,DWORD PTR[ebx]
                and     edx,RGB_MASK
                cmp     eax,edx
                jne     @F

;/*
;**        {
;**            PhyIndex = i;
;**            MinDiff = 0;
;**            break;
;*/

                mov     PhyIndex,ecx
                mov     MinDiff,0
                jmp     end_loop1
@@:

;/*
;**        }
;*/

        add     ebx,sizeof RGB2
        inc     ecx
enter_loop1:
        cmp     ecx,ulDeviceDefaultPaletteSize
        jb      top_loop1
end_loop1:

;/*
;**    }
;**
;**    ;/******************************************************************/
;**    ;/* If not found then look for closest                             */
;**    ;/******************************************************************/
;**    if (MinDiff > 0)
;*/

        cmp     MinDiff,0
        jbe     end_if1

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

        mov     ecx,0
        mov     ebx,DeviceDefaultPalette
        jmp     enter_loop2
top_loop2:

;/*
;**        {
;**            ;/**********************************************************/
;**            ;/* Get difference between our colour and the colour at    */
;**            ;/* this index                                             */
;**            ;/**********************************************************/
;**            Diff = rgb2_diff(RGBColor, DeviceDefaultPalette[i]);
;**
;*/

                INVOKE  rgb2_diff,
                        RGBColor,
                        RGB2 PTR [ebx]

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

                cmp     eax,MinDiff
                jae     @F

;/*
;**            {
;**                MinDiff = Diff;
;**                PhyIndex = i;
;*/

                mov     MinDiff,eax
                mov     PhyIndex,ecx
@@:

;/*
;**            }
;*/

        add     ebx,sizeof RGB2
        inc     ecx
enter_loop2:
        cmp     ecx,ulDeviceDefaultPaletteSize
        jb      top_loop2
end_loop2:

;/*
;**        }
;*/

end_if1:

;/*
;**    }   ;/* end of perfect match not found                             */
;**
;**    ;/******************************************************************/
;**    ;/* Make any adjustment necessary to take into account that at 8   */
;**    ;/* bits per pel the default palette may be split into two halves. */
;**    ;/******************************************************************/
;**    if (   (DDT.BitCount == 8)
;**        && (PhyIndex >= (ulDeviceDefaultPaletteSize / 2)) )
;*/

        mov     eax,PhyIndex
        mov     ecx,ulDeviceDefaultPaletteSize
        mov     edx,ecx
        shr     ecx,1

        cmp     eax,ecx
        jb      @F

;/*
;**    {
;**        PhyIndex =  PhyIndex + (256 - ulDeviceDefaultPaletteSize);
;*/

        add     eax,256
        sub     eax,edx
@@:

;/*
;**    }
;**
;**    ;/******************************************************************/
;**    ;/* Return the PhyIndex                                            */
;**    ;/******************************************************************/
;**    return(PhyIndex);
;*/

indpi_exit:
        ret
InnerNearestDefaultPhysicalIndex ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = NearestDirectDefaultPhysicalIndex
;*
;* DESCRIPTION   = NearestDirectDefaultPhysicalIndex finds the index of the
;*                 entry in the current device default physical palette for
;*                 OD_DIRECT DCs which is the closest match to the supplied
;*                 RGB value.
;*
;*
;* INPUT         = RGBColor :RGB2
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

NearestDirectDefaultPhysicalIndex PROC SYSCALL,
        RGBColor        :RGB2

;/*
;**    if (DDT.BitCount == 16)
;**    {
;**        ;/**************************************************************/
;**        ;/* 16bpp requires massaging to get from the RGB to the index  */
;**        ;/**************************************************************/
;**        return(RGB16FromPRGB2(&RGBColor));
;**    }
;**
;**    ;/******************************************************************/
;**    ;/* Return the PhyIndex                                            */
;**    ;/******************************************************************/
;**    return(InnerNearestDefaultPhysicalIndex(RGBColor,
;**                                            DirectDeviceDefaultPalette,
;**                                            ulDirectDeviceDefaultPaletteSize));
;*/

        INVOKE  InnerNearestDefaultPhysicalIndex,
                RGBColor,
                DirectDeviceDefaultPalette,
                ulDirectDeviceDefaultPaletteSize
        ret
NearestDirectDefaultPhysicalIndex ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = NearestMemoryDefaultPhysicalIndex
;*
;* DESCRIPTION   = NearestMemoryDefaultPhysicalIndex finds the index of the
;*                 entry in the current device default physical palette for
;*                 OD_MEMORY DCs which is the closest match to the supplied
;*                 RGB value.
;*
;*
;* INPUT         = RGBColor  :RGB2
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

NearestMemoryDefaultPhysicalIndex PROC SYSCALL,
        RGBColor        :RGB2

;/*
;**    if (DDT.BitCount == 16)
;**    {
;**        ;/**************************************************************/
;**        ;/* 16bpp requires massaging to get from the RGB to the index  */
;**        ;/**************************************************************/
;**        return(RGB16FromPRGB2(&RGBColor));
;**    }
;**
;**    ;/******************************************************************/
;**    ;/* Return the PhyIndex                                            */
;**    ;/******************************************************************/
;**    return(InnerNearestDefaultPhysicalIndex(RGBColor,
;**                                            MemoryDeviceDefaultPalette,
;**                                            (ULONG)SizeOfHWPalette));
;**
;*/

        INVOKE  InnerNearestDefaultPhysicalIndex,
                RGBColor,
                MemoryDeviceDefaultPalette,
                SizeOfHWPalette
        ret
NearestMemoryDefaultPhysicalIndex ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = NearestDefaultPhysicalIndex
;*
;* DESCRIPTION   = NearestDefaultPhysicalIndex finds the index of the entry
;*                 in the default physical palette which is the closest
;*                 match to the supplied RGB value.
;*
;* INPUT         = pddc     :PDDC
;*                 RGBColor :RGB2
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

NearestDefaultPhysicalIndex PROC SYSCALL,
        pddc            :PDDC,
        RGBColor        :RGB2

        mov     eax,pddc


;/*
;**    ;/******************************************************************/
;**    ;/* With palette manager the device default palette for the screen */
;**    ;/* (OD_DIRECT DCs) will change size as HW slots are allocated to  */
;**    ;/* palette manager palettes.  The device default palette for      */
;**    ;/* OD_MEMORY DCs will always be the full size 256 entry palette   */
;**    ;/* at 8 bits per pel.  At 4 bits per pel the device default       */
;**    ;/* palette will always be the 16 entry reduced size device        */
;**    ;/* default palette for both cases. We must call off to two        */
;**    ;/* different routines which will pass the correct device default  */
;**    ;/* palette on to the low level InnerNearestDefaultPysicalIndex    */
;**    ;/* function.                                                      */
;**    ;/******************************************************************/
;**    if (pdc->DCIDCType == OD_DIRECT)
;*/

        test    [eax].DDC.ddc_fb,DDC_DEVICE
        jz      else_1

;/*
;**    {
;*/


ifdef FIREWALLS

;/*
;**        ;/**************************************************************/
;**        ;/* This is a good place to check that the DCs device default  */
;**        ;/* palette pointer is set correctly.                          */
;**        ;/**************************************************************/
;**        if (  (pdc->DCIDeviceDefaultPalette != DirectDeviceDefaultPalette)
;**           && (pdc->DCIColFormat != LCOLF_PALETTE) )
;*/

        mov     edx,DirectDeviceDefaultPalette
        cmp     [eax].DDC.ddc_pDefPal,edx
        je      @F
        test    [eax].DDC.ddc_fbClrTbl,DDC_PALETTE
        jnz     @F

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

        DebugMsg2       <NearestDefaultPhysicalIndex: ddc_pDefPal <> DirectDeviceDefaultPalette>
        int 3
        mov     [eax].DDC.ddc_pDefPal,edx
@@:

;/*
;**        }
;*/

endif ;/* FIREWALLS */

;/*
;**        return( NearestDirectDefaultPhysicalIndex(RGBColor) );
;*/

        INVOKE  NearestDirectDefaultPhysicalIndex,
                RGBColor

        jmp     ndpi_exit

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

else_1:

;/*
;**    {
;*/

ifdef FIREWALLS

;/*
;**        ;/**************************************************************/
;**        ;/* This is a good place to check that the DCs device default  */
;**        ;/* palette pointer is set correctly.                          */
;**        ;/**************************************************************/
;**        if (  (pdc->DCIDeviceDefaultPalette != MemoryDeviceDefaultPalette)
;**           && (pdc->DCIColFormat != LCOLF_PALETTE) )
;*/

        mov     edx,MemoryDeviceDefaultPalette
        cmp     [eax].DDC.ddc_pDefPal,edx
        je      @F
        test    [eax].DDC.ddc_fbClrTbl,DDC_PALETTE
        jnz     @F

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

        DebugMsg2       <NearestDefaultPhysicalIndex: ddc_pDefPal <> MemoryDeviceDefaultPalette>
        int 3
        mov     [eax].DDC.ddc_pDefPal,edx
@@:

;/*
;**        }
;*/

endif ;/* FIREWALLS */

;/*
;**        return( NearestMemoryDefaultPhysicalIndex(RGBColor) );
;*/

        INVOKE  NearestMemoryDefaultPhysicalIndex,
                RGBColor
        errn$   ndpi_exit
endif_1:

;/*
;**    }
;*/

ndpi_exit:
        ret
NearestDefaultPhysicalIndex ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = NearestRealizableIndex
;*
;* DESCRIPTION   = NearestRealizableIndex finds the index that gives the
;*                 nearest RGB (to the requested one) in the palette that
;*                 results from realizing the logical color table.
;*
;* INPUT         = pddc            :PDDC,
;*                 RGBColor        :RGB2
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

NearestRealizableIndex PROC SYSCALL USES EBX ESI,
        pddc            :PDDC,
        RGBColor        :RGB2

;/*
;** Local variables
;*/

LOCAL   Diff            :ULONG,  ;/* difference of current entry */
        MinDiff         :ULONG,  ;/* Minimum Difference to date  */
        i               :ULONG,  ;/* loop variable               */
        RealIndex       :ULONG,
        TestRGB         :RGB2

        mov     esi,pddc
        ddc?    esi

        ASSUME  esi:PDDC

        mov     ebx,[esi].ddc_pClrTbl

        ASSUME  EBX:PCOLORTABLE

;/*
;**    ;/******************************************************************/
;**    ;/* First check for exact match in the realizable palette          */
;**    ;/******************************************************************/
;**    MinDiff = 0xFFFFFFFF;
;*/

        mov     MinDiff,0FFFFFFFFh

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

        mov     ecx,0
top_for1:
        cmp     ecx,[esi].ddc_ctMax
        ja      exit_for1

;/*
;**    {
;**        if ( pdc->DCIColorTable[i].PhyIndex != CLR_NOPHYINDEX )
;*/

        .ERRNZ  COLORTABLETYPE-8
        cmp     [ebx+ecx*8].PhyIndex,CLR_NOPHYINDEX
        mov     eax,[ebx+ecx*8].LogRGB
        jne     endif_1

;/*
;**        {
;**            ;/**********************************************************/
;**            ;/* Index is valid, get it from the color table.           */
;**            ;/**********************************************************/
;**            TestRGB = pdc->DCIColorTable[i].LogRGB;
;**        }
;**        else
;*/

else_1:

;/*
;**        {
;**            ;/**********************************************************/
;**            ;/* This is a gap in the color table, get the entry from   */
;**            ;/* the device default palette.                            */
;**            ;/**********************************************************/
;**            TestRGB = MemoryDeviceDefaultPalette[i];
;*/

;PRK        mov     eax,MemoryDeviceDefaultPalette[ecx*4]
        mov     eax,MemoryDeviceDefaultPalette  ;PRK
        mov     eax,[eax+ecx*4]                 ;PRK
endif_1:

;/*
;**        }
;**
;**        ;/**************************************************************/
;**        ;/* Now see if we match the test RGB exactly.                  */
;**        ;/**************************************************************/
;**        if (TestRGB.bBlue  == RGBColor.bBlue  &&
;**            TestRGB.bGreen == RGBColor.bGreen &&
;**            TestRGB.bRed   == RGBColor.bRed)
;*/

        and     eax,RGB_MASK
        mov     edx,RGBColor
        and     edx,RGB_MASK
        cmp     eax,edx
        jne     not_same

;/*
;**        {
;**            RealIndex = i;
;*/

        mov     RealIndex,ecx

;/*
;**            MinDiff = 0;
;*/

        mov     MinDiff,0

;/*
;**            break;
;*/

        jmp     exit_for1
not_same:

;/*
;**        }
;*/

        inc     ecx
        jmp     top_for1
exit_for1:

;/*
;**    }
;**
;**    ;/******************************************************************/
;**    ;/* If an exact match not found then look for closest.             */
;**    ;/******************************************************************/
;**    if (MinDiff)
;*/

        cmp     MinDiff,0
        je      endif_2

;/*
;**    {
;**        for (i = 0; i <= pdc->DCIHighIndex; i++)
;*/

        mov     ecx,0
top_for2:
        cmp     ecx,[esi].ddc_ctMax
        ja      exit_for2

;/*
;**        {
;**            if ( pdc->DCIColorTable[i].PhyIndex != CLR_NOPHYINDEX )
;*/

        cmp     [ebx+ecx*8].PhyIndex,CLR_NOPHYINDEX
        mov     eax,[ebx+ecx*8].LogRGB
        jne     endif_3

;/*
;**            {
;**                ;/******************************************************/
;**                ;/* Index is valid, get it from the color table.       */
;**                ;/******************************************************/
;**                TestRGB = pdc->DCIColorTable[i].LogRGB;
;**            }
;**            else
;**            {
;**                ;/******************************************************/
;**                ;/* This is a gap in the color table, get the entry    */
;**                ;/* from the device default palette.                   */
;**                ;/******************************************************/
;**                TestRGB = MemoryDeviceDefaultPalette[i];
;*/

;PRK        mov     eax,MemoryDeviceDefaultPalette[ecx*4]
        mov     eax,MemoryDeviceDefaultPalette  ;PRK
        mov     eax,[eax+ecx*4]                 ;PRK
endif_3:

;/*
;**            }
;**            ;/******************************************************/
;**            ;/* This is a valid entry in the LCT so use its        */
;**            ;/* logical RGB value.                                 */
;**            ;/******************************************************/
;**            Diff = rgb2_diff(RGBColor, TestRGB);
;*/

        mov     TestRGB,eax

        INVOKE  rgb2_diff,
                RGBColor,
                TestRGB

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

        cmp     eax,MinDiff
        jae     not_closer

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

        mov     MinDiff,eax

;/*
;**                RealIndex = i;
;*/

        mov     RealIndex,ecx
not_closer:

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

        inc     ecx
        jmp     top_for2
exit_for2:
endif_2:

;/*
;**    }   ;/* end of perfect match not found                             */
;**
;**    ;/******************************************************************/
;**    ;/* Return the value from the realizable palette                   */
;**    ;/******************************************************************/
;**    return(RealIndex);
;*/

        mov     eax,RealIndex
        ret
NearestRealizableIndex ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = NearestLogicalColor
;*
;* DESCRIPTION   = NearestLogicalColor returns the index into the logical
;*                 color table which will generate the nearest color to
;*                 RGBColor.
;*
;*                 This is called by QueryColorIndex
;*
;* INPUT         = pddc     :PDDC,
;*                 Options  :ULONG,
;*                  Options can specify:
;*                  LCOLOPT_REALIZED - the RGB values to be used are those
;*                                    available after the LCT has been realized.
;*
;*                 RGBColor :RGB2
;*
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

NearestLogicalColor PROC SYSCALL USES EBX ESI,
        pddc            :PDDC,
        Options         :ULONG,
        RGBColor        :RGB2


;/*
;** Local variables.
;*/

LOCAL   i               :ULONG,         ;/* loop variable               */
        RGBVal          :RGB2,          ;/* Stores current color        */
        Diff            :ULONG,         ;/* Stores color difference     */
        MinDiff         :ULONG,         ;/* Stores minimum difference   */
        BestIndex       :ULONG          ;/* The best index found        */

        mov     esi,pddc
        ddc?    esi

        ASSUME  esi:PDDC

        mov     ebx,[esi].ddc_pClrTbl

        ASSUME  EBX:PCOLORTABLE

;/*
;**    ;/******************************************************************/
;**    ;/* Initialise MinDiff to be a jolly big number, bigger than any   */
;**    ;/* other MinDiff in the whole wide world                          */
;**    ;/******************************************************************/
;**    MinDiff = 0xFFFFFFFF;
;*/

        mov     MinDiff,0FFFFFFFFh

;/*
;**    ;/******************************************************************/
;**    ;/* Pass through all entries in logical color table                */
;**    ;/******************************************************************/
;**    for (i = pdc->DCILowIndex;
;**         i <= pdc->DCIHighIndex;
;**         i++)
;*/

        mov     ecx,[esi].ddc_ctMin
top_loop:
        cmp     ecx,[esi].ddc_ctMax
        ja      exit_loop

;/*
;**    {
;**        if ( pdc->DCIColorTable[i].PhyIndex != CLR_NOPHYINDEX )
;*/

        cmp     [ebx+ecx*8].PhyIndex,CLR_NOPHYINDEX
        je      endif_1

;/*
;**        {
;**            ;/**********************************************************/
;**            ;/* LCT entry is valid                                     */
;**            ;/**********************************************************/
;**            if (fRealizeSupported &&
;**                (Options & LCOLOPT_REALIZED))
;*/

        test    Options,LCOLOPT_REALIZED
        jz      not_realized

;/*
;**            {
;**                ;/******************************************************/
;**                ;/* Need to get the RGB value when color table is      */
;**                ;/* realized.                                          */
;**                ;/* Take the RGB value from the LCT.                   */
;**                ;/******************************************************/
;**                RGBVal = pdc->DCIColorTable[i].LogRGB;
;*/

        mov     eax,[ebx+ecx*8].LogRGB
        jmp     endif_2
not_realized:

;/*
;**            }
;**            else
;**            {
;**                ;/******************************************************/
;**                ;/* Calculate the RGB value when the table is not      */
;**                ;/* realized.                                          */
;**                ;/******************************************************/
;**                ;/******************************************************/
;**                ;/* Take the RGB value from the default palette, using */
;**                ;/* the index defined in the LCT.                      */
;**                ;/******************************************************/
;**                ;/******************************************************/
;**                ;/* we have to make a call here                        */
;**                ;/* we cant just pick up the value from the HWPalette  */
;**                ;/* because we may be in the background so some other  */
;**                ;/* app in the foreground may have dumped on top of    */
;**                ;/* the default palette entries                        */
;**                ;/******************************************************/
;**                RGBVal = NearestDefaultPhysicalColor(
;**                                          pdc->DCIColorTable[i].LogRGB);
;*/

                INVOKE  NearestDefaultPhysicalColor,
                        esi,
                        [ebx+ecx*8].LogRGB
endif_2:

;/*
;**            }
;**            ;/**********************************************************/
;**            ;/* Calculate the difference between the two RGB values    */
;**            ;/**********************************************************/
;**            Diff = rgb2_diff(RGBColor,RGBVal);
;*/

        mov     RGBVal,eax

        INVOKE  rgb2_diff,
                RGBColor,
                RGBVal

;/*
;**            if (Diff == 0)
;*/

        cmp     eax,0
        jne     endif_3

;/*
;**            {
;**                ;/******************************************************/
;**                ;/* Exact match has been found - set BestIndex and     */
;**                ;/* exit loop.                                         */
;**                ;/******************************************************/
;**                BestIndex = i;
;*/

        mov     BestIndex,ecx

;/*
;**               break;
;*/

        jmp     exit_loop
endif_3:

;/*
;**            }
;**            if (Diff < MinDiff)
;*/

        cmp     eax,MinDiff
        jae     endif_4

;/*
;**            {
;**                ;/******************************************************/
;**                ;/* This RGB value is the nearest to the desired RGB   */
;**                ;/* value so far. Store the difference and current     */
;**                ;/* index.                                             */
;**                ;/******************************************************/
;**                MinDiff = Diff;
;*/

        mov     MinDiff,eax

;/*
;**                BestIndex = i;
;*/

        mov     BestIndex,ecx
endif_4:

;/*
;**            }
;*/

endif_1:

;/*
;**        }
;*/

        inc     ecx
        jmp     top_loop
exit_loop:

;/*
;**    }
;**    ;/******************************************************************/
;**    ;/* Return the BestIndex                                           */
;**    ;/******************************************************************/
;**    return(BestIndex);
;*/

        mov     eax,BestIndex
        ret

NearestLogicalColor ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = SearchRealizedLCTPalette
;*
;* DESCRIPTION   = SearchRealizedLCTPalette finds the physical index having
;*                 the nearest RGB value to the given RGB, by searching the
;*                 table of values resulting from a LogicalColorTable which
;*                 has currently been realized.
;*                 We try and avoid doing a search if at all possible.
;*
;* INPUT         = RGBColor        :RGB2
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

SearchRealizedLCTPalette PROC SYSCALL,
        RGBColor        :RGB2


;/*
;** Local variables.
;*/


LOCAL   ulRGB   :ULONG

;/*
;**    ;/******************************************************************/
;**    ;/* Get the RGB value as a ULONG which makes for easier            */
;**    ;/* comparisons. Keep only the color components.                   */
;**    ;/******************************************************************/
;**    ulRGB = URGB(RGBColor) & 0x00ffffff;
;*/

        mov     eax,RGBColor
        and     eax,00ffffffh

;/*
;**    if (ulRGB == 0x00ffffff)
;*/

        cmp     eax,00ffffffh
        jne     else_1

;/*
;**    {
;**        return(RealizedWhiteIndex);
;*/

        mov     eax,RealizedWhiteIndex
        jmp     search_exit

;/*
;**    }
;**    else if (ulRGB == 0x00000000)
;*/

else_1:
        cmp     eax,0
        jne     else_2                          ;          

;/*
;**    {
;**        return(RealizedBlackIndex);
;*/

        mov     eax,RealizedBlackIndex
        jmp     search_exit

;/*
;**    }
;**    else if (ulRGB != ulLastSearched)
;*/

else_2:
        cmp     eax,ulLastSearched
        je      end_elses

;/*
;**    {
;**        ulIndexLastSearched = InnerSearchRealizedLCTPalette(RGBColor);
;*/

        mov     ulLastSearched,eax

        INVOKE  InnerSearchRealizedLCTPalette,
                RGBColor

;/*
;**        ulLastSearched = ulRGB;
;*/

        mov     ulIndexLastSearched,eax
end_elses:

;/*
;**    }
;**
;**    return(ulIndexLastSearched);
;*/

        mov     eax,ulIndexLastSearched
search_exit:


        ret
SearchRealizedLCTPalette ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = InnerSearchRealizedLCTPalette
;*
;* DESCRIPTION   = InnerSearchRealizedLCTPalette is used to actually do the
;*                 search (it does not do any caching of last searched
;*                 values).
;*
;*
;*
;* INPUT         = RGBColor :RGB2
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

InnerSearchRealizedLCTPalette PROC SYSCALL USES EBX ESI EDI,
        RGBColor        :RGB2


;/*
;**    ;/******************************************************************/
;**    ;/* First check for exact match in the realized LCT.               */
;**    ;/******************************************************************/
;**    for (i = 0; i < SizeOfHWPalette; i++)
;*/

        mov     esi,SizeOfHWPalette

        mov     eax,0
        lea     edx,RealizedLCTPalette
        jmp     enter_for1
top_for1:

;/*
;**    {
;**        ;/**************************************************************/
;**        ;/* Check for exact matches.                                   */
;**        ;/**************************************************************/
;**        if (RealizedLCTPalette[i].bBlue  == RGBColor.bBlue  &&
;**            RealizedLCTPalette[i].bGreen == RGBColor.bGreen &&
;**            RealizedLCTPalette[i].bRed   == RGBColor.bRed)
;**        {
;*/

                mov     ecx,DWORD PTR [edx]
                and     ecx,RGB_MASK
                mov     ebx,RGBColor
                and     ebx,RGB_MASK
                cmp     ecx,ebx
                je      isr_exit

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

        add     edx,sizeof RGB2
        inc     eax
enter_for1:
        cmp     eax,esi
        jb      top_for1
end_for1:

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

        mov     ebx,0FFFFFFFFh

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

        mov     ecx,0
        lea     edx,RealizedLCTPalette
        jmp     enter_for2
top_for2:

;/*
;**    {
;**        ;/**************************************************************/
;**        ;/* find the distance between this palette entry and the       */
;**        ;/* required color                                             */
;**        ;/**************************************************************/
;**        Diff = rgb2_diff(RGBColor,RealizedLCTPalette[i]);
;*/

        INVOKE  rgb2_diff,
                RGBColor,
                RGB2 PTR [edx]

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

        cmp     eax,ebx
        jae     @F

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

                mov     ebx,eax

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

                mov     edi,ecx
@@:

;/*
;**        }
;*/

        add     edx,sizeof RGB2
        inc     ecx
enter_for2:
        cmp     ecx,esi
        jb      top_for2
end_for2:
        mov     eax,edi

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

isr_exit:
        ret

InnerSearchRealizedLCTPalette ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = PhyToLogIndex
;*
;* DESCRIPTION   = PhyToLogIndex takes a physical index and returns the
;*                 (first) logical index in the current LogicalColorTable or
;*                 palette which will produce that physical index.  If no
;*                 logical index produces the physical index then the value
;*                 CLR_NOINDEX is returned.
;*
;* INPUT         = pddc            :PDDC,
;*                 ulPhyIndex      :ULONG
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

PhyToLogIndex PROC SYSCALL USES EBX ESI,
        pddc            :PDDC,
        ulPhyIndex      :ULONG

LOCAL   i       :ULONG

        mov     esi,pddc
        ddc?    esi

        ASSUME  esi:PDDC
        mov     eax,ulPhyIndex
        mov     ebx,[esi].ddc_npdevpal

        ASSUME  EBX:PDEVPAL

;/*
;**    if (pdc->DCIColFormat == LCOLF_PALETTE)
;*/

        test    [esi].ddc_fbClrTbl,DDC_PALETTE
        jz      else_1

;/*
;**    {
;**        ;/**************************************************************/
;**        ;/* For direct (screen) DCs we must search through the palette */
;**        ;/* looking for an entry is mapped to the HW palette slot      */
;**        ;/* (given by the physical index).                             */
;**        ;/**************************************************************/
;**        if (pdc->DCIDCType == OD_DIRECT)
;*/

        test    [esi].ddc_fb,DDC_DEVICE
        jz      not_device

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

        mov     ecx,0
top_loop1:
        cmp     ecx,[ebx].usCountStored
        jae     endif_1         ;exit loop

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

        cmp     [ebx].entries[ecx*8].bCurrent,al
        jne     no_ret

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

        mov     eax,ecx
        jmp     ptli_Exit
no_ret:

;/*
;**                }
;*/

        inc     ecx
        jmp     top_loop1

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

not_device:

;/*
;**        {
;**            ;/**********************************************************/
;**            ;/* For memory DCs we always use a one to one mapping so   */
;**            ;/* if the index we have is in the correct range then we   */
;**            ;/* can just return it.                                    */
;**            ;/**********************************************************/
;**            if (ulPhyIndex < pdc->Palette->usCountStored)
;*/

        assert  eax,E,ulPhyIndex
        cmp     eax,[ebx].usCountStored
        jae     endif_1

;/*
;**            {
;**                return(ulPhyIndex);
;*/

        mov     eax,ulPhyIndex
        jmp     ptli_Exit

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

else_1:

;/*
;**    {
;**        ;/**************************************************************/
;**        ;/* Search through the logical color table to find the entry   */
;**        ;/* which maps to the physical index.                          */
;**        ;/**************************************************************/
;*/

        assert  eax,E,ulPhyIndex

        mov     ebx,[esi].ddc_pClrTbl

        ASSUME  EBX:PCOLORTABLE

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

        mov     ecx,0
top_loop2:
        cmp     ecx,[esi].ddc_ctSize
        jae     exit_loop2

;/*
;**        {
;**            if (pdc->DCIColorTable[i].PhyIndex == ulPhyIndex)
;*/

        .ERRNZ  sizeof COLORTABLETYPE-8
        cmp     [ebx+ecx*8].PhyIndex,eax
        jne     endif_2

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

        mov     eax,ecx
        jmp     ptli_Exit
endif_2:

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

        inc     ecx
        jmp     top_loop2
exit_loop2:
endif_1:

;/*
;**    }
;**
;**    return(CLR_NOINDEX);
;*/

        mov     eax,CLR_NOINDEX
ptli_Exit:
        ret
PhyToLogIndex ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = ExactDefaultPhysicalIndex
;*
;* DESCRIPTION   = ExactDefaultPhysicalIndex searches the current default
;*                 physical palette and returns the index of the RGB entry
;*                 which matches the supplied RGB exactly.  If the exact
;*                 match does not exist then it returns PAL_ERROR (-1).
;*                 This routine is only designed to be called at 4 and 8
;*                 bits per pel.
;*
;* INPUT         = pddc     :PDDC,
;*                 RGBColor :ULONG
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ExactDefaultPhysicalIndex PROC SYSCALL USES ESI EBX,
        pddc            :PDDC,
        RGBColor        :ULONG


;/*
;** Local variables
;*/

LOCAL   i                       :ULONG, ;/* loop variable               */
        PhyIndex                        :ULONG,
        DeviceDefaultPalette            :PTR RGB2,
        ulDeviceDefaultPaletteSize      :ULONG


        mov     esi,pddc
        ddc?    esi

        ASSUME  esi:PDDC
        ASSUME  ebx:NOTHING
ifdef FIREWALLS

;/*
;**    if (   (pdc->DCISelListEntry->Info.BitCount != 4)
;**        && (pdc->DCISelListEntry->Info.BitCount != 8))
;*/

        mov     ebx,[esi].ddc_npsd
        test    [ebx].SURFACE.sd_fb,SD_COLOR
        jnz     no_halt

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

        int 3
no_halt:

;/*
;**    }
;*/

endif ;/* FIREWALLS */

;/*
;**    ;/******************************************************************/
;**    ;/* With palette manager the device default palette for the screen */
;**    ;/* (OD_DIRECT DCs) will change size as HW slots are allocated to  */
;**    ;/* palette manager palettes.  The device default palette for      */
;**    ;/* OD_MEMORY DCs will always be the full size 256 entry palette   */
;**    ;/* at 8 bits per pel.  At 4 bits per pel the device default       */
;**    ;/* palette will always be the 16 entry reduced size device        */
;**    ;/* default palette for both cases.                                */
;**    ;/******************************************************************/
;**    if (pdc->DCIDCType == OD_DIRECT)
;*/

        test    [esi].ddc_fb,DDC_DEVICE
        jz      else_1

;/*
;**    {
;**        DeviceDefaultPalette = DirectDeviceDefaultPalette;
;*/

        mov     eax,DirectDeviceDefaultPalette
        mov     DeviceDefaultPalette,eax

;/*
;**        ulDeviceDefaultPaletteSize = ulDirectDeviceDefaultPaletteSize;
;*/

        mov     eax,ulDirectDeviceDefaultPaletteSize
        mov     ulDeviceDefaultPaletteSize,eax
        jmp     endif_1

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

else_1:

;/*
;**    {
;**        DeviceDefaultPalette = MemoryDeviceDefaultPalette;
;*/

        mov     eax,MemoryDeviceDefaultPalette
        mov     DeviceDefaultPalette,eax

;/*
;**        ulDeviceDefaultPaletteSize = SizeOfHWPalette;
;*/

        mov     eax,SizeOfHWPalette
        mov     ulDeviceDefaultPaletteSize,eax
endif_1:

;/*
;**    }
;**
;**    ;/******************************************************************/
;**    ;/* Note: the VGA uses a cunning algorithm for calculating the     */
;**    ;/* nearest color. Ideally we want to improve our code here in     */
;**    ;/* a similar way.                                                 */
;**    ;/******************************************************************/
;**
;**    ;/******************************************************************/
;**    ;/* Search the palette for an exact match.                         */
;**    ;/******************************************************************/
;**    PhyIndex = PAL_ERROR;
;*/

        mov     PhyIndex,PAL_ERROR

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

        mov     ecx,0
top_loop:
        cmp     ecx,ulDeviceDefaultPaletteSize
        jae     exit_loop

;/*
;**    {
;**        if ( (URGB(RGBColor) & RGB_MASK) ==
;**             (URGB(DeviceDefaultPalette[i]) & RGB_MASK))
;*/

        mov     eax,RGBColor
        and     eax,RGB_MASK
;                 mov     edx,DeviceDefaultPalette[ecx*4]        
        mov     edx,DeviceDefaultPalette              ;          
        mov     edx,[edx+ecx*4]                       ;          
        and     edx,RGB_MASK
        cmp     eax,edx
        jne     no_match

;/*
;**        {
;**            PhyIndex = i;
;*/

        mov     PhyIndex,ecx
        jmp     exit_loop

;/*
;**            break;
;*/

no_match:

;/*
;**        }
;*/

        inc     ecx
        jmp     top_loop
exit_loop:

;/*
;**    }
;**
;**    ;/******************************************************************/
;**    ;/* Make any adjustment necessary to take into account that at 8   */
;**    ;/* bits per pel the default palette may be split into two halves. */
;**    ;/******************************************************************/
;**    if (   (PhyIndex != PAL_ERROR)
;**        && (DDT.BitCount == 8)
;**        && (PhyIndex >= (ulDeviceDefaultPaletteSize / 2)) )
;*/

        cmp     PhyIndex,PAL_ERROR
        je      no_adjust
        mov     eax,ulDeviceDefaultPaletteSize
        shr     eax,1
        cmp     PhyIndex,eax
        jb      no_adjust

;/*
;**    {
;**        PhyIndex =  PhyIndex + (256 - ulDeviceDefaultPaletteSize);
;*/

        mov     eax,256
        sub     eax,ulDeviceDefaultPaletteSize
        add     PhyIndex,eax

;/*
;**    }
;*/

no_adjust:

;/*
;**    ;/******************************************************************/
;**    ;/* Return the PhyIndex                                            */
;**    ;/******************************************************************/
;**    return(PhyIndex);
;*/

        mov     eax,PhyIndex
edpi_Exit:
        ret
ExactDefaultPhysicalIndex ENDP

        END
