aboutsummaryrefslogtreecommitdiff
path: root/backends/fs/ds/ds-fs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'backends/fs/ds/ds-fs.cpp')
-rw-r--r--backends/fs/ds/ds-fs.cpp1736
1 files changed, 1736 insertions, 0 deletions
diff --git a/backends/fs/ds/ds-fs.cpp b/backends/fs/ds/ds-fs.cpp
new file mode 100644
index 0000000000..8032267e83
--- /dev/null
+++ b/backends/fs/ds/ds-fs.cpp
@@ -0,0 +1,1736 @@
+/* ScummVMDS - Scumm Interpreter DS Port
+ * Copyright (C) 2002-2004 The ScummVM project and Neil Millstone
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#include "stdafx.h"
+#include "str.h"
+#include "fs.h"
+#include "common/util.h"
+#include <NDS/ARM9/console.h> //basic print funcionality
+#include "ds-fs.h"
+#include "dsmain.h"
+#include "gba_nds_fat.h"
+
+namespace DS {
+
+//////////////////////////////////////////////////////////////
+// DSFileSystemNode - Flash ROM file system using Zip files
+//////////////////////////////////////////////////////////////
+
+ZipFile* DSFileSystemNode::_zipFile = NULL;
+char currentDir[128];
+
+DSFileSystemNode::DSFileSystemNode() {
+ _displayName = "ds:/";
+ _path = "ds:/";
+ _isValid = true;
+ _isDirectory = true;
+ _path = "ds:/";
+
+/* if (!_archive) {
+ _archive = (GBFS_FILE *) find_first_gbfs_file(scummdata);
+ if (!_archive) consolePrintf("No GBFS archive found!\n");
+ }*/
+
+ if (!_zipFile) {
+ _zipFile = new ZipFile();
+ }
+}
+
+DSFileSystemNode::DSFileSystemNode(const String& path) {
+// consolePrintf("--%s ",path.c_str());
+
+ char disp[128];
+ char* pathStr = (char *) path.c_str();
+
+
+ int lastSlash = 3;
+ for (int r = 0; r < (int) strlen(pathStr) - 1; r++) {
+ if (path[r] == '\\') {
+ lastSlash = r;
+ }
+ }
+
+ strcpy(disp, pathStr + lastSlash + 1);
+
+ _displayName = String(disp);
+ _path = path;
+// _isValid = true;
+// _isDirectory = false;
+
+
+
+ if (!strncmp(pathStr, "ds:/", 4)) {
+ pathStr += 4;
+ }
+
+
+ if (*pathStr == '\0') {
+ _isValid = true;
+ _isDirectory = true;
+ return;
+ }
+
+ _zipFile->setAllFilesVisible(true);
+ if (_zipFile->findFile(pathStr)) {
+ _isValid = true;
+ _isDirectory = _zipFile->isDirectory();
+ } else {
+ _isValid = false;
+ _isDirectory = false;
+ }
+ _zipFile->setAllFilesVisible(false);
+
+// consolePrintf("%s - Found: %d, Dir: %d\n", pathStr, _isValid, _isDirectory);
+}
+
+DSFileSystemNode::DSFileSystemNode(const String& path, bool isDir) {
+// consolePrintf("--%s ",path.c_str());
+
+ char disp[128];
+ char* pathStr = (char *) path.c_str();
+ int lastSlash = 3;
+ for (int r = 0; r < (int) strlen(pathStr) - 1; r++) {
+ if (path[r] == '\\') {
+ lastSlash = r;
+ }
+ }
+
+ strcpy(disp, pathStr + lastSlash + 1);
+
+ _displayName = String(disp);
+ _path = path;
+ _isValid = true;
+ _isDirectory = isDir;
+
+// consolePrintf("Found: %d, Dir: %d\n", _isValid, _isDirectory);
+}
+
+DSFileSystemNode::DSFileSystemNode(const DSFileSystemNode* node) {
+
+}
+
+AbstractFilesystemNode* DSFileSystemNode::parent() const {
+// consolePrintf("parent\n");
+ DSFileSystemNode *p;
+
+ if (_path != "ds:/") {
+ char *path = (char *) _path.c_str();
+ int lastSlash = 4;
+
+ for (int r = 4; r < (int) strlen((char *) path); r++) {
+ if (path[r] == '\\') {
+ lastSlash = r;
+ }
+ }
+
+ p = new DSFileSystemNode(String(path, lastSlash));
+ ((DSFileSystemNode *) (p))->_isDirectory = true;
+ } else {
+ p = new DSFileSystemNode();
+ }
+
+ return p;
+
+}
+
+
+AbstractFilesystemNode *DSFileSystemNode::child(const Common::String& name) const {
+ if (_path.lastChar() == '\\') {
+ return new DSFileSystemNode(_path + name);
+ } else {
+ return new DSFileSystemNode(_path + "\\" + name);
+ }
+
+ return NULL;
+}
+
+
+bool DSFileSystemNode::listDir(AbstractFSList &dirList, ListMode mode) const {
+// consolePrintf("Listdir\n");
+
+
+// consolePrintf("Directory\n");
+
+
+ char temp[128];
+ strcpy(temp, _path.c_str());
+
+// consolePrintf("This dir: %s\n", temp);
+
+ if ((temp[0] == 'd') && (temp[1] == 's') && (temp[2] == ':') && (temp[3] == '/')) {
+ if (strlen(temp) != 4) {
+ _zipFile->changeDirectory(&temp[4]);
+ } else {
+ _zipFile->changeToRoot();
+
+/* // This is the root dir, so add the RAM folder
+ DSFileSystemNode* dsfsn = new DSFileSystemNode("ds:/ram");
+ dsfsn->_isDirectory = true;
+ dirList->push_back(wrap(dsfsn));*/
+ }
+ } else {
+ _zipFile->changeDirectory(temp);
+ }
+
+
+
+ if (_zipFile->restartFile()) {
+ do {
+ char name[128];
+ _zipFile->getFileName(name);
+
+// consolePrintf("file: %s\n", name);
+ if ( (_zipFile->isDirectory() && ((mode == FilesystemNode::kListDirectoriesOnly) || (mode == FilesystemNode::kListAll)) )
+ || (!_zipFile->isDirectory() && ((mode == FilesystemNode::kListFilesOnly) || (mode == FilesystemNode::kListAll)) ) )
+ {
+ DSFileSystemNode* dsfsn = new DSFileSystemNode("ds:/" + String(name), _zipFile->isDirectory());
+ dsfsn->_isDirectory = _zipFile->isDirectory();
+ dirList.push_back((dsfsn));
+ }
+
+ } while (_zipFile->skipFile());
+ }
+
+ return true;
+}
+
+
+
+
+/////////////////////////////////////////////////////////////////////////
+// GBAMPFileSystemNode - File system using GBA Movie Player and CF card
+/////////////////////////////////////////////////////////////////////////
+
+GBAMPFileSystemNode::GBAMPFileSystemNode() {
+ _displayName = "mp:/";
+ _path = "mp:/";
+ _isValid = true;
+ _isDirectory = true;
+ _path = "mp:/";
+}
+
+GBAMPFileSystemNode::GBAMPFileSystemNode(const String& path) {
+// consolePrintf("'%s'",path.c_str());
+
+ char disp[128];
+ char* pathStr = (char *) path.c_str();
+ int lastSlash = 3;
+ for (int r = 0; r < (int) strlen(pathStr) - 1; r++) {
+ if ((path[r] == '\\') || (path[r] == '/')) {
+ lastSlash = r;
+ }
+ }
+
+ strcpy(disp, pathStr + lastSlash + 1);
+
+ char check[128];
+ int success;
+
+ memset(check, 0, 128);
+ if (strlen(pathStr) > 3) {
+ strcpy(check, pathStr + 3);
+ if (check[strlen(check) - 1] == '/') {
+ check[strlen(check) - 1] = 0;
+ }
+ success = FAT_FileExists(check);
+ } else {
+ success = FT_DIR;
+ }
+// consolePrintf("Path: %s (%d)\n", check, success);
+
+ _displayName = String(disp);
+ _path = path;
+ _isValid = success == FT_FILE;
+ _isDirectory = success == FT_DIR;
+}
+
+GBAMPFileSystemNode::GBAMPFileSystemNode(const String& path, bool isDirectory) {
+// consolePrintf("'%s'",path.c_str());
+
+ char disp[128];
+ char* pathStr = (char *) path.c_str();
+ int lastSlash = 3;
+ for (int r = 0; r < (int) strlen(pathStr) - 1; r++) {
+ if ((path[r] == '\\') || (path[r] == '/')) {
+ lastSlash = r;
+ }
+ }
+
+ strcpy(disp, pathStr + lastSlash + 1);
+
+ _displayName = String(disp);
+ _path = path;
+ _isValid = true;
+ _isDirectory = isDirectory;
+}
+
+
+GBAMPFileSystemNode::GBAMPFileSystemNode(const GBAMPFileSystemNode* node) {
+
+}
+
+
+AbstractFilesystemNode* GBAMPFileSystemNode::parent() const {
+// consolePrintf("parent\n");
+ GBAMPFileSystemNode *p;
+
+ if (_path != "mp:/") {
+ char *path = (char *) _path.c_str();
+ int lastSlash = 4;
+
+ for (int r = 4; r < (int) strlen((char *) path); r++) {
+ if (path[r] == '/') {
+ lastSlash = r;
+ }
+ }
+
+ p = new GBAMPFileSystemNode(String(path, lastSlash));
+ p->_isDirectory = true;
+ } else {
+ p = new GBAMPFileSystemNode();
+ }
+
+ return p;
+
+}
+
+AbstractFilesystemNode *GBAMPFileSystemNode::child(const Common::String& name) const {
+ if (_path.lastChar() == '\\') {
+ return new DSFileSystemNode(_path + name);
+ } else {
+ return new DSFileSystemNode(_path + "\\" + name);
+ }
+
+ return NULL;
+}
+
+bool GBAMPFileSystemNode::listDir(AbstractFSList& dirList, ListMode mode) const {
+// consolePrintf("Listdir\n");
+
+ enum { TYPE_NO_MORE = 0, TYPE_FILE = 1, TYPE_DIR = 2 };
+
+ char temp[128], fname[128], *path, *pathTemp;
+ strcpy(temp, _path.c_str());
+
+ path = temp + 3;
+
+ pathTemp = path;
+ while (*pathTemp) {
+ if (*pathTemp == '\\') {
+ *pathTemp = '/';
+ }
+ pathTemp++;
+ }
+
+
+// consolePrintf("This dir: %s\n", path);
+ FAT_chdir(path);
+
+ int entryType = FAT_FindFirstFile(fname);
+
+ while (entryType != TYPE_NO_MORE) {
+
+ if ( ((entryType == TYPE_DIR) && ((mode == FilesystemNode::kListDirectoriesOnly) || (mode == FilesystemNode::kListAll)))
+ || ((entryType == TYPE_FILE) && ((mode == FilesystemNode::kListFilesOnly) || (mode == FilesystemNode::kListAll))) ) {
+ GBAMPFileSystemNode* dsfsn;
+
+ if (strcmp(fname, ".") && strcmp(fname, "..")) {
+
+ if (!strcmp(path, "/")) {
+ dsfsn = new GBAMPFileSystemNode("mp:" + String(path) + String(fname), entryType == TYPE_DIR);
+ } else {
+ dsfsn = new GBAMPFileSystemNode("mp:" + String(path) + String("/") + String(fname), entryType == TYPE_DIR);
+ }
+
+// dsfsn->_isDirectory = entryType == DIR;
+ dirList.push_back((dsfsn));
+ }
+
+
+ } else {
+// consolePrintf("Skipping %s\n", fname);
+ }
+
+ entryType = FAT_FindNextFile(fname);
+ }
+
+// consolePrintf("No more");
+
+ FAT_chdir("/");
+
+ return true;
+}
+
+
+// Stdio replacements
+#define MAX_FILE_HANDLES 32
+
+bool inited = false;
+DS::fileHandle handle[MAX_FILE_HANDLES];
+
+FILE* std_fopen(const char* name, const char* mode) {
+
+
+
+ if (!inited) {
+ for (int r = 0; r < MAX_FILE_HANDLES; r++) {
+ handle[r].used = false;
+ }
+ inited = true;
+ currentDir[0] = '\0';
+ }
+
+
+
+
+ char* realName = (char *) name;
+
+ // Remove file system prefix
+ if ((name[0] == 'd') && (name[1] == 's') && (name[2] == ':') && (name[3] == '/')) {
+ realName += 4;
+ }
+
+ if ((name[0] == 'm') && (name[1] == 'p') && (name[2] == ':') && (name[3] == '/')) {
+ realName += 4;
+ }
+
+// consolePrintf("Open file:");
+// consolePrintf("'%s', [%s]", realName, mode);
+
+
+ if (DS::isGBAMPAvailable()) {
+ FAT_chdir("/");
+
+ char* p = realName;
+ while (*p) {
+ if (*p == '\\') *p = '/';
+ p++;
+ }
+
+ FAT_FILE* result = FAT_fopen(realName, mode);
+
+ if (result == 0) {
+// consolePrintf("Error code %d\n", result);
+ //consolePrintf("Opening file %s\n", realName);
+ } else {
+// consolePrintf("Opened file %d\n", result);
+ }
+// MT_memoryReport();
+
+ return (fileHandle *) result;
+ }
+
+
+ // Fail to open file for writing. It's in ROM!
+
+ // Allocate a file handle
+ int r = 0;
+ while (handle[r].used) r++;
+
+ if (strchr(mode, 'w')) {
+// consolePrintf("Writing %s\n", realName);
+ handle[r].sramFile = (DSSaveFile *) DSSaveFileManager::instance()->openSavefile(realName, true);
+ } else {
+// consolePrintf("Reading %s\n", realName);
+ handle[r].sramFile = (DSSaveFile *) DSSaveFileManager::instance()->openSavefile(realName, false);
+ }
+
+
+ if (handle[r].sramFile) {
+ handle[r].used = true;
+ handle[r].pos = 0;
+ handle[r].data = NULL;
+ handle[r].size = handle[r].sramFile->getSize();
+// consolePrintf("Found it");
+ return &handle[r];
+ }
+
+// consolePrintf("Not in SRAM!");
+
+ char* data;
+
+ ZipFile* zip = DSFileSystemNode::getZip();
+ if (!zip) {
+// consolePrintf("No zip yet!");
+ return NULL;
+ }
+
+ // Grab the data if it exists
+
+ zip->setAllFilesVisible(true);
+
+ if (currentDir[0] != 0) {
+ char nameWithPath[128];
+ sprintf(nameWithPath, "%s\%s", currentDir, realName);
+ strcpy(realName, nameWithPath);
+ }
+
+// consolePrintf("fopen(%s, %s)\n", realName, name);
+
+ if (zip->findFile(realName)) {
+ data = zip->getFile();
+ zip->setAllFilesVisible(false);
+
+ // Allocate a file handle
+ int r = 0;
+ while (handle[r].used) r++;
+
+
+ handle[r].used = true;
+ handle[r].pos = 0;
+ handle[r].data = data;
+ handle[r].size = zip->getFileSize();
+
+// consolePrintf("Opened file %d: %s (%s) ", r, realName, name);
+ return &handle[r];
+ } else {
+ zip->setAllFilesVisible(false);
+// consolePrintf("Not found: %s (%s) ", realName, name);
+ return NULL;
+ }
+}
+void std_fclose(FILE* handle) {
+
+ if (DS::isGBAMPAvailable()) {
+ FAT_fclose((FAT_FILE *) handle);
+ return;
+ }
+
+ handle->used = false;
+ if (handle->sramFile) {
+ delete handle->sramFile;
+ handle->sramFile = NULL;
+ }
+}
+
+size_t std_fread(const void* ptr, size_t size, size_t numItems, FILE* handle) {
+
+// consolePrintf("fread %d,%d %d ", size, numItems, ptr);
+
+
+
+ if (DS::isGBAMPAvailable()) {
+
+
+ int bytes = FAT_fread((void *) ptr, size, numItems, (FAT_FILE *) handle);
+ if (!std_feof(handle)) {
+ return numItems;
+ } else {
+// consolePrintf("Read past end of file: %d read out of %d\n", bytes / size, numItems);
+ return bytes / size;
+ }
+ return numItems;
+
+/* int item = 0;
+ u8* data = (u8 *) ptr;
+ while ((item < numItems) && (!FAT_feof((FAT_FILE *) handle))) {
+
+
+ int bytes = 0;
+ while ((bytes < size) && (!FAT_feof((FAT_FILE *) handle))) {
+ *data++ = FAT_fgetc((FAT_FILE *) handle);
+ bytes++;
+ }
+
+ item++;
+
+ }
+
+ return item;*/
+
+
+ int items = 0;
+
+ //for (int r = 0; r < numItems; r++) {
+ if (!std_feof(handle)) {
+
+
+
+/* for (int t = 0; t < size; t++) {
+ if (feof(handle)) eof = true;
+ *(((char *) (ptr)) + r * size + t) = getc(handle);
+ }*/
+ int left = size * numItems;;
+ int bytesRead = -1;
+ while ((left > 0) && (!FAT_feof((FAT_FILE *) handle))) {
+ int amount = left > 8192? 8192: left;
+// do {
+ bytesRead = FAT_fread((void *) ptr, 1, amount, (FAT_FILE *) handle);
+ /* if (bytesRead == 0) {
+ consolePrintf("Pos:%d items:%d num:%d amount:%d read:%d\n", ftell(handle), items, numItems, amount, bytesRead);
+ left++;
+
+ int pos = ftell(handle);
+
+ fseek(handle, 0, SEEK_SET);
+ int c = getc(handle);
+ fseek(handle, pos - 1024, SEEK_SET);
+ fread(ptr, 1024, 1, handle);
+ swiWaitForVBlank();
+ //while (true);
+ }*/
+ //} while (bytesRead == 0);
+ left -= bytesRead;
+ ptr = ((char *) (ptr)) + bytesRead;
+ }
+
+ items = numItems - (left / size);
+
+
+
+
+// FAT_fread((void *) ptr, size, 1, ((int) (handle)) - 1);
+ // ptr = ((char *) (ptr)) + size;
+
+ }
+ //}
+
+// consolePrintf("...done %d \n", items)
+
+ return items;
+
+ }
+
+ if (handle->sramFile) {
+ int bytes = 0;
+ int result = 1;
+ //consolePrintf("fread size=", size * numItems);
+ for (int r = 0; (r < (s32) size * (s32) numItems) && (result > 0); r++) {
+ result = handle->sramFile->read((void *) ( ((char *) (ptr)) + r), 1);
+ bytes += result;
+ //consolePrintf("'%d',", ((char *) (ptr))[0]);
+ }
+
+ handle->pos += bytes;
+
+ return bytes / size;
+ }
+
+
+ if (handle->pos + size * numItems > handle->size) {
+ numItems = (handle->size - handle->pos) / size;
+ if (numItems < 0) numItems = 0;
+ }
+
+// consolePrintf("read %d ", size * numItems);
+
+ memcpy((void *) ptr, handle->data + handle->pos, size * numItems);
+
+ handle->pos += size * numItems;
+
+
+ return numItems;
+}
+
+size_t std_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle) {
+ if ((handle == stdin)) return 0;
+
+ if ((handle == stderr) || (handle == stdout)) {
+// consolePrintf((char *) ptr);
+ return size;
+ }
+
+ //consolePrintf("fwrite size=%d\n", size * numItems);
+
+ if (DS::isGBAMPAvailable()) {
+
+ FAT_fwrite(((char *) (ptr)), size, numItems, (FAT_FILE *) handle);
+ return numItems;
+
+ int length = size * numItems;
+ int pos = 0;
+
+ while (pos < length) {
+ int amount = length > 512? 512: length;
+
+ FAT_fwrite(((char *) (ptr)) + pos, 1, amount, (FAT_FILE *) handle);
+ length -= amount;
+ pos += amount;
+ }
+
+ return numItems;
+ }
+
+
+ if (handle->sramFile) {
+ handle->sramFile->write(ptr, size);
+ return size;
+ } else {
+ return 0;
+ }
+}
+
+void std_fprintf(FILE* handle, const char* fmt, ...) {
+ consolePrintf(fmt);
+}
+
+bool std_feof(FILE* handle) {
+// consolePrintf("feof ");
+
+ if (DS::isGBAMPAvailable()) {
+ return FAT_feof((FAT_FILE *) handle);
+ }
+
+ if (handle->sramFile) {
+ return handle->sramFile->eos();
+ }
+
+// consolePrintf("feof %s", handle->pos >= handle->size? "true": "false");
+ return handle->pos >= handle->size;
+}
+
+void std_fflush(FILE* handle) {
+// consolePrintf("fflush ");
+}
+
+char* std_fgets(char* str, int size, FILE* file) {
+// consolePrintf("fgets file=%d ", file);
+
+ if (DS::isGBAMPAvailable()) {
+
+ char* s = str;
+ while ((*s++ = std_getc(file)) >= 32) {
+// consolePrintf("%d ", *s);
+ }
+ *s = 0;
+
+// consolePrintf("Read:%s\n", str);
+
+ return str;
+ }
+
+
+ if (file->sramFile) {
+ file->pos--;
+ int p = -1;
+ do {
+ file->pos++;
+ p++;
+ file->sramFile->read((char *) &str[p], 1);
+// consolePrintf("%d,", str[p]);
+ } while ((str[p] >= 32) && (!feof(file)) && (p < size));
+ str[p + 1] = 0;
+ file->pos++;
+// consolePrintf("Read:%s\n", str);
+ return str;
+ }
+
+ return NULL;
+}
+
+long int std_ftell(FILE* handle) {
+
+ if (DS::isGBAMPAvailable()) {
+ return FAT_ftell((FAT_FILE *) handle);
+ }
+
+ return handle->pos;
+}
+
+int std_fseek(FILE* handle, long int offset, int whence) {
+// consolePrintf("fseek %d %d ", offset, whence);
+
+ if (DS::isGBAMPAvailable()) {
+ return FAT_fseek((FAT_FILE *) handle, offset, whence);
+ }
+
+
+ switch (whence) {
+ case SEEK_CUR: {
+ handle->pos += offset;
+ break;
+ }
+
+ case SEEK_SET: {
+ handle->pos = offset;
+ break;
+ }
+
+ case SEEK_END: {
+ handle->pos = handle->size + offset;
+ break;
+ }
+
+ default: {
+ handle->pos = offset;
+ break;
+ }
+
+ }
+
+ return 0;
+}
+
+void std_clearerr(FILE* handle) {
+// consolePrintf("clearerr ");
+}
+
+int std_getc(FILE* handle) {
+
+ if (DS::isGBAMPAvailable()) {
+ char c;
+ FAT_fread(&c, 1, 1, (FAT_FILE *) handle);
+
+ return c;
+ }
+
+// consolePrintf("fgetc ");
+ return 0; // Not supported yet
+}
+
+char* std_getcwd(char* dir, int dunno) {
+// consolePrintf("getcwd ");
+ dir[0] = '\0';
+ return dir; // Not supported yet
+}
+
+void std_cwd(char* dir) {
+ char buffer[128];
+ strcpy(buffer, dir);
+ char* realName = buffer;
+
+ if (DS::isGBAMPAvailable()) {
+ if ((strlen(dir) >= 4) && (dir[0] == 'm') && (dir[1] == 'p') && (dir[2] == ':') && (dir[3] == '/')) {
+ realName += 4;
+ }
+
+ // consolePrintf("Real cwd:%d\n", realName);
+
+ char* p = realName;
+ while (*p) {
+ if (*p == '\\') *p = '/';
+ p++;
+ }
+
+ // consolePrintf("Real cwd:%d\n", realName);
+ FAT_chdir(realName);
+ } else {
+ if ((strlen(dir) >= 4) && (dir[0] == 'd') && (dir[1] == 's') && (dir[2] == ':') && (dir[3] == '/')) {
+ realName += 4;
+ }
+
+ char* p = realName;
+ while (*p) {
+ if (*p == '\\') *p = '/';
+ p++;
+ }
+
+ strcpy(currentDir, realName);
+ if (*(currentDir + strlen(currentDir) - 1) == '/') {
+ *(currentDir + strlen(currentDir) - 1) = '\0';
+ }
+ consolePrintf("CWD: %s\n", currentDir);
+ }
+}
+
+int std_ferror(FILE* handle) {
+ return 0;
+}
+
+} // namespace DS
+
+// These functions are added to AbstractFileSystemNode and are therefore outside
+// the DS namespace.
+
+AbstractFilesystemNode *AbstractFilesystemNode::getCurrentDirectory() {
+// consolePrintf("New node");
+
+ if (DS::isGBAMPAvailable()) {
+ return new DS::GBAMPFileSystemNode();
+ } else {
+ return new DS::DSFileSystemNode();
+ }
+}
+
+AbstractFilesystemNode* AbstractFilesystemNode::getNodeForPath(const String& path) {
+ if (DS::isGBAMPAvailable()) {
+ return new DS::GBAMPFileSystemNode(path);
+ } else {
+ return new DS::DSFileSystemNode(path);
+ }
+}
+/* ScummVMDS - Scumm Interpreter DS Port
+ * Copyright (C) 2002-2004 The ScummVM project and Neil Millstone
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#include "stdafx.h"
+#include "str.h"
+#include "fs.h"
+#include "common/util.h"
+#include <NDS/ARM9/console.h> //basic print funcionality
+#include "ds-fs.h"
+#include "dsmain.h"
+#include "gba_nds_fat.h"
+
+namespace DS {
+
+//////////////////////////////////////////////////////////////
+// DSFileSystemNode - Flash ROM file system using Zip files
+//////////////////////////////////////////////////////////////
+
+ZipFile* DSFileSystemNode::_zipFile = NULL;
+char currentDir[128];
+
+DSFileSystemNode::DSFileSystemNode() {
+ _displayName = "ds:/";
+ _path = "ds:/";
+ _isValid = true;
+ _isDirectory = true;
+ _path = "ds:/";
+
+/* if (!_archive) {
+ _archive = (GBFS_FILE *) find_first_gbfs_file(scummdata);
+ if (!_archive) consolePrintf("No GBFS archive found!\n");
+ }*/
+
+ if (!_zipFile) {
+ _zipFile = new ZipFile();
+ }
+}
+
+DSFileSystemNode::DSFileSystemNode(const String& path) {
+// consolePrintf("--%s ",path.c_str());
+
+ char disp[128];
+ char* pathStr = (char *) path.c_str();
+
+
+ int lastSlash = 3;
+ for (int r = 0; r < (int) strlen(pathStr) - 1; r++) {
+ if (path[r] == '\\') {
+ lastSlash = r;
+ }
+ }
+
+ strcpy(disp, pathStr + lastSlash + 1);
+
+ _displayName = String(disp);
+ _path = path;
+// _isValid = true;
+// _isDirectory = false;
+
+
+
+ if (!strncmp(pathStr, "ds:/", 4)) {
+ pathStr += 4;
+ }
+
+
+ if (*pathStr == '\0') {
+ _isValid = true;
+ _isDirectory = true;
+ return;
+ }
+
+ _zipFile->setAllFilesVisible(true);
+ if (_zipFile->findFile(pathStr)) {
+ _isValid = true;
+ _isDirectory = _zipFile->isDirectory();
+ } else {
+ _isValid = false;
+ _isDirectory = false;
+ }
+ _zipFile->setAllFilesVisible(false);
+
+// consolePrintf("%s - Found: %d, Dir: %d\n", pathStr, _isValid, _isDirectory);
+}
+
+DSFileSystemNode::DSFileSystemNode(const String& path, bool isDir) {
+// consolePrintf("--%s ",path.c_str());
+
+ char disp[128];
+ char* pathStr = (char *) path.c_str();
+ int lastSlash = 3;
+ for (int r = 0; r < (int) strlen(pathStr) - 1; r++) {
+ if (path[r] == '\\') {
+ lastSlash = r;
+ }
+ }
+
+ strcpy(disp, pathStr + lastSlash + 1);
+
+ _displayName = String(disp);
+ _path = path;
+ _isValid = true;
+ _isDirectory = isDir;
+
+// consolePrintf("Found: %d, Dir: %d\n", _isValid, _isDirectory);
+}
+
+DSFileSystemNode::DSFileSystemNode(const DSFileSystemNode* node) {
+
+}
+
+AbstractFilesystemNode* DSFileSystemNode::parent() const {
+// consolePrintf("parent\n");
+ DSFileSystemNode *p;
+
+ if (_path != "ds:/") {
+ char *path = (char *) _path.c_str();
+ int lastSlash = 4;
+
+ for (int r = 4; r < (int) strlen((char *) path); r++) {
+ if (path[r] == '\\') {
+ lastSlash = r;
+ }
+ }
+
+ p = new DSFileSystemNode(String(path, lastSlash));
+ ((DSFileSystemNode *) (p))->_isDirectory = true;
+ } else {
+ p = new DSFileSystemNode();
+ }
+
+ return p;
+
+}
+
+
+AbstractFilesystemNode *DSFileSystemNode::child(const Common::String& name) const {
+ if (_path.lastChar() == '\\') {
+ return new DSFileSystemNode(_path + name);
+ } else {
+ return new DSFileSystemNode(_path + "\\" + name);
+ }
+
+ return NULL;
+}
+
+
+bool DSFileSystemNode::listDir(AbstractFSList &dirList, ListMode mode) const {
+// consolePrintf("Listdir\n");
+
+
+// consolePrintf("Directory\n");
+
+
+ char temp[128];
+ strcpy(temp, _path.c_str());
+
+// consolePrintf("This dir: %s\n", temp);
+
+ if ((temp[0] == 'd') && (temp[1] == 's') && (temp[2] == ':') && (temp[3] == '/')) {
+ if (strlen(temp) != 4) {
+ _zipFile->changeDirectory(&temp[4]);
+ } else {
+ _zipFile->changeToRoot();
+
+/* // This is the root dir, so add the RAM folder
+ DSFileSystemNode* dsfsn = new DSFileSystemNode("ds:/ram");
+ dsfsn->_isDirectory = true;
+ dirList->push_back(wrap(dsfsn));*/
+ }
+ } else {
+ _zipFile->changeDirectory(temp);
+ }
+
+
+
+ if (_zipFile->restartFile()) {
+ do {
+ char name[128];
+ _zipFile->getFileName(name);
+
+// consolePrintf("file: %s\n", name);
+ if ( (_zipFile->isDirectory() && ((mode == FilesystemNode::kListDirectoriesOnly) || (mode == FilesystemNode::kListAll)) )
+ || (!_zipFile->isDirectory() && ((mode == FilesystemNode::kListFilesOnly) || (mode == FilesystemNode::kListAll)) ) )
+ {
+ DSFileSystemNode* dsfsn = new DSFileSystemNode("ds:/" + String(name), _zipFile->isDirectory());
+ dsfsn->_isDirectory = _zipFile->isDirectory();
+ dirList.push_back((dsfsn));
+ }
+
+ } while (_zipFile->skipFile());
+ }
+
+ return true;
+}
+
+
+
+
+/////////////////////////////////////////////////////////////////////////
+// GBAMPFileSystemNode - File system using GBA Movie Player and CF card
+/////////////////////////////////////////////////////////////////////////
+
+GBAMPFileSystemNode::GBAMPFileSystemNode() {
+ _displayName = "mp:/";
+ _path = "mp:/";
+ _isValid = true;
+ _isDirectory = true;
+ _path = "mp:/";
+}
+
+GBAMPFileSystemNode::GBAMPFileSystemNode(const String& path) {
+// consolePrintf("'%s'",path.c_str());
+
+ char disp[128];
+ char* pathStr = (char *) path.c_str();
+ int lastSlash = 3;
+ for (int r = 0; r < (int) strlen(pathStr) - 1; r++) {
+ if ((path[r] == '\\') || (path[r] == '/')) {
+ lastSlash = r;
+ }
+ }
+
+ strcpy(disp, pathStr + lastSlash + 1);
+
+ char check[128];
+ int success;
+
+ memset(check, 0, 128);
+ if (strlen(pathStr) > 3) {
+ strcpy(check, pathStr + 3);
+ if (check[strlen(check) - 1] == '/') {
+ check[strlen(check) - 1] = 0;
+ }
+ success = FAT_FileExists(check);
+ } else {
+ success = FT_DIR;
+ }
+// consolePrintf("Path: %s (%d)\n", check, success);
+
+ _displayName = String(disp);
+ _path = path;
+ _isValid = success == FT_FILE;
+ _isDirectory = success == FT_DIR;
+}
+
+GBAMPFileSystemNode::GBAMPFileSystemNode(const String& path, bool isDirectory) {
+// consolePrintf("'%s'",path.c_str());
+
+ char disp[128];
+ char* pathStr = (char *) path.c_str();
+ int lastSlash = 3;
+ for (int r = 0; r < (int) strlen(pathStr) - 1; r++) {
+ if ((path[r] == '\\') || (path[r] == '/')) {
+ lastSlash = r;
+ }
+ }
+
+ strcpy(disp, pathStr + lastSlash + 1);
+
+ _displayName = String(disp);
+ _path = path;
+ _isValid = true;
+ _isDirectory = isDirectory;
+}
+
+
+GBAMPFileSystemNode::GBAMPFileSystemNode(const GBAMPFileSystemNode* node) {
+
+}
+
+
+AbstractFilesystemNode* GBAMPFileSystemNode::parent() const {
+// consolePrintf("parent\n");
+ GBAMPFileSystemNode *p;
+
+ if (_path != "mp:/") {
+ char *path = (char *) _path.c_str();
+ int lastSlash = 4;
+
+ for (int r = 4; r < (int) strlen((char *) path); r++) {
+ if (path[r] == '/') {
+ lastSlash = r;
+ }
+ }
+
+ p = new GBAMPFileSystemNode(String(path, lastSlash));
+ p->_isDirectory = true;
+ } else {
+ p = new GBAMPFileSystemNode();
+ }
+
+ return p;
+
+}
+
+AbstractFilesystemNode *GBAMPFileSystemNode::child(const Common::String& name) const {
+ if (_path.lastChar() == '\\') {
+ return new DSFileSystemNode(_path + name);
+ } else {
+ return new DSFileSystemNode(_path + "\\" + name);
+ }
+
+ return NULL;
+}
+
+bool GBAMPFileSystemNode::listDir(AbstractFSList& dirList, ListMode mode) const {
+// consolePrintf("Listdir\n");
+
+ enum { TYPE_NO_MORE = 0, TYPE_FILE = 1, TYPE_DIR = 2 };
+
+ char temp[128], fname[128], *path, *pathTemp;
+ strcpy(temp, _path.c_str());
+
+ path = temp + 3;
+
+ pathTemp = path;
+ while (*pathTemp) {
+ if (*pathTemp == '\\') {
+ *pathTemp = '/';
+ }
+ pathTemp++;
+ }
+
+
+// consolePrintf("This dir: %s\n", path);
+ FAT_chdir(path);
+
+ int entryType = FAT_FindFirstFile(fname);
+
+ while (entryType != TYPE_NO_MORE) {
+
+ if ( ((entryType == TYPE_DIR) && ((mode == FilesystemNode::kListDirectoriesOnly) || (mode == FilesystemNode::kListAll)))
+ || ((entryType == TYPE_FILE) && ((mode == FilesystemNode::kListFilesOnly) || (mode == FilesystemNode::kListAll))) ) {
+ GBAMPFileSystemNode* dsfsn;
+
+ if (strcmp(fname, ".") && strcmp(fname, "..")) {
+
+ if (!strcmp(path, "/")) {
+ dsfsn = new GBAMPFileSystemNode("mp:" + String(path) + String(fname), entryType == TYPE_DIR);
+ } else {
+ dsfsn = new GBAMPFileSystemNode("mp:" + String(path) + String("/") + String(fname), entryType == TYPE_DIR);
+ }
+
+// dsfsn->_isDirectory = entryType == DIR;
+ dirList.push_back((dsfsn));
+ }
+
+
+ } else {
+// consolePrintf("Skipping %s\n", fname);
+ }
+
+ entryType = FAT_FindNextFile(fname);
+ }
+
+// consolePrintf("No more");
+
+ FAT_chdir("/");
+
+ return true;
+}
+
+
+// Stdio replacements
+#define MAX_FILE_HANDLES 32
+
+bool inited = false;
+DS::fileHandle handle[MAX_FILE_HANDLES];
+
+FILE* std_fopen(const char* name, const char* mode) {
+
+
+
+ if (!inited) {
+ for (int r = 0; r < MAX_FILE_HANDLES; r++) {
+ handle[r].used = false;
+ }
+ inited = true;
+ currentDir[0] = '\0';
+ }
+
+
+
+
+ char* realName = (char *) name;
+
+ // Remove file system prefix
+ if ((name[0] == 'd') && (name[1] == 's') && (name[2] == ':') && (name[3] == '/')) {
+ realName += 4;
+ }
+
+ if ((name[0] == 'm') && (name[1] == 'p') && (name[2] == ':') && (name[3] == '/')) {
+ realName += 4;
+ }
+
+// consolePrintf("Open file:");
+// consolePrintf("'%s', [%s]", realName, mode);
+
+
+ if (DS::isGBAMPAvailable()) {
+ FAT_chdir("/");
+
+ char* p = realName;
+ while (*p) {
+ if (*p == '\\') *p = '/';
+ p++;
+ }
+
+ FAT_FILE* result = FAT_fopen(realName, mode);
+
+ if (result == 0) {
+// consolePrintf("Error code %d\n", result);
+ //consolePrintf("Opening file %s\n", realName);
+ } else {
+// consolePrintf("Opened file %d\n", result);
+ }
+// MT_memoryReport();
+
+ return (fileHandle *) result;
+ }
+
+
+ // Fail to open file for writing. It's in ROM!
+
+ // Allocate a file handle
+ int r = 0;
+ while (handle[r].used) r++;
+
+ if (strchr(mode, 'w')) {
+// consolePrintf("Writing %s\n", realName);
+ handle[r].sramFile = (DSSaveFile *) DSSaveFileManager::instance()->openSavefile(realName, true);
+ } else {
+// consolePrintf("Reading %s\n", realName);
+ handle[r].sramFile = (DSSaveFile *) DSSaveFileManager::instance()->openSavefile(realName, false);
+ }
+
+
+ if (handle[r].sramFile) {
+ handle[r].used = true;
+ handle[r].pos = 0;
+ handle[r].data = NULL;
+ handle[r].size = handle[r].sramFile->getSize();
+// consolePrintf("Found it");
+ return &handle[r];
+ }
+
+// consolePrintf("Not in SRAM!");
+
+ char* data;
+
+ ZipFile* zip = DSFileSystemNode::getZip();
+ if (!zip) {
+// consolePrintf("No zip yet!");
+ return NULL;
+ }
+
+ // Grab the data if it exists
+
+ zip->setAllFilesVisible(true);
+
+ if (currentDir[0] != 0) {
+ char nameWithPath[128];
+ sprintf(nameWithPath, "%s\%s", currentDir, realName);
+ strcpy(realName, nameWithPath);
+ }
+
+// consolePrintf("fopen(%s, %s)\n", realName, name);
+
+ if (zip->findFile(realName)) {
+ data = zip->getFile();
+ zip->setAllFilesVisible(false);
+
+ // Allocate a file handle
+ int r = 0;
+ while (handle[r].used) r++;
+
+
+ handle[r].used = true;
+ handle[r].pos = 0;
+ handle[r].data = data;
+ handle[r].size = zip->getFileSize();
+
+// consolePrintf("Opened file %d: %s (%s) ", r, realName, name);
+ return &handle[r];
+ } else {
+ zip->setAllFilesVisible(false);
+// consolePrintf("Not found: %s (%s) ", realName, name);
+ return NULL;
+ }
+}
+void std_fclose(FILE* handle) {
+
+ if (DS::isGBAMPAvailable()) {
+ FAT_fclose((FAT_FILE *) handle);
+ return;
+ }
+
+ handle->used = false;
+ if (handle->sramFile) {
+ delete handle->sramFile;
+ handle->sramFile = NULL;
+ }
+}
+
+size_t std_fread(const void* ptr, size_t size, size_t numItems, FILE* handle) {
+
+// consolePrintf("fread %d,%d %d ", size, numItems, ptr);
+
+
+
+ if (DS::isGBAMPAvailable()) {
+
+
+ int bytes = FAT_fread((void *) ptr, size, numItems, (FAT_FILE *) handle);
+ if (!std_feof(handle)) {
+ return numItems;
+ } else {
+// consolePrintf("Read past end of file: %d read out of %d\n", bytes / size, numItems);
+ return bytes / size;
+ }
+ return numItems;
+
+/* int item = 0;
+ u8* data = (u8 *) ptr;
+ while ((item < numItems) && (!FAT_feof((FAT_FILE *) handle))) {
+
+
+ int bytes = 0;
+ while ((bytes < size) && (!FAT_feof((FAT_FILE *) handle))) {
+ *data++ = FAT_fgetc((FAT_FILE *) handle);
+ bytes++;
+ }
+
+ item++;
+
+ }
+
+ return item;*/
+
+
+ int items = 0;
+
+ //for (int r = 0; r < numItems; r++) {
+ if (!std_feof(handle)) {
+
+
+
+/* for (int t = 0; t < size; t++) {
+ if (feof(handle)) eof = true;
+ *(((char *) (ptr)) + r * size + t) = getc(handle);
+ }*/
+ int left = size * numItems;;
+ int bytesRead = -1;
+ while ((left > 0) && (!FAT_feof((FAT_FILE *) handle))) {
+ int amount = left > 8192? 8192: left;
+// do {
+ bytesRead = FAT_fread((void *) ptr, 1, amount, (FAT_FILE *) handle);
+ /* if (bytesRead == 0) {
+ consolePrintf("Pos:%d items:%d num:%d amount:%d read:%d\n", ftell(handle), items, numItems, amount, bytesRead);
+ left++;
+
+ int pos = ftell(handle);
+
+ fseek(handle, 0, SEEK_SET);
+ int c = getc(handle);
+ fseek(handle, pos - 1024, SEEK_SET);
+ fread(ptr, 1024, 1, handle);
+ swiWaitForVBlank();
+ //while (true);
+ }*/
+ //} while (bytesRead == 0);
+ left -= bytesRead;
+ ptr = ((char *) (ptr)) + bytesRead;
+ }
+
+ items = numItems - (left / size);
+
+
+
+
+// FAT_fread((void *) ptr, size, 1, ((int) (handle)) - 1);
+ // ptr = ((char *) (ptr)) + size;
+
+ }
+ //}
+
+// consolePrintf("...done %d \n", items)
+
+ return items;
+
+ }
+
+ if (handle->sramFile) {
+ int bytes = 0;
+ int result = 1;
+ //consolePrintf("fread size=", size * numItems);
+ for (int r = 0; (r < (s32) size * (s32) numItems) && (result > 0); r++) {
+ result = handle->sramFile->read((void *) ( ((char *) (ptr)) + r), 1);
+ bytes += result;
+ //consolePrintf("'%d',", ((char *) (ptr))[0]);
+ }
+
+ handle->pos += bytes;
+
+ return bytes / size;
+ }
+
+
+ if (handle->pos + size * numItems > handle->size) {
+ numItems = (handle->size - handle->pos) / size;
+ if (numItems < 0) numItems = 0;
+ }
+
+// consolePrintf("read %d ", size * numItems);
+
+ memcpy((void *) ptr, handle->data + handle->pos, size * numItems);
+
+ handle->pos += size * numItems;
+
+
+ return numItems;
+}
+
+size_t std_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle) {
+ if ((handle == stdin)) return 0;
+
+ if ((handle == stderr) || (handle == stdout)) {
+// consolePrintf((char *) ptr);
+ return size;
+ }
+
+ //consolePrintf("fwrite size=%d\n", size * numItems);
+
+ if (DS::isGBAMPAvailable()) {
+
+ FAT_fwrite(((char *) (ptr)), size, numItems, (FAT_FILE *) handle);
+ return numItems;
+
+ int length = size * numItems;
+ int pos = 0;
+
+ while (pos < length) {
+ int amount = length > 512? 512: length;
+
+ FAT_fwrite(((char *) (ptr)) + pos, 1, amount, (FAT_FILE *) handle);
+ length -= amount;
+ pos += amount;
+ }
+
+ return numItems;
+ }
+
+
+ if (handle->sramFile) {
+ handle->sramFile->write(ptr, size);
+ return size;
+ } else {
+ return 0;
+ }
+}
+
+void std_fprintf(FILE* handle, const char* fmt, ...) {
+ consolePrintf(fmt);
+}
+
+bool std_feof(FILE* handle) {
+// consolePrintf("feof ");
+
+ if (DS::isGBAMPAvailable()) {
+ return FAT_feof((FAT_FILE *) handle);
+ }
+
+ if (handle->sramFile) {
+ return handle->sramFile->eos();
+ }
+
+// consolePrintf("feof %s", handle->pos >= handle->size? "true": "false");
+ return handle->pos >= handle->size;
+}
+
+void std_fflush(FILE* handle) {
+// consolePrintf("fflush ");
+}
+
+char* std_fgets(char* str, int size, FILE* file) {
+// consolePrintf("fgets file=%d ", file);
+
+ if (DS::isGBAMPAvailable()) {
+
+ char* s = str;
+ while ((*s++ = std_getc(file)) >= 32) {
+// consolePrintf("%d ", *s);
+ }
+ *s = 0;
+
+// consolePrintf("Read:%s\n", str);
+
+ return str;
+ }
+
+
+ if (file->sramFile) {
+ file->pos--;
+ int p = -1;
+ do {
+ file->pos++;
+ p++;
+ file->sramFile->read((char *) &str[p], 1);
+// consolePrintf("%d,", str[p]);
+ } while ((str[p] >= 32) && (!feof(file)) && (p < size));
+ str[p + 1] = 0;
+ file->pos++;
+// consolePrintf("Read:%s\n", str);
+ return str;
+ }
+
+ return NULL;
+}
+
+long int std_ftell(FILE* handle) {
+
+ if (DS::isGBAMPAvailable()) {
+ return FAT_ftell((FAT_FILE *) handle);
+ }
+
+ return handle->pos;
+}
+
+int std_fseek(FILE* handle, long int offset, int whence) {
+// consolePrintf("fseek %d %d ", offset, whence);
+
+ if (DS::isGBAMPAvailable()) {
+ return FAT_fseek((FAT_FILE *) handle, offset, whence);
+ }
+
+
+ switch (whence) {
+ case SEEK_CUR: {
+ handle->pos += offset;
+ break;
+ }
+
+ case SEEK_SET: {
+ handle->pos = offset;
+ break;
+ }
+
+ case SEEK_END: {
+ handle->pos = handle->size + offset;
+ break;
+ }
+
+ default: {
+ handle->pos = offset;
+ break;
+ }
+
+ }
+
+ return 0;
+}
+
+void std_clearerr(FILE* handle) {
+// consolePrintf("clearerr ");
+}
+
+int std_getc(FILE* handle) {
+
+ if (DS::isGBAMPAvailable()) {
+ char c;
+ FAT_fread(&c, 1, 1, (FAT_FILE *) handle);
+
+ return c;
+ }
+
+// consolePrintf("fgetc ");
+ return 0; // Not supported yet
+}
+
+char* std_getcwd(char* dir, int dunno) {
+// consolePrintf("getcwd ");
+ dir[0] = '\0';
+ return dir; // Not supported yet
+}
+
+void std_cwd(char* dir) {
+ char buffer[128];
+ strcpy(buffer, dir);
+ char* realName = buffer;
+
+ if (DS::isGBAMPAvailable()) {
+ if ((strlen(dir) >= 4) && (dir[0] == 'm') && (dir[1] == 'p') && (dir[2] == ':') && (dir[3] == '/')) {
+ realName += 4;
+ }
+
+ // consolePrintf("Real cwd:%d\n", realName);
+
+ char* p = realName;
+ while (*p) {
+ if (*p == '\\') *p = '/';
+ p++;
+ }
+
+ // consolePrintf("Real cwd:%d\n", realName);
+ FAT_chdir(realName);
+ } else {
+ if ((strlen(dir) >= 4) && (dir[0] == 'd') && (dir[1] == 's') && (dir[2] == ':') && (dir[3] == '/')) {
+ realName += 4;
+ }
+
+ char* p = realName;
+ while (*p) {
+ if (*p == '\\') *p = '/';
+ p++;
+ }
+
+ strcpy(currentDir, realName);
+ if (*(currentDir + strlen(currentDir) - 1) == '/') {
+ *(currentDir + strlen(currentDir) - 1) = '\0';
+ }
+ consolePrintf("CWD: %s\n", currentDir);
+ }
+}
+
+int std_ferror(FILE* handle) {
+ return 0;
+}
+
+} // namespace DS
+
+// These functions are added to AbstractFileSystemNode and are therefore outside
+// the DS namespace.
+
+AbstractFilesystemNode *AbstractFilesystemNode::getCurrentDirectory() {
+// consolePrintf("New node");
+
+ if (DS::isGBAMPAvailable()) {
+ return new DS::GBAMPFileSystemNode();
+ } else {
+ return new DS::DSFileSystemNode();
+ }
+}
+
+AbstractFilesystemNode* AbstractFilesystemNode::getNodeForPath(const String& path) {
+ if (DS::isGBAMPAvailable()) {
+ return new DS::GBAMPFileSystemNode(path);
+ } else {
+ return new DS::DSFileSystemNode(path);
+ }
+} \ No newline at end of file