'  0  IDirectDraw_QueryInterface(p, a, b)         (p)->lpVtbl->QueryInterface(p, a, b)
'  1  IDirectDraw_AddRef(p)                       (p)->lpVtbl->AddRef(p)
'  2  IDirectDraw_Release(p)                      (p)->lpVtbl->Release(p)
'  3  IDirectDraw_Compact(p)                      (p)->lpVtbl->Compact(p)
'  4  IDirectDraw_CreateClipper(p, a, b, c)       (p)->lpVtbl->CreateClipper(p, a, b, c)
'  5  IDirectDraw_CreatePalette(p, a, b, c, d)    (p)->lpVtbl->CreatePalette(p, a, b, c, d)
'  6  IDirectDraw_CreateSurface(p, a, b, c)       (p)->lpVtbl->CreateSurface(p, a, b, c)
'  7  IDirectDraw_DuplicateSurface(p, a, b)       (p)->lpVtbl->DuplicateSurface(p, a, b)
'  8  IDirectDraw_EnumDisplayModes(p, a, b, c, d) (p)->lpVtbl->EnumDisplayModes(p, a, b, c, d)
'  9  IDirectDraw_EnumSurfaces(p, a, b, c, d)     (p)->lpVtbl->EnumSurfaces(p, a, b, c, d)
'  10 IDirectDraw_FlipToGDISurface(p)             (p)->lpVtbl->FlipToGDISurface(p)
'  11 IDirectDraw_GetCaps(p, a, b)                (p)->lpVtbl->GetCaps(p, a, b)
'  12 IDirectDraw_GetDisplayMode(p, a)            (p)->lpVtbl->GetDisplayMode(p, a)
'  13 IDirectDraw_GetFourCCCodes(p, a, b)         (p)->lpVtbl->GetFourCCCodes(p, a, b)
'  14 IDirectDraw_GetGDISurface(p, a)             (p)->lpVtbl->GetGDISurface(p, a)
'  15 IDirectDraw_GetMonitorFrequency(p, a)       (p)->lpVtbl->GetMonitorFrequency(p, a)
'  16 IDirectDraw_GetScanLine(p, a)               (p)->lpVtbl->GetScanLine(p, a)
'  17 IDirectDraw_GetVerticalBlankStatus(p, a)    (p)->lpVtbl->GetVerticalBlankStatus(p, a)
'  18 IDirectDraw_Initialize(p, a)                (p)->lpVtbl->Initialize(p, a)
'  19 IDirectDraw_RestoreDisplayMode(p)           (p)->lpVtbl->RestoreDisplayMode(p)
'  20 IDirectDraw_SetCooperativeLevel(p, a, b)    (p)->lpVtbl->SetCooperativeLevel(p, a, b)
'  21 IDirectDraw_SetDisplayMode(p, a, b, c)      (p)->lpVtbl->SetDisplayMode(p, a, b, c)
'  22 IDirectDraw_WaitForVerticalBlank(p, a, b)   (p)->lpVtbl->WaitForVerticalBlank(p, a, b)

#define ddrawError(iErr) iDirectDrawError(__FUNCTION__,iErr,__LINE__): return iErr
'ddrawError(DDERR_INVALIDPARAMS)
sub iDirectDrawError(sPre as string,iError as integer,iPos as integer)
  #ifdef MyDebugErr
  var sText = "UnkErr #" & iError,sPos=" line: " & iPos
  Select case iError
  case E_NOINTERFACE        : sText = "E_NOINTERFACE"
  case DDERR_INVALIDCAPS    : sText = "DDERR_INVALIDCAPS"
  case DDERR_INVALIDPARAMS  : sText = "DDERR_INVALIDPARAMS"
  case DDERR_INVALIDOBJECT  : sText = "DDERR_INVALIDOBJECT"
  case DDERR_SURFACEBUSY    : sText = "DDERR_SURFACEBUSY"
  case DDERR_NOTLOCKED      : sText = "DDERR_NOTLOCKED"
  case else
    messagebox(null,"Unknown Return Value",sPos,MB_SYSTEMMODAL or MB_ICONWARNING)
  end select  
  cout("!!!ERROR!!! "+sPre+" "+sText+" "+sPos+" !!!ERROR!!!")
  #endif  
end sub
sub fbGfxResize(FIRST as integer=0)  
  Static as rect LastRect = type(-1,-1,-1,-1)
  'printf(!"%s %s:%i",__FUNCTION__,__FILE_NP__,__LINE__)
  if FIRST then
    #ifndef Render_OpenGL
    dim as zstring*512 TITLE    
    GetWindowText(DDRAWCOOP.hwnd,TITLE,512)
    'WindowTitle "fbgfx: "+TITLE
    #endif
  end if
  dim as rect DESKRECT
  scope    
    dim as any ptr hTemp
    if LastRect.left <> -1 and LastRect.bottom <> -1 then
      hTemp = MonitorFromRect(@LastRect,MONITOR_DEFAULTTONEAREST)
    else
      hTemp = MonitorFromWindow(DDRAWCOOP.hwnd,MONITOR_DEFAULTTONEAREST)
    end if
    dim as MonitorInfo MonInf = type(sizeof(MonitorInfo))
    if GetMonitorInfo(hTemp,@MonInf) = 0 then
      GetClientRect(GetDesktopWindow(),@DESKRECT)
    else
      DESKRECT = MonInf.rcMonitor
    end if
  end scope
  'printf(!"%s %s:%i\n",__FUNCTION__,__FILE_NP__,__LINE__)
  with DESKRECT
    dim as integer RESX=WINX,RESY=WINY   
    if RESX=0 then RESX=DDRAWCOOP.wwid : RESY=DDRAWCOOP.whei        
    'dim as integer RESX=dwWidth,RESY=dwHeight
    .right -= .left: .bottom -= .top
    if .right < RESX then RESX = .right
    if .bottom < RESY then RESY = .bottom
    if FULLSCREEN then RESX = .right:RESY = .bottom
    .left += (.right-RESX)/2: .top += (.bottom-RESY)/2
    #ifndef Render_OpenGL
      if FIRST then SetParent(FBWND,DDRAWCOOP.hwnd)      
      SetWindowPos(FBWND,null,0,0,RESX,RESY,SWP_NOZORDER)
      if FIRST then ShowWindow(FBWND,SW_HIDE)
    #endif      
    'printf(!"%s %s:%i\n",__FUNCTION__,__FILE_NP__,__LINE__)
    'Screencontrol(fb.SET_WINDOW_POS,0,0)
    'SetWindowPos(DDRAWCOOP.hwnd,HWND_BOTTOM,x,y,dwWidth,dwHeight,null)
    dim as long TMP    
    #ifdef Render_OpenGL      
    mt_glViewPort(0,0,RESX,RESY)      
    #endif      
    'printf(!"%s %s:%i\n",__FUNCTION__,__FILE_NP__,__LINE__)
    if FULLSCREEN then 
      if LastRect.Left=-1 and LastRect.Bottom=-1 then
        GetWindowRect(DDRAWCOOP.hwnd,@LastRect)
      end if
      TMP = GetWindowLong(DDRAWCOOP.hwnd,GWL_STYLE)
      TMP = (TMP and (not WS_OVERLAPPEDWINDOW)) or WS_POPUPWINDOW
      SetWindowLong(DDRAWCOOP.hwnd,GWL_STYLE,TMP)
      SetWindowPos(DDRAWCOOP.hwnd,HWND_TOPMOST,.left,.top,RESX,RESY,NULL)
    else
      TMP = GetWindowLong(DDRAWCOOP.hwnd,GWL_STYLE)
      TMP = (TMP and (not WS_POPUPWINDOW)) or TMP or WS_OVERLAPPEDWINDOW      
      SetWindowLong(DDRAWCOOP.hwnd,GWL_STYLE,TMP)
      dim as RECT ADJRECT
      ADJRECT.right = RESX: ADJRECT.bottom = RESY
      AdjustWindowRect(@ADJRECT,TMP,False)
      RESX = ADJRECT.right-ADJRECT.left
      RESY = ADJRECT.bottom-ADJRECT.top
      'printf(!"%s %s:%i\n",__FUNCTION__,__FILE_NP__,__LINE__)
      #ifdef Render_OpenGL      
      if WinX=0 and WinY=0 then
        SetWindowPos(DDRAWCOOP.hwnd,HWND_BOTTOM,.left,.top,RESX,RESY,SWP_NOACTIVATE or SWP_NOZORDER)
      elseif LastRect.Left<>-1 and LastRect.Bottom<>-1 then
        RESX = LastRect.right-LastRect.left: RESY = LastRect.bottom-LastRect.top
        printf(!"%i,%i-%i,%i\n",LastRect.left,LastRect.top,RESX,RESY)
        SetWindowPos(DDRAWCOOP.hwnd,HWND_BOTTOM,LastRect.left,LastRect.top,RESX,RESY,SWP_NOZORDER)
        LastRect = type(-1,-1,-1,-1)                
      end if      
      #else
      SetWindowPos(DDRAWCOOP.hwnd,HWND_BOTTOM,.left,.top,RESX,RESY,SWP_NOZORDER)
      #endif      
    end if  
    'if ISMAIN=0 then .left = -1024
    #ifndef Render_OpenGL
    if FIRST then ShowWindow(DDRAWCOOP.hwnd,SW_SHOW)
    if FIRST then ShowWindow(FBWND,SW_SHOW)
    if FIRST then SetForegroundWindow(DDRAWCOOP.hwnd)      
    #endif      
    'printf(!"%s %s:%i\n",__FUNCTION__,__FILE_NP__,__LINE__)
  end with    
  'printf(!" resized!\n")
end sub
#ifdef Render_OpenGL
dim shared as double LastSize
sub UnlockSize(ID as any ptr)
  sleepex 50,1
  dim MyPT as point, MyRC as rect
  GetWindowRect(DDRAWCOOP.hwnd,@MyRC)
  GetCursorPos(@MyPt)
  SetCursorPos(MyRc.left+50,MyRc.top+10)
  mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0)
  sleepex 1,1
  mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0)
  sleepex 1,1
  SetCursorPos(MyPt.x,MyPt.y)
end sub
sub UpdateSize(p as any ptr)
  #ifdef MyDebug
  cout("Update Size Thread: " & GetCurrentThreadID)
  #endif
  if p then
    while (timer-LastSize) < 1/5
      SleepEx(1,1)
    wend    
    'if DDRAWCOOP.hwnd then
      mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0)
      var pp = cast(uinteger ptr,p)  
      dim as hwnd pUnlock    
      pUnlock = ThreadCreate(@UnlockSize,0)    
      mt_glViewPort(0,0,pp[0],pp[1])
      threadwait(pUnlock):pUnlock=0
      LastSize=0
    'end if
  else
    fbGfxResize()
  end if
end sub
#endif

