Beasts and Bumpkins sounds
-
Rheini
- Moderator
- Posts: 653
- Joined: Wed Oct 18, 2006 9:48 pm
- Location: Germany
- Has thanked: 19 times
- Been thanked: 40 times
- Contact:
Beasts and Bumpkins sounds
Could someone help me with these sound files from the game Beasts and Bumpkins?
You do not have the required permissions to view the files attached to this post.
-
Rheini
- Moderator
- Posts: 653
- Joined: Wed Oct 18, 2006 9:48 pm
- Location: Germany
- Has thanked: 19 times
- Been thanked: 40 times
- Contact:
Re: Beasts and Bumpkins sounds
Found out that this seems to be some sort of http://wiki.multimedia.cx/index.php?tit ... _Arts_SCxl
But the first header is missing.
EDIT: And the compression type is 9, which is unknown.
But the first header is missing.
EDIT: And the compression type is 9, which is unknown.
-
Rheini
- Moderator
- Posts: 653
- Joined: Wed Oct 18, 2006 9:48 pm
- Location: Germany
- Has thanked: 19 times
- Been thanked: 40 times
- Contact:
Re: Beasts and Bumpkins sounds
Peter Ross suspected it to be MicroTalk 10:1, but I can't convert it with EA SoundXchange.
How can you verify if a certain format is used?
How can you verify if a certain format is used?
-
Rheini
- Moderator
- Posts: 653
- Joined: Wed Oct 18, 2006 9:48 pm
- Location: Germany
- Has thanked: 19 times
- Been thanked: 40 times
- Contact:
Re: Beasts and Bumpkins sounds
Guess the only way is to reverse engineer the codec 
But it's really hard to find the place where they are decoded, any suggestions?
(QSound is used, maybe that gives a hint?)
But it's really hard to find the place where they are decoded, any suggestions?
(QSound is used, maybe that gives a hint?)
You do not have the required permissions to view the files attached to this post.
-
Zench
- VIP member

- Posts: 209
- Joined: Sun May 04, 2008 9:11 pm
- Has thanked: 4 times
- Been thanked: 56 times
- Contact:
Re: Beasts and Bumpkins sounds
After RE'ing the main executable of the Beasts and Bumpkins demo, I got a working decoder!
I'm not sure if the codec has a name or not, but that's not all too important.
Dowload the tool
I'm not sure if the codec has a name or not, but that's not all too important.
Dowload the tool
And I said, "The well has finally run dry." So then that will be my battle cry.
-
Rheini
- Moderator
- Posts: 653
- Joined: Wed Oct 18, 2006 9:48 pm
- Location: Germany
- Has thanked: 19 times
- Been thanked: 40 times
- Contact:
Re: Beasts and Bumpkins sounds
WTF? Dude you made my day, I just say: http://drop.io/s7lo8bx 
I had almost given up on this. How did you do the debugging, the 640x480 fullscreen mode was a PITA for me.
Would you give me the source code? The sounds are pretty much the only thing I couldn't figure out so far (apart from the map format)
http://bitbucket.org/trass3r/openbb/wiki/Home
I had almost given up on this. How did you do the debugging, the 640x480 fullscreen mode was a PITA for me.
Would you give me the source code? The sounds are pretty much the only thing I couldn't figure out so far (apart from the map format)
http://bitbucket.org/trass3r/openbb/wiki/Home
-
Zench
- VIP member

