;*DDK*************************************************************************/
;
; COPYRIGHT (C) Microsoft Corporation, 1989
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/
        page    ,132
;/*****************************************************************************
;*
;* SOURCE FILE NAME = PALMAP.ASM
;*
;* DESCRIPTIVE NAME = Performs palette mapping and maintains palette 
;*                    mapping cache.
;*
;*
;* VERSION      V2.0
;*
;* DATE         11/12/89
;*
;* DESCRIPTION  Performs palette mapping and maintains palette  
;*              mapping cache.                                  
;*
;* FUNCTIONS    MakePaletteMappingValid
;*              FarAllocPalSeg
;*              AllocPalSeg
;*              FarFreePalSeg
;*              FreePalSeg
;*              CreatePalSegFromRGBs
;*              NoMappingNeeded
;*              HackPalMapper
;*              NonDefBMToScr
;*              NonDefScrToBM
;*              NonDefPalMapper
;*              DstIsDefPalMapper
;*              SrcIsDefPalMapper
;*              HDBMDevPalMapper
;*              ComposePaletteMapping
;*              NDevNDefNDevNDef
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   11/12/89                     Author:  Bob Grudem [bobgru]
;*****************************************************************************/


        .286p
        .xlist
        include cmacros.inc
INCL_GPIBITMAPS         equ                      1
INCL_DDIBUNDLES         equ                      1
INCL_GPILOGCOLORTABLE   equ                      1
        include pmgre.inc
DINCL_BITMAP            equ                      1
        include driver.inc
        include assert.mac
        include njmp.mac
        include palette.inc
        .list

        errcode <INSUFFICIENT_MEMORY>

        externFP far_enter_driver_sem             ;enter.asm
        externFP far_leave_driver                 ;enter.asm
        externFP MatchTwoPalettes                 ;colormat.asm
        externFP get_selPalSeg                    ;palmem.asm
        externFP DosReallocSeg
        externFP WinAllocMem
        externFP WinFreeMem

sBegin  Data

        externD hLocalHeap                         ;data.asm
        externB devpalDefault                      ;palsup.asm
        externB palsegDefPal                       ;palsup.asm
        externD phwpal                             ;palsup.asm
        externB abDefPalMap_16_256                ;palsup.asm

;/*
;** Variables for maintaining the cached palette-mapping.
;*/

;/*
;** devpalXXX     Palettes involved in currently cached mapping
;*/

globalW devpalSrc,0
globalW devpalDst,0

;/*
;** Flags for palette-mapping cache (defined in palette.inc):
;**
;** MPMV_SRC_DEV            source is device
;** MPMV_SRC_DEF            source palette is default
;** MPMV_DST_DEV            destination is device
;** MPMV_DST_DEF            dest palette is default
;** MPMV_SRC_DST_IDENTICAL  source and dest palettes same
;** MPMV_INVALID            pal mapping cache is invalid
;*/

globalB fbPalMap,0

;/*
;** npPalMapVectCache The current cached mapping vector.
;** abPalMapVect      Pointer to the growable cached mapping vector.
;*/

        public  abPalMapVect
abPalMapVect            db                       SIZE_HW_PAL dup (0)

        public  npPalMapVectCache
npPalMapVectCache       dw                       DataOFFSET abPalMapVect

sEnd    Data

sBegin  FarCode
        assumes cs,FarCode
        externW FarCodeData

;/*
;**  anpfnPalMappers
;** 
;**   This table dispatches to the proper subroutines to handle
;**   constructing a palette mapping vector.  It is index by the
;**   MPMV_* flags (in palette.inc).
;** 
;**   Note: The device-device blts do not use palette mapping for now, so
;**         the four corresponding table entries are NoMappingNeeded.  If
;**         these cases support palette mapping in the future, uncomment
;**         the alternate entries.  The code to construct the mapping
;**         vectors works, but the code to use the mapping vector doesn't.
;**                                                   --bobgru (20 May 90)
;** 
;** MPMV_SRC_DEF            equ                      00000001b  ;source palette is default
;** MPMV_SRC_DEV            equ                      00000010b  ;source is device
;** MPMV_DST_DEF            equ                      00000100b  ;dest palette is default
;** MPMV_DST_DEV            equ                      00001000b  ;destination is device
;*/

mkPalMapper     macro   foo
        dw      FarCodeOFFSET foo
        endm

