From fa11a745d642e6843034fb4ac68df179e273e096 Mon Sep 17 00:00:00 2001
From: dimok321 <15055714+dimok789@users.noreply.github.com>
Date: Sat, 13 Nov 2010 22:34:53 +0000
Subject: [PATCH] A lot of changes with this rev *Rewrote the whole
Settings.cpp into 11 classes. Each settings menu has it's own class now
*Reworked the whole sound system. Supported formats AIF/MP3/OGG/BNS/WAV now
with no file size limit (streaming). *Changed button click/over sounds to wav
from raw pcm *Lot's of bug fixes
---
Makefile | 11 +-
gui.pnproj | 2 +-
gui.pnps | 2 +-
source/FileOperations/File.cpp | 145 +
source/FileOperations/File.hpp | 30 +
source/SoundOperations/AifDecoder.cpp | 214 ++
source/SoundOperations/AifDecoder.hpp | 50 +
source/SoundOperations/BNSDecoder.cpp | 363 ++
source/SoundOperations/BNSDecoder.hpp | 59 +
source/SoundOperations/BufferCircle.cpp | 144 +
source/SoundOperations/BufferCircle.hpp | 92 +
source/SoundOperations/Mp3Decoder.cpp | 216 ++
source/SoundOperations/Mp3Decoder.hpp | 51 +
source/SoundOperations/OggDecoder.cpp | 144 +
source/SoundOperations/OggDecoder.hpp | 45 +
source/SoundOperations/SoundDecoder.cpp | 156 +
source/SoundOperations/SoundDecoder.hpp | 89 +
source/SoundOperations/SoundHandler.cpp | 271 ++
source/SoundOperations/SoundHandler.hpp | 68 +
source/SoundOperations/WavDecoder.cpp | 155 +
source/SoundOperations/WavDecoder.hpp | 75 +
.../gui_bgm.cpp | 460 ++-
.../{libwiigui => SoundOperations}/gui_bgm.h | 84 +-
source/SoundOperations/gui_sound.cpp | 380 ++
source/SoundOperations/gui_sound.h | 80 +
source/bannersound.cpp | 57 +-
source/cheats/cheatmenu.cpp | 8 +-
source/fatmounter.c | 1 +
source/filelist.h | 12 +-
source/homebrewboot/HomebrewBrowse.cpp | 41 +-
source/libs/libwbfs/libwbfs.c | 1654 ++++-----
source/libs/libwbfs/libwbfs.h | 2 +-
source/libs/libwbfs/libwbfs_os.h | 64 +-
source/libwiigui/gui.h | 71 +-
source/libwiigui/gui_button.cpp | 21 +-
source/libwiigui/gui_customoptionbrowser.cpp | 65 +-
source/libwiigui/gui_customoptionbrowser.h | 20 +-
source/libwiigui/gui_filebrowser.cpp | 9 +-
source/libwiigui/gui_gamebrowser.cpp | 3 +-
source/libwiigui/gui_gamebrowser.h | 129 +-
source/libwiigui/gui_gamecarousel.cpp | 5 -
source/libwiigui/gui_gamecarousel.h | 106 +-
source/libwiigui/gui_gamegrid.cpp | 5 -
source/libwiigui/gui_gamegrid.h | 2 -
source/libwiigui/gui_keyboard.cpp | 9 +-
source/libwiigui/gui_numpad.cpp | 406 ++-
source/libwiigui/gui_optionbrowser.cpp | 4 -
source/libwiigui/gui_searchbar.cpp | 12 +-
source/libwiigui/gui_searchbar.h | 2 -
source/libwiigui/gui_sound.cpp | 446 ---
source/libwiigui/gui_sound_decoder.h | 114 -
source/libwiigui/gui_sound_decoder_aiff.cpp | 158 -
source/libwiigui/gui_sound_decoder_bns.cpp | 257 --
source/libwiigui/gui_sound_decoder_mpg.cpp | 213 --
source/libwiigui/gui_sound_decoder_ogg.cpp | 285 --
source/libwiigui/gui_sound_decoder_wav.cpp | 237 --
source/main.cpp | 2 +-
source/menu.cpp | 13 +-
source/menu.h | 3 -
source/menu/MountGamePartition.cpp | 2 +-
source/menu/menu_disclist.cpp | 41 +-
source/menu/menu_install.cpp | 2 -
source/menu/menu_partition_selection.cpp | 8 +-
source/menu/menus.h | 1 -
source/prompts/DiscBrowser.cpp | 33 +-
source/prompts/DiscBrowser.h | 5 +-
source/prompts/PromptWindows.cpp | 156 +-
source/prompts/TitleBrowser.cpp | 13 +-
source/prompts/filebrowser.cpp | 21 +-
source/prompts/gameinfo.cpp | 5 +-
source/settings/Settings.cpp | 3052 +----------------
source/settings/SettingsPrompts.cpp | 25 +-
source/settings/menus/CustomPathsSM.cpp | 252 ++
source/settings/menus/CustomPathsSM.hpp | 43 +
source/settings/menus/FlyingButtonsMenu.cpp | 462 +++
source/settings/menus/FlyingButtonsMenu.hpp | 103 +
source/settings/menus/GUISettingsMenu.cpp | 334 ++
source/settings/menus/GUISettingsMenu.hpp | 45 +
source/settings/menus/GameLoadSM.cpp | 327 ++
source/settings/menus/GameLoadSM.hpp | 45 +
source/settings/menus/GameSettingsMenu.cpp | 121 +
source/settings/menus/GameSettingsMenu.hpp | 44 +
source/settings/menus/GlobalSettings.cpp | 200 ++
source/settings/menus/GlobalSettings.hpp | 43 +
source/settings/menus/IndGameLoadSM.cpp | 409 +++
source/settings/menus/IndGameLoadSM.hpp | 51 +
source/settings/menus/ParentalControlSM.cpp | 181 +
source/settings/menus/ParentalControlSM.hpp | 42 +
source/settings/menus/SettingsMenu.cpp | 125 +
source/settings/menus/SettingsMenu.hpp | 72 +
source/settings/menus/SoundSettingsMenu.cpp | 180 +
source/settings/menus/SoundSettingsMenu.hpp | 42 +
source/settings/menus/UninstallSM.cpp | 175 +
source/settings/menus/UninstallSM.hpp | 44 +
source/sounds/button_click.pcm | Bin 7204 -> 0 bytes
source/sounds/button_click.wav | Bin 0 -> 4848 bytes
source/sounds/button_click2.pcm | Bin 152064 -> 0 bytes
source/sounds/button_click2.wav | Bin 0 -> 101424 bytes
source/sounds/button_over.pcm | Bin 32256 -> 0 bytes
source/sounds/button_over.wav | Bin 0 -> 21552 bytes
source/sys.cpp | 5 +
source/themes/Theme_Downloader.cpp | 40 +-
source/utils/timer.c | 119 +
source/utils/timer.h | 68 +
source/utils/uncompress.c | 185 +
source/utils/uncompress.h | 55 +
source/wad/wad.cpp | 16 +-
107 files changed, 8292 insertions(+), 6722 deletions(-)
create mode 100644 source/FileOperations/File.cpp
create mode 100644 source/FileOperations/File.hpp
create mode 100644 source/SoundOperations/AifDecoder.cpp
create mode 100644 source/SoundOperations/AifDecoder.hpp
create mode 100644 source/SoundOperations/BNSDecoder.cpp
create mode 100644 source/SoundOperations/BNSDecoder.hpp
create mode 100644 source/SoundOperations/BufferCircle.cpp
create mode 100644 source/SoundOperations/BufferCircle.hpp
create mode 100644 source/SoundOperations/Mp3Decoder.cpp
create mode 100644 source/SoundOperations/Mp3Decoder.hpp
create mode 100644 source/SoundOperations/OggDecoder.cpp
create mode 100644 source/SoundOperations/OggDecoder.hpp
create mode 100644 source/SoundOperations/SoundDecoder.cpp
create mode 100644 source/SoundOperations/SoundDecoder.hpp
create mode 100644 source/SoundOperations/SoundHandler.cpp
create mode 100644 source/SoundOperations/SoundHandler.hpp
create mode 100644 source/SoundOperations/WavDecoder.cpp
create mode 100644 source/SoundOperations/WavDecoder.hpp
rename source/{libwiigui => SoundOperations}/gui_bgm.cpp (87%)
rename source/{libwiigui => SoundOperations}/gui_bgm.h (86%)
create mode 100644 source/SoundOperations/gui_sound.cpp
create mode 100644 source/SoundOperations/gui_sound.h
delete mode 100644 source/libwiigui/gui_sound.cpp
delete mode 100644 source/libwiigui/gui_sound_decoder.h
delete mode 100644 source/libwiigui/gui_sound_decoder_aiff.cpp
delete mode 100644 source/libwiigui/gui_sound_decoder_bns.cpp
delete mode 100644 source/libwiigui/gui_sound_decoder_mpg.cpp
delete mode 100644 source/libwiigui/gui_sound_decoder_ogg.cpp
delete mode 100644 source/libwiigui/gui_sound_decoder_wav.cpp
create mode 100644 source/settings/menus/CustomPathsSM.cpp
create mode 100644 source/settings/menus/CustomPathsSM.hpp
create mode 100644 source/settings/menus/FlyingButtonsMenu.cpp
create mode 100644 source/settings/menus/FlyingButtonsMenu.hpp
create mode 100644 source/settings/menus/GUISettingsMenu.cpp
create mode 100644 source/settings/menus/GUISettingsMenu.hpp
create mode 100644 source/settings/menus/GameLoadSM.cpp
create mode 100644 source/settings/menus/GameLoadSM.hpp
create mode 100644 source/settings/menus/GameSettingsMenu.cpp
create mode 100644 source/settings/menus/GameSettingsMenu.hpp
create mode 100644 source/settings/menus/GlobalSettings.cpp
create mode 100644 source/settings/menus/GlobalSettings.hpp
create mode 100644 source/settings/menus/IndGameLoadSM.cpp
create mode 100644 source/settings/menus/IndGameLoadSM.hpp
create mode 100644 source/settings/menus/ParentalControlSM.cpp
create mode 100644 source/settings/menus/ParentalControlSM.hpp
create mode 100644 source/settings/menus/SettingsMenu.cpp
create mode 100644 source/settings/menus/SettingsMenu.hpp
create mode 100644 source/settings/menus/SoundSettingsMenu.cpp
create mode 100644 source/settings/menus/SoundSettingsMenu.hpp
create mode 100644 source/settings/menus/UninstallSM.cpp
create mode 100644 source/settings/menus/UninstallSM.hpp
delete mode 100644 source/sounds/button_click.pcm
create mode 100644 source/sounds/button_click.wav
delete mode 100644 source/sounds/button_click2.pcm
create mode 100644 source/sounds/button_click2.wav
delete mode 100644 source/sounds/button_over.pcm
create mode 100644 source/sounds/button_over.wav
create mode 100644 source/utils/timer.c
create mode 100644 source/utils/timer.h
create mode 100644 source/utils/uncompress.c
create mode 100644 source/utils/uncompress.h
diff --git a/Makefile b/Makefile
index 6e979142..68ee12a0 100644
--- a/Makefile
+++ b/Makefile
@@ -33,6 +33,7 @@ SOURCES := source \
source/xml \
source/network \
source/settings \
+ source/settings/menus \
source/prompts \
source/wad \
source/banner \
@@ -43,6 +44,7 @@ SOURCES := source \
source/memory \
source/FileOperations \
source/ImageOperations \
+ source/SoundOperations \
source/utils \
source/utils/minizip \
source/usbloader/wbfs
@@ -53,7 +55,7 @@ INCLUDES := source
# options for code generation
#---------------------------------------------------------------------------------
-CFLAGS = -g -O4 -Wall $(MACHDEP) $(INCLUDE) -DHAVE_CONFIG_H
+CFLAGS = -g -O4 -Wall -Wno-multichar $(MACHDEP) $(INCLUDE) -DHAVE_CONFIG_H
CXXFLAGS = -Xassembler -aln=$@.lst $(CFLAGS)
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map,--section-start,.init=0x80B00000,-wrap,malloc,-wrap,free,-wrap,memalign,-wrap,calloc,-wrap,realloc,-wrap,malloc_usable_size
-include $(PROJECTDIR)/Make.config
@@ -93,6 +95,7 @@ TTFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ttf)))
PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png)))
OGGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ogg)))
PCMFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.pcm)))
+WAVFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.wav)))
DOLFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.dol)))
MP3FILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.mp3)))
@@ -110,7 +113,7 @@ export OFILES := $(addsuffix .o,$(BINFILES)) \
$(sFILES:.s=.o) $(SFILES:.S=.o) \
$(TTFFILES:.ttf=.ttf.o) $(PNGFILES:.png=.png.o) $(addsuffix .o,$(DOLFILES))\
$(OGGFILES:.ogg=.ogg.o) $(PCMFILES:.pcm=.pcm.o) $(MP3FILES:.mp3=.mp3.o) \
- $(addsuffix .o,$(ELFFILES)) $(CURDIR)/data/magic_patcher.o
+ $(WAVFILES:.wav=.wav.o) $(addsuffix .o,$(ELFFILES)) $(CURDIR)/data/magic_patcher.o
#---------------------------------------------------------------------------------
# build a list of include paths
@@ -215,6 +218,10 @@ language: $(wildcard $(PROJECTDIR)/Languages/*.lang)
%.pcm.o : %.pcm
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
+
+%.wav.o : %.wav
+ @echo $(notdir $<)
+ @bin2s -a 32 $< | $(AS) -o $(@)
%.mp3.o : %.mp3
@echo $(notdir $<)
diff --git a/gui.pnproj b/gui.pnproj
index 1cf7bd39..621e2f15 100644
--- a/gui.pnproj
+++ b/gui.pnproj
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/gui.pnps b/gui.pnps
index cbff6d41..ce6765fe 100644
--- a/gui.pnps
+++ b/gui.pnps
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/source/FileOperations/File.cpp b/source/FileOperations/File.cpp
new file mode 100644
index 00000000..ce68add3
--- /dev/null
+++ b/source/FileOperations/File.cpp
@@ -0,0 +1,145 @@
+#include
+#include "File.hpp"
+
+CFile::CFile()
+{
+ file_fd = NULL;
+ mem_file = NULL;
+ filesize = 0;
+ Pos = 0;
+}
+
+CFile::CFile(const char * filepath, const char * mode)
+{
+ file_fd = NULL;
+ open(filepath, mode);
+}
+
+CFile::CFile(const u8 * mem, int size)
+{
+ file_fd = NULL;
+ open(mem, size);
+}
+
+CFile::~CFile()
+{
+ close();
+}
+
+int CFile::open(const char * filepath, const char * mode)
+{
+ close();
+
+ file_fd = fopen(filepath, mode);
+ if(!file_fd)
+ return -1;
+
+ fseek(file_fd, 0, SEEK_END);
+ filesize = ftell(file_fd);
+ rewind();
+
+ return 0;
+}
+
+int CFile::open(const u8 * mem, int size)
+{
+ close();
+
+ mem_file = mem;
+ filesize = size;
+
+ return 0;
+}
+
+void CFile::close()
+{
+ if(file_fd)
+ fclose(file_fd);
+
+ file_fd = NULL;
+ mem_file = NULL;
+ filesize = 0;
+ Pos = 0;
+}
+
+int CFile::read(u8 * ptr, size_t size)
+{
+ if(file_fd)
+ {
+ int ret = fread(ptr, 1, size, file_fd);
+ if(ret > 0)
+ Pos += ret;
+ return ret;
+ }
+
+ int readsize = size;
+
+ if(readsize > (long int) filesize-Pos)
+ readsize = filesize-Pos;
+
+ if(readsize <= 0)
+ return readsize;
+
+ if(mem_file != NULL)
+ {
+ memcpy(ptr, mem_file+Pos, readsize);
+ Pos += readsize;
+ return readsize;
+ }
+
+ return -1;
+}
+
+int CFile::write(const u8 * ptr, size_t size)
+{
+ if(size < 0)
+ return size;
+
+ if(file_fd)
+ {
+ int ret = fwrite(ptr, 1, size, file_fd);
+ if(ret > 0)
+ Pos += ret;
+ return ret;
+ }
+
+ return -1;
+}
+
+int CFile::seek(long int offset, int origin)
+{
+ int ret = 0;
+
+ if(origin == SEEK_SET)
+ {
+ Pos = offset;
+ }
+ else if(origin == SEEK_CUR)
+ {
+ Pos += offset;
+ }
+ else if(origin == SEEK_END)
+ {
+ Pos = filesize+offset;
+ }
+ if(Pos < 0)
+ {
+ Pos = 0;
+ return -1;
+ }
+
+ if(file_fd)
+ ret = fseek(file_fd, Pos, SEEK_SET);
+
+ if(mem_file != NULL)
+ {
+ if(Pos > (long int) filesize)
+ {
+ Pos = filesize;
+ return -1;
+ }
+ }
+
+ return ret;
+}
+
diff --git a/source/FileOperations/File.hpp b/source/FileOperations/File.hpp
new file mode 100644
index 00000000..b5e1af75
--- /dev/null
+++ b/source/FileOperations/File.hpp
@@ -0,0 +1,30 @@
+#ifndef FILE_HPP_
+#define FILE_HPP_
+
+#include
+#include
+
+class CFile
+{
+ public:
+ CFile();
+ CFile(const char * filepath, const char * mode);
+ CFile(const u8 * memory, int memsize);
+ ~CFile();
+ int open(const char * filepath, const char * mode);
+ int open(const u8 * memory, int memsize);
+ void close();
+ int read(u8 * ptr, size_t size);
+ int write(const u8 * ptr, size_t size);
+ int seek(long int offset, int origin);
+ long int tell() { return Pos; };
+ long int size() { return filesize; };
+ void rewind() { seek(0, SEEK_SET); };
+ protected:
+ FILE * file_fd;
+ const u8 * mem_file;
+ u64 filesize;
+ long int Pos;
+};
+
+#endif
diff --git a/source/SoundOperations/AifDecoder.cpp b/source/SoundOperations/AifDecoder.cpp
new file mode 100644
index 00000000..3fa2f2b8
--- /dev/null
+++ b/source/SoundOperations/AifDecoder.cpp
@@ -0,0 +1,214 @@
+/***************************************************************************
+ * Copyright (C) 2010
+ * by Dimok
+ *
+ * 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.
+ *
+ * for WiiXplorer 2010
+ ***************************************************************************/
+#include
+#include
+#include "AifDecoder.hpp"
+
+typedef struct
+{
+ u32 fccCOMM;
+ u32 size;
+ u16 channels;
+ u8 frames[4];
+ u16 bps;
+ u8 freq[10];
+} SAIFFCommChunk;
+
+typedef struct
+{
+ u32 fccSSND;
+ u32 size;
+ u32 offset;
+ u32 blockSize;
+} SAIFFSSndChunk;
+
+// ------
+// 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)
+
+static 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;
+}
+
+AifDecoder::AifDecoder(const char * filepath)
+ : SoundDecoder(filepath)
+{
+ SoundType = SOUND_AIF;
+
+ if(!file_fd)
+ return;
+
+ OpenFile();
+}
+
+AifDecoder::AifDecoder(const u8 * snd, int len)
+ : SoundDecoder(snd, len)
+{
+ SoundType = SOUND_AIF;
+
+ if(!file_fd)
+ return;
+
+ OpenFile();
+}
+
+AifDecoder::~AifDecoder()
+{
+}
+
+void AifDecoder::OpenFile()
+{
+ SWaveHdr Header;
+ file_fd->read((u8 *) &Header, sizeof(SWaveHdr));
+
+ if (Header.magicRIFF != 'FORM')
+ {
+ CloseFile();
+ return;
+ }
+ else if(Header.magicWAVE != 'AIFF')
+ {
+ CloseFile();
+ return;
+ }
+
+ SWaveChunk WaveChunk;
+ do
+ {
+ int ret = file_fd->read((u8 *) &WaveChunk, sizeof(SWaveChunk));
+ if(ret <= 0)
+ {
+ CloseFile();
+ return;
+ }
+ }
+ while(WaveChunk.magicDATA != 'COMM');
+
+ DataOffset = file_fd->tell()+WaveChunk.size;
+
+ SAIFFCommChunk CommHdr;
+ file_fd->seek(file_fd->tell()-sizeof(SWaveChunk), SEEK_SET);
+ file_fd->read((u8 *) &CommHdr, sizeof(SAIFFCommChunk));
+
+ if(CommHdr.fccCOMM != 'COMM')
+ {
+ CloseFile();
+ return;
+ }
+
+ file_fd->seek(DataOffset, SEEK_SET);
+
+ SAIFFSSndChunk SSndChunk;
+ file_fd->read((u8 *) &SSndChunk, sizeof(SAIFFSSndChunk));
+
+ if(SSndChunk.fccSSND != 'SSND')
+ {
+ CloseFile();
+ return;
+ }
+
+ DataOffset += sizeof(SAIFFSSndChunk);
+ DataSize = SSndChunk.size-8;
+ SampleRate = (u32) ConvertFromIeeeExtended(CommHdr.freq);
+ Format = VOICE_STEREO_16BIT;
+
+ if(CommHdr.channels == 1 && CommHdr.bps == 8)
+ Format = VOICE_MONO_8BIT;
+ else if (CommHdr.channels == 1 && CommHdr.bps == 16)
+ Format = VOICE_MONO_16BIT;
+ else if (CommHdr.channels == 2 && CommHdr.bps == 8)
+ Format = VOICE_STEREO_8BIT;
+ else if (CommHdr.channels == 2 && CommHdr.bps == 16)
+ Format = VOICE_STEREO_16BIT;
+
+ Decode();
+}
+
+void AifDecoder::CloseFile()
+{
+ if(file_fd)
+ delete file_fd;
+
+ file_fd = NULL;
+}
+
+int AifDecoder::Read(u8 * buffer, int buffer_size, int pos)
+{
+ if(!file_fd)
+ return -1;
+
+ if(CurPos >= (int) DataSize)
+ return 0;
+
+ file_fd->seek(DataOffset+CurPos, SEEK_SET);
+
+ if(buffer_size > (int) DataSize-CurPos)
+ buffer_size = DataSize-CurPos;
+
+ int read = file_fd->read(buffer, buffer_size);
+ if(read > 0)
+ {
+ CurPos += read;
+ }
+
+ return read;
+}
diff --git a/source/SoundOperations/AifDecoder.hpp b/source/SoundOperations/AifDecoder.hpp
new file mode 100644
index 00000000..f9c6fd91
--- /dev/null
+++ b/source/SoundOperations/AifDecoder.hpp
@@ -0,0 +1,50 @@
+/***************************************************************************
+ * Copyright (C) 2010
+ * by Dimok
+ *
+ * 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.
+ *
+ * for WiiXplorer 2010
+ ***************************************************************************/
+#ifndef AIFDECODER_HPP_
+#define AIFDECODER_HPP_
+
+#include "SoundDecoder.hpp"
+#include "WavDecoder.hpp"
+
+class AifDecoder : public SoundDecoder
+{
+ public:
+ AifDecoder(const char * filepath);
+ AifDecoder(const u8 * snd, int len);
+ ~AifDecoder();
+ int GetFormat() { return Format; };
+ int GetSampleRate() { return SampleRate; };
+ int Read(u8 * buffer, int buffer_size, int pos);
+ protected:
+ void OpenFile();
+ void CloseFile();
+ u32 DataOffset;
+ u32 DataSize;
+ u32 SampleRate;
+ u8 Format;
+};
+
+#endif
diff --git a/source/SoundOperations/BNSDecoder.cpp b/source/SoundOperations/BNSDecoder.cpp
new file mode 100644
index 00000000..e79a2442
--- /dev/null
+++ b/source/SoundOperations/BNSDecoder.cpp
@@ -0,0 +1,363 @@
+/***************************************************************************
+ * Copyright (C) 2010
+ * by Dimok
+ *
+ * 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.
+ *
+ * for WiiXplorer 2010
+ ***************************************************************************/
+#include
+#include
+#include
+#include
+#include "BNSDecoder.hpp"
+
+BNSDecoder::BNSDecoder(const char * filepath)
+ : SoundDecoder(filepath)
+{
+ SoundType = SOUND_BNS;
+ memset(&SoundData, 0, sizeof(SoundBlock));
+
+ if(!file_fd)
+ return;
+
+ OpenFile();
+}
+
+BNSDecoder::BNSDecoder(const u8 * snd, int len)
+ : SoundDecoder(snd, len)
+{
+ SoundType = SOUND_BNS;
+ memset(&SoundData, 0, sizeof(SoundBlock));
+
+ if(!file_fd)
+ return;
+
+ OpenFile();
+}
+
+BNSDecoder::~BNSDecoder()
+{
+ ExitRequested = true;
+ while(Decoding)
+ usleep(100);
+
+ if(SoundData.buffer != NULL)
+ free(SoundData.buffer);
+
+ SoundData.buffer = NULL;
+}
+
+void BNSDecoder::OpenFile()
+{
+ u8 * tempbuff = new (std::nothrow) u8[file_fd->size()];
+ if(!tempbuff)
+ {
+ CloseFile();
+ return;
+ }
+
+ int done = 0;
+
+ while(done < file_fd->size())
+ {
+ int read = file_fd->read(tempbuff, file_fd->size());
+ if(read > 0)
+ done += read;
+ else
+ {
+ CloseFile();
+ return;
+ }
+ }
+
+ SoundData = DecodefromBNS(tempbuff, done);
+ if(SoundData.buffer == NULL)
+ {
+ CloseFile();
+ return;
+ }
+
+ delete [] tempbuff;
+ tempbuff = NULL;
+
+ Decode();
+}
+
+void BNSDecoder::CloseFile()
+{
+ if(file_fd)
+ delete file_fd;
+
+ file_fd = NULL;
+}
+
+int BNSDecoder::Read(u8 * buffer, int buffer_size, int pos)
+{
+ if(!SoundData.buffer)
+ return -1;
+
+ if(SoundData.loopFlag)
+ {
+ int factor = SoundData.format == VOICE_STEREO_16BIT ? 4 : 2;
+ if(CurPos >= (int) SoundData.loopEnd*factor)
+ CurPos = SoundData.loopStart*factor;
+
+ if(buffer_size > (int) SoundData.loopEnd*factor-CurPos)
+ buffer_size = SoundData.loopEnd*factor-CurPos;
+ }
+ else
+ {
+ if(CurPos >= (int) SoundData.size)
+ return 0;
+
+ if(buffer_size > (int) SoundData.size-CurPos)
+ buffer_size = SoundData.size-CurPos;
+ }
+
+ memcpy(buffer, SoundData.buffer+CurPos, buffer_size);
+ CurPos += buffer_size;
+
+ return buffer_size;
+}
+
+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;
+}
+
+SoundBlock DecodefromBNS(const u8 *buffer, u32 size)
+{
+ SoundBlock OutBlock;
+ memset(&OutBlock, 0, sizeof(SoundBlock));
+
+ const BNSHeader &hdr = *(BNSHeader *)buffer;
+ if (size < sizeof hdr)
+ return OutBlock;
+ if (hdr.fccBNS != 'BNS ')
+ return OutBlock;
+ // 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 OutBlock;
+ // 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 OutBlock;
+ u8 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 OutBlock;
+ u32 freq = (u32) infoChunk.freq;
+ u32 length = 0;
+ // Copy data
+ if (infoChunk.codecNum == 0)
+ {
+ OutBlock.buffer = decodeBNS(length, infoChunk, dataChunk);
+ if (!OutBlock.buffer)
+ return OutBlock;
+ }
+ else
+ {
+ OutBlock.buffer = (u8*) malloc(dataChunk.size);
+ if (!OutBlock.buffer)
+ return OutBlock;
+ memcpy(OutBlock.buffer, &dataChunk.data, dataChunk.size);
+ length = dataChunk.size;
+ }
+
+ OutBlock.frequency = freq;
+ OutBlock.format = format;
+ OutBlock.size = length;
+ OutBlock.loopStart = infoChunk.loopStart;
+ OutBlock.loopEnd = infoChunk.loopEnd;
+ OutBlock.loopFlag = infoChunk.loopFlag;
+
+ return OutBlock;
+}
diff --git a/source/SoundOperations/BNSDecoder.hpp b/source/SoundOperations/BNSDecoder.hpp
new file mode 100644
index 00000000..4c9d76c3
--- /dev/null
+++ b/source/SoundOperations/BNSDecoder.hpp
@@ -0,0 +1,59 @@
+/***************************************************************************
+ * Copyright (C) 2010
+ * by Dimok
+ *
+ * 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.
+ *
+ * for WiiXplorer 2010
+ ***************************************************************************/
+#ifndef BNSDECODER_HPP_
+#define BNSDECODER_HPP_
+
+#include "SoundDecoder.hpp"
+
+typedef struct _SoundBlock
+{
+ u8 * buffer;
+ u32 size;
+ u8 format;
+ u32 frequency;
+ u32 loopStart;
+ u32 loopEnd;
+ u8 loopFlag;
+} SoundBlock;
+
+class BNSDecoder : public SoundDecoder
+{
+ public:
+ BNSDecoder(const char * filepath);
+ BNSDecoder(const u8 * snd, int len);
+ ~BNSDecoder();
+ int GetFormat() { return SoundData.format; };
+ int GetSampleRate() { return SoundData.frequency; };
+ int Read(u8 * buffer, int buffer_size, int pos);
+ protected:
+ void OpenFile();
+ void CloseFile();
+ SoundBlock SoundData;
+};
+
+SoundBlock DecodefromBNS(const u8 *buffer, u32 size);
+
+#endif
diff --git a/source/SoundOperations/BufferCircle.cpp b/source/SoundOperations/BufferCircle.cpp
new file mode 100644
index 00000000..a8ff1e44
--- /dev/null
+++ b/source/SoundOperations/BufferCircle.cpp
@@ -0,0 +1,144 @@
+/***************************************************************************
+ * Copyright (C) 2010
+ * by Dimok
+ *
+ * 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.
+ *
+ * for WiiXplorer 2010
+ ***************************************************************************/
+#include
+#include "BufferCircle.hpp"
+
+#define ALIGN32(x) (((x) + 31) & ~31)
+
+BufferCircle::BufferCircle()
+{
+ which = 0;
+ BufferBlockSize = 0;
+}
+
+BufferCircle::~BufferCircle()
+{
+ FreeBuffer();
+ SoundBuffer.clear();
+ BufferSize.clear();
+ BufferReady.clear();
+}
+
+void BufferCircle::SetBufferBlockSize(int size)
+{
+ if(size < 0)
+ return;
+
+ BufferBlockSize = size;
+
+ for(int i = 0; i < Size(); i++)
+ {
+ if(SoundBuffer[i] != NULL)
+ free(SoundBuffer[i]);
+
+ SoundBuffer[i] = (u8 *) memalign(32, ALIGN32(BufferBlockSize));
+ BufferSize[i] = 0;
+ BufferReady[i] = false;
+ }
+}
+
+void BufferCircle::Resize(int size)
+{
+ while(size < Size())
+ RemoveBuffer(Size()-1);
+
+ int oldSize = Size();
+
+ SoundBuffer.resize(size);
+ BufferSize.resize(size);
+ BufferReady.resize(size);
+
+ for(int i = oldSize; i < Size(); i++)
+ {
+ if(BufferBlockSize > 0)
+ SoundBuffer[i] = (u8 *) memalign(32, ALIGN32(BufferBlockSize));
+ else
+ SoundBuffer[i] = NULL;
+ BufferSize[i] = 0;
+ BufferReady[i] = false;
+ }
+}
+
+void BufferCircle::RemoveBuffer(int pos)
+{
+ if(!Valid(pos))
+ return;
+
+ if(SoundBuffer[pos] != NULL)
+ free(SoundBuffer[pos]);
+
+ SoundBuffer.erase(SoundBuffer.begin()+pos);
+ BufferSize.erase(BufferSize.begin()+pos);
+ BufferReady.erase(BufferReady.begin()+pos);
+}
+
+void BufferCircle::ClearBuffer()
+{
+ for(int i = 0; i < Size(); i++)
+ {
+ BufferSize[i] = 0;
+ BufferReady[i] = false;
+ }
+ which = 0;
+}
+
+void BufferCircle::FreeBuffer()
+{
+ for(int i = 0; i < Size(); i++)
+ {
+ if(SoundBuffer[i] != NULL)
+ free(SoundBuffer[i]);
+
+ SoundBuffer[i] = NULL;
+ BufferSize[i] = 0;
+ BufferReady[i] = false;
+ }
+}
+
+void BufferCircle::LoadNext()
+{
+ int pos = (which+Size()-1) % Size();
+ BufferReady[pos] = false;
+ BufferSize[pos] = 0;
+
+ which = (which+1) % Size();
+}
+
+void BufferCircle::SetBufferReady(int pos, bool state)
+{
+ if(!Valid(pos))
+ return;
+
+ BufferReady[pos] = state;
+}
+
+void BufferCircle::SetBufferSize(int pos, int size)
+{
+ if(!Valid(pos))
+ return;
+
+ BufferSize[pos] = size;
+}
diff --git a/source/SoundOperations/BufferCircle.hpp b/source/SoundOperations/BufferCircle.hpp
new file mode 100644
index 00000000..56ab0898
--- /dev/null
+++ b/source/SoundOperations/BufferCircle.hpp
@@ -0,0 +1,92 @@
+/***************************************************************************
+ * Copyright (C) 2010
+ * by Dimok
+ *
+ * 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.
+ *
+ * for WiiXplorer 2010
+ ***************************************************************************/
+#ifndef BUFFER_CIRCLE_HPP_
+#define BUFFER_CIRCLE_HPP_
+
+#include
+#include
+
+class BufferCircle
+{
+ public:
+ //!> Constructor
+ BufferCircle();
+ //!> Destructor
+ ~BufferCircle();
+ //!> Set circle size
+ void Resize(int size);
+ //!> Get the circle size
+ int Size() { return SoundBuffer.size(); };
+ //!> Set/resize the buffer size
+ void SetBufferBlockSize(int size);
+ //!> Remove a buffer
+ void RemoveBuffer(int pos);
+ //!> Set all buffers clear
+ void ClearBuffer();
+ //!> Free all buffers
+ void FreeBuffer();
+ //!> Switch to next buffer
+ void LoadNext();
+ //!> Get the current buffer
+ u8 * GetBuffer() { if(!Valid(which)) return 0; return SoundBuffer[which]; };
+ //!> Get a buffer at a position
+ u8 * GetBuffer(int pos) { if(!Valid(pos)) return NULL; else return SoundBuffer[pos]; };
+ //!> Get next buffer
+ u8 * GetNextBuffer() { if(Size() <= 0) return 0; else return SoundBuffer[(which+1) % Size()]; };
+ //!> Get previous buffer
+ u8 * GetLastBuffer() { if(Size() <= 0) return 0; else return SoundBuffer[(which+Size()-1) % Size()]; };
+ //!> Get current buffer size
+ u32 GetBufferSize() { if(!Valid(which)) return 0; else return BufferSize[which]; };
+ //!> Get buffer size at position
+ u32 GetBufferSize(int pos) { if(!Valid(pos)) return 0; else return BufferSize[pos]; };
+ //!> Get previous buffer size
+ u32 GetLastBufferSize() { if(Size() <= 0) return 0; else return BufferSize[(which+Size()-1) % Size()]; };
+ //!> Is current buffer ready
+ bool IsBufferReady() { if(!Valid(which)) return false; else return BufferReady[which]; };
+ //!> Is a buffer at a position ready
+ bool IsBufferReady(int pos) { if(!Valid(pos)) return false; else return BufferReady[pos]; };
+ //!> Is next buffer ready
+ bool IsNextBufferReady() { if(Size() <= 0) return false; else return BufferReady[(which+1) % Size()]; };
+ //!> Is last buffer ready
+ bool IsLastBufferReady() { if(Size() <= 0) return false; else return BufferReady[(which+Size()-1) % Size()]; };
+ //!> Set a buffer at a position to a ready state
+ void SetBufferReady(int pos, bool st);
+ //!> Set the buffersize at a position
+ void SetBufferSize(int pos, int size);
+ //!> Get the current position in the circle
+ u16 Which() { return which; };
+ protected:
+ //!> Check if the position is a valid position in the vector
+ bool Valid(int pos) { return !(which < 0 || which >= Size()); };
+
+ u16 which;
+ u32 BufferBlockSize;
+ std::vector SoundBuffer;
+ std::vector BufferSize;
+ std::vector BufferReady;
+};
+
+#endif
diff --git a/source/SoundOperations/Mp3Decoder.cpp b/source/SoundOperations/Mp3Decoder.cpp
new file mode 100644
index 00000000..13dd0ae7
--- /dev/null
+++ b/source/SoundOperations/Mp3Decoder.cpp
@@ -0,0 +1,216 @@
+/***************************************************************************
+ * Copyright (C) 2010
+ * by Dimok
+ *
+ * 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.
+ *
+ * for WiiXplorer 2010
+ ***************************************************************************/
+#include
+#include
+#include
+#include
+#include
+#include
+#include "Mp3Decoder.hpp"
+
+Mp3Decoder::Mp3Decoder(const char * filepath)
+ : SoundDecoder(filepath)
+{
+ SoundType = SOUND_MP3;
+ ReadBuffer = NULL;
+ mad_timer_reset(&Timer);
+ mad_stream_init(&Stream);
+ mad_frame_init(&Frame);
+ mad_synth_init(&Synth);
+
+ if(!file_fd)
+ return;
+
+ OpenFile();
+}
+
+Mp3Decoder::Mp3Decoder(const u8 * snd, int len)
+ : SoundDecoder(snd, len)
+{
+ SoundType = SOUND_MP3;
+ ReadBuffer = NULL;
+ mad_timer_reset(&Timer);
+ mad_stream_init(&Stream);
+ mad_frame_init(&Frame);
+ mad_synth_init(&Synth);
+
+ if(!file_fd)
+ return;
+
+ OpenFile();
+}
+
+Mp3Decoder::~Mp3Decoder()
+{
+ ExitRequested = true;
+ while(Decoding)
+ usleep(100);
+
+ mad_synth_finish(&Synth);
+ mad_frame_finish(&Frame);
+ mad_stream_finish(&Stream);
+
+ if(ReadBuffer)
+ free(ReadBuffer);
+ ReadBuffer = NULL;
+}
+
+void Mp3Decoder::OpenFile()
+{
+ GuardPtr = NULL;
+ ReadBuffer = (u8 *) memalign(32, SoundBlockSize*SoundBlocks);
+ if(!ReadBuffer)
+ {
+ if(file_fd)
+ delete file_fd;
+ file_fd = NULL;
+ return;
+ }
+
+ u8 dummybuff[4096];
+ int ret = Read((u8 *) &dummybuff, 4096, 0);
+ if(ret <= 0)
+ {
+ if(file_fd)
+ delete file_fd;
+ file_fd = NULL;
+ return;
+ }
+
+ SampleRate = (u32) Frame.header.samplerate;
+ Format = ((MAD_NCHANNELS(&Frame.header) == 2) ? VOICE_STEREO_16BIT : VOICE_MONO_16BIT);
+ Rewind();
+ Decode();
+}
+
+int Mp3Decoder::Rewind()
+{
+ mad_synth_finish(&Synth);
+ mad_frame_finish(&Frame);
+ mad_stream_finish(&Stream);
+ mad_timer_reset(&Timer);
+ mad_stream_init(&Stream);
+ mad_frame_init(&Frame);
+ mad_synth_init(&Synth);
+ SynthPos = 0;
+ GuardPtr = NULL;
+
+ if(!file_fd)
+ return -1;
+
+ return SoundDecoder::Rewind();
+}
+
+static inline s16 FixedToShort(mad_fixed_t Fixed)
+{
+ /* Clipping */
+ if(Fixed>=MAD_F_ONE)
+ return(SHRT_MAX);
+ if(Fixed<=-MAD_F_ONE)
+ return(-SHRT_MAX);
+
+ Fixed=Fixed>>(MAD_F_FRACBITS-15);
+ return((s16)Fixed);
+}
+
+int Mp3Decoder::Read(u8 * buffer, int buffer_size, int pos)
+{
+ if(!file_fd)
+ return -1;
+
+ if(Format == VOICE_STEREO_16BIT)
+ buffer_size &= ~0x0003;
+ else
+ buffer_size &= ~0x0001;
+
+ u8 * write_pos = buffer;
+ u8 * write_end = buffer+buffer_size;
+
+ while(1)
+ {
+ while(SynthPos < Synth.pcm.length)
+ {
+ if(write_pos >= write_end)
+ return write_pos-buffer;
+
+ *((s16 *) write_pos) = FixedToShort(Synth.pcm.samples[0][SynthPos]);
+ write_pos += 2;
+
+ if(MAD_NCHANNELS(&Frame.header) == 2)
+ {
+ *((s16 *) write_pos) = FixedToShort(Synth.pcm.samples[1][SynthPos]);
+ write_pos += 2;
+ }
+ SynthPos++;
+ }
+
+ if(Stream.buffer == NULL || Stream.error == MAD_ERROR_BUFLEN)
+ {
+ u8 * ReadStart = ReadBuffer;
+ int ReadSize = SoundBlockSize*SoundBlocks;
+ int Remaining = 0;
+
+ if(Stream.next_frame != NULL)
+ {
+ Remaining = Stream.bufend - Stream.next_frame;
+ memmove(ReadBuffer, Stream.next_frame, Remaining);
+ ReadStart += Remaining;
+ ReadSize -= Remaining;
+ }
+
+ ReadSize = file_fd->read(ReadStart, ReadSize);
+ if(ReadSize <= 0)
+ {
+ GuardPtr = ReadStart;
+ memset(GuardPtr, 0, MAD_BUFFER_GUARD);
+ ReadSize = MAD_BUFFER_GUARD;
+ }
+
+ CurPos += ReadSize;
+ mad_stream_buffer(&Stream, ReadBuffer, Remaining+ReadSize);
+ }
+
+ if(mad_frame_decode(&Frame,&Stream))
+ {
+ if(MAD_RECOVERABLE(Stream.error))
+ {
+ if(Stream.error != MAD_ERROR_LOSTSYNC || !GuardPtr)
+ continue;
+ }
+ else
+ {
+ if(Stream.error != MAD_ERROR_BUFLEN)
+ return -1;
+ else if(Stream.error == MAD_ERROR_BUFLEN && GuardPtr)
+ return -1;
+ }
+ }
+
+ mad_timer_add(&Timer,Frame.header.duration);
+ mad_synth_frame(&Synth,&Frame);
+ SynthPos = 0;
+ }
+}
diff --git a/source/SoundOperations/Mp3Decoder.hpp b/source/SoundOperations/Mp3Decoder.hpp
new file mode 100644
index 00000000..a622f1f3
--- /dev/null
+++ b/source/SoundOperations/Mp3Decoder.hpp
@@ -0,0 +1,51 @@
+/***************************************************************************
+ * Copyright (C) 2010
+ * by Dimok
+ *
+ * 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.
+ *
+ * for WiiXplorer 2010
+ ***************************************************************************/
+#include
+
+#include "SoundDecoder.hpp"
+
+class Mp3Decoder : public SoundDecoder
+{
+ public:
+ Mp3Decoder(const char * filepath);
+ Mp3Decoder(const u8 * sound, int len);
+ ~Mp3Decoder();
+ int GetFormat() { return Format; };
+ int GetSampleRate() { return SampleRate; };
+ int Rewind();
+ int Read(u8 * buffer, int buffer_size, int pos);
+ protected:
+ void OpenFile();
+ struct mad_stream Stream;
+ struct mad_frame Frame;
+ struct mad_synth Synth;
+ mad_timer_t Timer;
+ u8 * GuardPtr;
+ u8 * ReadBuffer;
+ u8 Format;
+ u32 SampleRate;
+ u32 SynthPos;
+};
diff --git a/source/SoundOperations/OggDecoder.cpp b/source/SoundOperations/OggDecoder.cpp
new file mode 100644
index 00000000..904270ac
--- /dev/null
+++ b/source/SoundOperations/OggDecoder.cpp
@@ -0,0 +1,144 @@
+/***************************************************************************
+ * Copyright (C) 2010
+ * by Dimok
+ *
+ * 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.
+ *
+ * for WiiXplorer 2010
+ ***************************************************************************/
+#include
+#include
+#include "OggDecoder.hpp"
+
+extern "C" int ogg_read(void * punt, int bytes, int blocks, int *f)
+{
+ return ((CFile *) f)->read((u8 *) punt, bytes*blocks);
+}
+
+extern "C" int ogg_seek(int *f, ogg_int64_t offset, int mode)
+{
+ return ((CFile *) f)->seek((u64) offset, mode);
+}
+
+extern "C" int ogg_close(int *f)
+{
+ ((CFile *) f)->close();
+ return 0;
+}
+
+extern "C" long ogg_tell(int *f)
+{
+ return (long) ((CFile *) f)->tell();
+}
+
+static ov_callbacks callbacks = {
+ (size_t (*)(void *, size_t, size_t, void *)) ogg_read,
+ (int (*)(void *, ogg_int64_t, int)) ogg_seek,
+ (int (*)(void *)) ogg_close,
+ (long (*)(void *)) ogg_tell
+};
+
+OggDecoder::OggDecoder(const char * filepath)
+ : SoundDecoder(filepath)
+{
+ SoundType = SOUND_OGG;
+
+ if(!file_fd)
+ return;
+
+ OpenFile();
+}
+
+OggDecoder::OggDecoder(const u8 * snd, int len)
+ : SoundDecoder(snd, len)
+{
+ SoundType = SOUND_OGG;
+
+ if(!file_fd)
+ return;
+
+ OpenFile();
+}
+
+OggDecoder::~OggDecoder()
+{
+ ExitRequested = true;
+ while(Decoding)
+ usleep(100);
+
+ if(file_fd)
+ ov_clear(&ogg_file);
+}
+
+void OggDecoder::OpenFile()
+{
+ if (ov_open_callbacks(file_fd, &ogg_file, NULL, 0, callbacks) < 0)
+ {
+ delete file_fd;
+ file_fd = NULL;
+ return;
+ }
+
+ ogg_info = ov_info(&ogg_file, -1);
+ Decode();
+}
+
+int OggDecoder::GetFormat()
+{
+ if(!file_fd)
+ return VOICE_STEREO_16BIT;
+
+ return ((ogg_info->channels == 2) ? VOICE_STEREO_16BIT : VOICE_MONO_16BIT);
+}
+
+int OggDecoder::GetSampleRate()
+{
+ if(!file_fd)
+ return 0;
+
+ return (int) ogg_info->rate;
+}
+
+int OggDecoder::Rewind()
+{
+ if(!file_fd)
+ return -1;
+
+ int ret = ov_time_seek(&ogg_file, 0);
+ CurPos = 0;
+ EndOfFile = false;
+
+ return ret;
+}
+
+int OggDecoder::Read(u8 * buffer, int buffer_size, int pos)
+{
+ if(!file_fd)
+ return -1;
+
+ int bitstream = 0;
+
+ int read = ov_read(&ogg_file, (char *) buffer, buffer_size, &bitstream);
+
+ if(read > 0)
+ CurPos += read;
+
+ return read;
+}
diff --git a/source/SoundOperations/OggDecoder.hpp b/source/SoundOperations/OggDecoder.hpp
new file mode 100644
index 00000000..49de225e
--- /dev/null
+++ b/source/SoundOperations/OggDecoder.hpp
@@ -0,0 +1,45 @@
+/***************************************************************************
+ * Copyright (C) 2010
+ * by Dimok
+ *
+ * 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.
+ *
+ * for WiiXplorer 2010
+ ***************************************************************************/
+#include
+#include
+
+#include "SoundDecoder.hpp"
+
+class OggDecoder : public SoundDecoder
+{
+ public:
+ OggDecoder(const char * filepath);
+ OggDecoder(const u8 * snd, int len);
+ ~OggDecoder();
+ int GetFormat();
+ int GetSampleRate();
+ int Rewind();
+ int Read(u8 * buffer, int buffer_size, int pos);
+ protected:
+ void OpenFile();
+ OggVorbis_File ogg_file;
+ vorbis_info *ogg_info;
+};
diff --git a/source/SoundOperations/SoundDecoder.cpp b/source/SoundOperations/SoundDecoder.cpp
new file mode 100644
index 00000000..f4bc6ecb
--- /dev/null
+++ b/source/SoundOperations/SoundDecoder.cpp
@@ -0,0 +1,156 @@
+/***************************************************************************
+ * Copyright (C) 2010
+ * by Dimok
+ *
+ * 3Band resampling thanks to libmad
+ *
+ * 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.
+ *
+ * for WiiXplorer 2010
+ ***************************************************************************/
+#include
+#include
+#include
+#include
+#include "SoundDecoder.hpp"
+#include "main.h"
+
+SoundDecoder::SoundDecoder()
+{
+ file_fd = NULL;
+ Init();
+}
+
+SoundDecoder::SoundDecoder(const char * filepath)
+{
+ file_fd = new CFile(filepath, "rb");
+ Init();
+}
+
+SoundDecoder::SoundDecoder(const u8 * buffer, int size)
+{
+ file_fd = new CFile(buffer, size);
+ Init();
+}
+
+SoundDecoder::~SoundDecoder()
+{
+ ExitRequested = true;
+ while(Decoding)
+ usleep(100);
+
+ if(file_fd)
+ delete file_fd;
+ file_fd = NULL;
+}
+
+void SoundDecoder::Init()
+{
+ SoundType = SOUND_RAW;
+ SoundBlocks = 8;
+ SoundBlockSize = 8192;
+ CurPos = 0;
+ Loop = false;
+ EndOfFile = false;
+ Decoding = false;
+ ExitRequested = false;
+ SoundBuffer.SetBufferBlockSize(SoundBlockSize);
+ SoundBuffer.Resize(SoundBlocks);
+}
+
+int SoundDecoder::Rewind()
+{
+ CurPos = 0;
+ EndOfFile = false;
+ file_fd->rewind();
+
+ return 0;
+}
+
+int SoundDecoder::Read(u8 * buffer, int buffer_size, int pos)
+{
+ int ret = file_fd->read(buffer, buffer_size);
+ CurPos += ret;
+
+ return ret;
+}
+
+void SoundDecoder::Decode()
+{
+ if(!file_fd || ExitRequested || EndOfFile)
+ return;
+
+ u16 newWhich = SoundBuffer.Which();
+ u16 i = 0;
+ for (i = 0; i < SoundBuffer.Size()-2; i++)
+ {
+ if(!SoundBuffer.IsBufferReady(newWhich))
+ break;
+
+ newWhich = (newWhich+1) % SoundBuffer.Size();
+ }
+
+ if(i == SoundBuffer.Size()-2)
+ return;
+
+ Decoding = true;
+
+ int done = 0;
+ u8 * write_buf = SoundBuffer.GetBuffer(newWhich);
+ if(!write_buf)
+ {
+ ExitRequested = true;
+ Decoding = false;
+ return;
+ }
+
+ while(done < SoundBlockSize)
+ {
+ int ret = Read(&write_buf[done], SoundBlockSize-done, Tell());
+
+ if(ret <= 0)
+ {
+ if(Loop)
+ {
+ Rewind();
+ continue;
+ }
+ else
+ {
+ EndOfFile = true;
+ break;
+ }
+ }
+
+ done += ret;
+ }
+
+ if(done > 0)
+ {
+ SoundBuffer.SetBufferSize(newWhich, done);
+ SoundBuffer.SetBufferReady(newWhich, true);
+ }
+
+ if(!SoundBuffer.IsBufferReady((newWhich+1) % SoundBuffer.Size()))
+ Decode();
+
+ Decoding = false;
+}
+
diff --git a/source/SoundOperations/SoundDecoder.hpp b/source/SoundOperations/SoundDecoder.hpp
new file mode 100644
index 00000000..b9e71ad4
--- /dev/null
+++ b/source/SoundOperations/SoundDecoder.hpp
@@ -0,0 +1,89 @@
+/***************************************************************************
+ * Copyright (C) 2010
+ * by Dimok
+ *
+ * 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.
+ *
+ * for WiiXplorer 2010
+ ***************************************************************************/
+#ifndef SOUND_DECODER_HPP
+#define SOUND_DECODER_HPP
+
+#include
+#include
+#include
+#include "utils/timer.h"
+#include "FileOperations/File.hpp"
+#include "BufferCircle.hpp"
+
+enum
+{
+ SOUND_RAW = 0,
+ SOUND_MP3,
+ SOUND_OGG,
+ SOUND_WAV,
+ SOUND_BNS,
+ SOUND_AIF
+};
+
+class SoundDecoder
+{
+ public:
+ SoundDecoder();
+ SoundDecoder(const char * filepath);
+ SoundDecoder(const u8 * buffer, int size);
+ ~SoundDecoder();
+ virtual int Read(u8 * buffer, int buffer_size, int pos);
+ virtual int Tell() { return CurPos; };
+ virtual int Seek(int pos) { CurPos = pos; return file_fd->seek(CurPos, SEEK_SET); };
+ virtual int Rewind();
+ virtual int GetFormat() { return VOICE_STEREO_16BIT; };
+ virtual int GetSampleRate() { return 48000; };
+ virtual void Decode();
+ virtual u32 GetBufferSize() { return SoundBuffer.GetBufferSize(); };
+ virtual u8 * GetBuffer() { return SoundBuffer.GetBuffer(); };
+ virtual u8 * GetNextBuffer() { return SoundBuffer.GetNextBuffer(); };
+ virtual u8 * GetLastBuffer() { return SoundBuffer.GetLastBuffer(); };
+ virtual void LoadNext() { SoundBuffer.LoadNext(); };
+ virtual bool IsBufferReady() { return SoundBuffer.IsBufferReady(); };
+ virtual bool IsNextBufferReady() { return SoundBuffer.IsNextBufferReady(); };
+ virtual bool IsLastBufferReady() { return SoundBuffer.IsLastBufferReady(); };
+ virtual bool IsEOF() { return EndOfFile; };
+ virtual void SetLoop(bool l) { Loop = l; };
+ virtual u8 GetSoundType() { return SoundType; };
+ virtual void ClearBuffer() { SoundBuffer.ClearBuffer(); };
+ virtual bool IsStereo() { return (GetFormat() == VOICE_STEREO_16BIT || GetFormat() == VOICE_STEREO_8BIT); };
+ virtual bool Is16Bit() { return (GetFormat() == VOICE_STEREO_16BIT || GetFormat() == VOICE_MONO_16BIT); };
+ protected:
+ void Init();
+
+ CFile * file_fd;
+ BufferCircle SoundBuffer;
+ u8 SoundType;
+ u16 SoundBlocks;
+ int SoundBlockSize;
+ int CurPos;
+ bool Loop;
+ bool EndOfFile;
+ bool Decoding;
+ bool ExitRequested;
+};
+
+#endif
diff --git a/source/SoundOperations/SoundHandler.cpp b/source/SoundOperations/SoundHandler.cpp
new file mode 100644
index 00000000..a4548886
--- /dev/null
+++ b/source/SoundOperations/SoundHandler.cpp
@@ -0,0 +1,271 @@
+/***************************************************************************
+ * Copyright (C) 2010
+ * by Dimok
+ *
+ * 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.
+ *
+ * for WiiXplorer 2010
+ ***************************************************************************/
+#include
+#include
+#include "SoundHandler.hpp"
+#include "Mp3Decoder.hpp"
+#include "OggDecoder.hpp"
+#include "WavDecoder.hpp"
+#include "AifDecoder.hpp"
+#include "BNSDecoder.hpp"
+
+SoundHandler * SoundHandler::instance = NULL;
+
+SoundHandler::SoundHandler()
+{
+ Decoding = false;
+ ExitRequested = false;
+ for(u32 i = 0; i < MAX_DECODERS; ++i)
+ DecoderList[i] = NULL;
+
+ ThreadStack = (u8 *) memalign(32, 32768);
+ if(!ThreadStack)
+ return;
+
+ LWP_CreateThread(&SoundThread, UpdateThread, this, ThreadStack, 32768, 80);
+}
+
+SoundHandler::~SoundHandler()
+{
+ ExitRequested = true;
+ ThreadSignal();
+ LWP_JoinThread(SoundThread, NULL);
+ SoundThread = LWP_THREAD_NULL;
+ if(ThreadStack)
+ free(ThreadStack);
+
+ ClearDecoderList();
+}
+
+SoundHandler * SoundHandler::Instance()
+{
+ if (instance == NULL)
+ {
+ instance = new SoundHandler();
+ }
+ return instance;
+}
+
+void SoundHandler::DestroyInstance()
+{
+ if(instance)
+ {
+ delete instance;
+ }
+ instance = NULL;
+}
+
+void SoundHandler::AddDecoder(int voice, const char * filepath)
+{
+ if(voice < 0 || voice >= MAX_DECODERS)
+ return;
+
+ if(DecoderList[voice] != NULL)
+ RemoveDecoder(voice);
+
+ DecoderList[voice] = GetSoundDecoder(filepath);
+}
+
+void SoundHandler::AddDecoder(int voice, const u8 * snd, int len)
+{
+ if(voice < 0 || voice >= MAX_DECODERS)
+ return;
+
+ if(DecoderList[voice] != NULL)
+ RemoveDecoder(voice);
+
+ DecoderList[voice] = GetSoundDecoder(snd, len);
+}
+
+void SoundHandler::RemoveDecoder(int voice)
+{
+ if(voice < 0 || voice >= MAX_DECODERS)
+ return;
+
+ if(DecoderList[voice] != NULL)
+ {
+ if(DecoderList[voice]->GetSoundType() == SOUND_OGG) delete ((OggDecoder *) DecoderList[voice]);
+ else if(DecoderList[voice]->GetSoundType() == SOUND_MP3) delete ((Mp3Decoder *) DecoderList[voice]);
+ else if(DecoderList[voice]->GetSoundType() == SOUND_WAV) delete ((WavDecoder *) DecoderList[voice]);
+ else if(DecoderList[voice]->GetSoundType() == SOUND_AIF) delete ((AifDecoder *) DecoderList[voice]);
+ else if(DecoderList[voice]->GetSoundType() == SOUND_BNS) delete ((BNSDecoder *) DecoderList[voice]);
+ else delete DecoderList[voice];
+ }
+
+ DecoderList[voice] = NULL;
+}
+
+void SoundHandler::ClearDecoderList()
+{
+ for(u32 i = 0; i < MAX_DECODERS; ++i)
+ RemoveDecoder(i);
+}
+
+static inline bool CheckMP3Signature(const u8 * buffer)
+{
+ const char MP3_Magic[][3] =
+ {
+ {'I', 'D', '3'}, //'ID3'
+ {0xff, 0xfe}, //'MPEG ADTS, layer III, v1.0 [protected]', 'mp3', 'audio/mpeg'),
+ {0xff, 0xff}, //'MPEG ADTS, layer III, v1.0', 'mp3', 'audio/mpeg'),
+ {0xff, 0xfa}, //'MPEG ADTS, layer III, v1.0 [protected]', 'mp3', 'audio/mpeg'),
+ {0xff, 0xfb}, //'MPEG ADTS, layer III, v1.0', 'mp3', 'audio/mpeg'),
+ {0xff, 0xf2}, //'MPEG ADTS, layer III, v2.0 [protected]', 'mp3', 'audio/mpeg'),
+ {0xff, 0xf3}, //'MPEG ADTS, layer III, v2.0', 'mp3', 'audio/mpeg'),
+ {0xff, 0xf4}, //'MPEG ADTS, layer III, v2.0 [protected]', 'mp3', 'audio/mpeg'),
+ {0xff, 0xf5}, //'MPEG ADTS, layer III, v2.0', 'mp3', 'audio/mpeg'),
+ {0xff, 0xf6}, //'MPEG ADTS, layer III, v2.0 [protected]', 'mp3', 'audio/mpeg'),
+ {0xff, 0xf7}, //'MPEG ADTS, layer III, v2.0', 'mp3', 'audio/mpeg'),
+ {0xff, 0xe2}, //'MPEG ADTS, layer III, v2.5 [protected]', 'mp3', 'audio/mpeg'),
+ {0xff, 0xe3}, //'MPEG ADTS, layer III, v2.5', 'mp3', 'audio/mpeg'),
+ };
+
+ if(buffer[0] == MP3_Magic[0][0] && buffer[1] == MP3_Magic[0][1] &&
+ buffer[2] == MP3_Magic[0][2])
+ {
+ return true;
+ }
+
+ for(int i = 1; i < 13; i++)
+ {
+ if(buffer[0] == MP3_Magic[i][0] && buffer[1] == MP3_Magic[i][1])
+ return true;
+ }
+
+ return false;
+}
+
+SoundDecoder * SoundHandler::GetSoundDecoder(const char * filepath)
+{
+ u32 magic;
+ CFile f(filepath, "rb");
+ if(f.size() == 0)
+ return NULL;
+
+ do
+ {
+ f.read((u8 *) &magic, 1);
+ }
+ while(((u8 *) &magic)[0] == 0 && f.tell() < f.size());
+
+ if(f.tell() == f.size())
+ return NULL;
+
+ f.seek(f.tell()-1, SEEK_SET);
+ f.read((u8 *) &magic, 4);
+ f.close();
+
+ if(magic == 'OggS')
+ {
+ return new OggDecoder(filepath);
+ }
+ else if(magic == 'RIFF')
+ {
+ return new WavDecoder(filepath);
+ }
+ else if(magic == 'BNS ')
+ {
+ return new BNSDecoder(filepath);
+ }
+ else if(magic == 'FORM')
+ {
+ return new AifDecoder(filepath);
+ }
+ else if(CheckMP3Signature((u8 *) &magic) == true)
+ {
+ return new Mp3Decoder(filepath);
+ }
+
+ return new SoundDecoder(filepath);
+}
+
+SoundDecoder * SoundHandler::GetSoundDecoder(const u8 * sound, int length)
+{
+ const u8 * check = sound;
+ int counter = 0;
+
+ while(check[0] == 0 && counter < length)
+ {
+ check++;
+ counter++;
+ }
+
+ if(counter >= length)
+ return NULL;
+
+ u32 * magic = (u32 *) check;
+
+ if(magic[0] == 'OggS')
+ {
+ return new OggDecoder(sound, length);
+ }
+ else if(magic[0] == 'RIFF')
+ {
+ return new WavDecoder(sound, length);
+ }
+ else if(magic[0] == 'BNS ')
+ {
+ return new BNSDecoder(sound, length);
+ }
+ else if(magic[0] == 'FORM')
+ {
+ return new AifDecoder(sound, length);
+ }
+ else if(CheckMP3Signature(check) == true)
+ {
+ return new Mp3Decoder(sound, length);
+ }
+
+ return new SoundDecoder(sound, length);
+}
+
+void * SoundHandler::UpdateThread(void *arg)
+{
+ ((SoundHandler *) arg)->InternalSoundUpdates();
+ return NULL;
+}
+
+void SoundHandler::InternalSoundUpdates()
+{
+ u16 i = 0;
+ LWP_InitQueue(&ThreadQueue);
+ while (!ExitRequested)
+ {
+ LWP_ThreadSleep(ThreadQueue);
+
+ for(i = 0; i < MAX_DECODERS; ++i)
+ {
+ if(DecoderList[i] == NULL)
+ continue;
+
+ Decoding = true;
+ DecoderList[i]->Decode();
+ }
+ Decoding = false;
+ }
+ LWP_CloseQueue(ThreadQueue);
+ ThreadQueue = LWP_TQUEUE_NULL;
+}
diff --git a/source/SoundOperations/SoundHandler.hpp b/source/SoundOperations/SoundHandler.hpp
new file mode 100644
index 00000000..b10953ec
--- /dev/null
+++ b/source/SoundOperations/SoundHandler.hpp
@@ -0,0 +1,68 @@
+/***************************************************************************
+ * Copyright (C) 2010
+ * by Dimok
+ *
+ * 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.
+ *
+ * for WiiXplorer 2010
+ ***************************************************************************/
+#ifndef SOUNDHANDLER_H_
+#define SOUNDHANDLER_H_
+
+#include
+#include
+#include "SoundDecoder.hpp"
+
+#define MAX_DECODERS 16
+
+class SoundHandler
+{
+ public:
+ static SoundHandler * Instance();
+ static void DestroyInstance();
+
+ void AddDecoder(int voice, const char * filepath);
+ void AddDecoder(int voice, const u8 * snd, int len);
+ void RemoveDecoder(int voice);
+ void DestroyDecoder(SoundDecoder * decoder);
+
+ SoundDecoder * Decoder(int i) { return ((i < 0 || i >= MAX_DECODERS) ? NULL : DecoderList[i]); };
+ void ThreadSignal() { LWP_ThreadSignal(ThreadQueue); };
+ bool IsDecoding() { return Decoding; };
+ protected:
+ SoundHandler();
+ ~SoundHandler();
+ static void * UpdateThread(void *arg);
+ void InternalSoundUpdates();
+ void ClearDecoderList();
+ SoundDecoder * GetSoundDecoder(const char * filepath);
+ SoundDecoder * GetSoundDecoder(const u8 * sound, int length);
+
+ static SoundHandler * instance;
+ u8 * ThreadStack;
+ lwp_t SoundThread;
+ lwpq_t ThreadQueue;
+ bool Decoding;
+ bool ExitRequested;
+
+ SoundDecoder * DecoderList[MAX_DECODERS];
+};
+
+#endif
diff --git a/source/SoundOperations/WavDecoder.cpp b/source/SoundOperations/WavDecoder.cpp
new file mode 100644
index 00000000..3f37b95b
--- /dev/null
+++ b/source/SoundOperations/WavDecoder.cpp
@@ -0,0 +1,155 @@
+/***************************************************************************
+ * Copyright (C) 2010
+ * by Dimok
+ *
+ * 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.
+ *
+ * for WiiXplorer 2010
+ ***************************************************************************/
+#include
+#include "WavDecoder.hpp"
+#include "utils/uncompress.h"
+
+WavDecoder::WavDecoder(const char * filepath)
+ : SoundDecoder(filepath)
+{
+ SoundType = SOUND_WAV;
+ SampleRate = 48000;
+ Format = VOICE_STEREO_16BIT;
+
+ if(!file_fd)
+ return;
+
+ OpenFile();
+}
+
+WavDecoder::WavDecoder(const u8 * snd, int len)
+ : SoundDecoder(snd, len)
+{
+ SoundType = SOUND_WAV;
+ SampleRate = 48000;
+ Format = VOICE_STEREO_16BIT;
+
+ if(!file_fd)
+ return;
+
+ OpenFile();
+}
+
+WavDecoder::~WavDecoder()
+{
+}
+
+void WavDecoder::OpenFile()
+{
+ SWaveHdr Header;
+ SWaveFmtChunk FmtChunk;
+ memset(&Header, 0, sizeof(SWaveHdr));
+ memset(&FmtChunk, 0, sizeof(SWaveFmtChunk));
+
+ file_fd->read((u8 *) &Header, sizeof(SWaveHdr));
+ file_fd->read((u8 *) &FmtChunk, sizeof(SWaveFmtChunk));
+
+ if (Header.magicRIFF != 'RIFF')
+ {
+ CloseFile();
+ return;
+ }
+ else if(Header.magicWAVE != 'WAVE')
+ {
+ CloseFile();
+ return;
+ }
+ else if(FmtChunk.magicFMT != 'fmt ')
+ {
+ CloseFile();
+ return;
+ }
+
+ DataOffset = sizeof(SWaveHdr)+le32(FmtChunk.size)+8;
+ file_fd->seek(DataOffset, SEEK_SET);
+ SWaveChunk DataChunk;
+ file_fd->read((u8 *) &DataChunk, sizeof(SWaveChunk));
+
+ if(DataChunk.magicDATA == 'fact')
+ {
+ DataOffset += 8+le32(DataChunk.size);
+ file_fd->seek(DataOffset, SEEK_SET);
+ file_fd->read((u8 *) &DataChunk, sizeof(SWaveChunk));
+ }
+ if(DataChunk.magicDATA != 'data')
+ {
+ CloseFile();
+ return;
+ }
+
+ DataOffset += 8;
+ DataSize = le32(DataChunk.size);
+ Is16Bit = (le16(FmtChunk.bps) == 16);
+ SampleRate = le32(FmtChunk.freq);
+
+ 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;
+
+ Decode();
+}
+
+void WavDecoder::CloseFile()
+{
+ if(file_fd)
+ delete file_fd;
+
+ file_fd = NULL;
+}
+
+int WavDecoder::Read(u8 * buffer, int buffer_size, int pos)
+{
+ if(!file_fd)
+ return -1;
+
+ if(CurPos >= (int) DataSize)
+ return 0;
+
+ file_fd->seek(DataOffset+CurPos, SEEK_SET);
+
+ if(buffer_size > (int) DataSize-CurPos)
+ buffer_size = DataSize-CurPos;
+
+ int read = file_fd->read(buffer, buffer_size);
+ if(read > 0)
+ {
+ if (Is16Bit)
+ {
+ read &= ~0x0001;
+
+ for (u32 i = 0; i < (u32) (read / sizeof (u16)); ++i)
+ ((u16 *) buffer)[i] = le16(((u16 *) buffer)[i]);
+ }
+ CurPos += read;
+ }
+
+ return read;
+}
diff --git a/source/SoundOperations/WavDecoder.hpp b/source/SoundOperations/WavDecoder.hpp
new file mode 100644
index 00000000..4681bf2b
--- /dev/null
+++ b/source/SoundOperations/WavDecoder.hpp
@@ -0,0 +1,75 @@
+/***************************************************************************
+ * Copyright (C) 2010
+ * by Dimok
+ *
+ * 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.
+ *
+ * for WiiXplorer 2010
+ ***************************************************************************/
+#ifndef WAVDECODER_HPP_
+#define WAVDECODER_HPP_
+
+#include "SoundDecoder.hpp"
+
+typedef struct
+{
+ u32 magicRIFF;
+ u32 size;
+ u32 magicWAVE;
+} SWaveHdr;
+
+typedef struct
+{
+ u32 magicFMT;
+ u32 size;
+ u16 format;
+ u16 channels;
+ u32 freq;
+ u32 avgBps;
+ u16 alignment;
+ u16 bps;
+} SWaveFmtChunk;
+
+typedef struct
+{
+ u32 magicDATA;
+ u32 size;
+} SWaveChunk;
+
+class WavDecoder : public SoundDecoder
+{
+ public:
+ WavDecoder(const char * filepath);
+ WavDecoder(const u8 * snd, int len);
+ ~WavDecoder();
+ int GetFormat() { return Format; };
+ int GetSampleRate() { return SampleRate; };
+ int Read(u8 * buffer, int buffer_size, int pos);
+ protected:
+ void OpenFile();
+ void CloseFile();
+ u32 DataOffset;
+ u32 DataSize;
+ u32 SampleRate;
+ u8 Format;
+ bool Is16Bit;
+};
+
+#endif
diff --git a/source/libwiigui/gui_bgm.cpp b/source/SoundOperations/gui_bgm.cpp
similarity index 87%
rename from source/libwiigui/gui_bgm.cpp
rename to source/SoundOperations/gui_bgm.cpp
index 98c89533..c56bd4fd 100644
--- a/source/libwiigui/gui_bgm.cpp
+++ b/source/SoundOperations/gui_bgm.cpp
@@ -1,236 +1,224 @@
-/****************************************************************************
- * SettingsPrompts
- * USB Loader GX 2009
- *
- * Backgroundmusic
- ***************************************************************************/
-#include
-#include "gui_bgm.h"
-#include "menu.h"
-
-GuiBGM::GuiBGM(const u8 *s, int l, int v) :
- GuiSound(s, l, v)
-{
- loop = 0;
- loopMode = ONCE;
- currentPath = NULL;
- currentPlaying = 0;
-
- //shouldn't be needed but
- //fixes some kind of weird bug in ogg system
- GuiSound::Load(s, l, v);
-}
-
-GuiBGM::~GuiBGM()
-{
- if (currentPath) delete[] currentPath;
-
- ClearList();
-}
-;
-
-void GuiBGM::SetLoop(bool l)
-{
-}
-
-void GuiBGM::SetLoop(int l)
-{
- loop = false;
- loopMode = ONCE;
-
- if (l == LOOP)
- {
- loop = true;
- }
- else loopMode = l;
-}
-
-bool GuiBGM::Load(const char *path)
-{
- if (!path)
- {
- LoadStandard();
- return false;
- }
- if (strcmp(path, "") == 0)
- {
- LoadStandard();
- return false;
- }
-
- if (!GuiSound::Load(path))
- {
- LoadStandard();
- return false;
- }
-
- return ParsePath(path);
-}
-
-bool GuiBGM::LoadStandard()
-{
- ClearList();
- if (currentPath)
- {
- delete[] currentPath;
- currentPath = NULL;
- }
-
- strcpy(Settings.ogg_path, "");
-
- bool ret = GuiSound::Load(bg_music_ogg, bg_music_ogg_size, true);
-
- if (ret) Play();
-
- return ret;
-}
-
-bool GuiBGM::ParsePath(const char * folderpath)
-{
- ClearList();
-
- if (currentPath) delete[] currentPath;
-
- currentPath = new char[strlen(folderpath) + 1];
- sprintf(currentPath, "%s", folderpath);
-
- char * isdirpath = strrchr(folderpath, '.');
- if (isdirpath)
- {
- char * pathptr = strrchr(currentPath, '/');
- if (pathptr)
- {
- pathptr++;
- pathptr[0] = 0;
- }
- }
-
- char * LoadedFilename = strrchr(folderpath, '/') + 1;
-
- char filename[1024];
- struct stat st;
-
- DIR_ITER * dir = diropen(currentPath);
- if (dir == NULL)
- {
- LoadStandard();
- return false;
- }
- u32 counter = 0;
-
- while (dirnext(dir, filename, &st) == 0)
- {
- char * fileext = strrchr(filename, '.');
- if (fileext)
- {
- if (strcasecmp(fileext, ".mp3") == 0 || strcasecmp(fileext, ".ogg") == 0 || strcasecmp(fileext, ".wav")
- == 0)
- {
- AddEntrie(filename);
-
- if (strcmp(LoadedFilename, filename) == 0) currentPlaying = counter;
-
- counter++;
- }
- }
- }
-
- dirclose(dir);
-
- snprintf(Settings.ogg_path, sizeof(Settings.ogg_path), "%s", folderpath);
-
- return true;
-}
-
-void GuiBGM::AddEntrie(const char * filename)
-{
- if (!filename) return;
-
- char * NewEntrie = new char[strlen(filename) + 1];
- sprintf(NewEntrie, "%s", filename);
-
- PlayList.push_back(NewEntrie);
-}
-
-void GuiBGM::ClearList()
-{
- for (u32 i = 0; i < PlayList.size(); i++)
- {
- if (PlayList.at(i) != NULL)
- {
- delete[] PlayList.at(i);
- PlayList.at(i) = NULL;
- }
- }
-
- PlayList.clear();
-}
-
-bool GuiBGM::PlayNext()
-{
- if (!currentPath) return false;
-
- currentPlaying++;
- if (currentPlaying >= (int) PlayList.size()) currentPlaying = 0;
-
- snprintf(Settings.ogg_path, sizeof(Settings.ogg_path), "%s%s", currentPath, PlayList.at(currentPlaying));
-
- if (!GuiSound::Load(Settings.ogg_path)) return false;
-
- Play();
-
- return true;
-}
-
-bool GuiBGM::PlayPrevious()
-{
- if (!currentPath) return false;
-
- currentPlaying--;
- if (currentPlaying < 0) currentPlaying = PlayList.size() - 1;
-
- snprintf(Settings.ogg_path, sizeof(Settings.ogg_path), "%s%s", currentPath, PlayList.at(currentPlaying));
-
- if (!GuiSound::Load(Settings.ogg_path)) return false;
-
- Play();
-
- return true;
-}
-
-bool GuiBGM::PlayRandom()
-{
- if (!currentPath) return false;
-
- srand(time(NULL));
-
- currentPlaying = rand() % PlayList.size();
-
- //just in case
- if (currentPlaying < 0)
- currentPlaying = PlayList.size() - 1;
- else if (currentPlaying >= (int) PlayList.size()) currentPlaying = 0;
-
- snprintf(Settings.ogg_path, sizeof(Settings.ogg_path), "%s%s", currentPath, PlayList.at(currentPlaying));
-
- if (!GuiSound::Load(Settings.ogg_path)) return false;
-
- Play();
-
- return true;
-}
-
-void GuiBGM::UpdateState()
-{
- if (!IsPlaying())
- {
- if (loopMode == DIR_LOOP)
- {
- PlayNext();
- }
- else if (loopMode == RANDOM_BGM)
- {
- PlayRandom();
- }
- }
-}
+/****************************************************************************
+ * SettingsPrompts
+ * USB Loader GX 2009
+ *
+ * Backgroundmusic
+ ***************************************************************************/
+#include
+#include "gui_bgm.h"
+#include "menu.h"
+
+GuiBGM::GuiBGM(const u8 *s, int l, int v) :
+ GuiSound(s, l, v, false, 0)
+{
+ loop = 0;
+ loopMode = ONCE;
+ currentPath = NULL;
+ currentPlaying = 0;
+ voice = 0;
+}
+
+GuiBGM::~GuiBGM()
+{
+ if (currentPath) delete[] currentPath;
+
+ ClearList();
+}
+;
+
+void GuiBGM::SetLoop(u8 l)
+{
+ loopMode = l;
+
+ GuiSound::SetLoop(l == LOOP);
+}
+
+bool GuiBGM::Load(const char *path)
+{
+ if (!path)
+ {
+ LoadStandard();
+ return false;
+ }
+ if (strcmp(path, "") == 0)
+ {
+ LoadStandard();
+ return false;
+ }
+
+ if (!GuiSound::Load(path))
+ {
+ LoadStandard();
+ return false;
+ }
+
+ return ParsePath(path);
+}
+
+bool GuiBGM::LoadStandard()
+{
+ ClearList();
+ if (currentPath)
+ {
+ delete[] currentPath;
+ currentPath = NULL;
+ }
+
+ strcpy(Settings.ogg_path, "");
+
+ bool ret = GuiSound::Load(bg_music_ogg, bg_music_ogg_size, false);
+
+ if (ret) Play();
+
+ return ret;
+}
+
+bool GuiBGM::ParsePath(const char * folderpath)
+{
+ ClearList();
+
+ if (currentPath) delete[] currentPath;
+
+ currentPath = new char[strlen(folderpath) + 1];
+ sprintf(currentPath, "%s", folderpath);
+
+ char * isdirpath = strrchr(folderpath, '.');
+ if (isdirpath)
+ {
+ char * pathptr = strrchr(currentPath, '/');
+ if (pathptr)
+ {
+ pathptr++;
+ pathptr[0] = 0;
+ }
+ }
+
+ char * LoadedFilename = strrchr(folderpath, '/') + 1;
+
+ char filename[1024];
+ struct stat st;
+
+ DIR_ITER * dir = diropen(currentPath);
+ if (dir == NULL)
+ {
+ LoadStandard();
+ return false;
+ }
+ u32 counter = 0;
+
+ while (dirnext(dir, filename, &st) == 0)
+ {
+ char * fileext = strrchr(filename, '.');
+ if (fileext)
+ {
+ if (strcasecmp(fileext, ".mp3") == 0 || strcasecmp(fileext, ".ogg") == 0 || strcasecmp(fileext, ".wav")
+ == 0)
+ {
+ AddEntrie(filename);
+
+ if (strcmp(LoadedFilename, filename) == 0) currentPlaying = counter;
+
+ counter++;
+ }
+ }
+ }
+
+ dirclose(dir);
+
+ snprintf(Settings.ogg_path, sizeof(Settings.ogg_path), "%s", folderpath);
+
+ return true;
+}
+
+void GuiBGM::AddEntrie(const char * filename)
+{
+ if (!filename) return;
+
+ char * NewEntrie = new char[strlen(filename) + 1];
+ sprintf(NewEntrie, "%s", filename);
+
+ PlayList.push_back(NewEntrie);
+}
+
+void GuiBGM::ClearList()
+{
+ for (u32 i = 0; i < PlayList.size(); i++)
+ {
+ if (PlayList.at(i) != NULL)
+ {
+ delete[] PlayList.at(i);
+ PlayList.at(i) = NULL;
+ }
+ }
+
+ PlayList.clear();
+}
+
+bool GuiBGM::PlayNext()
+{
+ if (!currentPath) return false;
+
+ currentPlaying++;
+ if (currentPlaying >= (int) PlayList.size()) currentPlaying = 0;
+
+ snprintf(Settings.ogg_path, sizeof(Settings.ogg_path), "%s%s", currentPath, PlayList.at(currentPlaying));
+
+ if (!GuiSound::Load(Settings.ogg_path)) return false;
+
+ Play();
+
+ return true;
+}
+
+bool GuiBGM::PlayPrevious()
+{
+ if (!currentPath) return false;
+
+ currentPlaying--;
+ if (currentPlaying < 0) currentPlaying = PlayList.size() - 1;
+
+ snprintf(Settings.ogg_path, sizeof(Settings.ogg_path), "%s%s", currentPath, PlayList.at(currentPlaying));
+
+ if (!GuiSound::Load(Settings.ogg_path)) return false;
+
+ Play();
+
+ return true;
+}
+
+bool GuiBGM::PlayRandom()
+{
+ if (!currentPath) return false;
+
+ srand(time(NULL));
+
+ currentPlaying = rand() % PlayList.size();
+
+ //just in case
+ if (currentPlaying < 0)
+ currentPlaying = PlayList.size() - 1;
+ else if (currentPlaying >= (int) PlayList.size()) currentPlaying = 0;
+
+ snprintf(Settings.ogg_path, sizeof(Settings.ogg_path), "%s%s", currentPath, PlayList.at(currentPlaying));
+
+ if (!GuiSound::Load(Settings.ogg_path)) return false;
+
+ Play();
+
+ return true;
+}
+
+void GuiBGM::UpdateState()
+{
+ if (!IsPlaying())
+ {
+ if (loopMode == DIR_LOOP)
+ {
+ PlayNext();
+ }
+ else if (loopMode == RANDOM_BGM)
+ {
+ PlayRandom();
+ }
+ }
+}
diff --git a/source/libwiigui/gui_bgm.h b/source/SoundOperations/gui_bgm.h
similarity index 86%
rename from source/libwiigui/gui_bgm.h
rename to source/SoundOperations/gui_bgm.h
index 8fe076d1..741ce36a 100644
--- a/source/libwiigui/gui_bgm.h
+++ b/source/SoundOperations/gui_bgm.h
@@ -1,42 +1,42 @@
-/****************************************************************************
- * SettingsPrompts
- * USB Loader GX 2009
- *
- * Backgroundmusic
- ***************************************************************************/
-
-#ifndef _BGM_H_
-#define _BGM_H_
-
-#include "libwiigui/gui.h"
-
-enum
-{
- ONCE = 0, LOOP, RANDOM_BGM, DIR_LOOP
-};
-
-class GuiBGM: public GuiSound
-{
- public:
- GuiBGM(const u8 *s, int l, int v);
- ~GuiBGM();
- bool Load(const char *path);
- bool LoadStandard();
- bool ParsePath(const char * folderpath);
- bool PlayNext();
- bool PlayPrevious();
- bool PlayRandom();
- void SetLoop(bool l);
- void SetLoop(int l);
- void UpdateState();
- protected:
- void AddEntrie(const char * filename);
- void ClearList();
-
- int currentPlaying;
- int loopMode;
- char * currentPath;
- std::vector PlayList;
-};
-
-#endif
+/****************************************************************************
+ * SettingsPrompts
+ * USB Loader GX 2009
+ *
+ * Backgroundmusic
+ ***************************************************************************/
+
+#ifndef _BGM_H_
+#define _BGM_H_
+
+#include
+#include "gui_sound.h"
+
+enum
+{
+ ONCE = 0, LOOP, RANDOM_BGM, DIR_LOOP
+};
+
+class GuiBGM: public GuiSound
+{
+ public:
+ GuiBGM(const u8 *s, int l, int v);
+ ~GuiBGM();
+ bool Load(const char *path);
+ bool LoadStandard();
+ bool ParsePath(const char * folderpath);
+ bool PlayNext();
+ bool PlayPrevious();
+ bool PlayRandom();
+ void SetLoop(u8 l);
+ void UpdateState();
+ protected:
+ void AddEntrie(const char * filename);
+ void ClearList();
+
+ int currentPlaying;
+ int loopMode;
+ char * currentPath;
+ std::vector PlayList;
+};
+
+#endif
diff --git a/source/SoundOperations/gui_sound.cpp b/source/SoundOperations/gui_sound.cpp
new file mode 100644
index 00000000..350ecaaf
--- /dev/null
+++ b/source/SoundOperations/gui_sound.cpp
@@ -0,0 +1,380 @@
+/***************************************************************************
+ * Copyright (C) 2010
+ * by Dimok
+ *
+ * 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.
+ *
+ * for WiiXplorer 2010
+ ***************************************************************************/
+#include
+#include "libwiigui/gui.h"
+#include "utils/uncompress.h"
+#include "FileOperations/fileops.h"
+#include "SoundHandler.hpp"
+#include "WavDecoder.hpp"
+
+#define MAX_SND_VOICES 16
+
+static bool VoiceUsed[MAX_SND_VOICES] =
+{
+ true, false, false, false, false, false,
+ false, false, false, false, false, false,
+ false, false, false, false
+};
+
+static inline int GetFirstUnusedVoice()
+{
+ for(int i = 1; i < MAX_SND_VOICES; i++)
+ {
+ if(VoiceUsed[i] == false)
+ return i;
+ }
+
+ return -1;
+}
+
+extern "C" void SoundCallback(s32 voice)
+{
+ SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
+ if(!decoder)
+ return;
+
+ if(decoder->IsBufferReady())
+ {
+ if(ASND_AddVoice(voice, decoder->GetBuffer(), decoder->GetBufferSize()) == SND_OK)
+ {
+ decoder->LoadNext();
+ SoundHandler::Instance()->ThreadSignal();
+ }
+ }
+ else if(decoder->IsEOF())
+ {
+ ASND_StopVoice(voice);
+ //if(voice == 0)
+ //MusicPlayer::Instance()->SetPlaybackFinished(true); //see if next music must be played
+ }
+ else
+ {
+ SoundHandler::Instance()->ThreadSignal();
+ }
+}
+
+GuiSound::GuiSound(const char * filepath)
+{
+ sound = NULL;
+ length = 0;
+ voice = GetFirstUnusedVoice();
+ if(voice > 0)
+ VoiceUsed[voice] = true;
+
+ volume = 255;
+ SoundEffectLength = 0;
+ loop = false;
+ allocated = false;
+ Load(filepath);
+}
+
+GuiSound::GuiSound(const u8 * snd, s32 len, int vol, bool isallocated, int v)
+{
+ sound = NULL;
+ length = 0;
+ if(v < 0)
+ voice = GetFirstUnusedVoice();
+ else
+ voice = v;
+
+ if(voice > 0)
+ VoiceUsed[voice] = true;
+
+ volume = vol;
+ SoundEffectLength = 0;
+ loop = false;
+ allocated = false;
+ Load(snd, len, isallocated);
+}
+
+GuiSound::~GuiSound()
+{
+ FreeMemory();
+ if(voice > 0)
+ VoiceUsed[voice] = false;
+}
+
+void GuiSound::FreeMemory()
+{
+ this->Stop();
+
+ SoundHandler::Instance()->RemoveDecoder(voice);
+
+ if(allocated && sound != NULL)
+ {
+ free(sound);
+ sound = NULL;
+ allocated = false;
+ }
+
+ SoundEffectLength = 0;
+}
+
+bool GuiSound::Load(const char * filepath)
+{
+ FreeMemory();
+
+ if(!filepath)
+ return false;
+
+ u32 magic;
+ FILE * f = fopen(filepath, "rb");
+ if(!f)
+ return false;
+
+ fread(&magic, 1, 4, f);
+ fclose(f);
+
+ if(magic == 'IMD5')
+ {
+ u8 * snd = NULL;
+ u64 filesize = 0;
+ LoadFileToMem(filepath, &snd, &filesize);
+ return Load(snd, filesize, true);
+ }
+
+ SoundHandler::Instance()->AddDecoder(voice, filepath);
+
+ SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
+ if(!decoder)
+ return false;
+
+ if(!decoder->IsBufferReady())
+ {
+ SoundHandler::Instance()->RemoveDecoder(voice);
+ return false;
+ }
+
+ SetLoop(loop);
+
+ return true;
+}
+
+bool GuiSound::Load(const u8 * snd, s32 len, bool isallocated)
+{
+ FreeMemory();
+
+ if(!snd)
+ return false;
+
+ if(!isallocated && *((u32 *) snd) == 'RIFF')
+ {
+ return LoadSoundEffect(snd, len);
+ }
+
+ if(*((u32 *) snd) == 'IMD5')
+ {
+ UncompressSoundbin(snd, len, isallocated);
+ }
+ else
+ {
+ sound = (u8 *) snd;
+ length = len;
+ allocated = isallocated;
+ }
+
+ SoundHandler::Instance()->AddDecoder(voice, sound, length);
+
+ SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
+ if(!decoder)
+ return false;
+
+ if(!decoder->IsBufferReady())
+ {
+ SoundHandler::Instance()->RemoveDecoder(voice);
+ return false;
+ }
+
+ SetLoop(loop);
+
+ return true;
+}
+
+bool GuiSound::LoadSoundEffect(const u8 * snd, s32 len)
+{
+ WavDecoder decoder(snd, len);
+ decoder.Rewind();
+
+ u32 done = 0;
+ sound = (u8 *) malloc(4096);
+ memset(sound, 0, 4096);
+
+ while(1)
+ {
+ u8 * tmpsnd = (u8 *) realloc(sound, done+4096);
+ if(!tmpsnd)
+ {
+ free(sound);
+ sound = NULL;
+ return false;
+ }
+
+ sound = tmpsnd;
+
+ int read = decoder.Read(sound+done, 4096, done);
+ if(read <= 0)
+ break;
+
+ done += read;
+ }
+
+ sound = (u8 *) realloc(sound, done);
+ SoundEffectLength = done;
+ allocated = true;
+
+ return true;
+}
+
+void GuiSound::Play()
+{
+ if(SoundEffectLength > 0)
+ {
+ ASND_StopVoice(voice);
+ ASND_SetVoice(voice, VOICE_STEREO_16BIT, 32000, 0, sound, SoundEffectLength, volume, volume, NULL);
+ return;
+ }
+
+ if(IsPlaying())
+ return;
+
+ if(voice < 0 || voice >= 16)
+ return;
+
+ SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
+ if(!decoder)
+ return;
+
+ if(decoder->IsEOF())
+ {
+ ASND_StopVoice(voice);
+ decoder->ClearBuffer();
+ decoder->Rewind();
+ decoder->Decode();
+ }
+
+ u8 * curbuffer = decoder->GetBuffer();
+ int bufsize = decoder->GetBufferSize();
+ decoder->LoadNext();
+ SoundHandler::Instance()->ThreadSignal();
+
+ ASND_SetVoice(voice, decoder->GetFormat(), decoder->GetSampleRate(), 0, curbuffer, bufsize, volume, volume, SoundCallback);
+}
+
+void GuiSound::Stop()
+{
+ if(voice < 0 || voice >= 16)
+ return;
+
+ ASND_StopVoice(voice);
+
+ SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
+ if(!decoder)
+ return;
+
+ decoder->ClearBuffer();
+ Rewind();
+ SoundHandler::Instance()->ThreadSignal();
+}
+
+void GuiSound::Pause()
+{
+ if(voice < 0 || voice >= 16)
+ return;
+
+ ASND_StopVoice(voice);
+}
+
+void GuiSound::Resume()
+{
+ Play();
+}
+
+bool GuiSound::IsPlaying()
+{
+ if(voice < 0 || voice >= 16)
+ return false;
+
+ int result = ASND_StatusVoice(voice);
+
+ if(result == SND_WORKING || result == SND_WAITING)
+ return true;
+
+ return false;
+}
+
+void GuiSound::SetVolume(int vol)
+{
+ if(voice < 0 || voice >= 16)
+ return;
+
+ if(vol < 0)
+ return;
+
+ volume = 255*(vol/100.0);
+ ASND_ChangeVolumeVoice(voice, volume, volume);
+}
+
+void GuiSound::SetLoop(u8 l)
+{
+ loop = l;
+
+ SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
+ if(!decoder)
+ return;
+
+ decoder->SetLoop(l == 1);
+}
+
+void GuiSound::Rewind()
+{
+ SoundDecoder * decoder = SoundHandler::Instance()->Decoder(voice);
+ if(!decoder)
+ return;
+
+ decoder->Rewind();
+}
+
+void GuiSound::UncompressSoundbin(const u8 * snd, int len, bool isallocated)
+{
+ const u8 * file = snd+32;
+ if(*((u32 *) file) == 'LZ77')
+ {
+ u32 size = 0;
+ sound = uncompressLZ77(file, len-32, &size);
+ length = size;
+ }
+ else
+ {
+ length = len-32;
+ sound = (u8 *) malloc(length);
+ memcpy(sound, file, length);
+ }
+
+ if(isallocated)
+ free((u8 *) snd);
+
+ allocated = true;
+}
diff --git a/source/SoundOperations/gui_sound.h b/source/SoundOperations/gui_sound.h
new file mode 100644
index 00000000..1101b16b
--- /dev/null
+++ b/source/SoundOperations/gui_sound.h
@@ -0,0 +1,80 @@
+/***************************************************************************
+ * Copyright (C) 2010
+ * by Dimok
+ *
+ * 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.
+ *
+ * for WiiXplorer 2010
+ ***************************************************************************/
+#ifndef GUI_SOUND_H_
+#define GUI_SOUND_H_
+
+#include
+
+//!Sound conversion and playback. A wrapper for other sound libraries - ASND, libmad, ltremor, etc
+class GuiSound
+{
+ public:
+ //!Constructor
+ //!\param sound Pointer to the sound data
+ //!\param filesize Length of sound data
+ GuiSound(const char * filepath);
+ GuiSound(const u8 * sound, int filesize, int volume, bool allocated = false, int voice = -1);
+ //!Destructor
+ ~GuiSound();
+ //!Load a file and replace the old one
+ bool Load(const char * filepath);
+ //!Load a file and replace the old one
+ bool Load(const u8 * sound, int filesize, bool allocated = true);
+ //!For quick playback of the internal soundeffects
+ bool LoadSoundEffect(const u8 * snd, s32 len);
+ //!Start sound playback
+ void Play();
+ //!Stop sound playback
+ void Stop();
+ //!Pause sound playback
+ void Pause();
+ //!Resume sound playback
+ void Resume();
+ //!Checks if the sound is currently playing
+ //!\return true if sound is playing, false otherwise
+ bool IsPlaying();
+ //!Rewind the music
+ void Rewind();
+ //!Set sound volume
+ //!\param v Sound volume (0-100)
+ void SetVolume(int v);
+ //!\param l Loop (true to loop)
+ void SetLoop(u8 l);
+ //!Special sound case for sound.bin
+ void UncompressSoundbin(const u8 * snd, int len, bool isallocated);
+ protected:
+ //!Stops sound and frees all memory/closes files
+ void FreeMemory();
+ u8 * sound; //!< Pointer to the sound data
+ int length; //!< Length of sound data
+ s32 voice; //!< Currently assigned ASND voice channel
+ int volume; //!< Sound volume (0-100)
+ u8 loop; //!< Loop sound playback
+ u32 SoundEffectLength; //!< Check if it is an app soundeffect for faster playback
+ bool allocated; //!< Is the file allocated or not
+};
+
+#endif
diff --git a/source/bannersound.cpp b/source/bannersound.cpp
index 48d11de2..8a6939ff 100644
--- a/source/bannersound.cpp
+++ b/source/bannersound.cpp
@@ -9,6 +9,7 @@
#include "libs/libwbfs/libwbfs.h"
#include "language/gettext.h"
#include "bannersound.h"
+#include "utils/uncompress.h"
struct IMD5Header
{
@@ -67,58 +68,6 @@ static char *u8Filename(const U8Entry *fst, int i)
return (char *) (fst + fst[0].numEntries) + fst[i].nameOffset;
}
-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 *inBuf, u32 inLength, u32 &size)
-{
- u8 *buffer = NULL;
- if (inLength <= 0x8 || *((const u32 *) inBuf) != 0x4C5A3737 /*"LZ77"*/|| inBuf[4] != 0x10) return NULL;
- u32 uncSize = le32(((const u32 *) inBuf)[1] << 8);
-
- const u8 *inBufEnd = inBuf + inLength;
- inBuf += 8;
- buffer = new (std::nothrow) u8[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;
-}
-
const u8 *LoadBannerSound(const u8 *discid, u32 *size)
{
if (!discid) return NULL;
@@ -181,7 +130,7 @@ const u8 *LoadBannerSound(const u8 *discid, u32 *size)
if (*((u32*) soundChunk) == 0x4C5A3737 /*"LZ77"*/)
{
u32 uncSize = 0;
- u8 * uncompressed_data = uncompressLZ77(soundChunk, soundChunkSize, uncSize);
+ u8 * uncompressed_data = uncompressLZ77(soundChunk, soundChunkSize, &uncSize);
if (!uncompressed_data)
{
// WindowPrompt(tr("Can't decompress LZ77"), 0, tr("OK"));
@@ -192,7 +141,7 @@ const u8 *LoadBannerSound(const u8 *discid, u32 *size)
free(opening_bnr);
return uncompressed_data;
}
- u8 *out = new (std::nothrow) u8[soundChunkSize];
+ u8 *out = (u8 *) malloc(soundChunkSize);
if (out)
{
memcpy(out, soundChunk, soundChunkSize);
diff --git a/source/cheats/cheatmenu.cpp b/source/cheats/cheatmenu.cpp
index 81684d4e..c4964e3e 100644
--- a/source/cheats/cheatmenu.cpp
+++ b/source/cheats/cheatmenu.cpp
@@ -30,10 +30,6 @@ int CheatMenu(const char * gameID)
bool exit = false;
int ret = 1;
- // because destroy GuiSound must wait while sound playing is finished, we use a global sound
- if (!btnClick2) btnClick2 = new GuiSound(button_click2_pcm, button_click2_pcm_size, Settings.sfxvolume);
- // GuiSound btnClick(button_click2_pcm, button_click2_pcm_size, Settings.sfxvolume);
-
GuiImageData btnOutline(Resources::GetFile("button_dialogue_box.png"), Resources::GetFileSize("button_dialogue_box.png"));
GuiImageData settingsbg(Resources::GetFile("settings_background.png"), Resources::GetFileSize("settings_background.png"));
GuiImage settingsbackground(&settingsbg);
@@ -46,14 +42,14 @@ int CheatMenu(const char * gameID)
GuiText backBtnTxt(tr( "Back" ), 22, Theme.prompttext);
backBtnTxt.SetMaxWidth(btnOutline.GetWidth() - 30);
GuiImage backBtnImg(&btnOutline);
- GuiButton backBtn(&backBtnImg, &backBtnImg, 2, 3, -140, 400, &trigA, NULL, btnClick2, 1);
+ GuiButton backBtn(&backBtnImg, &backBtnImg, 2, 3, -140, 400, &trigA, NULL, btnSoundClick2, 1);
backBtn.SetLabel(&backBtnTxt);
backBtn.SetTrigger(&trigB);
GuiText createBtnTxt(tr( "Create" ), 22, Theme.prompttext);
createBtnTxt.SetMaxWidth(btnOutline.GetWidth() - 30);
GuiImage createBtnImg(&btnOutline);
- GuiButton createBtn(&createBtnImg, &createBtnImg, 2, 3, 160, 400, &trigA, NULL, btnClick2, 1);
+ GuiButton createBtn(&createBtnImg, &createBtnImg, 2, 3, 160, 400, &trigA, NULL, btnSoundClick2, 1);
createBtn.SetLabel(&createBtnTxt);
char txtfilename[55];
diff --git a/source/fatmounter.c b/source/fatmounter.c
index b134ef77..39212be0 100644
--- a/source/fatmounter.c
+++ b/source/fatmounter.c
@@ -82,6 +82,7 @@ void USBDevice_deInit()
fatUnmount("USB:/");
//only shutdown libogc usb and not the cios one
__io_usbstorage.shutdown();
+ __io_usbstorage2.shutdown();
fat_usb_mount = 0;
fat_usb_sec = 0;
diff --git a/source/filelist.h b/source/filelist.h
index 4c6e9a47..6009cb67 100644
--- a/source/filelist.h
+++ b/source/filelist.h
@@ -71,14 +71,14 @@ extern const u32 credits_button_png_size;
extern const u8 credits_button_over_png[];
extern const u32 credits_button_over_png_size;
-extern const u8 button_over_pcm[];
-extern const u32 button_over_pcm_size;
+extern const u8 button_over_wav[];
+extern const u32 button_over_wav_size;
-extern const u8 button_click_pcm[];
-extern const u32 button_click_pcm_size;
+extern const u8 button_click_wav[];
+extern const u32 button_click_wav_size;
-extern const u8 button_click2_pcm[];
-extern const u32 button_click2_pcm_size;
+extern const u8 button_click2_wav[];
+extern const u32 button_click2_wav_size;
extern const u8 tooltip_left_png[];
extern const u32 tooltip_left_png_size;
diff --git a/source/homebrewboot/HomebrewBrowse.cpp b/source/homebrewboot/HomebrewBrowse.cpp
index f380055a..7d823952 100644
--- a/source/homebrewboot/HomebrewBrowse.cpp
+++ b/source/homebrewboot/HomebrewBrowse.cpp
@@ -208,13 +208,6 @@ int MenuHomebrewBrowse()
int slidedirection = FADE;
- /*** Sound Variables ***/
- GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, Settings.sfxvolume);
- // because destroy GuiSound must wait while sound playing is finished, we use a global sound
- if (!btnClick2) btnClick2 = new GuiSound(button_click2_pcm, button_click2_pcm_size, Settings.sfxvolume);
- // GuiSound btnClick(button_click2_pcm, button_click2_pcm_size, Settings.sfxvolume);
- GuiSound btnClick1(button_click_pcm, button_click_pcm_size, Settings.sfxvolume);
-
/*** Image Variables ***/
GuiImageData btnOutline(Resources::GetFile("button_dialogue_box.png"), Resources::GetFileSize("button_dialogue_box.png"));
@@ -273,7 +266,7 @@ int MenuHomebrewBrowse()
backBtnTxt.SetWidescreen(Settings.widescreen);
backBtnImg.SetWidescreen(Settings.widescreen);
}
- GuiButton backBtn(&backBtnImg, &backBtnImg, 2, 3, -180, 400, &trigA, &btnSoundOver, btnClick2, 1);
+ GuiButton backBtn(&backBtnImg, &backBtnImg, 2, 3, -180, 400, &trigA, btnSoundOver, btnSoundClick2, 1);
backBtn.SetLabel(&backBtnTxt);
backBtn.SetTrigger(&trigB);
@@ -285,8 +278,8 @@ int MenuHomebrewBrowse()
GoLeftBtn.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
GoLeftBtn.SetPosition(25, -25);
GoLeftBtn.SetImage(&GoLeftImg);
- GoLeftBtn.SetSoundOver(&btnSoundOver);
- GoLeftBtn.SetSoundClick(btnClick2);
+ GoLeftBtn.SetSoundOver(btnSoundOver);
+ GoLeftBtn.SetSoundClick(btnSoundClick2);
GoLeftBtn.SetEffectGrow();
GoLeftBtn.SetTrigger(&trigA);
GoLeftBtn.SetTrigger(&trigL);
@@ -297,8 +290,8 @@ int MenuHomebrewBrowse()
GoRightBtn.SetAlignment(ALIGN_RIGHT, ALIGN_MIDDLE);
GoRightBtn.SetPosition(-25, -25);
GoRightBtn.SetImage(&GoRightImg);
- GoRightBtn.SetSoundOver(&btnSoundOver);
- GoRightBtn.SetSoundClick(btnClick2);
+ GoRightBtn.SetSoundOver(btnSoundOver);
+ GoRightBtn.SetSoundClick(btnSoundClick2);
GoRightBtn.SetEffectGrow();
GoRightBtn.SetTrigger(&trigA);
GoRightBtn.SetTrigger(&trigR);
@@ -332,8 +325,8 @@ int MenuHomebrewBrowse()
MainButton1.SetLabel(&MainButton1Txt);
MainButton1.SetLabel(&MainButton1DescTxt, 1);
MainButton1.SetLabelOver(&MainButton1DescOverTxt, 1);
- MainButton1.SetSoundOver(&btnSoundOver);
- MainButton1.SetSoundClick(&btnClick1);
+ MainButton1.SetSoundOver(btnSoundOver);
+ MainButton1.SetSoundClick(btnSoundClick);
MainButton1.SetEffectGrow();
MainButton1.SetTrigger(&trigA);
@@ -359,8 +352,8 @@ int MenuHomebrewBrowse()
MainButton2.SetLabel(&MainButton2Txt);
MainButton2.SetLabel(&MainButton2DescTxt, 1);
MainButton2.SetLabelOver(&MainButton2DescOverTxt, 1);
- MainButton2.SetSoundOver(&btnSoundOver);
- MainButton2.SetSoundClick(&btnClick1);
+ MainButton2.SetSoundOver(btnSoundOver);
+ MainButton2.SetSoundClick(btnSoundClick);
MainButton2.SetEffectGrow();
MainButton2.SetTrigger(&trigA);
@@ -386,8 +379,8 @@ int MenuHomebrewBrowse()
MainButton3.SetLabel(&MainButton3Txt);
MainButton3.SetLabel(&MainButton3DescTxt, 1);
MainButton3.SetLabelOver(&MainButton3DescOverTxt, 1);
- MainButton3.SetSoundOver(&btnSoundOver);
- MainButton3.SetSoundClick(&btnClick1);
+ MainButton3.SetSoundOver(btnSoundOver);
+ MainButton3.SetSoundClick(btnSoundClick);
MainButton3.SetEffectGrow();
MainButton3.SetTrigger(&trigA);
@@ -416,8 +409,8 @@ int MenuHomebrewBrowse()
MainButton4.SetLabel(&MainButton4Txt);
MainButton4.SetLabel(&MainButton4DescTxt, 1);
MainButton4.SetLabelOver(&MainButton4DescOverTxt, 1);
- MainButton4.SetSoundOver(&btnSoundOver);
- MainButton4.SetSoundClick(&btnClick1);
+ MainButton4.SetSoundOver(btnSoundOver);
+ MainButton4.SetSoundClick(btnSoundClick);
MainButton4.SetEffectGrow();
MainButton4.SetTrigger(&trigA);
@@ -429,8 +422,8 @@ int MenuHomebrewBrowse()
GuiButton wifiBtn(wifiImg.GetWidth(), wifiImg.GetHeight());
wifiBtn.SetImage(&wifiImg);
wifiBtn.SetPosition(500, 400);
- wifiBtn.SetSoundOver(&btnSoundOver);
- wifiBtn.SetSoundClick(&btnClick1);
+ wifiBtn.SetSoundOver(btnSoundOver);
+ wifiBtn.SetSoundClick(btnSoundClick);
wifiBtn.SetEffectGrow();
wifiBtn.SetAlpha(80);
wifiBtn.SetTrigger(&trigA);
@@ -441,8 +434,8 @@ int MenuHomebrewBrowse()
channelBtn.SetAlignment(ALIGN_LEFT, ALIGN_TOP);
channelBtn.SetPosition(440, 400);
channelBtn.SetImage(&channelBtnImg);
- channelBtn.SetSoundOver(&btnSoundOver);
- channelBtn.SetSoundClick(btnClick2);
+ channelBtn.SetSoundOver(btnSoundOver);
+ channelBtn.SetSoundClick(btnSoundClick2);
channelBtn.SetEffectGrow();
channelBtn.SetTrigger(&trigA);
diff --git a/source/libs/libwbfs/libwbfs.c b/source/libs/libwbfs/libwbfs.c
index 120be9ea..57a4df82 100644
--- a/source/libs/libwbfs/libwbfs.c
+++ b/source/libs/libwbfs/libwbfs.c
@@ -1,827 +1,827 @@
-// Copyright 2009 Kwiirk
-// Licensed under the terms of the GNU GPL, version 2
-// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
-
-// Modified by oggzee
-
-#include "libwbfs.h"
-
-#define likely(x) __builtin_expect(!!(x), 1)
-#define unlikely(x) __builtin_expect(!!(x), 0)
-
-#define ERROR(x) do {wbfs_error(x);goto error;}while(0)
-#define ALIGN_LBA(x) (((x)+p->hd_sec_sz-1)&(~(p->hd_sec_sz-1)))
-
-wbfs_t wbfs_iso_file;
-
-static int force_mode = 0;
-
-void wbfs_set_force_mode(int force)
-{
- force_mode = force;
-}
-
-static u8 size_to_shift(u32 size)
-{
- u8 ret = 0;
- while (size)
- {
- ret++;
- size >>= 1;
- }
- return ret - 1;
-}
-#define read_le32_unaligned(x) ((x)[0]|((x)[1]<<8)|((x)[2]<<16)|((x)[3]<<24))
-
-wbfs_t*wbfs_open_hd(rw_sector_callback_t read_hdsector, rw_sector_callback_t write_hdsector, void *callback_data,
- int hd_sector_size, int num_hd_sector __attribute( ( unused ) ), int reset)
-{
- int i = num_hd_sector, ret;
- u8 *ptr, *tmp_buffer = wbfs_ioalloc( hd_sector_size );
- u8 part_table[16 * 4];
- ret = read_hdsector(callback_data, 0, 1, tmp_buffer);
- if (ret) return 0;
- //find wbfs partition
- wbfs_memcpy( part_table, tmp_buffer + 0x1be, 16*4 );
- ptr = part_table;
- for (i = 0; i < 4; i++, ptr += 16)
- {
- u32 part_lba = read_le32_unaligned( ptr + 0x8 );
- wbfs_head_t *head = (wbfs_head_t *) tmp_buffer;
- ret = read_hdsector(callback_data, part_lba, 1, tmp_buffer);
- // verify there is the magic.
- if (head->magic == wbfs_htonl( WBFS_MAGIC ))
- {
- wbfs_t*p = wbfs_open_partition(read_hdsector, write_hdsector, callback_data, hd_sector_size, 0, part_lba,
- reset);
- wbfs_iofree( tmp_buffer );
- return p;
- }
- }
- wbfs_iofree( tmp_buffer );
- if (reset)// XXX make a empty hd partition..
- {
- }
- return 0;
-}
-wbfs_t*wbfs_open_partition(rw_sector_callback_t read_hdsector, rw_sector_callback_t write_hdsector,
- void *callback_data, int hd_sector_size, int num_hd_sector, u32 part_lba, int reset)
-{
- wbfs_t *p = wbfs_malloc( sizeof( wbfs_t ) );
-
- wbfs_head_t *head = wbfs_ioalloc( hd_sector_size ? hd_sector_size : 512 );
-
- //constants, but put here for consistancy
- p->wii_sec_sz = 0x8000;
- p->wii_sec_sz_s = size_to_shift(0x8000);
- p->n_wii_sec = (num_hd_sector / 0x8000) * hd_sector_size;
- p->n_wii_sec_per_disc = 143432 * 2;//support for double layers discs..
- p->head = head;
- p->part_lba = part_lba;
- // init the partition
- if (reset)
- {
- u8 sz_s;
- wbfs_memset( head, 0, hd_sector_size );
- head->magic = wbfs_htonl( WBFS_MAGIC );
- head->hd_sec_sz_s = size_to_shift(hd_sector_size);
- head->n_hd_sec = wbfs_htonl( num_hd_sector );
- // choose minimum wblk_sz that fits this partition size
- for (sz_s = 6; sz_s < 11; sz_s++)
- {
- // ensure that wbfs_sec_sz is big enough to address every blocks using 16 bits
- if (p->n_wii_sec < ((1U << 16) * (1 << sz_s))) break;
- }
- head->wbfs_sec_sz_s = sz_s + p->wii_sec_sz_s;
- }
- else read_hdsector(callback_data, p->part_lba, 1, head);
- if (head->magic != wbfs_htonl( WBFS_MAGIC ))
- ERROR( "bad magic" );
- if (!force_mode && hd_sector_size && head->hd_sec_sz_s != size_to_shift(hd_sector_size))
- ERROR( "hd sector size doesn't match" );
- if (!force_mode && num_hd_sector && head->n_hd_sec != wbfs_htonl( num_hd_sector ))
- ERROR( "hd num sector doesn't match" );
- p->hd_sec_sz = 1 << head->hd_sec_sz_s;
- p->hd_sec_sz_s = head->hd_sec_sz_s;
- p->n_hd_sec = wbfs_ntohl( head->n_hd_sec );
-
- p->n_wii_sec = (p->n_hd_sec / p->wii_sec_sz) * (p->hd_sec_sz);
-
- p->wbfs_sec_sz_s = head->wbfs_sec_sz_s;
- p->wbfs_sec_sz = 1 << p->wbfs_sec_sz_s;
- p->n_wbfs_sec = p->n_wii_sec >> (p->wbfs_sec_sz_s - p->wii_sec_sz_s);
- p->n_wbfs_sec_per_disc = p->n_wii_sec_per_disc >> (p->wbfs_sec_sz_s - p->wii_sec_sz_s);
- p->disc_info_sz = ALIGN_LBA( sizeof( wbfs_disc_info_t ) + p->n_wbfs_sec_per_disc * 2 );
-
- //printf("hd_sector_size %X wii_sector size %X wbfs sector_size %X\n",p->hd_sec_sz,p->wii_sec_sz,p->wbfs_sec_sz);
- p->read_hdsector = read_hdsector;
- p->write_hdsector = write_hdsector;
- p->callback_data = callback_data;
-
- p->freeblks_lba = (p->wbfs_sec_sz - p->n_wbfs_sec / 8) >> p->hd_sec_sz_s;
-
- if (!reset)
- p->freeblks = 0; // will alloc and read only if needed
- else
- {
- // init with all free blocks
- p->freeblks = wbfs_ioalloc( ALIGN_LBA( p->n_wbfs_sec / 8 ) );
- wbfs_memset( p->freeblks, 0xff, p->n_wbfs_sec / 8 );
- }
- p->max_disc = (p->freeblks_lba - 1) / (p->disc_info_sz >> p->hd_sec_sz_s);
- if (p->max_disc > p->hd_sec_sz - sizeof(wbfs_head_t)) p->max_disc = p->hd_sec_sz - sizeof(wbfs_head_t);
-
- p->tmp_buffer = wbfs_ioalloc( p->hd_sec_sz );
- p->n_disc_open = 0;
- return p;
- error: wbfs_free( p );
- wbfs_iofree( head );
- return 0;
-
-}
-
-void wbfs_sync(wbfs_t*p)
-{
- // copy back descriptors
- if (p->write_hdsector)
- {
- p->write_hdsector(p->callback_data, p->part_lba + 0, 1, p->head);
-
- if (p->freeblks) p->write_hdsector(p->callback_data, p->part_lba + p->freeblks_lba,
- ALIGN_LBA( p->n_wbfs_sec / 8 ) >> p->hd_sec_sz_s, p->freeblks);
- }
-}
-
-void wbfs_close(wbfs_t*p)
-{
- wbfs_sync(p);
-
- if (p->n_disc_open)
- ERROR( "trying to close wbfs while discs still open" );
-
- wbfs_iofree( p->head );
- wbfs_iofree( p->tmp_buffer );
- if (p->freeblks) wbfs_iofree( p->freeblks );
-
- wbfs_free( p );
-
- error: return;
-}
-
-wbfs_disc_t *wbfs_open_disc(wbfs_t* p, u8 *discid)
-{
- u32 i;
- int disc_info_sz_lba = p->disc_info_sz >> p->hd_sec_sz_s;
- wbfs_disc_t *d = 0;
- for (i = 0; i < p->max_disc; i++)
- {
- if (p->head->disc_table[i])
- {
- p->read_hdsector(p->callback_data, p->part_lba + 1 + i * disc_info_sz_lba, 1, p->tmp_buffer);
- if (wbfs_memcmp( discid, p->tmp_buffer, 6 ) == 0)
- {
- d = wbfs_malloc( sizeof( *d ) );
- if (!d)
- ERROR( "allocating memory" );
- d->p = p;
- d->i = i;
- d->header = wbfs_ioalloc( p->disc_info_sz );
- if (!d->header)
- ERROR( "allocating memory" );
- p->read_hdsector(p->callback_data, p->part_lba + 1 + i * disc_info_sz_lba, disc_info_sz_lba, d->header);
- p->n_disc_open++;
- // for(i=0;in_wbfs_sec_per_disc;i++)
- // printf("%d,",wbfs_ntohs(d->header->wlba_table[i]));
- return d;
- }
- }
- }
- return 0;
- error: if (d) wbfs_iofree( d );
- return 0;
-
-}
-void wbfs_close_disc(wbfs_disc_t*d)
-{
- d->p->n_disc_open--;
- wbfs_iofree( d->header );
- 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, u32 len, u8 *data)
-{
- if (d->p == &wbfs_iso_file)
- {
- return wbfs_iso_file_read(d, offset, data, len);
- }
-
- wbfs_t *p = d->p;
- u16 wlba = offset >> (p->wbfs_sec_sz_s - 2);
- u32 iwlba_shift = p->wbfs_sec_sz_s - p->hd_sec_sz_s;
- u32 lba_mask = (p->wbfs_sec_sz - 1) >> (p->hd_sec_sz_s);
- u32 lba = (offset >> (p->hd_sec_sz_s - 2)) & lba_mask;
- u32 off = offset & ((p->hd_sec_sz >> 2) - 1);
- u16 iwlba = wbfs_ntohs( d->header->wlba_table[wlba] );
- u32 len_copied;
- int err = 0;
- u8 *ptr = data;
- if (unlikely( iwlba == 0 )) return 1;
- if (unlikely( off ))
- {
- off *= 4;
- err = p->read_hdsector(p->callback_data, p->part_lba + (iwlba << iwlba_shift) + lba, 1, p->tmp_buffer);
- if (err) return err;
- len_copied = p->hd_sec_sz - off;
- if (likely( len < len_copied )) len_copied = len;
- wbfs_memcpy( ptr, p->tmp_buffer + off, len_copied );
- len -= len_copied;
- ptr += len_copied;
- lba++;
- if (unlikely( lba > lba_mask && len ))
- {
- lba = 0;
- iwlba = wbfs_ntohs( d->header->wlba_table[++wlba] );
- if (unlikely( iwlba == 0 )) return 1;
- }
- }
- while (likely( len >= p->hd_sec_sz ))
- {
- u32 nlb = len >> (p->hd_sec_sz_s);
-
- if (unlikely( lba + nlb > p->wbfs_sec_sz )) // dont cross wbfs sectors..
- nlb = p->wbfs_sec_sz - lba;
- err = p->read_hdsector(p->callback_data, p->part_lba + (iwlba << iwlba_shift) + lba, nlb, ptr);
- if (err) return err;
- len -= nlb << p->hd_sec_sz_s;
- ptr += nlb << p->hd_sec_sz_s;
- lba += nlb;
- if (unlikely( lba > lba_mask && len ))
- {
- lba = 0;
- iwlba = wbfs_ntohs( d->header->wlba_table[++wlba] );
- if (unlikely( iwlba == 0 )) return 1;
- }
- }
- if (unlikely( len ))
- {
- err = p->read_hdsector(p->callback_data, p->part_lba + (iwlba << iwlba_shift) + lba, 1, p->tmp_buffer);
- if (err) return err;
- wbfs_memcpy( ptr, p->tmp_buffer, len );
- }
- return 0;
-}
-
-// disc listing
-u32 wbfs_count_discs(wbfs_t*p)
-{
- u32 i, count = 0;
- for (i = 0; i < p->max_disc; i++)
- if (p->head->disc_table[i]) count++;
- return count;
-
-}
-
-u32 wbfs_sector_used(wbfs_t *p, wbfs_disc_info_t *di)
-{
- u32 tot_blk = 0, j;
- for (j = 0; j < p->n_wbfs_sec_per_disc; j++)
- if (wbfs_ntohs( di->wlba_table[j] )) tot_blk++;
- return tot_blk;
-}
-
-u32 wbfs_sector_used2(wbfs_t *p, wbfs_disc_info_t *di, u32 *last_blk)
-{
- u32 tot_blk = 0, j;
- for (j = 0; j < p->n_wbfs_sec_per_disc; j++)
- if (wbfs_ntohs( di->wlba_table[j] ))
- {
- if (last_blk) *last_blk = j;
- tot_blk++;
- }
- return tot_blk;
-}
-
-u32 wbfs_get_disc_info(wbfs_t*p, u32 index, u8 *header, int header_size, u32 *size)//size in 32 bit
-{
- u32 i, count = 0;
- if (!p) return 1;
- int disc_info_sz_lba = p->disc_info_sz >> p->hd_sec_sz_s;
-
- for (i = 0; i < p->max_disc; i++)
- if (p->head->disc_table[i])
- {
- if (count++ == index)
- {
- p->read_hdsector(p->callback_data, p->part_lba + 1 + i * disc_info_sz_lba, 1, p->tmp_buffer);
- if (header_size > (int) p->hd_sec_sz) header_size = p->hd_sec_sz;
- u32 magic = wbfs_ntohl( *( u32* )( p->tmp_buffer + 24 ) );
- if (magic != 0x5D1C9EA3)
- {
- p->head->disc_table[i] = 0;
- return 1;
- }
- memcpy(header, p->tmp_buffer, header_size);
- if (size)
- {
- u8 *header = wbfs_ioalloc( p->disc_info_sz );
- p->read_hdsector(p->callback_data, p->part_lba + 1 + i * disc_info_sz_lba, disc_info_sz_lba, header);
- u32 sec_used = wbfs_sector_used(p, (wbfs_disc_info_t *) header);
- wbfs_iofree( header );
- *size = sec_used << (p->wbfs_sec_sz_s - 2);
- }
- return 0;
- }
- }
- return 1;
-}
-
-static void load_freeblocks(wbfs_t*p)
-{
- if (p->freeblks) return;
- // XXX should handle malloc error..
- p->freeblks = wbfs_ioalloc( ALIGN_LBA( p->n_wbfs_sec / 8 ) );
- p->read_hdsector(p->callback_data, p->part_lba + p->freeblks_lba, ALIGN_LBA( p->n_wbfs_sec / 8 ) >> p->hd_sec_sz_s,
- p->freeblks);
-
-}
-u32 wbfs_count_usedblocks(wbfs_t*p)
-{
- u32 i, j, count = 0;
- load_freeblocks(p);
- for (i = 0; i < p->n_wbfs_sec / (8 * 4); i++)
- {
- u32 v = wbfs_ntohl( p->freeblks[i] );
- if (v == ~0U)
- count += 32;
- else if (v != 0) for (j = 0; j < 32; j++)
- if (v & (1 << j)) count++;
- }
- return count;
-}
-
-// write access
-
-
-//static
-int block_used(u8 *used, u32 i, u32 wblk_sz)
-{
- u32 k;
- i *= wblk_sz;
- for (k = 0; k < wblk_sz; k++)
- if (i + k < 143432 * 2 && used[i + k]) return 1;
- return 0;
-}
-
-static u32 alloc_block(wbfs_t*p)
-{
- u32 i, j;
- for (i = 0; i < p->n_wbfs_sec / (8 * 4); i++)
- {
- u32 v = wbfs_ntohl( p->freeblks[i] );
- if (v != 0)
- {
- for (j = 0; j < 32; j++)
- if (v & (1 << j))
- {
- p->freeblks[i] = wbfs_htonl( v & ~( 1 << j ) );
- return (i * 32) + j + 1;
- }
- }
- }
- return ~0;
-}
-static void free_block(wbfs_t *p, int bl)
-{
- int i = (bl - 1) / (32);
- int j = (bl - 1) & 31;
- u32 v = wbfs_ntohl( p->freeblks[i] );
- p->freeblks[i] = wbfs_htonl( v | 1 << j );
-}
-
-u32 wbfs_add_disc(wbfs_t*p, read_wiidisc_callback_t read_src_wii_disc, void *callback_data,
- progress_callback_t spinner, partition_selector_t sel, int copy_1_1)
-{
- int i, discn;
- u32 tot, cur;
- u32 wii_sec_per_wbfs_sect = 1 << (p->wbfs_sec_sz_s - p->wii_sec_sz_s);
- wiidisc_t *d = 0;
- u8 *used = 0;
- wbfs_disc_info_t *info = 0;
- u8* copy_buffer = 0;
- int retval = -1;
- int num_wbfs_sect_to_copy;
- u32 last_used;
- used = wbfs_malloc( p->n_wii_sec_per_disc );
-
- if (!used)
- ERROR( "unable to alloc memory" );
- // copy_1_1 needs disk usage for layers detection
- //if(!copy_1_1)
- {
- d = wd_open_disc(read_src_wii_disc, callback_data);
- if (!d)
- ERROR( "unable to open wii disc" );
- wd_build_disc_usage(d, sel, used);
- wd_close_disc(d);
- d = 0;
- }
-
- for (i = 0; i < p->max_disc; i++)// find a free slot.
- if (p->head->disc_table[i] == 0) break;
- if (i == p->max_disc)
- ERROR( "no space left on device (table full)" );
- p->head->disc_table[i] = 1;
- discn = i;
- load_freeblocks(p);
-
- // build disc info
- info = wbfs_ioalloc( p->disc_info_sz );
- read_src_wii_disc(callback_data, 0, 0x100, info->disc_header_copy);
-
- copy_buffer = wbfs_ioalloc( p->wii_sec_sz );
- if (!copy_buffer)
- ERROR( "alloc memory" );
- tot = 0;
- cur = 0;
- num_wbfs_sect_to_copy = p->n_wbfs_sec_per_disc;
- // count total number of sectors to write
- last_used = 0;
- for (i = 0; i < num_wbfs_sect_to_copy; i++)
- {
- if (block_used(used, i, wii_sec_per_wbfs_sect))
- {
- tot += wii_sec_per_wbfs_sect;
- last_used = i;
- }
- }
- if (copy_1_1)
- {
- // detect single or dual layer
- if ((last_used + 1) > (p->n_wbfs_sec_per_disc / 2))
- {
- // dual layer
- num_wbfs_sect_to_copy = p->n_wbfs_sec_per_disc;
- }
- else
- {
- // single layer
- num_wbfs_sect_to_copy = p->n_wbfs_sec_per_disc / 2;
- }
- tot = num_wbfs_sect_to_copy * wii_sec_per_wbfs_sect;
- }
- /*
- // num of hd sectors to copy could be specified directly
- if (copy_1_1 > 1) {
- u32 hd_sec_per_wii_sec = p->wii_sec_sz / p->hd_sec_sz;
- num_wbfs_sect_to_copy = copy_1_1 / hd_sec_per_wii_sec / wii_sec_per_wbfs_sect;
- tot = num_wbfs_sect_to_copy * wii_sec_per_wbfs_sect;
- }*/
- int ret = 0;
- if (spinner) spinner(0, tot);
- for (i = 0; i < num_wbfs_sect_to_copy; i++)
- {
- u16 bl = 0;
- if (copy_1_1 || block_used(used, i, wii_sec_per_wbfs_sect))
- {
- u16 j;
-
- bl = alloc_block(p);
- if (bl == 0xffff)
- ERROR( "no space left on device (disc full)" );
- for (j = 0; j < wii_sec_per_wbfs_sect; j++)
- {
- u32 offset = (i * (p->wbfs_sec_sz >> 2)) + (j * (p->wii_sec_sz >> 2));
-
- ret = read_src_wii_disc(callback_data, offset, p->wii_sec_sz, copy_buffer);
- if (ret)
- {
- if (copy_1_1 && i > p->n_wbfs_sec_per_disc / 2)
- {
- // end of dual layer data
- if (j > 0)
- {
- info->wlba_table[i] = wbfs_htons( bl );
- }
- spinner(tot, tot);
- break;
- }
- //ERROR("read error");
- printf("\rWARNING: read (%u) error (%d)\n", offset, ret);
- }
-
- //fix the partition table
- if (offset == (0x40000 >> 2)) wd_fix_partition_table(d, sel, copy_buffer);
- p->write_hdsector(p->callback_data, p->part_lba + bl * (p->wbfs_sec_sz / p->hd_sec_sz) + j
- * (p->wii_sec_sz / p->hd_sec_sz), p->wii_sec_sz / p->hd_sec_sz, copy_buffer);
- cur++;
- if (spinner) spinner(cur, tot);
- }
- }
- if (ret) break;
- info->wlba_table[i] = wbfs_htons( bl );
- wbfs_sync(p);
- }
- // write disc info
- int disc_info_sz_lba = p->disc_info_sz >> p->hd_sec_sz_s;
- p->write_hdsector(p->callback_data, p->part_lba + 1 + discn * disc_info_sz_lba, disc_info_sz_lba, info);
- wbfs_sync(p);
- retval = 0;
- error: if (d) wd_close_disc(d);
- if (used) wbfs_free( used );
- if (info) wbfs_iofree( info );
- if (copy_buffer) wbfs_iofree( copy_buffer );
- // init with all free blocks
-
- return retval;
-}
-
-u32 wbfs_rm_disc(wbfs_t*p, u8* discid)
-{
- wbfs_disc_t *d = wbfs_open_disc(p, discid);
- int i;
- int discn = 0;
- int disc_info_sz_lba = p->disc_info_sz >> p->hd_sec_sz_s;
- if (!d) return 1;
- load_freeblocks(p);
- discn = d->i;
- for (i = 0; i < p->n_wbfs_sec_per_disc; i++)
- {
- u32 iwlba = wbfs_ntohs( d->header->wlba_table[i] );
- if (iwlba) free_block(p, iwlba);
- }
- memset(d->header, 0, p->disc_info_sz);
- p->write_hdsector(p->callback_data, p->part_lba + 1 + discn * disc_info_sz_lba, disc_info_sz_lba, d->header);
- p->head->disc_table[discn] = 0;
- wbfs_close_disc(d);
- wbfs_sync(p);
- return 0;
-}
-
-u32 wbfs_ren_disc(wbfs_t*p, u8* discid, u8* newname)
-{
- wbfs_disc_t *d = wbfs_open_disc(p, discid);
- int disc_info_sz_lba = p->disc_info_sz >> p->hd_sec_sz_s;
-
- if (!d) return 1;
-
- memset(d->header->disc_header_copy + 0x20, 0, 0x40);
- strncpy((char *) d->header->disc_header_copy + 0x20, (char *) newname, 0x39);
-
- p->write_hdsector(p->callback_data, p->part_lba + 1 + d->i * disc_info_sz_lba, disc_info_sz_lba, d->header);
- wbfs_close_disc(d);
- return 0;
-}
-
-u32 wbfs_rID_disc(wbfs_t*p, u8* discid, u8* newID)
-{
- wbfs_disc_t *d = wbfs_open_disc(p, discid);
- int disc_info_sz_lba = p->disc_info_sz >> p->hd_sec_sz_s;
-
- if (!d) return 1;
-
- memset(d->header->disc_header_copy, 0, 0x10);
- strncpy((char *) d->header->disc_header_copy, (char *) newID, 0x9);
-
- p->write_hdsector(p->callback_data, p->part_lba + 1 + d->i * disc_info_sz_lba, disc_info_sz_lba, d->header);
- wbfs_close_disc(d);
- return 0;
-}
-
-// trim the file-system to its minimum size
-u32 wbfs_trim(wbfs_t*p)
-{
- u32 maxbl;
- load_freeblocks(p);
- maxbl = alloc_block(p);
- p->n_hd_sec = maxbl << (p->wbfs_sec_sz_s - p->hd_sec_sz_s);
- p->head->n_hd_sec = wbfs_htonl( p->n_hd_sec );
- // make all block full
- memset(p->freeblks, 0, p->n_wbfs_sec / 8);
- wbfs_sync(p);
- // os layer will truncate the file.
- return maxbl;
-}
-
-// data extraction
-u32 wbfs_extract_disc(wbfs_disc_t*d, rw_sector_callback_t write_dst_wii_sector, void *callback_data,
- progress_callback_t spinner)
-{
- wbfs_t *p = d->p;
- u8* copy_buffer = 0;
- int i;
- int src_wbs_nlb = p->wbfs_sec_sz / p->hd_sec_sz;
- int dst_wbs_nlb = p->wbfs_sec_sz / p->wii_sec_sz;
- copy_buffer = wbfs_ioalloc( p->wbfs_sec_sz );
- if (!copy_buffer)
- ERROR( "alloc memory" );
-
- for (i = 0; i < p->n_wbfs_sec_per_disc; i++)
- {
- u32 iwlba = wbfs_ntohs( d->header->wlba_table[i] );
- if (iwlba)
- {
-
- if (spinner) spinner(i, p->n_wbfs_sec_per_disc);
- p->read_hdsector(p->callback_data, p->part_lba + iwlba * src_wbs_nlb, src_wbs_nlb, copy_buffer);
- write_dst_wii_sector(callback_data, i * dst_wbs_nlb, dst_wbs_nlb, copy_buffer);
- }
- }
- wbfs_iofree( copy_buffer );
- return 0;
- error: return 1;
-}
-
-float wbfs_estimate_disc(wbfs_t *p, read_wiidisc_callback_t read_src_wii_disc, void *callback_data,
- partition_selector_t sel)
-{
- u8 *b;
- int i;
- u32 tot;
- u32 wii_sec_per_wbfs_sect = 1 << (p->wbfs_sec_sz_s - p->wii_sec_sz_s);
- wiidisc_t *d = 0;
- u8 *used = 0;
- wbfs_disc_info_t *info = 0;
-
- tot = 0;
-
- used = wbfs_malloc( p->n_wii_sec_per_disc );
- if (!used)
- {
- ERROR( "unable to alloc memory" );
- }
-
- d = wd_open_disc(read_src_wii_disc, callback_data);
- if (!d)
- {
- ERROR( "unable to open wii disc" );
- }
-
- wd_build_disc_usage(d, sel, used);
- wd_close_disc(d);
- d = 0;
-
- info = wbfs_ioalloc( p->disc_info_sz );
- b = (u8 *) info;
- read_src_wii_disc(callback_data, 0, 0x100, info->disc_header_copy);
-
- //fprintf(stderr, "estimating %c%c%c%c%c%c %s...\n",b[0], b[1], b[2], b[3], b[4], b[5], b + 0x20);
-
- for (i = 0; i < p->n_wbfs_sec_per_disc; i++)
- {
- if (block_used(used, i, wii_sec_per_wbfs_sect))
- {
- tot++;
- }
- }
- //memcpy(header, b,0x100);
-
- error: if (d) wd_close_disc(d);
-
- if (used) wbfs_free( used );
-
- if (info) wbfs_iofree( info );
-
- return tot * (((p->wbfs_sec_sz * 1.0) / p->hd_sec_sz) * 512);
-}
-u32 wbfs_size_disc(wbfs_t*p, read_wiidisc_callback_t read_src_wii_disc, void *callback_data, partition_selector_t sel,
- u32 *comp_size, u32 *real_size)
-{
- int i;
- u32 tot = 0, last = 0;
- u32 wii_sec_per_wbfs_sect = 1 << (p->wbfs_sec_sz_s - p->wii_sec_sz_s);
- wiidisc_t *d = 0;
- u8 *used = 0;
- used = wbfs_malloc( p->n_wii_sec_per_disc );
- if (!used)
- ERROR( "unable to alloc memory" );
- d = wd_open_disc(read_src_wii_disc, callback_data);
- if (!d)
- ERROR( "unable to open wii disc" );
- wd_build_disc_usage(d, sel, used);
- wd_close_disc(d);
- d = 0;
-
- // count total number to write for spinner
- for (i = 0; i < p->n_wbfs_sec_per_disc; i++)
- {
- if (block_used(used, i, wii_sec_per_wbfs_sect))
- {
- tot += wii_sec_per_wbfs_sect;
- last = i * wii_sec_per_wbfs_sect;
- }
- }
-
- error: if (d) wd_close_disc(d);
- if (used) wbfs_free( used );
-
- *comp_size = tot;
- *real_size = last;
-
- return 0;
-}
-
-// 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)
-
-// offset points 32bit words, count counts bytes
-//int (*read_wiidisc_callback_t)(void*fp,u32 offset,u32 count,void*iobuf);
-
-// connect wiidisc to wbfs_disc
-int read_wiidisc_wbfsdisc(void*fp, u32 offset, u32 count, void*iobuf)
-{
- return wbfs_disc_read((wbfs_disc_t*) fp, offset, count, iobuf);
-}
-
-int wbfs_extract_file(wbfs_disc_t*d, char *path, void **data)
-{
- wiidisc_t *wd = 0;
- int ret = 0;
-
- wd = wd_open_disc(read_wiidisc_wbfsdisc, d);
- if (!wd)
- {
- ERROR( "opening wbfs disc" );
- return -1;
- }
- wd->extracted_size = 0;
- *data = wd_extract_file(wd, ONLY_GAME_PARTITION, path);
- ret = wd->extracted_size;
- if (!*data)
- {
- //ERROR("file not found");
- ret = -1;
- }
- wd_close_disc(wd);
- error: return ret;
-}
-
-int wbfs_get_fragments(wbfs_disc_t *d, _frag_append_t append_fragment, void *callback_data)
-{
- if (!d) return -1;
- wbfs_t *p = d->p;
- int src_wbs_nlb = p->wbfs_sec_sz / p->hd_sec_sz;
- int i, ret, last = 0;
- for (i = 0; i < p->n_wbfs_sec_per_disc; i++)
- {
- u32 iwlba = wbfs_ntohs( d->header->wlba_table[i] );
- if (iwlba)
- {
- ret = append_fragment(callback_data, i * src_wbs_nlb, // offset
- p->part_lba + iwlba * src_wbs_nlb, // sector
- src_wbs_nlb); // count
- if (ret) return ret; // error
- last = i;
- }
- }
- if (last < p->n_wbfs_sec_per_disc / 2)
- {
- last = p->n_wbfs_sec_per_disc / 2;
- }
- u32 size = last * src_wbs_nlb;
- append_fragment(callback_data, size, 0, 0); // set size
- return 0;
-}
-
-// wrapper for reading .iso files using wbfs apis
-
-#include
-#include
-
-// offset is pointing 32bit words to address the whole dvd, although len is in bytes
-int wbfs_iso_file_read(wbfs_disc_t*d, u32 offset, u8 *data, u32 len)
-{
- if (!d || d->p != &wbfs_iso_file) return -1;
- int fd = (int) d->header;
- off_t off = ((u64) offset) << 2;
- off_t ret_off;
- int ret;
- ret_off = lseek(fd, off, SEEK_SET);
- if (ret_off != off) return -1;
- ret = read(fd, data, len);
- if (ret != len) return -2;
- return 0;
-}
-
-u32 wbfs_disc_sector_used(wbfs_disc_t *d, u32 *num_blk)
-{
- if (d->p == &wbfs_iso_file)
- {
- int fd = (int) d->header;
- struct stat st;
- if (fstat(fd, &st) == -1) return 0;
- if (num_blk)
- {
- *num_blk = (st.st_size >> 9); // in 512 units
- }
- return st.st_blocks; // in 512 units (can be sparse)
- }
- u32 last_blk = 0;
- u32 ret;
- ret = wbfs_sector_used2(d->p, d->header, &last_blk);
- if (num_blk)
- {
- *num_blk = last_blk + 1;
- }
- return ret;
-}
-
+// Copyright 2009 Kwiirk
+// Licensed under the terms of the GNU GPL, version 2
+// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+
+// Modified by oggzee
+
+#include "libwbfs.h"
+
+#define likely(x) __builtin_expect(!!(x), 1)
+#define unlikely(x) __builtin_expect(!!(x), 0)
+
+#define ERROR(x) do {wbfs_error(x);goto error;}while(0)
+#define ALIGN_LBA(x) (((x)+p->hd_sec_sz-1)&(~(p->hd_sec_sz-1)))
+
+wbfs_t wbfs_iso_file;
+
+static int force_mode = 0;
+
+void wbfs_set_force_mode(int force)
+{
+ force_mode = force;
+}
+
+static u8 size_to_shift(u32 size)
+{
+ u8 ret = 0;
+ while (size)
+ {
+ ret++;
+ size >>= 1;
+ }
+ return ret - 1;
+}
+#define read_le32_unaligned(x) ((x)[0]|((x)[1]<<8)|((x)[2]<<16)|((x)[3]<<24))
+
+wbfs_t*wbfs_open_hd(rw_sector_callback_t read_hdsector, rw_sector_callback_t write_hdsector, void *callback_data,
+ int hd_sector_size, int num_hd_sector __attribute( ( unused ) ), int reset)
+{
+ int i = num_hd_sector, ret;
+ u8 *ptr, *tmp_buffer = wbfs_ioalloc( hd_sector_size );
+ u8 part_table[16 * 4];
+ ret = read_hdsector(callback_data, 0, 1, tmp_buffer);
+ if (ret) return 0;
+ //find wbfs partition
+ wbfs_memcpy( part_table, tmp_buffer + 0x1be, 16*4 );
+ ptr = part_table;
+ for (i = 0; i < 4; i++, ptr += 16)
+ {
+ u32 part_lba = read_le32_unaligned( ptr + 0x8 );
+ wbfs_head_t *head = (wbfs_head_t *) tmp_buffer;
+ ret = read_hdsector(callback_data, part_lba, 1, tmp_buffer);
+ // verify there is the magic.
+ if (head->magic == wbfs_htonl( WBFS_MAGIC ))
+ {
+ wbfs_t*p = wbfs_open_partition(read_hdsector, write_hdsector, callback_data, hd_sector_size, 0, part_lba,
+ reset);
+ wbfs_iofree( tmp_buffer );
+ return p;
+ }
+ }
+ wbfs_iofree( tmp_buffer );
+ if (reset)// XXX make a empty hd partition..
+ {
+ }
+ return 0;
+}
+wbfs_t*wbfs_open_partition(rw_sector_callback_t read_hdsector, rw_sector_callback_t write_hdsector,
+ void *callback_data, int hd_sector_size, int num_hd_sector, u32 part_lba, int reset)
+{
+ wbfs_t *p = wbfs_malloc( sizeof( wbfs_t ) );
+
+ wbfs_head_t *head = wbfs_ioalloc( hd_sector_size ? hd_sector_size : 512 );
+
+ //constants, but put here for consistancy
+ p->wii_sec_sz = 0x8000;
+ p->wii_sec_sz_s = size_to_shift(0x8000);
+ p->n_wii_sec = (num_hd_sector / 0x8000) * hd_sector_size;
+ p->n_wii_sec_per_disc = 143432 * 2;//support for double layers discs..
+ p->head = head;
+ p->part_lba = part_lba;
+ // init the partition
+ if (reset)
+ {
+ u8 sz_s;
+ wbfs_memset( head, 0, hd_sector_size );
+ head->magic = wbfs_htonl( WBFS_MAGIC );
+ head->hd_sec_sz_s = size_to_shift(hd_sector_size);
+ head->n_hd_sec = wbfs_htonl( num_hd_sector );
+ // choose minimum wblk_sz that fits this partition size
+ for (sz_s = 6; sz_s < 11; sz_s++)
+ {
+ // ensure that wbfs_sec_sz is big enough to address every blocks using 16 bits
+ if (p->n_wii_sec < ((1U << 16) * (1 << sz_s))) break;
+ }
+ head->wbfs_sec_sz_s = sz_s + p->wii_sec_sz_s;
+ }
+ else read_hdsector(callback_data, p->part_lba, 1, head);
+ if (head->magic != wbfs_htonl( WBFS_MAGIC ))
+ ERROR( "bad magic" );
+ if (!force_mode && hd_sector_size && head->hd_sec_sz_s != size_to_shift(hd_sector_size))
+ ERROR( "hd sector size doesn't match" );
+ if (!force_mode && num_hd_sector && head->n_hd_sec != wbfs_htonl( num_hd_sector ))
+ ERROR( "hd num sector doesn't match" );
+ p->hd_sec_sz = 1 << head->hd_sec_sz_s;
+ p->hd_sec_sz_s = head->hd_sec_sz_s;
+ p->n_hd_sec = wbfs_ntohl( head->n_hd_sec );
+
+ p->n_wii_sec = (p->n_hd_sec / p->wii_sec_sz) * (p->hd_sec_sz);
+
+ p->wbfs_sec_sz_s = head->wbfs_sec_sz_s;
+ p->wbfs_sec_sz = 1 << p->wbfs_sec_sz_s;
+ p->n_wbfs_sec = p->n_wii_sec >> (p->wbfs_sec_sz_s - p->wii_sec_sz_s);
+ p->n_wbfs_sec_per_disc = p->n_wii_sec_per_disc >> (p->wbfs_sec_sz_s - p->wii_sec_sz_s);
+ p->disc_info_sz = ALIGN_LBA( sizeof( wbfs_disc_info_t ) + p->n_wbfs_sec_per_disc * 2 );
+
+ //printf("hd_sector_size %X wii_sector size %X wbfs sector_size %X\n",p->hd_sec_sz,p->wii_sec_sz,p->wbfs_sec_sz);
+ p->read_hdsector = read_hdsector;
+ p->write_hdsector = write_hdsector;
+ p->callback_data = callback_data;
+
+ p->freeblks_lba = (p->wbfs_sec_sz - p->n_wbfs_sec / 8) >> p->hd_sec_sz_s;
+
+ if (!reset)
+ p->freeblks = 0; // will alloc and read only if needed
+ else
+ {
+ // init with all free blocks
+ p->freeblks = wbfs_ioalloc( ALIGN_LBA( p->n_wbfs_sec / 8 ) );
+ wbfs_memset( p->freeblks, 0xff, p->n_wbfs_sec / 8 );
+ }
+ p->max_disc = (p->freeblks_lba - 1) / (p->disc_info_sz >> p->hd_sec_sz_s);
+ if (p->max_disc > p->hd_sec_sz - sizeof(wbfs_head_t)) p->max_disc = p->hd_sec_sz - sizeof(wbfs_head_t);
+
+ p->tmp_buffer = wbfs_ioalloc( p->hd_sec_sz );
+ p->n_disc_open = 0;
+ return p;
+ error: wbfs_free( p );
+ wbfs_iofree( head );
+ return 0;
+
+}
+
+void wbfs_sync(wbfs_t*p)
+{
+ // copy back descriptors
+ if (p->write_hdsector)
+ {
+ p->write_hdsector(p->callback_data, p->part_lba + 0, 1, p->head);
+
+ if (p->freeblks) p->write_hdsector(p->callback_data, p->part_lba + p->freeblks_lba,
+ ALIGN_LBA( p->n_wbfs_sec / 8 ) >> p->hd_sec_sz_s, p->freeblks);
+ }
+}
+
+void wbfs_close(wbfs_t*p)
+{
+ wbfs_sync(p);
+
+ if (p->n_disc_open)
+ ERROR( "trying to close wbfs while discs still open" );
+
+ wbfs_iofree( p->head );
+ wbfs_iofree( p->tmp_buffer );
+ if (p->freeblks) wbfs_iofree( p->freeblks );
+
+ wbfs_free( p );
+
+ error: return;
+}
+
+wbfs_disc_t *wbfs_open_disc(wbfs_t* p, u8 *discid)
+{
+ u32 i;
+ int disc_info_sz_lba = p->disc_info_sz >> p->hd_sec_sz_s;
+ wbfs_disc_t *d = 0;
+ for (i = 0; i < p->max_disc; i++)
+ {
+ if (p->head->disc_table[i])
+ {
+ p->read_hdsector(p->callback_data, p->part_lba + 1 + i * disc_info_sz_lba, 1, p->tmp_buffer);
+ if (wbfs_memcmp( discid, p->tmp_buffer, 6 ) == 0)
+ {
+ d = wbfs_malloc( sizeof( *d ) );
+ if (!d)
+ ERROR( "allocating memory" );
+ d->p = p;
+ d->i = i;
+ d->header = wbfs_ioalloc( p->disc_info_sz );
+ if (!d->header)
+ ERROR( "allocating memory" );
+ p->read_hdsector(p->callback_data, p->part_lba + 1 + i * disc_info_sz_lba, disc_info_sz_lba, d->header);
+ p->n_disc_open++;
+ // for(i=0;in_wbfs_sec_per_disc;i++)
+ // printf("%d,",wbfs_ntohs(d->header->wlba_table[i]));
+ return d;
+ }
+ }
+ }
+ return 0;
+ error: if (d) wbfs_iofree( d );
+ return 0;
+
+}
+void wbfs_close_disc(wbfs_disc_t*d)
+{
+ d->p->n_disc_open--;
+ wbfs_iofree( d->header );
+ 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, u32 len, u8 *data)
+{
+ if (d->p == &wbfs_iso_file)
+ {
+ return wbfs_iso_file_read(d, offset, data, len);
+ }
+
+ wbfs_t *p = d->p;
+ u16 wlba = offset >> (p->wbfs_sec_sz_s - 2);
+ u32 iwlba_shift = p->wbfs_sec_sz_s - p->hd_sec_sz_s;
+ u32 lba_mask = (p->wbfs_sec_sz - 1) >> (p->hd_sec_sz_s);
+ u32 lba = (offset >> (p->hd_sec_sz_s - 2)) & lba_mask;
+ u32 off = offset & ((p->hd_sec_sz >> 2) - 1);
+ u16 iwlba = wbfs_ntohs( d->header->wlba_table[wlba] );
+ u32 len_copied;
+ int err = 0;
+ u8 *ptr = data;
+ if (unlikely( iwlba == 0 )) return 1;
+ if (unlikely( off ))
+ {
+ off *= 4;
+ err = p->read_hdsector(p->callback_data, p->part_lba + (iwlba << iwlba_shift) + lba, 1, p->tmp_buffer);
+ if (err) return err;
+ len_copied = p->hd_sec_sz - off;
+ if (likely( len < len_copied )) len_copied = len;
+ wbfs_memcpy( ptr, p->tmp_buffer + off, len_copied );
+ len -= len_copied;
+ ptr += len_copied;
+ lba++;
+ if (unlikely( lba > lba_mask && len ))
+ {
+ lba = 0;
+ iwlba = wbfs_ntohs( d->header->wlba_table[++wlba] );
+ if (unlikely( iwlba == 0 )) return 1;
+ }
+ }
+ while (likely( len >= p->hd_sec_sz ))
+ {
+ u32 nlb = len >> (p->hd_sec_sz_s);
+
+ if (unlikely( lba + nlb > p->wbfs_sec_sz )) // dont cross wbfs sectors..
+ nlb = p->wbfs_sec_sz - lba;
+ err = p->read_hdsector(p->callback_data, p->part_lba + (iwlba << iwlba_shift) + lba, nlb, ptr);
+ if (err) return err;
+ len -= nlb << p->hd_sec_sz_s;
+ ptr += nlb << p->hd_sec_sz_s;
+ lba += nlb;
+ if (unlikely( lba > lba_mask && len ))
+ {
+ lba = 0;
+ iwlba = wbfs_ntohs( d->header->wlba_table[++wlba] );
+ if (unlikely( iwlba == 0 )) return 1;
+ }
+ }
+ if (unlikely( len ))
+ {
+ err = p->read_hdsector(p->callback_data, p->part_lba + (iwlba << iwlba_shift) + lba, 1, p->tmp_buffer);
+ if (err) return err;
+ wbfs_memcpy( ptr, p->tmp_buffer, len );
+ }
+ return 0;
+}
+
+// disc listing
+u32 wbfs_count_discs(wbfs_t*p)
+{
+ u32 i, count = 0;
+ for (i = 0; i < p->max_disc; i++)
+ if (p->head->disc_table[i]) count++;
+ return count;
+
+}
+
+u32 wbfs_sector_used(wbfs_t *p, wbfs_disc_info_t *di)
+{
+ u32 tot_blk = 0, j;
+ for (j = 0; j < p->n_wbfs_sec_per_disc; j++)
+ if (wbfs_ntohs( di->wlba_table[j] )) tot_blk++;
+ return tot_blk;
+}
+
+u32 wbfs_sector_used2(wbfs_t *p, wbfs_disc_info_t *di, u32 *last_blk)
+{
+ u32 tot_blk = 0, j;
+ for (j = 0; j < p->n_wbfs_sec_per_disc; j++)
+ if (wbfs_ntohs( di->wlba_table[j] ))
+ {
+ if (last_blk) *last_blk = j;
+ tot_blk++;
+ }
+ return tot_blk;
+}
+
+u32 wbfs_get_disc_info(wbfs_t*p, u32 index, u8 *header, int header_size, u32 *size)//size in 32 bit
+{
+ u32 i, count = 0;
+ if (!p) return 1;
+ int disc_info_sz_lba = p->disc_info_sz >> p->hd_sec_sz_s;
+
+ for (i = 0; i < p->max_disc; i++)
+ if (p->head->disc_table[i])
+ {
+ if (count++ == index)
+ {
+ p->read_hdsector(p->callback_data, p->part_lba + 1 + i * disc_info_sz_lba, 1, p->tmp_buffer);
+ if (header_size > (int) p->hd_sec_sz) header_size = p->hd_sec_sz;
+ u32 magic = wbfs_ntohl( *( u32* )( p->tmp_buffer + 24 ) );
+ if (magic != 0x5D1C9EA3)
+ {
+ p->head->disc_table[i] = 0;
+ return 1;
+ }
+ memcpy(header, p->tmp_buffer, header_size);
+ if (size)
+ {
+ u8 *header = wbfs_ioalloc( p->disc_info_sz );
+ p->read_hdsector(p->callback_data, p->part_lba + 1 + i * disc_info_sz_lba, disc_info_sz_lba, header);
+ u32 sec_used = wbfs_sector_used(p, (wbfs_disc_info_t *) header);
+ wbfs_iofree( header );
+ *size = sec_used << (p->wbfs_sec_sz_s - 2);
+ }
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static void load_freeblocks(wbfs_t*p)
+{
+ if (p->freeblks) return;
+ // XXX should handle malloc error..
+ p->freeblks = wbfs_ioalloc( ALIGN_LBA( p->n_wbfs_sec / 8 ) );
+ p->read_hdsector(p->callback_data, p->part_lba + p->freeblks_lba, ALIGN_LBA( p->n_wbfs_sec / 8 ) >> p->hd_sec_sz_s,
+ p->freeblks);
+
+}
+u32 wbfs_count_usedblocks(wbfs_t*p)
+{
+ u32 i, j, count = 0;
+ load_freeblocks(p);
+ for (i = 0; i < p->n_wbfs_sec / (8 * 4); i++)
+ {
+ u32 v = wbfs_ntohl( p->freeblks[i] );
+ if (v == ~0U)
+ count += 32;
+ else if (v != 0) for (j = 0; j < 32; j++)
+ if (v & (1 << j)) count++;
+ }
+ return count;
+}
+
+// write access
+
+
+//static
+int block_used(u8 *used, u32 i, u32 wblk_sz)
+{
+ u32 k;
+ i *= wblk_sz;
+ for (k = 0; k < wblk_sz; k++)
+ if (i + k < 143432 * 2 && used[i + k]) return 1;
+ return 0;
+}
+
+static u32 alloc_block(wbfs_t*p)
+{
+ u32 i, j;
+ for (i = 0; i < p->n_wbfs_sec / (8 * 4); i++)
+ {
+ u32 v = wbfs_ntohl( p->freeblks[i] );
+ if (v != 0)
+ {
+ for (j = 0; j < 32; j++)
+ if (v & (1 << j))
+ {
+ p->freeblks[i] = wbfs_htonl( v & ~( 1 << j ) );
+ return (i * 32) + j + 1;
+ }
+ }
+ }
+ return ~0;
+}
+static void free_block(wbfs_t *p, int bl)
+{
+ int i = (bl - 1) / (32);
+ int j = (bl - 1) & 31;
+ u32 v = wbfs_ntohl( p->freeblks[i] );
+ p->freeblks[i] = wbfs_htonl( v | 1 << j );
+}
+
+s32 wbfs_add_disc(wbfs_t*p, read_wiidisc_callback_t read_src_wii_disc, void *callback_data,
+ progress_callback_t spinner, partition_selector_t sel, int copy_1_1)
+{
+ int i, discn;
+ u32 tot, cur;
+ u32 wii_sec_per_wbfs_sect = 1 << (p->wbfs_sec_sz_s - p->wii_sec_sz_s);
+ wiidisc_t *d = 0;
+ u8 *used = 0;
+ wbfs_disc_info_t *info = 0;
+ u8* copy_buffer = 0;
+ int retval = -1;
+ int num_wbfs_sect_to_copy;
+ u32 last_used;
+ used = wbfs_malloc( p->n_wii_sec_per_disc );
+
+ if (!used)
+ ERROR( "unable to alloc memory" );
+ // copy_1_1 needs disk usage for layers detection
+ //if(!copy_1_1)
+ {
+ d = wd_open_disc(read_src_wii_disc, callback_data);
+ if (!d)
+ ERROR( "unable to open wii disc" );
+ wd_build_disc_usage(d, sel, used);
+ wd_close_disc(d);
+ d = 0;
+ }
+
+ for (i = 0; i < p->max_disc; i++)// find a free slot.
+ if (p->head->disc_table[i] == 0) break;
+ if (i == p->max_disc)
+ ERROR( "no space left on device (table full)" );
+ p->head->disc_table[i] = 1;
+ discn = i;
+ load_freeblocks(p);
+
+ // build disc info
+ info = wbfs_ioalloc( p->disc_info_sz );
+ read_src_wii_disc(callback_data, 0, 0x100, info->disc_header_copy);
+
+ copy_buffer = wbfs_ioalloc( p->wii_sec_sz );
+ if (!copy_buffer)
+ ERROR( "alloc memory" );
+ tot = 0;
+ cur = 0;
+ num_wbfs_sect_to_copy = p->n_wbfs_sec_per_disc;
+ // count total number of sectors to write
+ last_used = 0;
+ for (i = 0; i < num_wbfs_sect_to_copy; i++)
+ {
+ if (block_used(used, i, wii_sec_per_wbfs_sect))
+ {
+ tot += wii_sec_per_wbfs_sect;
+ last_used = i;
+ }
+ }
+ if (copy_1_1)
+ {
+ // detect single or dual layer
+ if ((last_used + 1) > (p->n_wbfs_sec_per_disc / 2))
+ {
+ // dual layer
+ num_wbfs_sect_to_copy = p->n_wbfs_sec_per_disc;
+ }
+ else
+ {
+ // single layer
+ num_wbfs_sect_to_copy = p->n_wbfs_sec_per_disc / 2;
+ }
+ tot = num_wbfs_sect_to_copy * wii_sec_per_wbfs_sect;
+ }
+ /*
+ // num of hd sectors to copy could be specified directly
+ if (copy_1_1 > 1) {
+ u32 hd_sec_per_wii_sec = p->wii_sec_sz / p->hd_sec_sz;
+ num_wbfs_sect_to_copy = copy_1_1 / hd_sec_per_wii_sec / wii_sec_per_wbfs_sect;
+ tot = num_wbfs_sect_to_copy * wii_sec_per_wbfs_sect;
+ }*/
+ int ret = 0;
+ if (spinner) spinner(0, tot);
+ for (i = 0; i < num_wbfs_sect_to_copy; i++)
+ {
+ u16 bl = 0;
+ if (copy_1_1 || block_used(used, i, wii_sec_per_wbfs_sect))
+ {
+ u16 j;
+
+ bl = alloc_block(p);
+ if (bl == 0xffff)
+ ERROR( "no space left on device (disc full)" );
+ for (j = 0; j < wii_sec_per_wbfs_sect; j++)
+ {
+ u32 offset = (i * (p->wbfs_sec_sz >> 2)) + (j * (p->wii_sec_sz >> 2));
+
+ ret = read_src_wii_disc(callback_data, offset, p->wii_sec_sz, copy_buffer);
+ if (ret)
+ {
+ if (copy_1_1 && i > p->n_wbfs_sec_per_disc / 2)
+ {
+ // end of dual layer data
+ if (j > 0)
+ {
+ info->wlba_table[i] = wbfs_htons( bl );
+ }
+ spinner(tot, tot);
+ break;
+ }
+ //ERROR("read error");
+ printf("\rWARNING: read (%u) error (%d)\n", offset, ret);
+ }
+
+ //fix the partition table
+ if (offset == (0x40000 >> 2)) wd_fix_partition_table(d, sel, copy_buffer);
+ p->write_hdsector(p->callback_data, p->part_lba + bl * (p->wbfs_sec_sz / p->hd_sec_sz) + j
+ * (p->wii_sec_sz / p->hd_sec_sz), p->wii_sec_sz / p->hd_sec_sz, copy_buffer);
+ cur++;
+ if (spinner) spinner(cur, tot);
+ }
+ }
+ if (ret) break;
+ info->wlba_table[i] = wbfs_htons( bl );
+ wbfs_sync(p);
+ }
+ // write disc info
+ int disc_info_sz_lba = p->disc_info_sz >> p->hd_sec_sz_s;
+ p->write_hdsector(p->callback_data, p->part_lba + 1 + discn * disc_info_sz_lba, disc_info_sz_lba, info);
+ wbfs_sync(p);
+ retval = 0;
+ error: if (d) wd_close_disc(d);
+ if (used) wbfs_free( used );
+ if (info) wbfs_iofree( info );
+ if (copy_buffer) wbfs_iofree( copy_buffer );
+ // init with all free blocks
+
+ return retval;
+}
+
+u32 wbfs_rm_disc(wbfs_t*p, u8* discid)
+{
+ wbfs_disc_t *d = wbfs_open_disc(p, discid);
+ int i;
+ int discn = 0;
+ int disc_info_sz_lba = p->disc_info_sz >> p->hd_sec_sz_s;
+ if (!d) return 1;
+ load_freeblocks(p);
+ discn = d->i;
+ for (i = 0; i < p->n_wbfs_sec_per_disc; i++)
+ {
+ u32 iwlba = wbfs_ntohs( d->header->wlba_table[i] );
+ if (iwlba) free_block(p, iwlba);
+ }
+ memset(d->header, 0, p->disc_info_sz);
+ p->write_hdsector(p->callback_data, p->part_lba + 1 + discn * disc_info_sz_lba, disc_info_sz_lba, d->header);
+ p->head->disc_table[discn] = 0;
+ wbfs_close_disc(d);
+ wbfs_sync(p);
+ return 0;
+}
+
+u32 wbfs_ren_disc(wbfs_t*p, u8* discid, u8* newname)
+{
+ wbfs_disc_t *d = wbfs_open_disc(p, discid);
+ int disc_info_sz_lba = p->disc_info_sz >> p->hd_sec_sz_s;
+
+ if (!d) return 1;
+
+ memset(d->header->disc_header_copy + 0x20, 0, 0x40);
+ strncpy((char *) d->header->disc_header_copy + 0x20, (char *) newname, 0x39);
+
+ p->write_hdsector(p->callback_data, p->part_lba + 1 + d->i * disc_info_sz_lba, disc_info_sz_lba, d->header);
+ wbfs_close_disc(d);
+ return 0;
+}
+
+u32 wbfs_rID_disc(wbfs_t*p, u8* discid, u8* newID)
+{
+ wbfs_disc_t *d = wbfs_open_disc(p, discid);
+ int disc_info_sz_lba = p->disc_info_sz >> p->hd_sec_sz_s;
+
+ if (!d) return 1;
+
+ memset(d->header->disc_header_copy, 0, 0x10);
+ strncpy((char *) d->header->disc_header_copy, (char *) newID, 0x9);
+
+ p->write_hdsector(p->callback_data, p->part_lba + 1 + d->i * disc_info_sz_lba, disc_info_sz_lba, d->header);
+ wbfs_close_disc(d);
+ return 0;
+}
+
+// trim the file-system to its minimum size
+u32 wbfs_trim(wbfs_t*p)
+{
+ u32 maxbl;
+ load_freeblocks(p);
+ maxbl = alloc_block(p);
+ p->n_hd_sec = maxbl << (p->wbfs_sec_sz_s - p->hd_sec_sz_s);
+ p->head->n_hd_sec = wbfs_htonl( p->n_hd_sec );
+ // make all block full
+ memset(p->freeblks, 0, p->n_wbfs_sec / 8);
+ wbfs_sync(p);
+ // os layer will truncate the file.
+ return maxbl;
+}
+
+// data extraction
+u32 wbfs_extract_disc(wbfs_disc_t*d, rw_sector_callback_t write_dst_wii_sector, void *callback_data,
+ progress_callback_t spinner)
+{
+ wbfs_t *p = d->p;
+ u8* copy_buffer = 0;
+ int i;
+ int src_wbs_nlb = p->wbfs_sec_sz / p->hd_sec_sz;
+ int dst_wbs_nlb = p->wbfs_sec_sz / p->wii_sec_sz;
+ copy_buffer = wbfs_ioalloc( p->wbfs_sec_sz );
+ if (!copy_buffer)
+ ERROR( "alloc memory" );
+
+ for (i = 0; i < p->n_wbfs_sec_per_disc; i++)
+ {
+ u32 iwlba = wbfs_ntohs( d->header->wlba_table[i] );
+ if (iwlba)
+ {
+
+ if (spinner) spinner(i, p->n_wbfs_sec_per_disc);
+ p->read_hdsector(p->callback_data, p->part_lba + iwlba * src_wbs_nlb, src_wbs_nlb, copy_buffer);
+ write_dst_wii_sector(callback_data, i * dst_wbs_nlb, dst_wbs_nlb, copy_buffer);
+ }
+ }
+ wbfs_iofree( copy_buffer );
+ return 0;
+ error: return 1;
+}
+
+float wbfs_estimate_disc(wbfs_t *p, read_wiidisc_callback_t read_src_wii_disc, void *callback_data,
+ partition_selector_t sel)
+{
+ u8 *b;
+ int i;
+ u32 tot;
+ u32 wii_sec_per_wbfs_sect = 1 << (p->wbfs_sec_sz_s - p->wii_sec_sz_s);
+ wiidisc_t *d = 0;
+ u8 *used = 0;
+ wbfs_disc_info_t *info = 0;
+
+ tot = 0;
+
+ used = wbfs_malloc( p->n_wii_sec_per_disc );
+ if (!used)
+ {
+ ERROR( "unable to alloc memory" );
+ }
+
+ d = wd_open_disc(read_src_wii_disc, callback_data);
+ if (!d)
+ {
+ ERROR( "unable to open wii disc" );
+ }
+
+ wd_build_disc_usage(d, sel, used);
+ wd_close_disc(d);
+ d = 0;
+
+ info = wbfs_ioalloc( p->disc_info_sz );
+ b = (u8 *) info;
+ read_src_wii_disc(callback_data, 0, 0x100, info->disc_header_copy);
+
+ //fprintf(stderr, "estimating %c%c%c%c%c%c %s...\n",b[0], b[1], b[2], b[3], b[4], b[5], b + 0x20);
+
+ for (i = 0; i < p->n_wbfs_sec_per_disc; i++)
+ {
+ if (block_used(used, i, wii_sec_per_wbfs_sect))
+ {
+ tot++;
+ }
+ }
+ //memcpy(header, b,0x100);
+
+ error: if (d) wd_close_disc(d);
+
+ if (used) wbfs_free( used );
+
+ if (info) wbfs_iofree( info );
+
+ return tot * (((p->wbfs_sec_sz * 1.0) / p->hd_sec_sz) * 512);
+}
+u32 wbfs_size_disc(wbfs_t*p, read_wiidisc_callback_t read_src_wii_disc, void *callback_data, partition_selector_t sel,
+ u32 *comp_size, u32 *real_size)
+{
+ int i;
+ u32 tot = 0, last = 0;
+ u32 wii_sec_per_wbfs_sect = 1 << (p->wbfs_sec_sz_s - p->wii_sec_sz_s);
+ wiidisc_t *d = 0;
+ u8 *used = 0;
+ used = wbfs_malloc( p->n_wii_sec_per_disc );
+ if (!used)
+ ERROR( "unable to alloc memory" );
+ d = wd_open_disc(read_src_wii_disc, callback_data);
+ if (!d)
+ ERROR( "unable to open wii disc" );
+ wd_build_disc_usage(d, sel, used);
+ wd_close_disc(d);
+ d = 0;
+
+ // count total number to write for spinner
+ for (i = 0; i < p->n_wbfs_sec_per_disc; i++)
+ {
+ if (block_used(used, i, wii_sec_per_wbfs_sect))
+ {
+ tot += wii_sec_per_wbfs_sect;
+ last = i * wii_sec_per_wbfs_sect;
+ }
+ }
+
+ error: if (d) wd_close_disc(d);
+ if (used) wbfs_free( used );
+
+ *comp_size = tot;
+ *real_size = last;
+
+ return 0;
+}
+
+// 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)
+
+// offset points 32bit words, count counts bytes
+//int (*read_wiidisc_callback_t)(void*fp,u32 offset,u32 count,void*iobuf);
+
+// connect wiidisc to wbfs_disc
+int read_wiidisc_wbfsdisc(void*fp, u32 offset, u32 count, void*iobuf)
+{
+ return wbfs_disc_read((wbfs_disc_t*) fp, offset, count, iobuf);
+}
+
+int wbfs_extract_file(wbfs_disc_t*d, char *path, void **data)
+{
+ wiidisc_t *wd = 0;
+ int ret = 0;
+
+ wd = wd_open_disc(read_wiidisc_wbfsdisc, d);
+ if (!wd)
+ {
+ ERROR( "opening wbfs disc" );
+ return -1;
+ }
+ wd->extracted_size = 0;
+ *data = wd_extract_file(wd, ONLY_GAME_PARTITION, path);
+ ret = wd->extracted_size;
+ if (!*data)
+ {
+ //ERROR("file not found");
+ ret = -1;
+ }
+ wd_close_disc(wd);
+ error: return ret;
+}
+
+int wbfs_get_fragments(wbfs_disc_t *d, _frag_append_t append_fragment, void *callback_data)
+{
+ if (!d) return -1;
+ wbfs_t *p = d->p;
+ int src_wbs_nlb = p->wbfs_sec_sz / p->hd_sec_sz;
+ int i, ret, last = 0;
+ for (i = 0; i < p->n_wbfs_sec_per_disc; i++)
+ {
+ u32 iwlba = wbfs_ntohs( d->header->wlba_table[i] );
+ if (iwlba)
+ {
+ ret = append_fragment(callback_data, i * src_wbs_nlb, // offset
+ p->part_lba + iwlba * src_wbs_nlb, // sector
+ src_wbs_nlb); // count
+ if (ret) return ret; // error
+ last = i;
+ }
+ }
+ if (last < p->n_wbfs_sec_per_disc / 2)
+ {
+ last = p->n_wbfs_sec_per_disc / 2;
+ }
+ u32 size = last * src_wbs_nlb;
+ append_fragment(callback_data, size, 0, 0); // set size
+ return 0;
+}
+
+// wrapper for reading .iso files using wbfs apis
+
+#include
+#include
+
+// offset is pointing 32bit words to address the whole dvd, although len is in bytes
+int wbfs_iso_file_read(wbfs_disc_t*d, u32 offset, u8 *data, u32 len)
+{
+ if (!d || d->p != &wbfs_iso_file) return -1;
+ int fd = (int) d->header;
+ off_t off = ((u64) offset) << 2;
+ off_t ret_off;
+ int ret;
+ ret_off = lseek(fd, off, SEEK_SET);
+ if (ret_off != off) return -1;
+ ret = read(fd, data, len);
+ if (ret != len) return -2;
+ return 0;
+}
+
+u32 wbfs_disc_sector_used(wbfs_disc_t *d, u32 *num_blk)
+{
+ if (d->p == &wbfs_iso_file)
+ {
+ int fd = (int) d->header;
+ struct stat st;
+ if (fstat(fd, &st) == -1) return 0;
+ if (num_blk)
+ {
+ *num_blk = (st.st_size >> 9); // in 512 units
+ }
+ return st.st_blocks; // in 512 units (can be sparse)
+ }
+ u32 last_blk = 0;
+ u32 ret;
+ ret = wbfs_sector_used2(d->p, d->header, &last_blk);
+ if (num_blk)
+ {
+ *num_blk = last_blk + 1;
+ }
+ return ret;
+}
+
diff --git a/source/libs/libwbfs/libwbfs.h b/source/libs/libwbfs/libwbfs.h
index 8921773a..c115e5c0 100644
--- a/source/libs/libwbfs/libwbfs.h
+++ b/source/libs/libwbfs/libwbfs.h
@@ -185,7 +185,7 @@ extern "C"
@sel: selects which partitions to copy.
@copy_1_1: makes a 1:1 copy, whenever a game would not use the wii disc format, and some data is hidden outside the filesystem.
*/
- u32 wbfs_add_disc(wbfs_t*p, read_wiidisc_callback_t read_src_wii_disc, void *callback_data,
+ s32 wbfs_add_disc(wbfs_t*p, read_wiidisc_callback_t read_src_wii_disc, void *callback_data,
progress_callback_t spinner, partition_selector_t sel, int copy_1_1);
/*! remove a wiidvd inside a partition */
diff --git a/source/libs/libwbfs/libwbfs_os.h b/source/libs/libwbfs/libwbfs_os.h
index f7670525..f0931e5e 100644
--- a/source/libs/libwbfs/libwbfs_os.h
+++ b/source/libs/libwbfs/libwbfs_os.h
@@ -1,32 +1,32 @@
-#ifndef LIBWBFS_GLUE_H
-#define LIBWBFS_GLUE_H
-
-#include
-
-#define debug_printf(fmt, ...);
-
-#include
-#define wbfs_fatal(x) do { printf("\nwbfs panic: %s\n\n",x); while(1); } while(0)
-#define wbfs_error(x) do { printf("\nwbfs error: %s\n\n",x); } while(0)
-
-#include
-#include
-
-#define wbfs_malloc(x) malloc(x)
-#define wbfs_free(x) free(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)))
-#define wbfs_ntohl(x) (x)
-#define wbfs_htonl(x) (x)
-#define wbfs_ntohs(x) (x)
-#define wbfs_htons(x) (x)
-
-#include
-
-#define wbfs_memcmp(x,y,z) memcmp(x,y,z)
-#define wbfs_memcpy(x,y,z) memcpy(x,y,z)
-#define wbfs_memset(x,y,z) memset(x,y,z)
-
-#endif
+#ifndef LIBWBFS_GLUE_H
+#define LIBWBFS_GLUE_H
+
+#include
+
+#define debug_printf(fmt, ...);
+
+#include
+#define wbfs_fatal(x) do { printf("\nwbfs panic: %s\n\n",x); return; } while(0)
+#define wbfs_error(x) do { printf("\nwbfs error: %s\n\n",x); } while(0)
+
+#include
+#include
+
+#define wbfs_malloc(x) malloc(x)
+#define wbfs_free(x) free(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)))
+#define wbfs_ntohl(x) (x)
+#define wbfs_htonl(x) (x)
+#define wbfs_ntohs(x) (x)
+#define wbfs_htons(x) (x)
+
+#include
+
+#define wbfs_memcmp(x,y,z) memcmp(x,y,z)
+#define wbfs_memcpy(x,y,z) memcpy(x,y,z)
+#define wbfs_memset(x,y,z) memset(x,y,z)
+
+#endif
diff --git a/source/libwiigui/gui.h b/source/libwiigui/gui.h
index f1e8f74b..196524fc 100644
--- a/source/libwiigui/gui.h
+++ b/source/libwiigui/gui.h
@@ -46,8 +46,15 @@
#include "filelist.h"
#include "input.h"
#include "OptionList.hpp"
+#include "SoundOperations/gui_sound.h"
+#include "SoundOperations/gui_bgm.h"
+//! Frequently used variables
extern FreeTypeGX *fontSystem;
+extern GuiSound *btnSoundClick;
+extern GuiSound *btnSoundClick2;
+extern GuiSound *btnSoundOver;
+extern GuiBGM *bgMusic;
#define SCROLL_INITIAL_DELAY 20
#define SCROLL_LOOP_DELAY 3
@@ -108,70 +115,6 @@ typedef struct _paddata
#define EFFECT_ROCK_VERTICLE 1024
#define EFFECT_GOROUND 2048
-#define MAX_SND_VOICES 16
-
-class GuiSoundDecoder;
-class GuiSound
-{
- public:
- //!Constructor
- //!\param s Pointer to the sound data
- //!\param l Length of sound data
- //!\param v Sound volume (0-100)
- //!\param r RAW PCM Sound, when no decoder is found then try to play as raw-pcm
- //!\param a true--> Pointer to the sound data is allocated with new u8[...]
- //!\ GuiSound will be destroy the buffer if it no more needed
- //!\ false-> sound data buffer has to live just as long as GuiSound
- GuiSound(const u8 *s, int l, int v = 100, bool r = true, bool a = false);
- //!Constructor
- //!\param p Path to the sound data
- //!\param v Sound volume (0-100)
- GuiSound(const char *p, int v = 100);
- //!Load - stop playing and load the new sound data
- //! if load not failed replace the current with new sound data
- //! otherwise the current date will not changed
- //!\params same as by Constructors
- //!\return true ok / false = failed
- bool Load(const u8 *s, int l, bool r = false, bool a = false);
- bool Load(const char *p);
- //!Destructor
- ~GuiSound();
-
- //!Start sound playback
- void Play();
- //!Stop sound playback
- void Stop();
- //!Pause sound playback
- void Pause();
- //!Resume sound playback
- void Resume();
- //!Checks if the sound is currently playing
- //!\return true if sound is playing, false otherwise
- bool IsPlaying();
- //!Set sound volume
- //!\param v Sound volume (0-100)
- void SetVolume(int v);
- //!Set the sound to loop playback (only applies to OGG)
- //!\param l Loop (true to loop)
- void SetLoop(bool l);
- //!Get the playing time in ms for that moment (only applies to OGG)
- protected:
- s32 voice; // used asnd-voice
- u8 *play_buffer[3]; // trpple-playbuffer
- int buffer_nr; // current playbuffer
- int buffer_pos; // current idx to write in buffer
- bool buffer_ready; // buffer is filled and ready
- bool buffer_eof; // no mor datas - will stop playing
- bool loop; // play looped
- s32 volume; // volume
- GuiSoundDecoder *decoder;
-
- void DecoderCallback();
- void PlayerCallback();
- friend void *GuiSoundDecoderThread(void *args);
- friend void GuiSoundPlayerCallback(s32 Voice);
-};
-
//!Menu input trigger management. Determine if action is neccessary based on input data by comparing controller input data to a specific trigger element.
class GuiTrigger
{
diff --git a/source/libwiigui/gui_button.cpp b/source/libwiigui/gui_button.cpp
index 59bccea8..2d4ade53 100644
--- a/source/libwiigui/gui_button.cpp
+++ b/source/libwiigui/gui_button.cpp
@@ -51,10 +51,10 @@ GuiButton::GuiButton(int w, int h)
GuiButton::GuiButton(GuiImage* img, GuiImage* imgOver, int hor, int vert, int x, int y, GuiTrigger* trig,
GuiSound* sndOver, GuiSound* sndClick, u8 grow)
{
- width = img->GetWidth();
- height = img->GetHeight();
+ width = img ? img->GetWidth() : 0;
+ height = img ? img->GetHeight() : 0;
image = img;
- image->SetParent(this);
+ if(image) image->SetParent(this);
imageOver = imgOver;
if (imageOver) imageOver->SetParent(this);
imageHold = NULL;
@@ -97,10 +97,10 @@ GuiButton::GuiButton(GuiImage* img, GuiImage* imgOver, int hor, int vert, int x,
GuiButton::GuiButton(GuiImage* img, GuiImage* imgOver, int hor, int vert, int x, int y, GuiTrigger* trig,
GuiSound* sndOver, GuiSound* sndClick, u8 grow, GuiTooltip* tt, int ttx, int tty, int h_align, int v_align)
{
- width = img->GetWidth();
- height = img->GetHeight();
+ width = img ? img->GetWidth() : 0;
+ height = img ? img->GetHeight() : 0;
image = img;
- image->SetParent(this);
+ if(image) image->SetParent(this);
imageOver = imgOver;
if (imageOver) imageOver->SetParent(this);
imageHold = NULL;
@@ -139,9 +139,12 @@ GuiButton::GuiButton(GuiImage* img, GuiImage* imgOver, int hor, int vert, int x,
}
toolTip = tt;
- toolTip->SetParent(this);
- toolTip->SetAlignment(h_align, v_align);
- toolTip->SetPosition(ttx, tty);
+ if(toolTip)
+ {
+ toolTip->SetParent(this);
+ toolTip->SetAlignment(h_align, v_align);
+ toolTip->SetPosition(ttx, tty);
+ }
time1 = time2 = 0;
}
diff --git a/source/libwiigui/gui_customoptionbrowser.cpp b/source/libwiigui/gui_customoptionbrowser.cpp
index a3542c1e..0527717a 100644
--- a/source/libwiigui/gui_customoptionbrowser.cpp
+++ b/source/libwiigui/gui_customoptionbrowser.cpp
@@ -13,6 +13,7 @@
#include "../settings/CSettings.h"
#include "gui_customoptionbrowser.h"
#include "themes/CTheme.h"
+#include "menu.h"
#include
@@ -26,7 +27,6 @@ GuiCustomOptionBrowser::GuiCustomOptionBrowser(int w, int h, OptionList * l, con
width = w;
height = h;
options = l;
- size = PAGESIZE;
scrollbaron = scrollon;
selectable = true;
listOffset = this->FindMenuItem(-1, 1);
@@ -38,7 +38,6 @@ GuiCustomOptionBrowser::GuiCustomOptionBrowser(int w, int h, OptionList * l, con
trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
trigHeldA = new GuiTrigger;
trigHeldA->SetHeldTrigger(-1, WPAD_BUTTON_A, PAD_BUTTON_A);
- btnSoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, Settings.sfxvolume);
bgOptions = Resources::GetImageData(custombg);
@@ -104,14 +103,7 @@ GuiCustomOptionBrowser::GuiCustomOptionBrowser(int w, int h, OptionList * l, con
scrollbarBoxBtn->SetHoldable(true);
scrollbarBoxBtn->SetTrigger(trigHeldA);
- optionIndex = new int[size];
- optionVal = new GuiText *[size];
- optionValOver = new GuiText *[size];
- optionBtn = new GuiButton *[size];
- optionTxt = new GuiText *[size];
- optionBg = new GuiImage *[size];
-
- for (int i = 0; i < size; i++)
+ for (int i = 0; i < PAGESIZE; i++)
{
optionTxt[i] = new GuiText(options->GetName(i), 20, Theme.settingstext);
optionTxt[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
@@ -170,9 +162,8 @@ GuiCustomOptionBrowser::~GuiCustomOptionBrowser()
delete trigA;
delete trigHeldA;
- delete btnSoundClick;
- for (int i = 0; i < size; i++)
+ for (int i = 0; i < PAGESIZE; i++)
{
delete optionTxt[i];
delete optionVal[i];
@@ -180,20 +171,13 @@ GuiCustomOptionBrowser::~GuiCustomOptionBrowser()
delete optionBg[i];
delete optionBtn[i];
}
- delete[] optionIndex;
- delete[] optionVal;
- delete[] optionValOver;
- delete[] optionBtn;
- delete[] optionTxt;
- delete[] optionBg;
}
void GuiCustomOptionBrowser::SetFocus(int f)
{
- LOCK( this );
focus = f;
- for (int i = 0; i < size; i++)
+ for (int i = 0; i < PAGESIZE; i++)
optionBtn[i]->ResetState();
if (f == 1) optionBtn[selectedItem]->SetState(STATE_SELECTED);
@@ -201,14 +185,13 @@ void GuiCustomOptionBrowser::SetFocus(int f)
void GuiCustomOptionBrowser::ResetState()
{
- LOCK( this );
if (state != STATE_DISABLED)
{
state = STATE_DEFAULT;
stateChan = -1;
}
- for (int i = 0; i < size; i++)
+ for (int i = 0; i < PAGESIZE; i++)
{
optionBtn[i]->ResetState();
}
@@ -217,7 +200,7 @@ void GuiCustomOptionBrowser::ResetState()
int GuiCustomOptionBrowser::GetClickedOption()
{
int found = -1;
- for (int i = 0; i < size; i++)
+ for (int i = 0; i < PAGESIZE; i++)
{
if (optionBtn[i]->GetState() == STATE_CLICKED)
{
@@ -232,7 +215,7 @@ int GuiCustomOptionBrowser::GetClickedOption()
int GuiCustomOptionBrowser::GetSelectedOption()
{
int found = -1;
- for (int i = 0; i < size; i++)
+ for (int i = 0; i < PAGESIZE; i++)
{
if (optionBtn[i]->GetState() == STATE_SELECTED)
{
@@ -245,7 +228,7 @@ int GuiCustomOptionBrowser::GetSelectedOption()
void GuiCustomOptionBrowser::SetClickable(bool enable)
{
- for (int i = 0; i < size; i++)
+ for (int i = 0; i < PAGESIZE; i++)
{
optionBtn[i]->SetClickable(enable);
}
@@ -284,14 +267,13 @@ int GuiCustomOptionBrowser::FindMenuItem(int currentItem, int direction)
*/
void GuiCustomOptionBrowser::Draw()
{
- LOCK( this );
if (!this->IsVisible()) return;
bgOptionsImg->Draw();
int next = listOffset;
- for (int i = 0; i < size; i++)
+ for (int i = 0; i < PAGESIZE; i++)
{
if (next >= 0)
{
@@ -313,12 +295,12 @@ void GuiCustomOptionBrowser::Draw()
void GuiCustomOptionBrowser::UpdateListEntries()
{
- scrollbaron = options->GetLength() > size;
+ scrollbaron = options->GetLength() > PAGESIZE;
if (listOffset < 0) listOffset = this->FindMenuItem(-1, 1);
int next = listOffset;
int maxNameWidth = 0;
- for (int i = 0; i < size; i++)
+ for (int i = 0; i < PAGESIZE; i++)
{
if (next >= 0)
{
@@ -343,7 +325,7 @@ void GuiCustomOptionBrowser::UpdateListEntries()
}
}
if (coL2 < (24 + maxNameWidth + 16)) coL2 = 24 + maxNameWidth + 16;
- for (int i = 0; i < size; i++)
+ for (int i = 0; i < PAGESIZE; i++)
{
if (optionBtn[i]->GetState() != STATE_DISABLED)
{
@@ -358,7 +340,6 @@ void GuiCustomOptionBrowser::UpdateListEntries()
void GuiCustomOptionBrowser::Update(GuiTrigger * t)
{
- LOCK( this );
int next, prev, lang = options->GetLength();
if (state == STATE_DISABLED || !t) return;
@@ -384,7 +365,7 @@ void GuiCustomOptionBrowser::Update(GuiTrigger * t)
if (buttonshold != WPAD_BUTTON_UP && buttonshold != WPAD_BUTTON_DOWN)
{
- for (int i = 0; i < size; i++)
+ for (int i = 0; i < PAGESIZE; i++)
{
if (next >= 0) next = this->FindMenuItem(next, 1);
@@ -418,7 +399,7 @@ void GuiCustomOptionBrowser::Update(GuiTrigger * t)
if (next >= 0)
{
- if (selectedItem == size - 1)
+ if (selectedItem == PAGESIZE - 1)
{
// move list down by 1
listOffset = this->FindMenuItem(listOffset, 1);
@@ -460,7 +441,7 @@ void GuiCustomOptionBrowser::Update(GuiTrigger * t)
if (next >= 0)
{
- if (selectedItem == size - 1)
+ if (selectedItem == PAGESIZE - 1)
{
// move list down by 1
listOffset = this->FindMenuItem(listOffset, 1);
@@ -506,7 +487,7 @@ void GuiCustomOptionBrowser::Update(GuiTrigger * t)
}
if (scrollbarBoxBtn->GetState() == STATE_HELD && scrollbarBoxBtn->GetStateChan() == t->chan && t->wpad.ir.valid
- && options->GetLength() > size)
+ && options->GetLength() > PAGESIZE)
{
scrollbarBoxBtn->SetPosition(width / 2 - 18 + 7, 0);
@@ -519,10 +500,10 @@ void GuiCustomOptionBrowser::Update(GuiTrigger * t)
listOffset = 0;
selectedItem = 0;
}
- else if (listOffset + size >= lang)
+ else if (listOffset + PAGESIZE >= lang)
{
- listOffset = lang - size;
- selectedItem = size - 1;
+ listOffset = lang - PAGESIZE;
+ selectedItem = PAGESIZE - 1;
}
}
int positionbar = 237 * (listOffset + selectedItem) / lang;
@@ -532,17 +513,17 @@ void GuiCustomOptionBrowser::Update(GuiTrigger * t)
if (t->Right())
{
- if (listOffset < lang && lang > size)
+ if (listOffset < lang && lang > PAGESIZE)
{
- listOffset = listOffset + size;
- if (listOffset + size >= lang) listOffset = lang - size;
+ listOffset = listOffset + PAGESIZE;
+ if (listOffset + PAGESIZE >= lang) listOffset = lang - PAGESIZE;
}
}
else if (t->Left())
{
if (listOffset > 0)
{
- listOffset = listOffset - size;
+ listOffset = listOffset - PAGESIZE;
if (listOffset < 0) listOffset = 0;
}
}
diff --git a/source/libwiigui/gui_customoptionbrowser.h b/source/libwiigui/gui_customoptionbrowser.h
index f5bd304b..f6064d94 100644
--- a/source/libwiigui/gui_customoptionbrowser.h
+++ b/source/libwiigui/gui_customoptionbrowser.h
@@ -1,4 +1,8 @@
+#ifndef GUI_CUSTOMBROWSER_H_
+#define GUI_CUSTOMBROWSER_H_
+
#include "gui.h"
+#include
//!Display a list of menu options
class GuiCustomOptionBrowser: public GuiElement
@@ -20,17 +24,16 @@ class GuiCustomOptionBrowser: public GuiElement
void UpdateListEntries();
int selectedItem;
int listOffset;
- int size;
int coL2;
int scrollbaron;
OptionList * options;
- int * optionIndex;
- GuiButton ** optionBtn;
- GuiText ** optionTxt;
- GuiText ** optionVal;
- GuiText ** optionValOver;
- GuiImage ** optionBg;
+ int optionIndex[PAGESIZE];
+ GuiButton * optionBtn[PAGESIZE];
+ GuiText * optionTxt[PAGESIZE];
+ GuiText * optionVal[PAGESIZE];
+ GuiText * optionValOver[PAGESIZE];
+ GuiImage * optionBg[PAGESIZE];
GuiButton * arrowUpBtn;
GuiButton * arrowDownBtn;
@@ -55,7 +58,8 @@ class GuiCustomOptionBrowser: public GuiElement
GuiImageData * scrollbarBox;
GuiImageData * scrollbarBoxOver;
- GuiSound * btnSoundClick;
GuiTrigger * trigA;
GuiTrigger * trigHeldA;
};
+
+#endif
diff --git a/source/libwiigui/gui_filebrowser.cpp b/source/libwiigui/gui_filebrowser.cpp
index 1e71fbdc..d2a5e07c 100644
--- a/source/libwiigui/gui_filebrowser.cpp
+++ b/source/libwiigui/gui_filebrowser.cpp
@@ -32,18 +32,15 @@ GuiFileBrowser::GuiFileBrowser(int w, int h)
trigHeldA = new GuiTrigger;
trigHeldA->SetHeldTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
- btnSoundOver = new GuiSound(button_over_pcm, button_over_pcm_size, Settings.sfxvolume);
- btnSoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, Settings.sfxvolume);
-
bgFileSelection = new GuiImageData(Resources::GetFile("bg_browser.png"), Resources::GetFileSize("bg_browser.png"));
bgFileSelectionImg = new GuiImage(bgFileSelection);
bgFileSelectionImg->SetParent(this);
bgFileSelectionImg->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
bgFileSelectionEntry = Resources::GetImageData("bg_browser_selection.png");
-
+
fileFolder = Resources::GetImageData("icon_folder.png");
-
+
scrollbar = Resources::GetImageData("scrollbar.png");
scrollbarImg = new GuiImage(scrollbar);
scrollbarImg->SetParent(this);
@@ -160,8 +157,6 @@ GuiFileBrowser::~GuiFileBrowser()
delete arrowUp;
delete scrollbarBox;
- delete btnSoundOver;
- delete btnSoundClick;
delete trigHeldA;
delete trigA;
diff --git a/source/libwiigui/gui_gamebrowser.cpp b/source/libwiigui/gui_gamebrowser.cpp
index 9ab6c889..f6320859 100644
--- a/source/libwiigui/gui_gamebrowser.cpp
+++ b/source/libwiigui/gui_gamebrowser.cpp
@@ -17,6 +17,7 @@
#include "settings/GameTitles.h"
#include "usbloader/GameList.h"
#include "themes/CTheme.h"
+#include "menu.h"
#include
#include
@@ -41,7 +42,6 @@ GuiGameBrowser::GuiGameBrowser(int w, int h, int selected, int offset)
trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
trigHeldA = new GuiTrigger;
trigHeldA->SetHeldTrigger(-1, WPAD_BUTTON_A, PAD_BUTTON_A);
- btnSoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, Settings.sfxvolume);
bgGames = Resources::GetImageData("bg_options.png");
newGames = Resources::GetImageData("new.png");
@@ -182,7 +182,6 @@ GuiGameBrowser::~GuiGameBrowser()
delete trigA;
delete trigHeldA;
- delete btnSoundClick;
for (int i = 0; i < pagesize; i++)
{
diff --git a/source/libwiigui/gui_gamebrowser.h b/source/libwiigui/gui_gamebrowser.h
index c8370dc9..3918f239 100644
--- a/source/libwiigui/gui_gamebrowser.h
+++ b/source/libwiigui/gui_gamebrowser.h
@@ -1,65 +1,64 @@
-#ifndef _GUIGAMEBROWSER_H_
-#define _GUIGAMEBROWSER_H_
-
-#include "gui.h"
-#include "../usbloader/disc.h"
-
-class GuiGameBrowser: public GuiElement
-{
- public:
- GuiGameBrowser(int w, int h, int selected = 0, int offset = 0);
- ~GuiGameBrowser();
- int FindMenuItem(int c, int d);
- int GetClickedOption();
- int GetSelectedOption();
- void ResetState();
- void SetFocus(int f);
- void Draw();
- void Update(GuiTrigger * t);
- int GetOffset();
- void Reload();
- //GuiText * optionVal[PAGESIZE];
- protected:
- void UpdateListEntries();
- int selectedItem;
- int listOffset;
- int scrollbaron;
- int pagesize;
- int maxTextWidth;
-
- int * gameIndex;
- GuiButton ** game;
- GuiText ** gameTxt;
- GuiText ** gameTxtOver;
- GuiImage ** gameBg;
- GuiImage ** newImg;
-
- GuiButton * arrowUpBtn;
- GuiButton * arrowDownBtn;
- GuiButton * scrollbarBoxBtn;
-
- GuiImage * bgGameImg;
- GuiImage * scrollbarImg;
- GuiImage * arrowDownImg;
- GuiImage * arrowDownOverImg;
- GuiImage * arrowUpImg;
- GuiImage * arrowUpOverImg;
- GuiImage * scrollbarBoxImg;
- GuiImage * scrollbarBoxOverImg;
-
- GuiImageData * bgGames;
- GuiImageData * bgGamesEntry;
- GuiImageData * newGames;
- GuiImageData * scrollbar;
- GuiImageData * arrowDown;
- GuiImageData * arrowDownOver;
- GuiImageData * arrowUp;
- GuiImageData * arrowUpOver;
- GuiImageData * scrollbarBox;
- GuiImageData * scrollbarBoxOver;
-
- GuiSound * btnSoundClick;
- GuiTrigger * trigA;
- GuiTrigger * trigHeldA;
-};
-#endif
+#ifndef _GUIGAMEBROWSER_H_
+#define _GUIGAMEBROWSER_H_
+
+#include "gui.h"
+#include "../usbloader/disc.h"
+
+class GuiGameBrowser: public GuiElement
+{
+ public:
+ GuiGameBrowser(int w, int h, int selected = 0, int offset = 0);
+ ~GuiGameBrowser();
+ int FindMenuItem(int c, int d);
+ int GetClickedOption();
+ int GetSelectedOption();
+ void ResetState();
+ void SetFocus(int f);
+ void Draw();
+ void Update(GuiTrigger * t);
+ int GetOffset();
+ void Reload();
+ //GuiText * optionVal[PAGESIZE];
+ protected:
+ void UpdateListEntries();
+ int selectedItem;
+ int listOffset;
+ int scrollbaron;
+ int pagesize;
+ int maxTextWidth;
+
+ int * gameIndex;
+ GuiButton ** game;
+ GuiText ** gameTxt;
+ GuiText ** gameTxtOver;
+ GuiImage ** gameBg;
+ GuiImage ** newImg;
+
+ GuiButton * arrowUpBtn;
+ GuiButton * arrowDownBtn;
+ GuiButton * scrollbarBoxBtn;
+
+ GuiImage * bgGameImg;
+ GuiImage * scrollbarImg;
+ GuiImage * arrowDownImg;
+ GuiImage * arrowDownOverImg;
+ GuiImage * arrowUpImg;
+ GuiImage * arrowUpOverImg;
+ GuiImage * scrollbarBoxImg;
+ GuiImage * scrollbarBoxOverImg;
+
+ GuiImageData * bgGames;
+ GuiImageData * bgGamesEntry;
+ GuiImageData * newGames;
+ GuiImageData * scrollbar;
+ GuiImageData * arrowDown;
+ GuiImageData * arrowDownOver;
+ GuiImageData * arrowUp;
+ GuiImageData * arrowUpOver;
+ GuiImageData * scrollbarBox;
+ GuiImageData * scrollbarBoxOver;
+
+ GuiTrigger * trigA;
+ GuiTrigger * trigHeldA;
+};
+#endif
diff --git a/source/libwiigui/gui_gamecarousel.cpp b/source/libwiigui/gui_gamecarousel.cpp
index d333fa2f..2c2db0cc 100644
--- a/source/libwiigui/gui_gamecarousel.cpp
+++ b/source/libwiigui/gui_gamecarousel.cpp
@@ -70,9 +70,6 @@ GuiGameCarousel::GuiGameCarousel(int w, int h, const char *themePath, const u8 *
trigMinus = new GuiTrigger;
trigMinus->SetButtonOnlyTrigger(-1, WPAD_BUTTON_MINUS | WPAD_CLASSIC_BUTTON_MINUS, 0);
- btnSoundClick = new GuiSound(button_click2_pcm, button_click2_pcm_size, Settings.sfxvolume);
- btnSoundOver = new GuiSound(button_over_pcm, button_over_pcm_size, Settings.sfxvolume);
-
imgLeft = Resources::GetImageData("startgame_arrow_left.png");
imgRight = Resources::GetImageData("startgame_arrow_right.png");
@@ -164,8 +161,6 @@ GuiGameCarousel::~GuiGameCarousel()
delete trigR;
delete trigPlus;
delete trigMinus;
- delete btnSoundClick;
- delete btnSoundOver;
delete gamename;
for (int i = 0; i < pagesize; i++)
diff --git a/source/libwiigui/gui_gamecarousel.h b/source/libwiigui/gui_gamecarousel.h
index bd8db075..ae654ac5 100644
--- a/source/libwiigui/gui_gamecarousel.h
+++ b/source/libwiigui/gui_gamecarousel.h
@@ -1,54 +1,52 @@
-#ifndef _GUIGAMECAROUSEL_H_
-#define _GUIGAMECAROUSEL_H_
-
-#include "gui.h"
-#include "../usbloader/disc.h"
-class GuiImageAsync;
-class GuiGameCarousel: public GuiElement
-{
- public:
- GuiGameCarousel(int w, int h, const char *themePath, const u8 *imagebg, int imagebgsize, int selected = 0, int offset = 0);
- ~GuiGameCarousel();
- int FindMenuItem(int c, int d);
- int GetClickedOption();
- int GetSelectedOption();
- void ResetState();
- void SetFocus(int f);
- void Draw();
- void Update(GuiTrigger * t);
- int GetOffset();
- void Reload();
- //GuiText * optionVal[PAGESIZE];
- protected:
- GuiImageData noCover;
- int selectedItem;
- int listOffset;
- int scrollbaron;
- int pagesize;
- int speed;
- int clickedItem;
-
- int * gameIndex;
- GuiButton ** game;
- GuiImageAsync ** coverImg;
-
- GuiText * gamename;
-
- GuiButton * btnRight;
- GuiButton * btnLeft;
-
- GuiImage * btnLeftImg;
- GuiImage * btnRightImg;
-
- GuiImageData * imgLeft;
- GuiImageData * imgRight;
-
- GuiSound * btnSoundOver;
- GuiSound * btnSoundClick;
- GuiTrigger * trigA;
- GuiTrigger * trigL;
- GuiTrigger * trigR;
- GuiTrigger * trigPlus;
- GuiTrigger * trigMinus;
-};
-#endif
+#ifndef _GUIGAMECAROUSEL_H_
+#define _GUIGAMECAROUSEL_H_
+
+#include "gui.h"
+#include "../usbloader/disc.h"
+class GuiImageAsync;
+class GuiGameCarousel: public GuiElement
+{
+ public:
+ GuiGameCarousel(int w, int h, const char *themePath, const u8 *imagebg, int imagebgsize, int selected = 0, int offset = 0);
+ ~GuiGameCarousel();
+ int FindMenuItem(int c, int d);
+ int GetClickedOption();
+ int GetSelectedOption();
+ void ResetState();
+ void SetFocus(int f);
+ void Draw();
+ void Update(GuiTrigger * t);
+ int GetOffset();
+ void Reload();
+ //GuiText * optionVal[PAGESIZE];
+ protected:
+ GuiImageData noCover;
+ int selectedItem;
+ int listOffset;
+ int scrollbaron;
+ int pagesize;
+ int speed;
+ int clickedItem;
+
+ int * gameIndex;
+ GuiButton ** game;
+ GuiImageAsync ** coverImg;
+
+ GuiText * gamename;
+
+ GuiButton * btnRight;
+ GuiButton * btnLeft;
+
+ GuiImage * btnLeftImg;
+ GuiImage * btnRightImg;
+
+ GuiImageData * imgLeft;
+ GuiImageData * imgRight;
+
+ GuiTrigger * trigA;
+ GuiTrigger * trigL;
+ GuiTrigger * trigR;
+ GuiTrigger * trigPlus;
+ GuiTrigger * trigMinus;
+};
+#endif
diff --git a/source/libwiigui/gui_gamegrid.cpp b/source/libwiigui/gui_gamegrid.cpp
index bf04ef8d..c4c33f2c 100644
--- a/source/libwiigui/gui_gamegrid.cpp
+++ b/source/libwiigui/gui_gamegrid.cpp
@@ -238,9 +238,6 @@ GuiGameGrid::GuiGameGrid(int w, int h, const char *themePath, const u8 *imagebg,
trigMinus = new GuiTrigger;
trigMinus->SetButtonOnlyTrigger(-1, WPAD_BUTTON_MINUS | WPAD_CLASSIC_BUTTON_MINUS, 0);
- btnSoundClick = new GuiSound(button_click2_pcm, button_click2_pcm_size, Settings.sfxvolume);
- btnSoundOver = new GuiSound(button_over_pcm, button_over_pcm_size, Settings.sfxvolume);
-
int btnHeight = (int) lround(sqrt(RADIUS * RADIUS - 90000) - RADIUS - 50);
// Button Left
@@ -303,8 +300,6 @@ GuiGameGrid::~GuiGameGrid()
delete trigMinus;
delete trig1;
delete trig2;
- delete btnSoundClick;
- delete btnSoundOver;
for (int i = pagesize - 1; i >= 0; i--)
{
diff --git a/source/libwiigui/gui_gamegrid.h b/source/libwiigui/gui_gamegrid.h
index 0dd739df..86a0cc9b 100644
--- a/source/libwiigui/gui_gamegrid.h
+++ b/source/libwiigui/gui_gamegrid.h
@@ -45,8 +45,6 @@ class GuiGameGrid: public GuiElement
GuiImageData * imgLeft;
GuiImageData * imgRight;
- GuiSound * btnSoundOver;
- GuiSound * btnSoundClick;
GuiTrigger * trigA;
GuiTrigger * trigL;
GuiTrigger * trigR;
diff --git a/source/libwiigui/gui_keyboard.cpp b/source/libwiigui/gui_keyboard.cpp
index 59ced7df..ce4e80c1 100644
--- a/source/libwiigui/gui_keyboard.cpp
+++ b/source/libwiigui/gui_keyboard.cpp
@@ -13,6 +13,7 @@
#include "../settings/CSettings.h"
#include
#include
+#include "menu.h"
/**
* Constructor for the GuiKeyboard class.
*/
@@ -136,8 +137,6 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max, int min, int lang)
keyLarge = new GuiImageData(keyboard_largekey_over_png, keyboard_largekey_over_png_size);
keyLargeOver = new GuiImageData(keyboard_largekey_over_png, keyboard_largekey_over_png_size);
- keySoundOver = new GuiSound(button_over_pcm, button_over_pcm_size, Settings.sfxvolume);
- keySoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, Settings.sfxvolume);
trigA = new GuiTrigger;
trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
trigB = new GuiTrigger;
@@ -161,11 +160,9 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max, int min, int lang)
keyBackText = new GuiText("Back", 20, ( GXColor )
{ 0, 0, 0, 0xff});
}
- //GuiButton(GuiImage* img, GuiImage* imgOver, int hor, int vert, int x, int y, GuiTrigger* trig, GuiSound* sndOver, GuiSound* sndClick, u8 grow);
-
//keyBack = new GuiButton(keyMedium->GetWidth(), keyMedium->GetHeight());
keyBack = new GuiButton(keyBackImg, keyBackOverImg, 0, 3, 11 * 42 + 40 + eurocheck, 0 * 42 + 120, trigA,
- keySoundOver, keySoundClick, 1);
+ btnSoundOver, btnSoundClick, 1);
//keyBack->SetImage(keyBackImg);
//keyBack->SetImageOver(keyBackOverImg);
keyBack->SetLabel(keyBackText);
@@ -366,8 +363,6 @@ GuiKeyboard::~GuiKeyboard()
delete keyMediumOver;
delete keyLarge;
delete keyLargeOver;
- delete keySoundOver;
- delete keySoundClick;
delete trigA;
delete trigB;
diff --git a/source/libwiigui/gui_numpad.cpp b/source/libwiigui/gui_numpad.cpp
index 83dbd9db..a6596376 100644
--- a/source/libwiigui/gui_numpad.cpp
+++ b/source/libwiigui/gui_numpad.cpp
@@ -1,205 +1,201 @@
-/****************************************************************************
- * USB Loader GX
- *
- * r-win 2009
- *
- * gui_numpad.cpp
- *
- * GUI class definitions
- ***************************************************************************/
-
-#include "gui.h"
-#include "../main.h"
-#include "../settings/CSettings.h"
-#include
-#include
-/**
- * Constructor for the GuiNumpad class.
- */
-
-#define SAFEFREE(p) if(p){free(p);p=NULL;}
-
-GuiNumpad::GuiNumpad(char * t, u32 max)
-{
- width = 400;
- height = 370;
- selectable = true;
- focus = 0; // allow focus
- alignmentHor = ALIGN_CENTRE;
- alignmentVert = ALIGN_MIDDLE;
- kbtextmaxlen = max > sizeof(kbtextstr) ? sizeof(kbtextstr) : max; // limit max up to sizeof(kbtextstr)
- // strlcpy(kbtextstr, t, kbtextmaxlen);
- strncpy(kbtextstr, t, kbtextmaxlen); // strncpy is needed to fill the rest with \0
- kbtextstr[sizeof(kbtextstr) - 1] = 0; // terminate with \0
-
- char thekeys[11] = { '1', '2', '3', '4', '5', '6', '7', '8', '9', '\0', '0' };
- memcpy(keys, thekeys, sizeof(thekeys));
-
- keyTextbox = new GuiImageData(keyboard_textbox_png, keyboard_textbox_png_size);
- keyTextboxImg = new GuiImage(keyTextbox);
- keyTextboxImg->SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
- keyTextboxImg->SetPosition(0, 40);//(0,0);
- this->Append(keyTextboxImg);
-
- kbText = new GuiText(kbtextstr, 20, ( GXColor )
- { 0, 0, 0, 0xff});
- kbText->SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
- kbText->SetPosition(0, 53);//(0, 13);
- kbText->SetPassChar('*');
- this->Append(kbText);
-
- keyMedium = new GuiImageData(keyboard_mediumkey_over_png, keyboard_mediumkey_over_png_size);
- keyMediumOver = new GuiImageData(keyboard_mediumkey_over_png, keyboard_mediumkey_over_png_size);
-
- keySoundOver = new GuiSound(button_over_pcm, button_over_pcm_size, Settings.sfxvolume);
- keySoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, Settings.sfxvolume);
- trigA = new GuiTrigger;
- trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
- trigB = new GuiTrigger;
- trigB->SetButtonOnlyTrigger(-1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B);
-
- keyBackImg = new GuiImage(keyMedium);
- keyBackOverImg = new GuiImage(keyMediumOver);
- keyBackText = new GuiText("Back", 20, ( GXColor )
- { 0, 0, 0, 0xff});
-
- keyBack = new GuiButton(keyBackImg, keyBackOverImg, ALIGN_CENTRE, ALIGN_MIDDLE, 90, 80, trigA, keySoundOver,
- keySoundClick, 1);
- keyBack->SetLabel(keyBackText);
- keyBack->SetTrigger(trigB);
- this->Append(keyBack);
-
- keyClearImg = new GuiImage(keyMedium);
- keyClearOverImg = new GuiImage(keyMediumOver);
- keyClearText = new GuiText("Clear", 20, ( GXColor )
- { 0, 0, 0, 0xff});
- keyClear = new GuiButton(keyClearImg, keyClearOverImg, ALIGN_CENTRE, ALIGN_MIDDLE, -90, 80, trigA, keySoundOver,
- keySoundClick, 1);
- keyClear->SetLabel(keyClearText);
- this->Append(keyClear);
-
- char txt[2] = { 0, 0 };
- for (int i = 0; i < 11; i++)
- {
- if (keys[i] != '\0')
- {
- int col = i % 3;
- int row = i / 3;
-
- keyImg[i] = new GuiImage(keyMedium);
- keyImgOver[i] = new GuiImage(keyMediumOver);
- txt[0] = keys[i];
- keyTxt[i] = new GuiText(txt, 20, ( GXColor )
- { 0, 0, 0, 0xff});
- keyTxt[i]->SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM);
- keyTxt[i]->SetPosition(0, -10);
- keyBtn[i] = new GuiButton(keyImg[i], keyImgOver[i], ALIGN_CENTRE, ALIGN_MIDDLE, -90 + 90 * col, -70 + 50
- * row, trigA, keySoundOver, keySoundClick, 1);
- keyBtn[i]->SetLabel(keyTxt[i]);
-
- this->Append(keyBtn[i]);
- }
- }
-}
-
-/**
- * Destructor for the GuiKeyboard class.
- */
-GuiNumpad::~GuiNumpad()
-{
- SAFEFREE( kbText )
- SAFEFREE( keyTextbox )
- SAFEFREE( keyTextboxImg )
- SAFEFREE( keyBackText )
- SAFEFREE( keyBackImg )
- SAFEFREE( keyBackOverImg )
- SAFEFREE( keyBack )
- SAFEFREE( keyClear )
- SAFEFREE( keyClearImg )
- SAFEFREE( keyClearOverImg )
- SAFEFREE( keyClearText )
- SAFEFREE( keyMedium )
- SAFEFREE( keyMediumOver )
- SAFEFREE( keySoundOver )
- SAFEFREE( keySoundClick )
- SAFEFREE( trigA )
- SAFEFREE( trigB )
-
- for (int i = 0; i < 11; i++)
- {
- if (keys[i] != '\0')
- {
- SAFEFREE( keyImg[i] )
- SAFEFREE( keyImgOver[i] )
- SAFEFREE( keyTxt[i] )
- SAFEFREE( keyBtn[i] )
- }
- }
-}
-
-void GuiNumpad::Update(GuiTrigger * t)
-{
- LOCK( this );
- if (_elements.size() == 0 || (state == STATE_DISABLED && parentElement)) return;
-
- for (u8 i = 0; i < _elements.size(); i++)
- {
- try
- {
- _elements.at(i)->Update(t);
- }
- catch (const std::exception& e)
- {
- }
- }
-
- if (keyBack->GetState() == STATE_CLICKED)
- {
- if (strlen(kbtextstr) > 0)
- {
- kbtextstr[strlen(kbtextstr) - 1] = 0;
- kbText->SetText(kbtextstr);
- }
- keyBack->SetState(STATE_SELECTED, t->chan);
- }
- else if (keyClear->GetState() == STATE_CLICKED)
- {
- memset(kbtextstr, 0, sizeof(kbtextstr));
- kbText->SetText(kbtextstr);
- keyClear->SetState(STATE_SELECTED, t->chan);
- }
-
- char txt[2] = { 0, 0 };
- for (int i = 0; i < 11; i++)
- {
- if (keys[i] != '\0')
- {
- if (keyBtn[i]->GetState() == STATE_CLICKED)
- {
- txt[0] = keys[i];
- if (strlen(kbtextstr) < kbtextmaxlen - 1) // -1 --> kbtextmaxlen means with term. '\0'
- {
- kbtextstr[strlen(kbtextstr)] = txt[0];
- kbText->SetText(kbtextstr);
- }
- keyBtn[i]->SetState(STATE_SELECTED, t->chan);
- }
- }
- }
-
- kbText->SetPosition(0, 53);
-
- this->ToggleFocus(t);
-
- if (focus) // only send actions to this window if it's in focus
- {
- // pad/joystick navigation
- if (t->Right())
- this->MoveSelectionHor(1);
- else if (t->Left())
- this->MoveSelectionHor(-1);
- else if (t->Down())
- this->MoveSelectionVert(1);
- else if (t->Up()) this->MoveSelectionVert(-1);
- }
-}
+/****************************************************************************
+ * USB Loader GX
+ *
+ * r-win 2009
+ *
+ * gui_numpad.cpp
+ *
+ * GUI class definitions
+ ***************************************************************************/
+
+#include "gui.h"
+#include "../main.h"
+#include "../settings/CSettings.h"
+#include
+#include
+/**
+ * Constructor for the GuiNumpad class.
+ */
+
+#define SAFEFREE(p) if(p){free(p);p=NULL;}
+
+GuiNumpad::GuiNumpad(char * t, u32 max)
+{
+ width = 400;
+ height = 370;
+ selectable = true;
+ focus = 0; // allow focus
+ alignmentHor = ALIGN_CENTRE;
+ alignmentVert = ALIGN_MIDDLE;
+ kbtextmaxlen = max > sizeof(kbtextstr) ? sizeof(kbtextstr) : max; // limit max up to sizeof(kbtextstr)
+ // strlcpy(kbtextstr, t, kbtextmaxlen);
+ strncpy(kbtextstr, t, kbtextmaxlen); // strncpy is needed to fill the rest with \0
+ kbtextstr[sizeof(kbtextstr) - 1] = 0; // terminate with \0
+
+ char thekeys[11] = { '1', '2', '3', '4', '5', '6', '7', '8', '9', '\0', '0' };
+ memcpy(keys, thekeys, sizeof(thekeys));
+
+ keyTextbox = new GuiImageData(keyboard_textbox_png, keyboard_textbox_png_size);
+ keyTextboxImg = new GuiImage(keyTextbox);
+ keyTextboxImg->SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
+ keyTextboxImg->SetPosition(0, 40);//(0,0);
+ this->Append(keyTextboxImg);
+
+ kbText = new GuiText(kbtextstr, 20, ( GXColor )
+ { 0, 0, 0, 0xff});
+ kbText->SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
+ kbText->SetPosition(0, 53);//(0, 13);
+ kbText->SetPassChar('*');
+ this->Append(kbText);
+
+ keyMedium = new GuiImageData(keyboard_mediumkey_over_png, keyboard_mediumkey_over_png_size);
+ keyMediumOver = new GuiImageData(keyboard_mediumkey_over_png, keyboard_mediumkey_over_png_size);
+
+ trigA = new GuiTrigger;
+ trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
+ trigB = new GuiTrigger;
+ trigB->SetButtonOnlyTrigger(-1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B);
+
+ keyBackImg = new GuiImage(keyMedium);
+ keyBackOverImg = new GuiImage(keyMediumOver);
+ keyBackText = new GuiText("Back", 20, ( GXColor )
+ { 0, 0, 0, 0xff});
+
+ keyBack = new GuiButton(keyBackImg, keyBackOverImg, ALIGN_CENTRE, ALIGN_MIDDLE, 90, 80, trigA, keySoundOver,
+ keySoundClick, 1);
+ keyBack->SetLabel(keyBackText);
+ keyBack->SetTrigger(trigB);
+ this->Append(keyBack);
+
+ keyClearImg = new GuiImage(keyMedium);
+ keyClearOverImg = new GuiImage(keyMediumOver);
+ keyClearText = new GuiText("Clear", 20, ( GXColor )
+ { 0, 0, 0, 0xff});
+ keyClear = new GuiButton(keyClearImg, keyClearOverImg, ALIGN_CENTRE, ALIGN_MIDDLE, -90, 80, trigA, keySoundOver,
+ keySoundClick, 1);
+ keyClear->SetLabel(keyClearText);
+ this->Append(keyClear);
+
+ char txt[2] = { 0, 0 };
+ for (int i = 0; i < 11; i++)
+ {
+ if (keys[i] != '\0')
+ {
+ int col = i % 3;
+ int row = i / 3;
+
+ keyImg[i] = new GuiImage(keyMedium);
+ keyImgOver[i] = new GuiImage(keyMediumOver);
+ txt[0] = keys[i];
+ keyTxt[i] = new GuiText(txt, 20, ( GXColor )
+ { 0, 0, 0, 0xff});
+ keyTxt[i]->SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM);
+ keyTxt[i]->SetPosition(0, -10);
+ keyBtn[i] = new GuiButton(keyImg[i], keyImgOver[i], ALIGN_CENTRE, ALIGN_MIDDLE, -90 + 90 * col, -70 + 50
+ * row, trigA, keySoundOver, keySoundClick, 1);
+ keyBtn[i]->SetLabel(keyTxt[i]);
+
+ this->Append(keyBtn[i]);
+ }
+ }
+}
+
+/**
+ * Destructor for the GuiKeyboard class.
+ */
+GuiNumpad::~GuiNumpad()
+{
+ SAFEFREE( kbText )
+ SAFEFREE( keyTextbox )
+ SAFEFREE( keyTextboxImg )
+ SAFEFREE( keyBackText )
+ SAFEFREE( keyBackImg )
+ SAFEFREE( keyBackOverImg )
+ SAFEFREE( keyBack )
+ SAFEFREE( keyClear )
+ SAFEFREE( keyClearImg )
+ SAFEFREE( keyClearOverImg )
+ SAFEFREE( keyClearText )
+ SAFEFREE( keyMedium )
+ SAFEFREE( keyMediumOver )
+ SAFEFREE( trigA )
+ SAFEFREE( trigB )
+
+ for (int i = 0; i < 11; i++)
+ {
+ if (keys[i] != '\0')
+ {
+ SAFEFREE( keyImg[i] )
+ SAFEFREE( keyImgOver[i] )
+ SAFEFREE( keyTxt[i] )
+ SAFEFREE( keyBtn[i] )
+ }
+ }
+}
+
+void GuiNumpad::Update(GuiTrigger * t)
+{
+ LOCK( this );
+ if (_elements.size() == 0 || (state == STATE_DISABLED && parentElement)) return;
+
+ for (u8 i = 0; i < _elements.size(); i++)
+ {
+ try
+ {
+ _elements.at(i)->Update(t);
+ }
+ catch (const std::exception& e)
+ {
+ }
+ }
+
+ if (keyBack->GetState() == STATE_CLICKED)
+ {
+ if (strlen(kbtextstr) > 0)
+ {
+ kbtextstr[strlen(kbtextstr) - 1] = 0;
+ kbText->SetText(kbtextstr);
+ }
+ keyBack->SetState(STATE_SELECTED, t->chan);
+ }
+ else if (keyClear->GetState() == STATE_CLICKED)
+ {
+ memset(kbtextstr, 0, sizeof(kbtextstr));
+ kbText->SetText(kbtextstr);
+ keyClear->SetState(STATE_SELECTED, t->chan);
+ }
+
+ char txt[2] = { 0, 0 };
+ for (int i = 0; i < 11; i++)
+ {
+ if (keys[i] != '\0')
+ {
+ if (keyBtn[i]->GetState() == STATE_CLICKED)
+ {
+ txt[0] = keys[i];
+ if (strlen(kbtextstr) < kbtextmaxlen - 1) // -1 --> kbtextmaxlen means with term. '\0'
+ {
+ kbtextstr[strlen(kbtextstr)] = txt[0];
+ kbText->SetText(kbtextstr);
+ }
+ keyBtn[i]->SetState(STATE_SELECTED, t->chan);
+ }
+ }
+ }
+
+ kbText->SetPosition(0, 53);
+
+ this->ToggleFocus(t);
+
+ if (focus) // only send actions to this window if it's in focus
+ {
+ // pad/joystick navigation
+ if (t->Right())
+ this->MoveSelectionHor(1);
+ else if (t->Left())
+ this->MoveSelectionHor(-1);
+ else if (t->Down())
+ this->MoveSelectionVert(1);
+ else if (t->Up()) this->MoveSelectionVert(-1);
+ }
+}
diff --git a/source/libwiigui/gui_optionbrowser.cpp b/source/libwiigui/gui_optionbrowser.cpp
index 0f5dbea3..32086efb 100644
--- a/source/libwiigui/gui_optionbrowser.cpp
+++ b/source/libwiigui/gui_optionbrowser.cpp
@@ -38,8 +38,6 @@ GuiOptionBrowser::GuiOptionBrowser(int w, int h, OptionList * l, const char *ima
trigHeldA = new GuiTrigger;
trigHeldA->SetHeldTrigger(-1, WPAD_BUTTON_A, PAD_BUTTON_A);
- btnSoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, Settings.sfxvolume);
-
bgOptions = Resources::GetImageData(imagebg);
bgOptionsImg = new GuiImage(bgOptions);
bgOptionsImg->SetParent(this);
@@ -152,7 +150,6 @@ GuiOptionBrowser::GuiOptionBrowser(int w, int h, OptionList * l, const char *ima
trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
trigHeldA = new GuiTrigger;
trigHeldA->SetHeldTrigger(-1, WPAD_BUTTON_A, PAD_BUTTON_A);
- btnSoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, Settings.sfxvolume);
bgOptions = Resources::GetImageData(imagebg);
@@ -276,7 +273,6 @@ GuiOptionBrowser::~GuiOptionBrowser()
loaded = 0;
delete trigA;
- delete btnSoundClick;
// delete optionBg;
for (int i = 0; i < PAGESIZE; i++)
diff --git a/source/libwiigui/gui_searchbar.cpp b/source/libwiigui/gui_searchbar.cpp
index f05afafb..0f17ac26 100644
--- a/source/libwiigui/gui_searchbar.cpp
+++ b/source/libwiigui/gui_searchbar.cpp
@@ -31,9 +31,7 @@ class cSearchButton
GuiSearchBar::GuiSearchBar(const wchar_t *SearchChars) :
inSide(0), text((char *) NULL, 22, ( GXColor )
- { 0, 0, 0, 255}), buttons(0), keyImageData(keyboard_key_png, keyboard_key_png_size), keyOverImageData(keyboard_key_over_png, keyboard_key_over_png_size), sndOver(
- button_over_pcm, button_over_pcm_size, Settings.sfxvolume), sndClick(button_click_pcm,
- button_click_pcm_size, Settings.sfxvolume)
+ { 0, 0, 0, 255}), buttons(0), keyImageData(keyboard_key_png, keyboard_key_png_size), keyOverImageData(keyboard_key_over_png, keyboard_key_over_png_size)
{
trig.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE);
@@ -57,7 +55,7 @@ GuiSearchBar::GuiSearchBar(const wchar_t *SearchChars) :
if (x == 0) y++;
charstr[0] = SearchChars[i];
buttons[i] = new cSearchButton(charstr, &keyImageData, &keyOverImageData, x_start + x * 42, y_start - 42 + y
- * 42, &trig, &sndOver, &sndClick);
+ * 42, &trig, btnSoundOver, btnSoundClick);
this->Append(&(buttons[i]->button));
}
height = 10 + 42 + y * 42 + 10;
@@ -73,16 +71,14 @@ GuiSearchBar::GuiSearchBar(const wchar_t *SearchChars) :
BacspaceBtnImg_Over = new GuiImage(imgBacspaceBtn);
BacspaceBtnImg = new GuiImage(BacspaceBtnImg_Over);
BacspaceBtnImg->SetGrayscale();
- BacspaceBtn = new GuiButton(BacspaceBtnImg, BacspaceBtnImg_Over, ALIGN_RIGHT, ALIGN_TOP, -52, 10, &trig, &sndOver,
- &sndClick, 1);
+ BacspaceBtn = new GuiButton(BacspaceBtnImg, BacspaceBtnImg_Over, ALIGN_RIGHT, ALIGN_TOP, -52, 10, &trig, btnSoundOver, btnSoundClick, 1);
this->Append(BacspaceBtn);
imgClearBtn = Resources::GetImageData("keyboard_clear_over.png");
ClearBtnImg_Over = new GuiImage(imgClearBtn);
ClearBtnImg = new GuiImage(ClearBtnImg_Over);
ClearBtnImg->SetGrayscale();
- ClearBtn = new GuiButton(ClearBtnImg, ClearBtnImg_Over, ALIGN_RIGHT, ALIGN_TOP, -10, 10, &trig, &sndOver,
- &sndClick, 1);
+ ClearBtn = new GuiButton(ClearBtnImg, ClearBtnImg_Over, ALIGN_RIGHT, ALIGN_TOP, -10, 10, &trig, btnSoundOver, btnSoundClick, 1);
this->Append(ClearBtn);
// SetPosition(100,100);
diff --git a/source/libwiigui/gui_searchbar.h b/source/libwiigui/gui_searchbar.h
index f3cd7d01..23bbb82e 100644
--- a/source/libwiigui/gui_searchbar.h
+++ b/source/libwiigui/gui_searchbar.h
@@ -30,7 +30,5 @@ class GuiSearchBar: public GuiWindow
GuiImageData keyImageData;
GuiImageData keyOverImageData;
GuiTrigger trig;
- GuiSound sndOver;
- GuiSound sndClick;
};
diff --git a/source/libwiigui/gui_sound.cpp b/source/libwiigui/gui_sound.cpp
deleted file mode 100644
index 2442fed2..00000000
--- a/source/libwiigui/gui_sound.cpp
+++ /dev/null
@@ -1,446 +0,0 @@
-/****************************************************************************
- * libwiigui
- *
- * Tantric 2009
- *
- * gui_sound.cpp
- *
- * decoder modification by ardi 2009
- *
- * GUI class definitions
- ***************************************************************************/
-
-#include "gui.h"
-#include
-#include "gecko.h"
-
-#include "gui_sound_decoder.h"
-
-#define BUFFER_SIZE 8192
-
-/***************************************************************
- *
- * D E C O D E R – L I S T
- *
- *
- ***************************************************************/
-
-GuiSoundDecoder::DecoderListEntry *GuiSoundDecoder::DecoderList = NULL;
-GuiSoundDecoder::DecoderListEntry &GuiSoundDecoder::RegisterDecoder(DecoderListEntry &Decoder,
- GuiSoundDecoderCreate fnc)
-{
- if (Decoder.fnc != fnc)
- {
- Decoder.fnc = fnc;
- Decoder.next = DecoderList;
- DecoderList = &Decoder;
- }
- return Decoder;
-}
-GuiSoundDecoder *GuiSoundDecoder::GetDecoder(const u8 * snd, u32 len, bool snd_is_allocated)
-{
- for (DecoderListEntry *de = DecoderList; de; de = de->next)
- {
- GuiSoundDecoder *d = NULL;
- try
- {
- d = de->fnc(snd, len, snd_is_allocated);
- }
- catch (const char *error)
- {
- gprintf("%s", error);
- }
- catch (...)
- {
- }
- if (d) return d;
- }
- return NULL;
-}
-
-/***************************************************************
- *
- * D E C O D E R – T H R E A D
- *
- *
- ***************************************************************/
-
-static GuiSound *GuiSoundPlayer[16] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL };
-
-static lwp_t GuiSoundDecoderThreadHandle = LWP_THREAD_NULL;
-static bool GuiSoundDecoderThreadRunning = false;
-static bool GuiSoundDecoderDataRquested = false;
-
-void *GuiSoundDecoderThread(void *args)
-{
- GuiSoundDecoderThreadRunning = true;
- do
- {
- if (GuiSoundDecoderDataRquested)
- {
- GuiSoundDecoderDataRquested = false;
- GuiSound **players = GuiSoundPlayer;
- for (int i = 0; i < 16; ++i, ++players)
- {
- GuiSound *player = *players;
- if (player) player->DecoderCallback();
- }
- }
- if (!GuiSoundDecoderDataRquested) usleep(50);
- } while (GuiSoundDecoderThreadRunning);
- return 0;
-}
-
-/***************************************************************
- *
- * A S N D – C A L L B A C K
- *
- *
- ***************************************************************/
-
-void GuiSoundPlayerCallback(s32 Voice)
-{
- if (Voice >= 0 && Voice < 16 && GuiSoundPlayer[Voice])
- {
- GuiSoundPlayer[Voice]->PlayerCallback();
- GuiSoundDecoderDataRquested = true;
- }
-}
-
-/***************************************************************
- *
- * R A W - D E C O D E R
- * Decoder for Raw-PCM-Datas (16bit Stereo 48kHz)
- *
- ***************************************************************/
-class GuiSoundDecoderRAW: public GuiSoundDecoder
-{
- protected:
- GuiSoundDecoderRAW(const u8 * snd, u32 len, bool snd_is_allocated)
- {
- pcm_start = snd;
- is_allocated = snd_is_allocated;
- pcm_end = pcm_start + len;
- pos = pcm_start;
- is_running = false;
-
- }
- public:
- ~GuiSoundDecoderRAW()
- {
- while (is_running)
- usleep(50);
- if (is_allocated) delete[] pcm_start;
- }
- static GuiSoundDecoder *Create(const u8 * snd, u32 len, bool snd_is_allocated)
- {
- try
- {
- return new GuiSoundDecoderRAW(snd, len, snd_is_allocated);
- }
- catch (...)
- {
- }
- return NULL;
- }
- s32 GetFormat()
- {
- return VOICE_STEREO_16BIT;
- }
- s32 GetSampleRate()
- {
- return 48000;
- }
- /* Read reads data from stream to buffer
- return: >0 = readed bytes;
- 0 = EOF;
- <0 = Error;
- */
- int Read(u8 * buffer, int buffer_size)
- {
- if (pos >= pcm_end) return 0; // EOF
-
- is_running = true;
- if (pos + buffer_size > pcm_end) buffer_size = pcm_end - pos;
- memcpy(buffer, pos, buffer_size);
- pos += buffer_size;
- is_running = false;
- return buffer_size;
- }
- int Rewind()
- {
- pos = pcm_start;
- return 0;
- }
- private:
- const u8 *pcm_start;
- const u8 *pcm_end;
- bool is_allocated;
- const u8 *pos;
- bool is_running;
-
-};
-
-/***************************************************************
- *
- * G u i S o u n d
- *
- *
- ***************************************************************/
-#define GuiSoundBufferReady 0x01
-#define GuiSoundBufferEOF 0x02
-#define GuiSoundFinish 0x04
-static int GuiSoundCount = 0;
-/**
- * Constructor for the GuiSound class.
- */
-GuiSound::GuiSound(const u8 *s, int l, int v/*=100*/, bool r/*=true*/, bool a/*=false*/)
-{
- if (GuiSoundCount++ == 0 || GuiSoundDecoderThreadHandle == LWP_THREAD_NULL)
- {
- LWP_CreateThread(&GuiSoundDecoderThreadHandle, GuiSoundDecoderThread, NULL, NULL, 32768, 80);
- }
- voice = -1;
- play_buffer[0] = (u8*) memalign(32, BUFFER_SIZE * 3); // tripple-buffer first is played
- play_buffer[1] = play_buffer[0] + BUFFER_SIZE; // second is waiting
- play_buffer[2] = play_buffer[1] + BUFFER_SIZE; // third is decoding
- buffer_nr = 0; // current playbuffer
- buffer_pos = 0; // current idx to write in buffer
- buffer_ready = false;
- buffer_eof = false;
- loop = false; // play looped
- volume = v; // volume
- decoder = NULL;
- if (play_buffer[0]) // playbuffer ok
- Load(s, l, r, a);
-}
-bool GuiSound::Load(const u8 *s, int l, bool r/*=false*/, bool a/*=false*/)
-{
- Stop();
- if (!play_buffer[0]) return false;
- GuiSoundDecoder *newDecoder = GuiSoundDecoder::GetDecoder(s, l, a);
- if (!newDecoder && r) newDecoder = GuiSoundDecoderRAW::Create(s, l, a);
- if (newDecoder)
- {
- delete decoder;
- decoder = newDecoder;
- return true;
- }
- else if (a) delete[] s;
- return false;
-}
-GuiSound::GuiSound(const char *p, int v/*=100*/)
-{
- if (GuiSoundCount++ == 0 || GuiSoundDecoderThreadHandle == LWP_THREAD_NULL)
- {
- LWP_CreateThread(&GuiSoundDecoderThreadHandle, GuiSoundDecoderThread, NULL, NULL, 32 * 1024, 80);
- }
- voice = -1;
- play_buffer[0] = (u8*) memalign(32, BUFFER_SIZE * 3); // tripple-buffer first is played
- play_buffer[1] = play_buffer[0] + BUFFER_SIZE; // second is waiting
- play_buffer[2] = play_buffer[1] + BUFFER_SIZE; // third is decoding
- buffer_nr = 0; // current playbuffer
- buffer_pos = 0; // current idx to write in buffer
- buffer_ready = false;
- buffer_eof = false;
- loop = false; // play looped
- volume = v; // volume
- decoder = NULL;
- if (play_buffer[0]) // playbuffer ok
- Load(p);
-}
-bool GuiSound::Load(const char *p)
-{
- Stop(); // stop playing
- if (!play_buffer[0]) return false;
-
- bool ret = false;
- voice = -2; // -2 marks loading from file
- u32 filesize = 0;
- u8 *buffer = NULL;
- size_t result;
-
- FILE * pFile = fopen(p, "rb");
- if (pFile)
- {
- // get file size:
- fseek(pFile, 0, SEEK_END);
- filesize = ftell(pFile);
- fseek(pFile, 0, SEEK_SET);
-
- // allocate memory to contain the whole file:
- buffer = new (std::nothrow) u8[filesize];
- if (buffer)
- {
- // copy the file into the buffer:
- result = fread(buffer, 1, filesize, pFile);
- if (result == filesize)
- ret = Load(buffer, filesize, false, true);
- else delete[] buffer;
- }
- fclose(pFile);
- }
- return ret;
-}
-
-/**
- * Destructor for the GuiSound class.
- */
-GuiSound::~GuiSound()
-{
- if (!loop) while (voice >= 0)
- usleep(50);
- Stop();
- if (--GuiSoundCount == 0 && GuiSoundDecoderThreadHandle != LWP_THREAD_NULL)
- {
- GuiSoundDecoderThreadRunning = false;
- LWP_JoinThread(GuiSoundDecoderThreadHandle, NULL);
- GuiSoundDecoderThreadHandle = LWP_THREAD_NULL;
- }
- delete decoder;
- free(play_buffer[0]);
-}
-
-void GuiSound::Play()
-{
- Stop(); // stop playing if it played
- if (!play_buffer[0]) return;
- if (!decoder) return; // no decoder or no play_buffer -> no playing
- // initialize the buffer
- buffer_nr = 0; // allways starts with buffer 0
- buffer_pos = 0; // reset position
- buffer_ready = false;
- buffer_eof = false;
- decoder->Rewind(); // play from begin
- DecoderCallback(); // fill first buffer;
- if (!buffer_ready || buffer_eof) // if first buffer not ready -> no play
- return;
- voice = ASND_GetFirstUnusedVoice();
- if (voice >= 0)
- {
- s32 vol = (255 * volume) / 100;
- s32 format = decoder->GetFormat();
- s32 samplerate = decoder->GetSampleRate();
- s32 first_pos = buffer_pos;
- // switch to next buffer
- buffer_nr = 1;
- buffer_pos = 0;
- buffer_ready = false;
- buffer_eof = false;
- DecoderCallback(); // fill second buffer;
- GuiSoundPlayer[voice] = this; // activate Callbacks for this voice
- // Play the voice
- ASND_SetVoice(voice, format, samplerate, 0, play_buffer[0], first_pos, vol, vol, GuiSoundPlayerCallback);
- }
-}
-/*
- int GuiSound::PlayOggFile(char * path)
- {
- if(Load(path))
- Play();
- return 1;
- }
- */
-void GuiSound::Stop()
-{
- if (voice < 0) return;
- GuiSoundPlayer[voice] = NULL; // disable Callbacks
- SND_StopVoice(voice);
- voice = -1;
-}
-
-void GuiSound::Pause()
-{
- if (voice < 0) return;
- ASND_PauseVoice(voice, 1);
-}
-
-void GuiSound::Resume()
-{
- if (voice < 0) return;
- ASND_PauseVoice(voice, 0);
-}
-
-bool GuiSound::IsPlaying()
-{
- return voice >= 0;
-}
-
-void GuiSound::SetVolume(int vol)
-{
- volume = vol;
- if (voice < 0) return;
- int newvol = 255 * (volume / 100.0);
- ASND_ChangeVolumeVoice(voice, newvol, newvol);
-}
-
-void GuiSound::SetLoop(bool l)
-{
- loop = l;
-}
-
-void GuiSound::DecoderCallback()
-{
- if (buffer_ready || buffer_eof) // if buffer ready or EOF -> nothing
- return;
- bool error = false;
- while (buffer_pos < BUFFER_SIZE)
- {
- int ret = decoder->Read(&play_buffer[buffer_nr][buffer_pos], BUFFER_SIZE - buffer_pos);
- if (ret > 0)
- buffer_pos += ret; // ok -> fill the buffer more
- else if (ret == 0) // EOF from decoder
- {
- if (loop)
- decoder->Rewind(); // if loop -> rewind and fill the buffer more
- else if (buffer_pos)
- break; // has data in buffer -> play the buffer
- else buffer_eof = true; // no data in buffer -> return EOF
- return;
- }
- else if (ret < 0) // an ERROR
- {
- if (buffer_pos)
- break; // has data in buffer -> play the buffer
- else if (loop)
- {
- if (!error) // if no prev error
- {
- decoder->Rewind(); // if loop -> rewind
- error = true; // set error-state
- continue; // and fill the buffer more
- }
- buffer_eof = true; // has prev error -> error in first block -> return EOF
- return;
- }
- else
- {
- buffer_eof = true; // no loop -> return EOF
- return;
- }
- }
- error = false; // clear error-state
- }
- buffer_ready = true;
-}
-void GuiSound::PlayerCallback()
-{
- if (buffer_eof) // if EOF
- {
- if (ASND_TestPointer(voice, play_buffer[(buffer_nr + 2) % 3]) == 0) // test prev. Buffer
- Stop();
- }
- else if (buffer_ready) // if buffer ready
- {
- if (ASND_AddVoice(voice, play_buffer[buffer_nr], buffer_pos) == SND_OK) // add buffer
- {
- // next buffer
- buffer_nr = (buffer_nr + 1) % 3;
- buffer_pos = 0;
- buffer_ready = false;
- buffer_eof = false;
- }
- }
-}
-
diff --git a/source/libwiigui/gui_sound_decoder.h b/source/libwiigui/gui_sound_decoder.h
deleted file mode 100644
index fd81babd..00000000
--- a/source/libwiigui/gui_sound_decoder.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/****************************************************************************
- * libwiigui
- *
- * Tantric 2009
- *
- * gui_sound_decoder.h
- *
- * by ardi 2009
- *
- * GUI class definitions
- ***************************************************************************/
-
-#ifndef GUI_SOUND_DECODER_H
-#define GUI_SOUND_DECODER_H
-
-#include
-
-#define REGISTER_GUI_SOUND_DECODER(decoder) GuiSoundDecoder::DecoderListEntry decoder##_l = GuiSoundDecoder::RegisterDecoder(decoder##_l, decoder::Create)
-class GuiSoundDecoder;
-typedef GuiSoundDecoder *(*GuiSoundDecoderCreate)(const u8 * snd, u32 len, bool snd_is_allocated);
-
-class GuiSoundDecoder
-{
- protected:
- GuiSoundDecoder()
- {
- }
- ; // Constructors must protected so it can create only with Init(...);
- public:
- virtual ~GuiSoundDecoder()
- {
- }
- ;
- // begin API
- // ---------
- // each Decoder must have an own static Create(...) fnc
- // static GuiSoundDecoder *Create(const u8 * snd, u32 len, bool snd_is_allocated);
- virtual s32 GetFormat() = 0;
- virtual s32 GetSampleRate() = 0;
- /* Read reads data from stream to buffer
- return: >0 = readed bytes;
- 0 = EOF;
- <0 = Error;
- */
- virtual int Read(u8 * buffer, int buffer_size) = 0;
- // set the stream to the start
- virtual int Rewind() = 0;
- // -------
- // end API
-
-
- struct DecoderListEntry
- {
- GuiSoundDecoderCreate fnc;
- DecoderListEntry *next;
- };
- static DecoderListEntry &RegisterDecoder(DecoderListEntry &Decoder, GuiSoundDecoderCreate fnc);
- static GuiSoundDecoder *GetDecoder(const u8 * snd, u32 len, bool snd_is_allocated);
- private:
- static DecoderListEntry *DecoderList;
- GuiSoundDecoder(GuiSoundDecoder&); // no copy
-};
-
-#define BIG_ENDIAN_HOST 1 // Wii PPC is a Big-Endian-Host
-#if BIG_ENDIAN_HOST
-
-inline uint16_t be16(const uint8_t *p8)
-{
- return *((uint16_t*) p8);
-}
-inline uint32_t be32(const uint8_t *p8)
-{
- return *((uint32_t*) p8);
-}
-inline uint16_t le16(const uint8_t *p8)
-{
- uint16_t ret = p8[1] << 8 | p8[0];
- return ret;
-}
-inline uint32_t le32(const uint8_t *p8)
-{
- uint32_t ret = p8[3] << 24 | p8[2] << 16 | p8[1] << 8 | p8[0];
- return ret;
-}
-
-#elif LITTLE_ENDIAN_HOST
-inline uint16_t be16( const uint8_t *p8 )
-{
- uint16_t ret = p8[0] << 8 | p8[1];
- return ret;
-}
-inline uint32_t be32( const uint8_t *p8 )
-{
- uint32_t ret = p8[0] << 24 | p8[1] << 16 | p8[2] << 8 | p8[3];
- return ret;
-}
-inline uint16_t le16( const uint8_t *p8 )
-{
- return *( ( uint16_t* )p8 );
-}
-inline uint32_t le32( const uint8_t *p8 )
-{
- return *( ( uint32_t* )p8 );
-}
-#else
-#error "BIG_ENDIAN_HOST or LITTLE_ENDIAN_HOST not setted"
-#endif /* XXX_ENDIAN_HOST */
-
-#define be16inc(p8) (p8+=2, be16(p8-2))
-#define le16inc(p8) (p8+=2, le16(p8-2))
-#define be32inc(p8) (p8+=4, be32(p8-4))
-#define le32inc(p8) (p8+=4, le32(p8-4))
-
-#endif /* GUI_SOUND_DECODER_H */
diff --git a/source/libwiigui/gui_sound_decoder_aiff.cpp b/source/libwiigui/gui_sound_decoder_aiff.cpp
deleted file mode 100644
index 1811f7c8..00000000
--- a/source/libwiigui/gui_sound_decoder_aiff.cpp
+++ /dev/null
@@ -1,158 +0,0 @@
-/****************************************************************************
- * libwiigui
- *
- * ardi 2009
- *
- * gui_sound_plugin_aif.cpp
- *
- * GUI class definitions
- ***************************************************************************/
-
-#include
-#include
-#include
-#include
-#include
-
-#include "gui_sound_decoder.h"
-
-// ------
-// 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)
-
-static double ConvertFromIeeeExtended(const u8* bytes)
-{
- double f;
- int expon;
- u32 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;
-}
-// ------
-
-class GuiSoundDecoderAIFF: public GuiSoundDecoder
-{
- protected:
- GuiSoundDecoderAIFF(const u8 * snd, u32 len, bool snd_is_allocated)
- {
- sound = snd;
- length = len;
- is_allocated = snd_is_allocated;
- is_running = false;
-
- const u8 *in_ptr = sound;
-
- if (be32inc( in_ptr ) != 0x464F524D /*'FORM'*/) throw("No FORM chunk");
- if (be32inc( in_ptr ) + 8 != len) throw("wrong Size");
- if (be32inc( in_ptr ) != 0x41494646 /*'AIFF'*/) throw("No AIFF chunk");
-
- while (in_ptr + 8 < sound + len)
- {
- u32 chunk_id = be32inc( in_ptr );
- u32 chunk_size = be32inc( in_ptr );
- const u8 *chunk_start = in_ptr;
- switch (chunk_id)
- {
- case 0x434F4D4D /*'COMM'*/:
- channelCount = be16inc( in_ptr );
- in_ptr += 4; // skip numSampleFrames
- bytePerSample = (be16inc( in_ptr ) + 7) / 8;
- if (bytePerSample < 1 && bytePerSample > 2) throw("wrong bits per Sample");
- sampleRate = ConvertFromIeeeExtended(in_ptr);
- break;
- case 0x53534E44 /*'SSND'*/:
- pcm_start = in_ptr + 8;
- pcm_end = chunk_start + chunk_size;
- break;
- }
- in_ptr = chunk_start + chunk_size;
- }
- currentPos = pcm_start;
- }
- public:
- ~GuiSoundDecoderAIFF()
- {
- while (is_running)
- usleep(50);
- if (is_allocated) delete[] sound;
- }
- static GuiSoundDecoder *Create(const u8 * snd, u32 len, bool snd_is_allocated)
- {
- if (snd && len > 12 && snd[0] == 'F' && snd[1] == 'O' && snd[2] == 'R' && snd[3] == 'M' && snd[8] == 'A'
- && snd[9] == 'I' && snd[10] == 'F' && snd[11] == 'F') return new GuiSoundDecoderAIFF(snd, len,
- snd_is_allocated);
- return NULL;
- }
- s32 GetFormat()
- {
- if (bytePerSample == 2)
- return channelCount == 2 ? VOICE_STEREO_16BIT : VOICE_MONO_16BIT;
- else return channelCount == 2 ? VOICE_STEREO_8BIT : VOICE_MONO_8BIT;
- }
- s32 GetSampleRate()
- {
- return sampleRate;
- }
- /* Read reads data from stream to buffer
- return: >0 = readed bytes;
- 0 = EOF;
- <0 = Error;
- */
- int Read(u8 * buffer, int buffer_size)
- {
- if (currentPos >= pcm_end) return 0; // EOF
-
- is_running = true;
- if (currentPos + buffer_size > pcm_end) buffer_size = pcm_end - currentPos;
- memcpy(buffer, currentPos, buffer_size);
- currentPos += buffer_size;
- is_running = false;
- return buffer_size;
- }
- int Rewind()
- {
- while (is_running)
- usleep(50);
- currentPos = pcm_start;
- return 0;
- }
- private:
- const u8 *sound;
- u32 length;
- bool is_allocated;
- bool is_running;
-
- u32 sampleRate;
- u16 channelCount;
- u16 bytePerSample;
- const u8 *pcm_start;
- const u8 *pcm_end;
- const u8 *currentPos;
-};
-REGISTER_GUI_SOUND_DECODER( GuiSoundDecoderAIFF );
diff --git a/source/libwiigui/gui_sound_decoder_bns.cpp b/source/libwiigui/gui_sound_decoder_bns.cpp
deleted file mode 100644
index ac7f872d..00000000
--- a/source/libwiigui/gui_sound_decoder_bns.cpp
+++ /dev/null
@@ -1,257 +0,0 @@
-/****************************************************************************
- * libwiigui
- *
- * Tantric 2009
- *
- * gui_sound_plugin_bns.cpp
- *
- * by ardi 2009
- *
- * Decoder for Wii bns-sound
- *
- * GUI class definitions
- ***************************************************************************/
-
-#include
-#include
-
-#include "gui_sound_decoder.h"
-#define BIG_ENDIAN_HOST 1
-
-class chanel_t
-{
- public:
- void Reset()
- {
- currentPos = startPos;
- hist1 = hist2 = 0;
- }
- int DecodeNextBlock()
- {
- int Offset = 0;
- if (currentPos == loopStart)
- {
- loop_hist1 = hist1;
- loop_hist2 = hist2;
- }
- if (loop && currentPos >= endPos)
- {
- currentPos = loopStart;
- hist1 = loop_hist1;
- hist2 = loop_hist2;
- Offset = loopOffset;
-
- }
-
- if (currentPos + 8 <= endPos)
- {
- u16 index = (*currentPos >> 4) & 0x07;
- s32 scale = 1 << (*currentPos++ & 0x0F);
- for (int i = 0; i < 14; i += 2)
- {
- nibbles[i] = ((s8) *currentPos) >> 4;
- nibbles[i + 1] = ((s8) ((*currentPos++) << 4)) >> 4;
- }
- for (int i = 0; i < 14; ++i)
- {
- s32 sample = (scale * nibbles[i]) << 11;
- sample += coEfficients[index * 2] * hist1;
- sample += coEfficients[index * 2 + 1] * hist2;
- sample += 1024;
- sample = sample >> 11;
- if (sample > 32767)
- sample = 32767;
- else if (sample < -32768) sample = -32768;
- pcm[i] = sample;
-
- hist2 = hist1;
- hist1 = sample;
- }
- return Offset;
- }
- return -1;
- }
-
- const u8* startPos;
- const u8* endPos;
- const u8* currentPos;
- s16 coEfficients[16];
- s16 nibbles[14];
- s16 pcm[14];
- s16 hist1;
- s16 hist2;
- bool loop;
- const u8* loopStart;
- u16 loopOffset;
- s16 loop_hist1;
- s16 loop_hist2;
-};
-
-class GuiSoundDecoderBNS: public GuiSoundDecoder
-{
- protected:
- GuiSoundDecoderBNS(const u8 * snd, u32 len, bool snd_is_allocated)
- {
- sound = snd;
- is_running = false;
- is_allocated = snd_is_allocated;
-
- const u8 *in_ptr = sound;
-
- /////////////////
- // READ HEADER //
- /////////////////
- if (be32inc( in_ptr ) != 0x424E5320 /*'BNS '*/) throw("Not a BNS");
-
- in_ptr += 4; // skip 4 byte
-
- u32 bnssize = be32inc( in_ptr );
- if (bnssize != len) throw("Wrong size");
-
- in_ptr += 4; // skip unknown1
-
- const u8* infoStart = sound + be32inc( in_ptr );
- in_ptr += 4; // skip const u8* infoEnd = infoStart + be32inc(in_ptr);
-
- channel[0].startPos = sound + be32inc( in_ptr ) + 8;
- channel[0].endPos = channel[0].startPos + be32inc( in_ptr ) - 8;
-
- ///////////////
- // READ INFO //
- ///////////////
- in_ptr = infoStart + 8; // skip 'INFO' and Infosize
-
- in_ptr++; // skip u8 codeType = *in_ptr++;
-
- channel[0].loop = channel[1].loop = *in_ptr++; // u8 loopFlag;
-
- channelCount = *in_ptr++;
-
- in_ptr++; // skip unknown byte
-
- sampleRate = be16inc( in_ptr );
-
- in_ptr += 2; // skip unknown word
-
- u32 loopStart = be32inc( in_ptr );
- channel[0].loopStart = channel[0].startPos + ((loopStart / 14) * 8);//LoopPos to BlockStart
- channel[1].loopStart = channel[1].startPos + ((loopStart / 14) * 8);
- channel[0].loopOffset = channel[1].loopOffset = loopStart % 14;
-
- in_ptr += 4; // skip u32 SampleCount = be32inc(in_ptr);
-
- in_ptr += 24; // skip unknown Bytes
-
- if (channelCount == 2)
- {
- in_ptr += 4; // skip unknown long
- u32 ChannelSplit = be32inc( in_ptr );
-
- in_ptr += 8; // skip 2x unknown long
-
- channel[1].endPos = channel[0].endPos;
- channel[0].endPos = channel[1].startPos = channel[0].startPos + ChannelSplit;
-
- channel[1].loopStart = channel[1].startPos + (channel[0].loopStart - channel[0].startPos);
- }
- for (int a = 0; a < 16; a++)
- {
- channel[0].coEfficients[a] = (s16) be16inc( in_ptr );
- }
- if (channelCount == 2)
- {
- in_ptr += 16; // skip 16 byte
- for (int a = 0; a < 16; a++)
- {
- channel[1].coEfficients[a] = (s16) be16inc( in_ptr );
- }
- }
- channel[0].Reset();
- channel[1].Reset();
- currentBlockPos = 14;
- }
- public:
- ~GuiSoundDecoderBNS()
- {
- while (is_running)
- usleep(50);
- if (is_allocated) delete[] sound;
- }
- static GuiSoundDecoder *Create(const u8 * snd, u32 len, bool snd_is_allocated)
- {
- if (snd && len > 4 && snd[0] == 'B' && snd[1] == 'N' && snd[2] == 'S' && snd[3] == ' ') return new GuiSoundDecoderBNS(
- snd, len, snd_is_allocated);
- return NULL;
- }
- s32 GetFormat()
- {
- return channelCount == 2 ? VOICE_STEREO_16BIT : VOICE_MONO_16BIT;
- }
- s32 GetSampleRate()
- {
- return sampleRate;
- }
- /* Read reads data from stream to buffer
- return: >0 = readed bytes;
- 0 = EOF;
- <0 = Error;
- */
- int Read(u8 * buffer, int buffer_size)
- {
- is_running = true;
- u8 *write_pos = buffer;
- u8 *write_end = buffer + buffer_size;
-
- for (;;)
- {
- if (currentBlockPos >= 14)
- {
- int Offset = channel[0].DecodeNextBlock();
- if (Offset < 0 || (channelCount == 2 && channel[1].DecodeNextBlock() < 0))
- {
- is_running = false;
- return write_pos - buffer;
- }
- currentBlockPos = Offset;
- }
- for (; currentBlockPos < 14; ++currentBlockPos)
- {
- if (write_pos >= write_end)
- {
- is_running = false;
- return write_pos - buffer;
- }
- *((s16*) write_pos) = channel[0].pcm[currentBlockPos];
- write_pos += 2;
- if (channelCount == 2) // stereo
- {
- *((s16*) write_pos) = channel[1].pcm[currentBlockPos];
- write_pos += 2;
- }
- }
- }
- is_running = false;
- return 0;
- }
- int Rewind()
- {
- channel[0].Reset();
- channel[1].Reset();
- currentBlockPos = 14;
- return 0;
- }
- private:
- const u8 *sound;
- bool is_allocated;
- bool is_running;
- chanel_t channel[2];
- u16 currentBlockPos;
- u16 channelCount;
- u32 sampleRate;
- // u16 loopOffset;
- // u16 bytePerSample;
- // const u8 *soundDataStart;
- // const u8 *soundDataEnd;
- // u32 soundDataLen;
-};
-REGISTER_GUI_SOUND_DECODER( GuiSoundDecoderBNS );
diff --git a/source/libwiigui/gui_sound_decoder_mpg.cpp b/source/libwiigui/gui_sound_decoder_mpg.cpp
deleted file mode 100644
index 40cb7512..00000000
--- a/source/libwiigui/gui_sound_decoder_mpg.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
-/****************************************************************************
- * libwiigui
- *
- * Tantric 2009
- *
- * gui_sound_plugin_mpg.cpp
- *
- * by ardi 2009
- *
- * Decoder for MPEG-Audio Mpeg-1/-2 Layer I,II and III with libmad
- *
- * GUI class definitions
- ***************************************************************************/
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "gui_sound_decoder.h"
-
-static inline s16 FixedToShort(mad_fixed_t Fixed)
-{
- /* Clipping */
- if (Fixed >= MAD_F_ONE) return (SHRT_MAX);
- if (Fixed <= -MAD_F_ONE) return (-SHRT_MAX);
-
- Fixed = Fixed >> (MAD_F_FRACBITS - 15);
- return ((s16) Fixed);
-}
-
-#define ADMA_BUFFERSIZE (8192)
-#define DATABUFFER_SIZE (32768)
-// http://www.fr-an.de/fragen/v06/02_01.htm
-
-
-class GuiSoundDecoderMPG: public GuiSoundDecoder
-{
- protected:
- GuiSoundDecoderMPG(const u8 * snd, u32 len, bool snd_is_allocated)
- {
- sound = snd;
- length = len;
- is_allocated = snd_is_allocated;
- // Init mad-structures
- mad_stream_init(&madStream);
- mad_stream_buffer(&madStream, sound, length);
- mad_frame_init(&madFrame);
- mad_synth_init(&madSynth);
- madSynthPcmPos = 0;
- mad_timer_reset( &madTimer );
- guardBuffer = NULL;
- is_running = false;
-
- // decode first Frame
- if (DecodeFirstFrame())
- {
- mad_synth_finish( &madSynth );
- mad_frame_finish(&madFrame);
- mad_stream_finish(&madStream);
- throw("Stream Error");
- }
- }
- public:
- ~GuiSoundDecoderMPG()
- {
- while (is_running)
- usleep(50);
- mad_synth_finish( &madSynth );
- mad_frame_finish(&madFrame);
- mad_stream_finish(&madStream);
- delete[] guardBuffer;
- if (is_allocated) delete[] sound;
- }
- static GuiSoundDecoder *Create(const u8 * snd, u32 len, bool snd_is_allocated)
- {
- struct mad_stream madStream;
- struct mad_header madHeader;
- mad_stream_init(&madStream);
- mad_stream_buffer(&madStream, snd, len);
- mad_header_init(&madHeader);
- s32 ret = mad_header_decode(&madHeader, &madStream);
- if (ret == 0 || madStream.error == MAD_ERROR_LOSTSYNC) // LOSTSYNC in first call is ok
- {
- int i;
- for (i = 0; i < 4 && mad_header_decode(&madHeader, &madStream) == 0; i++)
- ;
- if (i == 4)
- {
- mad_header_finish( &madHeader );
- mad_stream_finish(&madStream);
- return new GuiSoundDecoderMPG(snd, len, snd_is_allocated);
- }
- } mad_header_finish( &madHeader );
- mad_stream_finish(&madStream);
- return NULL;
- }
- s32 GetFormat()
- {
- return MAD_NCHANNELS( &madFrame.header ) == 2 ? VOICE_STEREO_16BIT : VOICE_MONO_16BIT;
- }
- s32 GetSampleRate()
- {
- return madFrame.header.samplerate;
- }
- /* Read reads data from stream to buffer
- return: >0 = readed bytes;
- 0 = EOF;
- <0 = Error;
- */
- int Read(u8 * buffer, int buffer_size)
- {
- is_running = true;
- if (MAD_NCHANNELS( &madFrame.header ) == 2) // stereo
- buffer_size &= ~0x0003; // make size to a kind of 4
- else buffer_size &= ~0x0001; // make size to a kind of 2
- u8 *write_pos = buffer;
- u8 *write_end = buffer + buffer_size;
-
- for (;;)
- {
- for (; madSynthPcmPos < madSynth.pcm.length; ++madSynthPcmPos)
- {
- if (write_pos >= write_end)
- {
- is_running = false;
- return write_pos - buffer;
- }
- *((s16*) write_pos) = FixedToShort(madSynth.pcm.samples[0][madSynthPcmPos]);
- write_pos += 2;
- if (MAD_NCHANNELS( &madFrame.header ) == 2) // stereo
- {
- *((s16*) write_pos) = FixedToShort(madSynth.pcm.samples[1][madSynthPcmPos]);
- write_pos += 2;
- }
- }
-
- madStream.error = MAD_ERROR_NONE;
- if (mad_frame_decode(&madFrame, &madStream))
- {
- if (MAD_RECOVERABLE( madStream.error ))
- {
- if (madStream.error != MAD_ERROR_LOSTSYNC || !guardBuffer) continue;
- }
- else if (madStream.error == MAD_ERROR_BUFLEN)
- {
- if (!guardBuffer)
- {
- u32 guardLen = (madStream.bufend - madStream.next_frame);
- guardBuffer = new (std::nothrow) u8[guardLen + MAD_BUFFER_GUARD];
- if (guardBuffer)
- {
- memcpy(guardBuffer, madStream.next_frame, guardLen);
- memset(guardBuffer + guardLen, 0, MAD_BUFFER_GUARD);
- mad_stream_buffer(&madStream, guardBuffer, guardLen + MAD_BUFFER_GUARD);
- continue;
- }
- }
- }
- break;
- }
- mad_timer_add(&madTimer, madFrame.header.duration);
- mad_synth_frame(&madSynth, &madFrame);
- madSynthPcmPos = 0;
- }
- is_running = false;
- return write_pos - buffer;
- }
- int Rewind()
- {
- while (is_running)
- usleep(50);
- delete[] guardBuffer;
- guardBuffer = NULL;
- mad_stream_buffer(&madStream, sound, length);
- mad_synth_finish( &madSynth );
- mad_synth_init(&madSynth);
- madSynthPcmPos = 0;
- mad_timer_reset( &madTimer );
- // decode first Frame
- return DecodeFirstFrame();
- }
- private:
- int DecodeFirstFrame()
- {
- for (;;)
- {
- madStream.error = MAD_ERROR_NONE;
- if (mad_frame_decode(&madFrame, &madStream))
- {
- if (MAD_RECOVERABLE( madStream.error ))
- continue;
- else return -1;
- }
- mad_timer_add(&madTimer, madFrame.header.duration);
- mad_synth_frame(&madSynth, &madFrame);
- return 0;
- }
- }
- const u8 *sound;
- u32 length;
- bool is_allocated;
- struct mad_stream madStream;
- struct mad_frame madFrame;
- struct mad_synth madSynth;
- u16 madSynthPcmPos;
- mad_timer_t madTimer;
- u8 *guardBuffer;
- bool is_running;
-};
-REGISTER_GUI_SOUND_DECODER( GuiSoundDecoderMPG );
diff --git a/source/libwiigui/gui_sound_decoder_ogg.cpp b/source/libwiigui/gui_sound_decoder_ogg.cpp
deleted file mode 100644
index 5cf4c76b..00000000
--- a/source/libwiigui/gui_sound_decoder_ogg.cpp
+++ /dev/null
@@ -1,285 +0,0 @@
-/****************************************************************************
- * libwiigui
- *
- * Tantric 2009
- *
- * gui_sound_plugin_ogg.cpp
- *
- * by ardi 2009
- *
- * Decoder for ogg-vorbis with libtremor
- *
- * GUI class definitions
- ***************************************************************************/
-
-#include
-#include
-#include
-#include
-#include
-
-#include "gui_sound_decoder.h"
-
-/* functions to read the Ogg file from memory */
-
-static struct
-{
- char *mem;
- int size;
- int pos;
-} file[4];
-
-static int f_read(void * punt, int bytes, int blocks, int *f)
-{
- int b;
- int c = 0;
- int d;
-
- if (bytes * blocks <= 0) return 0;
-
- blocks *= bytes;
-
- while (blocks > 0)
- {
- b = blocks;
- if (b > 4096) b = 4096;
-
- d = (*f) - 0x666;
- if ((unsigned) (d) <= (0x669 - 0x666))
- {
- if (file[d].size == 0) return -1;
- if ((file[d].pos + b) > file[d].size) b = file[d].size - file[d].pos;
- if (b > 0)
- {
- memcpy(punt, file[d].mem + file[d].pos, b);
- file[d].pos += b;
- }
- }
- else b = read(*f, ((char *) punt) + c, b);
-
- if (b <= 0)
- {
- return c / bytes;
- }
- c += b;
- blocks -= b;
- }
- return c / bytes;
-}
-
-static int f_seek(int *f, ogg_int64_t offset, int mode)
-{
- if (f == NULL) return (-1);
-
- int k;
- mode &= 3;
-
- int d = (*f) - 0x666;
- if ((unsigned) (d) <= (0x669 - 0x666))
- {
- k = 0;
-
- if (file[d].size == 0) return -1;
-
- if (mode == 0)
- {
- if ((offset) >= file[d].size)
- {
- file[d].pos = file[d].size;
- k = -1;
- }
- else if ((offset) < 0)
- {
- file[d].pos = 0;
- k = -1;
- }
- else file[d].pos = offset;
- }
- else if (mode == 1)
- {
- if ((file[d].pos + offset) >= file[d].size)
- {
- file[d].pos = file[d].size;
- k = -1;
- }
- else if ((file[d].pos + offset) < 0)
- {
- file[d].pos = 0;
- k = -1;
- }
- else file[d].pos += offset;
- }
- else if (mode == 2)
- {
-
- if ((file[d].size + offset) >= file[d].size)
- {
- file[d].pos = file[d].size;
- k = -1;
- }
- else if ((file[d].size + offset) < 0)
- {
- file[d].pos = 0;
- k = -1;
- }
- else file[d].pos = file[d].size + offset;
- }
-
- }
- else k = lseek(*f, (int) offset, mode);
-
- if (k < 0)
- k = -1;
- else k = 0;
- return k;
-}
-
-static int f_close(int *f)
-{
- int d = (*f) - 0x666;
- if ((unsigned) (d) <= (0x669 - 0x666))
- {
- file[d].size = 0;
- file[d].pos = 0;
- if (file[d].mem)
- {
- file[d].mem = (char *) 0;
- }
- return 0;
- }
- else return close(*f);
- return 0;
-}
-
-static long f_tell(int *f)
-{
- int k;
-
- int d = (*f) - 0x666;
- if ((unsigned) (d) <= (0x669 - 0x666))
- {
- k = file[d].pos;
- }
- else k = lseek(*f, 0, 1);
-
- return (long) k;
-}
-
-static int mem_open(char * ogg, int size)
-{
- static int one = 1;
- int n;
- if (one)
- {
- one = 0;
-
- file[0].size = 0;
- file[1].size = 0;
- file[2].size = 0;
- file[3].size = 0;
- file[0].mem = ogg;
- file[0].size = size;
- file[0].pos = 0;
- return (0x666);
- }
-
- for (n = 0; n < 4; n++)
- {
- if (file[n].size == 0)
- {
- file[n].mem = ogg;
- file[n].size = size;
- file[n].pos = 0;
- return (0x666 + n);
- }
- }
- return -1;
-}
-
-static int mem_close(int fd)
-{
- if ((unsigned) ((fd) - 0x666) <= (0x669 - 0x666)) // it is a memory file descriptor?
- {
- fd -= 0x666;
- file[fd].size = 0;
- return 0;
- }
- else return f_close(&fd);
-}
-
-static ov_callbacks callbacks = { (size_t(*)(void *, size_t, size_t, void *)) f_read,
- (int(*)(void *, ogg_int64_t, int)) f_seek, (int(*)(void *)) f_close, (long(*)(void *)) f_tell };
-
-class GuiSoundDecoderOGG: public GuiSoundDecoder
-{
- protected:
- GuiSoundDecoderOGG(const u8 * snd, u32 len, bool snd_is_allocated)
- {
- sound = snd;
- is_allocated = snd_is_allocated;
- ogg_fd = mem_open((char *) snd, len);
- if (ogg_fd < 0) throw("mem open failed");
-
- if (ov_open_callbacks((void*) &ogg_fd, &ogg_file, NULL, 0, callbacks) < 0)
- {
- mem_close(ogg_fd);
- throw("ogg open failed");
- }
- ogg_info = ov_info(&ogg_file, -1);
- bitstream = 0;
- is_running = false;
- }
- public:
- ~GuiSoundDecoderOGG()
- {
- while (is_running)
- usleep(50);
- ov_clear(&ogg_file);
- if (is_allocated) delete[] sound;
- }
- static GuiSoundDecoder *Create(const u8 * snd, u32 len, bool snd_is_allocated)
- {
- if (snd && len > 4 && snd[0] == 'O' && snd[1] == 'g' && snd[2] == 'g' && snd[3] == 'S') return new GuiSoundDecoderOGG(
- snd, len, snd_is_allocated);
- return NULL;
- }
- s32 GetFormat()
- {
- return ogg_info->channels == 2 ? VOICE_STEREO_16BIT : VOICE_MONO_16BIT;
- }
- s32 GetSampleRate()
- {
- return ogg_info->rate;
- }
- /* Read reads data from stream to buffer
- return: >0 = readed bytes;
- 0 = EOF;
- <0 = Error;
- */
- int Read(u8 * buffer, int buffer_size)
- {
- is_running = true;
- int ret = ov_read(&ogg_file, (char *) buffer, buffer_size, &bitstream);
- if (ret < 0)
- {
- /* error in the stream. Not a problem, just reporting it in
- case we (the app) cares. In this case, we don't. */
- if (ret != OV_HOLE) ret = 0; // we says EOF
- }
- is_running = false;
- return ret;
- }
- int Rewind()
- {
- return ov_time_seek(&ogg_file, 0);
- }
- private:
- const u8 *sound;
- bool is_allocated;
- int ogg_fd;
- OggVorbis_File ogg_file;
- vorbis_info *ogg_info;
- int bitstream;
- bool is_running;
-};
-REGISTER_GUI_SOUND_DECODER( GuiSoundDecoderOGG );
diff --git a/source/libwiigui/gui_sound_decoder_wav.cpp b/source/libwiigui/gui_sound_decoder_wav.cpp
deleted file mode 100644
index 30f4d462..00000000
--- a/source/libwiigui/gui_sound_decoder_wav.cpp
+++ /dev/null
@@ -1,237 +0,0 @@
-/****************************************************************************
- * libwiigui
- *
- * Tantric 2009
- *
- * gui_sound_plugin_wav.cpp
- *
- * by ardi 2009
- *
- * Decoder for WAVE PCM
- *
- * GUI class definitions
- ***************************************************************************/
-
-#include
-#include