'   0 IDirectPlay3A_QueryInterface(p,a,b)                 (p)->lpVtbl->QueryInterface(p,a,b)                 
'   1 IDirectPlay3A_AddRef(p)                             (p)->lpVtbl->AddRef(p)                             
'   2 IDirectPlay3A_Release(p)                            (p)->lpVtbl->Release(p)                            
'   3 IDirectPlay3A_AddPlayerToGroup(p,a,b)               (p)->lpVtbl->AddPlayerToGroup(p,a,b)               
'   4 IDirectPlay3A_Close(p)                              (p)->lpVtbl->Close(p)                              
'   5 IDirectPlay3A_CreateGroup(p,a,b,c,d,e)              (p)->lpVtbl->CreateGroup(p,a,b,c,d,e)              
'   6 IDirectPlay3A_CreatePlayer(p,a,b,c,d,e,f)           (p)->lpVtbl->CreatePlayer(p,a,b,c,d,e,f)           
'   7 IDirectPlay3A_DeletePlayerFromGroup(p,a,b)          (p)->lpVtbl->DeletePlayerFromGroup(p,a,b)          
'   8 IDirectPlay3A_DestroyGroup(p,a)                     (p)->lpVtbl->DestroyGroup(p,a)                     
'   9 IDirectPlay3A_DestroyPlayer(p,a)                    (p)->lpVtbl->DestroyPlayer(p,a)                    
'  10 IDirectPlay3A_EnumGroupPlayers(p,a,b,c,d,e)         (p)->lpVtbl->EnumGroupPlayers(p,a,b,c,d,e)         
'  11 IDirectPlay3A_EnumGroups(p,a,b,c,d)                 (p)->lpVtbl->EnumGroups(p,a,b,c,d)                 
'  12 IDirectPlay3A_EnumPlayers(p,a,b,c,d)                (p)->lpVtbl->EnumPlayers(p,a,b,c,d)                
'  13 IDirectPlay3A_EnumSessions(p,a,b,c,d,e)             (p)->lpVtbl->EnumSessions(p,a,b,c,d,e)             
'  14 IDirectPlay3A_GetCaps(p,a,b)                        (p)->lpVtbl->GetCaps(p,a,b)                        
'  15 IDirectPlay3A_GetMessageCount(p,a,b)                (p)->lpVtbl->GetMessageCount(p,a,b)                
'  16 IDirectPlay3A_GetGroupData(p,a,b,c,d)               (p)->lpVtbl->GetGroupData(p,a,b,c,d)               
'  17 IDirectPlay3A_GetGroupName(p,a,b,c)                 (p)->lpVtbl->GetGroupName(p,a,b,c)                 
'  18 IDirectPlay3A_GetPlayerAddress(p,a,b,c)             (p)->lpVtbl->GetPlayerAddress(p,a,b,c)             
'  19 IDirectPlay3A_GetPlayerCaps(p,a,b,c)                (p)->lpVtbl->GetPlayerCaps(p,a,b,c)                
'  20 IDirectPlay3A_GetPlayerData(p,a,b,c,d)              (p)->lpVtbl->GetPlayerData(p,a,b,c,d)              
'  21 IDirectPlay3A_GetPlayerName(p,a,b,c)                (p)->lpVtbl->GetPlayerName(p,a,b,c)                
'  22 IDirectPlay3A_GetSessionDesc(p,a,b)                 (p)->lpVtbl->GetSessionDesc(p,a,b)                 
'  23 IDirectPlay3A_Initialize(p,a)                       (p)->lpVtbl->Initialize(p,a)                       
'  24 IDirectPlay3A_Open(p,a,b)                           (p)->lpVtbl->Open(p,a,b)                           
'  25 IDirectPlay3A_Receive(p,a,b,c,d,e)                  (p)->lpVtbl->Receive(p,a,b,c,d,e)                  
'  26 IDirectPlay3A_Send(p,a,b,c,d,e)                     (p)->lpVtbl->Send(p,a,b,c,d,e)                     
'  27 IDirectPlay3A_SetGroupData(p,a,b,c,d)               (p)->lpVtbl->SetGroupData(p,a,b,c,d)               
'  28 IDirectPlay3A_SetGroupName(p,a,b,c)                 (p)->lpVtbl->SetGroupName(p,a,b,c)                 
'  29 IDirectPlay3A_SetPlayerData(p,a,b,c,d)              (p)->lpVtbl->SetPlayerData(p,a,b,c,d)              
'  30 IDirectPlay3A_SetPlayerName(p,a,b,c)                (p)->lpVtbl->SetPlayerName(p,a,b,c)                
'  31 IDirectPlay3A_SetSessionDesc(p,a,b)                 (p)->lpVtbl->SetSessionDesc(p,a,b)                 
'  32 IDirectPlay3A_AddGroupToGroup(p,a,b)                (p)->lpVtbl->AddGroupToGroup(p,a,b)                
'  33 IDirectPlay3A_CreateGroupInGroup(p,a,b,c,d,e,f)     (p)->lpVtbl->CreateGroupInGroup(p,a,b,c,d,e,f)     
'  34 IDirectPlay3A_DeleteGroupFromGroup(p,a,b)           (p)->lpVtbl->DeleteGroupFromGroup(p,a,b)           
'  35 IDirectPlay3A_EnumConnections(p,a,b,c,d)            (p)->lpVtbl->EnumConnections(p,a,b,c,d)            
'  36 IDirectPlay3A_EnumGroupsInGroup(p,a,b,c,d,e)        (p)->lpVtbl->EnumGroupsInGroup(p,a,b,c,d,e)        
'  37 IDirectPlay3A_GetGroupConnectionSettings(p,a,b,c,d) (p)->lpVtbl->GetGroupConnectionSettings(p,a,b,c,d) 
'  38 IDirectPlay3A_InitializeConnection(p,a,b)           (p)->lpVtbl->InitializeConnection(p,a,b)           
'  39 IDirectPlay3A_SecureOpen(p,a,b,c,d)                 (p)->lpVtbl->SecureOpen(p,a,b,c,d)                 
'  40 IDirectPlay3A_SendChatMessage(p,a,b,c,d)            (p)->lpVtbl->SendChatMessage(p,a,b,c,d)            
'  41 IDirectPlay3A_SetGroupConnectionSettings(p,a,b,c)   (p)->lpVtbl->SetGroupConnectionSettings(p,a,b,c)   
'  42 IDirectPlay3A_StartSession(p,a,b)                   (p)->lpVtbl->StartSession(p,a,b)                   
'  43 IDirectPlay3A_GetGroupFlags(p,a,b)                  (p)->lpVtbl->GetGroupFlags(p,a,b)                  
'  44 IDirectPlay3A_GetGroupParent(p,a,b)                 (p)->lpVtbl->GetGroupParent(p,a,b)                 
'  45 IDirectPlay3A_GetPlayerAccount(p,a,b,c,d)           (p)->lpVtbl->GetPlayerAccount(p,a,b,c,d)           
'  46 IDirectPlay3A_GetPlayerFlags(p,a,b)                 (p)->lpVtbl->GetPlayerFlags(p,a,b)                 
'                                                                                                            
' ****************************************************************************************