anpfnPalMappers label   word                       ;   +---Dst---+---Src---+
        mkPalMapper     NDevNDefNDevNDef         ;00 <NDev,NDef,NDev,NDef>
        mkPalMapper     SrcIsDefPalMapper        ;01 <NDev,NDef,NDev, Def>
        mkPalMapper     NonDefScrToBM             ;02 <NDev,NDef, Dev,NDef>
        mkPalMapper     NonDefPalMapper          ;03 <NDev,NDef, Dev, Def>
        mkPalMapper     DstIsDefPalMapper        ;04 <NDev, Def,NDev,NDef>
        mkPalMapper     NoMappingNeeded          ;05 <NDev, Def,NDev, Def>
        mkPalMapper     DstIsDefPalMapper        ;06 <NDev, Def, Dev,NDef>
        mkPalMapper     NoMappingNeeded          ;07 <NDev, Def, Dev, Def>
        mkPalMapper     NonDefBMToScr             ;08 < Dev,NDef,NDev,NDef>
        mkPalMapper     SrcIsDefPalMapper        ;09 < Dev,NDef,NDev, Def>
        mkPalMapper     NoMappingNeeded          ;0A < Dev,NDef, Dev,NDef>
        mkPalMapper     NoMappingNeeded          ;0B < Dev,NDef, Dev, Def>
        mkPalMapper     DstIsDefPalMapper        ;0C < Dev, Def,NDev,NDef>
        mkPalMapper     NoMappingNeeded          ;0D < Dev, Def,NDev, Def>
        mkPalMapper     NoMappingNeeded          ;0E < Dev, Def, Dev,NDef>
        mkPalMapper     NoMappingNeeded          ;0F < Dev, Def, Dev, Def>

;/*
;** These replace the corresponding entries above if dev->dev mapping
;** is turned on.
;**
;**       mkPalMapper     NonDefPalMapper          ;0A < Dev,NDef, Dev,NDef>
;**       mkPalMapper     NonDefPalMapper          ;0B < Dev,NDef, Dev, Def>
;**       mkPalMapper     DstIsDefPalMapper        ;0E < Dev, Def, Dev,NDef>
;*/

;/***************************************************************************
;*
;* FUNCTION NAME = MakePaletteMappingValid
;*
;* DESCRIPTION   = Make sure the palette mapping vector is valid.  If the cache 
;*                 is valid then just pass back the cached vector, otherwise    
;*                 recompute it.  The mapping vector may need to be resized.    
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,SI,DI,ES,DS,FLAGS
;*                 Registers Preserved:
;*                       BP
;*
;* INPUT         = DS = Data 
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = DX:AX --> palette mapping vector   
;*                        =  0 if no mapping required
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc MakePaletteMappingValid,<FAR,PUBLIC,NODATA>,<>
        parmW   npddcSrc
        parmW   npddcDst

        localW  devpalSrcNew
        localW  devpalDstNew
        localB  fbPalMapNew
cBegin

        xor     bx,bx                             ;initialize flags

;/*
;** src = (dev, non-dev)
;** src = (def, non-def)
;*/

        mov     si,npddcSrc
        cmp     [si].ddc_usId,DDC_IDENT ;if not ddc,
        .errnz  sd_usId - ddc_usId               ;   it's hbm w/default palette
        jne     mpmv_src_is_hbm
        test    [si].ddc_fb,DDC_DEVICE
        jz      mpmv_chk_src_pal
        or      bl,MPMV_SRC_DEV
mpmv_chk_src_pal:
        test    [si].ddc_fbBelow,DDC_PALETTE
        jnz     mpmv_chk_dst
        jmp     short mpmv_src_is_def
mpmv_src_is_hbm:
        or      bl,MPMV_SRC_HBM
mpmv_src_is_def:
        or      bl,MPMV_SRC_DEF

;/*
;** dst = (dev, non-dev)
;** dst = (def, non-def)
;*/

mpmv_chk_dst:
        mov     di,npddcDst
        test    [di].ddc_fb,DDC_DEVICE
        jz      mpmv_chk_dst_pal
        or      bl,MPMV_DST_DEV
mpmv_chk_dst_pal:
        test    [di].ddc_fbBelow,DDC_PALETTE
        jnz     mpmv_chk_ident_pals
        or      bl,MPMV_DST_DEF

;/*
;** src = dst
;*/

mpmv_chk_ident_pals:
        mov     ax,DataOFFSET devpalDefault
        test    bl,MPMV_SRC_HBM
        jnz     mpmv_have_src
        mov     ax,[si].ddc_npdevpal
mpmv_have_src:
        cmp     ax,[di].ddc_npdevpal
        jne     mpmv_have_flags
        or      bl,MPMV_SRC_DST_IDENTICAL
mpmv_have_flags:

;/*
;** Now that we have the cache flags, check for validity of the existing
;** cache.  The flags must be the same, and the new source and destination
;** devpals must be the same as those used for the cache.
;*/

        test    bl,MPMV_SRC_HBM
        jz      mpmv_not_bm_hack
        test    bl,MPMV_DST_DEF
        jz      mpmv_cache_invalid_bm_hack

