#ifndef fbc
#define fbc -p Res\ -c
#endif

#include once "asm.bi"
#include once "crt.bi"
'#include once "..\includes\LD32.bi"
#include once "win\mmsystem.bi"
#include once "win\d3d.bi"
#include once "fbgfx.bi"
#ifdef EnableNetPlay
  #include once "win\dplay.bi"
  #include once "win\winsock2.bi"
#endif
#include once "..\includes\ddraw.bi"
#include once "..\includes\header.bas"

#ifndef DPLAYOBJ
'extern as iDirectPlay3AObject DPLAYOBJ
'extern as DirectDrawObject DDOBJ
'extern as ddSpecialObject DDSPEC
'extern as ddSurfaceObject FRONTBUFFER
'extern as ddSurfaceObject BACKBUFFER
'extern as CooperativeStruct DDRAWCOOP
#endif

#include "Modules\Detour.bas"

dim shared as ulongint RGB_F800    = &h0000F8000000F800ull
dim shared as ulongint RGB_07E0    = &h000007E0000007E0ull
dim shared as ulongint RGB_001F    = &h0000001F0000001Full
dim shared as ulongint QCOLORKEY   = &h0000000000000000ull  
dim shared as ulongint QALPHA      = &hD0000000D0000000ull
dim shared as ulongint QCOLORMSK   = &h00FFFFFF00FFFFFFull

#undef Convert16to32
sub Convert16to32(ENTRADA as any ptr,SAIDA as any ptr,HORIZ as integer,VERTI as integer,PITCH as integer=0)
  asm
    mov ESI,[ENTRADA]    'Carrega Endereço do frame de 15bpp (origem)
    mov EDI,[SAIDA]      'Carrega Endereço do frame de 16bpp (destino)
    movq MM7,[QCOLORKEY] 'Carrega constante zero
    movq MM6,[RGB_F800]  'Carrega constante R
    movq MM5,[RGB_07E0]  'Carrega constante G
    movq MM4,[RGB_001F]  'Carrega Constante B
    movq MM3,[QALPHA]    'Initial mask/alpha
    mov EBX,[PITCH]      'Pitch difference
    mov ECX,[VERTI]      'Carrega em ECX número de linhas
    1:                   'Label para próxima LINHA
    mov EDX,[HORIZ]      'Carrega em EDX número de colunas
    shr EDX,1            'divide EDX 2 por (já que MMX faz 2 pixels por vez)
    2:                   'Label para próxima COLUNA
    movd MM0,[ESI]       'lodsw
    PUNPCKLWD MM0,MM0    'expande 2 words para 2 dwords
    movq MM1,MM0         'mov EBX,EAX
    movq MM2,MM0         'mov ECX,EAX
    pand MM0,MM6         'red
    pand MM1,MM5         'green
    pand MM2,MM4         'blue
    pslld MM0,8          'shr EAX,8
    pslld MM1,5          'shl EBX,5
    pslld MM2,3          'shl ECX,19
    por MM0,MM1          'or EAX,EBX
    movq MM1,MM7         'colorkey
    por MM0,MM2          'or EAX,ECX
    pcmpeqd MM1,MM0      'colorkey
    pandn MM1,MM3        'to alpha
    por MM0,MM1          'or ALPHA
    movq [EDI],MM0       'stosd
    add ESI,4            'Aponta fonte para próximos 4 pixels(8)
    add EDI,8            'Aponta fonte para próximos 4 pixels(16)
    dec EDX              'Decrementar contador de colunas
    jnz 2b               'Retorna para a label de próxima coluna até EDX zerar
    sub ecx,1            'one line done
    lea ESI,[ESI+EBX]    'pitch
    jnz 1b               'Decrementa contador de linhas e retora até zerar
    emms                 'libera mmx
  end asm
end sub
sub ColorKey32(pData as any ptr,iWidth as integer,iHeight as integer)
  var iCount = (iWidth*iHeight) shr 1
  asm    
    mov edi,[pData]
    mov ecx,[iCount]
    mov edx,0x00FFFFFF
    0:    
    test dword ptr [edi],(not &hFF0F0F0F)    
    jnz 1f
    and [edi],edx
    1:test dword ptr [edi+4],(not &hFF0F0F0F)        
    jnz 1f    
    and [edi+4],edx
    1:dec ecx
    lea edi,[edi+8]
    jnz 0b
  end asm