const DirectPlayPort = 47624
'#define DirectPlayTCP

function iDirectPlay3APrototype() as hresult
  #ifdef DebugFatal
  messagebox(null,"IDirectPlay3A::#" & IDIRECTPLAY3APROTOID & " Function not implemented", _
  "DirectX",MB_SYSTEMMODAL or MB_ICONERROR)
  #endif      
  ExitProcess(1)
  return DPERR_UNAVAILABLE
  
  asm
    .balign 32
    _iDirectPlay3AProtoTable_:  
    #macro ProtoNum(X,Y)
    mov dword ptr [IDIRECTPLAY3APROTOID],X
    call IDirectPlay3APrototype
    mov edx,[esp]
    add esp,(Y+4)
    jmp edx
    .balign 32
    #endmacro
    ProtoNum(00,12)
    ProtoNum(01,04)
    ProtoNum(02,04)
    ProtoNum(03,12)
    ProtoNum(04,04)
    ProtoNum(05,24)
    ProtoNum(06,28)
    ProtoNum(07,12)
    ProtoNum(08,08)
    ProtoNum(09,08)
    ProtoNum(10,24)
    ProtoNum(11,20)
    ProtoNum(12,20)
    ProtoNum(13,24)
    ProtoNum(14,12)
    ProtoNum(15,12)
    ProtoNum(16,20)
    ProtoNum(17,16)
    ProtoNum(18,16)
    ProtoNum(19,16)
    ProtoNum(20,20)
    ProtoNum(21,16)
    ProtoNum(22,12)
    ProtoNum(23,08)
    ProtoNum(24,12)
    ProtoNum(25,24)
    ProtoNum(26,24)
    ProtoNum(27,20)
    ProtoNum(28,16)
    ProtoNum(29,20)
    ProtoNum(30,16)
    ProtoNum(31,12)
    ProtoNum(32,12)
    ProtoNum(33,28)
    ProtoNum(34,12)
    ProtoNum(35,20)
    ProtoNum(36,24)
    ProtoNum(37,20)
    ProtoNum(38,12)
    ProtoNum(39,20)
    ProtoNum(40,20)
    ProtoNum(41,16)
    ProtoNum(42,12)
    ProtoNum(43,12)
    ProtoNum(44,12)
    ProtoNum(45,20)
    ProtoNum(46,12)
  end asm    
end function

#define DPlayError(A,B) iDirectPlay3Message(__FUNCTION__,B,A): return B
sub iDirectPlay3Message(sPre as string,iError as integer,iPos as integer)
  #ifdef CtlDebugDPLAYerror
  var sText = "UnkErr #" & iError,sPos=" line: " & iPos
  Select case iError
  case DPERR_ACCESSDENIED            : sText = "DPERR_ACCESSDENIED"
  case DPERR_ALREADYINITIALIZED      : sText = "DPERR_ALREADYINITIALIZED"
  case DPERR_AUTHENTICATIONFAILED    : sText = "DPERR_AUTHENTICATIONFAILED"
  case DPERR_BUFFERTOOSMALL          : sText = "DPERR_BUFFERTOOSMALL"
  case DPERR_CANNOTCREATESERVER      : sText = "DPERR_CANNOTCREATESERVER"
  case DPERR_CANTADDPLAYER           : sText = "DPERR_CANTADDPLAYER"
  case DPERR_CANTCREATEPLAYER        : sText = "DPERR_CANTCREATEPLAYER"
  case DPERR_CANTLOADCAPI            : sText = "DPERR_CANTLOADCAPI"
  case DPERR_CANTLOADSECURITYPACKAGE : sText = "DPERR_CANTLOADSECURITYPACKAGE"
  case DPERR_CANTLOADSSPI            : sText = "DPERR_CANTLOADSSPI"
  case DPERR_CONNECTING              : sText = "DPERR_CONNECTING"
  case DPERR_CONNECTIONLOST          : sText = "DPERR_CONNECTIONLOST"
  case DPERR_ENCRYPTIONFAILED        : sText = "DPERR_ENCRYPTIONFAILED"
  case DPERR_ENCRYPTIONNOTSUPPORTED  : sText = "DPERR_ENCRYPTIONNOTSUPPORTED"
  case DPERR_INVALIDFLAGS            : sText = "DPERR_INVALIDFLAGS"
  case DPERR_INVALIDPARAMS           : sText = "DPERR_INVALIDPARAMS"
  case DPERR_INVALIDPASSWORD         : sText = "DPERR_INVALIDPASSWORD"
  case DPERR_INVALIDPLAYER           : sText = "DPERR_INVALIDPLAYER"
  case DPERR_LOGONDENIED             : sText = "DPERR_LOGONDENIED"
  case DPERR_NOCONNECTION            : sText = "DPERR_NOCONNECTION"
  case DPERR_NOMESSAGES              : sText = "DPERR_NOMESSAGES"
  case DPERR_NONEWPLAYERS            : sText = "DPERR_NONEWPLAYERS"
  case DPERR_NOSESSIONS              : sText = "DPERR_NOSESSIONS"
  case DPERR_SIGNFAILED              : sText = "DPERR_SIGNFAILED"
  case DPERR_TIMEOUT                 : sText = "DPERR_TIMEOUT"
  case DPERR_UNINITIALIZED           : sText = "DPERR_UNINITIALIZED"
  case DPERR_USERCANCEL              : sText = "DPERR_USERCANCEL"
  end select  
  ccout(sPre+" "+sText+" "+sPos)
  #endif
  if iError = DPERR_NOMESSAGES then
    SwitchToThread()
  else
    SleepEx(1,1)
  end if