mpmv_not_bm_hack:
        mov     cl,bl
        xor     cl,fbPalMap
        jnz     mpmv_cache_invalid

        cmp     ax,devpalSrc
        jne     mpmv_cache_invalid
        mov     ax,[di].ddc_npdevpal
        cmp     ax,devpalDst
        jne     mpmv_cache_invalid

        mov     ax,npPalMapVectCache
        mov     dx,ds
        jmp     short mpmv_exit

;/*
;** The cache was invalid, so we have to compute another mapping vector.
;** Save the new cache flags.  The flag MPMV_SRC_DST_IDENTICAL is not part
;** of the index into anpfnPalMappers, so clear it out before calling
;** through the table.  Save the pointer to the new cached mapping vector.
;**
;** If the new mapping vector is static, the mapper function will return
;** with the carry set.  In this case, don't update the cache.  Since
;** little work is involved in determining if the mapping vector is static,
;** we can afford to do it on every call if necessary, to save redoing the
;** time consuming matching that went into the last cached vector.
;*/

mpmv_cache_invalid_bm_hack:
        cCall   HackPalMapper,<npddcDst>
        jmp     short mpmv_exit

mpmv_cache_invalid:
        mov     ax,DataOFFSET devpalDefault
        test    bl,MPMV_SRC_HBM
        jnz     mpmv_have_src_again
        mov     ax,[si].ddc_npdevpal
mpmv_have_src_again:
        mov     devpalSrcNew,ax
        mov     ax,[di].ddc_npdevpal
        mov     devpalDstNew,ax
        mov     fbPalMapNew,bl

        mov     al,bl
NON_INDEX_BITS  equ MPMV_SRC_DST_IDENTICAL or MPMV_SRC_HBM
        and     bx,(not NON_INDEX_BITS) and 0FFh
        shl     bx,1
        cCall   anpfnPalMappers[bx],<npddcSrc,npddcDst> ;AL = fbPalMap
        jc      mpmv_exit

        mov     npPalMapVectCache,ax
        mov     bx,devpalSrcNew
        mov     devpalSrc,bx
        mov     bx,devpalDstNew
        mov     devpalDst,bx
        mov     bl,fbPalMapNew
        mov     fbPalMap,bl

mpmv_exit:
cEnd

;/***************************************************************************
;*
;* FUNCTION NAME = AllocPalSeg
;*
;* DESCRIPTION   = Allocate enough memory on the heap for a palseg of the given 
;*                 number of colors.
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,SI,DI,ES,DS,FLAGS
;*                 Registers Preserved:
;*                       BP
;*
;* INPUT         = DS = Data 
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = AX = near pointer to memory allocated 
;* RETURN-ERROR  = AX = 0
;*
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc FarAllocPalSeg,<FAR,PUBLIC,NODATA>,<>
        parmW   crgb
cBegin
        cCall   AllocPalSeg,<crgb>
cEnd

cProc AllocPalSeg,<NEAR,PUBLIC,NODATA>,<>
        parmW   crgb
cBegin
        call    far_enter_driver_sem
        mov     ax,crgb
        palOff  ax
        add     ax,SIZE PALSEG
        cCall   WinAllocMem,<hLocalHeap,ax>
        call    far_leave_driver
cEnd

;/***************************************************************************
;*
;* FUNCTION NAME = FreePalSeg
;*
;* DESCRIPTION   = Free up memory allocated for a palseg of the given number of
;*                 colors.                                                     
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,SI,DI,ES,DS,FLAGS
;*                 Registers Preserved:
;*                       BP
;*
;* INPUT         = DS = Data 
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = AX = near pointer to memory allocated 
;* RETURN-ERROR  = AX = 0
;*
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc FarFreePalSeg,<FAR,PUBLIC,NODATA>,<>
        parmW   np
        parmW   crgb
cBegin
        cCall   FreePalSeg,<np,crgb>
cEnd

cProc FreePalSeg,<NEAR,PUBLIC,NODATA>,<>
        parmW   np
        parmW   crgb
cBegin
        call    far_enter_driver_sem
        mov     cx,crgb
        palOff  cx
        add     cx,SIZE PALSEG
        cCall   WinFreeMem,<hLocalHeap,np,cx>
ifdef FIREWALLS
        or      ax,ax
        jz      @F
        rip     text,<Heap Manager returned an error while freeing an object>
@@:
endif
        call    far_leave_driver
cEnd

;/***************************************************************************
;*
;* FUNCTION NAME = CreatePalSegFromRGBs
;*
;* DESCRIPTION   = This function takes an array of RGBs of the given size and   
;*                 creates a PALSEG structure at the given address.             
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,SI,DI,ES,DS,FLAGS
;*                 Registers Preserved:
;*                       BP
;*
;* INPUT         = DS = selector to segment containing *nprgb      
;*                 ES = selector to segment containing *nppalseg   
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = AX = near pointer to memory allocated 
;* RETURN-ERROR  = AX = 0
;*
;**************************************************************************/

        CPUMode 386

        assumes ds,nothing
        assumes es,nothing

