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;
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)
{
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;
}
"const",
"signed",
"unsigned",
- "struct",
"enum",
"CONST",
"volatile",
"WINADVAPI",
};
-// returns ptr to char after type ends
static int typecmp(const char *n, const char *t)
{
for (; *t != 0; n++, t++) {
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;
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] == '/'))
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;
return 0;
}
-static void build_pp_cache(FILE *fhdr)
+static void build_caches(FILE *fhdr)
{
long pos;
int ret;
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);
}
char *p;
if (pp_cache == NULL)
- build_pp_cache(fhdr);
+ build_caches(fhdr);
if (sym[0] == '_') // && strncmp(fname, "stdc", 4) == 0)
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)
{
if (pp->ret_type.name != NULL)
free(pp->ret_type.name);
free(pp);
+
+ (void)proto_lookup_struct;
}
};
// 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
{
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)
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");
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)
}
}
-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)
{
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)
{
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++;
}
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)