;*****************************************************************************/
;
; COPYRIGHT    Copyright (C) 1992 IBM Corporation
;
;    The following IBM OS/2 2.1 source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 2.x 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.;
;*****************************************************************************/
;.386p
        TITLE   RGBCONV.ASM
        .386
        .387
        INCLUDELIB os2386.lib
        INCLUDELIB dde4mbs.lib
CODE32  SEGMENT PARA USE32 PUBLIC 'CODE'
CODE32  ENDS
DATA32  SEGMENT PARA USE32 PUBLIC 'DATA'
DATA32  ENDS
CONST32 SEGMENT PARA USE32 PUBLIC 'CONST'
CONST32 ENDS
BSS32   SEGMENT PARA USE32 PUBLIC 'BSS'
BSS32   ENDS
DGROUP  GROUP CONST32, BSS32, DATA32
        ASSUME  CS:FLAT, DS:FLAT, SS:FLAT, ES:FLAT
DATA32  SEGMENT
;_DATA   SEGMENT  DWORD USE32 PUBLIC 'DATA'      ; changed from code to data
;        ASSUME   DS: FLAT


;** EXTRN        ConvTable:BYTE
ConvTable      DD   0

;_DATA   ENDS
DATA32  ENDS
BSS32   SEGMENT
BSS32   ENDS
CONST32 SEGMENT
CONST32 ENDS
CODE32  SEGMENT
;_TEXT   SEGMENT  DWORD USE32 PUBLIC 'CODE'
;        ASSUME   CS:_TEXT, DS: FLAT, SS: FLAT, ES: FLAT
;*********************************************
; Define the C calling macros
LBegin  macro len
        push    ebp
        mov     ebp,esp
        sub     esp,len
        endm
LEnd    macro
        mov     esp,ebp
        pop     ebp
        endm
;*********************************************

;*********************************************
; Define the RGB16_to_PAL8 - convert RGB16 to a PAL8 value
RGB16_to_PAL8 macro r_offset, d_offset, w_offset
        mov   ax,   Word Ptr [esi+r_offset]; get the RGB16 value   ; 4
        shr   ax,   1                      ; shift off LSB blue    ; 3
        ror   al,   4                      ; get green in LSB      ; 3
        shr   ax,   1                      ; shift out LSB green   ; 3
        shl   eax,  2                      ; x4 for table index    ; 3
        mov   al,   offset flat:ConvTable[eax+d_offset]            ; 4
        mov   Byte Ptr [edi+w_offset], al  ; Save Converted Value  ; 4
        endm
;*********************************************

;*********************************************
; Define the RGB16_to_2PAL8 - convert RGB16 to 2 PAL8 values
RGB16_to_2PAL8 macro r_offset, w2_offset, w_offset
        xor   eax,  eax
        mov   ax,   Word Ptr [esi+r_offset]; get the RGB16 value   ; 4
        shr   ax,   1                      ; shift off LSB blue    ; 3
        ror   al,   4                      ; get green in LSB      ; 3
        shr   ax,   1                      ; shift out LSB green   ; 3
        shl   eax,  2                      ; x4 for table index    ; 3
        mov   eax,  offset flat:ConvTable[eax]                     ; 4
        mov   Word Ptr [edi+w_offset], ax  ; Save Converted Value  ; 4
        ror   eax, 16                                              ; 2
        mov   Word Ptr [edi+w2_offset], ax ; Save Converted Value  ; 4
        endm
;*********************************************

;*********************************************
; Define the COPY_ESI_EDI - Copy a word from ESI+offset1 to EDI+offset2
COPY_ESI_EDI macro offsetD, offsetS
        mov   ax,   Word Ptr [esi+offsetS] ; get the Word value   ; 4
        mov   Word Ptr [edi+offsetD], ax   ; save Word Value      ; 2
        endm
;*********************************************

;*********************************************
; Define the COPY_ESI_EDI2 - Copy a word from ESI+offS to EDI+offD and
; EDI+offD+2 and EDI+offD+offL and EDI+offD+offL+2
; This macro doubles the data
COPY_ESI_EDI2 macro offD, offS, OffL
        mov   ax,   Word Ptr [esi+offS]        ; get the Word value   ; 4

                                               ; Double on first scanline
        mov   Word Ptr [edi+offD],        ax   ; save Word Value      ; 2
        mov   Word Ptr [edi+offD+2],      ax   ; save Word Value      ; 2
                                               ; Double on next Scanline
        mov   Word Ptr [edi+offD+offL],   ax   ; save Word Value      ; 2
        mov   Word Ptr [edi+offD+offL+2], ax   ; save Word Value      ; 2
        endm
;*********************************************


;*****************************************************************************;
; Procedure Name  :     Convert YUV422 to RGB24  and Invert                   ;
;                                                                             ;
; Description     :     Convert a Width x Height 16-bit YUV422 image          ;
;                       to RGB24 (8-Red, 8-Green, 8-Blue format) and          ;
;                       Inver the image                                  .    ;
;                                                                             ;
; Register status :                                                           ;
;*****************************************************************************;
ALIGN 4
;_YUV422_to_IRGB24 PROC NEAR

    PUBLIC YUV422_TO_IRGB24