cProc CreatePalSegFromRGBs,<NEAR,PUBLIC,NODATA>,<si,di>
        parmW   npPalSeg
        parmW   crgb
        parmW   nprgb
        parmW   cbRGB                            ;size of RGB in source array
cBegin

        push    ebx
        mov     si,nprgb                         ;DS:SI --> rgb array
        mov     di,npPalSeg                      ;ES:DI --> palseg

        xor     ax,ax
        stosw
        .errnz  palseg_fs

        mov     ax,crgb
        dec     ax
        stosw
        .errnz  palseg_usMax - palseg_fs - 2
        inc     ax

        palOff  ax
        add     ax,SIZE PALSEG
        stosw
        .errnz  palseg_cb - palseg_usMax - 2

        .errnz  palseg_apalclr - palseg_cb - 2

        mov     cx,crgb
        xor     eax,eax
        cmp     cbRGB,3
        je      cpfr_old_rgb

cpfr_new_rgb:
        movsd
        .errnz  palclr_rgb
        .errnz  (SIZE RGB2) - 4
        stosd
        .errnz  (SIZE PALCLR) - 8
        loop    cpfr_new_rgb
        jmp     short cpfr_exit

cpfr_old_rgb:
        movsw
        movsb
        .errnz  palclr_rgb
        .errnz  (SIZE RGB) - 3
        stosb
        stosd
        .errnz  (SIZE PALCLR) - 8
        loop    cpfr_old_rgb

cpfr_exit:
        pop     ebx

cEnd

        CPUMode 286

;/***************************************************************************
;*
;* FUNCTION NAME = NoMappingNeeded
;*
;* DESCRIPTION   = This routine just returns DX:AX = 0 to indicate that no
;*                 palette mapping is necessary for this blt.                   
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,SI,DI,ES,DS,FLAGS
;*                 Registers Preserved:
;*                       BP
;*
;* INPUT         = DS = Data                             
;*                 AL = fbPalMap flags for the new cache 
;* OUTPUT        = DX:AX = 0                          
;*                 C = 1 (==> don't update the cache) 
;* RETURN-NORMAL = AX = near pointer to memory allocated 
;* RETURN-ERROR  = AX = 0
;*
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc   NoMappingNeeded,<NEAR,PUBLIC>,<>
        parmW   npddcSrc
        parmW   npddcDst
        parmR   fbCmd,al
cBegin
        xor     ax,ax
        cwd
        stc
cEnd

;/***************************************************************************
;*
;* FUNCTION NAME = HackPalMapper
;*
;* DESCRIPTION   = Special pal mapper for the case of identical palettes in     
;*                 source bitmap and destination DC.  The mapping is the        
;*                 identity, possibly composed with the palette realization     
;*                 table.                                                       
;*
;*                 Registers Destroyed:
;*                       BX,CX,SI,DI,ES 
;*                 Registers Preserved: 
;*                       BP,DS          
;*
;* INPUT         = DS = Data                             
;*                 AL = fbPalMap flags for the new cache 
;* OUTPUT        = DX:AX --> palmap vector (= 0 if no mapping needed) 
;*                 C = 0 if cache is to be updated                    
;*                 C = 1 if cache is not to be updated
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = DX:AX  = 0 (couldn't get memory for resizing mapping, abort) 
;*                 C = 1 to prevent cache from being updated                        
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

        CPUMode 386
cProc   HackPalMapper,<NEAR,PUBLIC>,<>
        parmW   npddcDst
cBegin

;/*
;** initialize the mapping vector to the identity
;*/

        mov     di,ds
        mov     es,di
        mov     di,DataOFFSET abPalMapVect
        mov     cx,SIZE_HW_PAL/4
        mov     eax,03020100h
@@:     stosd
        add     eax,04040404h
        loop    @B
;/*
;** if the destination DC is the device, then map again through the
;** palette realization table
;*/

        mov     di,npddcDst
        test    [di].ddc_fb,DDC_DEVICE
        jz      hpm_load_return_code
        mov     di,[di].ddc_npdevpal
        les     bx,[di].devpal_pPalSeg
        palSize cx,es,bx
        cCall   ComposePaletteMapping,<di,cx>

hpm_load_return_code:
        mov     ax,DataOFFSET abPalMapVect
        mov     dx,ds
        clc                                       ;C = 0 ==> update the cache
cEnd
        CPUMode 286

