ifndef                  _DDS_ASM
_DDS_ASM                equ     1

; ------------------------------------------------------
; Includes
                        include Files.asm

; ------------------------------------------------------
; Structures
DDCOLORKEY              struct
dwColorSpaceLowValue    dword   ?               ; low boundary of color space that is to
dwColorSpaceHighValue   dword   ?               ; high boundary of color space that is
                                                ; to be treated as Color Key, inclusive
DDCOLORKEY              ends

_MultiSampleCaps        struct
wFlipMSTypes            word    ?               ; Multisample methods supported via flip for this D3DFORMAT
wBltMSTypes             word    ?               ; Multisample methods supported via blt for this D3DFORMAT
_MultiSampleCaps        ends

DDSCAPS2                struct
dwCaps                  dword   ?               ; capabilities of surface wanted
dwCaps2                 dword   ?
dwCaps3                 dword   ?
union
dwCaps4                 dword   ?
dwVolumeDepth           dword   ?
ends
DDSCAPS2                ends

DDPIXELFORMAT           struct
dwSize                  dword   ?               ; size of structure
dwFlags                 dword   ?               ; pixel format flags
dwFourCC                dword   ?               ; (FOURCC code)
union
dwRGBBitCount           dword   ?               ; how many bits per pixel
dwYUVBitCount           dword   ?               ; how many bits per pixel
dwZBufferBitDepth       dword   ?               ; how many total bits/pixel in z buffer (including any stencil bits)
dwAlphaBitDepth         dword   ?               ; how many bits for alpha channels
dwLuminanceBitCount     dword   ?               ; how many bits per pixel
dwBumpBitCount          dword   ?               ; how many bits per "buxel", total
dwPrivateFormatBitCount dword   ?               ; Bits per pixel of private driver formats. Only valid in texture
                                                ; format list and if DDPF_D3DFORMAT is set
ends ; 1
union
dwRBitMask              dword   ?               ; mask for red bit
dwYBitMask              dword   ?               ; mask for Y bits
dwStencilBitDepth       dword   ?               ; how many stencil bits (note: dwZBufferBitDepth-dwStencilBitDepth is total Z-only bits)
dwLuminanceBitMask      dword   ?               ; mask for luminance bits
dwBumpDuBitMask         dword   ?               ; mask for bump map U delta bits
dwOperations            dword   ?               ; DDPF_D3DFORMAT Operations
ends ; 2
union
dwGBitMask              dword   ?               ; mask for green bits
dwUBitMask              dword   ?               ; mask for U bits
dwZBitMask              dword   ?               ; mask for Z bits
dwBumpDvBitMask         dword   ?               ; mask for bump map V delta bits
MultiSampleCaps         _MultiSampleCaps <?>
ends ; 3
union
dwBBitMask              dword   ?               ; mask for blue bits
dwVBitMask              dword   ?               ; mask for V bits
dwStencilBitMask        dword   ?               ; mask for stencil bits
dwBumpLuminanceBitMask  dword   ?               ; mask for luminance in bump map
ends ; 4
union
dwRGBAlphaBitMask       dword   ?               ; mask for alpha channel
dwYUVAlphaBitMask       dword   ?               ; mask for alpha channel
dwLuminanceAlphaBitMask dword   ?               ; mask for alpha channel
dwRGBZBitMask           dword   ?               ; mask for Z channel
dwYUVZBitMask           dword   ?               ; mask for Z channel
ends ; 5
DDPIXELFORMAT           ends

DDSURFACEDESC2          struct
dwSize                  dword   ?               ; size of the DDSURFACEDESC structure
dwFlags                 dword   ?               ; determines what fields are valid
dwHeight                dword   ?               ; height of surface to be created
dwWidth                 dword   ?               ; width of input surface
UNION
lPitch                  dword   ?               ; distance to start of next line (return value only)
dwLinearSize            dword   ?               ; Formless late-allocated optimized surface size
ENDS ; 1
UNION
dwBackBufferCount       dword   ?               ; number of back buffers requested
dwDepth                 dword   ?               ; the depth if this is a volume texture
ENDS ; 5
UNION
dwMipMapCount           dword   ?               ; number of mip-map levels requested
                                                ; dwZBufferBitDepth removed, use ddpfPixelFormat one instead
dwRefreshRate           dword   ?               ; refresh rate (used when display mode is described)
dwSrcVBHandle           dword   ?               ; The source used in VB::Optimize
ENDS ; 2
dwAlphaBitDepth         dword   ?               ; depth of alpha buffer requested
dwReserved              dword   ?               ; reserved
lpSurface               LPVOID  ?               ; pointer to the associated surface memory
UNION
ddckCKDestOverlay       DDCOLORKEY <?>          ; color key for destination overlay use
dwEmptyFaceColor        dword   ?               ; Physical color for empty cubemap faces
ENDS ; 3
ddckCKDestBlt           DDCOLORKEY <?>          ; color key for destination blt use
ddckCKSrcOverlay        DDCOLORKEY <?>          ; color key for source overlay use
ddckCKSrcBlt            DDCOLORKEY <?>          ; color key for source blt use
union
ddpfPixelFormat         DDPIXELFORMAT <?>       ; pixel format description of the surface
dwFVF                   dword   ?               ; vertex format description of vertex buffers
ends ; 4
ddsCaps                 DDSCAPS2 <?>            ; direct draw surface capabilities
dwTextureStage          dword   ?               ; stage in multitexture cascade
DDSURFACEDESC2          ends