end sub
sub MergeAlpha(pData as any ptr,pAlpha as any ptr,iWidth as integer,iHeight as integer)
  var iCount = (iWidth*iHeight) shr 2
  asm
    mov edi,[pData]
    mov esi,[pAlpha]
    sub edi, 16
    mov ecx,[iCount]
    movq mm7,[QCOLORMSK]
    0:
    add edi,16
    movq mm4,[esi]
    movq mm5,[esi+8]
    movq mm0,[edi]    
    pslld mm4,24
    movq mm1,[edi+8]
    pslld mm5,24
    add esi,16
    pand mm0,mm7
    pand mm1,mm7
    por mm0,mm4
    por mm1,mm5        
    sub ecx,1
    movq [edi],mm0    
    movq [edi+8],mm1    
    jnz 0b
    emms
  end asm
end sub
  
' ***************************************************************
' ******************** BLUR 16 + NOISE **************************
' ***************************************************************
#if 0
  sub Blur16(ORIGIN as any ptr,SCRPTR as any ptr)
    
    const B16_LINE = 320*2
    static as ushort ptr BLURZIM
    
    dim as integer BLUROFF = (fix(rnd*32767) shl 1)
    
    if BLURZIM = 0 then
      BLURZIM = allocate(65536*2)
      BLURZIM = cast(ushort ptr,((cast(uinteger,BLURZIM) or 65535)+1))
      for C as integer = 0 to 32767
        BLURZIM[C] = ((rnd*65535) and &b0000100001100001)
      next C
    end if
    
    
    asm
      mov ESI,[ORIGIN]
      mov EDI,[SCRPTR]
      push EBP    
      mov ECX,[BLURZIM]
      add ECX,[BLUROFF]
      mov EBP,320*198
      
      movzx EAX, word ptr [ESI]          'load pixel 1
      shl EAX,5             ' \
      shr AX,2              ' | modify 565 to 888   
      shl EAX,8             ' | (keeping 565 values)
      shr AX,3              ' | for both 1/3 pixels 
      shr EAX,8             ' /
      
      .align 16
      _NEXT_PIXEL_:     '**** Begin New pixel ***8
      movzx EBX, word ptr [ESI+2]          'load pixel 2
      movzx EDX, word ptr [ESI+B16_LINE]   'load pixel 3
      shl EBX,5             ' \
      shl EDX,5             ' |
      shr BX,2              ' |
      shr DX,2              ' | modify 565 to 888   
      shl EBX,8             ' | (keeping 565 values)
      shl EDX,8             ' | for both 2/3 pixels 
      shr BX,3              ' |
      shr DX,3              ' |
      shr EBX,8             ' |
      shr EDX,8             ' /
      
      shl EAX,1
      add EAX,EBX           ' \
      add EAX,EDX           ' | Get Average of 4 pixels
      shr EAX,2             ' /
      
      shl EAX,8             ' \
      shl AX,3              ' | modify 888 to 565
      shr EAX,8             ' | (values was in 565)    
      shl AX,2              ' | for the averaged pixel    
      shr EAX,5             ' /
      
      xor AX,[ECX]
      add CX,2
      
      mov [EDI],AX          ' Store pixel
      add ESI,2             ' Point to next INPUT pixel
      add EDI,2             ' Point to next output pixel
      mov EAX,EBX           ' pixels 2/4 are now 1/2
      dec EBP               ' decrease pixel count
      jnz _NEXT_PIXEL_      ' go calc remaining pixels
      
      mov ESI,EDI
      sub ESI,640
      mov ECX,318
      rep movsw
      
      pop EBP
      
    end asm
    
  end sub
#endif

