*Added BannerSound playback to GameWindowPrompt, playing the gamesounds back (Thanks to Hibernatus for his decoding and uncompressing functions)

NOTE: Added option to enable/disable the BannerSounds and a volume option for it. Note that volume 0 is not the same as disabled. On volume 0 the sounds are still loaded. More options probably going to come.
This commit is contained in:
dimok321 2009-11-08 20:13:57 +00:00
parent 8466f2a45d
commit ab82b0b40d
11 changed files with 899 additions and 77 deletions

686
source/Game_Sound.cpp Normal file
View File

@ -0,0 +1,686 @@
/***************************************************************************
* Copyright (C) 2009
* by Hibernatus
*
* Game_Sound Class by Dimok
* Many other modifications and adjustments by Dimok for USB Loader GX
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any
* damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any
* purpose, including commercial applications, and to alter it and
* redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you
* must not claim that you wrote the original software. If you use
* this software in a product, an acknowledgment in the product
* documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and
* must not be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
***************************************************************************/
#include <stdio.h>
#include <ogcsys.h>
#include <unistd.h>
#include "usbloader/disc.h"
#include "usbloader/wbfs.h"
#include "prompts/PromptWindows.h"
#include "libwbfs/libwbfs.h"
#include "language/gettext.h"
#include "Game_Sound.h"
#define compare(src, str) ((src && str) ? strncasecmp((const char*) src, (const char *) str, strlen((const char *) str)) : -1)
GameSound::GameSound(const u8 * discid)
:GuiSound(NULL, 0, SOUND_PCM)
{
sound = NULL;
length = 0;
type = SOUND_PCM;
voice = 2;
volume = 100;
loop = false;
freq = 0;
format = 0;
this->LoadSound(discid);
}
GameSound::~GameSound()
{
Stop();
if(sound)
free(sound);
sound = NULL;
}
bool GameSound::Play()
{
Stop();
if (!sound || length == 0)
return false;
if (volume == 0)
return true;
return ASND_SetVoice(voice, format, freq, 0, sound, length, volume, volume, 0) == SND_OK;
}
struct IMD5Header
{
u32 fcc;
u32 filesize;
u8 zeroes[8];
u8 crypto[16];
} __attribute__((packed));
struct IMETHeader
{
u8 zeroes[64];
u32 fcc;
u8 unk[8];
u32 iconSize;
u32 bannerSize;
u32 soundSize;
u32 flag1;
u8 names[7][84];
u8 zeroes_2[0x348];
u8 crypto[16];
} __attribute__((packed));
struct U8Header
{
u32 fcc;
u32 rootNodeOffset;
u32 headerSize;
u32 dataOffset;
u8 zeroes[16];
} __attribute__((packed));
struct U8Entry
{
struct
{
u32 fileType : 8;
u32 nameOffset : 24;
};
u32 fileOffset;
union
{
u32 fileLength;
u32 numEntries;
};
} __attribute__((packed));
struct LZ77Info
{
u16 length : 4;
u16 offset : 12;
} __attribute__((packed));
static char *u8Filename(const U8Entry *fst, int i)
{
return (char *)(fst + fst[0].numEntries) + fst[i].nameOffset;
}
struct SWaveHdr
{
u32 fccRIFF;
u32 size;
u32 fccWAVE;
} __attribute__((packed));
struct SWaveFmtChunk
{
u32 fccFMT;
u32 size;
u16 format;
u16 channels;
u32 freq;
u32 avgBps;
u16 alignment;
u16 bps;
} __attribute__((packed));
struct SWaveChunk
{
u32 fcc;
u32 size;
u8 data;
} __attribute__((packed));
struct SAIFFCommChunk
{
u32 fccCOMM;
u32 size;
u16 channels;
u32 samples;
u16 bps;
u8 freq[10];
} __attribute__((packed));
struct SAIFFSSndChunk
{
u32 fccSSND;
u32 size;
u32 offset;
u32 blockSize;
u8 data;
} __attribute__((packed));
inline u32 le32(u32 i)
{
return ((i & 0xFF) << 24) | ((i & 0xFF00) << 8) | ((i & 0xFF0000) >> 8) | ((i & 0xFF000000) >> 24);
}
inline u16 le16(u16 i)
{
return ((i & 0xFF) << 8) | ((i & 0xFF00) >> 8);
}
static u8 * uncompressLZ77(const u8 *inputBuf, u32 inputLength, u32 &size)
{
u8 * buffer = NULL;
if (inputLength <= 0x8 || compare(inputBuf, "LZ77") != 0 || inputBuf[4] != 0x10)
{
return buffer;
}
u32 uncSize = le32(((const u32 *)inputBuf)[1] << 8);
const u8 *inBuf = inputBuf + 8;
const u8 *inBufEnd = inputBuf + inputLength;
buffer = (u8 *) malloc(uncSize);
if (!buffer)
return buffer;
u8 *bufCur = buffer;
u8 *bufEnd = buffer + uncSize;
while (bufCur < bufEnd && inBuf < inBufEnd)
{
u8 flags = *inBuf;
++inBuf;
for (int i = 0; i < 8 && bufCur < bufEnd && inBuf < inBufEnd; ++i)
{
if ((flags & 0x80) != 0)
{
const LZ77Info &info = *(const LZ77Info *)inBuf;
inBuf += sizeof (LZ77Info);
int length = info.length + 3;
if (bufCur - info.offset - 1 < buffer || bufCur + length > bufEnd)
return buffer;
memcpy(bufCur, bufCur - info.offset - 1, length);
bufCur += length;
}
else
{
*bufCur = *inBuf;
++inBuf;
++bufCur;
}
flags <<= 1;
}
}
size = uncSize;
return buffer;
}
void GameSound::LoadSound(const u8 *discid)
{
if(!discid)
return;
if(sound)
free(sound);
sound = NULL;
Disc_SetUSB(NULL);
wbfs_disc_t *disc = wbfs_open_disc(GetHddInfo(), (u8 *) discid);
if(!disc)
{
WindowPrompt(tr("Can't find disc"), 0, tr("OK"));
return;
}
wiidisc_t *wdisc = wd_open_disc((int (*)(void *, u32, u32, void *))wbfs_disc_read, disc);
if(!wdisc)
{
WindowPrompt(tr("Can't open disc"), 0, tr("OK"));
return;
}
u32 size = 0;
u8 * snddata = wd_extract_file(wdisc, &size, ALL_PARTITIONS, (char *) "opening.bnr");
if(!snddata)
{
WindowPrompt(tr("ERROR"), tr("Failed to extract opening.bnr"), tr("OK"));
return;
}
wd_close_disc(wdisc);
wbfs_close_disc(disc);
const u8 *soundBin;
const u8 *bnrArc;
const U8Entry *fst;
u32 i;
const u8 *soundChunk;
u32 soundChunkSize;
const IMETHeader &imetHdr = *(IMETHeader *) snddata;
if (compare(&imetHdr.fcc, "IMET") != 0)
{
WindowPrompt(tr("IMET Header wrong."), 0, tr("OK"));
return;
}
bnrArc = (const u8 *)(&imetHdr + 1);
const U8Header &bnrArcHdr = *(U8Header *)bnrArc;
fst = (const U8Entry *)(bnrArc + bnrArcHdr.rootNodeOffset);
for (i = 1; i < fst[0].numEntries; ++i)
if (fst[i].fileType == 0 && strcasecmp(u8Filename(fst, i), "sound.bin") == 0)
break;
if (i >= fst[0].numEntries)
{
return;
}
soundBin = bnrArc + fst[i].fileOffset;
if (compare((&((IMD5Header *)soundBin)->fcc), "IMD5") != 0)
{
WindowPrompt(tr("IMD5 Header not right."), 0, tr("OK"));
return;
}
soundChunk = soundBin + sizeof (IMD5Header);
soundChunkSize = fst[i].fileLength - sizeof (IMD5Header);
if (compare(soundChunk, "LZ77") == 0)
{
u32 uncSize = NULL;
u8 * uncompressed_data = uncompressLZ77(soundChunk, soundChunkSize, uncSize);
if (!uncompressed_data)
{
WindowPrompt(tr("Can't decompress LZ77"), 0, tr("OK"));
return;
}
soundChunk = uncompressed_data;
soundChunkSize = uncSize;
}
if(compare(soundChunk, "RIFF") == 0)
{
fromWAV(soundChunk, soundChunkSize);
}
else if(compare(soundChunk, "BNS ") == 0)
{
fromBNS(soundChunk, soundChunkSize);
}
else if(compare(soundChunk, "FORM") == 0)
{
fromAIFF(soundChunk, soundChunkSize);
}
free(snddata);
snddata = NULL;
}
bool GameSound::fromWAV(const u8 *buffer, u32 size)
{
const u8 *bufEnd = buffer + size;
const SWaveHdr &hdr = *(SWaveHdr *)buffer;
if (size < sizeof hdr)
return false;
if (compare(&hdr.fccRIFF, "RIFF") != 0)
return false;
if (size < le32(hdr.size) + sizeof hdr.fccRIFF + sizeof hdr.size)
return false;
if (compare(&hdr.fccWAVE, "WAVE") != 0)
return false;
// Find fmt
const SWaveChunk *chunk = (const SWaveChunk *)(buffer + sizeof hdr);
while (&chunk->data < bufEnd && compare(&chunk->fcc, "fmt ") != 0)
chunk = (const SWaveChunk *)(&chunk->data + le32(chunk->size));
if (&chunk->data >= bufEnd)
return false;
const SWaveFmtChunk &fmtChunk = *(const SWaveFmtChunk *)chunk;
// Check format
if (le16(fmtChunk.format) != 1)
return false;
format = (u8)-1;
if (le16(fmtChunk.channels) == 1 && le16(fmtChunk.bps) == 8 && le16(fmtChunk.alignment) <= 1)
format = VOICE_MONO_8BIT;
else if (le16(fmtChunk.channels) == 1 && le16(fmtChunk.bps) == 16 && le16(fmtChunk.alignment) <= 2)
format = VOICE_MONO_16BIT;
else if (le16(fmtChunk.channels) == 2 && le16(fmtChunk.bps) == 8 && le16(fmtChunk.alignment) <= 2)
format = VOICE_STEREO_8BIT;
else if (le16(fmtChunk.channels) == 2 && le16(fmtChunk.bps) == 16 && le16(fmtChunk.alignment) <= 4)
format = VOICE_STEREO_16BIT;
if (format == (u8)-1)
return false;
freq = le32(fmtChunk.freq);
// Find data
chunk = (const SWaveChunk *)(&chunk->data + le32(chunk->size));
while (&chunk->data < bufEnd && compare(&chunk->fcc, "data") != 0)
chunk = (const SWaveChunk *)(&chunk->data + le32(chunk->size));
if (compare(&chunk->fcc, "data") != 0 || &chunk->data + le32(chunk->size) > bufEnd)
return false;
// Data found
sound = (u8 *) malloc(le32(chunk->size));
if (!sound)
return false;
memcpy(sound, &chunk->data, le32(chunk->size));
length = le32(chunk->size);
// Endianness
if (le16(fmtChunk.bps) == 16)
for (u32 i = 0; i < length / sizeof (u16); ++i)
((u16 *) sound)[i] = le16(((u16 *) sound)[i]);
return true;
}
// ------
// Copyright (C) 1988-1991 Apple Computer, Inc.
#ifndef HUGE_VAL
# define HUGE_VAL HUGE
#endif
# define UnsignedToFloat(u) (((double)((long)(u - 2147483647L - 1))) + 2147483648.0)
double ConvertFromIeeeExtended(const unsigned char* bytes)
{
double f;
int expon;
unsigned long hiMant, loMant;
expon = ((bytes[0] & 0x7F) << 8) | (bytes[1] & 0xFF);
hiMant = ((unsigned long)(bytes[2] & 0xFF) << 24)
| ((unsigned long)(bytes[3] & 0xFF) << 16)
| ((unsigned long)(bytes[4] & 0xFF) << 8)
| ((unsigned long)(bytes[5] & 0xFF));
loMant = ((unsigned long)(bytes[6] & 0xFF) << 24)
| ((unsigned long)(bytes[7] & 0xFF) << 16)
| ((unsigned long)(bytes[8] & 0xFF) << 8)
| ((unsigned long)(bytes[9] & 0xFF));
if (expon == 0 && hiMant == 0 && loMant == 0) {
f = 0;
}
else {
if (expon == 0x7FFF) {
f = HUGE_VAL;
}
else {
expon -= 16383;
f = ldexp(UnsignedToFloat(hiMant), expon-=31);
f += ldexp(UnsignedToFloat(loMant), expon-=32);
}
}
if (bytes[0] & 0x80)
return -f;
else
return f;
}
// ------
bool GameSound::fromAIFF(const u8 *buffer, u32 size)
{
const u8 *bufEnd = buffer + size;
const SWaveHdr &hdr = *(SWaveHdr *)buffer;
if (size < sizeof hdr)
return false;
if (compare(&hdr.fccRIFF, "FORM") != 0)
return false;
if (size < hdr.size + sizeof hdr.fccRIFF + sizeof hdr.size)
return false;
if (compare(&hdr.fccWAVE, "AIFF") != 0)
return false;
// Find fmt
const SWaveChunk *chunk = (const SWaveChunk *)(buffer + sizeof hdr);
while (&chunk->data < bufEnd && compare(&chunk->fcc, "COMM") != 0)
chunk = (const SWaveChunk *)(&chunk->data + chunk->size);
if (&chunk->data >= bufEnd)
return false;
const SAIFFCommChunk &fmtChunk = *(const SAIFFCommChunk *)chunk;
// Check format
format = (u8)-1;
if (le16(fmtChunk.channels) == 1 && fmtChunk.bps == 8)
format = VOICE_MONO_8BIT;
else if (fmtChunk.channels == 1 && fmtChunk.bps == 16)
format = VOICE_MONO_16BIT;
else if (fmtChunk.channels == 2 && fmtChunk.bps == 8)
format = VOICE_STEREO_8BIT;
else if (fmtChunk.channels == 2 && fmtChunk.bps == 16)
format = VOICE_STEREO_16BIT;
if (format == (u8)-1)
return false;
freq = (u32)ConvertFromIeeeExtended(fmtChunk.freq);
// Find data
chunk = (const SWaveChunk *)(&chunk->data + chunk->size);
while (&chunk->data < bufEnd && compare(&chunk->fcc, "SSND") != 0)
chunk = (const SWaveChunk *)(&chunk->data + chunk->size);
if (compare(&chunk->fcc, "SSND") != 0 || &chunk->data + chunk->size > bufEnd)
return false;
// Data found
const SAIFFSSndChunk &dataChunk = *(const SAIFFSSndChunk *)chunk;
sound = (u8 *) malloc(dataChunk.size - 8);
if (!sound)
return false;
memcpy(sound, &dataChunk.data, dataChunk.size - 8);
length = dataChunk.size - 8;
return true;
}
struct BNSHeader
{
u32 fccBNS;
u32 magic;
u32 size;
u16 unk1;
u16 unk2;
u32 infoOffset;
u32 infoSize;
u32 dataOffset;
u32 dataSize;
} __attribute__((packed));
struct BNSInfo
{
u32 fccINFO;
u32 size;
u8 codecNum;
u8 loopFlag;
u8 chanCount;
u8 zero;
u16 freq;
u8 pad1[2];
u32 loopStart;
u32 loopEnd;
u32 offsetToChanStarts;
u8 pad2[4];
u32 chan1StartOffset;
u32 chan2StartOffset;
u32 chan1Start;
u32 coeff1Offset;
u8 pad3[4];
u32 chan2Start;
u32 coeff2Offset;
u8 pad4[4];
s16 coefficients1[8][2];
u16 chan1Gain;
u16 chan1PredictiveScale;
s16 chan1PrevSamples[2];
u16 chan1LoopPredictiveScale;
s16 chan1LoopPrevSamples[2];
u16 chan1LoopPadding;
s16 coefficients2[8][2];
u16 chan2Gain;
u16 chan2PredictiveScale;
s16 chan2PrevSamples[2];
u16 chan2LoopPredictiveScale;
s16 chan2LoopPrevSamples[2];
u16 chan2LoopPadding;
} __attribute__((packed));
struct BNSData
{
u32 fccDATA;
u32 size;
u8 data;
} __attribute__((packed));
struct ADPCMByte
{
s8 sample1 : 4;
s8 sample2 : 4;
} __attribute__((packed));
struct BNSADPCMBlock
{
u8 pad : 1;
u8 coeffIndex : 3;
u8 lshift : 4;
ADPCMByte samples[7];
} __attribute__((packed));
struct BNSDecObj
{
s16 prevSamples[2];
s16 coeff[8][2];
};
static void loadBNSInfo(BNSInfo &bnsInfo, const u8 *buffer)
{
const u8 *ptr = buffer + 8;
bnsInfo = *(const BNSInfo *)buffer;
if (bnsInfo.offsetToChanStarts == 0x18 && bnsInfo.chan1StartOffset == 0x20 && bnsInfo.chan2StartOffset == 0x2C
&& bnsInfo.coeff1Offset == 0x38 && bnsInfo.coeff2Offset == 0x68)
return;
bnsInfo.chan1StartOffset = *(const u32 *)(ptr + bnsInfo.offsetToChanStarts);
bnsInfo.chan1Start = *(const u32 *)(ptr + bnsInfo.chan1StartOffset);
bnsInfo.coeff1Offset = *(const u32 *)(ptr + bnsInfo.chan1StartOffset + 4);
if ((u8 *)bnsInfo.coefficients1 != ptr + bnsInfo.coeff1Offset)
memcpy(bnsInfo.coefficients1, ptr + bnsInfo.coeff1Offset, (u8 *)bnsInfo.coefficients2 - (u8 *)&bnsInfo.coefficients1);
if (bnsInfo.chanCount == 2)
{
bnsInfo.chan2StartOffset = *(const u32 *)(ptr + bnsInfo.offsetToChanStarts + 4);
bnsInfo.chan2Start = *(const u32 *)(ptr + bnsInfo.chan2StartOffset);
bnsInfo.coeff2Offset = *(const u32 *)(ptr + bnsInfo.chan2StartOffset + 4);
if ((u8 *)bnsInfo.coefficients2 != ptr + bnsInfo.coeff2Offset)
memcpy(bnsInfo.coefficients2, ptr + bnsInfo.coeff2Offset, (u8 *)bnsInfo.coefficients2 - (u8 *)&bnsInfo.coefficients1);
}
}
static void decodeADPCMBlock(s16 *buffer, const BNSADPCMBlock &block, BNSDecObj &bnsDec)
{
int h1 = bnsDec.prevSamples[0];
int h2 = bnsDec.prevSamples[1];
int c1 = bnsDec.coeff[block.coeffIndex][0];
int c2 = bnsDec.coeff[block.coeffIndex][1];
for (int i = 0; i < 14; ++i)
{
int nibSample = ((i & 1) == 0) ? block.samples[i / 2].sample1 : block.samples[i / 2].sample2;
int sampleDeltaHP = (nibSample << block.lshift) << 11;
int predictedSampleHP = c1 * h1 + c2 * h2;
int sampleHP = predictedSampleHP + sampleDeltaHP;
buffer[i] = std::min(std::max(-32768, (sampleHP + 1024) >> 11), 32767);
h2 = h1;
h1 = buffer[i];
}
bnsDec.prevSamples[0] = h1;
bnsDec.prevSamples[1] = h2;
}
static u8 * decodeBNS(u32 &size, const BNSInfo &bnsInfo, const BNSData &bnsData)
{
static s16 smplBlock[14];
BNSDecObj decObj;
int numBlocks = (bnsData.size - 8) / 8;
int numSamples = numBlocks * 14;
const BNSADPCMBlock *inputBuf = (const BNSADPCMBlock *)&bnsData.data;
u8 * buffer = (u8 *) malloc(numSamples * sizeof (s16));
s16 *outputBuf;
if (!buffer)
return buffer;
memcpy(decObj.coeff, bnsInfo.coefficients1, sizeof decObj.coeff);
memcpy(decObj.prevSamples, bnsInfo.chan1PrevSamples, sizeof decObj.prevSamples);
outputBuf = (s16 *)buffer;
if (bnsInfo.chanCount == 1)
for (int i = 0; i < numBlocks; ++i)
{
decodeADPCMBlock(smplBlock, inputBuf[i], decObj);
memcpy(outputBuf, smplBlock, sizeof smplBlock);
outputBuf += 14;
}
else
{
numBlocks /= 2;
for (int i = 0; i < numBlocks; ++i)
{
decodeADPCMBlock(smplBlock, inputBuf[i], decObj);
for (int j = 0; j < 14; ++j)
outputBuf[j * 2] = smplBlock[j];
outputBuf += 2 * 14;
}
outputBuf = (s16 *)buffer + 1;
memcpy(decObj.coeff, bnsInfo.coefficients2, sizeof decObj.coeff);
memcpy(decObj.prevSamples, bnsInfo.chan2PrevSamples, sizeof decObj.prevSamples);
for (int i = 0; i < numBlocks; ++i)
{
decodeADPCMBlock(smplBlock, inputBuf[numBlocks + i], decObj);
for (int j = 0; j < 14; ++j)
outputBuf[j * 2] = smplBlock[j];
outputBuf += 2 * 14;
}
}
size = numSamples * sizeof (s16);
return buffer;
}
bool GameSound::fromBNS(const u8 *buffer, u32 size)
{
const BNSHeader &hdr = *(BNSHeader *)buffer;
if (size < sizeof hdr)
return false;
if (compare(&hdr.fccBNS, "BNS ") != 0)
return false;
// Find info and data
BNSInfo infoChunk;
loadBNSInfo(infoChunk, buffer + hdr.infoOffset);
const BNSData &dataChunk = *(const BNSData *)(buffer + hdr.dataOffset);
// Check sizes
if (size < hdr.size || size < hdr.infoOffset + hdr.infoSize || size < hdr.dataOffset + hdr.dataSize
|| hdr.infoSize < 0x60 || hdr.dataSize < sizeof dataChunk
|| infoChunk.size != hdr.infoSize || dataChunk.size != hdr.dataSize)
return false;
// Check format
if (infoChunk.codecNum != 0) // Only codec i've found : 0 = ADPCM. Maybe there's also 1 and 2 for PCM 8 or 16 bits ?
return false;
format = (u8)-1;
if (infoChunk.chanCount == 1 && infoChunk.codecNum == 0)
format = VOICE_MONO_16BIT;
else if (infoChunk.chanCount == 2 && infoChunk.codecNum == 0)
format = VOICE_STEREO_16BIT;
if (format == (u8)-1)
return false;
freq = infoChunk.freq;
// Copy data
if (infoChunk.codecNum == 0)
{
sound = decodeBNS(length, infoChunk, dataChunk);
if (!sound)
return false;
}
else
{
sound = (u8*) malloc(dataChunk.size);
if (!sound)
return false;
memcpy(sound, &dataChunk.data, dataChunk.size);
length = dataChunk.size;
}
return true;
}