end sub
' ****************************************************************************************
UndefAll()
#define P1 pThis as iDirectPlay3AObject ptr
#define P2 IID as GUID ptr
#define P3 IOBJECT as any ptr ptr
function iDirectPlay3A_0_QueryInterface(P1,P2,P3) as hresult
  #ifdef CtlDebugDPLAY
  dim as string sGUID = "{00000000-0000-0000-0000-000000000000}"
  if IID then sGUID = QueryGUIDString(IID)
  ccout("IDirectPlay3A.QueryInterface (0)" + NEWLINE + _
  " This: "+hex$(cast(uinteger,pThis),8)+ _
  " IID: "+sGUID+" Obj: 0x"+hex$(IOBJECT,8))
  #endif
  var sTMP="",iInterface = CheckGUID(IID,sTMP)
  select case iInterface
  case giIID_IDirectPlay2A, giIID_IDirectPlay3A    
    if DPLAYOBJ.sHost = "" then DPLAYOBJ.sHost = "mysoft.zapto.org" 
    '"192.168.0.111"
    #define A (offsetof(typeof(DPLAYOBJ),Interface+4))
    #define B (offsetof(typeof(DPLAYOBJ),_PRESERVE_))
    memset(pThis+A,0,(B-A))    
    *IOBJECT = @DPLAYOBJ : return S_OK
  case else
    return DPERR_NOINTERFACE
  end select
end function
' ****************************************************************************************
UndefAll()
#define P1 pThis as iDirectPlay3AObject ptr
function iDirectPlay3A_2_Release(P1) as hresult
  #ifdef CtlDebugDPLAY
  ccout("IDirectPlay3A.Release (2)" + chr$(13,10) + _
  " >> This: "+hex$(cast(uinteger,pThis),8))
  #endif
  if pThis then 
    with *cptr(iDirectPlay3AObject ptr,pThis)
      if .SockServer then hClose(.SockServer):.SockServer=0
      if .BuffServer then Deallocate(.BuffServer): .BuffServer=0
      .iSessions = 0
      for CNT as integer = 0 to ubound(.tPlayers)
        with .tPlayers(CNT)
          .idPlayer = 0
          if .lpData then deallocate(.lpData): .lpData=0
          if .SockPlayer then hClose(.SockPlayer): .SockPlayer=0          
          if .SUdpPlayer then hClose(.SUdpPlayer): .SUdpPlayer=0
          if .BuffPlayer then Deallocate(.BuffPlayer): .BuffPlayer=0: .SizePlayer=0          
        end with
      next CNT      
      with .tSession
        .dwMaxPlayers=0:.dwReserved1=0:.dwReserved2=0
        if .lpszSessionNameA then deallocate(.lpszSessionNameA)
        if .lpszPasswordA then deallocate(.lpszPasswordA)
        .lpszSessionNameA=0:.lpszPasswordA=0
      end with
      #define A (offsetof(typeof(*pThis),Interface+4))
      #define B (offsetof(typeof(*pThis),_PRESERVE_))
      memset(pThis+A,0,(B-A))
    end with
  end if
  return DD_OK
end function
' ****************************************************************************************
UndefAll()
#define P1 pThis        as iDirectPlay3AObject ptr
#define P2 lpidPlayer   as LPDPID
#define P3 lpPlayerName as LPDPNAME
#define P4 hEvent       as HANDLE
#define P5 lpData       as LPVOID
#define P6 dwDataSz     as DWORD
#define P7 dwFlags      as DWORD
function IDirectPlay3A_6_CreatePlayer(P1,P2,P3,P4,P5,P6,P7) as hresult
  #ifdef CtlDebugDPLAY
  scope
    dim sStruct as string
    if lpidPlayer then
      if isBadReadPtr(lpidPlayer,4) then
        sStruct += "    Player ID: 0x"+hex$(lpidPlayer,8)+" [BAD ACCESS]" !"\r\n"
      else
        sStruct += "    Player ID: 0x"+hex$(lpidPlayer,8)+" [" & *lpidPlayer & "]" !"\r\n"
      end if
    end if    
    if lpPlayerName  then
      with *lpPlayerName
        sStruct += "  Struct Size: " & .dwSize & " flags: ("+hex$(.dwFlags)+")" !"\r\n"
        sStruct += "  Player Name: ["+Zstr(.lpszLongNameA)+"] ["+Zstr(.lpszShortNameA)+"]" !"\r\n"
      end with
    end if
    sStruct += "       hEvent: "+hex$(hEvent,8)+!"\r\n"
    sStruct += "  Player Data: "+hex$(lpData,8)+!"\r\n"
    sStruct += "       DataSz: " & dwDataSz & !"\r\n"
    dim sFlags as string = "", iFlags as integer = dwFlags    
    if (iFlags and DPPLAYER_SERVERPLAYER) then iFlags -= &h100: sFlags += "SERVER "
    if (iFlags and DPPLAYER_SPECTATOR)    then iFlags -= &h200: sFlags += "SPEC "
    if (iFlags and DPPLAYER_LOCAL)        then iFlags -= &h008: sFlags += "LOCAL "
    if (iFlags and DPPLAYER_OWNER)        then iFlags -= &h010: sFlags += "OWNER "    
    if (iFlags)                           then sFlags += "0x"+hex$(iFlags)+" "   
    ccout("IDP3A.CreatePlayer(6) " _
    " flags:( "+sFlags+")" !"\r\n" + sStruct) '" _ 'THIS: 0x"+hex$(IDIRECTPLAY3A,8)+ _
  end scope
  #endif
  
  with *cptr(iDirectPlay3AObject ptr,pThis)
    if .Interface <> itDirectPlay then DPlayError(__LINE__,DPERR_INVALIDPARAMS)    
    if .SockServer = 0 then DPlayError(__LINE__,DPERR_NOSESSIONS)
    if lpidPlayer = 0 then DPlayError(__LINE__,DPERR_INVALIDPARAMS)    
    if .tSession.dwCurrentPlayers >= .tSession.dwMaxPlayers then
      DPlayError(__LINE__,DPERR_CANTADDPLAYER)
    end if
    for CNT as integer = 0 to ubound(.tPlayers)
      if .tPlayers(CNT).idPlayer then continue for
      #define NewPlayer() .tPlayers(CNT)
      *lpidPlayer = CNT+1
      memset(@NewPlayer(),0,sizeof(iDpPlayer))
      NewPlayer().idPlayer   = *lpidPlayer
      NewPlayer().hEvent     = hEvent
      NewPlayer().dwDataSz   = dwDataSz
      NewPlayer().dwFlags    = iif(.tSession.dwCurrentPlayers=0,DPENUMPLAYERS_SERVERPLAYER,DPENUMPLAYERS_REMOTE)
     'dwFlags
      NewPlayer().SockPlayer = null
      NewPlayer().sUDPPlayer = null
      if lpPlayerName then NewPlayer().PlayerName = *lpPlayerName
      if lpData then 
        NewPlayer().lpData = allocate(dwDataSz)
        memcpy(NewPlayer().lpData,lpData,dwDataSz)
      end if
      .tSession.dwCurrentPlayers += 1
      return DP_OK
    next CNT
    DPlayError(__LINE__,DPERR_CANTADDPLAYER)
  end with
  