- Posts: 209
- Joined: Sun May 04, 2008 9:11 pm
- Has thanked: 4 times
- Been thanked: 56 times
- Contact:
Re: Beasts and Bumpkins sounds
That was one of the problems I had too. So I used a virtual machine. VirtualBox has a neat feature -- when you install the guest additions in the virtualized operating system it will automatically resize the screen to fit VirtualBox's window. You can pretty much see where this is going. You'd just have to resize the window to change the screen res from whatever the game changed it to.Rheini wrote:How did you do the debugging, the 640x480 fullscreen mode was a PITA for me.
For some reason, when these sounds are decoded in the game, QSound is not used to play them. It uses DirectSound pretty much directly (although from a pointer returned by QSound).
Sure, though the good stuff is all in assembly. However I did make a nice little wrapper for it in C++.Rheini wrote:Would you give me the source code? The sounds are pretty much the only thing I couldn't figure out so far (apart from the map format)
You do not have the required permissions to view the files attached to this post.
And I said, "The well has finally run dry." So then that will be my battle cry.
-
Rheini
- Moderator
- Posts: 653
- Joined: Wed Oct 18, 2006 9:48 pm
- Location: Germany
- Has thanked: 19 times
- Been thanked: 40 times
- Contact:
Re: Beasts and Bumpkins sounds
Yeah when I tracked QSound usage I got ahold of the environmental sounds, they are played using QSound.Zench wrote:For some reason, when these sounds are decoded in the game, QSound is not used to play them. It uses DirectSound pretty much directly (although from a pointer returned by QSound).
Thanks for the code, will see what I can do with it.
-
Rheini
- Moderator
- Posts: 653
- Joined: Wed Oct 18, 2006 9:48 pm
- Location: Germany
- Has thanked: 19 times
- Been thanked: 40 times
- Contact:
Re: Beasts and Bumpkins sounds
Works like a charm 
Converted the initialization routine
Converted the initialization routine
Code: Select all
void mtInitializeDecoder(S_inner_file_data* inner, const void* inputBuffer)
{
inner.CompressedData= inputBuffer+1;
inner.Bits = (cast(ubyte*)inputBuffer)[0];
inner.BitCount = 8;
inner.FirstBit = getBits(inner, 1);
inner.Second4Bits = 32 - getBits(inner, 4);
inner.FloatTable[0] = (getBits(inner, 4) + 1) * 8.0;
float ST1 = 1.04 - (getBits(inner, 6) * -0.001);
for (int eax = 0; eax < 63; eax++)
inner.FloatTable[eax+1] = inner.FloatTable[eax] * ST1;
inner.Table1 = 0;
inner.Table2 = 0;
inner.BigTable = 0;
}-
Zench
- VIP member

- Posts: 209
- Joined: Sun May 04, 2008 9:11 pm
- Has thanked: 4 times
- Been thanked: 56 times
- Contact:
Re: Beasts and Bumpkins sounds
Awesome. Now for the rest of it! 
And I said, "The well has finally run dry." So then that will be my battle cry.
-
Rheini
- Moderator
- Posts: 653
- Joined: Wed Oct 18, 2006 9:48 pm
- Location: Germany
- Has thanked: 19 times
- Been thanked: 40 times
- Contact:
Re: Beasts and Bumpkins sounds
I started with DecodeBlock but it's a lot of work.
How did you get that struct layout? Are you certain that it's correct?
It seems like at least Table1 is a float table.
Also I haven't found out what getBits does yet.
How did you get that struct layout? Are you certain that it's correct?
It seems like at least Table1 is a float table.
Also I haven't found out what getBits does yet.
Code: Select all
uint getBits(S_inner_file_data* buffer, uint count)
{
uint res = buffer.Bits & bitmask_lookup_table[count];
uint a = buffer.BitCount - count;
uint b = buffer.Bits >> count; // note: count only byte!
buffer.BitCount = a;
buffer.Bits = b;
if (a >= 8)
return res;
buffer.Bits = ((cast(ubyte*)buffer.CompressedData)[0] << a) | b;
buffer.CompressedData++;
buffer.BitCount = a + 8;
return res;
}-
Rheini
- Moderator
- Posts: 653
- Joined: Wed Oct 18, 2006 9:48 pm
- Location: Germany
- Has thanked: 19 times
- Been thanked: 40 times
- Contact:
Re: Beasts and Bumpkins sounds
Though some parts are really strange, just look at that -20 stuff:
And CompressedData seems to be floats as well?
And CompressedData seems to be floats as well?
Code: Select all
int __thiscall sub_46B020(S_inner_file_data *this)
{
float *result; // eax@1
signed int v2; // ebp@1
int v3; // esi@1
int v4; // ebx@2
int v5; // edi@2
int v6; // edx@2
result = this->FloatTable;
v3 = -20 - (_DWORD)this;
v2 = 54;
do
{
v4 = (int)((char *)result + v3 - 20);
v5 = (int)((char *)result + v3 - 12);
v6 = (int)(result - 5);
result += 2;
--v2;
*(float *)v6 = (*(float *)((char *)&this->pCompressedData + v5) + *(result - 4)) * -0.11459156
- (*(float *)((char *)&this->pCompressedData + v4) + *(result - 2)) * -0.01803268
- (*(float *)(v6 - 4) + *(result - 6)) * -0.59738597;
}
while ( v2 );
return (int)result;
}-
Zench
- VIP member

