'   0 IDirect3D2_QueryInterface(p,a,b)  (p)->lpVtbl->QueryInterface(p,a,b)
'   1 IDirect3D2_AddRef(p)              (p)->lpVtbl->AddRef(p)
'   2 IDirect3D2_Release(p)             (p)->lpVtbl->Release(p)
'   3 IDirect3D2_EnumDevices(p,a,b)     (p)->lpVtbl->EnumDevices(p,a,b)
'   4 IDirect3D2_CreateLight(p,a,b)     (p)->lpVtbl->CreateLight(p,a,b)
'   5 IDirect3D2_CreateMaterial(p,a,b)  (p)->lpVtbl->CreateMaterial(p,a,b)
'   6 IDirect3D2_CreateViewport(p,a,b)  (p)->lpVtbl->CreateViewport(p,a,b)
'   7 IDirect3D2_FindDevice(p,a,b)      (p)->lpVtbl->FindDevice(p,a,b)
'   8 IDirect3D2_CreateDevice(p,a,b,c)  (p)->lpVtbl->CreateDevice(p,a,b,c)

' ****************************************************************************************
function iDirect3D2Prototype() as hresult  
  FatalError("iDirect3D2::#%i Function not implemented",IDIRECT3D2PROTOID)  
  return DDERR_UNSUPPORTED
  
  asm
    .balign 32
    _IDirect3D2ProtoTable_:  
    #macro ProtoNum(X)
    mov dword ptr [IDIRECT3D2PROTOID],X
    jmp iDirect3D2Prototype
    .balign 32
    #endmacro
    ProtoNum(0)
    ProtoNum(1)
    ProtoNum(2)
    ProtoNum(3)
    ProtoNum(4)
    ProtoNum(5)
    ProtoNum(6)
    ProtoNum(7)
    ProtoNum(8)
    ProtoNum(9)
    ProtoNum(10)
    ProtoNum(11)
    ProtoNum(12)
    ProtoNum(13)
    ProtoNum(14)
    ProtoNum(15)
    ProtoNum(16)
    ProtoNum(17)
    ProtoNum(18)
    ProtoNum(19)
    ProtoNum(20)
  end asm  
  
end function
' ****************************************************************************************
UndefAll()
#define P1 IDIRECT3D2 as iDirect3D2Object ptr
function iDirect3D2_2_Release(P1) as hresult
  #ifdef MyDebugD3D
  Cout("IDirect3D2.Release (2)" + chr$(13,10) + _
  " >> IDIRECT3D2: "+hex$(cast(uinteger,IDIRECT3D2),8))
  #endif
  Delete IDIRECT3D2  
  return DD_OK
end function
' ****************************************************************************************
UndefAll()
#define P1 pTHIS          as iDirect3D2Object ptr
#define P2 DeviceCallBack as LPD3DENUMDEVICESCALLBACK
#define P3 UserData       as any ptr
function iDirect3D2_3_EnumDevices(P1,P2,P3) as hresult
  #ifdef MyDebugD3D
  Cout("IDirect3D2.EnumDevices (3)" + chr$(13,10) + _
  " >> THIS: "+HexPtr(pTHIS)+ "  CallBack: "+HexPtr(DeviceCallBack) + _
  "  UserData: "+HexPtr(UserData))
  #endif  
  
  dim as D3DDeviceDesc DeviceDesc
  with DeviceDesc
    .dwSize = sizeof(DeviceDesc)
    .dwFlags = -1
    'D3DDD_BCLIPPING or D3DDD_COLORMODEL or D3DDD_DEVCAPS or _
    'D3DDD_DEVICERENDERBITDEPTH or D3DDD_DEVICEZBUFFERBITDEPTH or _
    'D3DDD_LIGHTINGCAPS or D3DDD_LINECAPS or D3DDD_MAXBUFFERSIZE or _    
    'D3DDD_MAXVERTEXCOUNT or D3DDD_TRANSFORMCAPS or D3DDD_TRICAPS
    .dcmColorModel = D3DCOLOR_RGB
    .dwDevCaps = -1
    'D3DDEVCAPS_CANBLTSYSTONONLOCAL or D3DDEVCAPS_CANRENDERAFTERFLIP or _
    'D3DDEVCAPS_DRAWPRIMITIVES2 or D3DDEVCAPS_DRAWPRIMTLVERTEX or _
    'D3DDEVCAPS_DRAWPRIMITIVES2EX or D3DDEVCAPS_EXECUTESYSTEMMEMORY or _ 'D3DDEVCAPS_EXECUTEVIDEOMEMORY
    'D3DDEVCAPS_FLOATTLVERTEX or D3DDEVCAPS_HWRASTERIZATION or _
    'D3DDEVCAPS_HWTRANSFORMANDLIGHT _ 'D3DDEVCAPS_SEPARATETEXTUREMEMORIES
    'or _ 'D3DDEVCAPS_SORTDECREASINGZ D3DDEVCAPS_SORTEXACT D3DDEVCAPS_SORTINCREASINGZ
    'D3DDEVCAPS_TLVERTEXSYSTEMMEMORY or _ 'D3DDEVCAPS_TEXTURENONLOCALVIDEOMEMORY
    'D3DDEVCAPS_TEXTURESYSTEMMEMORY or D3DDEVCAPS_TEXTUREVIDEOMEMORY 'D3DDEVCAPS_TLVERTEXVIDEOMEMORY
    .dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP '-1
    .bClipping = True
    with .dlcLightingCaps
      .dwSize = sizeof(D3DLIGHTINGCAPS)
      .dwCaps = -1
      .dwLightingModel = D3DLIGHTINGMODEL_RGB
      .dwNumLights = 8
    end with
    with .dpcLineCaps
      .dwSize = sizeof(D3DPRIMCAPS)
      .dwMiscCaps = -1 xor D3DPMISCCAPS_CULLNONE
      .dwRasterCaps = -1
      .dwZCmpCaps = -1
      .dwSrcBlendCaps = -1
      .dwDestBlendCaps = -1
      .dwAlphaCmpCaps = -1
      .dwShadeCaps = -1 'D3DPSHADECAPS_COLORFLATRGB '-1
      .dwTextureCaps = -1 'not D3DPTEXTURECAPS_PERSPECTIVE  '-1
      .dwTextureFilterCaps = -1
      .dwTextureBlendCaps = D3DPTBLENDCAPS_COPY or D3DPTBLENDCAPS_DECAL or D3DPTBLENDCAPS_MODULATE
      .dwTextureAddressCaps = not D3DPTADDRESSCAPS_MIRROR
      .dwStippleWidth = 32
      .dwStippleHeight = 32
    end with
    with .dpcTriCaps
      .dwSize = sizeof(D3DPRIMCAPS)      
      .dwMiscCaps = -1 xor D3DPMISCCAPS_CULLNONE
      .dwRasterCaps = -1
      .dwZCmpCaps = -1
      .dwSrcBlendCaps = -1
      .dwDestBlendCaps = -1
      .dwAlphaCmpCaps = -1
      .dwShadeCaps = -1 'D3DPSHADECAPS_COLORGOURAUDRGB
      .dwTextureCaps = -1 'not D3DPTEXTURECAPS_PERSPECTIVE  '-1
      .dwTextureFilterCaps = -1
      .dwTextureBlendCaps = D3DPTBLENDCAPS_COPY or D3DPTBLENDCAPS_DECAL or D3DPTBLENDCAPS_MODULATE
      .dwTextureAddressCaps = not D3DPTADDRESSCAPS_MIRROR
      .dwStippleWidth = 32
      .dwStippleHeight = 32
    end with    
    .dwDeviceRenderBitDepth = DDBD_8 or DDBD_16 or DDBD_24 or DDBD_32
    .dwDeviceZBufferBitDepth = DDBD_8 or DDBD_16 or  DDBD_24 or DDBD_32
    .dwMaxBufferSize = 0
    .dwMaxVertexCount = 65535 '16384
    .dwMinTextureWidth = 32
    .dwMinTextureHeight = 32
    .dwMaxTextureWidth = 8192
    .dwMaxTextureHeight = 8192
    .dwMinStippleWidth = 0
    .dwMaxStippleWidth = 32
    .dwMinStippleHeight = 0
    .dwMaxStippleHeight = 32
    .dwMaxTextureRepeat = 256
    .dwMaxTextureAspectRatio = 1
    .dwMaxAnisotropy = 16	
    .wMaxTextureBlendStages = 4
    .wMaxSimultaneousTextures = 4
  end with
  
  DeviceCallBack(@MYGUIDS(giIDirect3DDevice2).GUID, _
  "Direct3D driver compatible emulation by Mysoft", _
  "Mysoft GregForce OpenGL compatible HAL D3D device", _
  @DeviceDesc,@DeviceDesc, UserData)
  
  'return DDERR_INVALIDOBJECT
  return DD_OK