end function
' ****************************************************************************************
UndefAll()
#define P1 pThis as iDirectPlay3AObject ptr
#define P2 idPlayer as DPID
function iDirectPlay3A_9_DestroyPlayer(P1,P2) as hresult
  #ifdef CtlDebugDPLAY
  ccout("IDirectPlay3A.DestroyPlayer(9)" + chr$(13,10) + _
  " >> This: "+hex$(cast(uinteger,pThis),8)+" Player: " & idPlayer)
  #endif
  if pThis then 
    with *cptr(iDirectPlay3AObject ptr,pThis)      
      for CNT as integer = 0 to ubound(.tPlayers)
        with .tPlayers(CNT)
          if .idPlayer = idPlayer then
            .idPlayer = 0
            if .lpData then deallocate(.lpData): .lpData=0
            if .SockPlayer then hClose(.SockPlayer): .SockPlayer=0          
            if .SUdpPlayer then hClose(.SUdpPlayer): .SUdpPlayer=0
            if .BuffPlayer then Deallocate(.BuffPlayer): .BuffPlayer=0: .SizePlayer=0
          end if
        end with
      next CNT
    end with
  end if
  return DP_OK
end function
' ****************************************************************************************
UndefAll()
#define P1 pThis                  as iDirectPlay3AObject ptr
#define P2 lpguidInstance         as LPGUID
#define P3 lpEnumPlayersCallback2 as LPDPENUMPLAYERSCALLBACK2
#define P4 lpContext              as LPVOID
#define P5 dwFlags                as DWORD
function IDirectPlay3A_12_EnumPlayers(P1,P2,P3,P4,P5) as hresult
  LastFrame=timer
  with *cptr(iDirectPlay3AObject ptr,pThis)
    #ifdef CtlDebugDPLAY
    scope        
      dim sFlags as string = "", iFlags as integer = dwFlags    
      if (iFlags  =  DPENUMPLAYERS_ALL)          then iFlags -= &h000: sFlags += "ALL "
      if (iFlags and DPENUMPLAYERS_GROUP)        then iFlags -= &h020: sFlags += "GROUP "
      if (iFlags and DPENUMPLAYERS_LOCAL)        then iFlags -= &h008: sFlags += "LOCAL "
      if (iFlags and DPENUMPLAYERS_REMOTE)       then iFlags -= &h010: sFlags += "REMOTE "
      if (iFlags and DPENUMPLAYERS_SERVERPLAYER) then iFlags -= &h100: sFlags += "SERVER "    
      if (iFlags and DPENUMPLAYERS_SESSION)      then iFlags -= &h080: sFlags += "SESSION "    
      if (iFlags and DPENUMPLAYERS_SPECTATOR)    then iFlags -= &h200: sFlags += "SPEC "        
      if (iFlags)                                then sFlags += "0x"+hex$(iFlags)+" "   
      ccout("IDP3A.EnumPlayers(12)" !"\r\n" _
      "  Instance: "+QueryGUIDString(lpguidInstance)+ _
      "  Callback: 0x"+hex$(lpEnumPlayersCallback2,8)+!"\r\n" _
      "  Context: "+hex$(lpContext)+ _
      "  Flags:( "+sFlags+") Players: " & .tSession.dwCurrentPlayers)     
    end scope
    #endif    
    if .Interface <> itDirectPlay then DPlayError(__LINE__,DPERR_INVALIDPARAMS)    
    if .SockServer = 0 then DPlayError(__LINE__,DPERR_NOSESSIONS)
    if lpEnumPlayersCallback2 = 0 then DPlayError(__LINE__,DPERR_INVALIDPARAMS)
    
    if .IsServer andalso .SockServer > 0 andalso hSelect(.SockServer) then
      var TempIP=0,TempPort=0
      var SockTemp = hAccept(.SockServer,TempIP,TempPort)
      TempPort = DirectPlayPort+1 'for now
      if .tSession.dwCurrentPlayers >= .tSession.dwMaxPlayers then
        hClose(SockTemp)
      else
        var pSess = @.tSession
        for CNT as integer = 0 to ubound(.tPlayers)
          with .tPlayers(CNT)
            if .idPlayer then continue for
            memset(@.idPlayer,0,sizeof(iDpPlayer))
            .idPlayer   = CNT+1
            .dwFlags    = DPENUMPLAYERS_REMOTE
            .SockPlayer = SockTemp 
            #ifndef DirectPlayTCP
            .SUdpPlayer = hOpenUDP()
            .AddrPlayer = TempIP
            .PortPlayer = TempPort
            hBind(.SUdpPlayer,.PortPlayer)
            ccout("UDP Client Connected: "+hIPtoString(.AddrPlayer)+":" & .PortPlayer)
            #endif
          end with          
          hSend(SockTemp,cast(any ptr,pSess),sizeof(.tSession))
          if .tSession.dwReserved1 then
            hSend(SockTemp,.tSession.lpszSessionNameA,.tSession.dwReserved1)
          end if
          if .tSession.dwReserved2 then
            hSend(SockTemp,.tSession.lpszPasswordA,.tSession.dwReserved2)
          end if
          .tSession.dwCurrentPlayers += 1
          exit for
        next CNT
      end if
    end if
    
    for CNT as integer = 0 to ubound(.tPlayers)
      with .tPlayers(CNT)
        if .idPlayer then
          #ifdef CtlDebugDPLAY
          ccout("Player #" & CNT)
          #endif
          var iResu = lpEnumPlayersCallback2(.idPlayer, _
          DPPLAYERTYPE_PLAYER,@.PlayerName,dwFlags,lpContext)
          if iResu = false then exit for
        end if
      end with
    next CNT
  end with
  screenunlock  
  SleepEx 1,1 
  #ifdef Render_OpenGL
  mt_Screensync()
  #endif
  return DP_OK
end function
' ****************************************************************************************
sub InputHostName(pThis as any ptr)
  with *cptr(iDirectPlay3AObject ptr,pThis)
    LastFrame=0
    var TempHost = InputBox(DDRAWCOOP.hwnd, _
    "Rally Championship","Enter server Hostname",.sHost,IB_TOPMOST)  
    while len(TempHost)    
        .sHost=TempHost
        var iIP = hResolve(.sHost)
        if iIP = 0 then 
          MessageBox(FBWND,"Failed to resolve '"+.sHost+"'", _
          "Rally Championship",MB_ICONERROR or MB_OK or MB_SYSTEMMODAL)          
          exit while
        end if
        .SockServer = hOpen(): LastFrame=0
        if hConnect(.SockServer,iIP,DirectPlayPort) = 0 then
          MessageBox(FBWND,"Failed to connect to '"+.sHost+":" & DirectPlayPort & "'", _
          "Rally Championship",MB_ICONERROR or MB_OK or MB_SYSTEMMODAL)
          hClose(.SockServer):.SockServer=0
          exit while
        end if
        dim iSz as integer, pData as any ptr, iRecv as integer
        dim as any ptr pSess = @.tSession
        for CNT as integer = 0 to 2
          iRecv = 0
          select case CNT
          case 0 'header
            iSz=sizeof(.tSession): pSess = @.tSession
          case 1 'Session Name
            if .tSession.dwSize <> iSz then 
              hClose(.SockServer): .SockServer=0
              MessageBox(FBWND,"no server or bad server found at '"+.sHost+":" & DirectPlayPort & "'", _
              "Rally Championship",MB_ICONERROR or MB_OK or MB_SYSTEMMODAL)
              exit while
            end if
            .tSession.lpszSessionNameA = 0
            if .tSession.dwReserved1 = 0 then continue for
            iSz = .tSession.dwReserved1
            pSess = allocate(iSz)
            .tSession.lpszSessionNameA = pSess
          case 2 'Session Password
            .tSession.lpszPasswordA = 0
            if .tSession.dwReserved2 = 0 then continue for
            iSz = .tSession.dwReserved2
            pSess = allocate(iSz)
            .tSession.lpszPasswordA = pSess          
          end select
          do until iRecv=iSz
            if .SockServer=0 then exit sub
            if hSelect(.SockServer) then
              var iTemp = hReceive(.SockServer,pSess+iRecv,iSz-iRecv)
              if iTemp <= 0 then
                hClose(.SockServer): .SockServer=0
                MessageBox(FBWND,"Failed to join session at '"+.sHost+":" & DirectPlayPort & "'", _
                "Rally Championship",MB_ICONERROR or MB_OK or MB_SYSTEMMODAL)
                exit while
              end if
              iRecv += iTemp
            end if
          loop        
        next CNT   
        for CNT as integer = 0 to ubound(.tPlayers)
          if .tPlayers(CNT).idPlayer then continue for
          #define NewPlayer() .tPlayers(CNT)        
          memset(@NewPlayer(),0,sizeof(iDpPlayer))
          NewPlayer().idPlayer   = CNT+1
          NewPlayer().hEvent     = 0 'hEvent
          NewPlayer().dwDataSz   = 0 'dwDataSz
          NewPlayer().dwFlags    = DPENUMPLAYERS_REMOTE 'dwFlags
          NewPlayer().SockPlayer = .SockServer
          #ifndef DirectPlayTCP
          NewPlayer().SUdpPlayer = hOpenUdp()          
          NewPlayer().AddrPlayer = iIP
          NewPlayer().PortPlayer = DirectPlayPort+1
          hBindUDP(NewPlayer().SUdpPlayer,NewPlayer().PortPlayer)
          ccOut("Connected to Server "+hIPtoString(NewPlayer().AddrPlayer)+":" & NewPlayer().PortPlayer)
          #endif
          'NewPlayer().PlayerName = *lpPlayerName
          'if lpData then 
          '  NewPlayer().lpData = allocate(dwDataSz)
          '  memcpy(NewPlayer().lpData,lpData,dwDataSz)
          'end if
          .iSessions = 1
          .tSession.dwCurrentPlayers = 1
          .iHost = 2: exit sub
        next CNT
        hClose(.SockServer): .SockServer=0
        MessageBox(FBWND,"Failed to enum remote players at '"+.sHost+":" & DirectPlayPort & "'", _
        "Rally Championship",MB_ICONERROR or MB_OK or MB_SYSTEMMODAL)
        exit while    
      .iHost = 2: exit sub
    wend
    sleepex 50,0:Setforegroundwindow(DDRAWCOOP.hwnd)
    sleepex 50,0:keybd_event(VK_ESCAPE,fb.SC_ESCAPE,0,0)
    sleepex 50,0:keybd_event(VK_ESCAPE,fb.SC_ESCAPE,KEYEVENTF_KEYUP,0)
    sleepex 500,0:.iHost = 0 
  end with
end sub
UndefAll()
#define P1 pThis     as iDirectPlay3AObject ptr
#define P2 lpsd      as DPSESSIONDESC2 ptr
#define P3 dwTimeout as dword
#define P4 pCallBack as LPDPENUMSESSIONSCALLBACK2
#define P5 lpContext as any ptr
#define P6 dwFlags   as DWORD
function iDirectPlay3A_13_EnumSessions(P1,P2,P3,P4,P5,P6) as hresult
  LastFrame=timer
  #ifdef CtlDebugDPLAY
  scope
    dim sStruct as string
    if lpsd then
      with *lpsd
        sStruct = _
        "  dwSize      : " & .dwSize & !"\r\n" _
        "  dwFlags     : " & .dwFlags & !"\r\n" _
        "  GuidInstance: " & QueryGUIDString(@.guidInstance) & !"\r\n" _
        "  GuidApplicat: " & QueryGUIDString(@.guidApplication) & !"\r\n" _
        "  dwMaxPlayers: " & .dwMaxPlayers & !"\r\n" _
        "  dwCurPlayers: " & .dwCurrentPlayers & !"\r\n" _
        "  lpszSessName: " & ZStr(.lpszSessionNameA) & !"\r\n" _
        "  lpszPassword: " & ZStr(.lpszPasswordA) & !"\r\n" _
        "  (" & .dwReserved1 & "," & .dwReserved2 & "," & .dwUser1 & _
        "," & .dwUser2 & "," & .dwUser3 & "," & .dwUser4 & ")"
      end with
    end if
    dim sFlags as string = "", iFlags as integer = dwFlags    
    if (iFlags and DPENUMSESSIONS_AVAILABLE)        then iFlags -= &h01: sFlags += "AVAIL "
    if (iFlags and DPENUMSESSIONS_ALL)              then iFlags -= &h02: sFlags += "ALL "
    if (iFlags and DPENUMSESSIONS_ASYNC)            then iFlags -= &h10: sFlags += "ASYNC "
    if (iFlags and DPENUMSESSIONS_STOPASYNC)        then iFlags -= &h20: sFlags += "STPASY "
    if (iFlags and DPENUMSESSIONS_PASSWORDREQUIRED) then iFlags -= &h40: sFlags += "PASS "
    if (iFlags and DPENUMSESSIONS_RETURNSTATUS)     then iFlags -= &h80: sFlags += "STATUS "
    if (iFlags)                                      then sFlags += "0x"+hex$(iFlags)+" "    
    ccout("IDP3A.EnumSessions(13) "+" s:"+hex$(lpsd)+ _ 'THIS: 0x"+hex$(IDIRECTPLAY3A,8)+ _
    " t:" & dwTimeout & " cb:"+hex$(pCallBack)+" ct:"+hex$(lpContext)+" f:( "+sFlags+")" + !"\r\n" + sStruct )
  end scope
  #endif
  sleepex(50,1)
  with *cptr(iDirectPlay3AObject ptr,pThis)
    if .Interface <> itDirectPlay then DPlayError(__LINE__,DPERR_INVALIDPARAMS)
    if .iSessions then
      if pCallBack(@.tSession,@dwTimeout,0,lpContext) then
        pCallBack(null,@dwTimeout,DPESC_TIMEDOUT,lpContext)      
      end if
      return DP_OK
    end if    
  
    if .iHost=0 then
      screenunlock
      .iHost=1: .pHost = ThreadCreate( @InputHostName , pThis )
    else    
      sleepex(100,1)
      if .iHost=2 then
        ccout("Hostname: '"+.sHost+"'")
      end if
      screenunlock
      #ifdef Render_OpenGL
      mt_Screensync()
      #endif
      if .iHost=3 then
        .iHost=0: DPlayError(__LINE__,DPERR_USERCANCEL)
      end if
    end if
  end with
  return DPERR_CONNECTING