49
source/Game_Sound.h Normal file
View File

@ -0,0 +1,49 @@
/***************************************************************************
* Copyright (C) 2009
* by Hibernatus
*
* Game_Sound Class by Dimok
* Many other modifications and adjustments by Dimok for USB Loader GX
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any
* damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any
* purpose, including commercial applications, and to alter it and
* redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you
* must not claim that you wrote the original software. If you use
* this software in a product, an acknowledgment in the product
* documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and
* must not be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
***************************************************************************/
#ifndef _GAMESOUND_H_
#define _GAMESOUND_H_
#include "libwiigui/gui.h"
class GameSound : public GuiSound
{
public:
GameSound(const u8 * discid);
~GameSound();
void LoadSound(const u8 *discid);
bool Play();
bool fromWAV(const u8 *buffer, u32 size);
bool fromAIFF(const u8 *buffer, u32 size);
bool fromBNS(const u8 *buffer, u32 size);
private:
u8 * sound;
u32 length;
u32 freq;
u8 format;
};
#endif

View File

@ -215,7 +215,7 @@ void wbfs_close_disc(wbfs_disc_t*d)
wbfs_free(d); wbfs_free(d);
} }
// offset is pointing 32bit words to address the whole dvd, although len is in bytes // offset is pointing 32bit words to address the whole dvd, although len is in bytes
int wbfs_disc_read(wbfs_disc_t*d,u32 offset, u8 *data, u32 len) int wbfs_disc_read(wbfs_disc_t*d,u32 offset, u32 len, u8 *data)
{ {
wbfs_t *p = d->p; wbfs_t *p = d->p;

View File

@ -157,7 +157,7 @@ u32 wbfs_sector_used(wbfs_t *p,wbfs_disc_info_t *di);
@param len: The length of the data to fetch, in *bytes* @param len: The length of the data to fetch, in *bytes*
*/ */
// offset is pointing 32bit words to address the whole dvd, although len is in bytes // offset is pointing 32bit words to address the whole dvd, although len is in bytes
int wbfs_disc_read(wbfs_disc_t*d,u32 offset, u8 *data, u32 len); int wbfs_disc_read(wbfs_disc_t*d,u32 offset, u32 len, u8 *data);
/*! @return the number of discs inside the paritition */ /*! @return the number of discs inside the paritition */
u32 wbfs_count_discs(wbfs_t*p); u32 wbfs_count_discs(wbfs_t*p);

View File

@ -14,7 +14,7 @@
#define wbfs_malloc(x) malloc(x) #define wbfs_malloc(x) malloc(x)
#define wbfs_free(x) free(x) #define wbfs_free(x) free(x)
#define wbfs_ioalloc(x) memalign(32, x) #define wbfs_ioalloc(x) memalign(32, ((x) + 31) & ~31)
#define wbfs_iofree(x) free(x) #define wbfs_iofree(x) free(x)
#define wbfs_be16(x) (*((u16*)(x))) #define wbfs_be16(x) (*((u16*)(x)))
#define wbfs_be32(x) (*((u32*)(x))) #define wbfs_be32(x) (*((u32*)(x)))

View File

@ -126,6 +126,8 @@ static u32 do_fst(wiidisc_t *d,u8 *fst, const char *names, u32 i)
{ {
d->extracted_buffer = wbfs_ioalloc(size); d->extracted_buffer = wbfs_ioalloc(size);
partition_read(d,offset, d->extracted_buffer, size,0); partition_read(d,offset, d->extracted_buffer, size,0);
if(d->extracted_buffer != 0)
d->extracted_buffer_size = size;
}else }else
partition_read(d,offset, 0, size,1); partition_read(d,offset, 0, size,1);
return i + 1; return i + 1;
@ -281,7 +283,7 @@ void wd_close_disc(wiidisc_t *d)
// returns a buffer allocated with wbfs_ioalloc() or NULL if not found of alloc error // returns a buffer allocated with wbfs_ioalloc() or NULL if not found of alloc error
// XXX pathname not implemented. files are extracted by their name. // XXX pathname not implemented. files are extracted by their name.
// first file found with that name is returned. // first file found with that name is returned.
u8 * wd_extract_file(wiidisc_t *d, partition_selector_t partition_type, char *pathname) u8 * wd_extract_file(wiidisc_t *d, u32 *size, partition_selector_t partition_type, char *pathname)
{ {
u8 *retval = 0; u8 *retval = 0;
d->extract_pathname = pathname; d->extract_pathname = pathname;
@ -291,7 +293,10 @@ u8 * wd_extract_file(wiidisc_t *d, partition_selector_t partition_type, char *pa
d->extract_pathname = 0; d->extract_pathname = 0;
d->part_sel = ALL_PARTITIONS; d->part_sel = ALL_PARTITIONS;
retval = d->extracted_buffer; retval = d->extracted_buffer;
if (size != 0)
*size = d->extracted_buffer_size;
d->extracted_buffer = 0; d->extracted_buffer = 0;
d->extracted_buffer_size = 0;
return retval; return retval;
} }

View File

@ -45,12 +45,13 @@ typedef struct wiidisc_s
char *extract_pathname; char *extract_pathname;
u8 *extracted_buffer; u8 *extracted_buffer;
u32 extracted_buffer_size;
}wiidisc_t; }wiidisc_t;
wiidisc_t *wd_open_disc(read_wiidisc_callback_t read,void*fp); wiidisc_t *wd_open_disc(read_wiidisc_callback_t read,void*fp);
void wd_close_disc(wiidisc_t *); void wd_close_disc(wiidisc_t *);
// returns a buffer allocated with wbfs_ioalloc() or NULL if not found of alloc error // returns a buffer allocated with wbfs_ioalloc() or NULL if not found of alloc error
u8 * wd_extract_file(wiidisc_t *d, partition_selector_t partition_type, char *pathname); u8 * wd_extract_file(wiidisc_t *d, u32 *size, partition_selector_t partition_type, char *pathname);
void wd_build_disc_usage(wiidisc_t *d, partition_selector_t selector, u8* usage_table); void wd_build_disc_usage(wiidisc_t *d, partition_selector_t selector, u8* usage_table);

View File

@ -37,6 +37,7 @@
#include "language/UpdateLanguage.h" #include "language/UpdateLanguage.h"
#include "gecko.h" #include "gecko.h"
#include "../lstub.h" #include "../lstub.h"
#include "Game_Sound.h"
@ -1024,6 +1025,8 @@ int GameWindowPrompt() {
char ID[5]; char ID[5];
char IDFull[7]; char IDFull[7];
GameSound * gameSound = NULL;
gprintf("\nGameWindowPrompt()"); gprintf("\nGameWindowPrompt()");
GuiWindow promptWindow(472,320); GuiWindow promptWindow(472,320);
promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE);
@ -1231,6 +1234,19 @@ int GameWindowPrompt() {
//load disc image based or what game is seleted //load disc image based or what game is seleted
struct discHdr * header = (mountMethod==1||mountMethod==2?dvdheader:&gameList[gameSelected]); struct discHdr * header = (mountMethod==1||mountMethod==2?dvdheader:&gameList[gameSelected]);
if(Settings.gamesound)
{
if(gameSound)
{
delete gameSound;
gameSound = NULL;
}
gameSound = new GameSound(header->id);
bgMusic->SetVolume(0);
gameSound->SetVolume(Settings.gamesoundvolume);
gameSound->Play();
}
snprintf (ID,sizeof(ID),"%c%c%c", header->id[0], header->id[1], header->id[2]); snprintf (ID,sizeof(ID),"%c%c%c", header->id[0], header->id[1], header->id[2]);
snprintf (IDFull,sizeof(IDFull),"%c%c%c%c%c%c", header->id[0], header->id[1], header->id[2],header->id[3], header->id[4], header->id[5]); snprintf (IDFull,sizeof(IDFull),"%c%c%c%c%c%c", header->id[0], header->id[1], header->id[2],header->id[3], header->id[4], header->id[5]);
@ -1340,7 +1356,10 @@ int GameWindowPrompt() {
ResumeGui(); ResumeGui();
changed = 0; changed = 0;
while (choice == -1) { while (choice == -1)
{
VIDEO_WaitVSync ();
diskImg.SetSpin(btn1.GetState() == STATE_SELECTED); diskImg.SetSpin(btn1.GetState() == STATE_SELECTED);
diskImg2.SetSpin(btn1.GetState() == STATE_SELECTED); diskImg2.SetSpin(btn1.GetState() == STATE_SELECTED);
if (shutdown == 1) { //for power button if (shutdown == 1) { //for power button
@ -1353,9 +1372,16 @@ int GameWindowPrompt() {
wiilight(0); wiilight(0);
Sys_Shutdown(); Sys_Shutdown();
} }
if (reset == 1) //for reset button if (reset == 1) //for reset button
Sys_Reboot(); Sys_Reboot();
if(gameSound)
{
if(!gameSound->IsPlaying())
bgMusic->SetVolume(Settings.volume);
}
if (btn1.GetState() == STATE_CLICKED) { if (btn1.GetState() == STATE_CLICKED) {
//playcounter //playcounter
struct Game_NUM* game_num = CFG_get_game_num(header->id); struct Game_NUM* game_num = CFG_get_game_num(header->id);
@ -1529,6 +1555,13 @@ int GameWindowPrompt() {
delete diskCover; delete diskCover;
delete diskCover2; delete diskCover2;
if(gameSound)
{
delete gameSound;
gameSound = NULL;
}
bgMusic->SetVolume(Settings.volume);
gprintf("\n\treturn %i",choice); gprintf("\n\treturn %i",choice);
return choice; return choice;
} }

View File

@ -1324,6 +1324,35 @@ int MenuSettings()
options2.SetValue(Idx,"%s", tr("OFF")); options2.SetValue(Idx,"%s", tr("OFF"));
} }
if(ret == ++Idx || firstRun)
{
if(firstRun) options2.SetName(Idx, "%s",tr("Game (Banner) Sounds"));
if(ret == Idx)
{
Settings.gamesound++;
if (Settings.gamesound > 1)
Settings.gamesound = 0;
}
if(Settings.gamesound == 1)
options2.SetValue(Idx,"%s", tr("ON"));
else
options2.SetValue(Idx,"%s", tr("OFF"));
}
if(ret == ++Idx || firstRun)
{
if(firstRun) options2.SetName(Idx, "%s",tr("GameSound Volume"));
if(ret == Idx)
{
Settings.gamesoundvolume += 10;
if (Settings.gamesoundvolume > 100)
Settings.gamesoundvolume = 0;
}
options2.SetValue(Idx,"%i", Settings.gamesoundvolume);
}
firstRun = false; firstRun = false;
} }
} }