' ***************************************************************
' ************************ BLUR 16 ******************************
' ***************************************************************
sub Blur16z(ORIGIN as any ptr,SCRPTR as any ptr)
  
  const B16_LINE = 512*2
  
  asm
    mov ESI,[ORIGIN]
    mov EDI,[SCRPTR]
    push EBP    
    mov EBP,512*511
    
    movzx EAX, word ptr [ESI]          'load pixel 1
    shl EAX,5             ' \
    shr AX,2              ' | modify 565 to 888   
    shl EAX,8             ' | (keeping 565 values)
    shr AX,3              ' | for both 1/3 pixels 
    shr EAX,8             ' /
    
    .align 16
    _B16Z_NEXT_PIXEL_:     '**** Begin New pixel ***8
    movzx EBX, word ptr [ESI+2]          'load pixel 2
    movzx EDX, word ptr [ESI+B16_LINE]   'load pixel 3
    shl EBX,5             ' \
    shl EDX,5             ' |
    shr BX,2              ' |
    shr DX,2              ' | modify 565 to 888   
    shl EBX,8             ' | (keeping 565 values)
    shl EDX,8             ' | for both 2/3 pixels 
    shr BX,3              ' |
    shr DX,3              ' |
    shr EBX,8             ' |
    shr EDX,8             ' /
    
    shl EAX,1
    add EAX,EBX           ' \
    add EAX,EDX           ' | Get Average of 4 pixels
    shr EAX,2             ' /
    
    shl EAX,8             ' \
    shl AX,3              ' | modify 888 to 565
    shr EAX,8             ' | (values was in 565)    
    shl AX,2              ' | for the averaged pixel    
    shr EAX,5             ' /
    
    mov [EDI],AX          ' Store pixel
    add ESI,2             ' Point to next INPUT pixel
    add EDI,2             ' Point to next output pixel
    mov EAX,EBX           ' pixels 2/4 are now 1/2
    dec EBP               ' decrease pixel count
    jnz _B16Z_NEXT_PIXEL_      ' go calc remaining pixels
    
    mov ESI,EDI
    sub ESI,1024
    mov ECX,510
    rep movsw
    
    pop EBP
    
  end asm
  
end sub

function GetHash(pData as any ptr,iSizeA8 as integer) as ulongint
  asm    
    mov ebx,[iSizeA8]
    mov esi,[pData]
    shr ebx,3
    xor eax,eax
    mov ecx,ebx
    xor edx,edx        
    shr ecx,2
    and ebx,3
    jz 1f
    0:
    add eax,[esi]
    add edx,[esi+4]
    rol eax,3
    ror edx,1
    add eax,&h55555555
    add edx,&hAAAAAAAA
    dec ebx
    lea esi,[esi+8]
    jnz 0b
    .align 4
    1:
    add eax,[esi]
    add edx,[esi+4]
    rol eax,3
    ror edx,1
    add eax,&h55555555
    add edx,&hAAAAAAAA
    add eax,[esi+8]
    add edx,[esi+12]
    rol eax,3
    ror edx,1
    add eax,&h55555555
    add edx,&hAAAAAAAA
    add eax,[esi+16]
    add edx,[esi+20]
    rol eax,3
    ror edx,1
    add eax,&h55555555
    add edx,&hAAAAAAAA
    add eax,[esi+24]
    add edx,[esi+28]
    rol eax,3
    ror edx,1
    add eax,&h55555555
    add edx,&hAAAAAAAA
    sub ecx,1
    lea esi,[esi+32]
    jnz 1b
    mov [function],eax
    mov [function+4],edx
  end asm
end function

sub Noise32(PIXPTR as any ptr,iSize as integer)
  static as uinteger uRand(16400)
  if uRand(0)=0 then
    for CNT as integer = 0 to 16400
      uRand(CNT) = (rnd*&hFFFFFF) and &h070707
    next CNT
  end if
  var iStart = int(rnd*16383)*4
  asm
    mov edi,[PIXPTR]
    lea esi,[uRand]
    mov ecx,[iSize]
    mov edx,[iStart]
    shr ecx, 3    
    0:
    movq mm0,[esi+edx+ 0]
    movq mm1,[esi+edx+ 8]
    movq mm2,[esi+edx+16]
    movq mm3,[esi+edx+24]
    movq mm4,[edi+ 0]
    movq mm5,[edi+ 8]
    movq mm6,[edi+16]
    movq mm7,[edi+24]
    pxor mm0,mm4
    pxor mm1,mm5
    pxor mm2,mm6
    pxor mm3,mm7
    movq [edi+ 0],mm0
    movq [edi+ 8],mm1
    movq [edi+16],mm2
    movq [edi+24],mm3
    add edx,32
    add edi,32
    and edx,65535
    dec ecx
    jnz 0b
    emms
  end asm
end sub