end function
' ****************************************************************************************
UndefAll()
#define P1 pThis        as iDirectPlay3AObject ptr
#define P2 pSessionDesc as DPSESSIONDESC2 ptr
#define P3 dwFlags      as dword
function iDirectPlay3A_24_Open(P1,P2,P3) as hresult
  LastFrame=timer
  #ifdef CtlDebugDPLAY
  scope
    with *pSessionDesc
      dim sStruct as string = _
      "  dwSize      : " & .dwSize & !"\r\n" _
      "  dwFlags     : " & .dwFlags & !"\r\n" _
      "  GuidInstance: " & QueryGUIDString(@.guidInstance) & !"\r\n" _
      "  GuidApplicat: " & QueryGUIDString(@.guidApplication) & !"\r\n" _
      "  dwMaxPlayers: " & .dwMaxPlayers & !"\r\n" _
      "  dwCurPlayers: " & .dwCurrentPlayers & !"\r\n" _
      "  lpszSessName: " & ZStr(.lpszSessionNameA) & !"\r\n" _
      "  lpszPassword: " & ZStr(.lpszPasswordA) & !"\r\n" _
      "  (" & .dwReserved1 & "," & .dwReserved2 & "," & .dwUser1 & _
      "," & .dwUser2 & "," & .dwUser3 & "," & .dwUser4 & ")"
    end with
    dim sFlags as string = "", iFlags as integer = dwFlags    
    if (iFlags and DPOPEN_JOIN)   then iFlags -= &h01: sFlags += "JOIN "
    if (iFlags and DPOPEN_CREATE) then iFlags -= &h02: sFlags += "CREATE "
    if (iFlags and &h80)          then iFlags -= &h80: sFlags += "STATUS "
    if (iFlags)                   then sFlags += "0x"+hex$(iFlags)+" "
    ccout("IDP3A.Open(24) "+ _ 'THIS: 0x"+hex$(IDIRECTPLAY3A,8)+ _
    " Sess:"+hex$(pSessionDesc)+" Flags:( "+SFlags+")" + !"\r\n" + sStruct )    
  end scope
  #endif
  with *cptr(iDirectPlay3AObject ptr,pThis)
    if .Interface <> itDirectPlay then DPlayError(__LINE__,DPERR_INVALIDPARAMS)
    .iHost = 0: .pHost = 0
    if (dwFlags and DPOPEN_RETURNSTATUS) then
      DPlayError(__LINE__,DPERR_ACCESSDENIED)
    elseif (dwFlags and DPOPEN_JOIN) then
      if .SockServer=0 or .iSessions=0 then DPlayError(__LINE__,DPERR_NOSESSIONS)
      if .tSession.dwCurrentPlayers >= .tSession.dwMaxPlayers then
        ccout("c:" & .tSession.dwCurrentPlayers & "  m:" & .tSession.dwMaxPlayers)
        DPlayError(__LINE__,DPERR_CANTCREATEPLAYER)
      end if
      pSessionDesc = @.tSession
      return DP_OK      
    elseif (dwFlags and DPOPEN_CREATE) then
      if .SockServer then DPlayError(__LINE__,DPERR_ALREADYINITIALIZED)
      .IsServer = true
      pSessionDesc->dwCurrentPlayers = 0 
      pSessionDesc->guidInstance = type(itDirectPlay,1)
      .tSession = *pSessionDesc
      .tSession.dwReserved1=0:.tSession.dwReserved2=0
      if .tSession.lpszSessionNameA then
        .tSession.dwReserved1 = strlen(.tSession.lpszSessionNameA)
        .tSession.lpszSessionNameA = allocate(.tSession.dwReserved1)
        memcpy(.tSession.lpszSessionNameA,pSessionDesc->lpszSessionNameA,.tSession.dwReserved1)
      end if
      if .tSession.lpszPasswordA then
        .tSession.dwReserved2 = strlen(.tSession.lpszPasswordA)
        .tSession.lpszPasswordA = allocate(.tSession.dwReserved2)
        memcpy(.tSession.lpszPasswordA,pSessionDesc->lpszPasswordA,.tSession.dwReserved2)
      end if      
      if .tSession.dwMaxPlayers < 1 then DPlayError(__LINE__,DPERR_INVALIDPARAMS)
      .SockServer = hOpen()
      .AddrServer = hResolve("192.168.0.111")
      .PortServer = DirectPlayPort
      if hBind(.SockServer,.PortServer)=0 or hListen(.SockServer)=0 then
        hClose(.SockServer): .SockServer = 0
        DPlayError(__LINE__,DPERR_CANNOTCREATESERVER )
      end if
      return DP_OK
    else      
      DPlayError(__LINE__,DPERR_INVALIDFLAGS)
    end if
  end with
  return DP_OK