View File

@ -332,10 +332,12 @@ void Global_Default(void) {
} }
Settings.volume = 80; Settings.volume = 80;
Settings.sfxvolume = 80; Settings.sfxvolume = 80;
Settings.gamesoundvolume = 80;
Settings.tooltips = TooltipsOn; Settings.tooltips = TooltipsOn;
char * empty = ""; char * empty = "";
snprintf(Settings.unlockCode, sizeof(Settings.unlockCode), empty); snprintf(Settings.unlockCode, sizeof(Settings.unlockCode), empty);
Settings.godmode = 1; Settings.godmode = 1;
Settings.gamesound = 1;
Settings.parentalcontrol = 0; Settings.parentalcontrol = 0;
Settings.cios = ios249; Settings.cios = ios249;
Settings.xflip = no; Settings.xflip = no;
@ -922,6 +924,12 @@ void global_cfg_set(char *name, char *val) {
Settings.sfxvolume = i; Settings.sfxvolume = i;
} }
return; return;
} else if (strcmp(name, "gamesoundvolume") == 0) {
int i;
if (sscanf(val, "%d", &i) == 1) {
Settings.gamesoundvolume = i;
}
return;
} else if (strcmp(name, "tooltips") == 0) { } else if (strcmp(name, "tooltips") == 0) {
int i; int i;
if (sscanf(val, "%d", &i) == 1) { if (sscanf(val, "%d", &i) == 1) {
@ -997,6 +1005,12 @@ void global_cfg_set(char *name, char *val) {
Settings.error002 = i; Settings.error002 = i;
} }
return; return;
} else if (strcmp(name, "gamesound") == 0) {
int i;
if (sscanf(val, "%d", &i) == 1) {
Settings.gamesound = i;
}
return;
} else if (strcmp(name, "titlesOverride") == 0) { } else if (strcmp(name, "titlesOverride") == 0) {
int i; int i;
if (sscanf(val, "%d", &i) == 1) { if (sscanf(val, "%d", &i) == 1) {
@ -1216,6 +1230,7 @@ bool cfg_save_global() { // save global settings
fprintf(f, "rumble = %d\n ", Settings.rumble); fprintf(f, "rumble = %d\n ", Settings.rumble);
fprintf(f, "volume = %d\n ", Settings.volume); fprintf(f, "volume = %d\n ", Settings.volume);
fprintf(f, "sfxvolume = %d\n ", Settings.sfxvolume); fprintf(f, "sfxvolume = %d\n ", Settings.sfxvolume);
fprintf(f, "gamesoundvolume = %d\n ", Settings.gamesoundvolume);
fprintf(f, "tooltips = %d\n ", Settings.tooltips); fprintf(f, "tooltips = %d\n ", Settings.tooltips);
fprintf(f, "password = %s\n ", Settings.unlockCode); fprintf(f, "password = %s\n ", Settings.unlockCode);
fprintf(f, "sort = %d\n ", Settings.sort); fprintf(f, "sort = %d\n ", Settings.sort);
@ -1245,6 +1260,7 @@ bool cfg_save_global() { // save global settings
} else { } else {
fprintf(f, "godmode = %d\n ", 0); fprintf(f, "godmode = %d\n ", 0);
} }
fprintf(f, "gamesound = %d\n ", Settings.gamesound);
fprintf(f, "dolpath = %s\n ", Settings.dolpath); fprintf(f, "dolpath = %s\n ", Settings.dolpath);
fprintf(f, "ogg_path = %s\n ", Settings.ogg_path); fprintf(f, "ogg_path = %s\n ", Settings.ogg_path);
fprintf(f, "wiilight = %d\n ", Settings.wiilight); fprintf(f, "wiilight = %d\n ", Settings.wiilight);
@ -1590,6 +1606,7 @@ bool cfg_load_global() {
} }
Settings.volume = 80; Settings.volume = 80;
Settings.sfxvolume = 80; Settings.sfxvolume = 80;
Settings.gamesoundvolume = 80;
Settings.titlesOverride = 1; Settings.titlesOverride = 1;
char * empty = ""; char * empty = "";

View File

@ -379,6 +379,7 @@ extern "C" {
u8 xflip; u8 xflip;
int volume; int volume;
int sfxvolume; int sfxvolume;
int gamesoundvolume;
u8 tooltips; u8 tooltips;
char unlockCode[20]; char unlockCode[20];
u8 parentalcontrol; u8 parentalcontrol;
@ -418,6 +419,7 @@ extern "C" {
u8 gridRows; u8 gridRows;
u8 autonetwork; u8 autonetwork;
u8 discart; u8 discart;
short gamesound;
}; };
void CFG_LoadGlobal(void); void CFG_LoadGlobal(void);