end function
' ****************************************************************************************
UndefALL()
#define P1 pTHIS       as iDirect3D2Object ptr
#define P2 OUTLIGHT    as D3DLightObject ptr ptr
#define P3 PUNKNOWN    as any ptr ptr
function IDirect3D2_4_CreateLight(P1,P2,P3) as hresult
  
  return DDERR_INVALIDPARAMS
  
  puts("A1")
  
  if OUTLIGHT=0 then ddrawError(DDERR_INVALIDPARAMS)  
  
  puts("A2")
  
  if pTHIS->Interface <> itDirect3D2 then
    ddrawError(DDERR_INVALIDOBJECT)
  end if
  
  if IsBadWritePtr(OUTLIGHT,4) then
    puts("Bad Ptr")
    'ddrawError(DDERR_INVALIDPARAMS)  
    return DD_OK
  end if
  
  puts("A3")
  *OUTLIGHT = new d3dlightObject
  puts("BB")
  d3dlightFuncs(d3dlight_FUNCS())  
  with *cptr(d3dlightObject ptr,*OUTLIGHT)
    .VTABLE = @d3dlight_FUNCS(0)
    .Interface = itd3dlight
  end with  
  
  #ifdef MyDebugD3D
  Cout("iDirect3D2.CreateLight (4)" + chr$(13,10) + _
  " >> THIS: "+hex$(cast(uinteger,pTHIS),8) + _
  " OUT: "+HexPtr(OUTLIGHT)+" NEW: "+HexPtr(*OUTLIGHT))
  #endif
  
  return DD_OK
  
end function

' ****************************************************************************************
UndefALL()
#define P1 pTHIS       as iDirect3D2Object ptr
#define P2 OUTMATERIAL as D3DMaterial2Object ptr ptr
#define P3 PUNKNOWN    as any ptr ptr
function IDirect3D2_5_CreateMaterial(P1,P2,P3) as hresult
  
  if OUTMATERIAL=0 then ddrawError(DDERR_INVALIDPARAMS)  
  if pTHIS->Interface <> itDirect3D2 then
    ddrawError(DDERR_INVALIDOBJECT)
  end if
  
  *OUTMATERIAL = new d3dMaterial2Object
  d3dMaterial2Funcs(d3dMaterial2_FUNCS())  
  with *cptr(d3dMaterial2Object ptr,*OUTMATERIAL)
    .VTABLE = @d3dMaterial2_FUNCS(0)
    .Interface = itd3dMaterial2    
  end with  
  
  #ifdef MyDebugD3D
  Cout("iDirect3D2.CreateMaterial (5)" + chr$(13,10) + _
  " >> THIS: "+hex$(cast(uinteger,pTHIS),8) + _
  " OUT: "+HexPtr(OUTMATERIAL)+" NEW: "+HexPtr(*OUTMATERIAL))
  #endif
  
  return DD_OK
  
