Logo Search packages:      
Sourcecode: scummvm version File versions

ds-fs.cpp

/* 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& n) const {
      if (_path.lastChar() == '\\') {
            return new DSFileSystemNode(_path + n);
      } else {
            return new DSFileSystemNode(_path + "\\" + n);
      }
      
      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 n[128];      
                  _zipFile->getFileName(n);
      
//                consolePrintf("file: %s\n", n);
                  if ( (_zipFile->isDirectory() && ((mode == FilesystemNode::kListDirectoriesOnly) || (mode == FilesystemNode::kListAll)) ) 
                        || (!_zipFile->isDirectory() && ((mode == FilesystemNode::kListFilesOnly) || (mode == FilesystemNode::kListAll)) ) ) 
                  {
                        DSFileSystemNode* dsfsn = new DSFileSystemNode("ds:/" + String(n), _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& n) const {
      if (_path.lastChar() == '\\') {
            return new DSFileSystemNode(_path + n);
      } else {
            return new DSFileSystemNode(_path + "\\" + n);
      }
      
      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.

00852 AbstractFilesystemNode *AbstractFilesystemNode::getCurrentDirectory() {
//    consolePrintf("New node");
        
      if (DS::isGBAMPAvailable()) {
            return new DS::GBAMPFileSystemNode();
      } else {
            return new DS::DSFileSystemNode();
      }
}

00862 AbstractFilesystemNode* AbstractFilesystemNode::getNodeForPath(const String& path) {
      if (DS::isGBAMPAvailable()) {
            return new DS::GBAMPFileSystemNode(path);
      } else {
            return new DS::DSFileSystemNode(path);
      }
}

Generated by  Doxygen 1.6.0   Back to index