end function 
' ****************************************************************************************
UndefAll()
#define P1 pThis        as iDirectPlay3AObject ptr
#define P2 lpidFrom     as LPDPID
#define P3 lpidTo       as LPDPID
#define P4 dwFlags      as DWORD
#define P5 lpData       as LPVOID
#define P6 lpdwDataSize as LPDWORD
function iDirectPlay3A_25_Receive(P1,P2,P3,P4,P5,P6) as hresult
  #ifdef CtlDebugNetworkRecv
  scope
    dim sFlags as string = "", iFlags as integer = dwFlags    
    if (iFlags and DPRECEIVE_ALL)         then iFlags -= &h1: sFlags += "ALL "
    if (iFlags and DPRECEIVE_PEEK)        then iFlags -= &h8: sFlags += "PEEK "
    if (iFlags and DPRECEIVE_TOPLAYER)    then iFlags -= &h2: sFlags += "TO "
    if (iFlags and DPRECEIVE_FROMPLAYER)  then iFlags -= &h4: sFlags += "FROM "    
    if (iFlags)                           then sFlags += "0x"+hex$(iFlags)+" "   
    ccout("IDP3A.Receive(25)" !"\r\n" _
    "  From: 0x"+hex$(lpidFrom)+"(" & *lpidFrom & ")" + _
    "  To: 0x"+hex$(lpidTo)+"(" & *lpidTo & ")" + _
    "  Flags:( "+sFlags+")" !"\r\n" _
    "  Data: "+hex$(lpData,8)+ _
    "  DataSz: " & *lpdwDataSize & " [0x"+hex$(lpdwDataSize,8)+"]")
    'sleepex 500,1    
  end scope
  #endif
  
  if (dwFlags <> DPRECEIVE_FROMPLAYER) then
    messagebox(null,"Receiving system message?","???",MB_SYSTEMMODAL)
  end if
  
  with *cptr(iDirectPlay3AObject ptr,pThis)
    if .Interface <> itDirectPlay then DPlayError(__LINE__,DPERR_INVALIDPARAMS)
    var iFrom = (*lpidFrom)-1
    #ifdef CtlDebugNetworkRecv
    if iFrom <> 0 and iFrom <> 1 then
      ccout("Bad Source: " & (*lpidFrom))
      DPlayError(__LINE__,DPERR_INVALIDPARAMS)
    end if
    #endif
    with .tPlayers(iFrom)
      if .idPlayer=0 or lpData=0 then DPlayError(__LINE__,DPERR_INVALIDPLAYER)      
      if .SockPlayer=0 then 
        screenunlock: sleepex 1,1
        DPlayError(__LINE__,DPERR_CONNECTIONLOST)
      end if
      
      dim as integer iAddr,iPort      
      #ifdef DirectPlayTCP
      if .dwMsgSize = 0 then        
        if hSelect(.SockPlayer)=0 then         
          screenunlock:sleepex 1,1
          DPlayError(__LINE__,DPERR_NOMESSAGES)
        end if        
        if hReceive(.SockPlayer,cast(any ptr,@.dwMsgSize),sizeof(DWORD)) < 0 then        
          .dwMsgSize=0:hClose(.SockPlayer):.SockPlayer=0          
          screenunlock: sleepex 1,1
          messagebox(null,"Connection Lost? (receive1 from "+ _
          hIPtoString(.AddrPlayer)+":" & .PortPlayer & ")","Rally 4",MB_ICONWARNING or MB_SYSTEMMODAL)
          DPlayError(__LINE__,DPERR_CONNECTIONLOST)
        end if        
      end if      
      if .dwMsgSize > *lpdwDataSize then        
        *lpdwDataSize = .dwMsgSize
        DPlayError(__LINE__,DPERR_BUFFERTOOSMALL)
      end if            
      var iRecv=0,iResu=0      
      while iRecv < .dwMsgSize        
        iResu = hReceive(.SockPlayer,lpData+iRecv,.dwMsgSize-iRecv)                
        if iResu < 0 then
          .dwMsgSize=0:hClose(.SockPlayer):.SockPlayer=0        
          screenunlock: sleepex 1,1
          messagebox(null,"Connection Lost? (receive2 from "+ _
          hIPtoString(.AddrPlayer)+":" & .PortPlayer & ")","Rally 4",MB_ICONWARNING or MB_SYSTEMMODAL)
          DPlayError(__LINE__,DPERR_CONNECTIONLOST)
        end if
        iRecv += iResu
      wend 
      #else
      
      if hSelect(.SockPlayer) then
        .dwMsgSize=0:hClose(.SockPlayer):.SockPlayer=0  
        hClose(.SUdpPlayer):.SUdpPlayer=0
        screenunlock: sleepex 1,1
        messagebox(null,"Connection Closed? ","Rally 4",MB_ICONWARNING or MB_SYSTEMMODAL)
        DPlayError(__LINE__,DPERR_CONNECTIONLOST)
      end if
        
      if hSelect(.SUdpPlayer)=0 then                
        screenunlock:sleepex 1,1
        DPlayError(__LINE__,DPERR_NOMESSAGES)
      end if
      'iAddr = .AddrPlayer : iPort = .PortPlayer
      iAddr=0:iPort=0
      if pThis->BuffServer=0 then 
        pThis->BuffServer=allocate(4096)          
      end if        
      var iResu = hReceiveUDP(.SUdpPlayer,iAddr,iPort,pThis->BuffServer,4096)        
      if iResu <= 0 then        
        iResu = WSAGetLastError() 
        .dwMsgSize=0:hClose(.SockPlayer):.SockPlayer=0  
        hClose(.SUdpPlayer):.SUdpPlayer=0
        screenunlock: sleepex 1,1
        messagebox(null,"Connection Error " & iResu & " (receive1 from "+ _
        *hIPtoString(.AddrPlayer)+":" & .PortPlayer & ")","Rally 4",MB_ICONWARNING or MB_SYSTEMMODAL)
        DPlayError(__LINE__,DPERR_CONNECTIONLOST)
      end if
      .dwMsgSize = *cptr(DWORD ptr,pThis->BuffServer)
      if (iResu-sizeof(DWORD)) <> .dwMsgSize then
        screenunlock: sleepex 1,1
        messagebox(null,"Message Size Doesnt Match " & _
        iResu & "<>" & .dwMsgSize & "(UDP Recv)","Rally 4",MB_ICONWARNING)
        DPlayError(__LINE__,DPERR_NOMESSAGES)
      end if
      if .dwMsgSize > *lpdwDataSize then        
        *lpdwDataSize = .dwMsgSize
        DPlayError(__LINE__,DPERR_BUFFERTOOSMALL)
      end if
      memcpy(lpData,pThis->BuffServer+sizeof(DWORD),.dwMsgSize)
      #endif      
      *lpdwDataSize = .dwMsgSize: .dwMsgSize = 0      
      return DP_OK      
    end with
  end with 
  
  return DPERR_NOMESSAGES