#undef gfxSubClass
function gfxSubClass (HWND as hwnd,UMSG as integer,WPARAM as wparam,LPARAM as lparam) as lresult
  'static as integer icnt
  'icnt += 1
  'printf(!"gfxSubClass! %i\r",icnt)
  'while CantLoseFocus=0
  '  sleepex 1,1
  'wend
  
  select case UMSG    
  #ifdef Render_OpenGL
  case WM_MOUSEMOVE
    if LastSize<>0 then LastSize=timer
  case WM_SIZE
    if ogl.bpp=16 then
      static as integer iSz(1)
      if LastSize then
        iSz(0)=LOWORD(lParam):iSz(1)=HIWORD(lParam)      
        LastSize=timer      
      else      
        iSz(0)=LOWORD(lParam):iSz(1)=HIWORD(lParam)
        if WINX<>0 then
          if iSz(0)>256 and iSz(1)>192 then 
            WINX=iSz(0):WINY=iSz(1)
          end if
        end if
        LastSize = timer
        ThreadCreate(@UpdateSize,@iSz(0))      
      end if
    end if
  case WM_CLOSE
    'exitprocess(0)
    terminateprocess(getcurrentprocess(),1)
  #endif
  case WM_CREATE
    'printf(!"Creating Window...\n")
    'sleep 1000,1
    with *cast(LPCREATESTRUCT,lParam)
      if .cx>=2048 and .cy>=2048 then
        .x=-.cx:.y=-.cy:.style and= (not WS_VISIBLE)
      end if
    end with
  case WM_ACTIVATE
    #ifndef Render_OpenGL
      if loword(wparam) = WA_CLICKACTIVE then
        Setforegroundwindow(DDRAWCOOP.hwnd)
       end if
    #endif    
  end select
  #ifdef Render_OpenGL  
  select case UMSG
  case WM_NCCALCSIZE
    '
  case else  
    if DWORGPROC then dwSubClass(HWND,UMSG,WPARAM,LPARAM)
  end select  
  #endif
  return CallWindowProc(ORGPROC,HWND,UMSG,WPARAM,LPARAM)
end function
dim shared as integer isUpdating,IsTMR
#undef dwSubClass
function dwSubClass (HWND as hwnd,UMSG as integer,WPARAM as wparam,LPARAM as lparam) as lresult
  if DWORGPROC=0 then return 0
  'return CallWindowProc(DWORGPROC,HWND,UMSG,WPARAM,LPARAM)
  'cout("Message: " & HWND & " / " & UMSG)
  static as integer icnt  
  if icnt=0 then
    icnt += 1  
    select case UMSG  
    'case WM_ACTIVATEAPP
    '  if wparam = FALSE then return 0
    'case WM_ACTIVATE
    '  if LOWORD(wparam) = WA_INACTIVE then
    '    return 0
    '  end if
    case WM_CLOSE
      screenunlock: screen 0
      ExitProcess(0)
    case WM_SYSKEYUP
      if wparam = VK_RETURN then
        FULLSCREEN xor= 1
        #ifdef Render_OpenGL
        ThreadCreate(@UpdateSize,0)
        #else
        fbGfxResize()
        #endif
      end if
    end select
    icnt -= 1
  end if
  return CallWindowProc(DWORGPROC,HWND,UMSG,WPARAM,LPARAM)
end function

function IDirectDrawPrototype() as hresult
  #ifdef DebugFatal
    printf(!"proto ddraw\n")
    messagebox(null,"IDirectDraw::#" & IDDPROTOID & " Function not implemented", _
    "DirectX",MB_SYSTEMMODAL or MB_ICONERROR)
  #endif      
  ExitProcess(1)
  return DDERR_UNSUPPORTED
  
  asm
    .balign 32
    _DDrawProtoTable_:  
    #macro ProtoNum(X)
    mov dword ptr [IDDPROTOID],X
    jmp IDirectDrawPrototype
    .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)
    ProtoNum(21)
    ProtoNum(22)
  end asm  
  
end function
' ****************************************************************************************

UndefAll()
#define P1 TDDRAW as DirectDrawObject ptr
#define P2 IID as GUID ptr
#define P3 IOBJECT as any ptr ptr
function IDirectDraw_0_QueryInterface(P1,P2,P3) as hresult  
  #ifdef MyDebug
  dim as string sGUID
  if IID then    
    sGUID = QueryGUIDString(IID)
  else    
    Cout("Error: Invalid Pointer for ddraw interface (DDERR_INVALIDPARAMS)")    
    ddrawError(DDERR_INVALIDPARAMS)
  end if  
  Cout("---- IDirectDraw.QueryInterface ----" + NewLine + _
  "GUID: "+sGUID+" Out: 0x"+hex$(IOBJECT,8) )
  
  '" Buffer: "+hexptr(poptval) & " Len: " & *poptlen)    
  '#endif
  #else
  if IID=0 then ddrawError(DDERR_INVALIDPARAMS)
  #endif
  
  #ifndef Enable3D
  ddrawError(DDERR_INVALIDOBJECT)  
  #else
  dim as string TMPQUERYS = "Unknown",TMPIID = "0x" + hex$(cast(any ptr,IID),8)
  dim as integer FUNCRESULT=DDERR_INVALIDOBJECT,QUERYRESULT = -1 
  
  if IID andalso isBadReadPtr(IID,sizeof(GUID))=0 then        
    QUERYRESULT = CheckGUID(IID,TMPQUERYS)
  end if  
  
  if QUERYRESULT <> -1 then    
    select case QUERYRESULT
    case giIDirect3D,giIDirect3D2
      *IOBJECT = new iDirect3D2Object
      iDirect3D2Funcs(IDIRECT3D2_FUNCS())  
      with *cptr(iDirect3D2Object ptr,*IOBJECT)
        .VTABLE = @IDIRECT3D2_FUNCS(0)
        .Interface = itDirect3D2
      end with  
      FUNCRESULT = DD_OK
    case giIDirectDraw2
      *IOBJECT = new iDirectDraw2Object
      iDirectDraw2Funcs(IDIRECTDRAW2_FUNCS())  
      with *cptr(iDirectDraw2Object ptr,*IOBJECT)
        .VTABLE = @IDIRECTDRAW2_FUNCS(0)
        .Interface = itDirectDraw2
      end with        
      FUNCRESULT = DD_OK
    case else 
      #ifdef MyDebug
      printf(!"Special: '%s'\n",sGUID)
      #endif
      *IOBJECT = new ddSpecialObject
      SpecialFuncs(DDSPECIAL_FUNCS())  
      with *cptr(ddSpecialObject ptr,*IOBJECT)
        .VTABLE = @DDSPECIAL_FUNCS(0)
        .Interface = itSpecial
      end with  
      FUNCRESULT = DD_OK
    end select  
  end if
  
  if FUNCRESULT <> DD_OK then
    ddrawError(FUNCRESULT)
  else
    return FUNCRESULT  
  end if
  #endif
  
end function
' ****************************************************************************************
UndefAll()
#define P1 TDDRAW as DirectDrawObject ptr
function IDirectDraw_2_Release(P1) as hresult
  #ifdef MyDebugX
  Cout("IDirectDraw.Release (2)" + chr$(13,10) + _
  " >> TDDRAW: "+hex$(cast(uinteger,TDDRAW),8))
  #endif
  return DD_OK
  DirectLock(DDMUTEX)  
  #ifndef Render_OpenGL  
  screen 0 
  #endif
  BACKBUFFER.DataPtr=0:FRONTBUFFER.DataPtr=0
  DirectUnlock(DDMUTEX)
  return DD_OK
end function
' ****************************************************************************************
UndefAll()
#define P1 TDDRAW as DirectDrawObject ptr
function IDirectDraw_3_Compact(P1) as hresult
  #ifdef MyDebugX
  Cout("IDirectDraw.Compact (3)" + chr$(13,10) + _
  " >> TDDRAW: "+hex$(cast(uinteger,TDDRAW),8))
  #endif  
  return DD_OK
end function
' ****************************************************************************************
UndefAll()
#define P1 TDDRAW as DirectDrawObject ptr
#define P2 dwFlags as dword
#define P3 LPDIRECTDRAWCLIPPER as ddClipperObject ptr ptr
#define P4 pUnkOuter as any ptr
function IDirectDraw_4_CreateClipper(P1,P2,P3,P4) as hresult
  DirectLock(DDMUTEX)
  #ifdef MyDebugX  
  Cout("IDirectDraw.CreateClipper (5)" + chr$(13,10) + _
  " > Object:"+hex$(cast(uinteger,TDDRAW))+ _  
  " ClipObject:"+hex$(cast(uinteger,LPDIRECTDRAWCLIPPER)))
  #endif  
  
  *LPDIRECTDRAWCLIPPER = new ddClipperobject
  ClipperFuncs(DDCLIPPER_FUNCS())
  
  dim as integer ENTRYCNT
  
  with **LPDIRECTDRAWCLIPPER
    .VTABLE = @DDCLIPPER_FUNCS(0)    
    .Interface = itClipper
  end with
  
  DirectUnlock(DDMUTEX)
  return DD_OK
  
end function
' ****************************************************************************************
UndefAll()
#define P1 TDDRAW as DirectDrawObject ptr
#define P2 dwFlags as dword
#define P3 lpColorTable as PaletteEntry ptr
#define P4 LPDIRECTDRAWPALETTE as ddPaletteObject ptr ptr
#define P5 pUnkOuter as any ptr
function IDirectDraw_5_CreatePalette(P1,P2,P3,P4,P5) as hresult
  DirectLock(DDMUTEX)
  #ifdef MyDebugX
  dim as string STMP
  if (dwFlags and DDPCAPS_1BIT)        then STMP += "1-bit "
  if (dwFlags and DDPCAPS_2BIT)        then STMP += "2-bit "
  if (dwFlags and DDPCAPS_4BIT)        then STMP += "4-bit "
  if (dwFlags and DDPCAPS_8BITENTRIES) then STMP += "as8bit "
  if (dwFlags and DDPCAPS_8BIT)        then STMP += "8-bit "
  if (dwFlags and DDPCAPS_ALLOW256)    then STMP += "AllEntries "
  Cout("IDirectDraw.CreatePalette (5)" + chr$(13,10) + _
  " > Object:"+hex$(cast(uinteger,TDDRAW))+ _
  " Table:"+hex$(cast(uinteger,lpColorTable))+ _
  " PalObject:"+hex$(cast(uinteger,LPDIRECTDRAWPALETTE))+" Flags:"+STMP)
  #endif  
  
  *LPDIRECTDRAWPALETTE = new ddPaletteObject
  PaletteFuncs(DDPALETTE_FUNCS())
  
  dim as integer ENTRYCNT
  if (dwFlags and DDPCAPS_1BIT) then ENTRYCNT = 2
  if (dwFlags and DDPCAPS_2BIT) then ENTRYCNT = 4
  if (dwFlags and DDPCAPS_4BIT) then ENTRYCNT = 16
  if (dwFlags and DDPCAPS_8BIT) then ENTRYCNT = 256
  
  with **LPDIRECTDRAWPALETTE
    .VTABLE = @DDPALETTE_FUNCS(0)
    .Interface = itPalette
    .Colors = ENTRYCNT
    for CNT as integer = 0 to ENTRYCNT-1
      .Pal(CNT).c.r = lpColorTable[CNT].peRed
      .Pal(CNT).c.g = lpColorTable[CNT].peGreen
      .Pal(CNT).c.b = lpColorTable[CNT].peBlue
    next CNT
  end with
  
  DirectUnlock(DDMUTEX)
  return DD_OK
  