YUV422_TO_IRGB24 PROC

   ;*The-Stack***********************************
   ; The local variables:
                luma1                  equ ebp-4
                luma2                  equ ebp-5
                backup                 equ ebp-12

   ; The passed parameters:
;                aSrc                    equ ebp+8
;                aDst                    equ ebp+12
;                lWidth                  equ ebp+16
;                lHeight                 equ ebp+20
                lHeight                 equ ebp+8
                lWidth                  equ ebp+12
                aDst                    equ ebp+16
                aSrc                    equ ebp+20
   ;*The-Stack***********************************

                ; Leave some room on the stack for local variables
                enter   20,0
                pushfd
                pushad

                ; Move the image from source pointer
                mov     esi,    [aSrc]

                ; Move the image to the destination pointer
                mov     edi,    [adst]
                mov     edx,[lHeight]   ; Height of image
                sub   edx,1             ; less 1 line for start of last line
                mov   ecx,[lWidth]      ; Size Width in PELs
                mov   eax,ecx           ;
                shl   eax,1             ; * 2
                add   eax,ecx           ; eax = width * 3 (bytes per PEL)
                mul   EDX               ; EAX*EDX goes into EDX:EAX
                                        ;  EDX will be zero
                add   EDI,EAX           ; point to last line of output buffer

                ; Length to backup after each scanline in Destination buffer
                mov     eax,[lwidth]       ; Each Pixel is 3 Bytes (RGB24)
                shl     eax,1              ; Pixel_width*2
                add     eax,[lwidth]       ; Pixel_width*2 + Pixel_width = 3
                shl     eax,1              ; * 2 (back up for next Inverted line)
                mov    [backup],eax        ; Detla to Previous/Next line in Dest

                ; set direction flag to increment
                cld

ICONVYUV_LINEA:
;  int 3
                ; Set ECX to PELs in a ROW
                mov     ecx,    [lWidth]   ; Width in PELs
                shr     ecx,1              ; Width / 2

ICONV_2PEL:
                lodsw
                mov    [luma1],al          ; Save Y = Lumance
                mov    dh,ah               ; U into DH

                lodsw
                mov    [luma2],al          ; Save Y = Lumance
                mov    dl,ah               ; V into DL


                call   UnScaleChroma2      ; EDX V = bit 31-16  U = bits 15-0

                movzx  bx,byte ptr [luma1] ; Y
                call   ConvertYUVToRGB24   ; BL=Red AH=Green AL=Blue
                shl    ebx,16              ; Move Red up to proper position
                and    eax,0FFFFh          ; Clear top for byte of Red
                or     eax,ebx             ; Combine Red in with Green and Blue
                mov    [edi],eax           ; Store RGB24 to 1 extra byte
                add    edi,3               ; Only 3 Valid Bytes but 4 written

                movzx  bx,byte ptr [luma2] ; Y
                call   ConvertYUVToRGB24
                shl    ebx,16              ; Move Red up to proper position
                and    eax,0FFFFh          ; Clear top for byte of Red
                or     eax,ebx             ; Combine Red in with Green and Blue
                mov    [edi],eax           ; Store RGB24 to 1 extra byte
                add    edi,3               ; Only 3 Valid Bytes but 4 written


                ; Check to see if we are at the end of the line.
                dec     ecx
                jnz     ICONV_2PEL

                sub     edi,[backup]       ; Backup to previous line to Invert
                dec     dword ptr [lHeight]
                jnz     ICONVYUV_LINEA


                ; Restore registers and the stack.
                popad
                popfd
                leave
                ret

;_YUV422_to_IRGB24 ENDP
YUV422_to_IRGB24 ENDP


;ZDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD?
;3 ConvertYUVToRGB24                                                    3
;3                                                                      3
;3 This routine converts one YUV value to a 24 bit RGB value and        3
;3 returns the result in AX and BL.                                     3
;3                                                                      3
;3      U = B-Y         ->      B = U+Y                                 3
;3      V = R-Y         ->      R = V+Y                                 3
;3      Y  = 0.299*R + 0.587*G + 0.114*B        ->                      3
;3      G = 1.704*Y - 0.5094*R - 0.1942*B                               3
;3                                                                      3
;3 Entry:       DX  = U = B-Y                                           3
;3              EDX = V = R-Y (bit 31-16)                                          3
;3              BX  = Y = luma component                                3
;3 Exit:        AH  = Green                                             3
;3              AL  = Blue                                              3
;3              BL  = Red                                               3
;3 Note:        U and V are signed numbers.  Luma is unsigned.          3
;3 Modifies:    AX,BX,DX                                                3
;@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDY
ALIGN 4
;ConvertYUVToRGB24 PROC NEAR
ConvertYUVToRGB24 PROC
        push    edx
