translate: initial struct parsing for member calls
authornotaz <notasas@gmail.com>
Sun, 5 Apr 2015 23:55:58 +0000 (02:55 +0300)
committernotaz <notasas@gmail.com>
Sun, 5 Apr 2015 23:55:58 +0000 (02:55 +0300)
tools/protoparse.h
tools/translate.c
win32.hlist

index 2647bba..511e337 100644 (file)
@@ -50,6 +50,15 @@ struct parsed_proto {
        unsigned int has_retreg:1;
 };
 
+struct parsed_struct {
+       char name[256];
+       struct {
+               int offset;
+               struct parsed_proto pp;
+       } members[64];
+       int member_count;
+};
+
 static const char *hdrfn;
 static int hdrfline = 0;
 
@@ -58,6 +67,7 @@ static void pp_copy_arg(struct parsed_proto_arg *d,
 
 static int b_pp_c_handler(char *proto, const char *fname,
        int is_include, int is_osinc, int is_cinc);
+static int struct_handler(FILE *fhdr, char *proto, int *line);
 
 static int do_protostrs(FILE *fhdr, const char *fname, int is_include)
 {
@@ -120,8 +130,12 @@ static int do_protostrs(FILE *fhdr, const char *fname, int is_include)
 
                hdrfline = line;
 
-               ret = b_pp_c_handler(protostr, hdrfn, is_include,
-                       is_osinc, is_cinc);
+               if (!strncmp(protostr, "struct", 6)
+                   && strchr(protostr, '{') != NULL)
+                       ret = struct_handler(fhdr, protostr, &line);
+               else
+                       ret = b_pp_c_handler(protostr, hdrfn,
+                               is_include, is_osinc, is_cinc);
                if (ret < 0)
                        break;
        }
@@ -165,7 +179,6 @@ static const char *known_type_mod[] = {
        "const",
        "signed",
        "unsigned",
-       "struct",
        "enum",
        "CONST",
        "volatile",
@@ -225,7 +238,6 @@ static const char *ignored_keywords[] = {
        "WINADVAPI",
 };
 
-// returns ptr to char after type ends
 static int typecmp(const char *n, const char *t)
 {
        for (; *t != 0; n++, t++) {
@@ -269,6 +281,14 @@ static int check_type(const char *name, struct parsed_type *type)
 
        n = skip_type_mod(name);
 
+       if (!strncmp(n, "struct", 6) && my_isblank(n[6])) {
+               type->is_struct = 1;
+
+               n += 6;
+               while (my_isblank(*n))
+                       n++;
+       }
+
        for (i = 0; i < ARRAY_SIZE(known_ptr_types); i++) {
                if (typecmp(n, known_ptr_types[i]))
                        continue;
@@ -351,7 +371,18 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp)
                p = sskip(p + 2);
        }
 
-       // strip unneeded stuff
+       // allow start of line comment
+       if (p[0] == '/' && p[1] == '*') {
+               p = strstr(p + 2, "*/");
+               if (p == NULL) {
+                       printf("%s:%d: multiline comments unsupported\n",
+                               hdrfn, hdrfline);
+                       return -1;
+               }
+               p = sskip(p + 2);
+       }
+
+       // we need remaining hints in comments, so strip / *
        for (p1 = p; p1[0] != 0 && p1[1] != 0; p1++) {
                if ((p1[0] == '/' && p1[1] == '*')
                 || (p1[0] == '*' && p1[1] == '/'))
@@ -662,6 +693,77 @@ static int pp_name_cmp(const void *p1, const void *p2)
        return strcmp(pp1->name, pp2->name);
 }
 
+static int ps_name_cmp(const void *p1, const void *p2)
+{
+       const struct parsed_struct *ps1 = p1, *ps2 = p2;
+       return strcmp(ps1->name, ps2->name);
+}
+
+// parsed struct cache
+static struct parsed_struct *ps_cache;
+static int ps_cache_size;
+static int ps_cache_alloc;
+
+static int struct_handler(FILE *fhdr, char *proto, int *line)
+{
+       struct parsed_struct *ps;
+       char lstr[256], *p;
+       int offset = 0;
+       int m = 0;
+       int ret;
+
+       if (ps_cache_size >= ps_cache_alloc) {
+               ps_cache_alloc = ps_cache_alloc * 2 + 64;
+               ps_cache = realloc(ps_cache, ps_cache_alloc
+                               * sizeof(ps_cache[0]));
+               my_assert_not(ps_cache, NULL);
+               memset(ps_cache + ps_cache_size, 0,
+                       (ps_cache_alloc - ps_cache_size)
+                        * sizeof(ps_cache[0]));
+       }
+
+       ps = &ps_cache[ps_cache_size++];
+       ret = sscanf(proto, "struct %255s {", ps->name);
+       if (ret != 1) {
+               printf("%s:%d: struct parse failed\n", hdrfn, *line);
+               return -1;
+       }
+
+       while (fgets(lstr, sizeof(lstr), fhdr))
+       {
+               (*line)++;
+
+               p = sskip(lstr);
+               if (p[0] == '/' && p[1] == '/')
+                       continue;
+               if (p[0] == '}')
+                       break;
+
+               if (m >= ARRAY_SIZE(ps->members)) {
+                       printf("%s:%d: too many struct members\n",
+                               hdrfn, *line);
+                       return -1;
+               }
+
+               hdrfline = *line;
+               ret = parse_protostr(p, &ps->members[m].pp);
+               if (ret < 0) {
+                       printf("%s:%d: struct member #%d/%02x "
+                               "doesn't parse\n", hdrfn, *line,
+                               m, offset);
+                       return -1;
+               }
+               ps->members[m].offset = offset;
+               offset += 4;
+               m++;
+       }
+
+       ps->member_count = m;
+
+       return 0;
+}
+
+// parsed proto cache
 static struct parsed_proto *pp_cache;
 static int pp_cache_size;
 static int pp_cache_alloc;
@@ -692,7 +794,7 @@ static int b_pp_c_handler(char *proto, const char *fname,
        return 0;
 }
 
-static void build_pp_cache(FILE *fhdr)
+static void build_caches(FILE *fhdr)
 {
        long pos;
        int ret;
@@ -705,6 +807,7 @@ static void build_pp_cache(FILE *fhdr)
                exit(1);
 
        qsort(pp_cache, pp_cache_size, sizeof(pp_cache[0]), pp_name_cmp);
+       qsort(ps_cache, ps_cache_size, sizeof(ps_cache[0]), ps_name_cmp);
        fseek(fhdr, pos, SEEK_SET);
 }
 
@@ -716,7 +819,7 @@ static const struct parsed_proto *proto_parse(FILE *fhdr, const char *sym,
        char *p;
 
        if (pp_cache == NULL)
-               build_pp_cache(fhdr);
+               build_caches(fhdr);
 
        if (sym[0] == '_') // && strncmp(fname, "stdc", 4) == 0)
                sym++;
@@ -734,6 +837,41 @@ static const struct parsed_proto *proto_parse(FILE *fhdr, const char *sym,
        return pp_ret;
 }
 
+static const struct parsed_proto *proto_lookup_struct(FILE *fhdr,
+       const char *type, int offset)
+{
+       struct parsed_struct ps_search, *ps;
+       int m;
+
+       if (pp_cache == NULL)
+               build_caches(fhdr);
+       if (ps_cache_size == 0)
+               return NULL;
+
+       while (my_isblank(*type))
+               type++;
+       if (!strncmp(type, "struct", 6) && my_isblank(type[6]))
+               type += 7;
+
+       if (sscanf(type, "%255s", ps_search.name) != 1)
+               return NULL;
+
+       ps = bsearch(&ps_search, ps_cache, ps_cache_size,
+                       sizeof(ps_cache[0]), ps_name_cmp);
+       if (ps == NULL) {
+               printf("%s: struct '%s' is missing\n",
+                       hdrfn, ps_search.name);
+               return NULL;
+       }
+
+       for (m = 0; m < ps->member_count; m++) {
+               if (ps->members[m].offset == offset)
+                       return &ps->members[m].pp;
+       }
+
+       return NULL;
+}
+
 static void pp_copy_arg(struct parsed_proto_arg *d,
        const struct parsed_proto_arg *s)
 {
@@ -833,4 +971,6 @@ static inline void proto_release(struct parsed_proto *pp)
        if (pp->ret_type.name != NULL)
                free(pp->ret_type.name);
        free(pp);
+
+       (void)proto_lookup_struct;
 }
index dadf7a9..bec6d07 100644 (file)
@@ -208,7 +208,8 @@ struct parsed_op {
 };
 
 // datap:
-// OP_CALL  - parser proto hint (str)
+// on start:  function/data type hint (sctproto)
+// after analysis:
 // (OPF_CC) - points to one of (OPF_FLAGS) that affects cc op
 // OP_PUSH  - points to OP_POP in complex push/pop graph
 // OP_POP   - points to OP_PUSH in simple push/pop pair
@@ -641,7 +642,7 @@ static char *default_cast_to(char *buf, size_t buf_size,
 {
   buf[0] = 0;
 
-  if (!opr->is_ptr)
+  if (!opr->is_ptr || strchr(opr->name, '['))
     return buf;
   if (opr->pp == NULL || opr->pp->type.name == NULL
     || opr->pp->is_fptr)
@@ -3488,10 +3489,25 @@ static void resolve_branches_parse_calls(int opcnt)
     po->bt_i = -1;
     po->btj = NULL;
 
+    if (po->datap != NULL) {
+      pp = calloc(1, sizeof(*pp));
+      my_assert_not(pp, NULL);
+
+      ret = parse_protostr(po->datap, pp);
+      if (ret < 0)
+        ferr(po, "bad protostr supplied: %s\n", (char *)po->datap);
+      free(po->datap);
+      po->datap = NULL;
+      po->pp = pp;
+    }
+
     if (po->op == OP_CALL) {
       pp = NULL;
 
-      if (po->operand[0].type == OPT_LABEL) {
+      if (po->pp != NULL)
+        pp = po->pp;
+      else if (po->operand[0].type == OPT_LABEL)
+      {
         tmpname = opr_name(po, 0);
         if (IS_START(tmpname, "loc_"))
           ferr(po, "call to loc_*\n");
@@ -3521,16 +3537,6 @@ static void resolve_branches_parse_calls(int opcnt)
           my_assert_not(pp, NULL);
         }
       }
-      else if (po->datap != NULL) {
-        pp = calloc(1, sizeof(*pp));
-        my_assert_not(pp, NULL);
-
-        ret = parse_protostr(po->datap, pp);
-        if (ret < 0)
-          ferr(po, "bad protostr supplied: %s\n", (char *)po->datap);
-        free(po->datap);
-        po->datap = NULL;
-      }
 
       if (pp != NULL) {
         if (pp->is_fptr)
@@ -3807,36 +3813,11 @@ static void scan_prologue_epilogue(int opcnt)
   }
 }
 
-static const struct parsed_proto *resolve_icall(int i, int opcnt,
-  int *pp_i, int *multi_src)
-{
-  const struct parsed_proto *pp = NULL;
-  int search_advice = 0;
-
-  *multi_src = 0;
-  *pp_i = -1;
-
-  switch (ops[i].operand[0].type) {
-  case OPT_REGMEM:
-  case OPT_LABEL:
-  case OPT_OFFSET:
-    pp = try_recover_pp(&ops[i], &ops[i].operand[0], &search_advice);
-    if (!search_advice)
-      break;
-    // fallthrough
-  default:
-    scan_for_call_type(i, &ops[i].operand[0], i + opcnt * 9, &pp,
-      pp_i, multi_src);
-    break;
-  }
-
-  return pp;
-}
-
 // find an instruction that changed opr before i op
 // *op_i must be set to -1 by the caller
-// *entry is set to 1 if one source is determined to be the caller
+// *is_caller is set to 1 if one source is determined to be g_func arg
 // returns 1 if found, *op_i is then set to origin
+// returns -1 if multiple origins are found
 static int resolve_origin(int i, const struct parsed_opr *opr,
   int magic, int *op_i, int *is_caller)
 {
@@ -4015,6 +3996,96 @@ static int try_resolve_const(int i, const struct parsed_opr *opr,
   return -1;
 }
 
+static const struct parsed_proto *resolve_icall(int i, int opcnt,
+  int *pp_i, int *multi_src)
+{
+  const struct parsed_proto *pp = NULL;
+  int search_advice = 0;
+  int offset = -1;
+  char name[256];
+  char s_reg[4];
+  int reg, len;
+  int ret;
+
+  *multi_src = 0;
+  *pp_i = -1;
+
+  switch (ops[i].operand[0].type) {
+  case OPT_REGMEM:
+    // try to resolve struct member calls
+    ret = sscanf(ops[i].operand[0].name, "%3s+%x%n",
+            s_reg, &offset, &len);
+    if (ret == 2 && len == strlen(ops[i].operand[0].name))
+    {
+      reg = char_array_i(regs_r32, ARRAY_SIZE(regs_r32), s_reg);
+      if (reg >= 0) {
+        struct parsed_opr opr = OPR_INIT(OPT_REG, OPLM_DWORD, reg);
+        int j = -1;
+        ret = resolve_origin(i, &opr, i + opcnt * 19, &j, NULL);
+        if (ret != 1)
+          break;
+        if (ops[j].op == OP_MOV && ops[j].operand[1].type == OPT_REGMEM
+          && ops[j].operand[0].lmod == OPLM_DWORD
+          && ops[j].pp == NULL) // no hint
+        {
+          // allow one simple dereference (directx)
+          reg = char_array_i(regs_r32, ARRAY_SIZE(regs_r32),
+                  ops[j].operand[1].name);
+          if (reg < 0)
+            break;
+          struct parsed_opr opr2 = OPR_INIT(OPT_REG, OPLM_DWORD, reg);
+          int k = -1;
+          ret = resolve_origin(j, &opr2, j + opcnt * 19, &k, NULL);
+          if (ret != 1)
+            break;
+          j = k;
+        }
+        if (ops[j].op != OP_MOV)
+          break;
+        if (ops[j].operand[0].lmod != OPLM_DWORD)
+          break;
+        if (ops[j].pp != NULL) {
+          // type hint in asm
+          pp = ops[j].pp;
+        }
+        else if (ops[j].operand[1].type == OPT_REGMEM) {
+          // allow 'hello[ecx]' - assume array of same type items
+          ret = sscanf(ops[j].operand[1].name, "%[^[][e%2s]",
+                  name, s_reg);
+          if (ret != 2)
+            break;
+          pp = proto_parse(g_fhdr, name, g_quiet_pp);
+        }
+        else if (ops[j].operand[1].type == OPT_LABEL)
+          pp = proto_parse(g_fhdr, ops[j].operand[1].name, g_quiet_pp);
+        else
+          break;
+        if (pp == NULL)
+          break;
+        if (pp->is_func || pp->is_fptr || !pp->type.is_struct) {
+          pp = NULL;
+          break;
+        }
+        pp = proto_lookup_struct(g_fhdr, pp->type.name, offset);
+      }
+      break;
+    }
+    // fallthrough
+  case OPT_LABEL:
+  case OPT_OFFSET:
+    pp = try_recover_pp(&ops[i], &ops[i].operand[0], &search_advice);
+    if (!search_advice)
+      break;
+    // fallthrough
+  default:
+    scan_for_call_type(i, &ops[i].operand[0], i + opcnt * 9, &pp,
+      pp_i, multi_src);
+    break;
+  }
+
+  return pp;
+}
+
 static struct parsed_proto *process_call_early(int i, int opcnt,
   int *adj_i)
 {
@@ -8065,11 +8136,8 @@ do_pending_endp:
 
     parse_op(&ops[pi], words, wordc);
 
-    if (sctproto != NULL) {
-      if (ops[pi].op == OP_CALL || ops[pi].op == OP_JMP)
-        ops[pi].datap = sctproto;
-      sctproto = NULL;
-    }
+    ops[pi].datap = sctproto;
+    sctproto = NULL;
     pi++;
   }
 
index 993b322..1f90f6e 100644 (file)
@@ -1865,30 +1865,131 @@ DWORD WINAPI lineTranslateDialogA(HLINEAPP,DWORD,DWORD,HWND,LPCSTR);
 DWORD WINAPI lineUnhold(HCALL);
 DWORD WINAPI lineUnparkA(HLINE,DWORD,LPHCALL,LPCSTR);
 
+struct IDirectDraw {
+          // IUnknown methods
+/*00*/    HRESULT (WINAPI *QueryInterface)(void *this, REFIID riid, void** ppvObject);
+/*04*/    ULONG (WINAPI *AddRef)(void *this);
+/*08*/    ULONG (WINAPI *Release)(void *this);
+          // IDirectDraw methods
+/*0c*/    int (WINAPI *Compact)(void *this);
+/*10*/    int (WINAPI *CreateClipper)(void *this, DWORD dwFlags, LPDIRECTDRAWCLIPPER *lplpDDClipper, IUnknown *pUnkOuter);
+/*14*/    int (WINAPI *CreatePalette)(void *this, DWORD dwFlags, LPPALETTEENTRY lpColorTable, LPDIRECTDRAWPALETTE *lplpDDPalette, IUnknown *pUnkOuter); // 14
+/*18*/    int (WINAPI *CreateSurface)(void *this, LPDDSURFACEDESC lpDDSurfaceDesc, LPDIRECTDRAWSURFACE *lplpDDSurface, IUnknown *pUnkOuter);
+/*1c*/    int (WINAPI *DuplicateSurface)(void *this, LPDIRECTDRAWSURFACE lpDDSurface, LPDIRECTDRAWSURFACE *lplpDupDDSurface);
+/*20*/    int (WINAPI *EnumDisplayModes)(void *this, DWORD dwFlags, LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext, LPDDENUMMODESCALLBACK lpEnumModesCallback);
+/*24*/    int (WINAPI *EnumSurfaces)(void *this, DWORD dwFlags, LPDDSURFACEDESC lpDDSD, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback);
+/*28*/    int (WINAPI *FlipToGDISurface)(void *this);
+/*2c*/    int (WINAPI *GetCaps)(void *this, LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps);
+/*30*/    int (WINAPI *GetDisplayMode)(void *this, LPDDSURFACEDESC lpDDSurfaceDesc);
+/*34*/    int (WINAPI *GetFourCCCodes)(void *this, LPDWORD lpNumCodes, LPDWORD lpCodes);
+/*38*/    int (WINAPI *GetGDISurface)(void *this, LPDIRECTDRAWSURFACE *lplpGDIDDSurface);
+/*3c*/    int (WINAPI *GetMonitorFrequency)(void *this, LPDWORD lpdwFrequency);
+/*40*/    int (WINAPI *GetScanLine)(void *this, LPDWORD lpdwScanLine);
+/*44*/    int (WINAPI *GetVerticalBlankStatus)(void *this, BOOL *lpbIsInVB);
+/*48*/    int (WINAPI *Initialize)(void *this, GUID *lpGUID);
+/*4c*/    int (WINAPI *RestoreDisplayMode)(void *this);
+/*50*/    int (WINAPI *SetCooperativeLevel)(void *this, HWND hWnd, DWORD dwFlags);
+/*54*/    int (WINAPI *SetDisplayMode)(void *this, DWORD dwWidth, DWORD dwHeight, DWORD dwBPP);
+/*58*/    int (WINAPI *WaitForVerticalBlank)(void *this, DWORD dwFlags, HANDLE hEvent);
+};
+
+struct IDirectDrawPalette {
+          // IUnknown methods
+/*00*/    HRESULT (WINAPI *QueryInterface)(void *this, REFIID riid, void** ppvObject);
+/*04*/    ULONG (WINAPI *AddRef)(void *this);
+/*08*/    ULONG (WINAPI *Release)(void *this);
+          // IDirectDrawPalette methods
+/*0c*/    int (WINAPI *GetCaps)(void *this, LPDWORD lpdwCaps);
+/*10*/    int (WINAPI *GetEntries)(void *this, DWORD dwFlags, DWORD dwBase, DWORD dwNumEntries, LPPALETTEENTRY lpEntries);
+/*14*/    int (WINAPI *Initialize)(void *this, LPDIRECTDRAW lpDD, DWORD dwFlags, LPPALETTEENTRY lpDDColorTable);
+/*18*/    int (WINAPI *SetEntries)(void *this, DWORD dwFlags, DWORD dwStartingEntry, DWORD dwCount, LPPALETTEENTRY lpEntries);
+};
+
+struct IDirectDrawSurface {
+          // IUnknown methods
+/*00*/    HRESULT (WINAPI *QueryInterface)(void *this, REFIID riid, void** ppvObject);
+/*04*/    ULONG (WINAPI *AddRef)(void *this);
+/*08*/    ULONG (WINAPI *Release)(void *this);
+          // IDirectDrawSurface methods
+/*0c*/    int (WINAPI *AddAttachedSurface)(void *this, LPDIRECTDRAWSURFACE lpDDSAttachedSurface);
+/*10*/    int (WINAPI *AddOverlayDirtyRect)(void *this, LPRECT lpRect);
+/*14*/    int (WINAPI *Blt)(void *this, LPRECT lpDestRect, LPDIRECTDRAWSURFACE lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx);
+/*18*/    int (WINAPI *BltBatch)(void *this, LPDDBLTBATCH lpDDBltBatch, DWORD dwCount, DWORD dwFlags);
+/*1c*/    int (WINAPI *BltFast)(void *this, DWORD dwX, DWORD dwY, LPDIRECTDRAWSURFACE lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwTrans);
+/*20*/    int (WINAPI *DeleteAttachedSurface)(void *this, DWORD dwFlags, LPDIRECTDRAWSURFACE lpDDSAttachedSurface);
+/*24*/    int (WINAPI *EnumAttachedSurfaces)(void *this, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback);
+/*28*/    int (WINAPI *EnumOverlayZOrders)(void *this, DWORD dwFlags, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpfnCallback);
+/*2c*/    int (WINAPI *Flip)(void *this, LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride, DWORD dwFlags);
+/*30*/    int (WINAPI *GetAttachedSurface)(void *this, LPDDSCAPS lpDDSCaps, LPDIRECTDRAWSURFACE *lplpDDAttachedSurface);
+/*34*/    int (WINAPI *GetBltStatus)(void *this, DWORD dwFlags);
+/*38*/    int (WINAPI *GetCaps)(void *this, LPDDSCAPS lpDDSCaps);
+/*3c*/    int (WINAPI *GetClipper)(void *this, LPDIRECTDRAWCLIPPER *lplpDDClipper);
+/*40*/    int (WINAPI *GetColorKey)(void *this, DWORD dwFlags, LPDDCOLORKEY lpDDColorKey);
+/*44*/    int (WINAPI *GetDC)(void *this, HDC *lphDC);
+/*48*/    int (WINAPI *GetFlipStatus)(void *this, DWORD dwFlags);
+/*4c*/    int (WINAPI *GetOverlayPosition)(void *this, LPLONG lplX, LPLONG lplY);
+/*50*/    int (WINAPI *GetPalette)(void *this, LPDIRECTDRAWPALETTE *lplpDDPalette);
+/*54*/    int (WINAPI *GetPixelFormat)(void *this, LPDDPIXELFORMAT lpDDPixelFormat);
+/*58*/    int (WINAPI *GetSurfaceDesc)(void *this, LPDDSURFACEDESC lpDDSurfaceDesc);
+/*5c*/    int (WINAPI *Initialize)(void *this, LPDIRECTDRAW lpDD, LPDDSURFACEDESC lpDDSurfaceDesc);
+/*60*/    int (WINAPI *IsLost)(void *this);
+/*64*/    int (WINAPI *Lock)(void *this, LPRECT lpDestRect, LPDDSURFACEDESC lpDDSurfaceDesc, DWORD dwFlags, HANDLE hEvent);
+/*68*/    int (WINAPI *ReleaseDC)(void *this, HDC hDC);
+/*6c*/    int (WINAPI *Restore)(void *this);
+/*70*/    int (WINAPI *SetClipper)(void *this, LPDIRECTDRAWCLIPPER lpDDClipper);
+/*74*/    int (WINAPI *SetColorKey)(void *this, DWORD dwFlags, LPDDCOLORKEY lpDDColorKey);
+/*78*/    int (WINAPI *SetOverlayPosition)(void *this, LONG lX, LONG lY);
+/*7c*/    int (WINAPI *SetPalette)(void *this, LPDIRECTDRAWPALETTE lpDDPalette);
+/*80*/    int (WINAPI *Unlock)(void *this, LPVOID lpSurfaceData);
+/*84*/    int (WINAPI *UpdateOverlay)(void *this, LPRECT lpSrcRect, LPDIRECTDRAWSURFACE lpDDDestSurface, LPRECT lpDestRect, DWORD dwFlags, LPDDOVERLAYFX lpDDOverlayFx);
+/*88*/    int (WINAPI *UpdateOverlayDisplay)(void *this, DWORD dwFlags);
+/*8c*/    int (WINAPI *UpdateOverlayZOrder)(void *this, DWORD dwFlags, LPDIRECTDRAWSURFACE lpDDSReference);
+};
+
+struct IDirectSound {
+          // IUnknown methods
+/*00*/    HRESULT (WINAPI *QueryInterface)(void *this, REFIID riid, void** ppvObject);
+/*04*/    ULONG (WINAPI *AddRef)(void *this);
+/*08*/    ULONG (WINAPI *Release)(void *this);
+          // IDirectSound methods
+/*0c*/    int (WINAPI *CreateSoundBuffer)(void *this, LPCDSBUFFERDESC lpcDSBufferDesc, LPLPDIRECTSOUNDBUFFER lplpDirectSoundBuffer, IUnknown *pUnkOuter);
+/*10*/    int (WINAPI *GetCaps)(void *this, LPDSCAPS lpDSCaps);
+/*14*/    int (WINAPI *DuplicateSoundBuffer)(void *this, LPDIRECTSOUNDBUFFER lpDsbOriginal, LPLPDIRECTSOUNDBUFFER lplpDsbDuplicate);
+/*18*/    int (WINAPI *SetCooperativeLevel)(void *this, HWND hwnd, DWORD dwLevel);
+/*1c*/    int (WINAPI *Compact)(void *this);
+/*20*/    int (WINAPI *GetSpeakerConfig)(void *this, LPDWORD lpdwSpeakerConfig);
+/*24*/    int (WINAPI *SetSpeakerConfig)(void *this, DWORD dwSpeakerConfig);
+/*28*/    int (WINAPI *Initialize)(void *this, LPCGUID lpcGuid);
+};
+
+struct IDirectSoundBuffer {
+          // IUnknown methods
+/*00*/    HRESULT (WINAPI *QueryInterface)(void *this, REFIID riid, void** ppvObject);
+/*04*/    ULONG (WINAPI *AddRef)(void *this);
+/*08*/    ULONG (WINAPI *Release)(void *this);
+          // IDirectSoundBuffer methods
+/*0c*/    int (WINAPI *GetCaps)(void *this, LPDSBCAPS lpDSBufferCaps);
+/*10*/    int (WINAPI *GetCurrentPosition)(void *this, LPDWORD lpdwCurrentPlayCursor, LPDWORD lpdwCurrentWriteCursor);
+/*14*/    int (WINAPI *GetFormat)(void *this, LPWAVEFORMATEX lpwfxFormat, DWORD dwSizeAllocated, LPDWORD lpdwSizeWritten);
+/*18*/    int (WINAPI *GetVolume)(void *this, LPLONG lplVolume);
+/*1c*/    int (WINAPI *GetPan)(void *this, LPLONG lplpan);
+/*20*/    int (WINAPI *GetFrequency)(void *this, LPDWORD lpdwFrequency);
+/*24*/    int (WINAPI *GetStatus)(void *this, LPDWORD lpdwStatus);
+/*28*/    int (WINAPI *Initialize)(void *this, LPDIRECTSOUND lpDirectSound, LPCDSBUFFERDESC lpcDSBufferDesc);
+/*2c*/    int (WINAPI *Lock)(void *this, DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1, LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags);
+/*30*/    int (WINAPI *Play)(void *this, DWORD dwReserved1, DWORD dwReserved2, DWORD dwFlags);
+/*34*/    int (WINAPI *SetCurrentPosition)(void *this, DWORD dwNewPosition);
+/*38*/    int (WINAPI *SetFormat)(void *this, LPCWAVEFORMATEX lpcfxFormat);
+/*3c*/    int (WINAPI *SetVolume)(void *this, LONG lVolume);
+/*40*/    int (WINAPI *SetPan)(void *this, LONG lPan);
+/*44*/    int (WINAPI *SetFrequency)(void *this, DWORD dwFrequency);
+/*48*/    int (WINAPI *Stop)(void *this);
+/*4c*/    int (WINAPI *Unlock)(void *this, LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioPtr2);
+/*50*/    int (WINAPI *Restore)(void *this);
+};
 
 //    sctproto: int (__stdcall *Direct*Create)(void *, void *, void *)
 // 08 sctproto: int (WINAPI *dx_Release)(void *iface)
-// IDirectDraw
-// 14 sctproto: int (WINAPI *ddraw1_CreatePalette)(void *iface, DWORD flags, PALETTEENTRY *entries, void **palette, void *)
-// 18 sctproto: int (WINAPI *ddraw1_CreateSurface)(void *iface, void *surface_desc, void **surface, void *)
-// 2C sctproto: int (WINAPI *ddraw1_GetCaps)(void *iface, void *driver_caps, void *hel_caps)
-// 38 sctproto: int (WINAPI *ddraw1_GetGDISurface)(void *iface, void **surface)
-// 44 sctproto: int (WINAPI *ddraw1_GetVerticalBlankStatus)(void *iface, BOOL *status)
-// 50 sctproto: int (WINAPI *ddraw1_SetCooperativeLevel)(void *iface, HWND window, DWORD flags)
-// 54 sctproto: int (WINAPI *ddraw1_SetDisplayMode)(void *iface, DWORD width, DWORD height, DWORD bpp)
-// 58 sctproto: int (WINAPI *ddraw1_WaitForVerticalBlank)(void *iface, DWORD flags, HANDLE event)
-// IDirectDrawPalette
-// 10 sctproto: int (WINAPI *palette_GetEntries)(void *, DWORD flags, DWORD start, DWORD count, PALETTEENTRY *entries)
-// 18 sctproto: int (WINAPI *palette_SetEntries)(void *, DWORD flags, DWORD start, DWORD count, PALETTEENTRY *entries)
-// IDirectDrawSurface
-// 14 sctproto: int (WINAPI *surface1_Blt)(void *, RECT *, void *, RECT *, DWORD, void *)
-// 30 sctproto: int (WINAPI *surface1_GetAttachedSurface)(void *, void *caps, void **attachment)
-// 38 sctproto: int (WINAPI *surface1_GetCaps)(void *iface, void *caps)
-// 54 sctproto: int (WINAPI *surface1_GetPixelFormat)(void *iface, void *fmt)
-// 64 sctproto: int (WINAPI *surface1_Lock)(void *, void *, void *, DWORD, HANDLE)
-// 6C sctproto: int (WINAPI *surface1_Restore)(void *)
-// 7C sctproto: int (WINAPI *surface1_SetPalette)(void *iface, void *palette)
-// 80 sctproto: int (WINAPI *surface1_Unlock)(void *, void *)
 // IDirectSound8
 // 0C sctproto: int (WINAPI *dsound_CreateSoundBuffer)(void *iface, void *dsbd, void **ppdsb, void *lpunk)
 // 18 sctproto: int (WINAPI *dsound_SetCooperativeLevel)(void *iface, HWND hwnd, DWORD level)