end function
' ****************************************************************************************
UndefAll()
#define P1 TDDRAW as DirectDrawObject ptr
#define P2 lpDDSurfaceDesc as DDSURFACEDESC ptr
#define P3 lplpDDSurface as ddSurfaceObject ptr ptr
#define P4 pUnkOuter as any ptr
function IDirectDraw_6_CreateSurface(P1,P2,P3,P4) as hresult  
  #ifdef MyDebugX
  Cout("IDirectDraw.CreateSurface (6)" + chr$(13,10) + _
  " >> Object: "+hex$(cast(uinteger,TDDRAW),8)+ _
  " - lpDDSurfaceDesc: "+hex$(cast(integer,lpDDSurfaceDesc),8)+ _
  " - lplpDDSurface: "+hex$(cast(integer,lplpDDSurface),8))
  #endif    
  if lpDDSurfaceDesc = 0 or lplpDDSurface=0 then
    ddrawError(DDERR_INVALIDPARAMS)
  end if
  
  DirectLock(DDMUTEX)
  dim as byte PRIMARY  
  static as ddSurfaceObject PRIMARYSURFACE
  dim as integer iCaps
  
  scope
    dim as string STMP    
    with *lpDDSurfaceDesc    
      #ifdef MyDebugX
      lCout(" >> Size > width: " & .dwWidth & " - Height: " & .dwHeight)    
      #endif
      if (.dwflags and DDSD_CAPS) then        
        with lpDDSurfaceDesc->ddsCaps
          if (.dwcaps and DDSCAPS_PRIMARYSURFACE) then 
            PRIMARY = 1
          end if
          iCaps = .dwCaps          
          #ifdef MyDebugX
          STMP = ""
          if (.dwcaps and DDSCAPS_ALPHA)           then STMP += "OnlyAlpha "
          if (.dwcaps and DDSCAPS_ALLOCONLOAD)     then STMP += "AllocOnLoad "
          if (.dwcaps and DDSCAPS_BACKBUFFER)      then STMP += "BackBuffer "
          'if (.dwcaps and DDSCAPS_DYNAMIC)         then STMP += "Dynamic "
          if (.dwcaps and DDSCAPS_FLIP)            then STMP += "Flip "
          if (.dwcaps and DDSCAPS_FRONTBUFFER)     then STMP += "FrontBuffer "
          'if (.dwcaps and DDSCAPS_NOTUSERLOCKABLE) then STMP += "NotLock "
          if (.dwcaps and DDSCAPS_OVERLAY)         then STMP += "Overlay "
          if (.dwcaps and DDSCAPS_PALETTE)         then STMP += "Palette "
          if (.dwcaps and DDSCAPS_TEXTURE)         then STMP += "Texture "
          if (.dwcaps and DDSCAPS_PRIMARYSURFACE)  then STMP += "Primary "            
          'if (.dwcaps and DDSCAPS_READONLY)        then STMP += "ReadOnly "
          if (.dwcaps and DDSCAPS_SYSTEMMEMORY)    then STMP += "System "
          if (.dwcaps and DDSCAPS_VIDEOMEMORY)     then STMP += "Video "
          if (.dwcaps and DDSCAPS_WRITEONLY)       then STMP += "WriteOnly "
          lCout(" >> Capabilites > "+STMP)
          #endif
        end with
      end if            
      if (.dwflags and DDSD_PIXELFORMAT) then        
        with lpDDSurfaceDesc->ddpfPixelFormat
          #ifdef MyDebugX
          STMP = ""
          if (.dwflags and DDPF_ALPHA)           then STMP += "OnlyAlpha "
          if (.dwflags and DDPF_ALPHAPIXELS)     then STMP += "Alpha "
          if (.dwflags and DDPF_ALPHAPREMULT)    then STMP += "PreMul "
          if (.dwflags and DDPF_FOURCC)          then STMP += "FourCC "
          if (.dwflags and DDPF_ZBUFFER)         then STMP += "ZBuffer "
          if (.dwflags and DDPF_ZPIXELS)         then STMP += "ZPixels "
          if (.dwflags and DDPF_PALETTEINDEXED8) then STMP += "Palette "
          if (.dwflags and DDPF_RGB)             then STMP += "RGB "
          if STMP = "" then STMP = "--"
          lCout(" >> Pixel > bits: " & .dwRGBBitCount & " - flags: " & STMP)
          #endif
        end with
      end if
    end with
  end scope
  
  if DDSURFACE_FUNCS(0)=0 then
    SurfaceFuncs(DDSURFACE_FUNCS())
  end if  
  
  if PRIMARY then    
    dim as integer w,h,d,b,p,r
    screeninfo w,h,d,b,p,r
    w=640:h=480
    'printf(!"primary: w=%i h=%i d=%i b=%i p=%i r=%i\n",w,h,d,b,p,r)
    with  PRIMARYSURFACE
      .VTABLE = @DDSURFACE_FUNCS(0)
      .Interface = itSurface
      .wid = w
      .hei = h
      .bpp = d
      .pitch = p
      .Primary = 1      
      .DataPtr = RenderFrameBuffer
      *lplpDDSurface = cast(any ptr,@.VTABLE)
    end with
  else
    dim as ddSurfaceObject ptr MYSURFACE = new ddSurfaceObject
    *lplpDDSurface = MYSURFACE
    dim as integer w,h,d,b,p,r
    with *lpDDSurfaceDesc          
      w = .dwWidth
      h = .dwHeight
      d = .ddpfPixelFormat.dwRGBBitCount      
    end with
    if d = 15 then d = 16
    if d <> 16 and d<>8 then d=32    
    with *MYSURFACE      
      .VTABLE = @DDSURFACE_FUNCS(0)      
      .Interface = itSurface
      .Primary = 0      
      .wid = w      
      .hei = h      
      .bpp = d      
      #ifdef Render_OpenGL
        mt_ImageCreate(@.fbimage,w,h,0,d)        
      #else
        .fbImage = ImageCreate(w,h,0,d)        
        TotalMemory += ((.fbimage->pitch*.fbimage->height)+32):TotalAllocs += 1        
        #ifdef DebugMemory
        printf(!"Allocate %s:%i(%3.2g)\n",__FUNCTION__,__LINE__,TotalMemory/(1024*1024))
        #endif
      #endif
      .Desc = *lpDDSurfaceDesc
      .DataPtr = .fbimage+1      
      .pitch = .fbimage->pitch
      .ID = -1
      #ifdef Render_OpenGL
      if (icaps and (DDSCAPS_VIDEOMEMORY or DDSCAPS_TEXTURE)) then
        if .bpp <> 16 and .bpp <> 8 then
          #ifdef MyDebugErr
          lCout("Tried to create an unknown accelerated texture!!!")
          #endif
        end if
        mt_glGenTextures(.wid,.hei,.bpp,1,@.ID)        
      end if      
      #endif

    end with    
  end if
  #ifdef MyDebugZ
  lCout(" > Created Surface: " & hex$(cast(uinteger,*lplpDDSurface),8))
  #endif
  DirectUnlock(DDMUTEX)
  return DD_OK