;/***************************************************************************
;*
;* FUNCTION NAME = NonDefBMToScr
;*
;* DESCRIPTION   = This routine constructs a mapping vector to copy pels from a 
;*                 memory bitmap DC to a screen DC, where both DCs have the     
;*                 same palette, and are not the default.  If the palettes are  
;*                 not identical, the call is passed on to NonDefPalMapper.     
;*
;*                 Registers Destroyed:
;*                       BX,CX,SI,DI,ES 
;*                 Registers Preserved: 
;*                       BP,DS          
;*
;* INPUT         = DS = Data                             
;*                 AL = fbPalMap flags for the new cache 
;* OUTPUT        = DX:AX --> palmap vector (= 0 if no mapping needed) 
;*                 C = 0 if cache is to be updated                    
;*                 C = 1 if cache is not to be updated
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

        CPUMode 386
cProc   NonDefBMToScr,<NEAR,PUBLIC>,<>
        parmW   npddcSrc
        parmW   npddcDst
        parmR   fbCmd,al
cBegin
        test    fbCmd,MPMV_SRC_DST_IDENTICAL
        jz      ndbts_pals_different

;/*
;** initialize the mapping vector to the identity
;*/

        mov     di,ds
        mov     es,di
        mov     di,DataOFFSET abPalMapVect
        mov     cx,SIZE_HW_PAL/4
        mov     eax,03020100h
@@:     stosd
        add     eax,04040404h
        loop    @B

;/*
;** map again through the palette realization table
;*/

        mov     di,npddcDst
        mov     di,[di].ddc_npdevpal
        les     bx,[di].devpal_pPalSeg
        assumes es,nothing
        palSize ax,es,bx,SIZE_HW_PAL
        cCall   ComposePaletteMapping,<di,ax>
        mov     ax,DataOFFSET abPalMapVect
        mov     dx,ds
        clc                                       ;C = 0 ==> update the cache
        jmp     short ndbts_exit

ndbts_pals_different:
        cCall   NonDefPalMapper,<npddcSrc,npddcDst,fbCmd>
ndbts_exit:
cEnd
        CPUMode 286

;/***************************************************************************
;*
;* FUNCTION NAME = NonDefScrToBM
;*
;* DESCRIPTION   = This routine constructs a mapping vector to copy pels from a 
;*                 screen DC to a memory bitmap DC, where both DCs have the     
;*                 same palette, and are not the default.  If the palettes are  
;*                 not identical, the call is passed on to NonDefPalMapper.     
;*
;*                 Registers Destroyed:
;*                       BX,CX,SI,DI,ES 
;*                 Registers Preserved: 
;*                       BP,DS          
;*
;* INPUT         = DS = Data                             
;*                 AL = fbPalMap flags for the new cache 
;* OUTPUT        = DX:AX --> palmap vector (= 0 if no mapping needed) 
;*                 C = 0 if cache is to be updated                    
;*                 C = 1 if cache is not to be updated
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

        CPUMode 386
cProc   NonDefScrToBM,<NEAR,PUBLIC>,<>
        parmW   npddcSrc
        parmW   npddcDst
        parmR   fbCmd,al
cBegin
        test    fbCmd,MPMV_SRC_DST_IDENTICAL
        jz      ndstb_pals_different

;/*
;** initialize the mapping vector to the identity
;*/

        mov     di,ds
        mov     es,di
        mov     di,DataOFFSET abPalMapVect
        mov     cx,SIZE_HW_PAL/4
        mov     eax,03020100h
@@:     stosd
        add     eax,04040404h
        loop    @B

;/*
;** invert the palette realization table
;*/

        mov     di,npddcDst
        mov     di,[di].ddc_npdevpal
        les     si,[di].devpal_pPalSeg
        assumes es,nothing
        palSize ax,es,si,SIZE_HW_PAL
        xchg    ax,cx
        sub     bh, bh
        sub     dx, dx                            ; dx=index
        mov     di,DataOFFSET abPalMapVect
MakeInverseTableLoop:
        mov     bl,es:[si].palseg_apalclr.palclr_bCur
        mov     byte ptr [di+bx],dl
        inc     dx
        add     si,size PALCLR
        loop    MakeInverseTableLoop

        mov     ax,DataOFFSET abPalMapVect
        mov     dx,ds
        clc                                       ;C = 0 ==> update the cache
        jmp     short ndstb_exit

ndstb_pals_different:
        cCall   NonDefPalMapper,<npddcSrc,npddcDst,fbCmd>
ndstb_exit:
cEnd
        CPUMode 286