; ------------------------------------------------------
; Structures
ifndef                  _DDS_STRUCT_ASM
_DDS_STRUCT_ASM         equ     1

DDS                     struct
_Datas                  dword   ?
_Width                  dword   ?
_Height                 dword   ?
_Bits                   dword   ?
_Mips                   dword   ?
_Compression            dword   ?
DDS                     ends
endif

; ------------------------------------------------------
; Name: Load_DDS
; Desc: Load Direct Draw Surface file into memory
Load_DDS                proc    uses ebx esi edi DDS_FName:dword, DDS_Struct:dword
                        local   DDS_Buffer:dword
                        local   FSize:dword
                        local   _MipMul:dword
                        local   _Width:dword
                        local   _Height:dword

                        mov     esi, DDS_Struct
                        mov     [esi + DDS._Datas], NULL

                        ; Load texture into memory
                        invoke  Load_File, DDS_FName, addr FSize
                        test    eax, eax
                        jz      Err_DDS_Load
                        mov     DDS_Buffer, eax

                        ; Decode the DDS file
                        mov     ebx, eax
                        cmp     dword ptr [ebx], " SDD"
                        jne     Err_DDS_Format
                        ; Pass header
                        add     ebx, 4
                        mov     eax, [ebx + DDSURFACEDESC2.dwWidth]
                        imul    eax, [ebx + DDSURFACEDESC2.dwHeight]
                        .if     eax > 0
                                mov     [esi + DDS._Mips], CMEM([ebx + DDSURFACEDESC2.dwMipMapCount])
                                mov     [esi + DDS._Width], CMEM([ebx + DDSURFACEDESC2.dwWidth])
                                mov     [esi + DDS._Height], CMEM([ebx + DDSURFACEDESC2.dwHeight])
                                mov     [esi + DDS._Bits], 4
                                mov     _MipMul, 16
                                .if     [ebx + DDSURFACEDESC2.ddpfPixelFormat.dwFourCC] == "1TXD"
                                        mov     [esi + DDS._Compression], GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
                                        mov     [esi + DDS._Bits], 3
                                        mov     _MipMul, 8
                                .elseif [ebx + DDSURFACEDESC2.ddpfPixelFormat.dwFourCC] == "3TXD"
                                        mov     [esi + DDS._Compression], GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
                                .elseif [ebx + DDSURFACEDESC2.ddpfPixelFormat.dwFourCC] == "5TXD"
                                        mov     [esi + DDS._Compression], GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
                                .else
                                        jmp     Err_DDS_Format
                                .endif
                                mov     _Width, CMEM([esi + DDS._Width])
                                mov     _Height, CMEM([esi + DDS._Height])
                                xor     edx, edx
                                xor     edi, edi
                                .repeat
                                        mov     eax, _Width
                                        add     eax, 3
                                        shr     eax, 2
                                        mov     ecx, _Height
                                        add     ecx, 3
                                        shr     ecx, 2
                                        imul    eax, ecx
                                        imul    eax, _MipMul
                                        add     edi, eax
                                        shr     _Width, 1
                                        shr     _Height, 1
                                        inc     edx
                                .until  edx >= [ebx + DDSURFACEDESC2.dwMipMapCount]
                                mov     eax, ALLOCMEM(edi)
                                test    eax, eax
                                jz      Err_DDS_Format
                                mov     [esi + DDS._Datas], eax
                                ; Point to raw datas in the file
                                lea     esi, [ebx + sizeof DDSURFACEDESC2]
                                ; Copy the datas
                                mov     ecx, edi
                                push    ecx
                                mov     edi, eax
                                shr     ecx,2
                                rep     movsd
                                pop     ecx
                                and     ecx,3
                                rep     movsb
                        .endif
                        FREEMEM DDS_Buffer
                        mov     eax, TRUE                               ; Loaded
                        ret
Err_DDS_Format:         FREEMEM DDS_Buffer
Err_DDS_Load:           xor     eax, eax                                ; Not loaded
                        ret
Load_DDS                endp

; ------------------------------------------------------
; Name: Unload_DDS
; Desc: Free an allocated Direct Draw Surface file
Unload_DDS              proc    uses esi DDS_Struct:dword
                        mov     esi, DDS_Struct
                        test    esi, esi
                        jz      @F
                        mov     eax, [esi + DDS._Datas]
                        test    eax, eax
                        jz      @F
                        FREEMEM eax
@@:                     ret
Unload_DDS              endp

endif