end function
' ****************************************************************************************
UndefALL()
#define P1 pTHIS       as iDirect3D2Object ptr
#define P2 OUTVIEWPORT as any ptr ptr
#define P3 PUNKNOWN    as any ptr ptr
function IDirect3D2_6_CreateViewport(P1,P2,P3) as hresult
  
  if OUTVIEWPORT=0 then ddrawError(DDERR_INVALIDPARAMS)  
  if pTHIS->Interface <> itDirect3D2 then
    ddrawError(DDERR_INVALIDOBJECT)
  end if
  
  *OUTVIEWPORT = new d3dViewPort2Object
  d3dViewPort2Funcs(d3dViewPort2_FUNCS())  
  with *cptr(d3dViewPort2Object ptr,*OUTVIEWPORT)
    .VTABLE = @d3dViewPort2_FUNCS(0)
    .Interface = itd3dViewPort2    
  end with  
  
  #ifdef MyDebugD3D
  Cout("iDirect3D2.CreateViewPort (6)" + chr$(13,10) + _
  " >> THIS: "+hex$(cast(uinteger,pTHIS),8) + _
  " OUT: "+HexPtr(OUTVIEWPORT)+" NEW: "+HexPtr(*OUTVIEWPORT))
  #endif
  
  return DD_OK
  
end function
' ****************************************************************************************
UndefALL()
#define P1 pTHIS     as iDirect3D2Object ptr
#define P2 CLASSID   as GUID ptr
#define P3 INSURFACE as ddSurfaceObject ptr
#define P4 OUTDEVICE as any ptr ptr
function iDirect3D2_8_CreateDevice(P1,P2,P3,P4) as hresult
  
  dim as string TMPQUERYS = "Unknown",TMPIID = "0x" + hex$(cast(any ptr,CLASSID),8)
  dim as integer FUNCRESULT=DDERR_INVALIDOBJECT,QUERYRESULT = -1 

  if CLASSID andalso isBadReadPtr(CLASSID,sizeof(GUID))=0 then        
    #ifdef MyDebugD3D
    TMPIID = GetGuid(CLASSID)    
    #endif
    QUERYRESULT = CheckGUID(CLASSID,TMPQUERYS)    
  end if
  
  if INSURFACE=0 orelse INSURFACE->Interface<>itSurface then
    FUNCRESULT = DDERR_INVALIDPARAMS
  elseif QUERYRESULT > -1 then
    select case QUERYRESULT
    case giIDirect3D2,giIDirect3DDevice2      
      *OUTDEVICE = new d3dDevice2Object
      d3dDevice2Funcs(d3dDevice2_FUNCS())  
      with *cptr(d3dDevice2Object ptr,*OUTDEVICE)
        .VTABLE = @d3dDevice2_FUNCS(0)
        .Interface = itd3dDevice2
        .Surface = INSURFACE
        #ifdef Enable3D
        .SrcBlend = GL_ONE
        .TgtBlend = GL_ZERO
        #endif
      end with      
      FUNCRESULT = DD_OK      
    case else
      FUNCRESULT = E_NOINTERFACE
    end select
  end if
  
  #ifdef MyDebugD3D
  Cout("iDirect3D2.CreateDevice (8)" + chr$(13,10) + _
  " >> THIS: "+hex$(cast(uinteger,pTHIS),8) + " IID: "+TMPIID+chr$(13,10) + _
  "    SURFACE: "+HexPtr(INSURFACE)+" Query: "+QueryGUIDString(CLASSID)+" = "+HexPtr(*OUTDEVICE))
  #endif  
  
  if FUNCRESULT <> DD_OK then
    ddrawError(FUNCRESULT)
  end if
  return FUNCRESULT
  
end function
' ****************************************************************************************
' ****************************************************************************************
sub iDirect3D2Funcs(VTABLE() as any ptr)
  dim as any ptr PROTOTABLE
  asm mov dword ptr [PROTOTABLE], offset _IDirect3D2ProtoTable_
  for CNT as integer = 0 to 20
    VTABLE(CNT) = PROTOTABLE+CNT*32
  next CNT  
  VTABLE(2) = @iDirect3D2_2_Release
  VTABLE(3) = @iDirect3D2_3_EnumDevices
  VTABLE(4) = @iDirect3D2_4_CreateLight
  VTABLE(5) = @IDirect3D2_5_CreateMaterial
  VTABLE(6) = @IDirect3D2_6_CreateViewport
  VTABLE(8) = @iDirect3D2_8_CreateDevice
end sub