;/***************************************************************************
;*
;* FUNCTION NAME = NonDefPalMapper
;*
;* DESCRIPTION   = 
;*
;*      This routine constructs a mapping between one palette and another.
;*      It assumes that neither the source nor the destination palette are
;*      the default, except that the source can be the hardware palette,
;*      in which case any other source palette is ignored. The destination
;*      can also be the hardware palette, in which case the source is mapped
;*      through any destination palette into the hardware. The mapping has
;*      three stages:
;*   
;*                  source       --> destination --> hardware
;*             (may be hardware)                       (optional)
;*
;*                 Registers Destroyed:
;*                       BX,CX,SI,DI,ES 
;*                 Registers Preserved: 
;*                       BP,DS          
;*
;* INPUT         = DS = Data                             
;*                 AL = fbPalMap flags for the new cache 
;* OUTPUT        = DX:AX --> palmap vector (= 0 if no mapping needed) 
;*                 C = 0 if cache is to be updated                    
;*                 C = 1 if cache is not to be updated
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc   NonDefPalMapper,<NEAR,PUBLIC>,<>
        parmW   npddcSrc
        parmW   npddcDst
        parmR   fbCmd,al
        localW  cclr
cBegin
        test    fbCmd,MPMV_SRC_DEV
        jz      ndpm_get_src_pal
        cCall   AllocPalSeg,<SIZE_HW_PAL>
        cwd                                      ;sign extend zero in case of error
        or      ax,ax                            ;0 ==> error
        stc                                      ;C = 1 ==> don't update cache
        njz     ndpm_exit
        mov     npddcSrc,ax                       ;don't need npddcSrc in this case

        les     bx,phwpal
        assumes es,nothing
        cCall   CreatePalSegFromRGBs,<ax,SIZE_HW_PAL,bx,4>
        mov     ax,npddcSrc
        mov     bx,ds
        mov     cclr,SIZE_HW_PAL
        jmp     short ndpm_get_dst_pal

ndpm_get_src_pal:
        mov     si,npddcSrc
        mov     si,[si].ddc_npdevpal
        les     di,[si].devpal_pPalSeg
        assumes es,nothing
        palSize ax,es,di,SIZE_HW_PAL
        mov     cclr,ax
        xchg    ax,cx
        mov     ax,di
        mov     bx,es

ndpm_get_dst_pal:
        mov     di,npddcDst
        mov     di,[di].ddc_npdevpal
        mov     cx,[di].devpal_pPalSeg.lo
        mov     dx,[di].devpal_pPalSeg.hi

        farPtr  pPalSrc,bx,ax
        farPtr  pPalDst,dx,cx
        farPtr  myMapVect,ds,<DataOFFSET abPalMapVect>
        cCall   MatchTwoPalettes,<pPalSrc,pPalDst,myMapVect,MTP_LIMIT_SIZE>

        test    fbCmd,MPMV_DST_DEV
        jz      ndpm_check_palseg

        mov     di,npddcDst
        mov     di,[di].ddc_npdevpal
        cCall   ComposePaletteMapping,<di,cclr>

ndpm_check_palseg:
        test    fbCmd,MPMV_SRC_DEV
        jz      ndpm_load_return_code
        cCall   FreePalSeg,<npddcSrc,SIZE_HW_PAL>

ndpm_load_return_code:
        mov     ax,DataOFFSET abPalMapVect
        mov     dx,ds
        clc                                       ;C = 0 ==> update the cache
ndpm_exit:
cEnd

;/***************************************************************************
;*
;* FUNCTION NAME = DstIsDefPalMapper
;*
;* DESCRIPTION   = 
;*
;*       This routine constructs a mapping between one palette and another.
;*       It assumes that the destination palette is the default, and that the
;*       source DC is not the default palette.  The destination can also be
;*       the hardware palette, in which case the source is mapped through the
;*       default palette into the hardware. The mapping has three stages:
;*    
;*                   source       --> destination --> hardware
;*              (custom palette)                        (default) (optional)
;*
;*                 Registers Destroyed:
;*                       BX,CX,SI,DI,ES 
;*                 Registers Preserved: 
;*                       BP,DS          
;*
;* INPUT         = DS = Data                             
;*                 AL = fbPalMap flags for the new cache 
;* OUTPUT        = DX:AX --> palmap vector (= 0 if no mapping needed) 
;*                 C = 0 if cache is to be updated                    
;*                 C = 1 if cache is not to be updated
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = DX:AX  =  0 (couldn't get memory for resizing mapping, abort)
;*                 C = 1 to prevent cache from being updated
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc   DstIsDefPalMapper,<NEAR,PUBLIC>,<>
        parmW   npddcSrc
        parmW   npddcDst
        parmR   fbCmd,al
        localW  cclrSrc
        localW  nppalSrc
cBegin
        test    fbCmd,MPMV_SRC_DEV
        jz      ddef_src_not_dev

        cCall   AllocPalSeg,<SIZE_HW_PAL>
        or      ax,ax                            ;0 ==> error
        jnz     ddef_got_src_palseg
        xor     ax,ax
        cwd
        stc
        jmp     ddef_exit

ddef_got_src_palseg:
        mov     nppalSrc,ax
        mov     cclrSrc,SIZE_HW_PAL

ifdef FIREWALLS
        mov     bx,es
        assert  bx,E,<phwpal.hi>
endif
        mov     bx,phwpal.lo
        cCall   CreatePalSegFromRGBs,<ax,SIZE_HW_PAL,bx,4>
        mov     ax,nppalSrc
        mov     bx,ds
        jmp     short ddef_match_palettes

ddef_src_not_dev:
        mov     si,npddcSrc
        mov     si,[si].ddc_npdevpal
        les     bx,[si].devpal_pPalSeg
        assumes es,nothing
        palSize ax,es,bx,SIZE_HW_PAL
        mov     cclrSrc,ax
        xchg    ax,bx
        mov     bx,es

;/*
;** Match the palettes.  The mapping vector will take source pels into
;** the logical index range of the default palette.  Afterwards, we will
;** have to map each entry through the default palette realization table
;** to get the actual ipcs.
;*/

