aboutsummaryrefslogtreecommitdiff
path: root/backends
diff options
context:
space:
mode:
authorEugene Sandulenko2008-06-04 20:28:20 +0000
committerEugene Sandulenko2008-06-04 20:28:20 +0000
commit5e666ef774d11d030ea9957ecc64a197de2abcd8 (patch)
tree0d7e9e8c78dd31c25127f7498c2e2955641ceefa /backends
parent1869141f0448621b19ab25d3ca338a134500a049 (diff)
downloadscummvm-rg350-5e666ef774d11d030ea9957ecc64a197de2abcd8.tar.gz
scummvm-rg350-5e666ef774d11d030ea9957ecc64a197de2abcd8.tar.bz2
scummvm-rg350-5e666ef774d11d030ea9957ecc64a197de2abcd8.zip
Patch #1971285: "Nintendo Wii port"
svn-id: r32547
Diffstat (limited to 'backends')
-rw-r--r--backends/fs/wii/wii-fs-factory.cpp49
-rw-r--r--backends/fs/wii/wii-fs-factory.h50
-rw-r--r--backends/fs/wii/wii-fs.cpp196
-rw-r--r--backends/module.mk1
-rw-r--r--backends/platform/wii/Makefile156
-rw-r--r--backends/platform/wii/gecko_console.cpp91
-rw-r--r--backends/platform/wii/gecko_console.h14
-rw-r--r--backends/platform/wii/gx_supp.cpp264
-rw-r--r--backends/platform/wii/gx_supp.h39
-rw-r--r--backends/platform/wii/main.cpp88
-rw-r--r--backends/platform/wii/osystem.cpp188
-rw-r--r--backends/platform/wii/osystem.h163
-rw-r--r--backends/platform/wii/osystem_events.cpp262
-rw-r--r--backends/platform/wii/osystem_gfx.cpp453
-rw-r--r--backends/platform/wii/osystem_sfx.cpp133
15 files changed, 2147 insertions, 0 deletions
diff --git a/backends/fs/wii/wii-fs-factory.cpp b/backends/fs/wii/wii-fs-factory.cpp
new file mode 100644
index 0000000000..9839858dd5
--- /dev/null
+++ b/backends/fs/wii/wii-fs-factory.cpp
@@ -0,0 +1,49 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#if defined(__WII__)
+
+#include <unistd.h>
+
+#include "backends/fs/wii/wii-fs-factory.h"
+#include "backends/fs/wii/wii-fs.cpp"
+
+DECLARE_SINGLETON(WiiFilesystemFactory);
+
+AbstractFilesystemNode *WiiFilesystemFactory::makeRootFileNode() const {
+ return new WiiFilesystemNode();
+}
+
+AbstractFilesystemNode *WiiFilesystemFactory::makeCurrentDirectoryFileNode() const {
+ char buf[MAXPATHLEN];
+
+ if (getcwd(buf, MAXPATHLEN))
+ return new WiiFilesystemNode(buf, true);
+ else
+ return new WiiFilesystemNode();
+}
+
+AbstractFilesystemNode *WiiFilesystemFactory::makeFileNodePath(const String &path) const {
+ return new WiiFilesystemNode(path, true);
+}
+#endif
+
diff --git a/backends/fs/wii/wii-fs-factory.h b/backends/fs/wii/wii-fs-factory.h
new file mode 100644
index 0000000000..24badee330
--- /dev/null
+++ b/backends/fs/wii/wii-fs-factory.h
@@ -0,0 +1,50 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef _WII_FILESYSTEM_FACTORY_H_
+#define _WII_FILESYSTEM_FACTORY_H_
+
+#include "common/singleton.h"
+#include "backends/fs/fs-factory.h"
+
+/**
+ * Creates WiiFilesystemNode objects.
+ *
+ * Parts of this class are documented in the base interface class, FilesystemFactory.
+ */
+class WiiFilesystemFactory : public FilesystemFactory, public Common::Singleton<WiiFilesystemFactory> {
+public:
+ typedef Common::String String;
+
+ virtual AbstractFilesystemNode *makeRootFileNode() const;
+ virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
+ virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
+
+protected:
+ WiiFilesystemFactory() {};
+
+private:
+ friend class Common::Singleton<SingletonBaseType>;
+};
+
+#endif /*Wii_FILESYSTEM_FACTORY_H*/
+
diff --git a/backends/fs/wii/wii-fs.cpp b/backends/fs/wii/wii-fs.cpp
new file mode 100644
index 0000000000..e6d0cf4c7e
--- /dev/null
+++ b/backends/fs/wii/wii-fs.cpp
@@ -0,0 +1,196 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#if defined(__WII__)
+
+#include "backends/fs/abstract-fs.h"
+
+#include <sys/dir.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/**
+ * Implementation of the ScummVM file system API based on Wii.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemNode.
+ */
+class WiiFilesystemNode : public AbstractFilesystemNode {
+protected:
+ String _displayName;
+ String _path;
+ bool _isDirectory, _isReadable, _isWritable;
+
+public:
+ /**
+ * Creates a WiiFilesystemNode with the root node as path.
+ */
+ WiiFilesystemNode();
+
+ /**
+ * Creates a WiiFilesystemNode for a given path.
+ *
+ * @param path String with the path the new node should point to.
+ * @param verify true if the isValid and isDirectory flags should be verified during the construction.
+ */
+ WiiFilesystemNode(const String &path, bool verify);
+
+ virtual bool exists() const;
+ virtual String getDisplayName() const { return _displayName; }
+ virtual String getName() const { return _displayName; }
+ virtual String getPath() const { return _path; }
+ virtual bool isDirectory() const { return _isDirectory; }
+ virtual bool isReadable() const { return _isReadable; }
+ virtual bool isWritable() const { return _isWritable; }
+
+ virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
+ virtual AbstractFilesystemNode *getParent() const;
+
+private:
+ virtual void setFlags();
+};
+
+/**
+ * Returns the last component of a given path.
+ *
+ * Examples:
+ * /foo/bar.txt would return /bar.txt
+ * /foo/bar/ would return /bar/
+ *
+ * @param str String containing the path.
+ * @return Pointer to the first char of the last component inside str.
+ */
+const char *lastPathComponent(const Common::String &str) {
+ if(str.empty())
+ return "";
+
+ const char *start = str.c_str();
+ const char *cur = start + str.size() - 2;
+
+ while (cur >= start && *cur != '/') {
+ --cur;
+ }
+
+ return cur + 1;
+}
+
+void WiiFilesystemNode::setFlags() {
+ struct stat st;
+
+ _isDirectory = false;
+ _isReadable = false;
+ _isWritable = false;
+
+ if (!stat(_path.c_str(), &st)) {
+ _isDirectory = S_ISDIR(st.st_mode);
+ _isReadable = (st.st_mode & S_IRUSR) > 0;
+ _isWritable = (st.st_mode & S_IWUSR) > 0;
+ }
+}
+
+
+WiiFilesystemNode::WiiFilesystemNode() {
+ // The root dir.
+ _path = "fat:/";
+ _displayName = _path;
+
+ setFlags();
+}
+
+WiiFilesystemNode::WiiFilesystemNode(const String &p, bool verify) {
+ assert(p.size() > 0);
+
+ _path = p;
+
+ _displayName = lastPathComponent(_path);
+
+ if (verify)
+ setFlags();
+}
+
+bool WiiFilesystemNode::exists() const {
+ struct stat st;
+ return stat(_path.c_str (), &st) == 0;
+}
+
+AbstractFilesystemNode *WiiFilesystemNode::getChild(const String &n) const {
+ assert(_isDirectory);
+
+ String newPath(_path);
+ if (newPath.lastChar() != '/')
+ newPath += '/';
+ newPath += n;
+
+ return new WiiFilesystemNode(newPath, true);
+}
+
+bool WiiFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool hidden) const {
+ assert(_isDirectory);
+
+ DIR_ITER* dp = diropen (_path.c_str());
+
+ if (dp == NULL)
+ return false;
+
+ char filename[MAXPATHLEN];
+ struct stat st;
+
+ while (dirnext(dp, filename, &st) == 0) {
+ if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0)
+ continue;
+
+ String newPath(_path);
+ if (newPath.lastChar() != '/')
+ newPath += '/';
+ newPath += filename;
+
+ bool isDir = S_ISDIR(st.st_mode);
+
+ if ((mode == FilesystemNode::kListFilesOnly && isDir) ||
+ (mode == FilesystemNode::kListDirectoriesOnly && !isDir))
+ continue;
+
+ if (isDir)
+ newPath += '/';
+
+ myList.push_back(new WiiFilesystemNode(newPath, true));
+ }
+
+ dirclose(dp);
+
+ return true;
+}
+
+AbstractFilesystemNode *WiiFilesystemNode::getParent() const {
+ if (_path == "/")
+ return 0;
+
+ const char *start = _path.c_str();
+ const char *end = lastPathComponent(_path);
+
+ return new WiiFilesystemNode(String(start, end - start), true);
+}
+
+#endif //#if defined(__WII__)
+
diff --git a/backends/module.mk b/backends/module.mk
index 187cc83ee9..6642a3a281 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -9,6 +9,7 @@ MODULE_OBJS := \
fs/psp/psp-fs-factory.o \
fs/symbian/symbian-fs-factory.o \
fs/windows/windows-fs-factory.o \
+ fs/wii/wii-fs-factory.o \
events/default/default-events.o \
midi/alsa.o \
midi/camd.o \
diff --git a/backends/platform/wii/Makefile b/backends/platform/wii/Makefile
new file mode 100644
index 0000000000..0654fa254d
--- /dev/null
+++ b/backends/platform/wii/Makefile
@@ -0,0 +1,156 @@
+DEBUG_WII = 1
+
+ENABLE_SCUMM = 1
+ENABLE_SCUMM_7_8 = 1
+ENABLE_HE = 1
+# ENABLE_AGI = 1
+ENABLE_AGOS = 1
+ENABLE_CINE = 1
+ENABLE_CRUISE = 1
+ENABLE_DRASCULA = 1
+ENABLE_GOB = 1
+ENABLE_IGOR = 1
+ENABLE_KYRA = 1
+ENABLE_LURE = 1
+ENABLE_M4 = 1
+ENABLE_MADE = 1
+ENABLE_PARALLACTION = 1
+ENABLE_QUEEN = 1
+ENABLE_SAGA = 1
+ENABLE_SKY = 1
+ENABLE_SWORD1 = 1
+ENABLE_SWORD2 = 1
+ENABLE_TOUCHE = 1
+
+DISABLE_HQ_SCALERS = 1
+DISABLE_SCALERS = 1
+
+USE_ZLIB = 1
+USE_MAD = 1
+USE_TREMOR = 1
+USE_FLAC = 1
+USE_MPEG2 = 1
+USE_MT32EMU = 1
+
+srcdir = ../../..
+VPATH = $(srcdir)
+HAVE_GCC3 = 1
+
+DISTPATH = $(srcdir)/dists/wii
+
+ifeq ($(strip $(DEVKITPPC)),)
+$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
+endif
+
+PREFIX = $(DEVKITPPC)/bin/powerpc-gekko-
+CXX = $(PREFIX)g++
+AS = $(PREFIX)gcc
+LD = $(PREFIX)gcc
+AR = $(PREFIX)ar cru
+RANLIB = $(PREFIX)ranlib
+STRIP = $(PREFIX)strip -g
+OBJCOPY = $(PREFIX)objcopy
+MKDIR = mkdir -p
+RM = rm -f
+CP = cp -f
+
+TARGET = scummvm-wii
+
+MACHDEP = -DGEKKO -mrvl -mcpu=750 -meabi -mhard-float \
+ -ffunction-sections -fdata-sections -fmodulo-sched
+
+INCDIR = $(srcdir) . $(srcdir)/engines/ $(DEVKITPRO)/libogc/include
+LIBDIR = $(DEVKITPRO)/libogc/lib/wii
+
+CXXFLAGS = -g -Os -Wall $(MACHDEP) -D__WII__ \
+ -Wno-multichar -fno-exceptions -fno-rtti
+
+CXXFLAGS += $(addprefix -I,$(INCDIR))
+LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(TARGET).elf.map
+LDFLAGS += $(addprefix -L,$(LIBDIR))
+LIBS = -lstdc++ -lfat -lwiiuse -lbte -logc -lm
+
+CXXFLAGS += -I$(DEVKITPRO)/3rd/wii/include
+LDFLAGS += -L$(DEVKITPRO)/3rd/wii/lib
+
+ifdef DEBUG_WII
+CXXFLAGS += -DDEBUG_WII
+LIBS += -ldb
+endif
+
+ifdef USE_ZLIB
+CXXFLAGS += -DUSE_ZLIB
+LIBS += -lz
+endif
+
+ifdef USE_MAD
+CXXFLAGS += -DUSE_MAD -I$(DEVKITPRO)/libogc/include/mad
+LIBS += -lmad
+endif
+
+ifdef USE_TREMOR
+CXXFLAGS += -DUSE_VORBIS -DUSE_TREMOR
+LIBS += -lvorbisidec
+endif
+
+ifdef USE_FLAC
+CXXFLAGS += -DUSE_FLAC
+LIBS += -lFLAC
+endif
+
+ifdef USE_MPEG2
+CXXFLAGS += -DUSE_MPEG2
+LIBS += -lmpeg2
+endif
+
+ifdef USE_MT32EMU
+CXXFLAGS += -DUSE_MT32EMU
+endif
+
+OBJS := backends/platform/wii/main.o \
+ backends/platform/wii/gecko_console.o \
+ backends/platform/wii/gx_supp.o \
+ backends/platform/wii/osystem.o \
+ backends/platform/wii/osystem_gfx.o \
+ backends/platform/wii/osystem_sfx.o \
+ backends/platform/wii/osystem_events.o
+
+include $(srcdir)/Makefile.common
+
+.PHONY: clean-wii distclean-wii upload dist
+
+all: $(TARGET).dol
+
+$(TARGET).dol: $(TARGET).elf
+ $(OBJCOPY) -O binary $< $@
+
+$(TARGET).elf: $(OBJS)
+ $(LD) $^ $(LDFLAGS) $(LIBS) -o $@
+
+clean: clean-wii
+
+clean-wii:
+ @-$(RM) $(TARGET).elf $(TARGET).elf.map $(TARGET).dol
+
+distclean: distclean-wii
+
+distclean-wii:
+ @-$(RM) dist
+
+upload:
+ $(DEVKITPPC)/bin/wiiload $(TARGET).dol
+
+dist:
+ $(MKDIR) dist/apps/scummvm
+ $(CP) $(TARGET).dol dist/apps/scummvm/boot.dol
+ $(CP) $(DISTPATH)/meta.xml dist/apps/scummvm/
+ $(CP) $(DISTPATH)/icon.png dist/apps/scummvm/
+ $(CP) $(DISTPATH)/READMII dist/apps/scummvm/
+ $(CP) $(srcdir)/AUTHORS dist/apps/scummvm/
+ $(CP) $(srcdir)/COPYING dist/apps/scummvm/
+ $(CP) $(srcdir)/COPYRIGHT dist/apps/scummvm/
+ $(CP) $(srcdir)/NEWS dist/apps/scummvm/
+ $(CP) $(srcdir)/README dist/apps/scummvm/
+ $(CP) $(DIST_FILES_THEMES) dist/apps/scummvm/
+ $(CP) $(DIST_FILES_ENGINEDATA) dist/apps/scummvm/
+
diff --git a/backends/platform/wii/gecko_console.cpp b/backends/platform/wii/gecko_console.cpp
new file mode 100644
index 0000000000..c419f6e7e5
--- /dev/null
+++ b/backends/platform/wii/gecko_console.cpp
@@ -0,0 +1,91 @@
+/*-------------------------------------------------------------
+
+Copyright (C) 2008
+Hector Martin (marcan)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you
+must not claim that you wrote the original software. If you use
+this software in a product, an acknowledgment in the product
+documentation would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+
+-------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <sys/iosupport.h>
+#include <ogcsys.h>
+#include <gccore.h>
+#include <reent.h>
+
+#include "gecko_console.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static const devoptab_t *dotab_console;
+int usb_sendbuffer_safe(s32 chn,const void *buffer,int size);
+int usb_sendbuffer(s32 chn,const void *buffer,int size);
+
+int __gecko_write(struct _reent *r,int fd,const char *ptr,int len) {
+ char *tmp = (char*)ptr;
+ u32 level;
+ if(dotab_console)
+ dotab_console->write_r(r,fd,ptr,len);
+
+ if(!tmp || len<=0)
+ return -1;
+ level = IRQ_Disable();
+ usb_sendbuffer(1, ptr, len);
+ IRQ_Restore(level);
+ return len;
+}
+
+const devoptab_t dotab_gecko = {
+ "stdout", // device name
+ 0, // size of file structure
+ NULL, // device open
+ NULL, // device close
+ __gecko_write, // device write
+ NULL, // device read
+ NULL, // device seek
+ NULL, // device fstat
+ NULL, // device stat
+ NULL, // device link
+ NULL, // device unlink
+ NULL, // device chdir
+ NULL, // device rename
+ NULL, // device mkdir
+ 0, // dirStateSize
+ NULL, // device diropen_r
+ NULL, // device dirreset_r
+ NULL, // device dirnext_r
+ NULL, // device dirclose_r
+ NULL // device statvfs_r
+};
+
+void gecko_console_init(int chain) {
+ dotab_console = NULL;
+ if(chain)
+ dotab_console = devoptab_list[STD_OUT];
+ devoptab_list[STD_OUT] = &dotab_gecko;
+ devoptab_list[STD_ERR] = &dotab_gecko;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/backends/platform/wii/gecko_console.h b/backends/platform/wii/gecko_console.h
new file mode 100644
index 0000000000..ba7c393add
--- /dev/null
+++ b/backends/platform/wii/gecko_console.h
@@ -0,0 +1,14 @@
+#ifndef _WII_GECKO_CONSOLE_H_
+#define _WII_GECKO_CONSOLE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void gecko_console_init(int chain);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/backends/platform/wii/gx_supp.cpp b/backends/platform/wii/gx_supp.cpp
new file mode 100644
index 0000000000..4c7b8ed58a
--- /dev/null
+++ b/backends/platform/wii/gx_supp.cpp
@@ -0,0 +1,264 @@
+/****************************************************************************
+* Generic GX Support for Emulators
+* softdev 2007
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* NGC GX Video Functions
+*
+* These are pretty standard functions to setup and use GX scaling.
+****************************************************************************/
+
+#include <gccore.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <malloc.h>
+
+#define DEFAULT_FIFO_SIZE (256 * 1024)
+
+#define HASPECT 320
+#define VASPECT 240
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*** 2D ***/
+static u32 whichfb;
+static u32 *xfb[2];
+static GXRModeObj *vmode;
+
+/*** 3D GX ***/
+static u8 *gp_fifo;
+
+/*** Texture memory ***/
+static u8 *texturemem;
+static u32 texturesize;
+
+GXTexObj texobj;
+static Mtx view;
+static u16 vwidth, vheight, oldvwidth, oldvheight;
+
+/* New texture based scaler */
+typedef struct tagcamera {
+ Vector pos;
+ Vector up;
+ Vector view;
+} camera;
+
+static s16 square[] ATTRIBUTE_ALIGN(32) = {
+ -HASPECT, VASPECT, 0,
+ HASPECT, VASPECT, 0,
+ HASPECT, -VASPECT, 0,
+ -HASPECT, -VASPECT, 0,
+};
+
+static camera cam = {
+ { 0.0f, 0.0f, 370.0f },
+ { 0.0f, 0.5f, 0.0f },
+ { 0.0f, 0.0f, -0.5f }
+};
+
+void GX_InitVideo() {
+ vmode = VIDEO_GetPreferredMode(NULL);
+ VIDEO_Configure(vmode);
+
+ xfb[0] = (u32 *) MEM_K0_TO_K1 (SYS_AllocateFramebuffer(vmode));
+ xfb[1] = (u32 *) MEM_K0_TO_K1 (SYS_AllocateFramebuffer(vmode));
+ gp_fifo = (u8 *) memalign(32, DEFAULT_FIFO_SIZE);
+
+ VIDEO_ClearFrameBuffer(vmode, xfb[0], COLOR_BLACK);
+ VIDEO_ClearFrameBuffer(vmode, xfb[1], COLOR_BLACK);
+
+ whichfb = 0;
+ VIDEO_SetNextFramebuffer(xfb[whichfb]);
+ VIDEO_SetBlack(FALSE);
+ VIDEO_Flush();
+ VIDEO_WaitVSync();
+
+ if (vmode->viTVMode & VI_NON_INTERLACE)
+ VIDEO_WaitVSync();
+}
+
+/****************************************************************************
+ * Scaler Support Functions
+ ****************************************************************************/
+static void draw_init(void) {
+ GX_ClearVtxDesc();
+ GX_SetVtxDesc(GX_VA_POS, GX_INDEX8);
+ GX_SetVtxDesc(GX_VA_CLR0, GX_INDEX8);
+ GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
+
+ GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0);
+ GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
+ GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
+
+ GX_SetArray(GX_VA_POS, square, 3 * sizeof(s16));
+
+ GX_SetNumTexGens(1);
+ GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
+
+ GX_InvalidateTexAll();
+
+ GX_InitTexObj(&texobj, texturemem, vwidth, vheight, GX_TF_RGB565,
+ GX_CLAMP, GX_CLAMP, GX_FALSE);
+}
+
+static void draw_vert(u8 pos, u8 c, f32 s, f32 t) {
+ GX_Position1x8(pos);
+ GX_Color1x8(c);
+ GX_TexCoord2f32(s, t);
+}
+
+static void draw_square(Mtx v) {
+ Mtx m;
+ Mtx mv;
+
+ guMtxIdentity(m);
+ guMtxTransApply(m, m, 0, 0, -100);
+ guMtxConcat(v, m, mv);
+
+ GX_LoadPosMtxImm(mv, GX_PNMTX0);
+ GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
+ draw_vert(0, 0, 0.0, 0.0);
+ draw_vert(1, 0, 1.0, 0.0);
+ draw_vert(2, 0, 1.0, 1.0);
+ draw_vert(3, 0, 0.0, 1.0);
+ GX_End();
+}
+
+/****************************************************************************
+ * StartGX
+ ****************************************************************************/
+void GX_Start(u16 width, u16 height, s16 haspect, s16 vaspect) {
+ Mtx p;
+
+ GX_AbortFrame();
+
+ /*** Set new aspect ***/
+ square[0] = square[9] = -haspect;
+ square[3] = square[6] = haspect;
+ square[1] = square[4] = vaspect;
+ square[7] = square[10] = -vaspect;
+
+ /*** Allocate 32byte aligned texture memory ***/
+ texturesize = (width * height) * 2;
+ texturemem = (u8 *) memalign(32, texturesize);
+
+ GXColor gxbackground = { 0, 0, 0, 0xff };
+
+ /*** Clear out FIFO area ***/
+ memset(gp_fifo, 0, DEFAULT_FIFO_SIZE);
+
+ /*** Initialise GX ***/
+ GX_Init(gp_fifo, DEFAULT_FIFO_SIZE);
+ GX_SetCopyClear(gxbackground, 0x00ffffff);
+
+ GX_SetViewport(0, 0, vmode->fbWidth, vmode->efbHeight, 0, 1);
+ GX_SetDispCopyYScale((f32) vmode->xfbHeight / (f32) vmode->efbHeight);
+ GX_SetScissor(0, 0, vmode->fbWidth, vmode->efbHeight);
+ GX_SetDispCopySrc(0, 0, vmode->fbWidth, vmode->efbHeight);
+ GX_SetDispCopyDst(vmode->fbWidth, vmode->xfbHeight);
+ GX_SetCopyFilter(vmode->aa, vmode->sample_pattern, GX_TRUE,
+ vmode->vfilter);
+ GX_SetFieldMode(vmode->field_rendering,
+ ((vmode->viHeight == 2 * vmode->xfbHeight) ?
+ GX_ENABLE : GX_DISABLE));
+ GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);
+ GX_SetCullMode(GX_CULL_NONE);
+ GX_CopyDisp(xfb[whichfb ^ 1], GX_TRUE);
+ GX_SetDispCopyGamma(GX_GM_1_0);
+
+ guPerspective(p, 60, 1.33f, 10.0f, 1000.0f);
+ GX_LoadProjectionMtx(p, GX_PERSPECTIVE);
+ memset(texturemem, 0, texturesize);
+
+ GX_Flush();
+
+ /*** Setup for first call to scaler ***/
+ vwidth = vheight = -1;
+}
+
+/****************************************************************************
+* GX_Render
+*
+* Pass in a buffer, width and height to update as a tiled RGB565 texture
+****************************************************************************/
+void GX_Render(u16 width, u16 height, u8 *buffer, u16 pitch) {
+ u16 h, w;
+ u64 *dst = (u64 *) texturemem;
+ u64 *src1 = (u64 *) buffer;
+ u64 *src2 = (u64 *) (buffer + pitch);
+ u64 *src3 = (u64 *) (buffer + (pitch * 2));
+ u64 *src4 = (u64 *) (buffer + (pitch * 3));
+ u16 rowpitch = (pitch >> 3) * 3 + pitch % 8;
+
+ vwidth = width;
+ vheight = height;
+
+ whichfb ^= 1;
+
+ if ((oldvheight != vheight) || (oldvwidth != vwidth)) {
+ /** Update scaling **/
+ oldvwidth = vwidth;
+ oldvheight = vheight;
+ draw_init();
+ memset(&view, 0, sizeof(Mtx));
+ guLookAt(view, &cam.pos, &cam.up, &cam.view);
+ GX_SetViewport(0, 0, vmode->fbWidth, vmode->efbHeight, 0, 1);
+ }
+
+ GX_InvVtxCache();
+ GX_InvalidateTexAll();
+ GX_SetTevOp(GX_TEVSTAGE0, GX_DECAL);
+ GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
+
+ for (h = 0; h < vheight; h += 4) {
+ for (w = 0; w < (vwidth >> 2); w++) {
+ *dst++ = *src1++;
+ *dst++ = *src2++;
+ *dst++ = *src3++;
+ *dst++ = *src4++;
+ }
+
+ src1 += rowpitch;
+ src2 += rowpitch;
+ src3 += rowpitch;
+ src4 += rowpitch;
+ }
+
+ DCFlushRange(texturemem, texturesize);
+
+ GX_SetNumChans(1);
+ GX_LoadTexObj(&texobj, GX_TEXMAP0);
+
+ draw_square(view);
+
+ GX_DrawDone();
+
+ GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
+ GX_SetColorUpdate(GX_TRUE);
+ GX_CopyDisp(xfb[whichfb], GX_TRUE);
+ GX_Flush();
+
+ VIDEO_SetNextFramebuffer(xfb[whichfb]);
+ VIDEO_Flush();
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/backends/platform/wii/gx_supp.h b/backends/platform/wii/gx_supp.h
new file mode 100644
index 0000000000..9393e93a26
--- /dev/null
+++ b/backends/platform/wii/gx_supp.h
@@ -0,0 +1,39 @@
+/****************************************************************************
+* Generic GX Scaler
+* softdev 2007
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* NGC GX Video Functions
+*
+* These are pretty standard functions to setup and use GX scaling.
+****************************************************************************/
+#ifndef _WII_GX_SUPP_H_
+#define _WII_GX_SUPP_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void GX_InitVideo();
+
+void GX_Start(u16 width, u16 height, s16 haspect, s16 vaspect);
+void GX_Render(u16 width, u16 height, u8 *buffer, u16 pitch);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/backends/platform/wii/main.cpp b/backends/platform/wii/main.cpp
new file mode 100644
index 0000000000..7529df6de3
--- /dev/null
+++ b/backends/platform/wii/main.cpp
@@ -0,0 +1,88 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <fat.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "osystem.h"
+
+#ifdef DEBUG_WII
+#include <debug.h>
+#include <gecko_console.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int main(int argc, char *argv[]) {
+ s32 res;
+
+ VIDEO_Init();
+ PAD_Init();
+ AUDIO_Init(NULL);
+
+#ifdef DEBUG_WII
+ gecko_console_init(0);
+ //DEBUG_Init(GDBSTUB_DEVICE_USB, 1);
+#endif
+
+ printf("startup\n");
+
+ if (!fatInitDefault()) {
+ printf("fatInitDefault failed\n");
+ } else {
+ // set the default path if libfat couldnt set it
+ // this allows loading over tcp/usbgecko
+ char buf[MAXPATHLEN];
+
+ getcwd(buf, MAXPATHLEN);
+ if (!strcmp(buf, "fat:/"))
+ chdir("/apps/scummvm");
+
+ //fatEnableReadAhead(PI_DEFAULT, 32, 128);
+ }
+
+ g_system = new OSystem_Wii();
+ assert(g_system);
+
+ res = scummvm_main(argc, argv);
+ g_system->quit();
+
+ printf("shutdown\n");
+
+ if (!fatUnmount(PI_DEFAULT)) {
+ printf("fatUnmount failed\n");
+ fatUnsafeUnmount(PI_DEFAULT);
+ }
+
+ printf("reloading\n");
+
+ return res;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/backends/platform/wii/osystem.cpp b/backends/platform/wii/osystem.cpp
new file mode 100644
index 0000000000..97bee24d0f
--- /dev/null
+++ b/backends/platform/wii/osystem.cpp
@@ -0,0 +1,188 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "osystem.h"
+#include "backends/fs/wii/wii-fs-factory.h"
+
+#include <unistd.h>
+
+#include <ogc/mutex.h>
+#include <ogc/lwp_watchdog.h>
+
+OSystem_Wii::OSystem_Wii() :
+ _startup_time(0),
+ _alarm(-1),
+
+ _palette(NULL),
+ _cursorPalette(NULL),
+ _cursorPaletteDisabled(true),
+
+ _gameWidth(0),
+ _gameHeight(0),
+ _gamePixels(NULL),
+
+ _overlayVisible(false),
+ _overlayWidth(0),
+ _overlayHeight(0),
+ _overlaySize(0),
+ _overlayPixels(NULL),
+
+ _lastScreenUpdate(0),
+ _texture(NULL),
+ _currentWidth(0),
+ _currentHeight(0),
+
+ _supportedGraphicsModes(NULL),
+ _activeGraphicsMode(-1),
+
+ _mouseVisible(false),
+ _mouseX(0),
+ _mouseY(0),
+ _mouseWidth(0),
+ _mouseHeight(0),
+ _mouseHotspotX(0),
+ _mouseHotspotY(0),
+ _mouseKeyColor(0),
+ _mouseCursor(NULL),
+
+ _savefile(NULL),
+ _mixer(NULL),
+ _timer(NULL) {
+}
+
+OSystem_Wii::~OSystem_Wii() {
+ if (_savefile) {
+ delete _savefile;
+ _savefile = NULL;
+ }
+
+ if (_mixer) {
+ delete _mixer;
+ _mixer = NULL;
+ }
+
+ if (_timer) {
+ delete _timer;
+ _timer = NULL;
+ }
+}
+
+void OSystem_Wii::initBackend() {
+ _startup_time = gettime();
+
+ _savefile = new DefaultSaveFileManager();
+ _mixer = new Audio::Mixer();
+ _timer = new DefaultTimerManager();
+
+ initGfx();
+ initSfx();
+ initEvents();
+
+ OSystem::initBackend();
+}
+
+void OSystem_Wii::quit() {
+ deinitEvents();
+ deinitSfx();
+ deinitGfx();
+}
+
+bool OSystem_Wii::hasFeature(Feature f) {
+ return f == kFeatureCursorHasPalette;
+}
+
+void OSystem_Wii::setFeatureState(Feature f, bool enable) {
+}
+
+bool OSystem_Wii::getFeatureState(Feature f) {
+ return false;
+}
+
+uint32 OSystem_Wii::getMillis() {
+ return ticks_to_millisecs(diff_ticks(_startup_time, gettime()));
+}
+
+void OSystem_Wii::delayMillis(uint msecs) {
+ usleep(msecs * 1000);
+}
+
+OSystem::MutexRef OSystem_Wii::createMutex() {
+ mutex_t *mutex = (mutex_t *) malloc(sizeof(mutex_t));
+ s32 res = LWP_MutexInit(mutex, false);
+
+ if (res) {
+ printf("ERROR creating mutex\n");
+ delete mutex;
+ return NULL;
+ }
+
+ return (MutexRef) mutex;
+}
+
+void OSystem_Wii::lockMutex(MutexRef mutex) {
+ s32 res = LWP_MutexLock(*(mutex_t *) mutex);
+
+ if (res)
+ printf("ERROR locking mutex %p (%d)\n", mutex, res);
+}
+
+void OSystem_Wii::unlockMutex(MutexRef mutex) {
+ s32 res = LWP_MutexUnlock(*(mutex_t *) mutex);
+
+ if (res)
+ printf("ERROR unlocking mutex %p (%d)\n", mutex, res);
+}
+
+void OSystem_Wii::deleteMutex(MutexRef mutex) {
+ s32 res = LWP_MutexDestroy(*(mutex_t *) mutex);
+
+ if (res)
+ printf("ERROR destroying mutex %p (%d)\n", mutex, res);
+}
+
+void OSystem_Wii::setWindowCaption(const char *caption) {
+ printf("window caption: %s\n", caption);
+}
+
+Common::SaveFileManager *OSystem_Wii::getSavefileManager() {
+ assert(_savefile);
+ return _savefile;
+}
+
+Audio::Mixer *OSystem_Wii::getMixer() {
+ assert(_mixer);
+ return _mixer;
+}
+
+Common::TimerManager *OSystem_Wii::getTimerManager() {
+ assert(_timer);
+ return _timer;
+}
+
+FilesystemFactory *OSystem_Wii::getFilesystemFactory() {
+ return &WiiFilesystemFactory::instance();
+}
+
+void OSystem_Wii::getTimeAndDate(struct tm &t) const {
+ time_t curTime = time(0);
+ t = *localtime(&curTime);
+}
+
diff --git a/backends/platform/wii/osystem.h b/backends/platform/wii/osystem.h
new file mode 100644
index 0000000000..f65310bada
--- /dev/null
+++ b/backends/platform/wii/osystem.h
@@ -0,0 +1,163 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _WII_OSYSTEM_H_
+#define _WII_OSYSTEM_H_
+
+#include "common/system.h"
+#include "base/main.h"
+
+#include "common/rect.h"
+#include "common/events.h"
+
+#include "backends/saves/default/default-saves.h"
+#include "backends/timer/default/default-timer.h"
+#include "graphics/surface.h"
+#include "sound/mixer.h"
+
+#include <gctypes.h>
+#include <gccore.h>
+#include <ogcsys.h>
+
+class OSystem_Wii : public OSystem {
+private:
+ s64 _startup_time;
+ syswd_t _alarm;
+
+ u16 *_palette;
+ u16 *_cursorPalette;
+ bool _cursorPaletteDisabled;
+
+ u16 _gameWidth, _gameHeight;
+ u8 *_gamePixels;
+ Graphics::Surface _surface;
+
+ bool _overlayVisible;
+ u16 _overlayWidth, _overlayHeight;
+ u32 _overlaySize;
+ OverlayColor *_overlayPixels;
+
+ u32 _lastScreenUpdate;
+ u16 *_texture;
+ u16 _currentWidth, _currentHeight;
+
+ OSystem::GraphicsMode *_supportedGraphicsModes;
+ s32 _activeGraphicsMode;
+
+ bool _mouseVisible;
+ s32 _mouseX, _mouseY;
+ u32 _mouseWidth, _mouseHeight;
+ s32 _mouseHotspotX, _mouseHotspotY;
+ u8 _mouseKeyColor;
+ u8 *_mouseCursor;
+
+ u32 _lastPadCheck;
+
+ void initGfx();
+ void deinitGfx();
+
+ void initSfx();
+ void deinitSfx();
+
+ void initEvents();
+ void deinitEvents();
+ void updateEventScreenResolution();
+
+protected:
+ Common::SaveFileManager *_savefile;
+ Audio::Mixer *_mixer;
+ DefaultTimerManager *_timer;
+
+public:
+ OSystem_Wii();
+ virtual ~OSystem_Wii();
+
+ virtual void initBackend();
+
+ virtual bool hasFeature(Feature f);
+ virtual void setFeatureState(Feature f, bool enable);
+ virtual bool getFeatureState(Feature f);
+ virtual const GraphicsMode *getSupportedGraphicsModes() const;
+ virtual int getDefaultGraphicsMode() const;
+ bool setGraphicsMode(const char *name);
+ virtual bool setGraphicsMode(int mode);
+ virtual int getGraphicsMode() const;
+ virtual void initSize(uint width, uint height);
+ virtual int16 getWidth();
+ virtual int16 getHeight();
+ virtual void setPalette(const byte *colors, uint start, uint num);
+ virtual void grabPalette(byte *colors, uint start, uint num);
+ virtual void setCursorPalette(const byte *colors, uint start, uint num);
+ virtual void disableCursorPalette(bool disable);
+ virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y,
+ int w, int h);
+ virtual void updateScreen();
+ virtual Graphics::Surface *lockScreen();
+ virtual void unlockScreen();
+ virtual void setShakePos(int shakeOffset);
+
+ virtual void showOverlay();
+ virtual void hideOverlay();
+ virtual void clearOverlay();
+ virtual void grabOverlay(OverlayColor *buf, int pitch);
+ virtual void copyRectToOverlay(const OverlayColor *buf, int pitch,
+ int x, int y, int w, int h);
+ virtual int16 getOverlayWidth();
+ virtual int16 getOverlayHeight();
+
+ virtual OverlayColor RGBToColor(uint8 r, uint8 g, uint8 b);
+ virtual void colorToRGB(OverlayColor color, uint8 &r, uint8 &g, uint8 &b);
+ virtual OverlayColor ARGBToColor(uint8 a, uint8 r, uint8 g, uint8 b);
+ virtual void colorToARGB(OverlayColor color, uint8 &a, uint8 &r,
+ uint8 &g, uint8 &b);
+
+ virtual bool showMouse(bool visible);
+
+ virtual void warpMouse(int x, int y);
+ virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX,
+ int hotspotY, byte keycolor = 255,
+ int cursorTargetScale = 1);
+
+ virtual bool pollEvent(Common::Event &event);
+ virtual uint32 getMillis();
+ virtual void delayMillis(uint msecs);
+
+ virtual MutexRef createMutex();
+ virtual void lockMutex(MutexRef mutex);
+ virtual void unlockMutex(MutexRef mutex);
+ virtual void deleteMutex(MutexRef mutex);
+
+ typedef void (*SoundProc)(void *param, byte *buf, int len);
+ virtual int getOutputSampleRate() const;
+
+ virtual void quit();
+
+ virtual void setWindowCaption(const char *caption);
+
+ virtual Common::SaveFileManager *getSavefileManager();
+ virtual Audio::Mixer *getMixer();
+ virtual Common::TimerManager *getTimerManager();
+ FilesystemFactory *getFilesystemFactory();
+ void getTimeAndDate(struct tm &t) const;
+};
+
+#endif
+
diff --git a/backends/platform/wii/osystem_events.cpp b/backends/platform/wii/osystem_events.cpp
new file mode 100644
index 0000000000..09dfb5e96b
--- /dev/null
+++ b/backends/platform/wii/osystem_events.cpp
@@ -0,0 +1,262 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <unistd.h>
+#include <malloc.h>
+
+#ifndef GAMECUBE
+#include <wiiuse/wpad.h>
+#endif
+
+#include <ogc/lwp_watchdog.h>
+
+#include "osystem.h"
+
+#define TIMER_THREAD_STACKSIZE (1024 * 32)
+#define TIMER_THREAD_PRIO 64
+
+#define PAD_CHECK_TIME 40
+
+#ifndef GAMECUBE
+#define PADS_A (PAD_BUTTON_A | (WPAD_BUTTON_A << 16))
+#define PADS_B (PAD_BUTTON_B | (WPAD_BUTTON_B << 16))
+#define PADS_X (PAD_BUTTON_X | (WPAD_BUTTON_MINUS << 16))
+#define PADS_Y (PAD_BUTTON_Y | (WPAD_BUTTON_PLUS << 16))
+#define PADS_Z (PAD_TRIGGER_Z | (WPAD_BUTTON_2 << 16))
+#define PADS_START (PAD_BUTTON_START | (WPAD_BUTTON_HOME << 16))
+#define PADS_UP (PAD_BUTTON_UP | (WPAD_BUTTON_UP << 16))
+#define PADS_DOWN (PAD_BUTTON_DOWN | (WPAD_BUTTON_DOWN << 16))
+#define PADS_LEFT (PAD_BUTTON_LEFT | (WPAD_BUTTON_LEFT << 16))
+#define PADS_RIGHT (PAD_BUTTON_RIGHT | (WPAD_BUTTON_RIGHT << 16))
+#else
+#define PADS_A PAD_BUTTON_A
+#define PADS_B PAD_BUTTON_B
+#define PADS_X PAD_BUTTON_X
+#define PADS_Y PAD_BUTTON_Y
+#define PADS_Z PAD_TRIGGER_Z
+#define PADS_START PAD_BUTTON_START
+#define PADS_UP PAD_BUTTON_UP
+#define PADS_DOWN PAD_BUTTON_DOWN
+#define PADS_LEFT PAD_BUTTON_LEFT
+#define PADS_RIGHT PAD_BUTTON_RIGHT
+#endif
+
+static lwpq_t timer_queue;
+static lwp_t timer_thread;
+static u8 *timer_stack;
+static bool timer_thread_running = false;
+static bool timer_thread_quit = false;
+
+static void * timer_thread_func(void *arg) {
+ while (!timer_thread_quit) {
+ DefaultTimerManager *tm =
+ (DefaultTimerManager *) g_system->getTimerManager();
+ tm->handler();
+
+ usleep(1000 * 10);
+ }
+
+ return NULL;
+}
+
+void OSystem_Wii::initEvents() {
+ timer_thread_quit = false;
+
+ timer_stack = (u8 *) memalign(32, TIMER_THREAD_STACKSIZE);
+ memset(timer_stack, 0, TIMER_THREAD_STACKSIZE);
+
+ LWP_InitQueue(&timer_queue);
+
+ s32 res = LWP_CreateThread(&timer_thread, timer_thread_func, NULL,
+ timer_stack, TIMER_THREAD_STACKSIZE,
+ TIMER_THREAD_PRIO);
+
+ if (res) {
+ printf("ERROR creating timer thread: %d\n", res);
+ LWP_CloseQueue(timer_queue);
+ }
+
+ timer_thread_running = res == 0;
+
+#ifndef GAMECUBE
+ WPAD_Init();
+ WPAD_SetDataFormat(WPAD_CHAN_0, WPAD_FMT_BTNS_ACC_IR);
+ WPAD_SetIdleTimeout(120);
+#endif
+}
+
+void OSystem_Wii::deinitEvents() {
+ if (timer_thread_running) {
+ timer_thread_quit = true;
+ LWP_ThreadBroadcast(timer_queue);
+
+ LWP_JoinThread(timer_thread, NULL);
+ LWP_CloseQueue(timer_queue);
+
+ timer_thread_running = false;
+ }
+
+#ifndef GAMECUBE
+ WPAD_Shutdown();
+#endif
+}
+
+void OSystem_Wii::updateEventScreenResolution() {
+#ifndef GAMECUBE
+ WPAD_SetVRes(WPAD_CHAN_0, _currentWidth + _currentWidth / 5,
+ _currentHeight + _currentHeight / 5);
+#endif
+}
+
+#define KBD_EVENT(pad_button, kbd_keycode, kbd_ascii) \
+ do { \
+ if ((bd | bu) & pad_button) { \
+ if (bd & pad_button) \
+ event.type = Common::EVENT_KEYDOWN; \
+ else \
+ event.type = Common::EVENT_KEYUP; \
+ event.kbd.keycode = kbd_keycode; \
+ event.kbd.ascii = kbd_ascii; \
+ return true; \
+ } \
+ } while (0)
+
+bool OSystem_Wii::pollEvent(Common::Event &event) {
+ u32 bd, bh, bu;
+
+ PAD_ScanPads();
+
+ bd = PAD_ButtonsDown(0);
+ bh = PAD_ButtonsHeld(0);
+ bu = PAD_ButtonsUp(0);
+
+#ifndef GAMECUBE
+ WPAD_ScanPads();
+
+ s32 res = WPAD_Probe(0, NULL);
+
+ if (res == WPAD_ERR_NONE) {
+
+ bd |= WPAD_ButtonsDown(0) << 16;
+ bh |= WPAD_ButtonsHeld(0) << 16;
+ bu |= WPAD_ButtonsUp(0) << 16;
+ }
+#endif
+
+ if (bd || bu) {
+ if (bh & PADS_UP)
+ event.kbd.flags = Common::KBD_SHIFT;
+
+ KBD_EVENT(PADS_Z, Common::KEYCODE_RETURN, Common::ASCII_RETURN);
+ KBD_EVENT(PADS_X, Common::KEYCODE_ESCAPE, Common::ASCII_ESCAPE);
+ KBD_EVENT(PADS_Y, Common::KEYCODE_PERIOD, '.');
+ KBD_EVENT(PADS_START, Common::KEYCODE_F5, Common::ASCII_F5);
+ KBD_EVENT(PADS_UP, Common::KEYCODE_LSHIFT, 0);
+ KBD_EVENT(PADS_DOWN, Common::KEYCODE_0, '0');
+ KBD_EVENT(PADS_LEFT, Common::KEYCODE_y, 'y');
+ KBD_EVENT(PADS_RIGHT, Common::KEYCODE_n, 'n');
+
+ if ((bd | bu) & (PADS_A | PADS_B)) {
+ if (bd & PADS_A)
+ event.type = Common::EVENT_LBUTTONDOWN;
+ else if (bu & PADS_A)
+ event.type = Common::EVENT_LBUTTONUP;
+ else if (bd & PADS_B)
+ event.type = Common::EVENT_RBUTTONDOWN;
+ else if (bu & PADS_B)
+ event.type = Common::EVENT_RBUTTONUP;
+
+ event.mouse.x = _mouseX;
+ event.mouse.y = _mouseY;
+
+ return true;
+ }
+ }
+
+ s32 mx = _mouseX;
+ s32 my = _mouseY;
+
+#ifndef GAMECUBE
+ if (res == WPAD_ERR_NONE) {
+ struct ir_t ir;
+
+ WPAD_IR(0, &ir);
+
+ if (ir.valid) {
+ mx = ir.x - _currentWidth / 10;
+ my = ir.y - _currentHeight / 10;
+
+ if (mx < 0)
+ mx = 0;
+
+ if (mx >= _currentWidth)
+ mx = _currentWidth - 1;
+
+ if (my < 0)
+ my = 0;
+
+ if (my >= _currentHeight)
+ my = _currentHeight - 1;
+
+ if ((mx != _mouseX) || (my != _mouseY)) {
+ event.type = Common::EVENT_MOUSEMOVE;
+ event.mouse.x = _mouseX = mx;
+ event.mouse.y = _mouseY = my;
+
+ return true;
+ }
+ }
+ }
+#endif
+
+ uint32 time = getMillis();
+ if (time - _lastPadCheck > PAD_CHECK_TIME) {
+ _lastPadCheck = time;
+
+ if (abs (PAD_StickX(0)) > 16)
+ mx += PAD_StickX(0) / (4 * _overlayWidth / _currentWidth);
+ if (abs (PAD_StickY(0)) > 16)
+ my -= PAD_StickY(0) / (4 * _overlayHeight / _currentHeight);
+
+ if (mx < 0)
+ mx = 0;
+
+ if (mx >= _currentWidth)
+ mx = _currentWidth - 1;
+
+ if (my < 0)
+ my = 0;
+
+ if (my >= _currentHeight)
+ my = _currentHeight - 1;
+
+ if ((mx != _mouseX) || (my != _mouseY)) {
+ event.type = Common::EVENT_MOUSEMOVE;
+ event.mouse.x = _mouseX = mx;
+ event.mouse.y = _mouseY = my;
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
diff --git a/backends/platform/wii/osystem_gfx.cpp b/backends/platform/wii/osystem_gfx.cpp
new file mode 100644
index 0000000000..1e54233c93
--- /dev/null
+++ b/backends/platform/wii/osystem_gfx.cpp
@@ -0,0 +1,453 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <malloc.h>
+
+#include "osystem.h"
+#include "gx_supp.h"
+
+#define MAX_FPS 30
+
+enum GraphicModeID {
+ GM_DEFAULT
+};
+
+void OSystem_Wii::initGfx() {
+ _surface.w = 0;
+ _surface.h = 0;
+ _surface.pitch = 0;
+ _surface.pixels = NULL;
+ _surface.bytesPerPixel = 0;
+
+ GX_InitVideo();
+
+ _overlayWidth = 640;
+ _overlayHeight = 480;
+
+ _overlaySize = _overlayWidth * _overlayHeight * 2;
+ _overlayPixels = (OverlayColor *) memalign(32, _overlaySize);
+
+ _palette = (u16 *) memalign(32, 256 * 2);
+ memset(_palette, 0, 256 * 2);
+
+ _cursorPalette = (u16 *) memalign(32, 256 * 2);
+ memset(_cursorPalette, 0, 256 * 2);
+
+ _supportedGraphicsModes = new OSystem::GraphicsMode[2];
+ _supportedGraphicsModes[0].name = strdup("gx");
+ _supportedGraphicsModes[0].description = strdup("wii hardware scaler");
+ _supportedGraphicsModes[0].id = GM_DEFAULT;
+ _supportedGraphicsModes[1].name = 0;
+ _supportedGraphicsModes[1].description = 0;
+ _supportedGraphicsModes[1].id = 0;
+
+ _texture = (u16 *) memalign(32, _overlaySize);
+
+ GX_Start(_overlayWidth, _overlayHeight, 320, 240);
+}
+
+void OSystem_Wii::deinitGfx() {
+ GX_AbortFrame();
+
+ if (_supportedGraphicsModes) {
+ delete[] _supportedGraphicsModes;
+ _supportedGraphicsModes = NULL;
+ }
+
+ if (_gamePixels) {
+ free(_gamePixels);
+ _gamePixels = NULL;
+ }
+
+ if (_palette) {
+ free(_palette);
+ _palette = NULL;
+ }
+
+ if (_overlayPixels) {
+ free(_overlayPixels);
+ _overlayPixels = NULL;
+ }
+
+ if (_mouseCursor) {
+ free(_mouseCursor);
+ _mouseCursor = NULL;
+ }
+
+ if (_cursorPalette) {
+ free(_cursorPalette);
+ _cursorPalette = NULL;
+ }
+
+ if (_texture) {
+ free(_texture);
+ _texture = NULL;
+ }
+}
+
+const OSystem::GraphicsMode* OSystem_Wii::getSupportedGraphicsModes() const {
+ return _supportedGraphicsModes;
+}
+
+int OSystem_Wii::getDefaultGraphicsMode() const {
+ return GM_DEFAULT;
+}
+
+bool OSystem_Wii::setGraphicsMode(const char *mode) {
+ setGraphicsMode(GM_DEFAULT);
+
+ return true;
+}
+
+bool OSystem_Wii::setGraphicsMode(int mode) {
+ return true;
+}
+
+int OSystem_Wii::getGraphicsMode() const {
+ return _activeGraphicsMode;
+}
+
+void OSystem_Wii::initSize(uint width, uint height) {
+ if (_gameWidth != width || _gameHeight != height) {
+ printf("initSize %u %u\n", width, height);
+
+ _gameWidth = width;
+ _gameHeight = height;
+
+ if(_gamePixels)
+ free(_gamePixels);
+
+ _gamePixels = (u8 *) memalign(32, _gameWidth * _gameHeight);
+
+ if (!_overlayVisible) {
+ _currentWidth = _gameWidth;
+ _currentHeight = _gameHeight;
+ updateEventScreenResolution();
+ }
+ }
+}
+
+int16 OSystem_Wii::getWidth() {
+ return _gameWidth;
+}
+
+int16 OSystem_Wii::getHeight() {
+ return _gameHeight;
+}
+
+void OSystem_Wii::setPalette(const byte *colors, uint start, uint num) {
+ const byte *p = colors;
+ for (uint i = 0; i < num; ++i) {
+ _palette[start + i] = RGBToColor(p[0], p[1], p[2]);
+ p += 4;
+ }
+}
+
+void OSystem_Wii::grabPalette(byte *colors, uint start, uint num) {
+ byte *p = colors;
+ u8 r, g, b;
+ for (uint i = 0; i < num; ++i) {
+ colorToRGB(_palette[start + i], r, g, b);
+ p[0] = r;
+ p[1] = g;
+ p[2] = b;
+ p[3] = 0xff;
+ p += 4;
+ }
+}
+
+void OSystem_Wii::setCursorPalette(const byte *colors, uint start, uint num) {
+ const byte *p = colors;
+ for (uint i = 0; i < num; ++i) {
+ _cursorPalette[start + i] = RGBToColor(p[0], p[1], p[2]);
+ p += 4;
+ }
+
+ _cursorPaletteDisabled = false;
+}
+
+void OSystem_Wii::disableCursorPalette(bool disable) {
+ _cursorPaletteDisabled = disable;
+}
+
+void OSystem_Wii::copyRectToScreen(const byte *buf, int pitch, int x, int y,
+ int w, int h) {
+ if (x < 0) {
+ w += x;
+ buf -= x;
+ x = 0;
+ }
+
+ if (y < 0) {
+ h += y;
+ buf -= y * pitch;
+ y = 0;
+ }
+
+ if (w > _gameWidth - x)
+ w = _gameWidth - x;
+
+ if (h > _gameHeight - y)
+ h = _gameHeight - y;
+
+ if (w <= 0 || h <= 0)
+ return;
+
+ byte *dst = _gamePixels + y * _gameWidth + x;
+ if (_gameWidth == pitch && pitch == w) {
+ memcpy(dst, buf, h * w);
+ } else {
+ do {
+ memcpy(dst, buf, w);
+ buf += pitch;
+ dst += _gameWidth;
+ } while (--h);
+ }
+}
+
+void OSystem_Wii::updateScreen() {
+ static u32 x, y, h, skip;
+ static s16 msx, msy, mox, moy, mskip;
+ static u16 mpx, mpy;
+ static u8 *s;
+ static u16 *d, *p;
+
+ u32 now = getMillis();
+ if (now - _lastScreenUpdate < 1000 / MAX_FPS)
+ return;
+
+ _lastScreenUpdate = now;
+
+ h = 0;
+ if (_overlayVisible) {
+ memcpy(_texture, _overlayPixels, _overlaySize);
+ } else {
+ for (y = 0; y < _gameHeight; ++y) {
+ for (x = 0; x < _gameWidth; ++x)
+ _texture[h + x] = _palette[_gamePixels[h + x]];
+
+ h += _gameWidth;
+ }
+ }
+
+ if (_mouseVisible) {
+ msx = _mouseX - _mouseHotspotX;
+ msy = _mouseY - _mouseHotspotY;
+ mox = 0;
+ moy = 0;
+ mpx = _mouseWidth;
+ mpy = _mouseHeight;
+
+ if (msx < 0) {
+ mox = -msx;
+ mpx -= mox;
+ msx = 0;
+ } else
+ if (msx + mpx > _currentWidth - 1)
+ mpx = _currentWidth - msx - 1;
+
+ if (msy < 0) {
+ moy = -msy;
+ mpy -= moy;
+ msy = 0;
+ } else
+ if (msy + mpy + 1 > _currentHeight - 1)
+ mpy = _currentHeight - msy - 1;
+
+
+ if (_cursorPaletteDisabled)
+ p = _palette;
+ else
+ p = _cursorPalette;
+
+ skip = _currentWidth - mpx;
+ mskip = _mouseWidth - mpx;
+
+ s = _mouseCursor + moy * _mouseWidth + mox;
+ d = _texture + (msy * _currentWidth + msx);
+
+ for (y = 0; y < mpy; ++y) {
+ for (x = 0; x < mpx; ++x) {
+ if (*s == _mouseKeyColor) {
+ s++;
+ d++;
+
+ continue;
+ }
+
+ *d++ = p[*s];
+ s++;
+ }
+
+ d += skip;
+ s += mskip;
+ }
+ }
+
+ GX_Render(_currentWidth, _currentHeight, (u8 *) _texture,
+ _currentWidth * 2);
+}
+
+Graphics::Surface *OSystem_Wii::lockScreen() {
+ _surface.pixels = _gamePixels;
+ _surface.w = _gameWidth;
+ _surface.h = _gameHeight;
+ _surface.pitch = _gameWidth;
+ _surface.bytesPerPixel = 1;
+
+ return &_surface;
+}
+
+void OSystem_Wii::unlockScreen() {
+}
+
+void OSystem_Wii::setShakePos(int shakeOffset) {
+}
+
+void OSystem_Wii::showOverlay() {
+ _mouseX = _overlayWidth / 2;
+ _mouseY = _overlayHeight / 2;
+ _overlayVisible = true;
+ _currentWidth = _overlayWidth;
+ _currentHeight = _overlayHeight;
+
+ updateEventScreenResolution();
+}
+
+void OSystem_Wii::hideOverlay() {
+ _mouseX = _gameWidth / 2;
+ _mouseY = _gameHeight / 2;
+ _overlayVisible = false;
+ _currentWidth = _gameWidth;
+ _currentHeight = _gameHeight;
+
+ updateEventScreenResolution();
+}
+
+void OSystem_Wii::clearOverlay() {
+ memset(_overlayPixels, 0, _overlaySize);
+}
+
+void OSystem_Wii::grabOverlay(OverlayColor *buf, int pitch) {
+ int h = _overlayHeight;
+ OverlayColor *src = _overlayPixels;
+
+ do {
+ memcpy(buf, src, _overlayWidth * sizeof(OverlayColor));
+ src += _overlayWidth;
+ buf += pitch;
+ } while (--h);
+}
+
+void OSystem_Wii::copyRectToOverlay(const OverlayColor *buf, int pitch, int x,
+ int y, int w, int h) {
+ if (x < 0) {
+ w += x;
+ buf -= x;
+ x = 0;
+ }
+
+ if (y < 0) {
+ h += y;
+ buf -= y * pitch;
+ y = 0;
+ }
+
+ if (w > _overlayWidth - x)
+ w = _overlayWidth - x;
+
+ if (h > _overlayHeight - y)
+ h = _overlayHeight - y;
+
+ if (w <= 0 || h <= 0)
+ return;
+
+ OverlayColor *dst = _overlayPixels + (y * _overlayWidth + x);
+ if (_overlayWidth == pitch && pitch == w) {
+ memcpy(dst, buf, h * w * sizeof(OverlayColor));
+ } else {
+ do {
+ memcpy(dst, buf, w * sizeof(OverlayColor));
+ buf += pitch;
+ dst += _overlayWidth;
+ } while (--h);
+ }
+}
+
+int16 OSystem_Wii::getOverlayWidth() {
+ return _overlayWidth;
+}
+
+int16 OSystem_Wii::getOverlayHeight() {
+ return _overlayHeight;
+}
+
+OverlayColor OSystem_Wii::RGBToColor(uint8 r, uint8 g, uint8 b) {
+ return (((r >> 3) & 0x1f) << 11) | (((g >> 2) & 0x3f) << 5 ) |
+ ((b >> 3) & 0x1f);
+}
+
+void OSystem_Wii::colorToRGB(OverlayColor color, uint8 &r, uint8 &g, uint8 &b) {
+ r = ((color >> 11) & 0x1f) << 3;
+ g = ((color >> 5) & 0x3f) << 2;
+ b = (color & 0x1f) << 3;
+}
+
+OverlayColor OSystem_Wii::ARGBToColor(uint8 a, uint8 r, uint8 g, uint8 b) {
+ return RGBToColor(r, g, b);
+}
+
+void OSystem_Wii::colorToARGB(OverlayColor color, uint8 &a, uint8 &r, uint8 &g,
+ uint8 &b) {
+ a = 0xff;
+ colorToRGB(color, r, g, b);
+}
+
+bool OSystem_Wii::showMouse(bool visible) {
+ bool last = _mouseVisible;
+ _mouseVisible = visible;
+
+ return last;
+}
+
+void OSystem_Wii::warpMouse(int x, int y) {
+ _mouseX = x;
+ _mouseY = y;
+}
+
+void OSystem_Wii::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX,
+ int hotspotY, byte keycolor,
+ int cursorTargetScale) {
+ (void) cursorTargetScale; // TODO
+
+ _mouseWidth = w;
+ _mouseHeight = h;
+ _mouseHotspotX = hotspotX;
+ _mouseHotspotY = hotspotY;
+ _mouseKeyColor = keycolor;
+
+ if (_mouseCursor)
+ free(_mouseCursor);
+
+ _mouseCursor = (u8 *) memalign(32, w * h);
+ memcpy(_mouseCursor, buf, w * h);
+}
+
diff --git a/backends/platform/wii/osystem_sfx.cpp b/backends/platform/wii/osystem_sfx.cpp
new file mode 100644
index 0000000000..16b2f3b055
--- /dev/null
+++ b/backends/platform/wii/osystem_sfx.cpp
@@ -0,0 +1,133 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <malloc.h>
+
+#include "osystem.h"
+
+#define SFX_THREAD_STACKSIZE (1024 * 128)
+#define SFX_THREAD_PRIO 80
+#define SFX_THREAD_FRAG_SIZE 4096
+
+static lwpq_t sfx_queue;
+static lwp_t sfx_thread;
+static u8 *sfx_stack;
+static bool sfx_thread_running = false;
+static bool sfx_thread_quit = false;
+
+static u8 sb = 0;
+static u8 *sound_buffer[2];
+
+static OSystem_Wii::SoundProc sound_proc = NULL;
+static void *proc_param = NULL;
+
+static void audio_switch_buffers() {
+ AUDIO_StopDMA();
+ AUDIO_InitDMA((u32) sound_buffer[sb], SFX_THREAD_FRAG_SIZE);
+ AUDIO_StartDMA();
+
+ LWP_ThreadSignal(sfx_queue);
+}
+
+static void * sfx_thread_func(void *arg) {
+ u8 next_sb;
+
+ while (true) {
+ LWP_ThreadSleep(sfx_queue);
+
+ if (sfx_thread_quit)
+ break;
+
+ next_sb = sb ^ 1;
+ sound_proc(proc_param, sound_buffer[next_sb], SFX_THREAD_FRAG_SIZE);
+ DCFlushRange(sound_buffer[next_sb], SFX_THREAD_FRAG_SIZE);
+
+ sb = next_sb;
+ }
+
+ return NULL;
+}
+
+void OSystem_Wii::initSfx() {
+ sfx_thread_running = false;
+ sfx_thread_quit = false;
+
+ sfx_stack = (u8 *) memalign(32, SFX_THREAD_STACKSIZE);
+ memset(sfx_stack, 0, SFX_THREAD_STACKSIZE);
+
+ LWP_InitQueue(&sfx_queue);
+
+ s32 res = LWP_CreateThread(&sfx_thread, sfx_thread_func, NULL, sfx_stack,
+ SFX_THREAD_STACKSIZE, SFX_THREAD_PRIO);
+
+ if (res) {
+ printf("ERROR creating sfx thread: %d\n", res);
+ LWP_CloseQueue(sfx_queue);
+ return;
+ }
+
+ sfx_thread_running = true;
+
+ sound_buffer[0] = (u8 *) memalign(32, SFX_THREAD_FRAG_SIZE);
+ sound_buffer[1] = (u8 *) memalign(32, SFX_THREAD_FRAG_SIZE);
+
+ memset(sound_buffer[0], 0, SFX_THREAD_FRAG_SIZE);
+ memset(sound_buffer[1], 0, SFX_THREAD_FRAG_SIZE);
+
+ DCFlushRange(sound_buffer[0], SFX_THREAD_FRAG_SIZE);
+ DCFlushRange(sound_buffer[1], SFX_THREAD_FRAG_SIZE);
+
+ sound_proc = Audio::Mixer::mixCallback;
+ proc_param = _mixer;
+
+ _mixer->setReady(true);
+
+ AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ);
+ AUDIO_RegisterDMACallback(audio_switch_buffers);
+
+ audio_switch_buffers();
+}
+
+void OSystem_Wii::deinitSfx() {
+ if (_mixer)
+ _mixer->setReady(false);
+
+ AUDIO_StopDMA();
+ AUDIO_RegisterDMACallback(NULL);
+
+ if (sfx_thread_running) {
+ sfx_thread_quit = true;
+ LWP_ThreadBroadcast(sfx_queue);
+
+ LWP_JoinThread(sfx_thread, NULL);
+ LWP_CloseQueue(sfx_queue);
+
+ sfx_thread_running = false;
+
+ free(sound_buffer[0]);
+ free(sound_buffer[1]);
+ }
+}
+
+int OSystem_Wii::getOutputSampleRate() const {
+ return 48000;
+}
+