Ticket #8952: ds-stream.patch

File ds-stream.patch, 24.6 KB (added by fingolfin, 16 years ago)

First step

  • backends/platform/ds/arm9/makefile

     
    237237endif
    238238
    239239PORT_OBJS :=    $(portdir)/source/blitters_arm.o $(portdir)/source/cdaudio.o $(portdir)/source/dsmain.o \
    240                 $(portdir)/../../../fs/ds/ds-fs.o $(portdir)/source/gbampsave.o $(portdir)/source/scummhelp.o\
     240                $(portdir)/../../../fs/ds/ds-fs.o $(portdir)/../../../fs/ds/dsstream.o \
     241                $(portdir)/source/gbampsave.o $(portdir)/source/scummhelp.o\
    241242                $(portdir)/source/osystem_ds.o $(portdir)/source/portdefs.o $(portdir)/source/ramsave.o\
    242243                $(portdir)/source/scummconsole.o $(portdir)/source/touchkeyboard.o $(portdir)/source/zipreader.o\
    243244                $(portdir)/source/dsoptions.o $(portdir)/source/keys.o $(portdir)/source/wordcompletion.o
  • backends/fs/stdiostream.cpp

     
    5757        //#define fsize(a)                      ps2_fsize(a)    // not used -- and it is not a standard function either
    5858#endif
    5959
    60 #ifdef __DS__
    61 
    62         // These functions replace the standard library functions of the same name.
    63         // As this header is included after the standard one, I have the chance to #define
    64         // all of these to my own code.
    65         //
    66         // A #define is the only way, as redefinig the functions would cause linker errors.
    67 
    68         // These functions need to be #undef'ed, as their original definition
    69         // in devkitarm is done with #includes (ugh!)
    70         #undef feof
    71         #undef clearerr
    72         //#undef getc
    73         //#undef ferror
    74 
    75         #include "backends/fs/ds/ds-fs.h"
    76 
    77 
    78         // Only functions used in the ScummVM source have been defined here!
    79         #define fopen(name, mode)                                       DS::std_fopen(name, mode)
    80         #define fclose(handle)                                          DS::std_fclose(handle)
    81         #define fread(ptr, size, items, file)           DS::std_fread(ptr, size, items, file)
    82         #define fwrite(ptr, size, items, file)          DS::std_fwrite(ptr, size, items, file)
    83         #define feof(handle)                                            DS::std_feof(handle)
    84         #define ftell(handle)                                           DS::std_ftell(handle)
    85         #define fseek(handle, offset, whence)           DS::std_fseek(handle, offset, whence)
    86         #define clearerr(handle)                                        DS::std_clearerr(handle)
    87         #define fflush(file)                                            DS::std_fflush(file)
    88         #undef ferror
    89         #define ferror(handle)                                          DS::std_ferror(handle)
    90 
    91 #endif
    92 
    9360StdioStream::StdioStream(void *handle) : _handle(handle) {
    9461        assert(handle);
    9562}
  • backends/fs/ds/ds-fs.h

     
    2828#include "zipreader.h"
    2929#include "ramsave.h"
    3030#include "scummconsole.h"
    31 #include "fat/gba_nds_fat.h"
    3231#include "backends/fs/abstract-fs.h"
     32#include "backends/fs/ds/dsstream.h"
    3333
    3434namespace DS {
    3535
     
    159159        virtual Common::WriteStream *createWriteStream();
    160160};
    161161
    162 struct fileHandle {
    163         int pos;
    164         bool used;
    165         char* data;
    166         int size;
    167 
    168         DSSaveFile* sramFile;
    169 };
    170 
    171 #undef stderr
    172 #undef stdout
    173 #undef stdin
    174 
    175 #define stdout ((DS::fileHandle*) -1)
    176 #define stderr ((DS::fileHandle*) -2)
    177 #define stdin ((DS::fileHandle*) -3)
    178 
    179 #define FILE DS::fileHandle
    180 
    181 // Please do not remove any of these prototypes that appear not to be required.
    182 FILE*   std_fopen(const char* name, const char* mode);
    183 void    std_fclose(FILE* handle);
    184 size_t  std_fread(const void* ptr, size_t size, size_t numItems, FILE* handle);
    185 size_t  std_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle);
    186 bool    std_feof(FILE* handle);
    187 long int std_ftell(FILE* handle);
    188 int             std_fseek(FILE* handle, long int offset, int whence);
    189 void    std_clearerr(FILE* handle);
    190 int             std_fflush(FILE* handle);
    191 int             std_ferror(FILE* handle);
    192 
    193162} //namespace DS
    194163
    195164#endif //_DS_FS_H
  • backends/fs/ds/dsstream.cpp

     
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL$
     22 * $Id$
     23 *
     24 */
     25
     26#include "common/scummsys.h"
     27#include "backends/fs/ds/dsstream.h"
     28#include "backends/fs/ds/ds-fs.h"
     29//#include "common/system.h"
     30
     31#include "backends/platform/ds/arm9/source/dsmain.h"
     32#include "backends/platform/ds/arm9/source/fat/gba_nds_fat.h"
     33
     34namespace DS {
     35
     36
     37// Stdio replacements
     38#define MAX_FILE_HANDLES 32
     39
     40static bool readPastEndOfFile = false;
     41static bool inited = false;
     42static char             currentDir[128];
     43static DS::fileHandle handle[MAX_FILE_HANDLES];
     44
     45FILE* std_fopen(const char* name, const char* mode) {
     46        if (!inited) {
     47                for (int r = 0; r < MAX_FILE_HANDLES; r++) {
     48                        handle[r].used = false;
     49                }
     50                inited = true;
     51                currentDir[0] = '\0';
     52        }
     53
     54        char* realName = (char *) name;
     55
     56        // Remove file system prefix
     57        if ((name[0] == 'd') && (name[1] == 's') && (name[2] == ':') && (name[3] == '/')) {
     58                realName += 4;
     59        }
     60
     61        if ((name[0] == 'm') && (name[1] == 'p') && (name[2] == ':') && (name[3] == '/')) {
     62                realName += 4;
     63        }
     64
     65//      consolePrintf("Open file:");
     66//      consolePrintf("'%s', [%s]", name, realName);
     67
     68        if (DS::isGBAMPAvailable()) {
     69                FAT_chdir("/");
     70
     71                // Turn all back slashes into forward slashes for gba_nds_fat
     72                char* p = realName;
     73                while (*p) {
     74                        if (*p == '\\') *p = '/';
     75                        p++;
     76                }
     77
     78                FAT_FILE* result = FAT_fopen(realName, mode);
     79
     80                if (result == 0) {
     81//                      consolePrintf("Error code %d\n", result);
     82                        //consolePrintf("Opening file %s\n", realName);
     83                } else {
     84//                      consolePrintf("Opened file %d\n", result);
     85                }
     86//              MT_memoryReport();
     87
     88                return (FILE *) result;
     89        }
     90
     91        // Fail to open file for writing.  It's in ROM!
     92
     93        // Allocate a file handle
     94        int r = 0;
     95        while (handle[r].used) {
     96                r++;
     97                assert(r < MAX_FILE_HANDLES);
     98        }
     99
     100#ifdef GBA_SRAM_SAVE
     101        if (strchr(mode, 'w')) {
     102//              consolePrintf("Writing %s\n", realName);
     103                handle[r].sramFile = (DSSaveFile *) DSSaveFileManager::instance()->openSavefile(realName, true);
     104        } else {
     105//              consolePrintf("Reading %s\n", realName);
     106                handle[r].sramFile = (DSSaveFile *) DSSaveFileManager::instance()->openSavefile(realName, false);
     107        }
     108#endif
     109
     110        if (handle[r].sramFile) {
     111                handle[r].used = true;
     112                handle[r].pos = 0;
     113                handle[r].data = NULL;
     114                handle[r].size = handle[r].sramFile->getSize();
     115//              consolePrintf("Found it");
     116                return &handle[r];
     117        }
     118
     119//      consolePrintf("Not in SRAM!");
     120
     121        char* data;
     122
     123        ZipFile* zip = DSFileSystemNode::getZip();
     124        if (!zip) {
     125//              consolePrintf("No zip yet!");
     126                return NULL;
     127        }
     128
     129        // Grab the data if it exists
     130
     131        zip->setAllFilesVisible(true);
     132
     133        if (currentDir[0] != 0) {
     134                char nameWithPath[128];
     135                sprintf(nameWithPath, "%s\%s", currentDir, realName);
     136                strcpy(realName, nameWithPath);
     137        }
     138
     139//      consolePrintf("fopen(%s, %s)\n", realName, name);
     140
     141        if (zip->findFile(realName)) {
     142                data = zip->getFile();
     143                zip->setAllFilesVisible(false);
     144
     145                // Allocate a file handle
     146                int r = 0;
     147                while (handle[r].used) r++;
     148
     149
     150                handle[r].used = true;
     151                handle[r].pos = 0;
     152                handle[r].data = data;
     153                handle[r].size = zip->getFileSize();
     154
     155//              consolePrintf("Opened file %d: %s (%s)   ", r, realName, name);
     156                return &handle[r];
     157        } else {
     158                zip->setAllFilesVisible(false);
     159//              consolePrintf("Not found: %s (%s)  ", realName, name);
     160                return NULL;
     161        }
     162}
     163
     164void std_fclose(FILE* handle) {
     165
     166        if (DS::isGBAMPAvailable()) {
     167                FAT_fclose((FAT_FILE *) handle);
     168                return;
     169        }
     170
     171        handle->used = false;
     172        if (handle->sramFile) {
     173                delete handle->sramFile;
     174                handle->sramFile = NULL;
     175        }
     176}
     177
     178size_t std_fread(const void* ptr, size_t size, size_t numItems, FILE* handle) {
     179//      consolePrintf("fread %d,%d %d ", size, numItems, ptr);
     180
     181        if (DS::isGBAMPAvailable()) {
     182                readPastEndOfFile = false;
     183
     184                int bytes = FAT_fread((void *) ptr, size, numItems, (FAT_FILE *) handle);
     185                if (!FAT_feof((FAT_FILE *) handle)) {
     186                        return numItems;
     187                } else {
     188//                      consolePrintf("Read past end of file: %d read out of %d\n", bytes / size, numItems);
     189                        if ((size_t)bytes != size * numItems) readPastEndOfFile = true;
     190                        return bytes / size;
     191                }
     192                return numItems;
     193        }
     194
     195        if (handle->sramFile) {
     196                int bytes = 0;
     197                int result = 1;
     198                //consolePrintf("fread size=", size * numItems);
     199                for (int r = 0; (r < (s32) size * (s32) numItems) && (result > 0); r++) {
     200                        result = handle->sramFile->read((void *) ( ((char *) (ptr)) + r), 1);
     201                        bytes += result;
     202                        //consolePrintf("'%d',", ((char *) (ptr))[0]);
     203                }
     204
     205                handle->pos += bytes;
     206
     207                return bytes / size;
     208        }
     209
     210        if ((int)(handle->pos + size * numItems) > handle->size) {
     211                numItems = (handle->size - handle->pos) / size;
     212                if (numItems < 0) numItems = 0;
     213        }
     214
     215//      consolePrintf("read %d  ", size * numItems);
     216
     217        memcpy((void *) ptr, handle->data + handle->pos, size * numItems);
     218        handle->pos += size * numItems;
     219
     220        return numItems;
     221}
     222
     223size_t std_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle) {
     224        if ((handle == stdin)) return 0;
     225
     226        if ((handle == stderr) || (handle == stdout)) {
     227//              consolePrintf((char *) ptr);
     228                return size;
     229        }
     230
     231        //consolePrintf("fwrite size=%d\n", size * numItems);
     232
     233        if (DS::isGBAMPAvailable()) {
     234                FAT_fwrite(((char *) (ptr)), size, numItems, (FAT_FILE *) handle);
     235                return numItems;
     236
     237                int length = size * numItems;
     238                int pos = 0;
     239
     240                while (pos < length) {
     241                        int amount = length > 512? 512: length;
     242
     243                        FAT_fwrite(((char *) (ptr)) + pos, 1, amount, (FAT_FILE *) handle);
     244                        length -= amount;
     245                        pos += amount;
     246                }
     247
     248                return numItems;
     249        }
     250
     251        if (handle->sramFile) {
     252                handle->sramFile->write(ptr, size);
     253                return size;
     254        } else {
     255                return 0;
     256        }
     257}
     258
     259bool std_feof(FILE* handle) {
     260//      consolePrintf("feof ");
     261
     262        if (DS::isGBAMPAvailable()) {
     263                return readPastEndOfFile && FAT_feof((FAT_FILE *) handle);
     264        }
     265
     266        if (handle->sramFile) {
     267                return handle->sramFile->eos();
     268        }
     269
     270//      consolePrintf("feof %s", handle->pos >= handle->size? "true": "false");
     271        return handle->pos >= handle->size;
     272}
     273
     274long int std_ftell(FILE* handle) {
     275        if (DS::isGBAMPAvailable()) {
     276                return FAT_ftell((FAT_FILE *) handle);
     277        }
     278
     279        return handle->pos;
     280}
     281
     282int std_fseek(FILE* handle, long int offset, int whence) {
     283//      consolePrintf("fseek %d %d ", offset, whence);
     284
     285        if (DS::isGBAMPAvailable()) {
     286                return FAT_fseek((FAT_FILE *) handle, offset, whence);
     287        }
     288
     289        switch (whence) {
     290                case SEEK_CUR:
     291                        handle->pos += offset;
     292                        break;
     293                case SEEK_SET:
     294                        handle->pos = offset;
     295                        break;
     296                case SEEK_END:
     297                        handle->pos = handle->size + offset;
     298                        break;
     299                default:
     300                        handle->pos = offset;
     301                        break;
     302        }
     303
     304        return 0;
     305}
     306
     307int std_ferror(FILE* handle) {
     308        //FIXME: not implemented?
     309//      consolePrintf("ferror ");
     310
     311        return readPastEndOfFile;
     312}
     313
     314void std_clearerr(FILE* handle) {
     315}
     316
     317void std_fprintf(FILE* handle, const char* fmt, ...) {
     318        consolePrintf(fmt);
     319}
     320
     321
     322
     323DSStream::DSStream(void *handle) : _handle(handle) {
     324        assert(handle);
     325}
     326
     327DSStream::~DSStream() {
     328        DS::std_fclose((FILE *)_handle);
     329}
     330
     331bool DSStream::err() const {
     332        return DS::std_ferror((FILE *)_handle) != 0;
     333}
     334
     335void DSStream::clearErr() {
     336        //FIXME: not implemented?
     337        readPastEndOfFile = false;
     338//      consolePrintf("clearerr ");
     339}
     340
     341bool DSStream::eos() const {
     342        return DS::std_feof((FILE *)_handle) != 0;
     343}
     344
     345int32 DSStream::pos() const {
     346        return DS::std_ftell((FILE *)_handle);
     347}
     348
     349int32 DSStream::size() const {
     350        int32 oldPos = DS::std_ftell((FILE *)_handle);
     351        DS::std_fseek((FILE *)_handle, 0, SEEK_END);
     352        int32 length = DS::std_ftell((FILE *)_handle);
     353        DS::std_fseek((FILE *)_handle, oldPos, SEEK_SET);
     354
     355        return length;
     356}
     357
     358bool DSStream::seek(int32 offs, int whence) {
     359        return DS::std_fseek((FILE *)_handle, offs, whence) == 0;
     360}
     361
     362uint32 DSStream::read(void *ptr, uint32 len) {
     363        return DS::std_fread((byte *)ptr, 1, len, (FILE *)_handle);
     364}
     365
     366uint32 DSStream::write(const void *ptr, uint32 len) {
     367        return DS::std_fwrite(ptr, 1, len, (FILE *)_handle);
     368}
     369
     370bool DSStream::flush() {
     371        //FIXME: not implemented?
     372//      consolePrintf("fflush ");
     373        return true;
     374}
     375
     376DSStream *DSStream::makeFromPath(const Common::String &path, bool writeMode) {
     377        FILE *handle = DS::std_fopen(path.c_str(), writeMode ? "wb" : "rb");
     378        if (handle)
     379                return new DSStream(handle);
     380        return 0;
     381}
     382
     383} //namespace DS
  • backends/fs/ds/dsstream.h

    Eigenschaftsänderungen: backends/fs/ds/dsstream.cpp
    ___________________________________________________________________
    Name: svn:mime-type
       + text/plain
    Name: svn:keywords
       + Date Rev Author URL Id
    Name: svn:eol-style
       + native
    
     
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL$
     22 * $Id$
     23 *
     24 */
     25
     26#ifndef BACKENDS_FS_DS_STREAM_H
     27#define BACKENDS_FS_DS_STREAM_H
     28
     29#include "common/scummsys.h"
     30#include "common/noncopyable.h"
     31#include "common/stream.h"
     32#include "common/str.h"
     33
     34#include "zipreader.h"
     35#include "ramsave.h"
     36
     37namespace DS {
     38
     39class DSStream : public Common::SeekableReadStream, public Common::WriteStream, public Common::NonCopyable {
     40protected:
     41        /** File handle to the actual file. */
     42        void *_handle;
     43
     44public:
     45        /**
     46         * Given a path, invokes fopen on that path and wrap the result in a
     47         * StdioStream instance.
     48         */
     49        static DSStream *makeFromPath(const Common::String &path, bool writeMode);
     50
     51        DSStream(void *handle);
     52        virtual ~DSStream();
     53
     54        bool err() const;
     55        void clearErr();
     56        bool eos() const;
     57
     58        virtual uint32 write(const void *dataPtr, uint32 dataSize);
     59        virtual bool flush();
     60
     61        virtual int32 pos() const;
     62        virtual int32 size() const;
     63        bool seek(int32 offs, int whence = SEEK_SET);
     64        uint32 read(void *dataPtr, uint32 dataSize);
     65};
     66
     67struct fileHandle {
     68        int pos;
     69        bool used;
     70        char* data;
     71        int size;
     72
     73        DSSaveFile* sramFile;
     74};
     75
     76#undef stderr
     77#undef stdout
     78#undef stdin
     79
     80#define stdout ((DS::fileHandle*) -1)
     81#define stderr ((DS::fileHandle*) -2)
     82#define stdin ((DS::fileHandle*) -3)
     83
     84#define FILE DS::fileHandle
     85
     86// Please do not remove any of these prototypes that appear not to be required.
     87FILE*   std_fopen(const char* name, const char* mode);
     88void    std_fclose(FILE* handle);
     89size_t  std_fread(const void* ptr, size_t size, size_t numItems, FILE* handle);
     90size_t  std_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle);
     91bool    std_feof(FILE* handle);
     92long int std_ftell(FILE* handle);
     93int             std_fseek(FILE* handle, long int offset, int whence);
     94
     95} //namespace DS
     96
     97#endif
  • backends/fs/ds/ds-fs.cpp

    Eigenschaftsänderungen: backends/fs/ds/dsstream.h
    ___________________________________________________________________
    Name: svn:mime-type
       + text/plain
    Name: svn:keywords
       + Date Rev Author URL Id
    Name: svn:eol-style
       + native
    
     
    2424#include "common/util.h"
    2525//#include <NDS/ARM9/console.h> //basic print funcionality
    2626#include "backends/fs/ds/ds-fs.h"
    27 #include "backends/fs/stdiostream.h"
     27#include "backends/fs/ds/dsstream.h"
    2828#include "dsmain.h"
    2929#include "fat/gba_nds_fat.h"
    3030
     
    3737//////////////////////////////////////////////////////////////
    3838
    3939ZipFile*        DSFileSystemNode::_zipFile = NULL;
    40 char            currentDir[128];
    41 bool            readPastEndOfFile = false;
    4240
    4341DSFileSystemNode::DSFileSystemNode() {
    4442        _displayName = "ds:/";
     
    197195}
    198196
    199197Common::SeekableReadStream *DSFileSystemNode::createReadStream() {
    200         return StdioStream::makeFromPath(getPath().c_str(), false);
     198        return DSStream::makeFromPath(getPath().c_str(), false);
    201199}
    202200
    203201Common::WriteStream *DSFileSystemNode::createWriteStream() {
    204         return StdioStream::makeFromPath(getPath().c_str(), true);
     202        return DSStream::makeFromPath(getPath().c_str(), true);
    205203}
    206204
    207205//////////////////////////////////////////////////////////////////////////
     
    376374//      consolePrintf("Opening: %s\n", getPath().c_str());
    377375
    378376        if (!strncmp(getPath().c_str(), "mp:/", 4)) {
    379                 return StdioStream::makeFromPath(getPath().c_str() + 3, false);
     377                return DSStream::makeFromPath(getPath().c_str() + 3, false);
    380378        } else {
    381                 return StdioStream::makeFromPath(getPath().c_str(), false);
     379                return DSStream::makeFromPath(getPath().c_str(), false);
    382380        }
    383381}
    384382
    385383Common::WriteStream *GBAMPFileSystemNode::createWriteStream() {
    386         return StdioStream::makeFromPath(getPath().c_str(), true);
     384        return DSStream::makeFromPath(getPath().c_str(), true);
    387385}
    388386
    389 // Stdio replacements
    390 #define MAX_FILE_HANDLES 32
    391 
    392 bool inited = false;
    393 DS::fileHandle handle[MAX_FILE_HANDLES];
    394 
    395 FILE* std_fopen(const char* name, const char* mode) {
    396         if (!inited) {
    397                 for (int r = 0; r < MAX_FILE_HANDLES; r++) {
    398                         handle[r].used = false;
    399                 }
    400                 inited = true;
    401                 currentDir[0] = '\0';
    402         }
    403 
    404         char* realName = (char *) name;
    405 
    406         // Remove file system prefix
    407         if ((name[0] == 'd') && (name[1] == 's') && (name[2] == ':') && (name[3] == '/')) {
    408                 realName += 4;
    409         }
    410 
    411         if ((name[0] == 'm') && (name[1] == 'p') && (name[2] == ':') && (name[3] == '/')) {
    412                 realName += 4;
    413         }
    414 
    415 //      consolePrintf("Open file:");
    416 //      consolePrintf("'%s', [%s]", name, realName);
    417 
    418         if (DS::isGBAMPAvailable()) {
    419                 FAT_chdir("/");
    420 
    421                 // Turn all back slashes into forward slashes for gba_nds_fat
    422                 char* p = realName;
    423                 while (*p) {
    424                         if (*p == '\\') *p = '/';
    425                         p++;
    426                 }
    427 
    428                 FAT_FILE* result = FAT_fopen(realName, mode);
    429 
    430                 if (result == 0) {
    431 //                      consolePrintf("Error code %d\n", result);
    432                         //consolePrintf("Opening file %s\n", realName);
    433                 } else {
    434 //                      consolePrintf("Opened file %d\n", result);
    435                 }
    436 //              MT_memoryReport();
    437 
    438                 return (FILE *) result;
    439         }
    440 
    441         // Fail to open file for writing.  It's in ROM!
    442 
    443         // Allocate a file handle
    444         int r = 0;
    445         while (handle[r].used) {
    446                 r++;
    447                 assert(r < MAX_FILE_HANDLES);
    448         }
    449 
    450 #ifdef GBA_SRAM_SAVE
    451         if (strchr(mode, 'w')) {
    452 //              consolePrintf("Writing %s\n", realName);
    453                 handle[r].sramFile = (DSSaveFile *) DSSaveFileManager::instance()->openSavefile(realName, true);
    454         } else {
    455 //              consolePrintf("Reading %s\n", realName);
    456                 handle[r].sramFile = (DSSaveFile *) DSSaveFileManager::instance()->openSavefile(realName, false);
    457         }
    458 #endif
    459 
    460         if (handle[r].sramFile) {
    461                 handle[r].used = true;
    462                 handle[r].pos = 0;
    463                 handle[r].data = NULL;
    464                 handle[r].size = handle[r].sramFile->getSize();
    465 //              consolePrintf("Found it");
    466                 return &handle[r];
    467         }
    468 
    469 //      consolePrintf("Not in SRAM!");
    470 
    471         char* data;
    472 
    473         ZipFile* zip = DSFileSystemNode::getZip();
    474         if (!zip) {
    475 //              consolePrintf("No zip yet!");
    476                 return NULL;
    477         }
    478 
    479         // Grab the data if it exists
    480 
    481         zip->setAllFilesVisible(true);
    482 
    483         if (currentDir[0] != 0) {
    484                 char nameWithPath[128];
    485                 sprintf(nameWithPath, "%s\%s", currentDir, realName);
    486                 strcpy(realName, nameWithPath);
    487         }
    488 
    489 //      consolePrintf("fopen(%s, %s)\n", realName, name);
    490 
    491         if (zip->findFile(realName)) {
    492                 data = zip->getFile();
    493                 zip->setAllFilesVisible(false);
    494 
    495                 // Allocate a file handle
    496                 int r = 0;
    497                 while (handle[r].used) r++;
    498 
    499 
    500                 handle[r].used = true;
    501                 handle[r].pos = 0;
    502                 handle[r].data = data;
    503                 handle[r].size = zip->getFileSize();
    504 
    505 //              consolePrintf("Opened file %d: %s (%s)   ", r, realName, name);
    506                 return &handle[r];
    507         } else {
    508                 zip->setAllFilesVisible(false);
    509 //              consolePrintf("Not found: %s (%s)  ", realName, name);
    510                 return NULL;
    511         }
    512 }
    513 
    514 void std_fclose(FILE* handle) {
    515 
    516         if (DS::isGBAMPAvailable()) {
    517                 FAT_fclose((FAT_FILE *) handle);
    518                 return;
    519         }
    520 
    521         handle->used = false;
    522         if (handle->sramFile) {
    523                 delete handle->sramFile;
    524                 handle->sramFile = NULL;
    525         }
    526 }
    527 
    528 size_t std_fread(const void* ptr, size_t size, size_t numItems, FILE* handle) {
    529 //      consolePrintf("fread %d,%d %d ", size, numItems, ptr);
    530 
    531         if (DS::isGBAMPAvailable()) {
    532                 readPastEndOfFile = false;
    533 
    534                 int bytes = FAT_fread((void *) ptr, size, numItems, (FAT_FILE *) handle);
    535                 if (!FAT_feof((FAT_FILE *) handle)) {
    536                         return numItems;
    537                 } else {
    538 //                      consolePrintf("Read past end of file: %d read out of %d\n", bytes / size, numItems);
    539                         if ((size_t)bytes != size * numItems) readPastEndOfFile = true;
    540                         return bytes / size;
    541                 }
    542                 return numItems;
    543         }
    544 
    545         if (handle->sramFile) {
    546                 int bytes = 0;
    547                 int result = 1;
    548                 //consolePrintf("fread size=", size * numItems);
    549                 for (int r = 0; (r < (s32) size * (s32) numItems) && (result > 0); r++) {
    550                         result = handle->sramFile->read((void *) ( ((char *) (ptr)) + r), 1);
    551                         bytes += result;
    552                         //consolePrintf("'%d',", ((char *) (ptr))[0]);
    553                 }
    554 
    555                 handle->pos += bytes;
    556 
    557                 return bytes / size;
    558         }
    559 
    560         if ((int)(handle->pos + size * numItems) > handle->size) {
    561                 numItems = (handle->size - handle->pos) / size;
    562                 if (numItems < 0) numItems = 0;
    563         }
    564 
    565 //      consolePrintf("read %d  ", size * numItems);
    566 
    567         memcpy((void *) ptr, handle->data + handle->pos, size * numItems);
    568         handle->pos += size * numItems;
    569 
    570         return numItems;
    571 }
    572 
    573 size_t std_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle) {
    574         if ((handle == stdin)) return 0;
    575 
    576         if ((handle == stderr) || (handle == stdout)) {
    577 //              consolePrintf((char *) ptr);
    578                 return size;
    579         }
    580 
    581         //consolePrintf("fwrite size=%d\n", size * numItems);
    582 
    583         if (DS::isGBAMPAvailable()) {
    584                 FAT_fwrite(((char *) (ptr)), size, numItems, (FAT_FILE *) handle);
    585                 return numItems;
    586 
    587                 int length = size * numItems;
    588                 int pos = 0;
    589 
    590                 while (pos < length) {
    591                         int amount = length > 512? 512: length;
    592 
    593                         FAT_fwrite(((char *) (ptr)) + pos, 1, amount, (FAT_FILE *) handle);
    594                         length -= amount;
    595                         pos += amount;
    596                 }
    597 
    598                 return numItems;
    599         }
    600 
    601         if (handle->sramFile) {
    602                 handle->sramFile->write(ptr, size);
    603                 return size;
    604         } else {
    605                 return 0;
    606         }
    607 }
    608 
    609 bool std_feof(FILE* handle) {
    610 //      consolePrintf("feof ");
    611 
    612         if (DS::isGBAMPAvailable()) {
    613                 return readPastEndOfFile && FAT_feof((FAT_FILE *) handle);
    614         }
    615 
    616         if (handle->sramFile) {
    617                 return handle->sramFile->eos();
    618         }
    619 
    620 //      consolePrintf("feof %s", handle->pos >= handle->size? "true": "false");
    621         return handle->pos >= handle->size;
    622 }
    623 
    624 int std_fflush(FILE* handle) {
    625         //FIXME: not implemented?
    626 //      consolePrintf("fflush ");
    627         return 0;
    628 }
    629 
    630 long int std_ftell(FILE* handle) {
    631         if (DS::isGBAMPAvailable()) {
    632                 return FAT_ftell((FAT_FILE *) handle);
    633         }
    634 
    635         return handle->pos;
    636 }
    637 
    638 int std_fseek(FILE* handle, long int offset, int whence) {
    639 //      consolePrintf("fseek %d %d ", offset, whence);
    640 
    641         if (DS::isGBAMPAvailable()) {
    642                 return FAT_fseek((FAT_FILE *) handle, offset, whence);
    643         }
    644 
    645         switch (whence) {
    646                 case SEEK_CUR:
    647                         handle->pos += offset;
    648                         break;
    649                 case SEEK_SET:
    650                         handle->pos = offset;
    651                         break;
    652                 case SEEK_END:
    653                         handle->pos = handle->size + offset;
    654                         break;
    655                 default:
    656                         handle->pos = offset;
    657                         break;
    658         }
    659 
    660         return 0;
    661 }
    662 
    663 int std_ferror(FILE* handle) {
    664         //FIXME: not implemented?
    665 //      consolePrintf("ferror ");
    666 
    667         return readPastEndOfFile;
    668 }
    669 
    670 void std_clearerr(FILE* handle) {
    671         //FIXME: not implemented?
    672         readPastEndOfFile = false;
    673 //      consolePrintf("clearerr ");
    674 }
    675 
    676 void std_fprintf(FILE* handle, const char* fmt, ...) {
    677         consolePrintf(fmt);
    678 }
    679 
    680 
    681387} // namespace DS