diff --git a/source/Game_Sound.cpp b/source/Game_Sound.cpp new file mode 100644 index 00000000..8bdd3d0a --- /dev/null +++ b/source/Game_Sound.cpp @@ -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 +#include +#include + +#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; +} diff --git a/source/Game_Sound.h b/source/Game_Sound.h new file mode 100644 index 00000000..82092b31 --- /dev/null +++ b/source/Game_Sound.h @@ -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 diff --git a/source/libwbfs/libwbfs.c b/source/libwbfs/libwbfs.c index 8b840a66..fa3be703 100644 --- a/source/libwbfs/libwbfs.c +++ b/source/libwbfs/libwbfs.c @@ -52,7 +52,7 @@ wbfs_t*wbfs_open_hd(rw_sector_callback_t read_hdsector, { // Override the sector size by the sector size in the wbfs header... hd_sector_size = 1 << head->hd_sec_sz_s; - + wbfs_t*p = wbfs_open_partition(read_hdsector,write_hdsector, callback_data,hd_sector_size,0,part_lba,reset); return p; @@ -215,7 +215,7 @@ void wbfs_close_disc(wbfs_disc_t*d) wbfs_free(d); } // 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; diff --git a/source/libwbfs/libwbfs.h b/source/libwbfs/libwbfs.h index eded1284..45ec33c7 100644 --- a/source/libwbfs/libwbfs.h +++ b/source/libwbfs/libwbfs.h @@ -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* */ // 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 */ u32 wbfs_count_discs(wbfs_t*p); @@ -212,11 +212,11 @@ u32 wbfs_extract_disc(wbfs_disc_t*d, rw_sector_callback_t write_dst_wii_sector,v u32 wbfs_extract_file(wbfs_disc_t*d, char *path); // remove some sanity checks -void wbfs_set_force_mode(int force); - -float wbfs_estimate_disc( - wbfs_t *p, read_wiidisc_callback_t read_src_wii_disc, - void *callback_data, +void wbfs_set_force_mode(int force); + +float wbfs_estimate_disc( + wbfs_t *p, read_wiidisc_callback_t read_src_wii_disc, + void *callback_data, partition_selector_t sel); #ifdef __cplusplus diff --git a/source/libwbfs/libwbfs_os.h b/source/libwbfs/libwbfs_os.h index 7b3efbaa..45f33464 100644 --- a/source/libwbfs/libwbfs_os.h +++ b/source/libwbfs/libwbfs_os.h @@ -14,7 +14,7 @@ #define wbfs_malloc(x) malloc(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_be16(x) (*((u16*)(x))) #define wbfs_be32(x) (*((u32*)(x))) diff --git a/source/libwbfs/wiidisc.c b/source/libwbfs/wiidisc.c index 0c521832..89d57023 100644 --- a/source/libwbfs/wiidisc.c +++ b/source/libwbfs/wiidisc.c @@ -126,6 +126,8 @@ static u32 do_fst(wiidisc_t *d,u8 *fst, const char *names, u32 i) { d->extracted_buffer = wbfs_ioalloc(size); partition_read(d,offset, d->extracted_buffer, size,0); + if(d->extracted_buffer != 0) + d->extracted_buffer_size = size; }else partition_read(d,offset, 0, size,1); return i + 1; @@ -155,7 +157,7 @@ static void do_files(wiidisc_t*d) // fake read dol and partition partition_read(d,apl_offset, 0, apl_size,1); partition_read(d,dol_offset, 0, (fst_offset - dol_offset)<<2,1); - + fst = wbfs_ioalloc(fst_size); if (fst == 0) @@ -228,7 +230,7 @@ static int test_parition_skip(u32 partition_type,partition_selector_t part_sel) default: return (partition_type!=part_sel); } -} +} static void do_disc(wiidisc_t*d) { u8 *b = wbfs_ioalloc(0x100); @@ -279,9 +281,9 @@ void wd_close_disc(wiidisc_t *d) wbfs_free(d); } // 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. -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; 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->part_sel = ALL_PARTITIONS; retval = d->extracted_buffer; + if (size != 0) + *size = d->extracted_buffer_size; d->extracted_buffer = 0; + d->extracted_buffer_size = 0; return retval; } @@ -308,8 +313,8 @@ void wd_build_disc_usage(wiidisc_t *d, partition_selector_t selector, u8* usage_ void wd_fix_partition_table(wiidisc_t *d, partition_selector_t selector, u8* partition_table) { u8 *b = partition_table; - u32 partition_offset; - u32 partition_type; + u32 partition_offset; + u32 partition_type; u32 n_partitions,i,j; u32 *b32; if(selector == ALL_PARTITIONS) @@ -317,7 +322,7 @@ void wd_fix_partition_table(wiidisc_t *d, partition_selector_t selector, u8* par n_partitions = _be32(b); if(_be32(b + 4)-(0x40000>>2) >0x50) wbfs_fatal("cannot modify this partition table. Please report the bug."); - + b += (_be32(b + 4)-(0x40000>>2))*4; j=0; for (i = 0; i < n_partitions; i++){ diff --git a/source/libwbfs/wiidisc.h b/source/libwbfs/wiidisc.h index 24a27f43..b8e59e0f 100644 --- a/source/libwbfs/wiidisc.h +++ b/source/libwbfs/wiidisc.h @@ -35,7 +35,7 @@ typedef struct wiidisc_s u32 partition_data_offset; u32 partition_data_size; u32 partition_block; - + u8 *tmp_buffer; u8 *tmp_buffer2; u8 disc_key[16]; @@ -45,12 +45,13 @@ typedef struct wiidisc_s char *extract_pathname; u8 *extracted_buffer; + u32 extracted_buffer_size; }wiidisc_t; wiidisc_t *wd_open_disc(read_wiidisc_callback_t read,void*fp); void wd_close_disc(wiidisc_t *); // 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); diff --git a/source/prompts/PromptWindows.cpp b/source/prompts/PromptWindows.cpp index 621ceeb7..e941346b 100644 --- a/source/prompts/PromptWindows.cpp +++ b/source/prompts/PromptWindows.cpp @@ -37,6 +37,7 @@ #include "language/UpdateLanguage.h" #include "gecko.h" #include "../lstub.h" +#include "Game_Sound.h" @@ -70,7 +71,7 @@ extern void HaltGui(); * into the specified variable. ***************************************************************************/ int OnScreenKeyboard(char * var, u32 maxlen, int min) { - + int save = -1; int keyset = 0; if (Settings.keyset == us) keyset = 0; @@ -78,7 +79,7 @@ int OnScreenKeyboard(char * var, u32 maxlen, int min) { else if (Settings.keyset == euro) keyset = 2; else if (Settings.keyset == azerty) keyset = 3; else if (Settings.keyset == qwerty) keyset = 4; - + gprintf("\nOnScreenKeyboard(%s, %i, %i) \n\tkeyset = %i",var,maxlen,min,keyset); GuiKeyboard keyboard(var, maxlen, min, keyset); @@ -149,7 +150,7 @@ int OnScreenKeyboard(char * var, u32 maxlen, int min) { ***************************************************************************/ void WindowCredits() { gprintf("\nWindowCredits()"); - + int angle = 0; GuiSound * creditsMusic = NULL; @@ -443,7 +444,7 @@ int WindowPrompt(const char *title, const char *msg, const char *btn1Label, int choice = -1; int count = wait; gprintf("\nWindowPrompt(%s, %s, %s, %s, %s, %s, %i)",title,msg,btn1Label,btn2Label, btn3Label,btn4Label,wait); - + GuiWindow promptWindow(472,320); promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); @@ -674,7 +675,7 @@ int WindowPrompt(const char *title, const char *msg, const char *btn1Label, mainWindow->SetState(STATE_DEFAULT); ResumeGui(); gprintf(" = %i",choice); - + return choice; } @@ -693,7 +694,7 @@ WindowExitPrompt(const char *title, const char *msg, const char *btn1Label, const char *btn2Label, const char *btn3Label, const char *btn4Label) { gprintf("\nWindowExitPrompt()"); - + GuiSound * homein = NULL; homein = new GuiSound(menuin_ogg, menuin_ogg_size, SOUND_OGG, Settings.sfxvolume); homein->SetVolume(Settings.sfxvolume); @@ -707,12 +708,12 @@ WindowExitPrompt(const char *title, const char *msg, const char *btn1Label, int choice = -1; char imgPath[100]; - + u64 oldstub = getStubDest(); loadStub(); if (oldstub != 0x00010001554c4e52ll && oldstub != 0x00010001554e454fll) Set_Stub(oldstub); - + GuiWindow promptWindow(640,480); promptWindow.SetAlignment(ALIGN_LEFT, ALIGN_TOP); promptWindow.SetPosition(0, 0); @@ -778,7 +779,7 @@ WindowExitPrompt(const char *title, const char *msg, const char *btn1Label, batteryBtn[3]->SetPosition(494, 150); - + #endif GuiTrigger trigA; trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); @@ -823,7 +824,7 @@ WindowExitPrompt(const char *title, const char *msg, const char *btn1Label, btn2.SetEffect(EFFECT_SLIDE_LEFT | EFFECT_SLIDE_IN, 50); btn2.SetRumble(false); btn2.SetPosition(-150, 0); - + GuiText btn3Txt(btn2Label, 28, (GXColor) {0, 0, 0, 255}); GuiImage btn3Img(&button); @@ -1010,7 +1011,7 @@ void SetFavoriteImages(GuiImage *b1, GuiImage *b2, GuiImage *b3, GuiImage *b4, G b3->SetImage(favoritevar >= 3 ? on : off); b4->SetImage(favoritevar >= 4 ? on : off); b5->SetImage(favoritevar >= 5 ? on : off); -} +} /**************************************************************************** * GameWindowPrompt @@ -1024,6 +1025,8 @@ int GameWindowPrompt() { char ID[5]; char IDFull[7]; + GameSound * gameSound = NULL; + gprintf("\nGameWindowPrompt()"); GuiWindow promptWindow(472,320); promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); @@ -1231,14 +1234,27 @@ int GameWindowPrompt() { //load disc image based or what game is seleted 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 (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]); gprintf("\n\t%s",IDFull); if (diskCover) delete diskCover; - - + + snprintf(imgPath,sizeof(imgPath),"%s%s.png", Settings.disc_path, IDFull); //changed to current full id diskCover = new GuiImageData(imgPath,0); @@ -1309,13 +1325,13 @@ int GameWindowPrompt() { nameTxt.SetEffect(EFFECT_FADE, 17); } else diskImg.SetImage(diskCover); - + if (!mountMethod) { WBFS_GameSize(header->id, &size); sizeTxt.SetTextf("%.2fGB", size); //set size text; } - + nameTxt.SetText(get_title(header)); struct Game_NUM* game_num = CFG_get_game_num(header->id); @@ -1340,7 +1356,10 @@ int GameWindowPrompt() { ResumeGui(); changed = 0; - while (choice == -1) { + while (choice == -1) + { + VIDEO_WaitVSync (); + diskImg.SetSpin(btn1.GetState() == STATE_SELECTED); diskImg2.SetSpin(btn1.GetState() == STATE_SELECTED); if (shutdown == 1) { //for power button @@ -1353,9 +1372,16 @@ int GameWindowPrompt() { wiilight(0); Sys_Shutdown(); } + if (reset == 1) //for reset button Sys_Reboot(); + if(gameSound) + { + if(!gameSound->IsPlaying()) + bgMusic->SetVolume(Settings.volume); + } + if (btn1.GetState() == STATE_CLICKED) { //playcounter struct Game_NUM* game_num = CFG_get_game_num(header->id); @@ -1529,6 +1555,13 @@ int GameWindowPrompt() { delete diskCover; delete diskCover2; + if(gameSound) + { + delete gameSound; + gameSound = NULL; + } + bgMusic->SetVolume(Settings.volume); + gprintf("\n\treturn %i",choice); return choice; } @@ -1732,7 +1765,7 @@ FormatingPartition(const char *title, partitionEntry *entry) { * SearchMissingImages ***************************************************************************/ bool SearchMissingImages(int choice2) { - + gprintf("\nSearchMissingImages(%i)",choice2); GuiWindow promptWindow(472,320); promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); @@ -1774,14 +1807,14 @@ bool SearchMissingImages(int choice2) { mainWindow->Append(&promptWindow); mainWindow->ChangeFocus(&promptWindow); ResumeGui(); - + //make sure that all games are added to the gamelist __Menu_GetEntries(1); cntMissFiles = 0; u32 i = 0; char filename[11]; - + //add IDs of games that are missing covers to cntMissFiles bool found1 = false; bool found2 = false; @@ -1789,7 +1822,7 @@ bool SearchMissingImages(int choice2) { for (i = 0; i < gameCnt && cntMissFiles < 500; i++) { struct discHdr* header = &gameList[i]; if (choice2 != 3) { - + char *covers_path = choice2==1 ? Settings.covers2d_path : Settings.covers_path; snprintf (filename,sizeof(filename),"%c%c%c.png", header->id[0], header->id[1], header->id[2]); @@ -1821,7 +1854,7 @@ bool SearchMissingImages(int choice2) { msgTxt.SetText(tr("No file missing!")); sleep(1); } - + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 50); while (promptWindow.GetEffect() > 0) usleep(50); @@ -1830,7 +1863,7 @@ bool SearchMissingImages(int choice2) { mainWindow->SetState(STATE_DEFAULT); __Menu_GetEntries(); ResumeGui(); - + gprintf(" = %i",cntMissFiles); if (cntMissFiles > 0) { //&& !IsNetworkInit()) { NetworkInitPrompt(); @@ -2341,7 +2374,7 @@ ProgressDownloadWindow(int choice2) { } /**Temporary redownloading 1st image because of a fucking corruption bug **/ -#if 0 // is no longer necessary, since libfat is fixed +#if 0 // is no longer necessary, since libfat is fixed char URLFile[100]; struct block file = downloadfile(URLFile); if (choice2 == 2) { @@ -2565,7 +2598,7 @@ int ProgressUpdateWindow() { //make the URL to get XML based on our games char XMLurl[3540]; build_XML_URL(XMLurl,sizeof(XMLurl)); - + if (IsNetworkInit() && ret >= 0) { updatemode = WindowPrompt(tr("What do you want to update?"), 0, "USB Loader GX", tr("WiiTDB Files"), tr("Language File"), tr("Cancel")); @@ -2733,7 +2766,7 @@ int ProgressUpdateWindow() { if (!failed && ret >= 0 && updatemode == 1) { WindowPrompt(tr("Successfully Updated") , tr("Restarting..."), tr("OK")); - + loadStub(); Set_Stub_Split(0x00010001,"UNEO"); Sys_BackToLoader(); @@ -2875,7 +2908,7 @@ int ProgressUpdateWindow() { //make the URL to get XML based on our games char XMLurl[3540]; build_XML_URL(XMLurl,sizeof(XMLurl)); - + char dolpath[150]; // char dolpathsuccess[150];//use coverspath as a folder for the update wad so we dont make a new folder and have to delete it snprintf(dolpath, sizeof(dolpath), "%sULNR.wad", Settings.covers_path); @@ -2913,7 +2946,7 @@ int ProgressUpdateWindow() { titleTxt.SetTextf("%s USB Loader GX", tr("Updating")); msgTxt.SetPosition(0,100); msgTxt.SetTextf("%s", tr("Updating WiiTDB.zip")); - + char wiitdbpath[200]; char wiitdbpathtmp[200]; struct block file = downloadfile(XMLurl); @@ -2934,7 +2967,7 @@ int ProgressUpdateWindow() { OpenXMLDatabase(Settings.titlestxt_path, Settings.db_language, Settings.db_JPtoEN, true, Settings.titlesOverride==1?true:false, true); // open file, reload titles, keep in memory } } - + msgTxt.SetTextf("%s", tr("Updating Language Files:")); updateLanguageFiles(); promptWindow.Append(&progressbarEmptyImg); diff --git a/source/settings/Settings.cpp b/source/settings/Settings.cpp index 2708bc19..11e9b318 100644 --- a/source/settings/Settings.cpp +++ b/source/settings/Settings.cpp @@ -361,7 +361,7 @@ int MenuSettings() MainButton2.SetEffect(EFFECT_FADE, 20); MainButton3.SetEffect(EFFECT_FADE, 20); MainButton4.SetEffect(EFFECT_FADE, 20); - } + } else if (slidedirection == LEFT) { MainButton1.SetEffect(EFFECT_SLIDE_LEFT | EFFECT_SLIDE_IN, 35); @@ -688,7 +688,7 @@ int MenuSettings() if(firstRun || ret >= 0) { int Idx = -1; - + if(ret == ++Idx || firstRun) { if(firstRun) options2.SetName(Idx, "%s",tr("App Language")); @@ -745,7 +745,7 @@ int MenuSettings() static const char *opts[settings_sinfo_max] = {trNOOP("Game ID"),trNOOP("Game Region"),trNOOP("Both"),trNOOP("Neither")}; options2.SetValue(Idx,"%s",tr(opts[Settings.sinfo])); } - + if(ret == ++Idx || firstRun) { if(firstRun) options2.SetName(Idx, "%s",tr("Clock")); @@ -755,7 +755,7 @@ int MenuSettings() else if (Settings.hddinfo == hr24) options2.SetValue(Idx,"24 %s",tr("Hour")); else if (Settings.hddinfo == Off) options2.SetValue(Idx,"%s",tr("OFF")); } - + if(ret == ++Idx || firstRun) { if(firstRun) options2.SetName(Idx, "%s",tr("Tooltips")); @@ -763,7 +763,7 @@ int MenuSettings() Settings.tooltips = 0; options2.SetValue(Idx,"%s",tr(opts_off_on[Settings.tooltips])); } - + if(ret == ++Idx || firstRun) { if(firstRun) options2.SetName(Idx, "%s",tr("Flip-X")); @@ -776,7 +776,7 @@ int MenuSettings() {trNOOP("DiskFlip"),"",""}}; options2.SetValue(Idx,"%s%s%s",tr(opts[Settings.keyset][0]),opts[Settings.keyset][1],tr(opts[Settings.keyset][2])); } - + if(ret == ++Idx || firstRun) { if(firstRun) options2.SetName(Idx, "%s",tr("Prompts Buttons")); @@ -785,7 +785,7 @@ int MenuSettings() static const char *opts[settings_off_on_max] = {trNOOP("Normal"),trNOOP("Widescreen Fix")}; options2.SetValue(Idx,"%s",tr(opts[Settings.wsprompt])); } - + if(ret == ++Idx || firstRun) { if(firstRun) options2.SetName(Idx, "%s",tr("Keyboard")); @@ -794,7 +794,7 @@ int MenuSettings() static const char *opts[settings_keyset_max] = {"QWERTY","QWERTY 2","DVORAK","QWERTZ","AZERTY"}; options2.SetValue(Idx,"%s", opts[Settings.keyset]); } - + if(ret == ++Idx || firstRun) { if(firstRun) options2.SetName(Idx, "%s",tr("Disc Artwork Download")); @@ -803,7 +803,7 @@ int MenuSettings() static const char *opts[4] = {trNOOP("Only Original"),trNOOP("Only Customs"),trNOOP("Original/Customs"),trNOOP("Customs/Original")}; options2.SetValue(Idx,"%s",tr(opts[Settings.discart])); } - + if(ret == ++Idx || firstRun) { if(firstRun) options2.SetName(Idx, "%s",tr("Wiilight")); @@ -812,7 +812,7 @@ int MenuSettings() static const char *opts[settings_wiilight_max] = {trNOOP("OFF"),trNOOP("ON"),trNOOP("Only for Install")}; options2.SetValue(Idx,"%s",tr(opts[Settings.wiilight])); } - + if(ret == ++Idx || firstRun) { if(firstRun) options2.SetName(Idx, "%s",tr("Rumble")); @@ -820,7 +820,7 @@ int MenuSettings() Settings.rumble = 0; //RUMBLE options2.SetValue(Idx,"%s",tr(opts_off_on[Settings.rumble])); } - + if(ret == ++Idx || firstRun) { if(firstRun) options2.SetName(Idx, "%s",tr("AutoInit Network")); @@ -836,7 +836,7 @@ int MenuSettings() Settings.titlesOverride = 0; options2.SetValue(Idx,"%s",tr(opts_off_on[Settings.titlesOverride])); } - + if(ret == ++Idx || firstRun) { if(firstRun) options2.SetName(Idx, "%s",tr("Screensaver")); @@ -845,7 +845,7 @@ int MenuSettings() static const char *opts[settings_screensaver_max] = {trNOOP("OFF"),trNOOP("3 min"),trNOOP("5 min"),trNOOP("10 min"),trNOOP("20 min"),trNOOP("30 min"),trNOOP("1 hour")}; options2.SetValue(Idx,"%s",tr(opts[Settings.screensaver])); } - + firstRun = false; } } @@ -931,7 +931,7 @@ int MenuSettings() if(firstRun || ret >= 0) { int Idx = -1; - + if(ret == ++Idx || firstRun) { if(firstRun) options2.SetName(Idx, "%s",tr("Video Mode")); @@ -939,7 +939,7 @@ int MenuSettings() Settings.video = 0; options2.SetValue(Idx,"%s%s",opts_videomode[Settings.video][0], tr(opts_videomode[Settings.video][1])); } - + if(ret == ++Idx || firstRun) { if(firstRun) options2.SetName(Idx, "%s",tr("VIDTV Patch")); @@ -1048,7 +1048,7 @@ int MenuSettings() Sys_Shutdown(); if (reset == 1) Sys_Reboot(); - + else if (backBtn.GetState() == STATE_CLICKED) { backBtn.ResetState(); @@ -1323,7 +1323,36 @@ int MenuSettings() else 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; } } @@ -1443,7 +1472,7 @@ int MenuSettings() options2.SetValue(Idx, "%s", Settings.covers_path); } - + if(ret == ++Idx || firstRun) { if(firstRun) options2.SetName(Idx, "%s", tr("2D Cover Path")); @@ -1500,7 +1529,7 @@ int MenuSettings() options2.SetValue(Idx, "%s", Settings.disc_path); } - + if(ret == ++Idx || firstRun) { if(firstRun) options2.SetName(Idx, "%s", tr("Theme Path")); @@ -1562,7 +1591,7 @@ int MenuSettings() options2.SetValue(Idx, "%s", CFG.theme_path); } - + if(ret == ++Idx || firstRun) { if(firstRun) options2.SetName(Idx, "%s", tr("WiiTDB Path")); @@ -1598,7 +1627,7 @@ int MenuSettings() options2.SetValue(Idx, "%s", Settings.titlestxt_path); } - + if(ret == ++Idx || firstRun) { if(firstRun) options2.SetName(Idx, "%s", tr("Update Path")); @@ -1625,7 +1654,7 @@ int MenuSettings() options2.SetValue(Idx, "%s", Settings.update_path); } - + if(ret == ++Idx || firstRun) { if(firstRun) options2.SetName(Idx, "%s", tr("GCT Cheatcodes Path")); @@ -1652,7 +1681,7 @@ int MenuSettings() options2.SetValue(Idx, "%s", Settings.Cheatcodespath); } - + if(ret == ++Idx || firstRun) { if(firstRun) options2.SetName(Idx, "%s", tr("TXT Cheatcodes Path")); @@ -1679,7 +1708,7 @@ int MenuSettings() options2.SetValue(Idx, "%s", Settings.TxtCheatcodespath); } - + if(ret == ++Idx || firstRun) { if(firstRun) options2.SetName(Idx, "%s", tr("DOL Path")); @@ -1710,7 +1739,7 @@ int MenuSettings() options2.SetValue(Idx, "%s", Settings.dolpath); } - + if(ret == ++Idx || firstRun) { if(firstRun) options2.SetName(Idx, "%s", tr("Homebrew Apps Path")); @@ -1741,7 +1770,7 @@ int MenuSettings() options2.SetValue(Idx, "%s", Settings.homebrewapps_path); } - + if(ret == ++Idx || firstRun) { if(firstRun) options2.SetName(Idx, "%s", tr("Theme Download Path")); @@ -1769,7 +1798,7 @@ int MenuSettings() } options2.SetValue(Idx, "%s", Settings.theme_downloadpath); } - + firstRun = false; } } @@ -1945,7 +1974,7 @@ int MenuSettings() break; } PageIndicatorBtn1.ResetState(); - } + } else if (PageIndicatorBtn2.GetState() == STATE_CLICKED) { if (pageToDisplay < 2) @@ -2077,7 +2106,7 @@ int GameSettings(struct discHdr * header) strncat(gameName, "...", 3); } } - else + else sprintf(gameName, "%c%c%c%c%c%c", header->id[0], header->id[1], header->id[2],header->id[3], header->id[4], header->id[5]); GuiText titleTxt(!mountMethod?get_title(header):gameName, 28, (GXColor) {0, 0, 0, 255}); @@ -2406,7 +2435,7 @@ int GameSettings(struct discHdr * header) if(ret >= 0 || firstRun == true) { int Idx = -1; - + if(ret == ++Idx || firstRun) { if(firstRun) options2.SetName(Idx, "%s",tr("Video Mode")); @@ -2414,7 +2443,7 @@ int GameSettings(struct discHdr * header) videoChoice = 0; options2.SetValue(Idx,"%s%s",opts_videomode[videoChoice][0], tr(opts_videomode[videoChoice][1])); } - + if(ret == ++Idx || firstRun) { if(firstRun) options2.SetName(Idx, "%s",tr("VIDTV Patch")); diff --git a/source/settings/cfg.c b/source/settings/cfg.c index 87e4ef79..0e468b7a 100644 --- a/source/settings/cfg.c +++ b/source/settings/cfg.c @@ -332,10 +332,12 @@ void Global_Default(void) { } Settings.volume = 80; Settings.sfxvolume = 80; + Settings.gamesoundvolume = 80; Settings.tooltips = TooltipsOn; char * empty = ""; snprintf(Settings.unlockCode, sizeof(Settings.unlockCode), empty); Settings.godmode = 1; + Settings.gamesound = 1; Settings.parentalcontrol = 0; Settings.cios = ios249; Settings.xflip = no; @@ -922,6 +924,12 @@ void global_cfg_set(char *name, char *val) { Settings.sfxvolume = i; } 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) { int i; if (sscanf(val, "%d", &i) == 1) { @@ -997,6 +1005,12 @@ void global_cfg_set(char *name, char *val) { Settings.error002 = i; } 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) { int i; 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, "volume = %d\n ", Settings.volume); fprintf(f, "sfxvolume = %d\n ", Settings.sfxvolume); + fprintf(f, "gamesoundvolume = %d\n ", Settings.gamesoundvolume); fprintf(f, "tooltips = %d\n ", Settings.tooltips); fprintf(f, "password = %s\n ", Settings.unlockCode); fprintf(f, "sort = %d\n ", Settings.sort); @@ -1245,6 +1260,7 @@ bool cfg_save_global() { // save global settings } else { fprintf(f, "godmode = %d\n ", 0); } + fprintf(f, "gamesound = %d\n ", Settings.gamesound); fprintf(f, "dolpath = %s\n ", Settings.dolpath); fprintf(f, "ogg_path = %s\n ", Settings.ogg_path); fprintf(f, "wiilight = %d\n ", Settings.wiilight); @@ -1590,6 +1606,7 @@ bool cfg_load_global() { } Settings.volume = 80; Settings.sfxvolume = 80; + Settings.gamesoundvolume = 80; Settings.titlesOverride = 1; char * empty = ""; diff --git a/source/settings/cfg.h b/source/settings/cfg.h index 5ed47de1..f4c4ab9d 100644 --- a/source/settings/cfg.h +++ b/source/settings/cfg.h @@ -379,6 +379,7 @@ extern "C" { u8 xflip; int volume; int sfxvolume; + int gamesoundvolume; u8 tooltips; char unlockCode[20]; u8 parentalcontrol; @@ -418,6 +419,7 @@ extern "C" { u8 gridRows; u8 autonetwork; u8 discart; + short gamesound; }; void CFG_LoadGlobal(void);