Blue:   mov     ax,dx
        add     ax,bx                  ;AX = U + Y = Blue
        jge     @F
        xor     ax,ax
        jmp     Red
@@:     cmp     ax,0ffh
        jle     Red
        mov     ax,0ffh

Red:    shr     edx,16                  ; V
        add     dx,bx                   ;DX = V + Y = Red
        jge     @F
        xor     dx,dx
        jmp     have_red_and_blue
@@:     cmp     dx,0ffh
        jle     have_red_and_blue
        mov     dl,0ffh

have_red_and_blue:
        mov     dh,al
        xchg    dx,bx                   ;BH = Blue   BL = Red   DX = Luma

Green:  mov     ax,436                  ;(436/256) = 1.703
        mul     dx
        mov     dh,dl
        mov     dl,ah                   ;DX = 1.704 * luma

        mov     al,bl                   ;Red
        mov     ah,130                  ;(130/256) = 0.5078
        mul     ah
        mov     al,ah
        xor     ah,ah
        sub     dx,ax                   ;DX = 1.704*luma - 0.508*red
        mov     al,bh                   ;Blue
        mov     ah,50
        mul     ah
        mov     al,ah
        xor     ah,ah
        sub     dx,ax                   ;DX = 1.704*luma - 0.508*red - 0.195*blue
        jge     check_green_overflow
        xor     dl,dl                   ;Set green to zero.
        jmp     have_rgb

check_green_overflow:
        cmp     dh,0                    ;Is green > 255?
        je      have_rgb                ;No.
        mov     dl,0ffh                 ;Yes, set it to 255.

have_rgb:
        mov     al,bh
        mov     ah,dl                   ;AH = Green   AL = Blue   BL = Red
        pop     edx
        ret
ConvertYUVToRGB24 ENDP

;ZDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD?
;3 UnScaleChroma                                                        3
;3                                                                      3
;3 This routine multiplies the two scaled 8 bits chroma components, U   3
;3 and V by the fractions 229/127 and 179/127, respectively.  The       3
;3 results are stored in the local variables U and V.                   3
;3                                                                      3
;3 Entry:       DL = scaled V                                           3
;3              DH = scaled U                                           3
;3 Exit:        EDX V = unscaled V bits 31-16                           3
;3              EDX U = unscaled U bits 15-0                            3
;3 Destroys:    AX,BX,DX                                                3
;@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDY
ALIGN 4
;UnScaleChroma PROC NEAR
UnScaleChroma PROC
        push    ecx
        mov     bl,dh                   ;BL = scaled U
        mov     al,dl
        cbw                             ;AX = scaled V (sign extended)
        mov     dx,361                  ;(361/256 = 179/127)
        imul    dx
        mov     al,ah
        mov     ah,dl
        mov     cx,ax                    ;CX = unscaled V

        mov     al,bl
        cbw                             ;AX = scaled U (sign extended)
        mov     dx,456                  ;(456/256 = 226/127)
        imul    dx
        mov     al,ah
        mov     ah,dl
;       mov     U,ax                    ;AX = unscaled U
        xor     edx,edx
        mov     dx,ax
        shl     ecx,16
        or      edx,ecx                 ; V bit 31-16 and U bit 15-0 of EDX
        pop     ecx
        ret
UnScaleChroma ENDP


;ZDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD?
;3 UnScaleChroma2                                                       3
;3                                                                      3
;3 This routine multiplies the two scaled 8 bits chroma components, U   3
;3 and V by the fractions 229/127 and 179/127, respectively.  The       3
;3 results are stored in the local variables U and V.                   3
;3                                                                      3
;3 Note:... on input U and V are normalize to -127 to +127              3
;3                                                                      3
;3 Entry:       DL = scaled V                                           3
;3              DH = scaled U                                           3
;3 Exit:        EDX V = unscaled V bits 31-16                           3
;3              EDX U = unscaled U bits 15-0                            3
;3 Destroys:    AX,BX,DX                                                3
;@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDY
ALIGN 4
;UnScaleChroma2 PROC NEAR
UnScaleChroma2 PROC
        push    ecx
        mov     bl,dh                   ;BL = scaled U
        movzx   ax,dl                   ; V
        sub     ax,80h                  ;AX = scaled V
        mov     dx,361                  ;(361/256 = 179/127)
        imul    dx
        mov     al,ah
        mov     ah,dl
        mov     cx,ax                    ;CX = unscaled V

        movzx   ax,bl                   ; U
        sub     ax,80H                  ;AX = scaled U
        mov     dx,456                  ;(456/256 = 226/127)
        imul    dx
        mov     al,ah
        mov     ah,dl
;       mov     U,ax                    ;AX = unscaled U
        xor     edx,edx
        mov     dx,ax
        shl     ecx,16
        or      edx,ecx                 ; V bit 31-16 and U bit 15-0 of EDX
        pop     ecx
        ret
UnScaleChroma2 ENDP

;_TEXT   ENDS
CODE32  ENDS
END
