Skip to content

Instantly share code, notes, and snippets.

@grechnik
Created August 1, 2020 21:58
Show Gist options
  • Save grechnik/35249daf34574e420404d5d1bdbcfe90 to your computer and use it in GitHub Desktop.
Save grechnik/35249daf34574e420404d5d1bdbcfe90 to your computer and use it in GitHub Desktop.
call bink2w32.dll to extract the raw sound
#include <windows.h>
#include <stdio.h>
typedef void* (__stdcall *BinkOpen_t)(const char*, unsigned);
typedef void (__stdcall *BinkNextFrame_t)(void*);
typedef void (__stdcall *BinkClose_t)(void*);
typedef int (__stdcall *BinkSetVideoOnOff_t)(void*, int);
typedef void* (__stdcall *BinkOpenTrack_t)(void*, unsigned);
typedef void (__stdcall *BinkCloseTrack_t)(void*);
typedef unsigned (__stdcall *BinkGetTrackData_t)(void*, void*);
typedef void (__stdcall *BinkSetSoundTrack_t)(unsigned, unsigned*);
int main(int argc, const char* argv[])
{
if (argc != 3) {
printf("Usage: extract_pcm <input.bk2> <output.pcm>\n");
return 1;
}
HANDLE bink2w32 = LoadLibrary(TEXT("bink2w32.dll"));
if (!bink2w32) {
printf("failed to load bink2w32.dll\n");
return 1;
}
BinkOpen_t BinkOpen = (BinkOpen_t)GetProcAddress(bink2w32, "_BinkOpen@8");
BinkNextFrame_t BinkNextFrame = (BinkNextFrame_t)GetProcAddress(bink2w32, "_BinkNextFrame@4");
BinkClose_t BinkClose = (BinkClose_t)GetProcAddress(bink2w32, "_BinkClose@4");
BinkSetVideoOnOff_t BinkSetVideoOnOff = (BinkSetVideoOnOff_t)GetProcAddress(bink2w32, "_BinkSetVideoOnOff@8");
BinkOpenTrack_t BinkOpenTrack = (BinkOpenTrack_t)GetProcAddress(bink2w32, "_BinkOpenTrack@8");
BinkCloseTrack_t BinkCloseTrack = (BinkCloseTrack_t)GetProcAddress(bink2w32, "_BinkCloseTrack@4");
BinkGetTrackData_t BinkGetTrackData = (BinkGetTrackData_t)GetProcAddress(bink2w32, "_BinkGetTrackData@8");
BinkSetSoundTrack_t BinkSetSoundTrack = (BinkSetSoundTrack_t)GetProcAddress(bink2w32, "_BinkSetSoundTrack@8");
if (!BinkOpen || !BinkNextFrame || !BinkClose || !BinkSetVideoOnOff || !BinkOpenTrack || !BinkCloseTrack || !BinkGetTrackData || !BinkSetSoundTrack) {
printf("required functions not found\n");
FreeLibrary(bink2w32);
return 1;
}
BinkSetSoundTrack(0, NULL);
// 0x400 = don't allocate frame buffers, we're not interested in video anyway
// 0x4000 = use data from BinkSetSoundTrack
void* bink = BinkOpen(argv[1], 0x4400);
if (!bink) {
printf("failed to open %s\n", argv[1]);
FreeLibrary(bink2w32);
return 1;
}
BinkSetVideoOnOff(bink, 0);
void* track = BinkOpenTrack(bink, 0);
if (!track) {
printf("failed to open track\n");
BinkClose(bink);
FreeLibrary(bink2w32);
return 1;
}
unsigned largestAudio = ((unsigned*)track)[3];
void* pcm = malloc(largestAudio + 0x20);
if (!pcm) {
printf("failed to allocate memory\n");
BinkCloseTrack(track);
BinkClose(bink);
FreeLibrary(bink2w32);
return 1;
}
void* pcm_aligned = (char*)pcm + (-(unsigned)pcm & 0x1F);
FILE* out = fopen(argv[2], "wb");
if (!out) {
printf("failed to create %s\n", argv[2]);
free(pcm);
BinkCloseTrack(track);
BinkClose(bink);
FreeLibrary(bink2w32);
return 1;
}
int ret = 0;
for (;;) {
unsigned n = BinkGetTrackData(track, pcm_aligned);
if (n > largestAudio) printf("internal error\n");
if (fwrite(pcm_aligned, 1, n, out) != n) {
printf("write error\n");
ret = 1;
break;
}
if (((int*)bink)[2] == ((int*)bink)[3])
break;
BinkNextFrame(bink);
}
if (fclose(out)) {
if (!ret) {
printf("write error\n");
ret = 1;
}
}
if (!ret)
printf("ok\n");
free(pcm);
BinkCloseTrack(track);
BinkClose(bink);
FreeLibrary(bink2w32);
return ret;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment