From 0b002beccd31fa2796a319427624af1b2ad580b6 Mon Sep 17 00:00:00 2001 From: Andre Heider Date: Sat, 5 Sep 2009 17:53:55 +0000 Subject: Support for SMB shares, cleaned up async FS functions. svn-id: r43965 --- backends/fs/wii/wii-fs-factory.cpp | 161 +++++++++++++++++++++++++++++++++- backends/fs/wii/wii-fs-factory.h | 39 +++++++- backends/fs/wii/wii-fs.cpp | 67 ++------------ backends/platform/wii/main.cpp | 9 -- backends/platform/wii/options.cpp | 136 ++++++++++++++++++++++++++-- backends/platform/wii/options.h | 16 ++++ backends/platform/wii/osystem.cpp | 42 ++++++++- backends/platform/wii/osystem_gfx.cpp | 22 ----- configure | 3 +- 9 files changed, 388 insertions(+), 107 deletions(-) diff --git a/backends/fs/wii/wii-fs-factory.cpp b/backends/fs/wii/wii-fs-factory.cpp index c9513f7784..4595e93555 100644 --- a/backends/fs/wii/wii-fs-factory.cpp +++ b/backends/fs/wii/wii-fs-factory.cpp @@ -27,8 +27,22 @@ #include "backends/fs/wii/wii-fs-factory.h" #include "backends/fs/wii/wii-fs.cpp" +#ifdef USE_WII_DI +#include +#endif + +#ifdef USE_WII_SMB +#include +#include +#endif + DECLARE_SINGLETON(WiiFilesystemFactory); +WiiFilesystemFactory::WiiFilesystemFactory() : + _dvdMounted(false), + _smbMounted(false) { +} + AbstractFSNode *WiiFilesystemFactory::makeRootFileNode() const { return new WiiFilesystemNode(); } @@ -46,8 +60,151 @@ AbstractFSNode *WiiFilesystemFactory::makeFileNodePath(const Common::String &pat return new WiiFilesystemNode(path); } -void WiiFilesystemFactory::asyncHandler(bool mount, const Common::String *path) { - WiiFilesystemNode::asyncHandler(mount, path); +void WiiFilesystemFactory::asyncInit() { +#ifdef USE_WII_SMB + asyncInitNetwork(); +#endif +} + +void WiiFilesystemFactory::asyncDeinit() { +#ifdef USE_WII_DI + umount(kDVD); + DI_Close(); +#endif +#ifdef USE_WII_SMB + umount(kSMB); + net_deinit(); +#endif +} + +#ifdef USE_WII_SMB +void WiiFilesystemFactory::asyncInitNetwork() { + net_init_async(NULL, NULL); +} + +void WiiFilesystemFactory::setSMBLoginData(const String &server, + const String &share, + const String &username, + const String &password) { + _smbServer = server; + _smbShare = share; + _smbUsername = username; + _smbPassword = password; +} +#endif + +bool WiiFilesystemFactory::isMounted(FileSystemType type) { + switch (type) { + case kDVD: + return _dvdMounted; + case kSMB: + return _smbMounted; + } + + return false; +} + +void WiiFilesystemFactory::mount(FileSystemType type) { + switch (type) { + case kDVD: +#ifdef USE_WII_DI + if (_dvdMounted) + break; + + printf("mount dvd\n"); + DI_Mount(); + + while (DI_GetStatus() & DVD_INIT) + usleep(20 * 1000); + + if (!(DI_GetStatus() & DVD_READY)) { + DI_StopMotor(); + printf("error mounting dvd\n"); + break; + } + + printf("mount ISO9660\n"); + if (ISO9660_Mount()) { + _dvdMounted = true; + printf("ISO9660 mounted\n"); + } else { + DI_StopMotor(); + printf("ISO9660 mount failed\n"); + } +#endif + break; + + case kSMB: +#ifdef USE_WII_SMB + if (_smbMounted) + break; + + printf("mount smb\n"); + + if (net_get_status()) { + printf("network not inited\n"); + break; + } + + if (smbInit(_smbUsername.c_str(), _smbPassword.c_str(), + _smbShare.c_str(), _smbServer.c_str())) { + _smbMounted = true; + printf("smb mounted\n"); + } else { + printf("error mounting smb\n"); + } +#endif + break; + } +} + +void WiiFilesystemFactory::umount(FileSystemType type) { + switch (type) { + case kDVD: +#ifdef USE_WII_DI + if (!_dvdMounted) + break; + + printf("umount dvd\n"); + + ISO9660_Unmount(); + DI_StopMotor(); + + _dvdMounted = false; +#endif + break; + + case kSMB: +#ifdef USE_WII_SMB + if (!_smbMounted) + break; + + printf("umount smb\n"); + + if (smbClose("smb:")) + printf("smb umounted\n"); + else + printf("error umounting smb\n"); + + _smbMounted = false; +#endif + break; + } +} + +void WiiFilesystemFactory::mountByPath(const String &path) { + if (path.hasPrefix("dvd:/")) + mount(kDVD); + else if (path.hasPrefix("smb:/")) + mount(kSMB); +} + +void WiiFilesystemFactory::umountUnused(const String &path) { + if (!path.hasPrefix("dvd:/")) + umount(kDVD); + + if (!path.hasPrefix("smb:/")) + umount(kSMB); } #endif diff --git a/backends/fs/wii/wii-fs-factory.h b/backends/fs/wii/wii-fs-factory.h index f58371d194..0e7f87a783 100644 --- a/backends/fs/wii/wii-fs-factory.h +++ b/backends/fs/wii/wii-fs-factory.h @@ -23,9 +23,12 @@ #ifndef _WII_FILESYSTEM_FACTORY_H_ #define _WII_FILESYSTEM_FACTORY_H_ +#include "common/str.h" #include "common/singleton.h" #include "backends/fs/fs-factory.h" +#include + /** * Creates WiiFilesystemNode objects. * @@ -33,17 +36,49 @@ */ class WiiFilesystemFactory : public FilesystemFactory, public Common::Singleton { public: + typedef Common::String String; + + enum FileSystemType { + kDVD, + kSMB + }; + virtual AbstractFSNode *makeRootFileNode() const; virtual AbstractFSNode *makeCurrentDirectoryFileNode() const; virtual AbstractFSNode *makeFileNodePath(const Common::String &path) const; - static void asyncHandler(bool mount, const Common::String *path); + void asyncInit(); + void asyncDeinit(); + +#ifdef USE_WII_SMB + void asyncInitNetwork(); + void setSMBLoginData(const String &server, const String &share, + const String &username, const String &password); +#endif + + bool isMounted(FileSystemType type); + + void mount(FileSystemType type); + void umount(FileSystemType type); + + void mountByPath(const String &path); + void umountUnused(const String &path); protected: - WiiFilesystemFactory() {}; + WiiFilesystemFactory(); private: friend class Common::Singleton; + + bool _dvdMounted; + bool _smbMounted; + +#ifdef USE_WII_SMB + String _smbServer; + String _smbShare; + String _smbUsername; + String _smbPassword; +#endif }; #endif /*Wii_FILESYSTEM_FACTORY_H*/ diff --git a/backends/fs/wii/wii-fs.cpp b/backends/fs/wii/wii-fs.cpp index 7a144cddbf..e6ba2a4aa0 100644 --- a/backends/fs/wii/wii-fs.cpp +++ b/backends/fs/wii/wii-fs.cpp @@ -29,14 +29,11 @@ #include #include #include +#include #include #include -#ifdef USE_WII_DI -#include -#endif - /** * Implementation of the ScummVM file system API based on Wii. * @@ -81,60 +78,8 @@ public: virtual Common::SeekableReadStream *createReadStream(); virtual Common::WriteStream *createWriteStream(); - - static void asyncHandler(bool umount, const Common::String *path); }; -void WiiFilesystemNode::asyncHandler(bool mount, const Common::String *path) { -#ifdef USE_WII_DI - static bool di_tryMount = true; - static bool di_isMounted = false; - - // umount not required filesystems - if (!mount) { - if (di_isMounted && (!path || (path && !path->hasPrefix("dvd:/")))) { - printf("umount ISO9660\n"); - ISO9660_Unmount(); - DI_StopMotor(); - di_tryMount = false; - di_isMounted = false; - } - - if (!path) - return; - } - - // re-mount DVD if data from its path has been requested. in this case, we - // have to wait for DI_Mount() to finish - if (!di_tryMount && !di_isMounted && path && path->hasPrefix("dvd:/")) { - printf("remount ISO9660\n"); - DI_Mount(); - - while (DI_GetStatus() & DVD_INIT) - usleep(20 * 1000); - - di_tryMount = true; - } - - if (!di_tryMount) - return; - - // check if the async DI_Mount() call has finished - if (DI_GetStatus() & DVD_READY) { - di_tryMount = false; - - printf("mount ISO9660\n"); - if (ISO9660_Mount()) { - di_isMounted = true; - printf("ISO9660 mounted\n"); - } else { - DI_StopMotor(); - printf("ISO9660 mount failed\n"); - } - } -#endif -} - // gets all registered devoptab devices bool WiiFilesystemNode::getDevopChildren(AbstractFSList &list, ListMode mode, bool hidden) const { u8 i; @@ -143,8 +88,6 @@ bool WiiFilesystemNode::getDevopChildren(AbstractFSList &list, ListMode mode, bo if (mode == Common::FSNode::kListFilesOnly) return true; - asyncHandler(true, NULL); - // skip in, out and err for (i = 3; i < STD_MAX; ++i) { dt = devoptab_list[i]; @@ -194,14 +137,14 @@ WiiFilesystemNode::WiiFilesystemNode(const Common::String &p) { _path = Common::normalizePath(p, '/'); - // "fat:" is not a valid directory, but "fat:/" is + WiiFilesystemFactory::instance().mountByPath(_path); + + // "sd:" is not a valid directory, but "sd:/" is if (_path.lastChar() == ':') _path += '/'; _displayName = lastPathComponent(_path, '/'); - asyncHandler(true, &_path); - struct stat st; if (!stat(_path.c_str(), &st)) setFlags(&st); @@ -217,7 +160,7 @@ WiiFilesystemNode::WiiFilesystemNode(const Common::String &p, const struct stat _path = Common::normalizePath(p, '/'); - // "fat:" is not a valid directory, but "fat:/" is + // "sd:" is not a valid directory, but "sd:/" is if (_path.lastChar() == ':') _path += '/'; diff --git a/backends/platform/wii/main.cpp b/backends/platform/wii/main.cpp index 801778395f..e0115c99ef 100644 --- a/backends/platform/wii/main.cpp +++ b/backends/platform/wii/main.cpp @@ -112,11 +112,6 @@ int main(int argc, char *argv[]) { SYS_SetPowerCallback(power_cb); #endif -#ifdef USE_WII_DI - // initial async mount for the browser, see wii-fs.cpp - DI_Mount(); -#endif - if (!fatInitDefault()) { printf("fatInitDefault failed\n"); } else { @@ -144,10 +139,6 @@ int main(int argc, char *argv[]) { fatUnmountDefault(); -#ifdef USE_WII_DI - DI_Close(); -#endif - if (power_btn_pressed) { printf("shutting down\n"); SYS_ResetSystem(SYS_POWEROFF, 0, 0); diff --git a/backends/platform/wii/options.cpp b/backends/platform/wii/options.cpp index f8b70804d0..1e35a23005 100644 --- a/backends/platform/wii/options.cpp +++ b/backends/platform/wii/options.cpp @@ -20,15 +20,18 @@ * */ +#include + #include "common/config-manager.h" #include "gui/dialog.h" #include "gui/TabWidget.h" +#include "backends/fs/wii/wii-fs-factory.h" #include "options.h" #include "gfx.h" WiiOptionsDialog::WiiOptionsDialog(bool doubleStrike) : - Dialog(180, 120, 304, 200), + Dialog((640 - 400) / 2, (480 - 340) / 2, 400, 340), _doubleStrike(doubleStrike) { if (_doubleStrike) { @@ -39,12 +42,12 @@ WiiOptionsDialog::WiiOptionsDialog(bool doubleStrike) : _strUnderscanY = "wii_video_default_underscan_y"; } - new ButtonWidget(this, 56, 160, 108, 24, "Cancel", 'c'); - new ButtonWidget(this, 180, 160, 108, 24, "Ok", 'k'); + new ButtonWidget(this, _w - 108 - 16, _h - 24 - 16, 108, 24, "Ok", 'k'); + new ButtonWidget(this, _w - 216 - 32, _h - 24 - 16, 108, 24, "Cancel", 'c'); - TabWidget *tab = new TabWidget(this, 0, 0, 304, 146); + TabWidget *tab = new TabWidget(this, 0, 0, _w, _h - 54); - tab->addTab("Video"); + int tabVideo = tab->addTab("Video"); new StaticTextWidget(tab, 16, 16, 128, 16, "Current video mode:", Graphics::kTextAlignRight); @@ -64,14 +67,86 @@ WiiOptionsDialog::WiiOptionsDialog(bool doubleStrike) : _sliderUnderscanY->setMinValue(0); _sliderUnderscanY->setMaxValue(32); +#ifdef USE_WII_DI + tab->addTab("DVD"); + + new StaticTextWidget(tab, 16, 16, 64, 16, + "Status:", Graphics::kTextAlignRight); + _textDVDStatus = new StaticTextWidget(tab, 96, 16, 192, 16, "Unknown", + Graphics::kTextAlignLeft); + + new ButtonWidget(tab, 16, 48, 108, 24, "Mount DVD", 'mdvd'); + new ButtonWidget(tab, 140, 48, 108, 24, "Unmount DVD", 'udvd'); +#endif + +#ifdef USE_WII_SMB + tab->addTab("SMB"); + + new StaticTextWidget(tab, 16, 16, 64, 16, + "Status:", Graphics::kTextAlignRight); + _textSMBStatus = new StaticTextWidget(tab, 96, 16, 192, 16, "Unknown", + Graphics::kTextAlignLeft); + + new StaticTextWidget(tab, 16, 52, 64, 16, + "Server:", Graphics::kTextAlignRight); + _editSMBServer = new EditTextWidget(tab, 96, 48, _w - 96 - 32, 24, ""); + + new StaticTextWidget(tab, 16, 92, 64, 16, + "Share:", Graphics::kTextAlignRight); + _editSMBShare = new EditTextWidget(tab, 96, 88, _w - 96 - 32, 24, ""); + + new StaticTextWidget(tab, 16, 132, 64, 16, + "Username:", Graphics::kTextAlignRight); + _editSMBUsername = new EditTextWidget(tab, 96, 128, _w - 96 - 32, 24, ""); + + new StaticTextWidget(tab, 16, 172, 64, 16, + "Password:", Graphics::kTextAlignRight); + _editSMBPassword = new EditTextWidget(tab, 96, 168, _w - 96 - 32, 24, ""); + + new ButtonWidget(tab, 16, 208, 108, 24, "Init network", 'net'); + + new ButtonWidget(tab, 140, 208, 108, 24, "Mount SMB", 'msmb'); + new ButtonWidget(tab, 264, 208, 108, 24, "Unmount SMB", 'usmb'); +#endif + + tab->setActiveTab(tabVideo); + load(); } WiiOptionsDialog::~WiiOptionsDialog() { } +void WiiOptionsDialog::handleTickle() { +#ifdef USE_WII_DI + if (WiiFilesystemFactory::instance().isMounted(WiiFilesystemFactory::kDVD)) + _textDVDStatus->setLabel("Mounted"); + else + _textDVDStatus->setLabel("Not mounted"); +#endif +#ifdef USE_WII_SMB + s32 net = net_get_status(); + String label; + + if (net) { + label = String::printf("Network not initialsed (%d)\n", net); + } else { + if (WiiFilesystemFactory::instance().isMounted(WiiFilesystemFactory::kSMB)) + label = "Mounted"; + else + label = "Not mounted"; + } + + _textSMBStatus->setLabel(label); +#endif + + Dialog::handleTickle(); +} + void WiiOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { + WiiFilesystemFactory &fsf = WiiFilesystemFactory::instance(); + switch (cmd) { case 'x': case 'y': @@ -89,6 +164,34 @@ void WiiOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, close(); break; +#ifdef USE_WII_DI + case 'mdvd': + fsf.mount(WiiFilesystemFactory::kDVD); + break; + + case 'udvd': + fsf.umount(WiiFilesystemFactory::kDVD); + break; +#endif + +#ifdef USE_WII_SMB + case 'net': + fsf.asyncInitNetwork(); + break; + + case 'msmb': + fsf.setSMBLoginData(_editSMBServer->getEditString(), + _editSMBShare->getEditString(), + _editSMBUsername->getEditString(), + _editSMBPassword->getEditString()); + fsf.mount(WiiFilesystemFactory::kSMB); + break; + + case 'usmb': + fsf.umount(WiiFilesystemFactory::kSMB); + break; +#endif + default: Dialog::handleCommand(sender, cmd, data); break; @@ -110,6 +213,17 @@ void WiiOptionsDialog::load() { _sliderUnderscanX->setValue(x); _sliderUnderscanY->setValue(y); + +#ifdef USE_WII_SMB + _editSMBServer->setEditString(ConfMan.get("wii_smb_server", + Common::ConfigManager::kApplicationDomain)); + _editSMBShare->setEditString(ConfMan.get("wii_smb_share", + Common::ConfigManager::kApplicationDomain)); + _editSMBUsername->setEditString(ConfMan.get("wii_smb_username", + Common::ConfigManager::kApplicationDomain)); + _editSMBPassword->setEditString(ConfMan.get("wii_smb_password", + Common::ConfigManager::kApplicationDomain)); +#endif } void WiiOptionsDialog::save() { @@ -119,6 +233,18 @@ void WiiOptionsDialog::save() { ConfMan.setInt(_strUnderscanY, _sliderUnderscanY->getValue(), Common::ConfigManager::kApplicationDomain); + +#ifdef USE_WII_SMB + ConfMan.set("wii_smb_server", _editSMBServer->getEditString(), + Common::ConfigManager::kApplicationDomain); + ConfMan.set("wii_smb_share", _editSMBShare->getEditString(), + Common::ConfigManager::kApplicationDomain); + ConfMan.set("wii_smb_username", _editSMBUsername->getEditString(), + Common::ConfigManager::kApplicationDomain); + ConfMan.set("wii_smb_password", _editSMBPassword->getEditString(), + Common::ConfigManager::kApplicationDomain); +#endif + ConfMan.flushToDisk(); } diff --git a/backends/platform/wii/options.h b/backends/platform/wii/options.h index 83c8ddd0d6..3e84933efd 100644 --- a/backends/platform/wii/options.h +++ b/backends/platform/wii/options.h @@ -25,6 +25,7 @@ #include "common/str.h" #include "gui/dialog.h" +#include "gui/EditTextWidget.h" using namespace GUI; @@ -35,6 +36,8 @@ public: WiiOptionsDialog(bool doubleStrike); virtual ~WiiOptionsDialog(); +protected: + virtual void handleTickle(); virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data); private: @@ -45,6 +48,19 @@ private: SliderWidget *_sliderUnderscanX; SliderWidget *_sliderUnderscanY; +#ifdef USE_WII_DI + StaticTextWidget *_textDVDStatus; +#endif + +#ifdef USE_WII_SMB + StaticTextWidget *_textNetworkStatus; + StaticTextWidget *_textSMBStatus; + EditTextWidget *_editSMBServer; + EditTextWidget *_editSMBShare; + EditTextWidget *_editSMBUsername; + EditTextWidget *_editSMBPassword; +#endif + void revert(); void load(); void save(); diff --git a/backends/platform/wii/osystem.cpp b/backends/platform/wii/osystem.cpp index 39c6b9df53..a32752104b 100644 --- a/backends/platform/wii/osystem.cpp +++ b/backends/platform/wii/osystem.cpp @@ -23,6 +23,7 @@ #include "backends/fs/wii/wii-fs-factory.h" #include "osystem.h" +#include "options.h" #include @@ -103,6 +104,28 @@ OSystem_Wii::~OSystem_Wii() { void OSystem_Wii::initBackend() { _startup_time = gettime(); + ConfMan.registerDefault("fullscreen", true); + ConfMan.registerDefault("aspect_ratio", true); + ConfMan.registerDefault("wii_video_default_underscan_x", 16); + ConfMan.registerDefault("wii_video_default_underscan_y", 16); + ConfMan.registerDefault("wii_video_ds_underscan_x", 16); + ConfMan.registerDefault("wii_video_ds_underscan_y", 16); + ConfMan.registerDefault("wii_smb_server", ""); + ConfMan.registerDefault("wii_smb_share", ""); + ConfMan.registerDefault("wii_smb_username", ""); + ConfMan.registerDefault("wii_smb_password", ""); + + WiiFilesystemFactory &fsf = WiiFilesystemFactory::instance(); + +#ifdef USE_WII_SMB + fsf.setSMBLoginData(ConfMan.get("wii_smb_server"), + ConfMan.get("wii_smb_share"), + ConfMan.get("wii_smb_username"), + ConfMan.get("wii_smb_password")); +#endif + + fsf.asyncInit(); + char buf[MAXPATHLEN]; if (!getcwd(buf, MAXPATHLEN)) strcpy(buf, "/"); @@ -123,14 +146,12 @@ void OSystem_Wii::quit() { deinitSfx(); deinitGfx(); - // umount all async filesystems - WiiFilesystemFactory::asyncHandler(false, NULL); + WiiFilesystemFactory::instance().asyncDeinit(); } void OSystem_Wii::engineInit() { _gameRunning = true; - // umount not required filesystems for this game - WiiFilesystemFactory::asyncHandler(false, &ConfMan.get("path")); + WiiFilesystemFactory::instance().umountUnused(ConfMan.get("path")); } void OSystem_Wii::engineDone() { @@ -241,3 +262,16 @@ void OSystem_Wii::getTimeAndDate(struct tm &t) const { t = *localtime(&curTime); } +void OSystem_Wii::showOptionsDialog() { + if (_optionsDlgActive) + return; + + bool ds = (_actualGraphicsMode == gmDoubleStrike) || + (_actualGraphicsMode == gmDoubleStrikeFiltered); + + _optionsDlgActive = true; + WiiOptionsDialog dlg(ds); + dlg.runModal(); + _optionsDlgActive = false; +} + diff --git a/backends/platform/wii/osystem_gfx.cpp b/backends/platform/wii/osystem_gfx.cpp index 3feaf65c1e..d33643193d 100644 --- a/backends/platform/wii/osystem_gfx.cpp +++ b/backends/platform/wii/osystem_gfx.cpp @@ -26,7 +26,6 @@ #include "backends/fs/wii/wii-fs-factory.h" #include "osystem.h" -#include "options.h" #include "gfx.h" #define ROUNDUP(x,n) (-(-(x) & -(n))) @@ -59,13 +58,6 @@ static const OSystem::GraphicsMode _supportedGraphicsModes[] = { }; void OSystem_Wii::initGfx() { - ConfMan.registerDefault("fullscreen", true); - ConfMan.registerDefault("aspect_ratio", true); - ConfMan.registerDefault("wii_video_default_underscan_x", 16); - ConfMan.registerDefault("wii_video_default_underscan_y", 16); - ConfMan.registerDefault("wii_video_ds_underscan_x", 16); - ConfMan.registerDefault("wii_video_ds_underscan_y", 16); - gfx_video_init(GFX_STANDARD_AUTO, GFX_MODE_DEFAULT); gfx_init(); gfx_set_underscan(ConfMan.getInt("wii_video_default_underscan_x"), @@ -718,17 +710,3 @@ void OSystem_Wii::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, _cursorPaletteDirty = true; } -void OSystem_Wii::showOptionsDialog() { - if (_optionsDlgActive) - return; - - bool ds = (_actualGraphicsMode == gmDoubleStrike) || - (_actualGraphicsMode == gmDoubleStrikeFiltered); - - _optionsDlgActive = true; - WiiOptionsDialog dlg(ds); - dlg.runModal(); - _optionsDlgActive = false; -} - - diff --git a/configure b/configure index 7d7b31549e..5e3e54a96f 100755 --- a/configure +++ b/configure @@ -1443,6 +1443,7 @@ if test -n "$_host"; then add_line_to_config_h "/* #define DEBUG_WII_MEMSTATS */" add_line_to_config_h "/* #define DEBUG_WII_GDB */" add_line_to_config_h "#define USE_WII_DI" + add_line_to_config_h "#define USE_WII_SMB" add_line_to_config_h "#define USE_WII_KBD" ;; gamecube) @@ -2186,7 +2187,7 @@ case $_backend in LIBS="$LIBS -lfat -logc -ldb" ;; *) - LIBS="$LIBS -ldi -lfat -lwiiuse -lbte -logc -lwiikeyboard -ldb" + LIBS="$LIBS -ldi -ltinysmb -lfat -lwiiuse -lbte -logc -lwiikeyboard -ldb" ;; esac ;; -- cgit v1.2.3