end function
' ****************************************************************************************
UndefAll()
#define P1 pThis        as iDirectPlay3AObject ptr
#define P2 idFrom       as DPID
#define P3 idTo         as DPID
#define P4 dwFlags      as DWORD
#define P5 lpData       as LPVOID
#define P6 dwDataSize   as DWORD
function iDirectPlay3A_26_Send(P1,P2,P3,P4,P5,P6) as hresult
  #ifdef CtlDebugNetworkSend
  scope
    dim sFlags as string = "", iFlags as integer = dwFlags    
    if (iFlags and DPSEND_ENCRYPTED)  then iFlags -= &h1: sFlags += "ENCRYPTED "
    if (iFlags and DPSEND_GUARANTEED) then iFlags -= &h8: sFlags += "GUARANTEED "
    if (iFlags and DPSEND_SIGNED)     then iFlags -= &h2: sFlags += "SIGNED "    
    if (iFlags)                       then sFlags += "0x"+hex$(iFlags)+" "   
    dim sTo as string
    select case idTo
    case DPID_SERVERPLAYER: sTO = "{Server}"
    case DPID_ALLPLAYERS  : sTO = "{Everybody}"
    case else             : sTO = str$(idTo)
    end select
    ccout("IDP3A.Send(26)" !"\r\n" _
    "  From: " & idFrom & _
    "  To: " & sTo & _
    "  Flags:( "+sFlags+")" !"\r\n" _
    "  Data: "+hex$(lpData,8)+ _
    "  DataSz: " & dwDataSize)
    'sleepex 500,1
    LastFrame=timer
  end scope
  #endif
  
  with *cptr(iDirectPlay3AObject ptr,pThis)
    if .Interface <> itDirectPlay then DPlayError(__LINE__,DPERR_INVALIDPARAMS)
    var iTO = iif(idTO=DPID_SERVERPLAYER,0,idTO-1)
    #ifdef CtlDebugNetworkSend
    if iTO <> 0 and iTO <> 1 then
      ccout("Bad Target: " & idTO)
      DPlayError(__LINE__,DPERR_INVALIDPARAMS)
    end if
    #endif
    with .tPlayers(iTO)
      if .idPlayer=0 or dwDataSize <= 0 then DPlayError(__LINE__,DPERR_INVALIDPLAYER)
      if .SockPlayer=0 then 
        screenunlock: sleepex 1,1
        DPlayError(__LINE__,DPERR_CONNECTIONLOST)
      end if
      static as double TMR
      #ifdef DirectPlayTCP
      while hSelect(.SockPlayer,true)=0
      #else
      while hSelect(.SUdpPlayer,true)=0
      #endif
        if TMR=0 then TMR=timer
        if (timer-TMR) > 60 then
          'hClose(.SockPlayer): .SockPlayer=0
          static as integer iErr
          iErr += 1
          if iErr=1 then
            screenunlock
            messagebox(null,"Connection Lost? (send)","Rally 4",MB_ICONWARNING or MB_SYSTEMMODAL)
          end if
          screenunlock: sleepex 1,1
          DPlayError(__LINE__,iErr)
          'DPlayError(__LINE__,DPERR_CONNECTIONLOST)
        end if
        sleep 1,1
      wend      
      if .SizePlayer < dwDataSize+sizeof(DWORD) then
        .SizePlayer = dwDataSize+sizeof(DWORD)
        .BuffPlayer = reallocate(.BuffPlayer,.SizePlayer)
      end if
      *cptr(DWORD ptr,.BuffPlayer) = dwDataSize
      memcpy(.BuffPlayer+sizeof(DWORD),lpData,dwDataSize)
      #ifdef DirectPlayTCP
      hSend(.SockPlayer,.BuffPlayer,dwDataSize+sizeof(DWORD))      
      #else
      hSendUDP(.SUdpPlayer,.AddrPlayer,.PortPlayer,.BuffPlayer,dwDataSize+sizeof(DWORD))      
      #endif
    end with
  end with    
  
  return DP_OK
end function

#if 0
type DPSESSIONDESC2
	dwSize as DWORD
	dwFlags as DWORD
	guidInstance as GUID
	guidApplication as GUID
	dwMaxPlayers as DWORD
	dwCurrentPlayers as DWORD
    union
        as LPWSTR lpszSessionName
        as LPSTR lpszSessionNameA
    end union
    union
        as LPWSTR lpszPassword
        as LPSTR lpszPasswordA
	end union
	dwReserved1 as DWORD
	dwReserved2 as DWORD
	dwUser1 as DWORD
	dwUser2 as DWORD
	dwUser3 as DWORD
	dwUser4 as DWORD
end type

#define DPSESSION_NEWPLAYERSDISABLED &h00000001
#define DPSESSION_MIGRATEHOST &h00000004
#define DPSESSION_NOMESSAGEID &h00000008
#define DPSESSION_JOINDISABLED &h00000020
#define DPSESSION_KEEPALIVE &h00000040
#define DPSESSION_NODATAMESSAGES &h00000080
#define DPSESSION_SECURESERVER &h00000100
#define DPSESSION_PRIVATE &h00000200
#define DPSESSION_PASSWORDREQUIRED &h00000400
#define DPSESSION_MULTICASTSERVER &h00000800
#define DPSESSION_CLIENTSERVER &h00001000
#define DPSESSION_DIRECTPLAYPROTOCOL &h00002000
#define DPSESSION_NOPRESERVEORDER &h00004000
#define DPSESSION_OPTIMIZELATENCY &h00008000
#define DPSESSION_ALLOWVOICERETRO &h00010000
#define DPSESSION_NOSESSIONDESCMESSAGES &h00020000
#endif

' ****************************************************************************************
' ****************************************************************************************
sub iDirectPlay3AFuncs(VTABLE() as any ptr)
  dim as any ptr PROTOTABLE
  asm mov dword ptr [PROTOTABLE], offset _iDirectPlay3AProtoTable_
  for CNT as integer = 0 to 46
    VTABLE(CNT) = PROTOTABLE+CNT*32
  next CNT  
  VTABLE( 0) = @iDirectPlay3A_0_QueryInterface
  VTABLE( 2) = @iDirectPlay3A_2_Release
  VTABLE( 4) = @iDirectPlay3A_2_Release 'iDirectPlay3A_2_Close
  VTABLE( 6) = @IDirectPlay3A_6_CreatePlayer
  VTABLE( 9) = @iDirectPlay3A_9_DestroyPlayer
  VTABLE(12) = @IDirectPlay3A_12_EnumPlayers
  VTABLE(13) = @iDirectPlay3A_13_EnumSessions
  VTABLE(24) = @iDirectPlay3A_24_Open
  VTABLE(25) = @iDirectPlay3A_25_Receive
  VTABLE(26) = @iDirectPlay3A_26_Send
end sub
