Beasts and Bumpkins sounds

Get help on any and all audio formats, or chip in and help others!
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

Post by Rheini » Fri Aug 17, 2007 12:45 am

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

Post by Rheini » Thu Sep 04, 2008 12:30 pm

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. :(

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

Post by Rheini » Wed Feb 18, 2009 1:53 pm

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?

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

Post by Rheini » Tue Nov 10, 2009 7:08 pm

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?)
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

Post by Rheini » Fri Mar 05, 2010 4:53 pm

Drives me crazy. how to get these sounds? :cry:

Zench
VIP member
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

Post by Zench » Tue Jul 27, 2010 6:34 pm

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
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

Post by Rheini » Tue Jul 27, 2010 7:30 pm

WTF? Dude you made my day, I just say: http://drop.io/s7lo8bx :wink:
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
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

Post by Zench » Tue Jul 27, 2010 8:37 pm

Rheini wrote:How did you do the debugging, the 640x480 fullscreen mode was a PITA for me.
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.

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).
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)
Sure, though the good stuff is all in assembly. However I did make a nice little wrapper for it in C++. 8)
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

Post by Rheini » Tue Jul 27, 2010 9:00 pm

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).
Yeah when I tracked QSound usage I got ahold of the environmental sounds, they are played using 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

Post by Rheini » Thu Jul 29, 2010 1:25 am

Works like a charm :)
Converted the initialization routine :wink:

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
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

Post by Zench » Thu Jul 29, 2010 4:26 pm

Awesome. Now for the rest of it! :wink:
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

Post by Rheini » Thu Jul 29, 2010 4:32 pm

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.

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

Post by Rheini » Fri Jul 30, 2010 2:45 am

Though some parts are really strange, just look at that -20 stuff:
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
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

Post by Zench » Wed Aug 04, 2010 7:00 pm

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.
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):

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];
};
Rheini wrote:Also I haven't found out what getBits does yet.
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:Though some parts are really strange, just look at that -20 stuff:
And CompressedData seems to be floats as well?
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 these :) . When you propagate it out all of the way, one of the pointers will cancel. Here is the function (it's correct, I tested it):

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 presume you're looking to add support for this in OpenBB. Well, I'm interested in contributing. I kinda went all out and recoded the entire decoder in C++ (and debugged out all my mistakes). So the C++ code attached below produces files that are 100% bit identical to assembly version. (I tested all the files from the demo, and I used MSVC++ 2003.) I had a little help from the latest trunk of Boomerang, but it produced incorrect code sometimes so I just hand coded most of it.

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 :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

Post by Rheini » Thu Aug 05, 2010 2:45 am

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 :)
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:

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;
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 :D
Thanks for your hard work :)

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++;
 		}
 	}

Post Reply