ddef_match_palettes:
        farPtr  pPalSrc,bx,ax
        farPtr  pPalDst,ds,<DataOFFSET palsegDefPal>
        farPtr  myMapVect,ds,<DataOFFSET abPalMapVect>
        cCall   MatchTwoPalettes,<pPalSrc,pPalDst,myMapVect,MTP_LIMIT_SIZE>

        mov     di,ds
        mov     es,di
        assumes es,Data
        mov     di,DataOFFSET abPalMapVect
        mov     cx,cclrSrc
        mov     bx,DataOFFSET abDefPalMap_16_256
ddef_loop:
        mov     al,[di]
        xlat
        stosb
        loop    ddef_loop

ddef_release_src:
        test    fbCmd,MPMV_SRC_DEV
        jz      ddef_load_return_val
        cCall   FreePalSeg,<nppalSrc,cclrSrc>

ddef_load_return_val:
        mov     ax,DataOFFSET abPalMapVect
        mov     dx,ds
        clc
ddef_exit:
cEnd

;/***************************************************************************
;*
;* FUNCTION NAME = SrcIsDefPalMapper
;*
;* DESCRIPTION   = 
;*
;*     This routine constructs a mapping between one palette and another.
;*     It assumes that the source palette is the default, the source DC is
;*     not the device.  It assumes the destination palette is not the default.
;*     The destination DC can be the device, in which case the source-to-
;*     destination mapping vector is concatenated with the hardware palette.
;*     The mapping has three stages:
;*  
;*                 source       --> destination --> hardware
;*            (default, non-                        (non-default) (optional)
;*              hardware)
;*
;*                 Registers Destroyed:
;*                       BX,CX,SI,DI,ES 
;*                 Registers Preserved: 
;*                       BP,DS          
;*
;* INPUT         = DS = Data                             
;*                 AL = fbPalMap flags for the new cache 
;* OUTPUT        = DX:AX --> palmap vector (= 0 if no mapping needed) 
;*                 C = 0 if cache is to be updated                    
;*                 C = 1 if cache is not to be updated
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = DX:AX  =  0 (couldn't get memory for resizing mapping, abort)
;*                 C = 1 to prevent cache from being updated
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc   SrcIsDefPalMapper,<NEAR,PUBLIC>,<>
        parmW   npddcSrc
        parmW   npddcDst
        parmR   fbCmd,al
cBegin
        mov     di,npddcDst
        mov     di,[di].ddc_npdevpal
        mov     cx,[di].devpal_pPalSeg.lo
        mov     dx,[di].devpal_pPalSeg.hi

        farPtr  pPalSrc,ds,<DataOFFSET palsegDefPal>
        farPtr  pPalDst,dx,cx
        farPtr  myMapVect,ds,<DataOFFSET abPalMapVect>
        cCall   MatchTwoPalettes,<pPalSrc,pPalDst,myMapVect,MTP_LIMIT_SIZE>

        test    fbCmd,MPMV_DST_DEV
        jz      sdef_load_return_val

        mov     di,npddcDst
        mov     di,[di].ddc_npdevpal
        mov     si,DataOFFSET palsegDefPal
        palSize cx,ds,si
        cCall   ComposePaletteMapping,<di,cx>

sdef_load_return_val:
        mov     ax,DataOFFSET abPalMapVect
        mov     dx,ds
        clc
sdef_exit:
cEnd

;/***************************************************************************
;*
;* FUNCTION NAME = HDBMDevPalMapper
;*
;* DESCRIPTION   = 
;*
;*       This routine constructs a mapping between a hdbm RGB table and the
;*       device palette.
;*
;*                 Registers Destroyed:
;*                       BX,CX,SI,DI,ES 
;*                 Registers Preserved: 
;*                       BP,DS          
;*
;* INPUT         = DS = Data                             
;* OUTPUT        = NONE
;* RETURN-NORMAL = DX:AX --> palmap vector (= 0 if no mapping needed)  
;* RETURN-ERROR  = DX:AX  =  0 (couldn't get memory for resizing mapping, abort)
;**************************************************************************/

        CPUMode 386

        assumes ds,Data
        assumes es,nothing

cProc   HDBMDevPalMapper,<FAR,PUBLIC>,<>
        parmW   npddcSrc
        parmW   npddcDst
        parmW   cclr
        parmW   cbRGB
cBegin
        xor     ax,ax
        cwd                                     ;assume no palette in dest
        mov     di,npddcDst
        test    [di].ddc_fbBelow,DDC_PALETTE
        jz      short hdpm_exit
        cCall   AllocPalSeg,<cclr>
        cwd                                     ;sign extend zero in case of error
        or      ax,ax                           ;0 ==> error
        jz      short hdpm_exit

        mov     si,npddcSrc                     ;get the source surface
        mov     npddcSrc,ax                     ;save the source palette
        push    ds
        lds     bx,dword ptr ds:[si].bm_sd.sd_pbmi
        assumes ds,nothing
        add     bx,ds:[bx].bmp2_cbFix.lo        ;DS:BX => RGB2 color table
        mov     es,FarCodeData
        assumes es,Data                         ;ES:AX => Source palette
        cCall   CreatePalSegFromRGBs,<ax,cclr,bx,cbRGB>
        pop     ds
        assumes ds,Data
        assumes es,nothing

hdpm_get_dst_pal:
        mov     di,npddcDst
        mov     di,[di].ddc_npdevpal
        mov     cx,[di].devpal_pPalSeg.lo
        mov     dx,[di].devpal_pPalSeg.hi

        farPtr  pPalSrc,ds,npddcSrc
        farPtr  pPalDst,dx,cx
        farPtr  myMapVect,ds,<DataOFFSET abPalMapVect>
        cCall   MatchTwoPalettes,<pPalSrc,pPalDst,myMapVect,MTP_LIMIT_SIZE>
        cCall   ComposePaletteMapping,<di,cclr>
        cCall   FreePalSeg,<npddcSrc,cclr>
        mov     ax,DataOFFSET abPalMapVect
        mov     dx,ds

hdpm_exit:

cEnd

        CPUMode 286

;/***************************************************************************
;*
;* FUNCTION NAME = ComposePaletteMapping
;*
;* DESCRIPTION   = 
;*
;*       This routine maps the entries in abPalMapVect in place through the
;*       palclr_bCur values from the given devpal.
;*
;*                 Registers Destroyed:
;*                       AL,BX,CX,SI,DI,ES  
;*                 Registers Preserved:     
;*                       AH,DX,BP,DS        
;*
;* INPUT         = DS = Data                             
;* OUTPUT        = NONE
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc ComposePaletteMapping,<NEAR,PUBLIC>,<ds>
        parmW   devpal
        parmW   cclr
cBegin
        mov     di,ds
        mov     es,di
        assumes es,Data
        mov     di,DataOFFSET abPalMapVect
        mov     si,devpal
        lds     si,[si].devpal_pPalSeg
        assumes ds,nothing

        mov     cx,cclr
@@:
        mov     bl,es:[di]
        xor     bh,bh
        palOff  bx
        mov     al,[si+bx].palseg_apalclr.palclr_bCur
        stosb
        loop    @B
cEnd

;/***************************************************************************
;*
;* FUNCTION NAME = NDevNDefNDevNDef
;*
;* DESCRIPTION   = Bitmap, custom --> bitmap, custom
;*                 If palettes are identical, no mapping is required.
;*
;*                 Registers Destroyed:
;*                       BX,CX,SI,DI,ES 
;*                 Registers Preserved: 
;*                       BP,DS          
;*
;* INPUT         = DS = Data                             
;*                 AL = fbPalMap flags for the new cache
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = DX:AX --> palmap vector (= 0 if no mapping needed)  
;*                 C = 0 if cache is to be updated
;*                 C = 1 if cache is not to be updated
;* RETURN-ERROR  = NONE
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc NDevNDefNDevNDef,<NEAR,PUBLIC>,<>
        parmW   npddcSrc
        parmW   npddcDst
        parmR   fbCmd,al
cBegin
        xor     ax,ax
        cwd
        test    al,MPMV_SRC_DST_IDENTICAL
        stc
        jnz     ndndndnd_exit

        mov     al,fbCmd
        cCall   NonDefPalMapper,<npddcSrc,npddcDst>

ndndndnd_exit:
cEnd

sEnd

ifdef FIREWALLS
        public  mpmv_chk_src_pal
        public  mpmv_src_is_def
        public  mpmv_chk_dst
        public  mpmv_chk_dst_pal
        public  mpmv_chk_ident_pals
        public  mpmv_have_flags
        public  mpmv_cache_invalid
        public  mpmv_exit
        public  ndpm_get_src_pal
        public  ndpm_get_dst_pal
        public  ndpm_check_palseg
        public  ndpm_load_return_code
        public  ndpm_exit
        public  ddef_src_not_dev
        public  ddef_match_palettes
        public  ddef_release_src
        public  ddef_exit
        public  ndndndnd_exit
endif

end