- Posts: 209
- Joined: Sun May 04, 2008 9:11 pm
- Has thanked: 4 times
- Been thanked: 56 times
- Contact:
Re: Beasts and Bumpkins sounds
Yes, you're right. And the other tables should be floats as well. That structure was pretty tentative until I figured out more of the meanings. Here is what I have now (the names are basically the same though):Rheini wrote:How did you get that struct layout? Are you certain that it's correct?
It seems like at least Table1 is a float table.
Code: Select all
struct S_inner_file_data
{
uint8_t* CompressedData;
uint32_t CurrentBits;
uint32_t BitCount;
uint32_t FirstBit;
uint32_t Second4Bits;
float FloatTable[64];
float Table1[12];
float Table2[12];
float BigTable[324];
float SampleBuffer[432];
};In case you didn't figure it out before you got to this, this is what it does: it reads count bits from the input stream (the CompressedData member of S_inner_file_data) and returns them.Rheini wrote:Also I haven't found out what getBits does yet.
Hmmm... that function doesn't take a pointer to S_inner_file_data but to an array of floats. All of the functions in the decoder aren't part of the same class, so ecx isn't always a this pointer (think fastcall calling convention). I think the weirdness in that function is because it subtracts pointers from each other. It bugs the crap out of me when I have to decipher theseRheini wrote:Though some parts are really strange, just look at that -20 stuff:
And CompressedData seems to be floats as well?
Code: Select all
void FunctionOne(float* Buffer)
{
float* CurrentPtr = Buffer + 5;
for (unsigned int i = 0; i < 54 ; i++)
{
double a = CurrentPtr[-8] + CurrentPtr[-2];
double b = CurrentPtr[-10] + CurrentPtr[0];
double c = CurrentPtr[-6] + CurrentPtr[-4];
CurrentPtr[-5] = (float)(a * -0.11459156 + b * 0.01803268 + c * 0.59738597);
CurrentPtr += 2;
}
return;
}I hope you're able to use it, and I hope I didn't spoil the fun you were having in converting the assembly to D
You do not have the required permissions to view the files attached to this post.
And I said, "The well has finally run dry." So then that will be my battle cry.
-
Rheini
- Moderator
- Posts: 653
- Joined: Wed Oct 18, 2006 9:48 pm
- Location: Germany
- Has thanked: 19 times
- Been thanked: 40 times
- Contact:
Re: Beasts and Bumpkins sounds
I didn't even think about that option. And because I only disassembled it and didn't debug it I couldn't recognize it either. I got the following now:Zench wrote:that function doesn't take a pointer to S_inner_file_data but to an array of floats. All of the functions in the decoder aren't part of the same class, so ecx isn't always a this pointer (think fastcall calling convention). I think the weirdness in that function is because it subtracts pointers from each other. It bugs the crap out of me when I have to decipher these
Code: Select all
for (ubyte i = 0; i < 108; i+=2)
{
buffer[i] = (buffer[i-3] + buffer[i+3]) * -0.11459156
+ (buffer[i-5] + buffer[i+5]) * 0.01803268
+ (buffer[i-1] + buffer[i+1]) * 0.59738597;
}
return;Thanks for your hard workI hope you're able to use it, and I hope I didn't spoil the fun you were having in converting the assembly to D
Still having problems with my BlockDecoder function though. Getting an ArrayOutOfBounds when indexing BigTable at the end, the only major differences are:
Code: Select all
- float* CurSampleBufPtr = DecoderStruct->SampleBuffer;
+ float* CurSampleBufPtr = DecoderStruct.SampleBuffer.ptr;
- if (!DecoderStruct->FirstBit)
+ if (!DecoderStruct.FirstBit)
{
- FunctionThree(DecoderStruct, Flag, TableB + 5, 1);
+ FunctionThree(DecoderStruct, Flag, &TableB[5], 1);
}
- FunctionThree(DecoderStruct, Flag, TableB + 5 + IndexAdjust, 2);
+ FunctionThree(DecoderStruct, Flag, &TableB[5 + IndexAdjust], 2);
- FunctionOne(TableB + 6 - IndexAdjust);
+ FunctionThree(&TableB[6 - IndexAdjust]);
SomeOtherFloat *= 0.5;
}
}
- float* BigTablePtr = DecoderStruct->BigTable + BigTableIndex;
-
- for (unsigned int i = 0; i < 108; i++)
+ for (uint k = 0; k < 108; k++)
{
- *CurSampleBufPtr = SomeOtherFloat * TableB[i + 5] + SomeFloat * BigTablePtr[i];
+ float tmp = SomeOtherFloat * TableB[k + 5];
+ float tmp2 = SomeFloat * DecoderStruct.BigTable[BigTableIndex + k];
+ *CurSampleBufPtr = tmp + tmp2;
CurSampleBufPtr++;
}
}