end function
' ****************************************************************************************
UndefAll()
#define P1 TDDRAW as DirectDrawObject ptr
#define P2 dwFlags as dword
#define P3 lpDDSurfaceDesc as DDSURFACEDESC ptr
#define P4 lpContext as any ptr
#define P5 lpEnumModesCallback as any ptr
function IDirectDraw_8_EnumDisplayModes(P1,P2,P3,P4,P5) as hresult
  dim F as function (as DDSURFACEDESC ptr, as any ptr) as hresult
  dim as integer SMODE
  dim as DDSURFACEDESC DESC
  dim as integer BITS,ENUMCOUNT
  
  #ifdef MyDebugX
  Cout("IDirectDraw.EnumDisplayModes (8)" + chr$(13,10) + _
  " >> TDDRAW: "+hex$(cast(uinteger,TDDRAW),8)+ _
  " - Surface: "+hex$(cast(integer,lpDDSurfaceDesc),8)+ _
  " - Callback: "+hex$(cast(integer,lpEnumModesCallback),8)+ _
  " - Context: " & lpContext)
  #endif
  
  if lpEnumModesCallback=0 then ddrawError(DDERR_INVALIDPARAMS)
  DirectLock(DDMUTEX)
  F=lpEnumModesCallback
  if lpDDSurfaceDesc then
    BITS = lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount
  end if
  
  with DESC
    .dwSize = sizeof(DDSURFACEDESC)
    .dwFlags = DDSD_ALL
    .dwBackBufferCount = 2
    .dwRefreshRate = 60
    .ddscaps.dwCaps = -1
    'with DESC.ddpfPixelFormat
    '  .dwflags = DDPF_RGB or DDPF_PALETTEINDEXEDTO8 or DDPF_PALETTEINDEXED8
    '  .dwRGBBitCount = 8      
    'end with    
  end with
  
  do
    if BITS=0 or BITS=8 then
      with DESC.ddpfPixelFormat
        .dwflags = DDPF_RGB or DDPF_PALETTEINDEXED8
        .dwRGBBitCount = 8            
      end with
      #if 0
        SMODE = ScreenList(8)  
        while SMODE
          with DESC
            .dwWidth = HiWord(SMODE)
            .dwHeight = LoWord(SMODE)
            '.lXPitch = 1
            .lPitch = .DwWidth*1 'lXPitch
            '.dwSurfaceSize = .lPitch*.dwHeight 
            'lCout("Mode: " & .dwWidth & "x" & .dwHeight & "x8@60")
          end with      
          ENUMCOUNT += 1
          if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
          SMODE = ScreenList()
        wend
      #else
        with DESC
          ENUMCOUNT += 8
          .dwWidth = 320 : .dwHeight = 200: .lPitch = .DwWidth: if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
          .dwWidth = 320 : .dwHeight = 240: .lPitch = .DwWidth: if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
          .dwWidth = 400 : .dwHeight = 300: .lPitch = .DwWidth: if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
          .dwWidth = 512 : .dwHeight = 384: .lPitch = .DwWidth: if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
          .dwWidth = 640 : .dwHeight = 400: .lPitch = .DwWidth: if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
          .dwWidth = 640 : .dwHeight = 480: .lPitch = .DwWidth: if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
          .dwWidth = 800 : .dwHeight = 600: .lPitch = .DwWidth: if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
          .dwWidth = 1024 : .dwHeight = 768: .lPitch = .DwWidth: if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do          
        end with
      #endif          
    end if    
    if BITS=0 or BITS=16 then
      with DESC.ddpfPixelFormat
        .dwflags = DDPF_RGB
        .dwRGBBitCount = 16    
        .dwRBitMask        = &b1111100000000000
        .dwGBitMask        = &b0000011111100000
        .dwBBitMask        = &b0000000000011111
        .dwRGBAlphaBitMask = &b0000000000000000      
      end with
      #if 0
        SMODE = ScreenList(16)  
        while SMODE
          with DESC
            .dwWidth = HiWord(SMODE)
            .dwHeight = LoWord(SMODE)
            '.lXPitch = 2
            .lPitch = .DwWidth*2 'lXPitch
            '.dwSurfaceSize = .lPitch*.dwHeight 
            'lCout("Mode: " & .dwWidth & "x" & .dwHeight & "x16@60")
          end with
          ENUMCOUNT += 1
          if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
          SMODE = ScreenList()
        wend
      #else      
        with DESC
          ENUMCOUNT += 8
          .dwWidth = 320 : .dwHeight = 200: .lPitch = .DwWidth*2: if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
          .dwWidth = 320 : .dwHeight = 240: .lPitch = .DwWidth*2: if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
          .dwWidth = 400 : .dwHeight = 300: .lPitch = .DwWidth*2: if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
          .dwWidth = 512 : .dwHeight = 384: .lPitch = .DwWidth*2: if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
          .dwWidth = 640 : .dwHeight = 400: .lPitch = .DwWidth*2: if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
          .dwWidth = 640 : .dwHeight = 480: .lPitch = .DwWidth*2: if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
          .dwWidth = 800 : .dwHeight = 600: .lPitch = .DwWidth*2: if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
          .dwWidth = 1024 : .dwHeight = 768: .lPitch = .DwWidth*2: if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
        end with
      #endif      
    end if    
    if BITS<>8 and BITS<>16 then  
      with DESC.ddpfPixelFormat
        .dwflags = DDPF_RGB or DDPF_ALPHAPIXELS
        .dwRGBBitCount = 32
        .dwRBitMask        = &b00000000111111110000000000000000
        .dwGBitMask        = &b00000000000000001111111100000000
        .dwBBitMask        = &b00000000000000000000000011111111
        .dwRGBAlphaBitMask = &b11111111000000000000000000000000
      end with
      #if 0
        SMODE = ScreenList(32)  
        while SMODE
          with DESC
            .dwWidth = HiWord(SMODE)
            .dwHeight = LoWord(SMODE)
            '.lXPitch = 4
            .lPitch = .DwWidth*4 'lXPitch        
            '.dwSurfaceSize = .lPitch*.dwHeight 
            'lCout("Mode: " & .dwWidth & "x" & .dwHeight & "x32@60")
          end with
          ENUMCOUNT += 1
          if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
          SMODE = ScreenList()
        wend      
      #else
        with DESC
          ENUMCOUNT += 8
          .dwWidth = 320 : .dwHeight = 200: .lPitch = .DwWidth*4: if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
          .dwWidth = 320 : .dwHeight = 240: .lPitch = .DwWidth*4: if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
          .dwWidth = 400 : .dwHeight = 300: .lPitch = .DwWidth*4: if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
          .dwWidth = 512 : .dwHeight = 384: .lPitch = .DwWidth*4: if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
          .dwWidth = 640 : .dwHeight = 400: .lPitch = .DwWidth*4: if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
          .dwWidth = 640 : .dwHeight = 480: .lPitch = .DwWidth*4: if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
          .dwWidth = 800 : .dwHeight = 600: .lPitch = .DwWidth*4: if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
          .dwWidth = 1024 : .dwHeight = 768: .lPitch = .DwWidth*4: if F(@DESC,lpContext) =  DDENUMRET_CANCEL then exit do
        end with
      #endif
    end if
  loop until 1
  
  #ifdef MyDebugX
  'LCout(" >> Enumerated " & ENUMCOUNT & " modes..." )
  #endif
  DirectUnlock(DDMUTEX)
  return DD_OK
  
end function
' ****************************************************************************************
UndefAll()
#define P1 TDDRAW as DirectDrawObject ptr
function IDirectDraw_10_FlipToGDISurface(P1) as hresult  
  #ifdef MyDebugX
  Cout("IDirectDraw.FlipToGDISurface (10)" + chr$(13,10) + _
  " >> TDDRAW: "+hex$(cast(uinteger,TDDRAW),8))
  #endif  
  DirectLock(DDMUTEX)  
  DirectUnlock(DDMUTEX)
  return DD_OK
end function
' ****************************************************************************************
UndefAll()
#define P1 TDDRAW as DirectDrawObject ptr
#define P2 lpDDDriverCaps as DDCAPS ptr
#define P3 lpDDEmulCaps as DDCAPS ptr
function IDirectDraw_11_GetCaps(P1,P2,P3) as hresult  
  #ifdef MyDebugX
  Cout("IDirectDraw.GetCaps (11)" + chr$(13,10) + _
  " >> TDDRAW: "+hex$(cast(uinteger,TDDRAW),8)+ _
  " - lpDDDriverCaps: "+hex$(cast(integer,lpDDDriverCaps),8)+ _
  " - lpDDEmulCaps: "+hex$(cast(integer,lpDDEmulCaps),8))
  #endif
  
  if TDDRAW=0 then ddrawError(DDERR_INVALIDOBJECT)
  if lpDDDriverCaps=0 and lpDDEmulCaps=0 then 
    #ifdef MyDebugZ
    lcout("Error: both driver and emulated caps are null (invalid params)")
    #endif
    ddrawError(DDERR_INVALIDPARAMS)
  end if
  
  #macro TempCaps()
  if 0 then '.dwSize <> sizeof(DDCAPS) then 
    #ifdef MyDebugZ
    lcout("Error: invalid size of DDCAPS (invalid params)")
    #endif
    ddrawError(DDERR_INVALIDPARAMS)
  end if    
  DirectLock(DDMUTEX)
  .dwCaps = not ( DDCAPS_NOHARDWARE or DDCAPS_ALIGNBOUNDARYDEST or DDCAPS_ALIGNBOUNDARYSRC or _
  DDCAPS_ALIGNSIZEDEST or DDCAPS_ALIGNSIZESRC or DDCAPS_ALIGNSTRIDE or DDCAPS_BANKSWITCHED or _
  DDCAPS_BLTQUEUE or DDCAPS_BLTFOURCC or DDCAPS_COLORKEYHWASSIST )
  .dwCaps2 = not DDCAPS2_NO2DDURING3DSCENE 
  .dwCKeyCaps = not DDCKEYCAPS_DESTOVERLAYONEACTIVE
  .dwFXCaps = not DDFXCAPS_BLTARITHSTRETCHYN 
  .dwFXAlphaCaps = -1
  .dwPalCaps = -1
  .dwSVCaps = -1
  .dwVidMemTotal = 16*1024*1024
  .dwVidMemFree = 16*1024*1024
  .dwMaxVisibleOverlays = 16  
  #endMacro
  
  if lpDDDriverCaps then
    with *lpDDDriverCaps      
      TempCaps()
    end with
  end if
  if lpDDEmulCaps then
    with *lpDDEmulCaps
      TempCaps()
    end with
  end if
  DirectUnlock(DDMUTEX)
  return DD_OK
end function
' ****************************************************************************************
UndefAll()
#define P1 TDDRAW as DirectDrawObject ptr
#define P2 lpDDSurfaceDesc as DDSURFACEDESC ptr
function IDirectDraw_12_GetDisplayMode(P1,P2) as hresult
  #ifdef MyDebugX
  Cout("IDirectDraw.GetDisplayMode (12)" + chr$(13,10) + _
  " >> TDDRAW: "+hex$(cast(uinteger,TDDRAW),8))
  #endif
  DirectLock(DDMUTEX)
  dim as integer w,h,d,b,p,r
  if RenderMutex then MutexLock(RenderMutex)
  screeninfo w,h,d,b,p,r  
  w=640:h=480
  if RenderMutex then MutexUnlock(RenderMutex)
  'printf(!"display mode: w=%i h=%i d=%i b=%i p=%i r=%i\n",w,h,d,b,p,r)
  if BACKBUFFER.DataPtr=0 then
    w=640:h=480:d=16:b=2:p=4:r=0
  end if
  
  with *lpDDSurfaceDesc
    .dwSize = sizeof(DDSURFACEDESC)
    .dwFlags = DDSD_ALL
    .dwBackBufferCount = 1
    .dwRefreshRate = r
    .ddscaps.dwCaps = -1
    .dwWidth = w
    .dwHeight = h
    .lPitch = p
    '.lXPitch = b
  end with  
  
  with lpDDSurfaceDesc->ddpfPixelFormat
    select case d
    case 8     
      .dwflags = DDPF_RGB or DDPF_PALETTEINDEXEDTO8 or DDPF_PALETTEINDEXED8
      .dwRGBBitCount = 8      
    case 16
      .dwflags = DDPF_RGB
      .dwRGBBitCount = 16    
      .dwRBitMask        = &b1111100000000000
      .dwGBitMask        = &b0000011111100000
      .dwBBitMask        = &b0000000000011111
      .dwRGBAlphaBitMask = &b0000000000000000
    case 32
      .dwflags = DDPF_RGB or DDPF_ALPHAPIXELS
      .dwRGBBitCount = 32
      .dwRBitMask        = &b00000000111111110000000000000000
      .dwGBitMask        = &b00000000000000001111111100000000
      .dwBBitMask        = &b00000000000000000000000011111111
      .dwRGBAlphaBitMask = &b11111111000000000000000000000000
    end select
  end with
  DirectUnlock(DDMUTEX)
  return DD_OK
end function
' ****************************************************************************************
UndefAll()
#define P1 TDDRAW as DirectDrawObject ptr
function IDirectDraw_19_RestoreDisplayMode(P1) as hresult  
  #ifdef MyDebugX
  Cout("IDirectDraw.RestoreDisplayMode (19)" + chr$(13,10) + _
  " >> TDDRAW: "+hex$(cast(uinteger,TDDRAW),8))  
  #endif  
  DirectLock(DDMUTEX)  
  DirectUnlock(DDMUTEX)  
  return DD_OK
end function
' ****************************************************************************************
UndefAll()
#define P1 TDDRAW as DirectDrawObject ptr
#define P2 HWND as hwnd
#define P3 DWFLAGS as dword
function IDirectDraw_20_SetCooperativeLevel(P1,P2,P3) as hresult
  DirectLock(DDMUTEX)
  dim as string SFLAGS
  dim as hresult RESU
  if (DWFLAGS and DDSCL_ALLOWMODEX)      then SFLAGS += "modex "
  if (DWFLAGS and DDSCL_ALLOWREBOOT)     then SFLAGS += "reboot "  
  if (DWFLAGS and DDSCL_EXCLUSIVE)       then SFLAGS += "exclusive "
  if (DWFLAGS and DDSCL_FULLSCREEN)      then SFLAGS += "full "
  if (DWFLAGS and DDSCL_NORMAL)          then SFLAGS += "normal "
  if (DWFLAGS and DDSCL_NOWINDOWCHANGES) then SFLAGS += "block"  
  #ifdef MyDebugX
  Cout("IDirectDraw.SetCooperativeLevel (20)" + chr$(13,10) + _
  " >> TDDRAW: "+hex$(cast(uinteger,TDDRAW),8)+" - HWND: "+ _
  hex$(cast(integer,HWND),8)+" - Flags: "+SFLAGS)
  #endif  
  DDRAWCOOP.Thread = GetCurrentThreadID()  
  'Messagebox(null,"T: " & GetCurrentThreadID,"Cooperative",MB_SYSTEMMODAL)
    
  DDRAWCOOP.hwnd = HWND
  if GetForegroundWindow() <> DDRAWCOOP.hwnd then
    SetForegroundWindow(DDRAWCOOP.hwnd)
  end if
  ShowWindow(DDRAWCOOP.hwnd,SW_SHOW)
  DirectUnlock(DDMUTEX)  
  
  return DD_OK  
end function
' ****************************************************************************************
UndefAll()
#define P1 TDDRAW as DirectDrawObject ptr
#define P2 dwWidth as dword
#define P3 dwHeight as dword
#define P4 dwBPP as dword
#define P5 dwRefreshRate as dword
#define P6 dwFlags as dword
function IDirectDraw_21_SetDisplayMode(P1,P2,P3,P4) as hresult
  DirectLock(DDMUTEX)
  #ifdef MyDebugX
  Cout("IDirectDraw.SetDisplayMode (21)" + chr$(13,10) + _
  " >> Mode: " & dwWidth & "x" & dwHeight & "x" & dwBPP)
  #endif  
  dim as integer FLAG
  if dwWidth<>BACKBUFFER.wid or dwHeight<>BACKBUFFER.hei or dwHeight<>BACKBUFFER.bpp then
    'screencontrol(fb.SET_DRIVER_NAME,"gdi")
    var FLAGS = fb.GFX_NO_SWITCH or fb.gfx_no_frame or fb.gfx_high_priority    
    #ifdef Render_OpenGL
      mt_Screenres(dwWidth,dwHeight,dwBpp,1,FLAGS)      
    #else
      screenres dwWidth,dwHeight,dwBPP,1,FLAGS      
    #endif      
    RenderFrameBuffer = screenptr
    dim as integer x,y    
    screencontrol(fb.GET_WINDOW_HANDLE,*cptr(integer ptr,@FBWND))    
    screencontrol(fb.GET_WINDOW_POS,x,y)
    DDRAWCOOP.wwid=dwWidth:DDRAWCOOP.whei=dwHeight
    DDRAWCOOP.wposx=x:DDRAWCOOP.wposy=y    
    fbGfxResize(True)
  end if  
  if DDSURFACE_FUNCS(0)=0 then
    SurfaceFuncs(DDSURFACE_FUNCS())
  end if  
  with BACKBUFFER
    if .fbImage then imagedestroy(.fbimage):.fbimage=0
    .wid = dwWidth
    .hei = dwHeight
    .bpp = dwBPP
    .pitch = dwWidth*(dwBPP/8)
    .VTABLE = @DDSURFACE_FUNCS(0)
    .Interface = itSurface
    .Primary = 1
    .BackBuffer = 1
    .fbImage = 0       
    .DataPtr = RenderFrameBuffer    
  end with
    
  DirectUnlock(DDMUTEX)
  return DD_OK
end function