From 1ffa13180f9b0eef110a6548d840257c15343804 Mon Sep 17 00:00:00 2001 From: James Brown Date: Sun, 9 Jul 2006 14:46:04 +0000 Subject: More DS port fixes svn-id: r23460 --- backends/platform/ds/arm9/source/compressor/lz.cpp | 539 ---- backends/platform/ds/arm9/source/dsoptions.cpp | 208 +- backends/platform/ds/arm9/source/fat/disc_io.c | 423 --- backends/platform/ds/arm9/source/fat/gba_nds_fat.c | 3333 -------------------- backends/platform/ds/arm9/source/fat/io_fcsr.c | 329 -- backends/platform/ds/arm9/source/fat/io_m3cf.c | 367 --- backends/platform/ds/arm9/source/fat/io_m3sd.c | 375 --- backends/platform/ds/arm9/source/fat/io_m3sd_asm.s | 197 -- backends/platform/ds/arm9/source/fat/io_mpcf.c | 357 --- backends/platform/ds/arm9/source/fat/io_nmmc.c | 358 --- backends/platform/ds/arm9/source/fat/io_sccf.c | 87 - backends/platform/ds/arm9/source/fat/io_scsd.c | 92 - backends/platform/ds/arm9/source/scummconsole.c | 2 +- backends/platform/ds/arm9/source/touchkeyboard.cpp | 315 +- backends/platform/ds/arm9/source/zipreader.cpp | 221 -- backends/platform/ds/makefile | 22 - 16 files changed, 3 insertions(+), 7222 deletions(-) (limited to 'backends') diff --git a/backends/platform/ds/arm9/source/compressor/lz.cpp b/backends/platform/ds/arm9/source/compressor/lz.cpp index 237b432ce8..1234bf7b3b 100644 --- a/backends/platform/ds/arm9/source/compressor/lz.cpp +++ b/backends/platform/ds/arm9/source/compressor/lz.cpp @@ -477,545 +477,6 @@ int LZ_CompressFast( unsigned char *in, unsigned char *out, } -/************************************************************************* -* LZ_Uncompress() - Uncompress a block of data using an LZ77 decoder. -* in - Input (compressed) buffer. -* out - Output (uncompressed) buffer. This buffer must be large -* enough to hold the uncompressed data. -* insize - Number of input bytes. -*************************************************************************/ - -void LZ_Uncompress( unsigned char *in, unsigned char *out, - unsigned int insize ) -{ - unsigned char marker, symbol; - unsigned int i, inpos, outpos, length, offset; - - /* Do we have anything to compress? */ - if( insize < 1 ) - { - return; - } - - /* Get marker symbol from input stream */ - marker = in[ 0 ]; - inpos = 1; - - /* Main decompression loop */ - outpos = 0; - do - { - symbol = in[ inpos ++ ]; - if( symbol == marker ) - { - /* We had a marker byte */ - if( in[ inpos ] == 0 ) - { - /* It was a single occurrence of the marker byte */ - out[ outpos ++ ] = marker; - ++ inpos; - } - else - { - /* Extract true length and offset */ - inpos += _LZ_ReadVarSize( &length, &in[ inpos ] ); - inpos += _LZ_ReadVarSize( &offset, &in[ inpos ] ); - - /* Copy corresponding data from history window */ - for( i = 0; i < length; ++ i ) - { - out[ outpos ] = out[ outpos - offset ]; - ++ outpos; - } - } - } - else - { - /* No marker, plain copy */ - out[ outpos ++ ] = symbol; - } - } - while( inpos < insize ); -} -/************************************************************************* -* Name: lz.c -* Author: Marcus Geelnard -* Description: LZ77 coder/decoder implementation. -* Reentrant: Yes -* $Id$ -* -* The LZ77 compression scheme is a substitutional compression scheme -* proposed by Abraham Lempel and Jakob Ziv in 1977. It is very simple in -* its design, and uses no fancy bit level compression. -* -* This is my first attempt at an implementation of a LZ77 code/decoder. -* -* The principle of the LZ77 compression algorithm is to store repeated -* occurrences of strings as references to previous occurrences of the same -* string. The point is that the reference consumes less space than the -* string itself, provided that the string is long enough (in this -* implementation, the string has to be at least 4 bytes long, since the -* minimum coded reference is 3 bytes long). Also note that the term -* "string" refers to any kind of byte sequence (it does not have to be -* an ASCII string, for instance). -* -* The coder uses a brute force approach to finding string matches in the -* history buffer (or "sliding window", if you wish), which is very, very -* slow. I recon the complexity is somewhere between O(n^2) and O(n^3), -* depending on the input data. -* -* There is also a faster implementation that uses a large working buffer -* in which a "jump table" is stored, which is used to quickly find -* possible string matches (see the source code for LZ_CompressFast() for -* more information). The faster method is an order of magnitude faster, -* and also does a full string search in the entire input buffer (it does -* not use a sliding window). -* -* The upside is that decompression is very fast, and the compression ratio -* is often very good. -* -* The reference to a string is coded as a (length,offset) pair, where the -* length indicates the length of the string, and the offset gives the -* offset from the current data position. To distinguish between string -* references and literal strings (uncompressed bytes), a string reference -* is preceded by a marker byte, which is chosen as the least common byte -* symbol in the input data stream (this marker byte is stored in the -* output stream as the first byte). -* -* Occurrences of the marker byte in the stream are encoded as the marker -* byte followed by a zero byte, which means that occurrences of the marker -* byte have to be coded with two bytes. -* -* The lengths and offsets are coded in a variable length fashion, allowing -* values of any magnitude (up to 4294967295 in this implementation). -* -* With this compression scheme, the worst case compression result is -* (257/256)*insize + 1. -* -*------------------------------------------------------------------------- -* Copyright (c) 2003-2004 Marcus Geelnard -* -* This software is provided 'as-is', without any express or implied -* warranty. In no event will the authors be held liable for any damages -* arising from the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software -* in a product, an acknowledgment in the product documentation would -* be appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not -* be misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source -* distribution. -* -* Marcus Geelnard -* marcus.geelnard at home.se -*************************************************************************/ - - -/************************************************************************* -* Constants used for LZ77 coding -*************************************************************************/ - -/* Maximum offset (can be any size < 2^32). Lower values gives faster - compression, while higher values gives better compression. - NOTE: LZ_CompressFast does not use this constant. */ -#define LZ_MAX_OFFSET 512 - - - -/************************************************************************* -* INTERNAL FUNCTIONS * -*************************************************************************/ - - -/************************************************************************* -* _LZ_StringCompare() - Return maximum length string match. -*************************************************************************/ - -inline static unsigned int _LZ_StringCompare( unsigned char * str1, - unsigned char * str2, unsigned int minlen, unsigned int maxlen ) -{ - unsigned int len; - - for( len = minlen; (len < maxlen) && (str1[len] == str2[len]); ++ len ); - - return len; -} - - -/************************************************************************* -* _LZ_WriteVarSize() - Write unsigned integer with variable number of -* bytes depending on value. -*************************************************************************/ - -inline static int _LZ_WriteVarSize( unsigned int x, unsigned char * buf ) -{ - unsigned int y; - int num_bytes, i, b; - - /* Determine number of bytes needed to store the number x */ - y = x >> 3; - for( num_bytes = 5; num_bytes >= 2; -- num_bytes ) - { - if( y & 0xfe000000 ) break; - y <<= 7; - } - - /* Write all bytes, seven bits in each, with 8:th bit set for all */ - /* but the last byte. */ - for( i = num_bytes-1; i >= 0; -- i ) - { - b = (x >> (i*7)) & 0x0000007f; - if( i > 0 ) - { - b |= 0x00000080; - } - *buf ++ = (unsigned char) b; - } - - /* Return number of bytes written */ - return num_bytes; -} - - -/************************************************************************* -* _LZ_ReadVarSize() - Read unsigned integer with variable number of -* bytes depending on value. -*************************************************************************/ - -inline static int _LZ_ReadVarSize( unsigned int * x, unsigned char * buf ) -{ - unsigned int y, b, num_bytes; - - /* Read complete value (stop when byte contains zero in 8:th bit) */ - y = 0; - num_bytes = 0; - do - { - b = (unsigned int) (*buf ++); - y = (y << 7) | (b & 0x0000007f); - ++ num_bytes; - } - while( b & 0x00000080 ); - - /* Store value in x */ - *x = y; - - /* Return number of bytes read */ - return num_bytes; -} - - - -/************************************************************************* -* PUBLIC FUNCTIONS * -*************************************************************************/ - - -/************************************************************************* -* LZ_Compress() - Compress a block of data using an LZ77 coder. -* in - Input (uncompressed) buffer. -* out - Output (compressed) buffer. This buffer must be 0.4% larger -* than the input buffer, plus one byte. -* insize - Number of input bytes. -* The function returns the size of the compressed data. -*************************************************************************/ - -int LZ_Compress( unsigned char *in, unsigned char *out, - unsigned int insize ) -{ - unsigned char marker, symbol; - unsigned int inpos, outpos, bytesleft, i; - unsigned int maxoffset, offset, bestoffset; - unsigned int maxlength, length, bestlength; - unsigned int histogram[ 256 ]; - unsigned char *ptr1, *ptr2; - - /* Do we have anything to compress? */ - if( insize < 1 ) - { - return 0; - } - - /* Create histogram */ - for( i = 0; i < 256; ++ i ) - { - histogram[ i ] = 0; - } - for( i = 0; i < insize; ++ i ) - { - ++ histogram[ in[ i ] ]; - } - - /* Find the least common byte, and use it as the code marker */ - marker = 0; - for( i = 1; i < 256; ++ i ) - { - if( histogram[ i ] < histogram[ marker ] ) - { - marker = i; - } - } - - /* Remember the repetition marker for the decoder */ - out[ 0 ] = marker; - - /* Start of compression */ - inpos = 0; - outpos = 1; - - /* Main compression loop */ - bytesleft = insize; - do - { - /* Determine most distant position */ - if( inpos > LZ_MAX_OFFSET ) maxoffset = LZ_MAX_OFFSET; - else maxoffset = inpos; - - /* Get pointer to current position */ - ptr1 = &in[ inpos ]; - - /* Search history window for maximum length string match */ - bestlength = 3; - bestoffset = 0; - for( offset = 3; offset <= maxoffset; ++ offset ) - { - /* Get pointer to candidate string */ - ptr2 = &ptr1[ -offset ]; - - /* Quickly determine if this is a candidate (for speed) */ - if( (ptr1[ 0 ] == ptr2[ 0 ]) && - (ptr1[ bestlength ] == ptr2[ bestlength ]) ) - { - /* Determine maximum length for this offset */ - maxlength = (bytesleft < offset ? bytesleft : offset); - - /* Count maximum length match at this offset */ - length = _LZ_StringCompare( ptr1, ptr2, 0, maxlength ); - - /* Better match than any previous match? */ - if( length > bestlength ) - { - bestlength = length; - bestoffset = offset; - } - } - } - - /* Was there a good enough match? */ - if( (bestlength >= 8) || - ((bestlength == 4) && (bestoffset <= 0x0000007f)) || - ((bestlength == 5) && (bestoffset <= 0x00003fff)) || - ((bestlength == 6) && (bestoffset <= 0x001fffff)) || - ((bestlength == 7) && (bestoffset <= 0x0fffffff)) ) - { - out[ outpos ++ ] = (unsigned char) marker; - outpos += _LZ_WriteVarSize( bestlength, &out[ outpos ] ); - outpos += _LZ_WriteVarSize( bestoffset, &out[ outpos ] ); - inpos += bestlength; - bytesleft -= bestlength; - } - else - { - /* Output single byte (or two bytes if marker byte) */ - symbol = in[ inpos ++ ]; - out[ outpos ++ ] = symbol; - if( symbol == marker ) - { - out[ outpos ++ ] = 0; - } - -- bytesleft; - } - } - while( bytesleft > 3 ); - - /* Dump remaining bytes, if any */ - while( inpos < insize ) - { - if( in[ inpos ] == marker ) - { - out[ outpos ++ ] = marker; - out[ outpos ++ ] = 0; - } - else - { - out[ outpos ++ ] = in[ inpos ]; - } - ++ inpos; - } - - return outpos; -} - - -/************************************************************************* -* LZ_CompressFast() - Compress a block of data using an LZ77 coder. -* in - Input (uncompressed) buffer. -* out - Output (compressed) buffer. This buffer must be 0.4% larger -* than the input buffer, plus one byte. -* insize - Number of input bytes. -* work - Pointer to a temporary buffer (internal working buffer), which -* must be able to hold (insize+65536) unsigned integers. -* The function returns the size of the compressed data. -*************************************************************************/ - -int LZ_CompressFast( unsigned char *in, unsigned char *out, - unsigned int insize, unsigned int *work ) -{ - unsigned char marker, symbol; - unsigned int inpos, outpos, bytesleft, i, index, symbols; - unsigned int offset, bestoffset; - unsigned int maxlength, length, bestlength; - unsigned int histogram[ 256 ], *lastindex, *jumptable; - unsigned char *ptr1, *ptr2; - - /* Do we have anything to compress? */ - if( insize < 1 ) - { - return 0; - } - - /* Assign arrays to the working area */ - lastindex = work; - jumptable = &work[ 65536 ]; - - /* Build a "jump table". Here is how the jump table works: - jumptable[i] points to the nearest previous occurrence of the same - symbol pair as in[i]:in[i+1], so in[i] == in[jumptable[i]] and - in[i+1] == in[jumptable[i]+1]. Following the jump table gives a - dramatic boost for the string search'n'match loop compared to doing - a brute force search. */ - for( i = 0; i < 65536; ++ i ) - { - lastindex[ i ] = 0xffffffff; - } - for( i = 0; i < insize-1; ++ i ) - { - symbols = (((unsigned int)in[i]) << 8) | ((unsigned int)in[i+1]); - index = lastindex[ symbols ]; - lastindex[ symbols ] = i; - jumptable[ i ] = index; - } - jumptable[ insize-1 ] = 0xffffffff; - - /* Create histogram */ - for( i = 0; i < 256; ++ i ) - { - histogram[ i ] = 0; - } - for( i = 0; i < insize; ++ i ) - { - ++ histogram[ in[ i ] ]; - } - - /* Find the least common byte, and use it as the code marker */ - marker = 0; - for( i = 1; i < 256; ++ i ) - { - if( histogram[ i ] < histogram[ marker ] ) - { - marker = i; - } - } - - /* Remember the repetition marker for the decoder */ - out[ 0 ] = marker; - - /* Start of compression */ - inpos = 0; - outpos = 1; - - /* Main compression loop */ - bytesleft = insize; - do - { - /* Get pointer to current position */ - ptr1 = &in[ inpos ]; - - /* Search history window for maximum length string match */ - bestlength = 3; - bestoffset = 0; - index = jumptable[ inpos ]; - while( index != 0xffffffff ) - { - /* Get pointer to candidate string */ - ptr2 = &in[ index ]; - - /* Quickly determine if this is a candidate (for speed) */ - if( ptr2[ bestlength ] == ptr1[ bestlength ] ) - { - /* Determine maximum length for this offset */ - offset = inpos - index; - maxlength = (bytesleft < offset ? bytesleft : offset); - - /* Count maximum length match at this offset */ - length = _LZ_StringCompare( ptr1, ptr2, 2, maxlength ); - - /* Better match than any previous match? */ - if( length > bestlength ) - { - bestlength = length; - bestoffset = offset; - } - } - - /* Get next possible index from jump table */ - index = jumptable[ index ]; - } - - /* Was there a good enough match? */ - if( (bestlength >= 8) || - ((bestlength == 4) && (bestoffset <= 0x0000007f)) || - ((bestlength == 5) && (bestoffset <= 0x00003fff)) || - ((bestlength == 6) && (bestoffset <= 0x001fffff)) || - ((bestlength == 7) && (bestoffset <= 0x0fffffff)) ) - { - out[ outpos ++ ] = (unsigned char) marker; - outpos += _LZ_WriteVarSize( bestlength, &out[ outpos ] ); - outpos += _LZ_WriteVarSize( bestoffset, &out[ outpos ] ); - inpos += bestlength; - bytesleft -= bestlength; - } - else - { - /* Output single byte (or two bytes if marker byte) */ - symbol = in[ inpos ++ ]; - out[ outpos ++ ] = symbol; - if( symbol == marker ) - { - out[ outpos ++ ] = 0; - } - -- bytesleft; - } - } - while( bytesleft > 3 ); - - /* Dump remaining bytes, if any */ - while( inpos < insize ) - { - if( in[ inpos ] == marker ) - { - out[ outpos ++ ] = marker; - out[ outpos ++ ] = 0; - } - else - { - out[ outpos ++ ] = in[ inpos ]; - } - ++ inpos; - } - - return outpos; -} - - /************************************************************************* * LZ_Uncompress() - Uncompress a block of data using an LZ77 decoder. * in - Input (compressed) buffer. diff --git a/backends/platform/ds/arm9/source/dsoptions.cpp b/backends/platform/ds/arm9/source/dsoptions.cpp index 04db01389b..5d168a9ac6 100644 --- a/backends/platform/ds/arm9/source/dsoptions.cpp +++ b/backends/platform/ds/arm9/source/dsoptions.cpp @@ -21,213 +21,7 @@ #include "dsmain.h" #include "gui/dialog.h" #include "gui/newgui.h" -#include "gui/listwidget.h" -#include "osystem_ds.h" -#include "engines/scumm/scumm.h" -#include "touchkeyboard.h" - -#ifdef DS_SCUMM_BUILD -namespace Scumm { - extern Common::StringList generateSavegameList(Scumm::ScummEngine *scumm, bool saveMode); - extern Scumm::ScummEngine *g_scumm; -} -#endif - -namespace DS { - -DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(20, 20, 320 - 40, 200 - 40) { - addButton(this, 10, 140, "Close", GUI::kCloseCmd, 'C'); - -#ifdef DS_SCUMM_BUILD - if (!DS::isGBAMPAvailable()) { -// addButton(this, 100, 140, "Delete Save", 'dels', 'D'); - } -#endif - - new GUI::StaticTextWidget(this, 0, 10, 280, 20, "ScummVM DS Options", GUI::kTextAlignCenter); - - _leftHandedCheckbox = new GUI::CheckboxWidget(this, 20, 30, 280, 20, "Left handed mode", 0, 'L'); - _indyFightCheckbox = new GUI::CheckboxWidget(this, 20, 50, 280, 20, "Indy fighting controls", 0, 'I'); - _unscaledCheckbox = new GUI::CheckboxWidget(this, 20, 70, 280, 20, "Unscaled lower screen", 0, 'S'); - - new GUI::StaticTextWidget(this, 20, 90, 110, 20, "Touch X Offset", GUI::kTextAlignLeft); - _touchX = new GUI::SliderWidget(this, 130, 90, 130, 12, 1); - _touchX->setMinValue(-8); - _touchX->setMaxValue(+8); - _touchX->setValue(0); - _touchX->setFlags(GUI::WIDGET_CLEARBG); - - new GUI::StaticTextWidget(this, 20, 110, 110, 20, "Touch Y Offset", GUI::kTextAlignLeft); - _touchY = new GUI::SliderWidget(this, 130, 110, 130, 12, 2); - _touchY->setMinValue(-8); - _touchY->setMaxValue(+8); - _touchY->setValue(0); - _touchY->setFlags(GUI::WIDGET_CLEARBG); - - new GUI::StaticTextWidget(this, 130 + 65 - 10, 130, 20, 20, "0", GUI::kTextAlignCenter); - new GUI::StaticTextWidget(this, 130 + 130 - 10, 130, 20, 20, "8", GUI::kTextAlignCenter); - new GUI::StaticTextWidget(this, 130 - 10, 130, 20, 20, "-8", GUI::kTextAlignCenter); - -#ifdef DS_SCUMM_BUILD - _delDialog = new Scumm::SaveLoadChooser("Delete game:", "Delete", false, Scumm::g_scumm); -#endif - - if (ConfMan.hasKey("lefthanded", "ds")) { - _leftHandedCheckbox->setState(ConfMan.getBool("lefthanded", "ds")); - } else { - _leftHandedCheckbox->setState(false); - } - - if (ConfMan.hasKey("unscaled", "ds")) { - _unscaledCheckbox->setState(ConfMan.getBool("unscaled", "ds")); - } else { - _unscaledCheckbox->setState(false); - } - - _indyFightCheckbox->setState(DS::getIndyFightState()); - - if (ConfMan.hasKey("xoffset", "ds")) { - _touchX->setValue(ConfMan.getInt("xoffset", "ds")); - } else { - _touchX->setValue(0); - } - - if (ConfMan.hasKey("yoffset", "ds")) { - _touchY->setValue(ConfMan.getInt("yoffset", "ds")); - } else { - _touchY->setValue(0); - } - -} - -DSOptionsDialog::~DSOptionsDialog() { - ConfMan.setBool("lefthanded", _leftHandedCheckbox->getState(), "ds"); - ConfMan.setBool("unscaled", _unscaledCheckbox->getState(), "ds"); - ConfMan.setInt("xoffset", _touchX->getValue(), "ds"); - ConfMan.setInt("yoffset", _touchY->getValue(), "ds"); - DS::setOptions(); - DS::setIndyFightState(_indyFightCheckbox->getState()); - ConfMan.flushToDisk(); -} - - -void DSOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) { - if (cmd == GUI::kCloseCmd) { - close(); - } - -#ifdef DS_SCUMM_BUILD -/* if (cmd == 'dels') { - _delDialog->setList(Scumm::generateSavegameList(Scumm::g_scumm, false)); - _delDialog->handleCommand(NULL, GUI::kListSelectionChangedCmd, 0); - - OSystem::Event event; - event.type = OSystem::EVENT_KEYDOWN; - event.kbd.ascii = SDLK_DOWN; - event.kbd.keycode = SDLK_DOWN; - OSystem_DS::instance()->addEvent(event); - - event.type = OSystem::EVENT_KEYUP; - OSystem_DS::instance()->addEvent(event); - - int idx = _delDialog->runModal(); - - if (idx >= 0) { - char name[256]; - Scumm::g_scumm->makeSavegameName(name, idx, false); - if (!DS::isGBAMPAvailable()) { - ((DSSaveFileManager *) (OSystem_DS::instance()->getSavefileManager()))->deleteFile(name); - } - } - - }*/ -#endif - - -} - -void showOptionsDialog() { - OSystem_DS* system = OSystem_DS::instance(); - - OSystem::Event event; - event.type = OSystem::EVENT_KEYDOWN; - event.kbd.keycode = 'P'; // F5 - event.kbd.ascii = 'P'; - event.kbd.flags = 0; - system->addEvent(event); - - DS::displayMode16Bit(); - - - DSOptionsDialog* d = new DSOptionsDialog(); - d->runModal(); - delete d; - - - DS::displayMode8Bit(); - - event.type = OSystem::EVENT_KEYDOWN; - event.kbd.keycode = 'P'; // F5 - event.kbd.ascii = 'P'; - event.kbd.flags = 0; - system->addEvent(event); -} - -void setOptions() { - ConfMan.addGameDomain("ds"); - - if (ConfMan.hasKey("lefthanded", "ds")) { - DS::setLeftHanded(ConfMan.getBool("lefthanded", "ds")); - } else { - DS::setLeftHanded(false); - } - - if (ConfMan.hasKey("unscaled", "ds")) { - DS::setUnscaledMode(ConfMan.getBool("unscaled", "ds")); - } else { - DS::setUnscaledMode(false); - } - - if (ConfMan.hasKey("xoffset", "ds")) { - DS::setTouchXOffset(ConfMan.getInt("xoffset", "ds")); - } else { - DS::setTouchXOffset(0); - } - - if (ConfMan.hasKey("yoffset", "ds")) { - DS::setTouchYOffset(ConfMan.getInt("yoffset", "ds")); - } else { - DS::setTouchXOffset(0); - } - -} - -} - -/* 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 "dsoptions.h" -#include "dsmain.h" -#include "gui/dialog.h" -#include "gui/newgui.h" -#include "gui/listwidget.h" +#include "gui/ListWidget.h" #include "osystem_ds.h" #include "engines/scumm/scumm.h" #include "touchkeyboard.h" diff --git a/backends/platform/ds/arm9/source/fat/disc_io.c b/backends/platform/ds/arm9/source/fat/disc_io.c index f2fbee5d65..a977dc9023 100644 --- a/backends/platform/ds/arm9/source/fat/disc_io.c +++ b/backends/platform/ds/arm9/source/fat/disc_io.c @@ -419,426 +419,3 @@ u32 disc_HostType (void) return 0; } } - -/* - - disc_io.c - - uniformed io-interface to work with Chishm's FAT library - - Written by MightyMax - - Modified by Chishm: - 2005-11-06 - * Added WAIT_CR modifications for NDS - - Modified by www.neoflash.com: - 2006-02-03 - * Added SUPPORT_* defines, comment out any of the SUPPORT_* defines in disc_io.h to remove support - for the given interface and stop code being linked to the binary - - * Added support for MK2 MMC interface - - * Added disc_Cache* functions - - Modified by Chishm: - 2006-02-05 - * Added Supercard SD support - - Modified by CyteX: - 2006-02-26 - * Added EFA2 support -*/ - -#include "disc_io.h" - -#ifdef NDS - #include -#endif - - -// Include known io-interfaces: -#ifdef SUPPORT_MPCF - #include "io_mpcf.h" -#endif - -#ifdef SUPPORT_M3CF - #include "io_m3cf.h" -#endif - -#ifdef SUPPORT_M3SD - #include "io_m3sd.h" -#endif - -#ifdef SUPPORT_SCCF - #include "io_sccf.h" -#endif - -#ifdef SUPPORT_SCSD - #include "io_scsd.h" -#endif - -#ifdef SUPPORT_FCSR - #include "io_fcsr.h" -#endif - -#ifdef SUPPORT_NMMC - #include "io_nmmc.h" -#endif - -#ifdef SUPPORT_EFA2 - #include "io_efa2.h" -#endif - -// Keep a pointer to the active interface -LPIO_INTERFACE active_interface = 0; - - -/* - - Disc Cache functions - 2006-02-03: - Added by www.neoflash.com - -*/ - -#ifdef DISC_CACHE - -#include - -#define CACHE_FREE 0xFFFFFFFF - -static u8 cacheBuffer[ DISC_CACHE_COUNT * 512 ]; - -static struct { - u32 sector; - u32 dirty; - u32 count; -} cache[ DISC_CACHE_COUNT ]; - -static u32 disc_CacheFind(u32 sector) { - u32 i; - - for( i = 0; i < DISC_CACHE_COUNT; i++ ) { - if( cache[ i ].sector == sector ) - return i; - } - - return CACHE_FREE; -} - -static u32 disc_CacheFindFree(void) { - - u32 i = 0, j; - u32 count = -1; - - for( j = 0; j < DISC_CACHE_COUNT; j++ ) { - - if( cache[ j ].sector == CACHE_FREE ) { - i = j; - break; - } - - if( cache[ j ].count < count ) { - count = cache[ j ].count; - i = j; - } - } - - if( cache[ i ].sector != CACHE_FREE && cache[i].dirty != 0 ) { - - active_interface->fn_WriteSectors( cache[ i ].sector, 1, &cacheBuffer[ i * 512 ] ); - /* todo: handle write error here */ - - cache[ i ].sector = CACHE_FREE; - cache[ i ].dirty = 0; - cache[ i ].count = 0; - } - - return i; -} - -void disc_CacheInit(void) { - - u32 i; - - for( i = 0; i < DISC_CACHE_COUNT; i++ ) { - cache[ i ].sector = CACHE_FREE; - cache[ i ].dirty = 0; - cache[ i ].count = 0; - } - -} - -bool disc_CacheFlush(void) { - - u32 i; - - if( !active_interface ) return false; - - for( i = 0; i < DISC_CACHE_COUNT; i++ ) { - if( cache[ i ].sector != CACHE_FREE && cache[ i ].dirty != 0 ) { - if( active_interface->fn_WriteSectors( cache[ i ].sector, 1, &cacheBuffer[ i * 512 ] ) == false ) - return false; - - cache[ i ].dirty = 0; - } - } - return true; -} - -bool disc_CacheReadSector( void *buffer, u32 sector) { - u32 i = disc_CacheFind( sector ); - if( i == CACHE_FREE ) { - i = disc_CacheFindFree(); - cache[ i ].sector = sector; - if( active_interface->fn_ReadSectors( sector, 1, &cacheBuffer[ i * 512 ] ) == false ) - return false; - } -#ifdef DISK_CACHE_DMA - DMA3_SRC = (u32)&cacheBuffer[ i * 512 ] - DMA3_DEST = (u32)buffer; - DMA3_CR = 128 | DMA_COPY_WORDS; -#else - memcpy( buffer, &cacheBuffer[ i * 512 ], 512 ); -#endif - cache[ i ].count++; - return true; -} - -bool disc_CacheWriteSector( void *buffer, u32 sector ) { - u32 i = disc_CacheFind( sector ); - if( i == CACHE_FREE ) { - i = disc_CacheFindFree(); - cache [ i ].sector = sector; - } -#ifdef DISK_CACHE_DMA - DMA3_SRC = (u32)buffer; - DMA3_DEST = (u32)&cacheBuffer[ i * 512 ]; - DMA3_CR = 128 | DMA_COPY_WORDS; -#else - memcpy( &cacheBuffer[ i * 512 ], buffer, 512 ); -#endif - cache[ i ].dirty=1; - cache[ i ].count++; - return true; -} - -#endif - -/* - - Hardware level disc funtions - -*/ - -bool disc_setGbaSlotInterface (void) -{ - // If running on an NDS, make sure the correct CPU can access - // the GBA cart. First implemented by SaTa. -#ifdef NDS - #ifdef ARM9 -// WAIT_CR &= ~(0x8080); - #endif - #ifdef ARM7 -// WAIT_CR |= (0x8080); - #endif -#endif - -#ifdef SUPPORT_M3CF - // check if we have a M3 perfect CF plugged in - active_interface = M3CF_GetInterface() ; - if (active_interface->fn_StartUp()) - { - // set M3 CF as default IO - return true ; - } ; -#endif - -#ifdef SUPPORT_M3SD - // check if we have a M3 perfect SD plugged in - active_interface = M3SD_GetInterface() ; - if (active_interface->fn_StartUp()) - { - // set M3 SD as default IO - return true ; - } ; -#endif - -#ifdef SUPPORT_MPCF - // check if we have a GBA Movie Player plugged in - active_interface = MPCF_GetInterface() ; - if (active_interface->fn_StartUp()) - { - // set GBAMP as default IO - return true ; - } ; -#endif - -#ifdef SUPPORT_SCCF - // check if we have a SuperCard CF plugged in - active_interface = SCCF_GetInterface() ; - if (active_interface->fn_StartUp()) - { - // set SC CF as default IO - return true ; - } ; -#endif - -#ifdef SUPPORT_SCSD - // check if we have a SuperCard SD plugged in - active_interface = SCSD_GetInterface() ; - if (active_interface->fn_StartUp()) - { - // set SC SD as default IO - return true ; - } ; -#endif - - -#ifdef SUPPORT_EFA2 - // check if we have a EFA2 plugged in - active_interface = EFA2_GetInterface() ; - if (active_interface->fn_StartUp()) - { - return true ; - } ; -#endif - -#ifdef SUPPORT_FCSR - // check if we have a GBA Flash Cart plugged in - active_interface = FCSR_GetInterface() ; - if (active_interface->fn_StartUp()) - { - // set FC as default IO - return true ; - } ; -#endif - - return false; -} - -#ifdef NDS -// Check the DS card slot for a valid memory card interface -// If an interface is found, it is set as the default interace -// and it returns true. Otherwise the default interface is left -// untouched and it returns false. -bool disc_setDsSlotInterface (void) -{ -#ifdef ARM9 - WAIT_CR &= ~(1<<11); -#endif -#ifdef ARM7 - WAIT_CR |= (1<<11); -#endif - -#ifdef SUPPORT_NMMC - // check if we have a Neoflash MK2 / MK3 plugged in - active_interface = NMMC_GetInterface() ; - if (active_interface->fn_StartUp()) - { - // set Neoflash MK2 / MK3 as default IO - return true ; - } ; -#endif - - return false; -} -#endif - - -bool disc_Init(void) -{ -#ifdef DISC_CACHE - disc_CacheInit(); -#endif - - - if (active_interface != 0) { - return true; - } - -#ifdef NDS - if (disc_setDsSlotInterface()) { - return true; - } -#endif - - if (disc_setGbaSlotInterface()) { - return true; - } - - // could not find a working IO Interface - active_interface = 0 ; - return false ; -} - -bool disc_IsInserted(void) -{ - if (active_interface) return active_interface->fn_IsInserted() ; - return false ; -} - -bool disc_ReadSectors(u32 sector, u8 numSecs, void* buffer) -{ -#ifdef DISC_CACHE - u8 *p=(u8*)buffer; - u32 i; - u32 inumSecs=numSecs; - if(numSecs==0) - inumSecs=256; - for( i = 0; ifn_ReadSectors(sector,numSecs,buffer) ; - return false ; -#endif -} - -bool disc_WriteSectors(u32 sector, u8 numSecs, void* buffer) -{ -#ifdef DISC_CACHE - u8 *p=(u8*)buffer; - u32 i; - u32 inumSecs=numSecs; - if(numSecs==0) - inumSecs=256; - for( i = 0; ifn_WriteSectors(sector,numSecs,buffer) ; - return false ; -#endif -} - -bool disc_ClearStatus(void) -{ - if (active_interface) return active_interface->fn_ClearStatus() ; - return false ; -} - -bool disc_Shutdown(void) -{ -#ifdef DISC_CACHE - disc_CacheFlush(); -#endif - if (active_interface) active_interface->fn_Shutdown() ; - active_interface = 0 ; - return true ; -} - -u32 disc_HostType (void) -{ - if (active_interface) { - return active_interface->ul_ioType; - } else { - return 0; - } -} - diff --git a/backends/platform/ds/arm9/source/fat/gba_nds_fat.c b/backends/platform/ds/arm9/source/fat/gba_nds_fat.c index b3b2858e41..46aff1ced9 100644 --- a/backends/platform/ds/arm9/source/fat/gba_nds_fat.c +++ b/backends/platform/ds/arm9/source/fat/gba_nds_fat.c @@ -3325,3336 +3325,3 @@ int FAT_fputs (const char *string, FAT_FILE* file) return writtenBytes ; } #endif - - - -/* - gba_nds_fat.c - By chishm (Michael Chisholm) - - Routines for reading a compact flash card - using the GBA Movie Player or M3. - - Some FAT routines are based on those in fat.c, which - is part of avrlib by Pascal Stang. - - This software is completely free. No warranty is provided. - If you use it, please give me credit and email me about your - project at chishm@hotmail.com - - See gba_nds_fat.txt for help and license details. -*/ - -//--------------------------------------------------------------- -// Includes - -#include "gba_nds_fat.h" -#include "disc_io.h" -#include -#ifdef NDS - #include // Time on the NDS -#endif -//---------------------------------------------------------------- -// Data types -#ifndef NULL - #define NULL 0 -#endif - -//---------------------------------------------------------------- -// NDS memory access control register -#ifdef NDS - #ifndef WAIT_CR - #define WAIT_CR (*(vu16*)0x04000204) - #endif -#endif - -//--------------------------------------------------------------- -// Appropriate placement of CF functions and data -#ifdef NDS - #define _VARS_IN_RAM -#else - #define _VARS_IN_RAM __attribute__ ((section (".sbss"))) -#endif - - -//----------------------------------------------------------------- -// FAT constants -#define CLUSTER_EOF_16 0xFFFF -#define CLUSTER_EOF 0x0FFFFFFF -#define CLUSTER_FREE 0x0000 -#define CLUSTER_FIRST 0x0002 - -#define FILE_LAST 0x00 -#define FILE_FREE 0xE5 - -#define FAT16_ROOT_DIR_CLUSTER 0x00 - - -//----------------------------------------------------------------- -// long file name constants -#define LFN_END 0x40 -#define LFN_DEL 0x80 - -//----------------------------------------------------------------- -// Data Structures - -// Take care of packing for GCC - it doesn't obey pragma pack() -// properly for ARM targets. -#ifdef __GNUC__ - #define __PACKED __attribute__ ((__packed__)) -#else - #define __PACKED - #pragma pack(1) -#endif - -// Boot Sector - must be packed -typedef struct -{ - u8 jmpBoot[3]; - u8 OEMName[8]; - // BIOS Parameter Block - u16 bytesPerSector; - u8 sectorsPerCluster; - u16 reservedSectors; - u8 numFATs; - u16 rootEntries; - u16 numSectorsSmall; - u8 mediaDesc; - u16 sectorsPerFAT; - u16 sectorsPerTrk; - u16 numHeads; - u32 numHiddenSectors; - u32 numSectors; - union // Different types of extended BIOS Parameter Block for FAT16 and FAT32 - { - struct - { - // Ext BIOS Parameter Block for FAT16 - u8 driveNumber; - u8 reserved1; - u8 extBootSig; - u32 volumeID; - u8 volumeLabel[11]; - u8 fileSysType[8]; - // Bootcode - u8 bootCode[448]; - } __PACKED fat16; - struct - { - // FAT32 extended block - u32 sectorsPerFAT32; - u16 extFlags; - u16 fsVer; - u32 rootClus; - u16 fsInfo; - u16 bkBootSec; - u8 reserved[12]; - // Ext BIOS Parameter Block for FAT16 - u8 driveNumber; - u8 reserved1; - u8 extBootSig; - u32 volumeID; - u8 volumeLabel[11]; - u8 fileSysType[8]; - // Bootcode - u8 bootCode[420]; - } __PACKED fat32; - } __PACKED extBlock; - - u16 bootSig; - -} __PACKED BOOT_SEC; - -// Directory entry - must be packed -typedef struct -{ - u8 name[8]; - u8 ext[3]; - u8 attrib; - u8 reserved; - u8 cTime_ms; - u16 cTime; - u16 cDate; - u16 aDate; - u16 startClusterHigh; - u16 mTime; - u16 mDate; - u16 startCluster; - u32 fileSize; -} __PACKED DIR_ENT; - -// Long file name directory entry - must be packed -typedef struct -{ - u8 ordinal; // Position within LFN - u16 char0; - u16 char1; - u16 char2; - u16 char3; - u16 char4; - u8 flag; // Should be equal to ATTRIB_LFN - u8 reserved1; // Always 0x00 - u8 checkSum; // Checksum of short file name (alias) - u16 char5; - u16 char6; - u16 char7; - u16 char8; - u16 char9; - u16 char10; - u16 reserved2; // Always 0x0000 - u16 char11; - u16 char12; -} __PACKED DIR_ENT_LFN; - -const char lfn_offset_table[13]={0x01,0x03,0x05,0x07,0x09,0x0E,0x10,0x12,0x14,0x16,0x18,0x1C,0x1E}; - -// End of packed structs -#ifdef __PACKED - #undef __PACKED -#endif -#ifndef __GNUC__ - #pragma pack() -#endif - -//----------------------------------------------------------------- -// Global Variables - -// _VARS_IN_RAM variables are stored in the largest section of WRAM -// available: IWRAM on NDS ARM7, EWRAM on NDS ARM9 and GBA - -// Files -_VARS_IN_RAM FAT_FILE openFiles[MAX_FILES_OPEN]; - -// Long File names -_VARS_IN_RAM char lfnName[MAX_FILENAME_LENGTH]; -bool lfnExists; - -// Locations on card -int filesysRootDir; -int filesysRootDirClus; -int filesysFAT; -int filesysSecPerFAT; -int filesysNumSec; -int filesysData; -int filesysBytePerSec; -int filesysSecPerClus; -int filesysBytePerClus; - -FS_TYPE filesysType = FS_UNKNOWN; -u32 filesysTotalSize; - -// Info about FAT -u32 fatLastCluster; -u32 fatFirstFree; - -// fatBuffer used to reduce wear on the CF card from multiple writes -_VARS_IN_RAM char fatBuffer[BYTE_PER_READ]; -u32 fatBufferCurSector; - -// Current working directory -u32 curWorkDirCluster; - -// Position of the directory entry last retreived with FAT_GetDirEntry -u32 wrkDirCluster; -int wrkDirSector; -int wrkDirOffset; - -// Global sector buffer to save on stack space -_VARS_IN_RAM unsigned char globalBuffer[BYTE_PER_READ]; - -//----------------------------------------------------------------- -// Functions contained in this file - predeclarations -char ucase (char character); -u16 getRTCtoFileTime (void); -u16 getRTCtoFileDate (void); - -bool FAT_AddDirEntry (const char* path, DIR_ENT newDirEntry); -bool FAT_ClearLinks (u32 cluster); -DIR_ENT FAT_DirEntFromPath (const char* path); -u32 FAT_FirstFreeCluster(void); -DIR_ENT FAT_GetDirEntry ( u32 dirCluster, int entry, int origin); -u32 FAT_LinkFreeCluster(u32 cluster); -u32 FAT_NextCluster(u32 cluster); -bool FAT_WriteFatEntry (u32 cluster, u32 value); -bool FAT_GetFilename (DIR_ENT dirEntry, char* alias); - -bool FAT_InitFiles (void); -bool FAT_FreeFiles (void); -int FAT_remove (const char* path); -bool FAT_chdir (const char* path); -FILE_TYPE FAT_FindFirstFile (char* filename); -FILE_TYPE FAT_FindNextFile (char* filename); -FILE_TYPE FAT_FileExists (const char* filename); -bool FAT_GetAlias (char* alias); -bool FAT_GetLongFilename (char* filename); -u32 FAT_GetFileSize (void); -u32 FAT_GetFileCluster (void); - -FAT_FILE* FAT_fopen(const char* path, const char* mode); -bool FAT_fclose (FAT_FILE* file); -bool FAT_feof(FAT_FILE* file); -int FAT_fseek(FAT_FILE* file, s32 offset, int origin); -u32 FAT_ftell (FAT_FILE* file); -u32 FAT_fread (void* buffer, u32 size, u32 count, FAT_FILE* file); -u32 FAT_fwrite (const void* buffer, u32 size, u32 count, FAT_FILE* file); -char FAT_fgetc (FAT_FILE* file); -char FAT_fputc (char c, FAT_FILE* file); - -/*----------------------------------------------------------------- -ucase -Returns the uppercase version of the given char -char IN: a character -char return OUT: uppercase version of character ------------------------------------------------------------------*/ -char ucase (char character) -{ - if ((character > 0x60) && (character < 0x7B)) - character = character - 0x20; - return (character); -} - - -/*----------------------------------------------------------------- -getRTCtoFileTime and getRTCtoFileDate -Returns the time / date in Dir Entry styled format -u16 return OUT: time / date in Dir Entry styled format ------------------------------------------------------------------*/ -u16 getRTCtoFileTime (void) -{ -#ifdef NDS - return ( - ( ( (IPC->rtc_hours > 11 ? IPC->rtc_hours - 40 : IPC->rtc_hours) & 0x1F) << 11) | - ( (IPC->rtc_minutes & 0x3F) << 5) | - ( (IPC->rtc_seconds >> 1) & 0x1F) ); -#else - return 0; -#endif -} - -u16 getRTCtoFileDate (void) -{ -#ifdef NDS - return ( - ( ((IPC->rtc_year + 20) & 0x7F) <<9) | - ( (IPC->rtc_month & 0xF) << 5) | - (IPC->rtc_day & 0x1F) ); -#else - return 0; -#endif -} - - -/*----------------------------------------------------------------- -Disc level FAT routines ------------------------------------------------------------------*/ -#define FAT_ClustToSect(m) \ - (((m-2) * filesysSecPerClus) + filesysData) - -/*----------------------------------------------------------------- -FAT_NextCluster -Internal function - gets the cluster linked from input cluster ------------------------------------------------------------------*/ -u32 FAT_NextCluster(u32 cluster) -{ - u32 nextCluster = CLUSTER_FREE; - u32 sector; - int offset; - - switch (filesysType) - { - case FS_UNKNOWN: - nextCluster = CLUSTER_FREE; - break; - - case FS_FAT12: - sector = filesysFAT + (((cluster * 3) / 2) / BYTE_PER_READ); - offset = ((cluster * 3) / 2) % BYTE_PER_READ; - - // If FAT buffer contains wrong sector - if (sector != fatBufferCurSector) - { - // Load correct sector to buffer - fatBufferCurSector = sector; - disc_ReadSector(fatBufferCurSector, fatBuffer); - } - - nextCluster = ((u8*)fatBuffer)[offset]; - offset++; - - if (offset >= BYTE_PER_READ) { - offset = 0; - fatBufferCurSector++; - disc_ReadSector(fatBufferCurSector, fatBuffer); - } - - nextCluster |= (((u8*)fatBuffer)[offset]) << 8; - - if (cluster & 0x01) { - nextCluster = nextCluster >> 4; - } else { - nextCluster &= 0x0FFF; - } - - if (nextCluster >= 0x0FF7) - { - nextCluster = CLUSTER_EOF; - } - - break; - - case FS_FAT16: - sector = filesysFAT + ((cluster << 1) / BYTE_PER_READ); - offset = cluster % (BYTE_PER_READ >> 1); - - // If FAT buffer contains wrong sector - if (sector != fatBufferCurSector) - { - // Load correct sector to buffer - fatBufferCurSector = sector; - disc_ReadSector(fatBufferCurSector, fatBuffer); - } - - // read the nextCluster value - nextCluster = ((u16*)fatBuffer)[offset]; - - if (nextCluster >= 0xFFF7) - { - nextCluster = CLUSTER_EOF; - } - break; - - case FS_FAT32: - sector = filesysFAT + ((cluster << 2) / BYTE_PER_READ); - offset = cluster % (BYTE_PER_READ >> 2); - - // If FAT buffer contains wrong sector - if (sector != fatBufferCurSector) - { - // Load correct sector to buffer - fatBufferCurSector = sector; - disc_ReadSector(fatBufferCurSector, fatBuffer); - } - - // read the nextCluster value - nextCluster = (((u32*)fatBuffer)[offset]) & 0x0FFFFFFF; - - if (nextCluster >= 0x0FFFFFF7) - { - nextCluster = CLUSTER_EOF; - } - break; - - default: - nextCluster = CLUSTER_FREE; - break; - } - - return nextCluster; -} - -#ifdef CAN_WRITE_TO_DISC -/*----------------------------------------------------------------- -FAT_WriteFatEntry -Internal function - writes FAT information about a cluster ------------------------------------------------------------------*/ -bool FAT_WriteFatEntry (u32 cluster, u32 value) -{ - u32 sector; - int offset; - - if ((cluster < 0x0002) || (cluster > fatLastCluster)) - { - return false; - } - - switch (filesysType) - { - case FS_UNKNOWN: - return false; - break; - - case FS_FAT12: - sector = filesysFAT + (((cluster * 3) / 2) / BYTE_PER_READ); - offset = ((cluster * 3) / 2) % BYTE_PER_READ; - - // If FAT buffer contains wrong sector - if (sector != fatBufferCurSector) - { - // Load correct sector to buffer - fatBufferCurSector = sector; - disc_ReadSector(fatBufferCurSector, fatBuffer); - } - - if (cluster & 0x01) { - - ((u8*)fatBuffer)[offset] = (((u8*)fatBuffer)[offset] & 0x0F) | ((value & 0x0F) << 4); - - offset++; - if (offset >= BYTE_PER_READ) { - offset = 0; - // write the buffer back to disc - disc_WriteSector(fatBufferCurSector, fatBuffer); - // read the next sector - fatBufferCurSector++; - disc_ReadSector(fatBufferCurSector, fatBuffer); - } - - ((u8*)fatBuffer)[offset] = (value & 0x0FF0) >> 4; - - } else { - - ((u8*)fatBuffer)[offset] = value & 0xFF; - - offset++; - if (offset >= BYTE_PER_READ) { - offset = 0; - // write the buffer back to disc - disc_WriteSector(fatBufferCurSector, fatBuffer); - // read the next sector - fatBufferCurSector++; - disc_ReadSector(fatBufferCurSector, fatBuffer); - } - - ((u8*)fatBuffer)[offset] = (((u8*)fatBuffer)[offset] & 0xF0) | ((value >> 8) & 0x0F); - } - - break; - - case FS_FAT16: - sector = filesysFAT + ((cluster << 1) / BYTE_PER_READ); - offset = cluster % (BYTE_PER_READ >> 1); - - // If FAT buffer contains wrong sector - if (sector != fatBufferCurSector) - { - // Load correct sector to buffer - fatBufferCurSector = sector; - disc_ReadSector(fatBufferCurSector, fatBuffer); - } - - // write the value to the FAT buffer - ((u16*)fatBuffer)[offset] = (value & 0xFFFF); - - break; - - case FS_FAT32: - sector = filesysFAT + ((cluster << 2) / BYTE_PER_READ); - offset = cluster % (BYTE_PER_READ >> 2); - - // If FAT buffer contains wrong sector - if (sector != fatBufferCurSector) - { - // Load correct sector to buffer - fatBufferCurSector = sector; - disc_ReadSector(fatBufferCurSector, fatBuffer); - } - - // write the value to the FAT buffer - (((u32*)fatBuffer)[offset]) = value; - - break; - - default: - return false; - break; - } - - // write the buffer back to disc - disc_WriteSector(fatBufferCurSector, fatBuffer); - - return true; -} -#endif - -#ifdef CAN_WRITE_TO_DISC -/*----------------------------------------------------------------- -FAT_ReadWriteFatEntryBuffered -Internal function - writes FAT information about a cluster to a - buffer that should then be flushed to disc using - FAT_WriteFatEntryFlushBuffer() - Call FAT_WriteFatEntry first so as not to ruin the disc. - Also returns the entry being replaced ------------------------------------------------------------------*/ -u32 FAT_ReadWriteFatEntryBuffered (u32 cluster, u32 value) -{ - u32 sector; - int offset; - u32 oldValue; - - if ((cluster < 0x0002) || (cluster > fatLastCluster)) - return CLUSTER_FREE; - - - switch (filesysType) - { - case FS_UNKNOWN: - oldValue = CLUSTER_FREE; - break; - - case FS_FAT12: - sector = filesysFAT + (((cluster * 3) / 2) / BYTE_PER_READ); - offset = ((cluster * 3) / 2) % BYTE_PER_READ; - - // If FAT buffer contains wrong sector - if (sector != fatBufferCurSector) - { - // write the old buffer to disc - if ((fatBufferCurSector >= filesysFAT) && (fatBufferCurSector < (filesysFAT + filesysSecPerFAT))) - disc_WriteSector(fatBufferCurSector, fatBuffer); - // Load correct sector to buffer - fatBufferCurSector = sector; - disc_ReadSector(fatBufferCurSector, fatBuffer); - } - - if (cluster & 0x01) { - - oldValue = (((u8*)fatBuffer)[offset] & 0xF0) >> 4; - ((u8*)fatBuffer)[offset] = (((u8*)fatBuffer)[offset] & 0x0F) | ((value & 0x0F) << 4); - - offset++; - if (offset >= BYTE_PER_READ) { - offset = 0; - // write the buffer back to disc - disc_WriteSector(fatBufferCurSector, fatBuffer); - // read the next sector - fatBufferCurSector++; - disc_ReadSector(fatBufferCurSector, fatBuffer); - } - - oldValue |= ((((u8*)fatBuffer)[offset]) << 4) & 0x0FF0; - ((u8*)fatBuffer)[offset] = (value & 0x0FF0) >> 4; - - } else { - - oldValue = ((u8*)fatBuffer)[offset] & 0xFF; - ((u8*)fatBuffer)[offset] = value & 0xFF; - - offset++; - if (offset >= BYTE_PER_READ) { - offset = 0; - // write the buffer back to disc - disc_WriteSector(fatBufferCurSector, fatBuffer); - // read the next sector - fatBufferCurSector++; - disc_ReadSector(fatBufferCurSector, fatBuffer); - } - - oldValue |= (((u8*)fatBuffer)[offset] & 0x0F) << 8; - ((u8*)fatBuffer)[offset] = (((u8*)fatBuffer)[offset] & 0xF0) | ((value >> 8) & 0x0F); - } - - if (oldValue >= 0x0FF7) - { - oldValue = CLUSTER_EOF; - } - - break; - - case FS_FAT16: - sector = filesysFAT + ((cluster << 1) / BYTE_PER_READ); - offset = cluster % (BYTE_PER_READ >> 1); - - // If FAT buffer contains wrong sector - if (sector != fatBufferCurSector) - { - // write the old buffer to disc - if ((fatBufferCurSector >= filesysFAT) && (fatBufferCurSector < (filesysFAT + filesysSecPerFAT))) - disc_WriteSector(fatBufferCurSector, fatBuffer); - // Load correct sector to buffer - fatBufferCurSector = sector; - disc_ReadSector(fatBufferCurSector, fatBuffer); - } - - // write the value to the FAT buffer - oldValue = ((u16*)fatBuffer)[offset]; - ((u16*)fatBuffer)[offset] = value; - - if (oldValue >= 0xFFF7) - { - oldValue = CLUSTER_EOF; - } - - break; - - case FS_FAT32: - sector = filesysFAT + ((cluster << 2) / BYTE_PER_READ); - offset = cluster % (BYTE_PER_READ >> 2); - - // If FAT buffer contains wrong sector - if (sector != fatBufferCurSector) - { - // write the old buffer to disc - if ((fatBufferCurSector >= filesysFAT) && (fatBufferCurSector < (filesysFAT + filesysSecPerFAT))) - disc_WriteSector(fatBufferCurSector, fatBuffer); - // Load correct sector to buffer - fatBufferCurSector = sector; - disc_ReadSector(fatBufferCurSector, fatBuffer); - } - - // write the value to the FAT buffer - oldValue = ((u32*)fatBuffer)[offset]; - ((u32*)fatBuffer)[offset] = value; - - if (oldValue >= 0x0FFFFFF7) - { - oldValue = CLUSTER_EOF; - } - - break; - - default: - oldValue = CLUSTER_FREE; - break; - } - - return oldValue; -} -#endif - -#ifdef CAN_WRITE_TO_DISC -/*----------------------------------------------------------------- -FAT_WriteFatEntryFlushBuffer -Flush the FAT buffer back to the disc ------------------------------------------------------------------*/ -bool FAT_WriteFatEntryFlushBuffer (void) -{ - // write the buffer disc - if ((fatBufferCurSector >= filesysFAT) && (fatBufferCurSector < (filesysFAT + filesysSecPerFAT))) - { - disc_WriteSector(fatBufferCurSector, fatBuffer); - return true; - } else { - return false; - } -} -#endif - -#ifdef CAN_WRITE_TO_DISC -/*----------------------------------------------------------------- -FAT_FirstFreeCluster -Internal function - gets the first available free cluster ------------------------------------------------------------------*/ -u32 FAT_FirstFreeCluster(void) -{ - // Start at first valid cluster - if (fatFirstFree < CLUSTER_FIRST) - fatFirstFree = CLUSTER_FIRST; - - while ((FAT_NextCluster(fatFirstFree) != CLUSTER_FREE) && (fatFirstFree <= fatLastCluster)) - { - fatFirstFree++; - } - if (fatFirstFree > fatLastCluster) - { - return CLUSTER_EOF; - } - return fatFirstFree; -} -#endif - -#ifdef CAN_WRITE_TO_DISC -/*----------------------------------------------------------------- -FAT_LinkFreeCluster -Internal function - gets the first available free cluster, sets it -to end of file, links the input cluster to it then returns the -cluster number ------------------------------------------------------------------*/ -u32 FAT_LinkFreeCluster(u32 cluster) -{ - u32 firstFree; - u32 curLink; - - if (cluster > fatLastCluster) - { - return CLUSTER_FREE; - } - - // Check if the cluster already has a link, and return it if so - curLink = FAT_NextCluster (cluster); - if ((curLink >= CLUSTER_FIRST) && (curLink < fatLastCluster)) - { - return curLink; // Return the current link - don't allocate a new one - } - - // Get a free cluster - firstFree = FAT_FirstFreeCluster(); - - // If couldn't get a free cluster then return - if (firstFree == CLUSTER_EOF) - { - return CLUSTER_FREE; - } - - if ((cluster >= CLUSTER_FIRST) && (cluster < fatLastCluster)) - { - // Update the linked from FAT entry - FAT_WriteFatEntry (cluster, firstFree); - } - // Create the linked to FAT entry - FAT_WriteFatEntry (firstFree, CLUSTER_EOF); - - return firstFree; -} -#endif - - -#ifdef CAN_WRITE_TO_DISC -/*----------------------------------------------------------------- -FAT_ClearLinks -Internal function - frees any cluster used by a file ------------------------------------------------------------------*/ -bool FAT_ClearLinks (u32 cluster) -{ - u32 nextCluster; - - if ((cluster < 0x0002) || (cluster > fatLastCluster)) - return false; - - // Store next cluster before erasing the link - nextCluster = FAT_NextCluster (cluster); - - // Erase the link - FAT_WriteFatEntry (cluster, CLUSTER_FREE); - - // Move onto next cluster - cluster = nextCluster; - - while ((cluster != CLUSTER_EOF) && (cluster != CLUSTER_FREE)) - { - cluster = FAT_ReadWriteFatEntryBuffered (cluster, CLUSTER_FREE); - } - - // Flush fat write buffer - FAT_WriteFatEntryFlushBuffer (); - - return true; -} -#endif - - -/*----------------------------------------------------------------- -FAT_InitFiles -Reads the FAT information from the CF card. -You need to call this before reading any files. -bool return OUT: true if successful. ------------------------------------------------------------------*/ -bool FAT_InitFiles (void) -{ - int i; - int bootSector; - BOOT_SEC* bootSec; - - if (!disc_Init()) - { - return (false); - } - - // Read first sector of CF card - if ( !disc_ReadSector(0, globalBuffer)) { - return false; - } - - // Make sure it is a valid MBR or boot sector - if ( (globalBuffer[0x1FE] != 0x55) || (globalBuffer[0x1FF] != 0xAA)) { - return false; - } - - // Check if there is a FAT string, which indicates this is a boot sector - if ((globalBuffer[0x36] == 'F') && (globalBuffer[0x37] == 'A') && (globalBuffer[0x38] == 'T')) - { - bootSector = 0; - } - // Check for FAT32 - else if ((globalBuffer[0x52] == 'F') && (globalBuffer[0x53] == 'A') && (globalBuffer[0x54] == 'T')) - { - bootSector = 0; - } - else // This is an MBR - { - // Find first valid partition from MBR - // First check for an active partition - for (i=0x1BE; (i < 0x1FE) && (globalBuffer[i] != 0x80); i+= 0x10); - // If it didn't find an active partition, search for any valid partition - if (i == 0x1FE) - for (i=0x1BE; (i < 0x1FE) && (globalBuffer[i+0x04] == 0x00); i+= 0x10); - - // Go to first valid partition - if ( i != 0x1FE) // Make sure it found a partition - { - bootSector = globalBuffer[0x8 + i] + (globalBuffer[0x9 + i] << 8) + (globalBuffer[0xA + i] << 16) + ((globalBuffer[0xB + i] << 24) & 0x0F); - } else { - bootSector = 0; // No partition found, assume this is a MBR free disk - } - } - - // Read in boot sector - bootSec = (BOOT_SEC*) globalBuffer; - if (!disc_ReadSector (bootSector, bootSec)) { - return false; - } - - // Store required information about the file system - if (bootSec->sectorsPerFAT != 0) - { - filesysSecPerFAT = bootSec->sectorsPerFAT; - } - else - { - filesysSecPerFAT = bootSec->extBlock.fat32.sectorsPerFAT32; - } - - if (bootSec->numSectorsSmall != 0) - { - filesysNumSec = bootSec->numSectorsSmall; - } - else - { - filesysNumSec = bootSec->numSectors; - } - - filesysBytePerSec = BYTE_PER_READ; // Sector size is redefined to be 512 bytes - filesysSecPerClus = bootSec->sectorsPerCluster * bootSec->bytesPerSector / BYTE_PER_READ; - filesysBytePerClus = filesysBytePerSec * filesysSecPerClus; - filesysFAT = bootSector + bootSec->reservedSectors; - - filesysRootDir = filesysFAT + (bootSec->numFATs * filesysSecPerFAT); - filesysData = filesysRootDir + ((bootSec->rootEntries * sizeof(DIR_ENT)) / filesysBytePerSec); - - filesysTotalSize = (filesysNumSec - filesysData) * filesysBytePerSec; - - // Store info about FAT - fatLastCluster = (filesysNumSec - filesysData) / bootSec->sectorsPerCluster; - fatFirstFree = CLUSTER_FIRST; - fatBufferCurSector = 0; - disc_ReadSector(fatBufferCurSector, fatBuffer); - - if (fatLastCluster < 4085) - { - filesysType = FS_FAT12; // FAT12 volume - unsupported - } - else if (fatLastCluster < 65525) - { - filesysType = FS_FAT16; // FAT16 volume - } - else - { - filesysType = FS_FAT32; // FAT32 volume - } - - if (filesysType != FS_FAT32) - { - filesysRootDirClus = FAT16_ROOT_DIR_CLUSTER; - } - else // Set up for the FAT32 way - { - filesysRootDirClus = bootSec->extBlock.fat32.rootClus; - // Check if FAT mirroring is enabled - if (!(bootSec->extBlock.fat32.extFlags & 0x80)) - { - // Use the active FAT - filesysFAT = filesysFAT + ( filesysSecPerFAT * (bootSec->extBlock.fat32.extFlags & 0x0F)); - } - } - - // Set current directory to the root - curWorkDirCluster = filesysRootDirClus; - wrkDirCluster = filesysRootDirClus; - wrkDirSector = 0; - wrkDirOffset = 0; - - // Set all files to free - for (i=0; i < MAX_FILES_OPEN; i++) - { - openFiles[i].inUse = false; - } - - // No long filenames so far - lfnExists = false; - for (i = 0; i < MAX_FILENAME_LENGTH; i++) - { - lfnName[i] = '\0'; - } - - return (true); -} - -/*----------------------------------------------------------------- -FAT_FreeFiles -Closes all open files then resets the CF card. -Call this before exiting back to the GBAMP -bool return OUT: true if successful. ------------------------------------------------------------------*/ -bool FAT_FreeFiles (void) -{ - int i; - - // Close all open files - for (i=0; i < MAX_FILES_OPEN; i++) - { - if (openFiles[i].inUse == true) - { - FAT_fclose(&openFiles[i]); - } - } - - // Flush any sectors in disc cache - disc_CacheFlush(); - - // Clear card status - disc_ClearStatus(); - - // Return status of card - return disc_IsInserted(); -} - - -/*----------------------------------------------------------------- -FAT_GetDirEntry -Return the file info structure of the next valid file entry -u32 dirCluster: IN cluster of subdirectory table -int entry: IN the desired file entry -int origin IN: relative position of the entry -DIR_ENT return OUT: desired dirEntry. First char will be FILE_FREE if - the entry does not exist. ------------------------------------------------------------------*/ -DIR_ENT FAT_GetDirEntry ( u32 dirCluster, int entry, int origin) -{ - DIR_ENT dir; - DIR_ENT_LFN lfn; - int firstSector = 0; - bool notFound = false; - bool found = false; - int maxSectors; - int lfnPos, aliasPos; - u8 lfnChkSum, chkSum; - - int i; - - dir.name[0] = FILE_FREE; // default to no file found - dir.attrib = 0x00; - - // Check if fat has been initialised - if (filesysBytePerSec == 0) - { - return (dir); - } - - switch (origin) - { - case SEEK_SET: - wrkDirCluster = dirCluster; - wrkDirSector = 0; - wrkDirOffset = -1; - break; - case SEEK_CUR: // Don't change anything - break; - case SEEK_END: // Find entry signifying end of directory - // Subtraction will never reach 0, so it keeps going - // until reaches end of directory - wrkDirCluster = dirCluster; - wrkDirSector = 0; - wrkDirOffset = -1; - entry = -1; - break; - default: - return dir; - } - - lfnChkSum = 0; - maxSectors = (wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? (filesysData - filesysRootDir) : filesysSecPerClus); - - // Scan Dir for correct entry - firstSector = (wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? filesysRootDir : FAT_ClustToSect(wrkDirCluster)); - disc_ReadSector (firstSector + wrkDirSector, globalBuffer); - found = false; - notFound = false; - do { - wrkDirOffset++; - if (wrkDirOffset == BYTE_PER_READ / sizeof (DIR_ENT)) - { - wrkDirOffset = 0; - wrkDirSector++; - if ((wrkDirSector == filesysSecPerClus) && (wrkDirCluster != FAT16_ROOT_DIR_CLUSTER)) - { - wrkDirSector = 0; - wrkDirCluster = FAT_NextCluster(wrkDirCluster); - if (wrkDirCluster == CLUSTER_EOF) - { - notFound = true; - } - firstSector = FAT_ClustToSect(wrkDirCluster); - } - else if ((wrkDirCluster == FAT16_ROOT_DIR_CLUSTER) && (wrkDirSector == (filesysData - filesysRootDir))) - { - notFound = true; // Got to end of root dir - } - disc_ReadSector (firstSector + wrkDirSector, globalBuffer); - } - dir = ((DIR_ENT*) globalBuffer)[wrkDirOffset]; - if ((dir.name[0] != FILE_FREE) && (dir.name[0] > 0x20) && ((dir.attrib & ATTRIB_VOL) != ATTRIB_VOL)) - { - entry--; - if (lfnExists) - { - // Calculate file checksum - chkSum = 0; - for (aliasPos=0; aliasPos < 11; aliasPos++) - { - // NOTE: The operation is an unsigned char rotate right - chkSum = ((chkSum & 1) ? 0x80 : 0) + (chkSum >> 1) + (aliasPos < 8 ? dir.name[aliasPos] : dir.ext[aliasPos - 8]); - } - if (chkSum != lfnChkSum) - { - lfnExists = false; - lfnName[0] = '\0'; - } - } - if (entry == 0) - { - if (!lfnExists) - { - FAT_GetFilename (dir, lfnName); - } - found = true; - } - } - else if (dir.name[0] == FILE_LAST) - { - if (origin == SEEK_END) - { - found = true; - } - else - { - notFound = true; - } - } - else if (dir.attrib == ATTRIB_LFN) - { - lfn = ((DIR_ENT_LFN*) globalBuffer)[wrkDirOffset]; - if (lfn.ordinal & LFN_DEL) - { - lfnExists = false; - } - else if (lfn.ordinal & LFN_END) // Last part of LFN, make sure it isn't deleted (Thanks MoonLight) - { - lfnExists = true; - lfnName[(lfn.ordinal & ~LFN_END) * 13] = '\0'; // Set end of lfn to null character - lfnChkSum = lfn.checkSum; - } - if (lfnChkSum != lfn.checkSum) - { - lfnExists = false; - } - if (lfnExists) - { - lfnPos = ((lfn.ordinal & ~LFN_END) - 1) * 13; - for (i = 0; i < 13; i++) { - lfnName[lfnPos + i] = ((u8*)&lfn)[(int)(lfn_offset_table[i])] /* | ((u8*)&lfn)[(int)(lfn_offset_table[i]) + 1] include this for unicode support*/; - } - } - } - } while (!found && !notFound); - - // If no file is found, return FILE_FREE - if (notFound) - { - dir.name[0] = FILE_FREE; - } - - return (dir); -} - - -/*----------------------------------------------------------------- -FAT_GetLongFilename -Get the long name of the last file or directory retrived with - GetDirEntry. Also works for FindFirstFile and FindNextFile. - If a long name doesn't exist, it returns the short name - instead. -char* filename: OUT will be filled with the filename, should be at - least 256 bytes long -bool return OUT: return true if successful ------------------------------------------------------------------*/ -bool FAT_GetLongFilename (char* filename) -{ - if (filename == NULL) - return false; - - strncpy (filename, lfnName, MAX_FILENAME_LENGTH - 1); - filename[MAX_FILENAME_LENGTH - 1] = '\0'; - - return true; -} - - -/*----------------------------------------------------------------- -FAT_GetFilename -Get the alias (short name) of the file or directory stored in - dirEntry -DIR_ENT dirEntry: IN a valid directory table entry -char* alias OUT: will be filled with the alias (short filename), - should be at least 13 bytes long -bool return OUT: return true if successful ------------------------------------------------------------------*/ -bool FAT_GetFilename (DIR_ENT dirEntry, char* alias) -{ - int i=0; - int j=0; - - alias[0] = '\0'; - if (dirEntry.name[0] != FILE_FREE) - { - if (dirEntry.name[0] == '.') - { - alias[0] = '.'; - if (dirEntry.name[1] == '.') - { - alias[1] = '.'; - alias[2] = '\0'; - } - else - { - alias[1] = '\0'; - } - } - else - { - // Copy the filename from the dirEntry to the string - for (i = 0; (i < 8) && (dirEntry.name[i] != ' '); i++) - { - alias[i] = dirEntry.name[i]; - } - // Copy the extension from the dirEntry to the string - if (dirEntry.ext[0] != ' ') - { - alias[i++] = '.'; - for ( j = 0; (j < 3) && (dirEntry.ext[j] != ' '); j++) - { - alias[i++] = dirEntry.ext[j]; - } - } - alias[i] = '\0'; - } - } - - return (alias[0] != '\0'); -} - -/*----------------------------------------------------------------- -FAT_GetAlias -Get the alias (short name) of the last file or directory entry read - using GetDirEntry. Works for FindFirstFile and FindNextFile -char* alias OUT: will be filled with the alias (short filename), - should be at least 13 bytes long -bool return OUT: return true if successful ------------------------------------------------------------------*/ -bool FAT_GetAlias (char* alias) -{ - if (alias == NULL) - { - return false; - } - // Read in the last accessed directory entry - disc_ReadSector ((wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? filesysRootDir : FAT_ClustToSect(wrkDirCluster)) + wrkDirSector, globalBuffer); - - return FAT_GetFilename (((DIR_ENT*)globalBuffer)[wrkDirOffset], alias); -} - -/*----------------------------------------------------------------- -FAT_GetFileSize -Get the file size of the last file found or openned. -This idea is based on a modification by MoonLight -u32 return OUT: the file size ------------------------------------------------------------------*/ -u32 FAT_GetFileSize (void) -{ - // Read in the last accessed directory entry - disc_ReadSector ((wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? filesysRootDir : FAT_ClustToSect(wrkDirCluster)) + wrkDirSector, globalBuffer); - - return ((DIR_ENT*)globalBuffer)[wrkDirOffset].fileSize; -} - -/*----------------------------------------------------------------- -FAT_GetFileCluster -Get the first cluster of the last file found or openned. -u32 return OUT: the file start cluster ------------------------------------------------------------------*/ -u32 FAT_GetFileCluster (void) -{ - // Read in the last accessed directory entry - disc_ReadSector ((wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? filesysRootDir : FAT_ClustToSect(wrkDirCluster)) + wrkDirSector, globalBuffer); - - return (((DIR_ENT*)globalBuffer)[wrkDirOffset].startCluster) | (((DIR_ENT*)globalBuffer)[wrkDirOffset].startClusterHigh << 16); -} - -/*----------------------------------------------------------------- -FAT_GetFileAttributes -Get the attributes of the last file found or openned. -u8 return OUT: the file's attributes ------------------------------------------------------------------*/ -u8 FAT_GetFileAttributes (void) -{ - // Read in the last accessed directory entry - disc_ReadSector ((wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? filesysRootDir : FAT_ClustToSect(wrkDirCluster)) + wrkDirSector, globalBuffer); - - return ((DIR_ENT*)globalBuffer)[wrkDirOffset].attrib; -} - -#ifdef CAN_WRITE_TO_DISC -/*----------------------------------------------------------------- -FAT_SetFileAttributes -Set the attributes of a file. -const char* filename IN: The name and path of the file to modify -u8 attributes IN: The attribute values to assign -u8 mask IN: Detemines which attributes are changed -u8 return OUT: the file's new attributes ------------------------------------------------------------------*/ -u8 FAT_SetFileAttributes (const char* filename, u8 attributes, u8 mask) -{ - // Get the file - if (!FAT_FileExists(filename)) { - return 0xff; - } - - // Read in the last accessed directory entry - disc_ReadSector ((wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? filesysRootDir : FAT_ClustToSect(wrkDirCluster)) + wrkDirSector, globalBuffer); - - ((DIR_ENT*)globalBuffer)[wrkDirOffset].attrib = (((DIR_ENT*)globalBuffer)[wrkDirOffset].attrib & ~(mask & 0x27)) | (attributes & 0x27); // 0x27 is he settable attributes - - disc_WriteSector ((wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? filesysRootDir : FAT_ClustToSect(wrkDirCluster)) + wrkDirSector, globalBuffer); - - return ((DIR_ENT*)globalBuffer)[wrkDirOffset].attrib; -} -#endif - -#ifdef FILE_TIME_SUPPORT -time_t FAT_FileTimeToCTime (u16 fileTime, u16 fileDate) -{ - struct tm timeInfo; - - timeInfo.tm_year = (fileDate >> 9) + 80; // years since midnight January 1970 - timeInfo.tm_mon = ((fileDate >> 5) & 0xf) - 1; // Months since january - timeInfo.tm_mday = fileDate & 0x1f; // Day of the month - - timeInfo.tm_hour = fileTime >> 11; // hours past midnight - timeInfo.tm_min = (fileTime >> 5) & 0x3f; // minutes past the hour - timeInfo.tm_sec = (fileTime & 0x1f) * 2; // seconds past the minute - - return mktime(&timeInfo); -} - -/*----------------------------------------------------------------- -FAT_GetFileCreationTime -Get the creation time of the last file found or openned. -time_t return OUT: the file's creation time ------------------------------------------------------------------*/ -time_t FAT_GetFileCreationTime (void) -{ - // Read in the last accessed directory entry - disc_ReadSector ((wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? filesysRootDir : FAT_ClustToSect(wrkDirCluster)) + wrkDirSector, globalBuffer); - - return FAT_FileTimeToCTime(((DIR_ENT*)globalBuffer)[wrkDirOffset].cTime, ((DIR_ENT*)globalBuffer)[wrkDirOffset].cDate); -} - -/*----------------------------------------------------------------- -FAT_GetFileLastWriteTime -Get the creation time of the last file found or openned. -time_t return OUT: the file's creation time ------------------------------------------------------------------*/ -time_t FAT_GetFileLastWriteTime (void) -{ - // Read in the last accessed directory entry - disc_ReadSector ((wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? filesysRootDir : FAT_ClustToSect(wrkDirCluster)) + wrkDirSector, globalBuffer); - - return FAT_FileTimeToCTime(((DIR_ENT*)globalBuffer)[wrkDirOffset].mTime, ((DIR_ENT*)globalBuffer)[wrkDirOffset].mDate); -} -#endif - -/*----------------------------------------------------------------- -FAT_DirEntFromPath -Finds the directory entry for a file or directory from a path -Path separator is a forward slash / -const char* path: IN null terminated string of path. -DIR_ENT return OUT: dirEntry of found file. First char will be FILE_FREE - if the file was not found ------------------------------------------------------------------*/ -DIR_ENT FAT_DirEntFromPath (const char* path) -{ - int pathPos; - char name[MAX_FILENAME_LENGTH]; - char alias[13]; - int namePos; - bool found, notFound; - DIR_ENT dirEntry; - u32 dirCluster; - bool flagLFN, dotSeen; - - // Start at beginning of path - pathPos = 0; - - if (path[pathPos] == '/') - { - dirCluster = filesysRootDirClus; // Start at root directory - } - else - { - dirCluster = curWorkDirCluster; // Start at current working dir - } - - // Eat any slash / - while ((path[pathPos] == '/') && (path[pathPos] != '\0')) - { - pathPos++; - } - - // Search until can't continue - found = false; - notFound = false; - while (!notFound && !found) - { - flagLFN = false; - // Copy name from path - namePos = 0; - if ((path[pathPos] == '.') && ((path[pathPos + 1] == '\0') || (path[pathPos + 1] == '/'))) { - // Dot entry - name[namePos++] = '.'; - pathPos++; - } else if ((path[pathPos] == '.') && (path[pathPos + 1] == '.') && ((path[pathPos + 2] == '\0') || (path[pathPos + 2] == '/'))){ - // Double dot entry - name[namePos++] = '.'; - pathPos++; - name[namePos++] = '.'; - pathPos++; - } else { - // Copy name from path - if (path[pathPos] == '.') { - flagLFN = true; - } - dotSeen = false; - while ((namePos < MAX_FILENAME_LENGTH - 1) && (path[pathPos] != '\0') && (path[pathPos] != '/')) - { - name[namePos] = ucase(path[pathPos]); - if ((name[namePos] <= ' ') || ((name[namePos] >= ':') && (name[namePos] <= '?'))) // Invalid character - { - flagLFN = true; - } - if (name[namePos] == '.') { - if (!dotSeen) { - dotSeen = true; - } else { - flagLFN = true; - } - } - namePos++; - pathPos++; - } - // Check if a long filename was specified - if (namePos > 12) - { - flagLFN = true; - } - } - - // Add end of string char - name[namePos] = '\0'; - - // Move through path to correct place - while ((path[pathPos] != '/') && (path[pathPos] != '\0')) - pathPos++; - // Eat any slash / - while ((path[pathPos] == '/') && (path[pathPos] != '\0')) - { - pathPos++; - } - - // Search current Dir for correct entry - dirEntry = FAT_GetDirEntry (dirCluster, 1, SEEK_SET); - while ( !found && !notFound) - { - // Match filename - found = true; - for (namePos = 0; (namePos < MAX_FILENAME_LENGTH) && found && (name[namePos] != '\0') && (lfnName[namePos] != '\0'); namePos++) - { - if (name[namePos] != ucase(lfnName[namePos])) - { - found = false; - } - } - if ((name[namePos] == '\0') != (lfnName[namePos] == '\0')) - { - found = false; - } - - // Check against alias as well. - if (!found) - { - FAT_GetFilename(dirEntry, alias); - found = true; - for (namePos = 0; (namePos < 13) && found && (name[namePos] != '\0') && (alias[namePos] != '\0'); namePos++) - { - if (name[namePos] != ucase(alias[namePos])) - { - found = false; - } - } - if ((name[namePos] == '\0') != (alias[namePos] == '\0')) - { - found = false; - } - } - - if (dirEntry.name[0] == FILE_FREE) - // Couldn't find specified file - { - found = false; - notFound = true; - } - if (!found && !notFound) - { - dirEntry = FAT_GetDirEntry (dirCluster, 1, SEEK_CUR); - } - } - - if (found && ((dirEntry.attrib & ATTRIB_DIR) == ATTRIB_DIR) && (path[pathPos] != '\0')) - // It has found a directory from within the path that needs to be followed - { - found = false; - dirCluster = dirEntry.startCluster | (dirEntry.startClusterHigh << 16); - } - } - - if (notFound) - { - dirEntry.name[0] = FILE_FREE; - dirEntry.attrib = 0x00; - } - - return (dirEntry); -} - - -#ifdef CAN_WRITE_TO_DISC -/*----------------------------------------------------------------- -FAT_AddDirEntry -Creates a new dir entry for a file -Path separator is a forward slash / -const char* path: IN null terminated string of path to file. -DIR_ENT newDirEntry IN: The directory entry to use. -int file IN: The file being added (optional, use -1 if not used) -bool return OUT: true if successful ------------------------------------------------------------------*/ -bool FAT_AddDirEntry (const char* path, DIR_ENT newDirEntry) -{ - char filename[MAX_FILENAME_LENGTH]; - int filePos, pathPos, aliasPos; - char tempChar; - bool flagLFN, dotSeen; - char fileAlias[13] = {0}; - int tailNum; - - unsigned char chkSum = 0; - - u32 oldWorkDirCluster; - - DIR_ENT* dirEntries = (DIR_ENT*)globalBuffer; - u32 dirCluster; - int secOffset; - int entryOffset; - int maxSectors; - u32 firstSector; - - DIR_ENT_LFN lfnEntry; - int lfnPos = 0; - - int dirEntryLength = 0; - int dirEntryRemain = 0; - u32 tempDirCluster; - int tempSecOffset; - int tempEntryOffset; - bool dirEndFlag = false; - - int i; - - // Store current working directory - oldWorkDirCluster = curWorkDirCluster; - - // Find filename within path and change to correct directory - if (path[0] == '/') - { - curWorkDirCluster = filesysRootDirClus; - } - - pathPos = 0; - filePos = 0; - flagLFN = false; - - while (path[pathPos + filePos] != '\0') - { - if (path[pathPos + filePos] == '/') - { - filename[filePos] = '\0'; - if (FAT_chdir(filename) == false) - { - curWorkDirCluster = oldWorkDirCluster; - return false; // Couldn't change directory - } - pathPos += filePos + 1; - filePos = 0; - } - filename[filePos] = path[pathPos + filePos]; - filePos++; - } - - // Skip over last slashes - while (path[pathPos] == '/') - pathPos++; - - // Check if the filename has a leading "." - // If so, it is an LFN - if (path[pathPos] == '.') { - flagLFN = true; - } - - // Copy name from path - filePos = 0; - dotSeen = false; - - while ((filePos < MAX_FILENAME_LENGTH - 1) && (path[pathPos] != '\0')) - { - filename[filePos] = path[pathPos]; - if ((filename[filePos] <= ' ') || ((filename[filePos] >= ':') && (filename[filePos] <= '?'))) // Invalid character - { - flagLFN = true; - } - if (filename[filePos] == '.') { - if (!dotSeen) { - dotSeen = true; - } else { - flagLFN = true; - } - } - filePos++; - pathPos++; - if ((filePos > 8) && !dotSeen) { - flagLFN = true; - } - } - - if (filePos == 0) // No filename - { - return false; - } - - // Check if a long filename was specified - if (filePos > 12) - { - flagLFN = true; - } - - // Check if extension is > 3 characters long - if (!flagLFN && (strrchr (filename, '.') != NULL) && (strlen(strrchr(filename, '.')) > 4)) { - flagLFN = true; - } - - lfnPos = (filePos - 1) / 13; - - // Add end of string char - filename[filePos++] = '\0'; - // Clear remaining chars - while (filePos < MAX_FILENAME_LENGTH) - filename[filePos++] = 0x01; // Set for LFN compatibility - - - if (flagLFN) - { - // Generate short filename - always a 2 digit number for tail - // Get first 5 chars of alias from LFN - aliasPos = 0; - filePos = 0; - if (filename[filePos] == '.') { - filePos++; - } - for ( ; (aliasPos < 5) && (filename[filePos] != '\0') && (filename[filePos] != '.') ; filePos++) - { - tempChar = ucase(filename[filePos]); - if (((tempChar > ' ' && tempChar < ':') || tempChar > '?') && tempChar != '.') - fileAlias[aliasPos++] = tempChar; - } - // Pad Alias with underscores - while (aliasPos < 5) - fileAlias[aliasPos++] = '_'; - - fileAlias[5] = '~'; - fileAlias[8] = '.'; - fileAlias[9] = ' '; - fileAlias[10] = ' '; - fileAlias[11] = ' '; - if (strchr (filename, '.') != NULL) { - while(filename[filePos] != '\0') - { - filePos++; - if (filename[filePos] == '.') - { - pathPos = filePos; - } - } - filePos = pathPos + 1; //pathPos is used as a temporary variable - // Copy first 3 characters of extension - for (aliasPos = 9; (aliasPos < 12) && (filename[filePos] != '\0'); filePos++) - { - tempChar = ucase(filename[filePos]); - if ((tempChar > ' ' && tempChar < ':') || tempChar > '?') - fileAlias[aliasPos++] = tempChar; - } - } else { - aliasPos = 9; - } - - // Pad Alias extension with spaces - while (aliasPos < 12) - fileAlias[aliasPos++] = ' '; - - fileAlias[12] = '\0'; - - - // Get a valid tail number - tailNum = 0; - do { - tailNum++; - fileAlias[6] = 0x30 + ((tailNum / 10) % 10); // 10's digit - fileAlias[7] = 0x30 + (tailNum % 10); // 1's digit - } while ((FAT_DirEntFromPath(fileAlias).name[0] != FILE_FREE) && (tailNum < 100)); - - if (tailNum < 100) // Found an alias not being used - { - // Calculate file checksum - chkSum = 0; - for (aliasPos=0; aliasPos < 12; aliasPos++) - { - // Skip '.' - if (fileAlias[aliasPos] == '.') - aliasPos++; - // NOTE: The operation is an unsigned char rotate right - chkSum = ((chkSum & 1) ? 0x80 : 0) + (chkSum >> 1) + fileAlias[aliasPos]; - } - } - else // Couldn't find a valid alias - { - return false; - } - - dirEntryLength = lfnPos + 2; - } - else // Its not a long file name - { - // Just copy alias straight from filename - for (aliasPos = 0; aliasPos < 13; aliasPos++) - { - tempChar = ucase(filename[aliasPos]); - if ((tempChar > ' ' && tempChar < ':') || tempChar > '?') - fileAlias[aliasPos] = tempChar; - } - fileAlias[12] = '\0'; - - lfnPos = -1; - - dirEntryLength = 1; - } - - // Change dirEntry name to match alias - for (aliasPos = 0; ((fileAlias[aliasPos] != '.') && (fileAlias[aliasPos] != '\0') && (aliasPos < 8)); aliasPos++) - { - newDirEntry.name[aliasPos] = fileAlias[aliasPos]; - } - while (aliasPos < 8) - { - newDirEntry.name[aliasPos++] = ' '; - } - aliasPos = 0; - while ((fileAlias[aliasPos] != '.') && (fileAlias[aliasPos] != '\0')) - aliasPos++; - filePos = 0; - while (( filePos < 3 ) && (fileAlias[aliasPos] != '\0')) - { - tempChar = fileAlias[aliasPos++]; - if ((tempChar > ' ' && tempChar < ':' && tempChar!='.') || tempChar > '?') - newDirEntry.ext[filePos++] = tempChar; - } - while (filePos < 3) - { - newDirEntry.ext[filePos++] = ' '; - } - - // Scan Dir for free entry - dirCluster = curWorkDirCluster; - secOffset = 0; - entryOffset = 0; - maxSectors = (dirCluster == FAT16_ROOT_DIR_CLUSTER ? (filesysData - filesysRootDir) : filesysSecPerClus); - firstSector = (dirCluster == FAT16_ROOT_DIR_CLUSTER ? filesysRootDir : FAT_ClustToSect(dirCluster)); - disc_ReadSector (firstSector + secOffset, dirEntries); - - dirEntryRemain = dirEntryLength; - tempDirCluster = dirCluster; - tempSecOffset = secOffset; - tempEntryOffset = entryOffset; - - // Search for a large enough space to fit in new directory entry - while ((dirEntries[entryOffset].name[0] != FILE_LAST) && (dirEntryRemain > 0)) - { - - entryOffset++; - - if (entryOffset == BYTE_PER_READ / sizeof (DIR_ENT)) - { - entryOffset = 0; - secOffset++; - if ((secOffset == filesysSecPerClus) && (dirCluster != FAT16_ROOT_DIR_CLUSTER)) - { - secOffset = 0; - if (FAT_NextCluster(dirCluster) == CLUSTER_EOF) - { - dirCluster = FAT_LinkFreeCluster(dirCluster); - dirEntries[0].name[0] = FILE_LAST; - } - else - { - dirCluster = FAT_NextCluster(dirCluster); - } - firstSector = FAT_ClustToSect(dirCluster); - } - else if ((dirCluster == FAT16_ROOT_DIR_CLUSTER) && (secOffset == (filesysData - filesysRootDir))) - { - return false; // Got to end of root dir - can't fit in more files - } - disc_ReadSector (firstSector + secOffset, dirEntries); - } - - if ((dirEntries[entryOffset].name[0] == FILE_FREE) || (dirEntries[entryOffset].name[0] == FILE_LAST) ) - { - dirEntryRemain--; - } else { - dirEntryRemain = dirEntryLength; - tempDirCluster = dirCluster; - tempSecOffset = secOffset; - tempEntryOffset = entryOffset; - } - } - - // Modifying the last directory is a special case - have to erase following entries - if (dirEntries[entryOffset].name[0] == FILE_LAST) - { - dirEndFlag = true; - } - - // Recall last used entry - dirCluster = tempDirCluster; - secOffset = tempSecOffset; - entryOffset = tempEntryOffset; - dirEntryRemain = dirEntryLength; - - // Re-read in first sector that will be written to - if (dirEndFlag && (entryOffset == 0)) { - memset (dirEntries, FILE_LAST, BYTE_PER_READ); - } else { - disc_ReadSector (firstSector + secOffset, dirEntries); - } - - // Add new directory entry - while (dirEntryRemain > 0) - { - // Move to next entry, first pass advances from last used entry - entryOffset++; - if (entryOffset == BYTE_PER_READ / sizeof (DIR_ENT)) - { - // Write out the current sector if we need to - entryOffset = 0; - if (dirEntryRemain < dirEntryLength) // Don't write out sector on first pass - { - disc_WriteSector (firstSector + secOffset, dirEntries); - } - secOffset++; - if ((secOffset == filesysSecPerClus) && (dirCluster != FAT16_ROOT_DIR_CLUSTER)) - { - secOffset = 0; - if (FAT_NextCluster(dirCluster) == CLUSTER_EOF) - { - dirCluster = FAT_LinkFreeCluster(dirCluster); - dirEntries[0].name[0] = FILE_LAST; - } - else - { - dirCluster = FAT_NextCluster(dirCluster); - } - firstSector = FAT_ClustToSect(dirCluster); - } - else if ((dirCluster == FAT16_ROOT_DIR_CLUSTER) && (secOffset == (filesysData - filesysRootDir))) - { - return false; // Got to end of root dir - can't fit in more files - } - if (dirEndFlag) - { - memset (dirEntries, FILE_LAST, BYTE_PER_READ); - } else { - disc_ReadSector (firstSector + secOffset, dirEntries); - } - } - - // Generate LFN entries - if (lfnPos >= 0) - { - lfnEntry.ordinal = (lfnPos + 1) | (dirEntryRemain == dirEntryLength ? LFN_END : 0); - for (i = 0; i < 13; i++) { - if (filename [lfnPos * 13 + i] == 0x01) { - ((u8*)&lfnEntry)[(int)lfn_offset_table[i]] = 0xff; - ((u8*)&lfnEntry)[(int)(lfn_offset_table[i]) + 1] = 0xff; - } else { - ((u8*)&lfnEntry)[(int)lfn_offset_table[i]] = filename [lfnPos * 13 + i]; - ((u8*)&lfnEntry)[(int)(lfn_offset_table[i]) + 1] = 0x00; - } - } - - lfnEntry.checkSum = chkSum; - lfnEntry.flag = ATTRIB_LFN; - lfnEntry.reserved1 = 0; - lfnEntry.reserved2 = 0; - - *((DIR_ENT_LFN*)&dirEntries[entryOffset]) = lfnEntry; - lfnPos --; - lfnEntry.ordinal = 0; - } // end writing long filename entries - else - { - dirEntries[entryOffset] = newDirEntry; - if (dirEndFlag && (entryOffset < (BYTE_PER_READ / sizeof (DIR_ENT))) ) - dirEntries[entryOffset+1].name[0] = FILE_LAST; - } - - dirEntryRemain--; - } - - // Write directory back to disk - disc_WriteSector (firstSector + secOffset, dirEntries); - - // Change back to Working DIR - curWorkDirCluster = oldWorkDirCluster; - - return true; -} -#endif - -/*----------------------------------------------------------------- -FAT_FindNextFile -Gets the name of the next directory entry - (can be a file or subdirectory) -char* filename: OUT filename, must be at least 13 chars long -FILE_TYPE return: OUT returns FT_NONE if failed, - FT_FILE if it found a file and FT_DIR if it found a directory ------------------------------------------------------------------*/ -FILE_TYPE FAT_FindNextFile(char* filename) -{ - // Get the next directory entry - DIR_ENT file; - file = FAT_GetDirEntry (curWorkDirCluster, 1, SEEK_CUR); - - if (file.name[0] == FILE_FREE) - { - return FT_NONE; // Did not find a file - } - - // Get the filename - if (filename != NULL) - FAT_GetFilename (file, filename); - - if ((file.attrib & ATTRIB_DIR) != 0) - { - return FT_DIR; // Found a directory - } - else - { - return FT_FILE; // Found a file - } -} - -/*----------------------------------------------------------------- -FAT_FindFirstFile -Gets the name of the first directory entry and resets the count - (can be a file or subdirectory) -char* filename: OUT filename, must be at least 13 chars long -FILE_TYPE return: OUT returns FT_NONE if failed, - FT_FILE if it found a file and FT_DIR if it found a directory ------------------------------------------------------------------*/ -FILE_TYPE FAT_FindFirstFile(char* filename) -{ - // Get the first directory entry - DIR_ENT file; - file = FAT_GetDirEntry (curWorkDirCluster, 1, SEEK_SET); - - if (file.name[0] == FILE_FREE) - { - return FT_NONE; // Did not find a file - } - - // Get the filename - if (filename != NULL) - FAT_GetFilename (file, filename); - - if ((file.attrib & ATTRIB_DIR) != 0) - { - return FT_DIR; // Found a directory - } - else - { - return FT_FILE; // Found a file - } -} - -/*----------------------------------------------------------------- -FAT_FindFirstFileLFN -Gets the long file name of the first directory entry and resets - the count (can be a file or subdirectory) -char* lfn: OUT long file name, must be at least 256 chars long -FILE_TYPE return: OUT returns FT_NONE if failed, - FT_FILE if it found a file and FT_DIR if it found a directory ------------------------------------------------------------------*/ -FILE_TYPE FAT_FindFirstFileLFN(char* lfn) -{ - FILE_TYPE type; - type = FAT_FindFirstFile(NULL); - FAT_GetLongFilename (lfn); - return type; -} - -/*----------------------------------------------------------------- -FAT_FindNextFileLFN -Gets the long file name of the next directory entry - (can be a file or subdirectory) -char* lfn: OUT long file name, must be at least 256 chars long -FILE_TYPE return: OUT returns FT_NONE if failed, - FT_FILE if it found a file and FT_DIR if it found a directory ------------------------------------------------------------------*/ -FILE_TYPE FAT_FindNextFileLFN(char* lfn) -{ - FILE_TYPE type; - type = FAT_FindNextFile(NULL); - FAT_GetLongFilename (lfn); - return type; -} - - -/*----------------------------------------------------------------- -FAT_FileExists -Returns the type of file -char* filename: IN filename of the file to look for -FILE_TYPE return: OUT returns FT_NONE if there is now file with - that name, FT_FILE if it is a file and FT_DIR if it is a directory ------------------------------------------------------------------*/ -FILE_TYPE FAT_FileExists(const char* filename) -{ - DIR_ENT dirEntry; - // Get the dirEntry for the path specified - dirEntry = FAT_DirEntFromPath (filename); - - if (dirEntry.name[0] == FILE_FREE) - { - return FT_NONE; - } - else if (dirEntry.attrib & ATTRIB_DIR) - { - return FT_DIR; - } - else - { - return FT_FILE; - } -} - -/*----------------------------------------------------------------- -FAT_GetFileSystemType -FS_TYPE return: OUT returns the current file system type ------------------------------------------------------------------*/ -FS_TYPE FAT_GetFileSystemType (void) -{ - return filesysType; -} - -/*----------------------------------------------------------------- -FAT_GetFileSystemTotalSize -u32 return: OUT returns the total disk space (used + free) ------------------------------------------------------------------*/ -u32 FAT_GetFileSystemTotalSize (void) -{ - return filesysTotalSize; -} - - - -/*----------------------------------------------------------------- -FAT_chdir -Changes the current working directory -const char* path: IN null terminated string of directory separated by - forward slashes, / is root -bool return: OUT returns true if successful ------------------------------------------------------------------*/ -bool FAT_chdir (const char* path) -{ - DIR_ENT dir; - if (path[0] == '/' && path[1] == '\0') - { - curWorkDirCluster = filesysRootDirClus; - return true; - } - if (path[0] == '\0') // Return true if changing relative to nothing - { - return true; - } - - dir = FAT_DirEntFromPath (path); - - if (((dir.attrib & ATTRIB_DIR) == ATTRIB_DIR) && (dir.name[0] != FILE_FREE)) - { - // Change directory - curWorkDirCluster = dir.startCluster | (dir.startClusterHigh << 16); - - // Move to correct cluster for root directory - if (curWorkDirCluster == FAT16_ROOT_DIR_CLUSTER) - { - curWorkDirCluster = filesysRootDirClus; - } - - // Reset file position in directory - wrkDirCluster = curWorkDirCluster; - wrkDirSector = 0; - wrkDirOffset = -1; - return true; - } - else - { - // Couldn't change directory - wrong path specified - return false; - } -} - -/*----------------------------------------------------------------- -FAT_fopen(filename, mode) -Opens a file -const char* path: IN null terminated string of filename and path - separated by forward slashes, / is root -const char* mode: IN mode to open file in - Supported modes: "r", "r+", "w", "w+", "a", "a+", don't use - "b" or "t" in any mode, as all files are openned in binary mode -FAT_FILE* return: OUT handle to open file, returns NULL if the file - couldn't be openned ------------------------------------------------------------------*/ -FAT_FILE* FAT_fopen(const char* path, const char* mode) -{ - int fileNum; - FAT_FILE* file; - DIR_ENT dirEntry; -#ifdef CAN_WRITE_TO_DISC - u32 startCluster; - int clusCount; -#endif - - char* pchTemp; - // Check that a valid mode was specified - pchTemp = strpbrk ( mode, "rRwWaA" ); - if (pchTemp == NULL) - { - return NULL; - } - if (strpbrk ( pchTemp+1, "rRwWaA" ) != NULL) - { - return NULL; - } - - // Get the dirEntry for the path specified - dirEntry = FAT_DirEntFromPath (path); - - // Check that it is not a directory - if (dirEntry.attrib & ATTRIB_DIR) - { - return NULL; - } - -#ifdef CAN_WRITE_TO_DISC - // Check that it is not a read only file being openned in a writing mode - if ( (strpbrk(mode, "wWaA+") != NULL) && (dirEntry.attrib & ATTRIB_RO)) - { - return NULL; - } -#else - if ( (strpbrk(mode, "wWaA+") != NULL)) - { - return NULL; - } -#endif - - // Find a free file buffer - for (fileNum = 0; (fileNum < MAX_FILES_OPEN) && (openFiles[fileNum].inUse == true); fileNum++); - - if (fileNum == MAX_FILES_OPEN) // No free files - { - return NULL; - } - - file = &openFiles[fileNum]; - // Remember where directory entry was - file->dirEntSector = (wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? filesysRootDir : FAT_ClustToSect(wrkDirCluster)) + wrkDirSector; - file->dirEntOffset = wrkDirOffset; - - if ( strpbrk(mode, "rR") != NULL ) //(ucase(mode[0]) == 'R') - { - if (dirEntry.name[0] == FILE_FREE) // File must exist - { - return NULL; - } - - file->read = true; -#ifdef CAN_WRITE_TO_DISC - file->write = ( strchr(mode, '+') != NULL ); //(mode[1] == '+'); -#else - file->write = false; -#endif - file->append = false; - - // Store information about position within the file, for use - // by FAT_fread, FAT_fseek, etc. - file->firstCluster = dirEntry.startCluster | (dirEntry.startClusterHigh << 16); - -#ifdef CAN_WRITE_TO_DISC - // Check if file is openned for random. If it is, and currently has no cluster, one must be - // assigned to it. - if (file->write && file->firstCluster == CLUSTER_FREE) - { - file->firstCluster = FAT_LinkFreeCluster (CLUSTER_FREE); - if (file->firstCluster == CLUSTER_FREE) // Couldn't get a free cluster - { - return NULL; - } - - // Store cluster position into the directory entry - dirEntry.startCluster = (file->firstCluster & 0xFFFF); - dirEntry.startClusterHigh = ((file->firstCluster >> 16) & 0xFFFF); - disc_ReadSector (file->dirEntSector, globalBuffer); - ((DIR_ENT*) globalBuffer)[file->dirEntOffset] = dirEntry; - disc_WriteSector (file->dirEntSector, globalBuffer); - } -#endif - - file->length = dirEntry.fileSize; - file->curPos = 0; - file->curClus = dirEntry.startCluster | (dirEntry.startClusterHigh << 16); - file->curSect = 0; - file->curByte = 0; - - // Not appending - file->appByte = 0; - file->appClus = 0; - file->appSect = 0; - - disc_ReadSector( FAT_ClustToSect( file->curClus), file->readBuffer); - file->inUse = true; // We're using this file now - - return file; - } // mode "r" - -#ifdef CAN_WRITE_TO_DISC - if ( strpbrk(mode, "wW") != NULL ) // (ucase(mode[0]) == 'W') - { - if (dirEntry.name[0] == FILE_FREE) // Create file if it doesn't exist - { - dirEntry.attrib = ATTRIB_ARCH; - dirEntry.reserved = 0; - - // Time and date set to system time and date - dirEntry.cTime_ms = 0; - dirEntry.cTime = getRTCtoFileTime(); - dirEntry.cDate = getRTCtoFileDate(); - dirEntry.aDate = getRTCtoFileDate(); - dirEntry.mTime = getRTCtoFileTime(); - dirEntry.mDate = getRTCtoFileDate(); - } - else // Already a file entry - { - // Free any clusters used - FAT_ClearLinks (dirEntry.startCluster | (dirEntry.startClusterHigh << 16)); - } - - // Get a cluster to use - startCluster = FAT_LinkFreeCluster (CLUSTER_FREE); - if (startCluster == CLUSTER_FREE) // Couldn't get a free cluster - { - return NULL; - } - - // Store cluster position into the directory entry - dirEntry.startCluster = (startCluster & 0xFFFF); - dirEntry.startClusterHigh = ((startCluster >> 16) & 0xFFFF); - - // The file has no data in it - its over written so should be empty - dirEntry.fileSize = 0; - - if (dirEntry.name[0] == FILE_FREE) // No file - { - // Have to create a new entry - if(!FAT_AddDirEntry (path, dirEntry)) - { - return NULL; - } - // Get the newly created dirEntry - dirEntry = FAT_DirEntFromPath (path); - - // Remember where directory entry was - file->dirEntSector = (wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? filesysRootDir : FAT_ClustToSect(wrkDirCluster)) + wrkDirSector; - file->dirEntOffset = wrkDirOffset; - } - else // Already a file - { - // Just modify the old entry - disc_ReadSector (file->dirEntSector, globalBuffer); - ((DIR_ENT*) globalBuffer)[file->dirEntOffset] = dirEntry; - disc_WriteSector (file->dirEntSector, globalBuffer); - } - - - // Now that file is created, open it - file->read = ( strchr(mode, '+') != NULL ); //(mode[1] == '+'); - file->write = true; - file->append = false; - - // Store information about position within the file, for use - // by FAT_fread, FAT_fseek, etc. - file->firstCluster = startCluster; - file->length = 0; // Should always have 0 bytes if openning in "w" mode - file->curPos = 0; - file->curClus = startCluster; - file->curSect = 0; - file->curByte = 0; - - // Not appending - file->appByte = 0; - file->appClus = 0; - file->appSect = 0; - - // Empty file, so empty read buffer - memset (file->readBuffer, 0, BYTE_PER_READ); - file->inUse = true; // We're using this file now - - return file; - } - - if ( strpbrk(mode, "aA") != NULL ) // (ucase(mode[0]) == 'A') - { - if (dirEntry.name[0] == FILE_FREE) // Create file if it doesn't exist - { - dirEntry.attrib = ATTRIB_ARCH; - dirEntry.reserved = 0; - - // Time and date set to system time and date - dirEntry.cTime_ms = 0; - dirEntry.cTime = getRTCtoFileTime(); - dirEntry.cDate = getRTCtoFileDate(); - dirEntry.aDate = getRTCtoFileDate(); - dirEntry.mTime = getRTCtoFileTime(); - dirEntry.mDate = getRTCtoFileDate(); - - // The file has no data in it - dirEntry.fileSize = 0; - - // Get a cluster to use - startCluster = FAT_LinkFreeCluster (CLUSTER_FREE); - if (startCluster == CLUSTER_FREE) // Couldn't get a free cluster - { - return NULL; - } - dirEntry.startCluster = (startCluster & 0xFFFF); - dirEntry.startClusterHigh = ((startCluster >> 16) & 0xFFFF); - - if(!FAT_AddDirEntry (path, dirEntry)) - return NULL; - - // Get the newly created dirEntry - dirEntry = FAT_DirEntFromPath (path); - - // Store append cluster - file->appClus = startCluster; - - // Remember where directory entry was - file->dirEntSector = (wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? filesysRootDir : FAT_ClustToSect(wrkDirCluster)) + wrkDirSector; - file->dirEntOffset = wrkDirOffset; - } - else // File already exists - reuse the old directory entry - { - startCluster = dirEntry.startCluster | (dirEntry.startClusterHigh << 16); - // If it currently has no cluster, one must be assigned to it. - if (startCluster == CLUSTER_FREE) - { - file->firstCluster = FAT_LinkFreeCluster (CLUSTER_FREE); - if (file->firstCluster == CLUSTER_FREE) // Couldn't get a free cluster - { - return NULL; - } - - // Store cluster position into the directory entry - dirEntry.startCluster = (file->firstCluster & 0xFFFF); - dirEntry.startClusterHigh = ((file->firstCluster >> 16) & 0xFFFF); - disc_ReadSector (file->dirEntSector, globalBuffer); - ((DIR_ENT*) globalBuffer)[file->dirEntOffset] = dirEntry; - disc_WriteSector (file->dirEntSector, globalBuffer); - - // Store append cluster - file->appClus = startCluster; - - } else { - - // Follow cluster list until last one is found - clusCount = dirEntry.fileSize / filesysBytePerClus; - file->appClus = startCluster; - while ((clusCount--) && (FAT_NextCluster (file->appClus) != CLUSTER_FREE) && (FAT_NextCluster (file->appClus) != CLUSTER_EOF)) - { - file->appClus = FAT_NextCluster (file->appClus); - } - if (clusCount >= 0) // Check if ran out of clusters - { - // Set flag to allocate new cluster when needed - file->appSect = filesysSecPerClus; - file->appByte = 0; - } - } - } - - // Now that file is created, open it - file->read = ( strchr(mode, '+') != NULL ); - file->write = false; - file->append = true; - - // Calculate the sector and byte of the current position, - // and store them - file->appSect = (dirEntry.fileSize % filesysBytePerClus) / BYTE_PER_READ; - file->appByte = dirEntry.fileSize % BYTE_PER_READ; - - // Store information about position within the file, for use - // by FAT_fread, FAT_fseek, etc. - file->firstCluster = startCluster; - file->length = dirEntry.fileSize; - file->curPos = dirEntry.fileSize; - file->curClus = file->appClus; - file->curSect = file->appSect; - file->curByte = file->appByte; - - // Read into buffer - disc_ReadSector( FAT_ClustToSect(file->curClus) + file->curSect, file->readBuffer); - file->inUse = true; // We're using this file now - return file; - } -#endif - - // Can only reach here if a bad mode was specified - return NULL; -} - -/*----------------------------------------------------------------- -FAT_fclose(file) -Closes a file -FAT_FILE* file: IN handle of the file to close -bool return OUT: true if successful, false if not ------------------------------------------------------------------*/ -bool FAT_fclose (FAT_FILE* file) -{ - // Clear memory used by file information - if ((file != NULL) && (file->inUse == true)) - { -#ifdef CAN_WRITE_TO_DISC - if (file->write || file->append) - { - // Write new length, time and date back to directory entry - disc_ReadSector (file->dirEntSector, globalBuffer); - - ((DIR_ENT*)globalBuffer)[file->dirEntOffset].fileSize = file->length; - ((DIR_ENT*)globalBuffer)[file->dirEntOffset].mTime = getRTCtoFileTime(); - ((DIR_ENT*)globalBuffer)[file->dirEntOffset].mDate = getRTCtoFileDate(); - ((DIR_ENT*)globalBuffer)[file->dirEntOffset].aDate = getRTCtoFileDate(); - - disc_WriteSector (file->dirEntSector, globalBuffer); - - // Flush any sectors in disc cache - disc_CacheFlush(); - } -#endif - file->inUse = false; - return true; - } - else - { - return false; - } -} - -/*----------------------------------------------------------------- -FAT_ftell(file) -Returns the current position in a file -FAT_FILE* file: IN handle of an open file -u32 OUT: Current position ------------------------------------------------------------------*/ -u32 FAT_ftell (FAT_FILE* file) -{ - // Return the position as specified in the FAT_FILE structure - if ((file != NULL) && (file->inUse == true)) - { - return file->curPos; - } - else - { - // Return -1 if no file was given - return -1; - } -} - -/*----------------------------------------------------------------- -FAT_fseek(file, offset, origin) -Seeks to specified byte position in file -FAT_FILE* file: IN handle of an open file -s32 offset IN: position to seek to, relative to origin -int origin IN: origin to seek from -int OUT: Returns 0 if successful, -1 if not ------------------------------------------------------------------*/ -int FAT_fseek(FAT_FILE* file, s32 offset, int origin) -{ - u32 cluster, nextCluster; - int clusCount; - u32 position; - u32 curPos; - - if ((file == NULL) || (file->inUse == false)) // invalid file - { - return -1; - } - - // Can't seek in append only mode - if (!file->read && !file->write) - { - return -1; - } - - curPos = file->curPos; - - switch (origin) - { - case SEEK_SET: - if (offset >= 0) - { - position = offset; - } else { - // Tried to seek before start of file - position = 0; - } - break; - case SEEK_CUR: - if (offset >= 0) - { - position = curPos + offset; - } - else if ( (u32)(offset * -1) >= curPos ) - { - // Tried to seek before start of file - position = 0; - } - else - { - // Using u32 to maintain 32 bits of accuracy - position = curPos - (u32)(offset * -1); - } - break; - case SEEK_END: - if (offset >= 0) - { - // Seeking to end of file - position = file->length; // Fixed thanks to MoonLight - } - else if ( (u32)(offset * -1) >= file->length ) - { - // Tried to seek before start of file - position = 0; - } - else - { - // Using u32 to maintain 32 bits of accuracy - position = file->length - (u32)(offset * -1); - } - break; - default: - return -1; - } - - if (position > file->length) - { - // Tried to go past end of file - position = file->length; - } - - // Save position - file->curPos = position; - - - // Calculate where the correct cluster is - if (position > curPos) - { - clusCount = (position - curPos + (file->curSect * filesysBytePerSec) + file->curByte) / filesysBytePerClus; // Fixed thanks to AgentQ - cluster = file->curClus; - } else { - clusCount = position / filesysBytePerClus; - cluster = file->firstCluster; - } - - // Calculate the sector and byte of the current position, - // and store them - file->curSect = (position % filesysBytePerClus) / BYTE_PER_READ; - file->curByte = position % BYTE_PER_READ; - - // Follow cluster list until desired one is found - if (clusCount > 0) // Only look at next cluster if need to - { - nextCluster = FAT_NextCluster (cluster); - } else { - nextCluster = cluster; - } - while ((clusCount--) && (nextCluster != CLUSTER_FREE) && (nextCluster != CLUSTER_EOF)) - { - cluster = nextCluster; - nextCluster = FAT_NextCluster (cluster); - } - // Check if ran out of clusters, and the file is being written to - if ((clusCount >= 0) && (file->write || file->append)) - { - // Set flag to allocate a new cluster - file->curSect = filesysSecPerClus; - file->curByte = 0; - } - file->curClus = cluster; - - // Reload sector buffer for new position in file, if it is a different sector - if ((curPos ^ position) >= BYTE_PER_READ) - { - disc_ReadSector( file->curSect + FAT_ClustToSect(file->curClus), file->readBuffer); - } - - return 0; -} - -/*----------------------------------------------------------------- -FAT_fread(buffer, size, count, file) -Reads in size * count bytes into buffer from file, starting - from current position. It then sets the current position to the - byte after the last byte read. If it reaches the end of file - before filling the buffer then it stops reading. -void* buffer OUT: Pointer to buffer to fill. Should be at least as - big as the number of bytes required -u32 size IN: size of each item to read -u32 count IN: number of items to read -FAT_FILE* file IN: Handle of an open file -u32 OUT: returns the actual number of bytes read ------------------------------------------------------------------*/ -u32 FAT_fread (void* buffer, u32 size, u32 count, FAT_FILE* file) -{ - int curByte; - int curSect; - u32 curClus; - u32 tempNextCluster; - - int tempVar; - - char* data = (char*)buffer; - - u32 length = size * count; - u32 remain; - - bool flagNoError = true; - - // Can't read non-existant files - if ((file == NULL) || (file->inUse == false) || size == 0 || count == 0 || buffer == NULL) - return 0; - - // Can only read files openned for reading - if (!file->read) - return 0; - - // Don't read past end of file - if (length + file->curPos > file->length) - length = file->length - file->curPos; - - remain = length; - - curByte = file->curByte; - curSect = file->curSect; - curClus = file->curClus; - - // Align to sector - tempVar = BYTE_PER_READ - curByte; - if (tempVar > remain) - tempVar = remain; - - if ((tempVar < BYTE_PER_READ) && flagNoError) - { - memcpy(data, &(file->readBuffer[curByte]), tempVar); - remain -= tempVar; - data += tempVar; - - curByte += tempVar; - if (curByte >= BYTE_PER_READ) - { - curByte = 0; - curSect++; - } - } - - // align to cluster - // tempVar is number of sectors to read - if (remain > (filesysSecPerClus - curSect) * BYTE_PER_READ) - { - tempVar = filesysSecPerClus - curSect; - } else { - tempVar = remain / BYTE_PER_READ; - } - - if ((tempVar > 0) && flagNoError) - { - disc_ReadSectors ( curSect + FAT_ClustToSect(curClus), tempVar, data); - data += tempVar * BYTE_PER_READ; - remain -= tempVar * BYTE_PER_READ; - - curSect += tempVar; - } - - // Move onto next cluster - // It should get to here without reading anything if a cluster is due to be allocated - if (curSect >= filesysSecPerClus) - { - tempNextCluster = FAT_NextCluster(curClus); - if ((remain == 0) && (tempNextCluster == CLUSTER_EOF)) - { - curSect = filesysSecPerClus; - } else { - curSect = 0; - curClus = tempNextCluster; - if (curClus == CLUSTER_FREE) - { - flagNoError = false; - } - } - } - - // Read in whole clusters - while ((remain >= filesysBytePerClus) && flagNoError) - { - disc_ReadSectors (FAT_ClustToSect(curClus), filesysSecPerClus, data); - data += filesysBytePerClus; - remain -= filesysBytePerClus; - - // Advance to next cluster - tempNextCluster = FAT_NextCluster(curClus); - if ((remain == 0) && (tempNextCluster == CLUSTER_EOF)) - { - curSect = filesysSecPerClus; - } else { - curSect = 0; - curClus = tempNextCluster; - if (curClus == CLUSTER_FREE) - { - flagNoError = false; - } - } - } - - // Read remaining sectors - tempVar = remain / BYTE_PER_READ; // Number of sectors left - if ((tempVar > 0) && flagNoError) - { - disc_ReadSectors (FAT_ClustToSect(curClus), tempVar, data); - data += tempVar * BYTE_PER_READ; - remain -= tempVar * BYTE_PER_READ; - curSect += tempVar; - } - - // Last remaining sector - // Check if sector wanted is different to the one started with - if ( ((file->curByte + length) >= BYTE_PER_READ) && flagNoError) - { - disc_ReadSector( curSect + FAT_ClustToSect( curClus), file->readBuffer); - if (remain > 0) - { - memcpy(data, file->readBuffer, remain); - curByte += remain; - remain = 0; - } - } - - // Length read is the wanted length minus the stuff not read - length = length - remain; - - // Update file information - file->curByte = curByte; - file->curSect = curSect; - file->curClus = curClus; - file->curPos = file->curPos + length; - return length; -} - -#ifdef CAN_WRITE_TO_DISC -/*----------------------------------------------------------------- -FAT_fwrite(buffer, size, count, file) -Writes size * count bytes into file from buffer, starting - from current position. It then sets the current position to the - byte after the last byte written. If the file was openned in - append mode it always writes to the end of the file. -const void* buffer IN: Pointer to buffer containing data. Should be - at least as big as the number of bytes to be written. -u32 size IN: size of each item to write -u32 count IN: number of items to write -FAT_FILE* file IN: Handle of an open file -u32 OUT: returns the actual number of bytes written ------------------------------------------------------------------*/ -u32 FAT_fwrite (const void* buffer, u32 size, u32 count, FAT_FILE* file) -{ - int curByte; - int curSect; - u32 curClus; - - u32 tempNextCluster; - int tempVar; - u32 length = size * count; - u32 remain = length; - char* data = (char*)buffer; - - char* writeBuffer; - - bool flagNoError = true; - bool flagAppending = false; - - if ((file == NULL) || (file->inUse == false) || length == 0 || buffer == NULL) - return 0; - - if (file->write) - { - // Write at current read pointer - curByte = file->curByte; - curSect = file->curSect; - curClus = file->curClus; - - // Use read buffer as write buffer - writeBuffer = file->readBuffer; - - // If it is writing past the current end of file, set appending flag - if (length + file->curPos > file->length) - { - flagAppending = true; - } - } - else if (file->append) - { - // Write at end of file - curByte = file->appByte; - curSect = file->appSect; - curClus = file->appClus; - flagAppending = true; - - // Use global buffer as write buffer, don't touch read buffer - writeBuffer = (char*)globalBuffer; - disc_ReadSector(curSect + FAT_ClustToSect(curClus), writeBuffer); - } - else - { - return 0; - } - - // Move onto next cluster if needed - if (curSect >= filesysSecPerClus) - { - curSect = 0; - tempNextCluster = FAT_NextCluster(curClus); - if ((tempNextCluster == CLUSTER_EOF) || (tempNextCluster == CLUSTER_FREE)) - { - // Ran out of clusters so get a new one - curClus = FAT_LinkFreeCluster(curClus); - if (curClus == CLUSTER_FREE) // Couldn't get a cluster, so abort - { - flagNoError = false; - } - memset(writeBuffer, 0, BYTE_PER_READ); - } else { - curClus = tempNextCluster; - disc_ReadSector( FAT_ClustToSect( curClus), writeBuffer); - } - } - - // Align to sector - tempVar = BYTE_PER_READ - curByte; - if (tempVar > remain) - tempVar = remain; - - if ((tempVar < BYTE_PER_READ) && flagNoError) - { - memcpy(&(writeBuffer[curByte]), data, tempVar); - remain -= tempVar; - data += tempVar; - curByte += tempVar; - - // Write buffer back to disk - disc_WriteSector (curSect + FAT_ClustToSect(curClus), writeBuffer); - - // Move onto next sector - if (curByte >= BYTE_PER_READ) - { - curByte = 0; - curSect++; - } - } - - // Align to cluster - // tempVar is number of sectors to write - if (remain > (filesysSecPerClus - curSect) * BYTE_PER_READ) - { - tempVar = filesysSecPerClus - curSect; - } else { - tempVar = remain / BYTE_PER_READ; - } - - if ((tempVar > 0) && flagNoError) - { - disc_WriteSectors ( curSect + FAT_ClustToSect(curClus), tempVar, data); - data += tempVar * BYTE_PER_READ; - remain -= tempVar * BYTE_PER_READ; - curSect += tempVar; - } - - if (((curSect >= filesysSecPerClus) && flagNoError) && (remain > 0)) - { - curSect = 0; - tempNextCluster = FAT_NextCluster(curClus); - if ((tempNextCluster == CLUSTER_EOF) || (tempNextCluster == CLUSTER_FREE)) - { - // Ran out of clusters so get a new one - curClus = FAT_LinkFreeCluster(curClus); - if (curClus == CLUSTER_FREE) // Couldn't get a cluster, so abort - { - flagNoError = false; - } - } else { - curClus = tempNextCluster; - } - } - - // Write whole clusters - while ((remain >= filesysBytePerClus) && flagNoError) - { - disc_WriteSectors (FAT_ClustToSect(curClus), filesysSecPerClus, data); - data += filesysBytePerClus; - remain -= filesysBytePerClus; - if (remain > 0) - { - tempNextCluster = FAT_NextCluster(curClus); - if ((tempNextCluster == CLUSTER_EOF) || (tempNextCluster == CLUSTER_FREE)) - { - // Ran out of clusters so get a new one - curClus = FAT_LinkFreeCluster(curClus); - if (curClus == CLUSTER_FREE) // Couldn't get a cluster, so abort - { - flagNoError = false; - break; - } - } else { - curClus = tempNextCluster; - } - } else { - // Allocate a new cluster when next writing the file - curSect = filesysSecPerClus; - } - } - - // Write remaining sectors - tempVar = remain / BYTE_PER_READ; // Number of sectors left - if ((tempVar > 0) && flagNoError) - { - disc_WriteSectors (FAT_ClustToSect(curClus), tempVar, data); - data += tempVar * BYTE_PER_READ; - remain -= tempVar * BYTE_PER_READ; - curSect += tempVar; - } - - // Last remaining sector - // Check if sector wanted is different to the one started with - if ( (( (file->append ? file->appByte : file->curByte) + length) >= BYTE_PER_READ) && flagNoError) - { - if (flagAppending) - { - // Zero sector before using it - memset (writeBuffer, 0, BYTE_PER_READ); - } else { - // Modify existing sector - disc_ReadSector( curSect + FAT_ClustToSect( curClus), writeBuffer); - } - if (remain > 0) { - memcpy(writeBuffer, data, remain); - curByte += remain; - remain = 0; - disc_WriteSector( curSect + FAT_ClustToSect( curClus), writeBuffer); - } - } - - // Amount read is the originally requested amount minus stuff remaining - length = length - remain; - - // Update file information - if (file->write) // Writing also shifts the read pointer - { - file->curByte = curByte; - file->curSect = curSect; - file->curClus = curClus; - file->curPos = file->curPos + length; - if (file->length < file->curPos) - { - file->length = file->curPos; - } - } - else if (file->append) // Appending doesn't affect the read pointer - { - file->appByte = curByte; - file->appSect = curSect; - file->appClus = curClus; - file->length = file->length + length; - } - - return length; -} -#endif - - -/*----------------------------------------------------------------- -FAT_feof(file) -Returns true if the end of file has been reached -FAT_FILE* file IN: Handle of an open file -bool return OUT: true if EOF, false if not ------------------------------------------------------------------*/ -bool FAT_feof(FAT_FILE* file) -{ - if ((file == NULL) || (file->inUse == false)) - return true; // Return eof on invalid files - - return (file->length == file->curPos); -} - - -#ifdef CAN_WRITE_TO_DISC -/*----------------------------------------------------------------- -FAT_remove (path) -Deletes the file or empty directory sepecified in path -const char* path IN: Path of item to delete -int return OUT: zero if successful, non-zero if not ------------------------------------------------------------------*/ -int FAT_remove (const char* path) -{ - DIR_ENT dirEntry; - u32 oldWorkDirCluster; - char checkFilename[13]; - FILE_TYPE checkFiletype; - - dirEntry = FAT_DirEntFromPath (path); - - if (dirEntry.name[0] == FILE_FREE) - { - return -1; - } - - // Only delete directories if the directory is entry - if (dirEntry.attrib & ATTRIB_DIR) - { - // Change to the directory temporarily - oldWorkDirCluster = curWorkDirCluster; - FAT_chdir(path); - - // Search for files or directories, excluding the . and .. entries - checkFiletype = FAT_FindFirstFile (checkFilename); - while ((checkFilename[0] == '.') && (checkFiletype != FT_NONE)) - { - checkFiletype = FAT_FindNextFile (checkFilename); - } - - // Change back to working directory - curWorkDirCluster = oldWorkDirCluster; - - // Check that the directory is empty - if (checkFiletype != FT_NONE) - { - // Directory isn't empty - return -1; - } - } - - // Refresh directory information - dirEntry = FAT_DirEntFromPath (path); - - // Free any clusters used - FAT_ClearLinks (dirEntry.startCluster | (dirEntry.startClusterHigh << 16)); - - // Remove Directory entry - disc_ReadSector ( (wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? filesysRootDir : FAT_ClustToSect(wrkDirCluster)) + wrkDirSector , globalBuffer); - ((DIR_ENT*)globalBuffer)[wrkDirOffset].name[0] = FILE_FREE; - disc_WriteSector ( (wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? filesysRootDir : FAT_ClustToSect(wrkDirCluster)) + wrkDirSector , globalBuffer); - - // Flush any sectors in disc cache - disc_CacheFlush(); - - return 0; -} -#endif - -#ifdef CAN_WRITE_TO_DISC -/*----------------------------------------------------------------- -FAT_mkdir (path) -Makes a new directory, so long as no other directory or file has - the same name. -const char* path IN: Path and filename of directory to make -int return OUT: zero if successful, non-zero if not ------------------------------------------------------------------*/ -int FAT_mkdir (const char* path) -{ - u32 newDirCluster; - u32 parentDirCluster; - DIR_ENT dirEntry; - DIR_ENT* entries = (DIR_ENT*)globalBuffer; - int i; - - int pathPos, filePos; - char pathname[MAX_FILENAME_LENGTH]; - u32 oldDirCluster; - - if (FAT_FileExists(path) != FT_NONE) - { - return -1; // File or directory exists with that name - } - - // Find filename within path and change to that directory - oldDirCluster = curWorkDirCluster; - if (path[0] == '/') - { - curWorkDirCluster = filesysRootDirClus; - } - - pathPos = 0; - filePos = 0; - - while (path[pathPos + filePos] != '\0') - { - if (path[pathPos + filePos] == '/') - { - pathname[filePos] = '\0'; - if (FAT_chdir(pathname) == false) - { - curWorkDirCluster = oldDirCluster; - return -1; // Couldn't change directory - } - pathPos += filePos + 1; - filePos = 0; - } - pathname[filePos] = path[pathPos + filePos]; - filePos++; - } - - // Now grab the parent directory's cluster - parentDirCluster = curWorkDirCluster; - curWorkDirCluster = oldDirCluster; - - // Get a new cluster for the file - newDirCluster = FAT_LinkFreeCluster(CLUSTER_FREE); - - if (newDirCluster == CLUSTER_FREE) - { - return -1; // Couldn't get a new cluster for the directory - } - // Fill in directory entry's information - dirEntry.attrib = ATTRIB_DIR; - dirEntry.reserved = 0; - // Time and date set to system time and date - dirEntry.cTime_ms = 0; - dirEntry.cTime = getRTCtoFileTime(); - dirEntry.cDate = getRTCtoFileDate(); - dirEntry.aDate = getRTCtoFileDate(); - dirEntry.mTime = getRTCtoFileTime(); - dirEntry.mDate = getRTCtoFileDate(); - // Store cluster position into the directory entry - dirEntry.startCluster = (newDirCluster & 0xFFFF); - dirEntry.startClusterHigh = ((newDirCluster >> 16) & 0xFFFF); - // The file has no data in it - its over written so should be empty - dirEntry.fileSize = 0; - - if (FAT_AddDirEntry (path, dirEntry) == false) - { - return -1; // Couldn't add the directory entry - } - - // Create the new directory itself - memset(entries, FILE_LAST, BYTE_PER_READ); - - // Create . directory entry - dirEntry.name[0] = '.'; - // Fill name and extension with spaces - for (i = 1; i < 11; i++) - { - dirEntry.name[i] = ' '; - } - - memcpy(entries, &dirEntry, sizeof(dirEntry)); - - // Create .. directory entry - dirEntry.name[1] = '.'; - dirEntry.startCluster = (parentDirCluster & 0xFFFF); - dirEntry.startClusterHigh = ((parentDirCluster >> 16) & 0xFFFF); - - memcpy(&entries[1], &dirEntry, sizeof(dirEntry)); - - // Write entry to disc - disc_WriteSector(FAT_ClustToSect(newDirCluster), entries); - - // Flush any sectors in disc cache - disc_CacheFlush(); - return 0; -} -#endif - -/*----------------------------------------------------------------- -FAT_fgetc (handle) -Gets the next character in the file -FAT_FILE* file IN: Handle of open file -bool return OUT: character if successful, EOF if not ------------------------------------------------------------------*/ -char FAT_fgetc (FAT_FILE* file) -{ - char c; - return (FAT_fread(&c, 1, 1, file) == 1) ? c : EOF; -} - -#ifdef CAN_WRITE_TO_DISC -/*----------------------------------------------------------------- -FAT_fputc (character, handle) -Writes the given character into the file -char c IN: Character to be written -FAT_FILE* file IN: Handle of open file -bool return OUT: character if successful, EOF if not ------------------------------------------------------------------*/ -char FAT_fputc (char c, FAT_FILE* file) -{ - return (FAT_fwrite(&c, 1, 1, file) == 1) ? c : EOF; -} -#endif - -/*----------------------------------------------------------------- -FAT_fgets (char *tgtBuffer, int num, FAT_FILE* file) -Gets a up to num bytes from file, stopping at the first - newline. - -CAUTION: does not do strictly streaming. I.e. it's - reading more then needed bytes and seeking back. - shouldn't matter for random access - -char *tgtBuffer OUT: buffer to write to -int num IN: size of target buffer -FAT_FILE* file IN: Handle of open file -bool return OUT: character if successful, EOF if not - - Written by MightyMax - Modified by Chishm - 2005-11-17 - * Added check for unix style text files - * Removed seek when no newline is found, since it isn't necessary --------------------------------------------------------------------*/ -char *FAT_fgets(char *tgtBuffer, int num, FAT_FILE* file) -{ - u32 curPos; - u32 readLength; - char *returnChar; - - // invalid filehandle - if (file == NULL) - { - return NULL ; - } - - // end of file - if (FAT_feof(file)==true) - { - return NULL ; - } - - // save current position - curPos = FAT_ftell(file); - - // read the full buffer (max string chars is num-1 and one end of string \0 - readLength = FAT_fread(tgtBuffer,1,num-1,file) ; - - // mark least possible end of string - tgtBuffer[readLength] = '\0' ; - - if (readLength==0) { - // return error - return NULL ; - } - - // get position of first return '\r' - returnChar = strchr(tgtBuffer,'\r'); - - // if no return is found, search for a newline - if (returnChar == NULL) - { - returnChar = strchr(tgtBuffer,'\n'); - } - - // Mark the return, if existant, as end of line/string - if (returnChar!=NULL) { - *returnChar++ = 0 ; - if (*returnChar=='\n') { // catch newline too when jumping over the end - // return to location after \r\n (strlen+2) - FAT_fseek(file,curPos+strlen(tgtBuffer)+2,SEEK_SET) ; - return tgtBuffer ; - } else { - // return to location after \r (strlen+1) - FAT_fseek(file,curPos+strlen(tgtBuffer)+1,SEEK_SET) ; - return tgtBuffer ; - } - } - - return tgtBuffer ; -} - -#ifdef CAN_WRITE_TO_DISC -/*----------------------------------------------------------------- -FAT_fputs (const char *string, FAT_FILE* file) -Writes string to file, excluding end of string character -const char *string IN: string to write -FAT_FILE* file IN: Handle of open file -bool return OUT: number of characters written if successful, - EOF if not - - Written by MightyMax - Modified by Chishm - 2005-11-17 - * Uses FAT_FILE instead of int - * writtenBytes is now u32 instead of int --------------------------------------------------------------------*/ -int FAT_fputs (const char *string, FAT_FILE* file) -{ - u32 writtenBytes; - // save string except end of string '\0' - writtenBytes = FAT_fwrite((void *)string, 1, strlen(string), file); - - // check if we had an error - if (writtenBytes != strlen(string)) - { - // return EOF error - return EOF; - } - - // return the charcount written - return writtenBytes ; -} -#endif - - - diff --git a/backends/platform/ds/arm9/source/fat/io_fcsr.c b/backends/platform/ds/arm9/source/fat/io_fcsr.c index 8ca311ac92..d576dfbb0f 100644 --- a/backends/platform/ds/arm9/source/fat/io_fcsr.c +++ b/backends/platform/ds/arm9/source/fat/io_fcsr.c @@ -327,332 +327,3 @@ LPIO_INTERFACE FCSR_GetInterface(void) { } ; #endif // SUPPORT_FCSR -/* - io_fcsr.c based on - - compact_flash.c - By chishm (Michael Chisholm) - - Hardware Routines for using a GBA Flash Cart and SRAM as a - block device. - - This software is completely free. No warranty is provided. - If you use it, please give me credit and email me about your - project at chishm@hotmail.com - - See gba_nds_fat.txt for help and license details. - - The file system must be 512 byte aligned, in cart address space. - SRAM is supported. -*/ - - -#include "io_fcsr.h" - -#ifdef SUPPORT_FCSR -#include - -//--------------------------------------------------------------- -// DMA -#ifdef _CF_USE_DMA - #ifndef NDS - #include "gba_dma.h" - #else - #include - #ifdef ARM9 - #include - #endif - #endif -#endif - -#ifdef NDS - #define SRAM_START 0x0A000000 -#else - #define SRAM_START 0x0E000000 -#endif - -#define NO_SRAM 0xFFFFFFFF - -#define FCSR 0x52534346 -const char FCSR_LabelString[] = " Chishm FAT"; - -u8* FCSR_FileSysPointer = 0; -u8* FCSR_SramSectorPointer[4] = {0,0,0,0}; -u32 FCSR_SramSectorStart[4] = {0,0,0,0}; -u32 FCSR_SramSectorEnd[4] = {0,0,0,0}; - -/*----------------------------------------------------------------- -FCSR_IsInserted -Is a GBA Flash Cart with a valid file system inserted? -bool return OUT: true if a GBA FC card is inserted ------------------------------------------------------------------*/ -bool FCSR_IsInserted (void) -{ - bool flagFoundFileSys = false; - - u32* fileSysPointer = (u32*)0x08000100; // Start at beginning of cart address space, offset by expected location of string - - // Search for file system - while ((fileSysPointer < (u32*)0x0A000000) && !flagFoundFileSys) // Only search while not at end of cart address space - { - while ((*fileSysPointer != FCSR) && (fileSysPointer < (u32*)0x0A000000)) - fileSysPointer += 0x40; - if ((strncmp(FCSR_LabelString, (char*)(fileSysPointer + 1), 12) == 0) && (fileSysPointer < (u32*)0x0A000000)) - { - flagFoundFileSys = true; - } else { - fileSysPointer += 0x80; - } - } - - return flagFoundFileSys; -} - - -/*----------------------------------------------------------------- -FCSR_ClearStatus -Finish any pending operations -bool return OUT: always true for GBA FC ------------------------------------------------------------------*/ -bool FCSR_ClearStatus (void) -{ - return true; -} - - -/*----------------------------------------------------------------- -FCSR_ReadSectors -Read 512 byte sector numbered "sector" into "buffer" -u32 sector IN: address of first 512 byte sector on Flash Cart to read -u8 numSecs IN: number of 512 byte sectors to read, - 1 to 256 sectors can be read, 0 = 256 -void* buffer OUT: pointer to 512 byte buffer to store data in -bool return OUT: true if successful ------------------------------------------------------------------*/ -bool FCSR_ReadSectors (u32 sector, u8 numSecs, void* buffer) -{ - int i; - bool flagSramSector = false; - int numSectors = (numSecs > 0 ? numSecs : 256); - int readLength = numSectors * BYTE_PER_READ; - u8* src;; - u8* dst; - - // Find which region this read is in - for (i = 0; (i < 4) && !flagSramSector; i++) - { - if ((sector >= FCSR_SramSectorStart[i]) && (sector < FCSR_SramSectorEnd[i])) - { - flagSramSector = true; - break; - } - } - - // Make sure read will be completely in SRAM range if it is partially there - if ( flagSramSector && ((sector + numSectors) > FCSR_SramSectorEnd[i])) - return false; - - // Copy data to buffer - if (flagSramSector) - { - src = FCSR_SramSectorPointer[i] + (sector - FCSR_SramSectorStart[i]) * BYTE_PER_READ; - } else { - src = FCSR_FileSysPointer + sector * BYTE_PER_READ; - } - dst = (u8*)buffer; - - if (flagSramSector) - { - while (readLength--) - { - *dst++ = *src++; - } - } else { // Reading from Cart ROM - -#ifdef _CF_USE_DMA - #ifdef NDS - #ifdef ARM9 - DC_FlushRange( buffer, readLength); - #endif // ARM9 - DMA3_SRC = (u32)src; - DMA3_DEST = (u32)buffer; - DMA3_CR = (readLength >> 1) | DMA_COPY_HALFWORDS; - #else // ! NDS - DMA3COPY ( src, buffer, (readLength >> 1) | DMA16 | DMA_ENABLE); - #endif // NDS -#else // !_CF_USE_DMA - memcpy (buffer, src, readLength); -#endif // _CF_USE_DMA - - } // if (flagSramSector) - - return true; -} - -/*----------------------------------------------------------------- -FCSR_WriteSectors -Write 512 byte sector numbered "sector" from "buffer" -u32 sector IN: address of 512 byte sector on Flash Cart to read -u8 numSecs IN: number of 512 byte sectors to read, - 1 to 256 sectors can be read, 0 = 256 -void* buffer IN: pointer to 512 byte buffer to read data from -bool return OUT: true if successful ------------------------------------------------------------------*/ -bool FCSR_WriteSectors (u32 sector, u8 numSecs, void* buffer) -{ - int i; - bool flagSramSector = false; - int writeLength = (numSecs > 0 ? numSecs : 256) * BYTE_PER_READ; - u8* src = (u8*) buffer; - u8* dst; - - // Find which region this sector belongs in - for (i = 0; (i < 4) && !flagSramSector; i++) - { - if ((sector >= FCSR_SramSectorStart[i]) && (sector < FCSR_SramSectorEnd[i])) - { - flagSramSector = true; - break; - } - } - - if (!flagSramSector) - return false; - - // Entire write must be within an SRAM region - if ((sector + (numSecs > 0 ? numSecs : 256)) > FCSR_SramSectorEnd[i]) - return false; - - // Copy data to SRAM - dst = FCSR_SramSectorPointer[i] + (sector - FCSR_SramSectorStart[i]) * BYTE_PER_READ; - while (writeLength--) - { - *dst++ = *src++; - } - - return true; -} - -/*----------------------------------------------------------------- -FCSR_Shutdown -unload the Flash Cart interface ------------------------------------------------------------------*/ -bool FCSR_Shutdown(void) -{ - int i; - if (FCSR_ClearStatus() == false) - return false; - - FCSR_FileSysPointer = 0; - - for (i=0; i < 4; i++) - { - FCSR_SramSectorPointer[i] = 0; - FCSR_SramSectorStart[i] = 0; - FCSR_SramSectorEnd[i] = 0; - } - return true; -} - -/*----------------------------------------------------------------- -FCSR_StartUp -initializes the Flash Cart interface, returns true if successful, -otherwise returns false ------------------------------------------------------------------*/ -bool FCSR_StartUp(void) -{ - bool flagFoundFileSys = false; - int i; - int SramRegionSize[4]; - u8* srcByte; - u8* destByte; - - u32* fileSysPointer = (u32*)0x08000100; // Start at beginning of cart address space, offset by expected location of string - - // Search for file system - while ((fileSysPointer < (u32*)0x0A000000) && !flagFoundFileSys) // Only search while not at end of cart address space - { - while ((*fileSysPointer != FCSR) && (fileSysPointer < (u32*)0x0A000000)) - fileSysPointer += 0x40; - if ((strncmp(FCSR_LabelString, (char*)(fileSysPointer + 1), 12) == 0) && (fileSysPointer < (u32*)0x0A000000)) - { - flagFoundFileSys = true; - } else { - fileSysPointer += 0x80; - } - } - - if (!flagFoundFileSys) - return false; - - // Flash cart file system pointer has been found - FCSR_FileSysPointer = (u8*)(fileSysPointer - 0x40); - - // Get SRAM sector regions from header block - for (i = 0; i < 4; i++) - { - FCSR_SramSectorStart[i] = fileSysPointer[i+4]; - SramRegionSize[i] = fileSysPointer[i+8]; - FCSR_SramSectorEnd[i] = FCSR_SramSectorStart[i] + SramRegionSize[i]; - } - - // Calculate SRAM region pointers - FCSR_SramSectorPointer[0] = (u8*)(SRAM_START + 4); - for (i = 1; i < 4; i++) - { - FCSR_SramSectorPointer[i] = FCSR_SramSectorPointer[i-1] + (SramRegionSize[i-1] * BYTE_PER_READ); - } - - // Initialise SRAM with overlay if it hasn't been done so - if ( (*((u8*)SRAM_START) != 'F') || (*((u8*)(SRAM_START+1)) != 'C') || (*((u8*)(SRAM_START+2)) != 'S') || (*((u8*)(SRAM_START+3)) != 'R') ) - { - *((u8*)SRAM_START) = 'F'; - *((u8*)(SRAM_START+1)) = 'C'; - *((u8*)(SRAM_START+2)) = 'S'; - *((u8*)(SRAM_START+3)) = 'R'; - - for (i = 0; i < 4; i++) - { - srcByte = FCSR_FileSysPointer + (FCSR_SramSectorStart[i] * BYTE_PER_READ); - destByte = FCSR_SramSectorPointer[i]; - while (srcByte < FCSR_FileSysPointer + (FCSR_SramSectorEnd[i] * BYTE_PER_READ) ) - *destByte++ = *srcByte++; - } - } - - // Get SRAM sector regions from header block - for (i = 0; i < 4; i++) - { - if (SramRegionSize[i] == 0) - { - FCSR_SramSectorStart[i] = NO_SRAM; - FCSR_SramSectorEnd[i] = NO_SRAM; - } - } - - return true; -} - -/*----------------------------------------------------------------- -the actual interface structure ------------------------------------------------------------------*/ -IO_INTERFACE io_fcsr = { - DEVICE_TYPE_FCSR, // 'FCSR' - FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_SLOT_GBA, - (FN_MEDIUM_STARTUP)&FCSR_StartUp, - (FN_MEDIUM_ISINSERTED)&FCSR_IsInserted, - (FN_MEDIUM_READSECTORS)&FCSR_ReadSectors, - (FN_MEDIUM_WRITESECTORS)&FCSR_WriteSectors, - (FN_MEDIUM_CLEARSTATUS)&FCSR_ClearStatus, - (FN_MEDIUM_SHUTDOWN)&FCSR_Shutdown -} ; - -/*----------------------------------------------------------------- -FCSR_GetInterface -returns the interface structure to host ------------------------------------------------------------------*/ -LPIO_INTERFACE FCSR_GetInterface(void) { - return &io_fcsr ; -} ; - -#endif // SUPPORT_FCSR diff --git a/backends/platform/ds/arm9/source/fat/io_m3cf.c b/backends/platform/ds/arm9/source/fat/io_m3cf.c index 238be7e311..910f01097e 100644 --- a/backends/platform/ds/arm9/source/fat/io_m3cf.c +++ b/backends/platform/ds/arm9/source/fat/io_m3cf.c @@ -360,373 +360,6 @@ IO_INTERFACE io_m3cf = { } ; -LPIO_INTERFACE M3CF_GetInterface(void) { - return &io_m3cf ; -} ; - -#endif // SUPPORT_M3CF -/* - io_m3cf.c based on - - compact_flash.c - By chishm (Michael Chisholm) - - Hardware Routines for reading a compact flash card - using the M3 Perfect CF Adapter - - CF routines modified with help from Darkfader - - This software is completely free. No warranty is provided. - If you use it, please give me credit and email me about your - project at chishm@hotmail.com - - See gba_nds_fat.txt for help and license details. -*/ - - -#include "io_m3cf.h" - -#ifdef SUPPORT_M3CF - -//--------------------------------------------------------------- -// DMA -#ifdef _CF_USE_DMA - #ifndef NDS - #include "gba_dma.h" - #else - #include - #ifdef ARM9 - #include - #endif - #endif -#endif - -//--------------------------------------------------------------- -// CF Addresses & Commands - -#define GAME_PAK 0x08000000 // Game pack start address - -// GBAMP CF Addresses -#define M3_REG_STS *(vu16*)(GAME_PAK + 0x000C0000) // Status of the CF Card / Device control -#define M3_REG_CMD *(vu16*)(GAME_PAK + 0x008E0000) // Commands sent to control chip and status return -#define M3_REG_ERR *(vu16*)(GAME_PAK + 0x00820000) // Errors / Features - -#define M3_REG_SEC *(vu16*)(GAME_PAK + 0x00840000) // Number of sector to transfer -#define M3_REG_LBA1 *(vu16*)(GAME_PAK + 0x00860000) // 1st byte of sector address -#define M3_REG_LBA2 *(vu16*)(GAME_PAK + 0x00880000) // 2nd byte of sector address -#define M3_REG_LBA3 *(vu16*)(GAME_PAK + 0x008A0000) // 3rd byte of sector address -#define M3_REG_LBA4 *(vu16*)(GAME_PAK + 0x008C0000) // last nibble of sector address | 0xE0 - -#define M3_DATA (vu16*)(GAME_PAK + 0x00800000) // Pointer to buffer of CF data transered from card - -// CF Card status -#define CF_STS_INSERTED 0x50 -#define CF_STS_REMOVED 0x00 -#define CF_STS_READY 0x58 - -#define CF_STS_DRQ 0x08 -#define CF_STS_BUSY 0x80 - -// CF Card commands -#define CF_CMD_LBA 0xE0 -#define CF_CMD_READ 0x20 -#define CF_CMD_WRITE 0x30 - -#define CARD_TIMEOUT 10000000 // Updated due to suggestion from SaTa, otherwise card will timeout sometimes on a write - - -/*----------------------------------------------------------------- -M3CF_IsInserted -Is a compact flash card inserted? -bool return OUT: true if a CF card is inserted ------------------------------------------------------------------*/ -bool M3CF_IsInserted (void) -{ - // Change register, then check if value did change - M3_REG_STS = CF_STS_INSERTED; - return ((M3_REG_STS & 0xff) == CF_STS_INSERTED); -} - - -/*----------------------------------------------------------------- -M3CF_ClearStatus -Tries to make the CF card go back to idle mode -bool return OUT: true if a CF card is idle ------------------------------------------------------------------*/ -bool M3CF_ClearStatus (void) -{ - int i; - - // Wait until CF card is finished previous commands - i=0; - while ((M3_REG_CMD & CF_STS_BUSY) && (i < CARD_TIMEOUT)) - { - i++; - } - - // Wait until card is ready for commands - i = 0; - while ((!(M3_REG_STS & CF_STS_INSERTED)) && (i < CARD_TIMEOUT)) - { - i++; - } - if (i >= CARD_TIMEOUT) - return false; - - return true; -} - - -/*----------------------------------------------------------------- -M3CF_ReadSectors -Read 512 byte sector numbered "sector" into "buffer" -u32 sector IN: address of first 512 byte sector on CF card to read -u8 numSecs IN: number of 512 byte sectors to read, - 1 to 256 sectors can be read, 0 = 256 -void* buffer OUT: pointer to 512 byte buffer to store data in -bool return OUT: true if successful ------------------------------------------------------------------*/ -bool M3CF_ReadSectors (u32 sector, u8 numSecs, void* buffer) -{ - int i; - int j = (numSecs > 0 ? numSecs : 256); - u16 *buff = (u16*)buffer; -#ifdef _CF_ALLOW_UNALIGNED - u8 *buff_u8 = (u8*)buffer; - int temp; -#endif - -#if defined _CF_USE_DMA && defined NDS && defined ARM9 - DC_FlushRange( buffer, j * BYTE_PER_READ); -#endif - - // Wait until CF card is finished previous commands - i=0; - while ((M3_REG_CMD & CF_STS_BUSY) && (i < CARD_TIMEOUT)) - { - i++; - } - - // Wait until card is ready for commands - i = 0; - while ((!(M3_REG_STS & CF_STS_INSERTED)) && (i < CARD_TIMEOUT)) - { - i++; - } - if (i >= CARD_TIMEOUT) - return false; - - // Set number of sectors to read - M3_REG_SEC = numSecs; - - // Set read sector - M3_REG_LBA1 = sector & 0xFF; // 1st byte of sector number - M3_REG_LBA2 = (sector >> 8) & 0xFF; // 2nd byte of sector number - M3_REG_LBA3 = (sector >> 16) & 0xFF; // 3rd byte of sector number - M3_REG_LBA4 = ((sector >> 24) & 0x0F )| CF_CMD_LBA; // last nibble of sector number - - // Set command to read - M3_REG_CMD = CF_CMD_READ; - - - while (j--) - { - // Wait until card is ready for reading - i = 0; - while (((M3_REG_STS & 0xff) != CF_STS_READY) && (i < CARD_TIMEOUT)) - { - i++; - } - if (i >= CARD_TIMEOUT) - return false; - - // Read data -#ifdef _CF_USE_DMA - #ifdef NDS - DMA3_SRC = (u32)M3_DATA; - DMA3_DEST = (u32)buff; - DMA3_CR = 256 | DMA_COPY_HALFWORDS | DMA_SRC_FIX; - #else - DMA3COPY ( M3_DATA, buff, 256 | DMA16 | DMA_ENABLE | DMA_SRC_FIXED); - #endif - buff += BYTE_PER_READ / 2; -#elif defined _CF_ALLOW_UNALIGNED - i=256; - if ((u32)buff_u8 & 0x01) { - while(i--) - { - temp = *M3_DATA; - *buff_u8++ = temp & 0xFF; - *buff_u8++ = temp >> 8; - } - } else { - while(i--) - *buff++ = *M3_DATA; - } -#else - i=256; - while(i--) - *buff++ = *M3_DATA; -#endif - } -#if defined _CF_USE_DMA && defined NDS - // Wait for end of transfer before returning - while(DMA3_CR & DMA_BUSY); -#endif - - return true; -} - - - -/*----------------------------------------------------------------- -M3CF_WriteSectors -Write 512 byte sector numbered "sector" from "buffer" -u32 sector IN: address of 512 byte sector on CF card to read -u8 numSecs IN: number of 512 byte sectors to read, - 1 to 256 sectors can be read, 0 = 256 -void* buffer IN: pointer to 512 byte buffer to read data from -bool return OUT: true if successful ------------------------------------------------------------------*/ -bool M3CF_WriteSectors (u32 sector, u8 numSecs, void* buffer) -{ - int i; - int j = (numSecs > 0 ? numSecs : 256); - u16 *buff = (u16*)buffer; -#ifdef _CF_ALLOW_UNALIGNED - u8 *buff_u8 = (u8*)buffer; - int temp; -#endif - -#if defined _CF_USE_DMA && defined NDS && defined ARM9 - DC_FlushRange( buffer, j * BYTE_PER_READ); -#endif - - // Wait until CF card is finished previous commands - i=0; - while ((M3_REG_CMD & CF_STS_BUSY) && (i < CARD_TIMEOUT)) - { - i++; - } - - // Wait until card is ready for commands - i = 0; - while ((!(M3_REG_STS & CF_STS_INSERTED)) && (i < CARD_TIMEOUT)) - { - i++; - } - if (i >= CARD_TIMEOUT) - return false; - - // Set number of sectors to write - M3_REG_SEC = numSecs; - - // Set write sector - M3_REG_LBA1 = sector & 0xFF; // 1st byte of sector number - M3_REG_LBA2 = (sector >> 8) & 0xFF; // 2nd byte of sector number - M3_REG_LBA3 = (sector >> 16) & 0xFF; // 3rd byte of sector number - M3_REG_LBA4 = ((sector >> 24) & 0x0F )| CF_CMD_LBA; // last nibble of sector number - - // Set command to write - M3_REG_CMD = CF_CMD_WRITE; - - while (j--) - { - // Wait until card is ready for writing - i = 0; - while (((M3_REG_STS & 0xff) != CF_STS_READY) && (i < CARD_TIMEOUT)) - { - i++; - } - if (i >= CARD_TIMEOUT) - return false; - - // Write data -#ifdef _CF_USE_DMA - #ifdef NDS - DMA3_SRC = (u32)buff; - DMA3_DEST = (u32)M3_DATA; - DMA3_CR = 256 | DMA_COPY_HALFWORDS | DMA_DST_FIX; - #else - DMA3COPY( buff, M3_DATA, 256 | DMA16 | DMA_ENABLE | DMA_DST_FIXED); - #endif - buff += BYTE_PER_READ / 2; -#elif defined _CF_ALLOW_UNALIGNED - i=256; - if ((u32)buff_u8 & 0x01) { - while(i--) - { - temp = *buff_u8++; - temp |= *buff_u8++ << 8; - *M3_DATA = temp; - } - } else { - while(i--) - *M3_DATA = *buff++; - } -#else - i=256; - while(i--) - *M3_DATA = *buff++; -#endif - } -#if defined _CF_USE_DMA && defined NDS - // Wait for end of transfer before returning - while(DMA3_CR & DMA_BUSY); -#endif - - return true; -} - - -/*----------------------------------------------------------------- -M3_Unlock -Returns true if M3 was unlocked, false if failed -Added by MightyMax ------------------------------------------------------------------*/ -bool M3_Unlock(void) -{ - // run unlock sequence - volatile unsigned short tmp ; - tmp = *(volatile unsigned short *)0x08000000 ; - tmp = *(volatile unsigned short *)0x08E00002 ; - tmp = *(volatile unsigned short *)0x0800000E ; - tmp = *(volatile unsigned short *)0x08801FFC ; - tmp = *(volatile unsigned short *)0x0800104A ; - tmp = *(volatile unsigned short *)0x08800612 ; - tmp = *(volatile unsigned short *)0x08000000 ; - tmp = *(volatile unsigned short *)0x08801B66 ; - tmp = *(volatile unsigned short *)0x08800006 ; - tmp = *(volatile unsigned short *)0x08000000 ; - // test that we have register access - tmp = M3_REG_LBA1; - M3_REG_LBA1 = (~tmp & 0xFF); - tmp = (~tmp & 0xFF); - // did it change? - return (M3_REG_LBA1 == tmp) ; -} - -bool M3CF_Shutdown(void) { - return M3CF_ClearStatus() ; -} ; - -bool M3CF_StartUp(void) { - return M3_Unlock() ; -} ; - - -IO_INTERFACE io_m3cf = { - DEVICE_TYPE_M3CF, - FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_SLOT_GBA, - (FN_MEDIUM_STARTUP)&M3CF_StartUp, - (FN_MEDIUM_ISINSERTED)&M3CF_IsInserted, - (FN_MEDIUM_READSECTORS)&M3CF_ReadSectors, - (FN_MEDIUM_WRITESECTORS)&M3CF_WriteSectors, - (FN_MEDIUM_CLEARSTATUS)&M3CF_ClearStatus, - (FN_MEDIUM_SHUTDOWN)&M3CF_Shutdown -} ; - - LPIO_INTERFACE M3CF_GetInterface(void) { return &io_m3cf ; } ; diff --git a/backends/platform/ds/arm9/source/fat/io_m3sd.c b/backends/platform/ds/arm9/source/fat/io_m3sd.c index 897f65bd6e..823f94a280 100644 --- a/backends/platform/ds/arm9/source/fat/io_m3sd.c +++ b/backends/platform/ds/arm9/source/fat/io_m3sd.c @@ -288,381 +288,6 @@ bool M3SD_ReadSectors (u32 sector, u8 numSecs, void* buffer) -/*----------------------------------------------------------------- -M3SD_WriteSectors -Write 512 byte sector numbered "sector" from "buffer" -u32 sector IN: address of 512 byte sector on CF card to read -u8 numSecs IN: number of 512 byte sectors to read, - 1 to 256 sectors can be read, 0 = 256 -void* buffer IN: pointer to 512 byte buffer to read data from -bool return OUT: true if successful ------------------------------------------------------------------*/ -bool M3SD_WriteSectors (u32 sector, u8 numSecs, void* buffer) -{ - - bool r=true; - int i; - for(i=0;i>7);// セクタH 9ビット=アドレスH 16ビット - SDIDA3=(sectorn<<9);// セクタL 7ビット=アドレスL 16ビット - SDDIR=0x29; // コマンド送信? - i=0; - - while ( ((SDSTA&0x01) != 0x01)&&(i < CARD_TIMEOUT) ) - { - i++; - } - SDDIR=0x09; - i=0; - SDDIR=0x49; - while ( ((SDSTA&0x40) != 0x40)&&(i < CARD_TIMEOUT) ) - { - i++; - } - SDDIR=0x09; - - SDDIR=0x8;//cmd input clken=0 datadir input clock=0 - SDCON=0x4;//send=0 get=0 en25=1 cmd1=0 - - w = SDDIR; - for(w=0;w<0x100;w++) - { - u16 d16; - u8 *d8=(u8 *)&d16; -// *(u16*)(TAddr+w*2) = SDDIR; // 16bit - d16 = SDDIR; // 16bit - *(u8 *)(TAddr+w*2) =d8[0]; - *(u8 *)(TAddr+w*2+1) =d8[1]; - - } - w = SDDIR; - w = SDDIR; - - if (i >= CARD_TIMEOUT) - return false; - - return true; - -} -//================================================== - - -//====================================================== -void SD_crc16(u16* buff,u16 num,u16* crc16buff); -void SD_data_write(u16 *buff,u16* crc16buff); - -u16 Hal4ATA_StatusByte; - -void Hal4ATA_GetStatus(void) -{ - Hal4ATA_StatusByte = SDSTA; -} - -bool Hal4ATA_WaitOnBusy(void) -{ - Hal4ATA_GetStatus(); - while ( (Hal4ATA_StatusByte & 0x01) != 0x1) - { - Hal4ATA_GetStatus(); - } - return TRUE; -} - -bool Hal4ATA_WaitOnBusyNDrdy(void) -{ - Hal4ATA_GetStatus(); - while ( (Hal4ATA_StatusByte&0x40) !=0x40) - { - Hal4ATA_GetStatus(); - } - return TRUE; -} - - -void SendCommand(u16 command, u32 sectorn) -{ - SDCON=0x8; - SDIDA1=0x40+command; - SDIDA2=(sectorn>>7); - SDIDA3=(sectorn<<9); - - SDDIR=0x29; - Hal4ATA_WaitOnBusy(); - SDDIR=0x09; -} - - -#define DMA3SAD *(u32*)0x040000D4 -#define DMA3DAD *(u32*)0x040000D8 -#define DMA3CNT *(u32*)0x040000DC - -void DMA3(u32 src, u32 dst, u32 cnt) -{ - DMA3SAD=src; - DMA3DAD=dst; - DMA3CNT=cnt; -} - - - -void PassRespond(u32 num) -{ - u32 i,dmanum; - - dmanum=(64+(num<<3))>>2; - SDDIR=0x8; - SDCON=0x4; - DMA3(0x8800000,(u32)&i,0x80400000+dmanum); -} - -//bool M3SD_write1sector(u32 sectorn,u16 * p) -bool M3SD_write1sector(u32 sectorn,u32 p) -{ - u16 crc[4]; - - SendCommand(24,sectorn); - PassRespond(6); - - SDDIR=0x4; - SDCON=0x0; - - SD_crc16((u16 *)p,512,crc); - SD_data_write((u16 *)p,crc); - return true; -} -//================================================== - - -// GBAMP CF Addresses - -#define M3_REG_STS *(vu16*)(0x09800000) // Status of the CF Card / Device control - -#define M3_DATA (vu16*)(0x08800000) // Pointer to buffer of CF data transered from card - -// CF Card status -#define CF_STS_INSERTED1 0x20 -#define CF_STS_INSERTED2 0x30 - -/*----------------------------------------------------------------- -M3SD_IsInserted -Is a compact flash card inserted? -bool return OUT: true if a CF card is inserted ------------------------------------------------------------------*/ -bool M3SD_IsInserted (void) -{ - int i; - u16 sta; - // Change register, then check if value did change - M3_REG_STS = CF_STS_INSERTED1; - - for(i=0;i= CARD_TIMEOUT) - return false; - - return true; -} - - -/*----------------------------------------------------------------- -M3SD_ReadSectors -Read 512 byte sector numbered "sector" into "buffer" -u32 sector IN: address of first 512 byte sector on CF card to read -u8 numSecs IN: number of 512 byte sectors to read, - 1 to 256 sectors can be read, 0 = 256 -void* buffer OUT: pointer to 512 byte buffer to store data in -bool return OUT: true if successful ------------------------------------------------------------------*/ -bool M3SD_ReadSectors (u32 sector, u8 numSecs, void* buffer) -{ - - - //void M3SD_read1sector(u32 sectorn,u32 TAddr) - bool r=true; - int i; - for(i=0;i - #ifdef ARM9 - #include - #endif - #endif -#endif - -//--------------------------------------------------------------- -// CF Addresses & Commands - -#define GAME_PAK 0x08000000 // Game pack start address - -// GBAMP CF Addresses -#define MP_REG_STS *(vu16*)(GAME_PAK + 0x018C0000) // Status of the CF Card / Device control -#define MP_REG_CMD *(vu16*)(GAME_PAK + 0x010E0000) // Commands sent to control chip and status return -#define MP_REG_ERR *(vu16*)(GAME_PAK + 0x01020000) // Errors / Features - -#define MP_REG_SEC *(vu16*)(GAME_PAK + 0x01040000) // Number of sector to transfer -#define MP_REG_LBA1 *(vu16*)(GAME_PAK + 0x01060000) // 1st byte of sector address -#define MP_REG_LBA2 *(vu16*)(GAME_PAK + 0x01080000) // 2nd byte of sector address -#define MP_REG_LBA3 *(vu16*)(GAME_PAK + 0x010A0000) // 3rd byte of sector address -#define MP_REG_LBA4 *(vu16*)(GAME_PAK + 0x010C0000) // last nibble of sector address | 0xE0 - -#define MP_DATA (vu16*)(GAME_PAK + 0x01000000) // Pointer to buffer of CF data transered from card - -// CF Card status -#define CF_STS_INSERTED 0x50 -#define CF_STS_REMOVED 0x00 -#define CF_STS_READY 0x58 - -#define CF_STS_DRQ 0x08 -#define CF_STS_BUSY 0x80 - -// CF Card commands -#define CF_CMD_LBA 0xE0 -#define CF_CMD_READ 0x20 -#define CF_CMD_WRITE 0x30 - -#define CARD_TIMEOUT 10000000 // Updated due to suggestion from SaTa, otherwise card will timeout sometimes on a write - - -/*----------------------------------------------------------------- -MPCF_IsInserted -Is a compact flash card inserted? -bool return OUT: true if a CF card is inserted ------------------------------------------------------------------*/ -bool MPCF_IsInserted (void) -{ - // Change register, then check if value did change - MP_REG_STS = CF_STS_INSERTED; - return ((MP_REG_STS & 0xff) == CF_STS_INSERTED); -} - - -/*----------------------------------------------------------------- -MPCF_ClearStatus -Tries to make the CF card go back to idle mode -bool return OUT: true if a CF card is idle ------------------------------------------------------------------*/ -bool MPCF_ClearStatus (void) -{ - int i; - - // Wait until CF card is finished previous commands - i=0; - while ((MP_REG_CMD & CF_STS_BUSY) && (i < CARD_TIMEOUT)) - { - i++; - } - - // Wait until card is ready for commands - i = 0; - while ((!(MP_REG_STS & CF_STS_INSERTED)) && (i < CARD_TIMEOUT)) - { - i++; - } - if (i >= CARD_TIMEOUT) - return false; - - return true; -} - - -/*----------------------------------------------------------------- -MPCF_ReadSectors -Read 512 byte sector numbered "sector" into "buffer" -u32 sector IN: address of first 512 byte sector on CF card to read -u8 numSecs IN: number of 512 byte sectors to read, - 1 to 256 sectors can be read, 0 = 256 -void* buffer OUT: pointer to 512 byte buffer to store data in -bool return OUT: true if successful ------------------------------------------------------------------*/ -bool MPCF_ReadSectors (u32 sector, u8 numSecs, void* buffer) -{ - int i; - int j = (numSecs > 0 ? numSecs : 256); - u16 *buff = (u16*)buffer; -#ifdef _CF_ALLOW_UNALIGNED - u8 *buff_u8 = (u8*)buffer; - int temp; -#endif - -#if (defined _CF_USE_DMA) && (defined NDS) && (defined ARM9) - DC_FlushRange( buffer, j * BYTE_PER_READ); -#endif - - // Wait until CF card is finished previous commands - i=0; - while ((MP_REG_CMD & CF_STS_BUSY) && (i < CARD_TIMEOUT)) - { - i++; - } - - // Wait until card is ready for commands - i = 0; - while ((!(MP_REG_STS & CF_STS_INSERTED)) && (i < CARD_TIMEOUT)) - { - i++; - } - if (i >= CARD_TIMEOUT) - return false; - - // Set number of sectors to read - MP_REG_SEC = numSecs; - - // Set read sector - MP_REG_LBA1 = sector & 0xFF; // 1st byte of sector number - MP_REG_LBA2 = (sector >> 8) & 0xFF; // 2nd byte of sector number - MP_REG_LBA3 = (sector >> 16) & 0xFF; // 3rd byte of sector number - MP_REG_LBA4 = ((sector >> 24) & 0x0F )| CF_CMD_LBA; // last nibble of sector number - - // Set command to read - MP_REG_CMD = CF_CMD_READ; - - - while (j--) - { - // Wait until card is ready for reading - i = 0; - while (((MP_REG_STS & 0xff)!= CF_STS_READY) && (i < CARD_TIMEOUT)) - { - i++; - } - if (i >= CARD_TIMEOUT) - return false; - - // Read data -#ifdef _CF_USE_DMA - #ifdef NDS - DMA3_SRC = (u32)MP_DATA; - DMA3_DEST = (u32)buff; - DMA3_CR = 256 | DMA_COPY_HALFWORDS | DMA_SRC_FIX; - #else - DMA3COPY ( MP_DATA, buff, 256 | DMA16 | DMA_ENABLE | DMA_SRC_FIXED); - #endif - buff += BYTE_PER_READ / 2; -#elif defined _CF_ALLOW_UNALIGNED - i=256; - if ((u32)buff_u8 & 0x01) { - while(i--) - { - temp = *MP_DATA; - *buff_u8++ = temp & 0xFF; - *buff_u8++ = temp >> 8; - } - } else { - while(i--) - *buff++ = *MP_DATA; - } -#else - i=256; - while(i--) - *buff++ = *MP_DATA; -#endif - } -#if (defined _CF_USE_DMA) && (defined NDS) - // Wait for end of transfer before returning - while(DMA3_CR & DMA_BUSY); -#endif - return true; -} - - - -/*----------------------------------------------------------------- -MPCF_WriteSectors -Write 512 byte sector numbered "sector" from "buffer" -u32 sector IN: address of 512 byte sector on CF card to read -u8 numSecs IN: number of 512 byte sectors to read, - 1 to 256 sectors can be read, 0 = 256 -void* buffer IN: pointer to 512 byte buffer to read data from -bool return OUT: true if successful ------------------------------------------------------------------*/ -bool MPCF_WriteSectors (u32 sector, u8 numSecs, void* buffer) -{ - int i; - int j = (numSecs > 0 ? numSecs : 256); - u16 *buff = (u16*)buffer; -#ifdef _CF_ALLOW_UNALIGNED - u8 *buff_u8 = (u8*)buffer; - int temp; -#endif - -#if defined _CF_USE_DMA && defined NDS && defined ARM9 - DC_FlushRange( buffer, j * BYTE_PER_READ); -#endif - - // Wait until CF card is finished previous commands - i=0; - while ((MP_REG_CMD & CF_STS_BUSY) && (i < CARD_TIMEOUT)) - { - i++; - } - - // Wait until card is ready for commands - i = 0; - while ((!(MP_REG_STS & CF_STS_INSERTED)) && (i < CARD_TIMEOUT)) - { - i++; - } - if (i >= CARD_TIMEOUT) - return false; - - // Set number of sectors to write - MP_REG_SEC = numSecs; - - // Set write sector - MP_REG_LBA1 = sector & 0xFF; // 1st byte of sector number - MP_REG_LBA2 = (sector >> 8) & 0xFF; // 2nd byte of sector number - MP_REG_LBA3 = (sector >> 16) & 0xFF; // 3rd byte of sector number - MP_REG_LBA4 = ((sector >> 24) & 0x0F )| CF_CMD_LBA; // last nibble of sector number - - // Set command to write - MP_REG_CMD = CF_CMD_WRITE; - - while (j--) - { - // Wait until card is ready for writing - i = 0; - while (((MP_REG_STS & 0xff) != CF_STS_READY) && (i < CARD_TIMEOUT)) - { - i++; - } - if (i >= CARD_TIMEOUT) - return false; - - // Write data -#ifdef _CF_USE_DMA - #ifdef NDS - DMA3_SRC = (u32)buff; - DMA3_DEST = (u32)MP_DATA; - DMA3_CR = 256 | DMA_COPY_HALFWORDS | DMA_DST_FIX; - #else - DMA3COPY( buff, MP_DATA, 256 | DMA16 | DMA_ENABLE | DMA_DST_FIXED); - #endif - buff += BYTE_PER_READ / 2; -#elif defined _CF_ALLOW_UNALIGNED - i=256; - if ((u32)buff_u8 & 0x01) { - while(i--) - { - temp = *buff_u8++; - temp |= *buff_u8++ << 8; - *MP_DATA = temp; - } - } else { - while(i--) - *MP_DATA = *buff++; - } -#else - i=256; - while(i--) - *MP_DATA = *buff++; -#endif - } -#if defined _CF_USE_DMA && defined NDS - // Wait for end of transfer before returning - while(DMA3_CR & DMA_BUSY); -#endif - - return true; -} - -/*----------------------------------------------------------------- -MPCF_Shutdown -unload the GBAMP CF interface ------------------------------------------------------------------*/ -bool MPCF_Shutdown(void) -{ - return MPCF_ClearStatus() ; -} - -/*----------------------------------------------------------------- -MPCF_StartUp -initializes the CF interface, returns true if successful, -otherwise returns false ------------------------------------------------------------------*/ -bool MPCF_StartUp(void) -{ - u8 temp = MP_REG_LBA1; - MP_REG_LBA1 = (~temp & 0xFF); - temp = (~temp & 0xFF); - return (MP_REG_LBA1 == temp) ; -} - -/*----------------------------------------------------------------- -the actual interface structure ------------------------------------------------------------------*/ -IO_INTERFACE io_mpcf = { - DEVICE_TYPE_MPCF, - FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_SLOT_GBA, - (FN_MEDIUM_STARTUP)&MPCF_StartUp, - (FN_MEDIUM_ISINSERTED)&MPCF_IsInserted, - (FN_MEDIUM_READSECTORS)&MPCF_ReadSectors, - (FN_MEDIUM_WRITESECTORS)&MPCF_WriteSectors, - (FN_MEDIUM_CLEARSTATUS)&MPCF_ClearStatus, - (FN_MEDIUM_SHUTDOWN)&MPCF_Shutdown -} ; - -/*----------------------------------------------------------------- -MPCF_GetInterface -returns the interface structure to host ------------------------------------------------------------------*/ -LPIO_INTERFACE MPCF_GetInterface(void) { - return &io_mpcf ; -} ; - -#endif // SUPPORT_MPCF diff --git a/backends/platform/ds/arm9/source/fat/io_nmmc.c b/backends/platform/ds/arm9/source/fat/io_nmmc.c index 2e6b99de24..a29c26e43a 100644 --- a/backends/platform/ds/arm9/source/fat/io_nmmc.c +++ b/backends/platform/ds/arm9/source/fat/io_nmmc.c @@ -351,364 +351,6 @@ IO_INTERFACE io_nmmc = { } ; -LPIO_INTERFACE NMMC_GetInterface(void) { - return &io_nmmc ; -} - -#endif // #ifdef SUPPORT_NMMC -/* - io_nmmc.c - - Hardware Routines for reading an SD or MMC card using - a Neoflash MK2 or MK3. - - Written by www.neoflash.com - - Submit bug reports for this device to the NeoFlash forums - - This software is completely free. No warranty is provided. - If you use it, please give me credit and email me about your - project at chishm@hotmail.com - - See gba_nds_fat.txt for help and license details. - - 2006-02-09 - www.neoflash.com: - * First stable release - - 2006-02-13 - Chishm - * Added ReadMK2Config function - * Added read config test to init function so no unnecessary card commands are sent - * Changed data read and write functions to use multiple block commands -*/ - -#include "io_nmmc.h" - -#ifdef SUPPORT_NMMC - -#include - -int spi_freq = 3; - -#define MK2_CONFIG_ZIP_RAM_CLOSE (1 << 5) -#define MK2_CONFIG_GAME_FLASH_CLOSE ((1 << 4) | (1 << 0)) -//#define MK2_CONFIG_ZIP_RAM_CLOSE ((1 << 5) | (1 << 1)) -//#define MK2_CONFIG_GAME_FLASH_CLOSE (1 << 4) - -#define MMC_READ_MULTIPLE_BLOCK 18 -#define MMC_READ_BLOCK 17 -#define MMC_WRITE_MULTIPLE_BLOCK 25 -#define MMC_WRITE_BLOCK 24 -#define MMC_STOP_TRANSMISSION 12 -#define MMC_SET_BLOCKLEN 16 -#define MMC_SET_BLOCK_COUNT 23 -#define MMC_SEND_CSD 9 - -// SPI functions - -static inline void Neo_OpenSPI( u8 frequency ) -{ - CARD_CR1 = 0x0000A040 | frequency; -} - -static inline u8 Neo_SPI( u8 dataByte ) -{ - CARD_EEPDATA = dataByte; - while (CARD_CR1 & 0x80); // card busy - return CARD_EEPDATA; -} - -static inline void Neo_CloseSPI ( void ) -{ - CARD_CR1 = 0; -} - -static inline void Neo_MK2GameMode() { - Neo_OpenSPI(spi_freq); // Enable DS Card's SPI port - Neo_SPI(0xF1); // Switch to game mode - Neo_CloseSPI(); // Disable DS Card's SPI port -} - -static inline void Neo_EnableEEPROM( bool enable ) { - Neo_OpenSPI(spi_freq); - if(enable) Neo_SPI(0x06); - else Neo_SPI(0x0E); - Neo_CloseSPI(); -} - -void Neo_WriteMK2Config(u8 config) { - Neo_EnableEEPROM(true); - Neo_OpenSPI(spi_freq); - Neo_SPI(0xFA); // Send mem conf write command - Neo_SPI(0x01); // Send high byte (0x01) - Neo_SPI(config); // Send low byte - Neo_CloseSPI(); - Neo_EnableEEPROM(false); -} - -u8 Neo_ReadMK2Config(void) -{ - u8 config; - Neo_EnableEEPROM(true); - Neo_OpenSPI(spi_freq); - Neo_SPI(0xf8); // Send mem conf read command - Neo_SPI(0x01); // Send high byte - config = Neo_SPI(0x00); // Get low byte - Neo_CloseSPI(); - Neo_EnableEEPROM(false); - return config; -} - -// Low level functions - -u8 selectMMC_command [8] = {0xFF, 0x00, 0x6A, 0xDF, 0x37, 0x59, 0x33, 0xA3}; - -void Neo_SelectMMC (u8 dataByte) -{ - selectMMC_command[1] = dataByte; // Set enable / disable byte - cardWriteCommand (selectMMC_command); // Send "5. Use the EEPROM CS to access the MK2 MMC/SD card" - CARD_CR2 = CARD_ACTIVATE | CARD_nRESET; - while (CARD_CR2 & CARD_BUSY); - return; -} - -void Neo_EnableMMC( bool enable ) -{ - if ( enable == false) { - Neo_CloseSPI (); - Neo_SelectMMC (0); - Neo_SelectMMC (0); - } else { - Neo_SelectMMC (1); - Neo_SelectMMC (1); - Neo_OpenSPI (spi_freq); - } - return; -} - -void Neo_SendMMCCommand( u8 command, u32 argument ) -{ - Neo_SPI (0xFF); - Neo_SPI (command | 0x40); - Neo_SPI ((argument >> 24) & 0xff); - Neo_SPI ((argument >> 16) & 0xff); - Neo_SPI ((argument >> 8) & 0xff) ; - Neo_SPI (argument & 0xff); - Neo_SPI (0x95); - Neo_SPI (0xFF); - return; -} - -bool Neo_CheckMMCResponse( u8 response, u8 mask ) { - u32 i; - for(i=0;i<256;i++) { - if( ( Neo_SPI( 0xFF ) & mask ) == response ) - return true; - } - return false; -} - -// Neo MMC functions - -bool Neo_InitMMC() { - Neo_MK2GameMode(); - Neo_WriteMK2Config( MK2_CONFIG_ZIP_RAM_CLOSE | MK2_CONFIG_GAME_FLASH_CLOSE); - - // Make sure the configuration was accepted - if (Neo_ReadMK2Config() != (MK2_CONFIG_ZIP_RAM_CLOSE | MK2_CONFIG_GAME_FLASH_CLOSE)) { - return false; // If not, then it wasn't initialised properly - } - - return true; -} - -// Neo MMC driver functions - -bool NMMC_IsInserted(void) { - int i; - - Neo_EnableMMC( true ); // Open SPI port to MMC card - Neo_SendMMCCommand(MMC_SEND_CSD, 0); - if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occured - Neo_EnableMMC( false ); - return false; - } - if( Neo_CheckMMCResponse( 0xFE, 0xFF ) == false ) { // Check for Start Block token - Neo_EnableMMC( false ); - return false; - } - - // consume data from card, and send clocks. - for (i = 0; i < 28; i++) { - Neo_SPI(0xff); - } - - return true; -} - -bool NMMC_ClearStatus (void) { - u32 i; - - Neo_EnableMMC( true ); // Open SPI port to MMC card - for (i = 0; i < 10; i++) { - Neo_SPI(0xFF); // Send 10 0xFF bytes to MMC card - } - Neo_SendMMCCommand(0, 0); // Send GO_IDLE_STATE command - if( Neo_CheckMMCResponse( 0x01, 0xFF ) == false ) { // Check that it replied with 0x01 (not idle, no other error) - Neo_EnableMMC( false ); - return false; - } - for(i=0;i<256;i++) { - Neo_SendMMCCommand(1, 0); // Poll with SEND_OP_COND - if( Neo_CheckMMCResponse( 0x00, 0x01 ) == true ) { // Check for idle state - Neo_EnableMMC( false ); // Close SPI port to MMC card - return true; // Card is now idle - } - } - Neo_EnableMMC( false ); - return false; -} - -bool NMMC_Shutdown(void) { - return NMMC_ClearStatus(); -} - -bool NMMC_StartUp(void) { - int i; - int transSpeed; - if (Neo_InitMMC() == false) { - return false; - } - if (NMMC_ClearStatus() == false) { - return false; - } - Neo_EnableMMC( true ); // Open SPI port to MMC card - - // Set block length - Neo_SendMMCCommand(MMC_SET_BLOCKLEN, BYTE_PER_READ ); - if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occured - Neo_EnableMMC( false ); - return false; - } - - // Check if we can use a higher SPI frequency - Neo_SendMMCCommand(MMC_SEND_CSD, 0); - if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occured - Neo_EnableMMC( false ); - return false; - } - if( Neo_CheckMMCResponse( 0xFE, 0xFF ) == false ) { // Check for Start Block token - Neo_EnableMMC( false ); - return false; - } - for (i = 0; i < 3; i++) { - Neo_SPI(0xFF); - } - transSpeed = Neo_SPI (0xFF); - for (i = 0; i < 24; i++) { - Neo_SPI(0xFF); - } - if ((transSpeed & 0xf0) >= 0x30) { - spi_freq = 0; - } - - Neo_EnableMMC( false ); - return true; -} - - -bool NMMC_WriteSectors (u32 sector, u8 numSecs, void* buffer) -{ - u32 i; - u8 *p=buffer; - - int totalSecs = (numSecs == 0) ? 256 : numSecs; - sector *= BYTE_PER_READ; - - Neo_EnableMMC( true ); // Open SPI port to MMC card - Neo_SendMMCCommand( 25, sector ); - if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occured - Neo_EnableMMC( false ); - return false; - } - - while (totalSecs--) { - Neo_SPI( 0xFC ); // Send Start Block token - for( i = 0; i < BYTE_PER_READ; i++ ) // Send a block of data - Neo_SPI( *p++ ); - Neo_SPI( 0xFF ); // Send fake CRC16 - Neo_SPI( 0xFF ); // Send fake CRC16 - - if( ( Neo_SPI( 0xFF ) & 0x0F ) != 0x05 ) { // Make sure the block was accepted - Neo_EnableMMC( false ); - return false; - } - while( Neo_SPI( 0xFF ) == 0x00 ); // Wait for the block to be written - } - - // Stop transmission block - Neo_SPI( 0xFD ); // Send Stop Transmission Block token - for( i = 0; i < BYTE_PER_READ; i++ ) // Send a block of fake data - Neo_SPI( 0xFF ); - Neo_SPI( 0xFF ); // Send fake CRC16 - Neo_SPI( 0xFF ); // Send fake CRC16 - - Neo_SPI (0xFF); // Send 8 clocks - while( Neo_SPI( 0xFF ) == 0x00 ); // Wait for the busy signal to clear - - - for ( i = 0; i < 0x10; i++) { - Neo_SPI (0xFF); // Send clocks for the MMC card to finish what it's doing - } - - Neo_EnableMMC( false ); // Close SPI port to MMC card - return true; -} - -bool NMMC_ReadSectors (u32 sector, u8 numSecs, void* buffer) -{ - u32 i; - u8 *p=buffer; - - int totalSecs = (numSecs == 0) ? 256 : numSecs; - sector *= BYTE_PER_READ; - - Neo_EnableMMC( true ); // Open SPI port to MMC card - - while (totalSecs--) { - Neo_SendMMCCommand(MMC_READ_BLOCK, sector ); - if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occured - Neo_EnableMMC( false ); - return false; - } - - if( Neo_CheckMMCResponse( 0xFE, 0xFF ) == false ) { // Check for Start Block token - Neo_EnableMMC( false ); - return false; - } - for( i = 0; i < BYTE_PER_READ; i++ ) // Read in a block of data - *p++ = Neo_SPI( 0xFF ); - Neo_SPI( 0xFF ); // Ignore CRC16 - Neo_SPI( 0xFF ); // Ignore CRC16 - sector += BYTE_PER_READ; - } - - Neo_EnableMMC( false ); // Close SPI port to MMC card - return true; -} - - -IO_INTERFACE io_nmmc = { - DEVICE_TYPE_NMMC, - FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE, - (FN_MEDIUM_STARTUP)&NMMC_StartUp, - (FN_MEDIUM_ISINSERTED)&NMMC_IsInserted, - (FN_MEDIUM_READSECTORS)&NMMC_ReadSectors, - (FN_MEDIUM_WRITESECTORS)&NMMC_WriteSectors, - (FN_MEDIUM_CLEARSTATUS)&NMMC_ClearStatus, - (FN_MEDIUM_SHUTDOWN)&NMMC_Shutdown -} ; - - LPIO_INTERFACE NMMC_GetInterface(void) { return &io_nmmc ; } diff --git a/backends/platform/ds/arm9/source/fat/io_sccf.c b/backends/platform/ds/arm9/source/fat/io_sccf.c index 336387e9d7..0c77f4673c 100644 --- a/backends/platform/ds/arm9/source/fat/io_sccf.c +++ b/backends/platform/ds/arm9/source/fat/io_sccf.c @@ -80,93 +80,6 @@ IO_INTERFACE io_sccf = { } ; -LPIO_INTERFACE SCCF_GetInterface(void) { - return &io_sccf ; -} ; - -#endif // SUPPORT_SCCF -/* - io_sccf.c based on - - compact_flash.c - By chishm (Michael Chisholm) - - Hardware Routines for reading a compact flash card - using the Super Card CF - - CF routines modified with help from Darkfader - - This software is completely free. No warranty is provided. - If you use it, please give me credit and email me about your - project at chishm@hotmail.com - - See gba_nds_fat.txt for help and license details. -*/ - - -#include "io_sccf.h" - -#ifdef SUPPORT_SCCF - -#ifndef SUPPORT_MPCF - #error Supercard CF support requires GBAMP CF support -#endif // SUPPORT_MPCF - -/*----------------------------------------------------------------- -Since all CF addresses and commands are the same for the GBAMP, -simply use it's functions instead. ------------------------------------------------------------------*/ - -extern bool MPCF_IsInserted (void); -extern bool MPCF_ClearStatus (void); -extern bool MPCF_ReadSectors (u32 sector, u8 numSecs, void* buffer); -extern bool MPCF_WriteSectors (u32 sector, u8 numSecs, void* buffer); - - -/*----------------------------------------------------------------- -SCCF_Unlock -Returns true if SuperCard was unlocked, false if failed -Added by MightyMax -Modified by Chishm ------------------------------------------------------------------*/ -bool SCCF_Unlock(void) -{ -#define CF_REG_LBA1 *(volatile unsigned short *)0x09060000 - unsigned char temp; - volatile short *unlockAddress = (volatile short *)0x09FFFFFE; - *unlockAddress = 0xA55A ; - *unlockAddress = 0xA55A ; - *unlockAddress = 0x3 ; - *unlockAddress = 0x3 ; - // provoke a ready reply - temp = CF_REG_LBA1; - CF_REG_LBA1 = (~temp & 0xFF); - temp = (~temp & 0xFF); - return (CF_REG_LBA1 == temp); -#undef CF_REG_LBA1 -} - -bool SCCF_Shutdown(void) { - return MPCF_ClearStatus() ; -} ; - -bool SCCF_StartUp(void) { - return SCCF_Unlock() ; -} ; - - -IO_INTERFACE io_sccf = { - DEVICE_TYPE_SCCF, - FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_SLOT_GBA, - (FN_MEDIUM_STARTUP)&SCCF_StartUp, - (FN_MEDIUM_ISINSERTED)&MPCF_IsInserted, - (FN_MEDIUM_READSECTORS)&MPCF_ReadSectors, - (FN_MEDIUM_WRITESECTORS)&MPCF_WriteSectors, - (FN_MEDIUM_CLEARSTATUS)&MPCF_ClearStatus, - (FN_MEDIUM_SHUTDOWN)&SCCF_Shutdown -} ; - - LPIO_INTERFACE SCCF_GetInterface(void) { return &io_sccf ; } ; diff --git a/backends/platform/ds/arm9/source/fat/io_scsd.c b/backends/platform/ds/arm9/source/fat/io_scsd.c index a2fccf45d2..b7449bb828 100644 --- a/backends/platform/ds/arm9/source/fat/io_scsd.c +++ b/backends/platform/ds/arm9/source/fat/io_scsd.c @@ -91,96 +91,4 @@ IO_INTERFACE io_scsd = { LPIO_INTERFACE SCSD_GetInterface(void) { return &io_scsd ; } ; -/* - io_scsd.c by SaTa. - based on io_sccf.c - - -*/ - -/* - io_sccf.c based on - - compact_flash.c - By chishm (Michael Chisholm) - - Hardware Routines for reading a compact flash card - using the Super Card CF - - CF routines modified with help from Darkfader - - This software is completely free. No warranty is provided. - If you use it, please give me credit and email me about your - project at chishm@hotmail.com - - See gba_nds_fat.txt for help and license details. -*/ - - -#include "io_scsd.h" - -/*----------------------------------------------------------------- -Since all CF addresses and commands are the same for the GBAMP, -simply use it's functions instead. ------------------------------------------------------------------*/ - -extern bool MPCF_IsInserted (void); -extern bool MPCF_ClearStatus (void); -extern bool MPCF_ReadSectors (u32 sector, u8 numSecs, void* buffer); -extern bool MPCF_WriteSectors (u32 sector, u8 numSecs, void* buffer); - -// add by SaTa. -extern void InitSCMode(void); // CFと同じ -extern void ReadSector(u16 *buff,u32 sector,u8 ReadNumber); -extern void WriteSector(u16 *buff,u32 sector,u8 writeNumber); -extern bool MemoryCard_IsInserted(void); // CFと違う -// - -/*----------------------------------------------------------------- -SCSD_Unlock -Returns true if SuperCard was unlocked, false if failed -Added by MightyMax -Modified by Chishm ------------------------------------------------------------------*/ -bool SCSD_Unlock(void) -{ - InitSCMode(); - return MemoryCard_IsInserted(); -} - -bool SCSD_Shutdown(void) { - return MPCF_ClearStatus() ; -} ; - -bool SCSD_StartUp(void) { - return SCSD_Unlock() ; -} ; - -bool SCSD_ReadSectors (u32 sector, u8 ReadNumber, void* buff) -{ - ReadSector((u16 *)buff,sector,ReadNumber); - return true; -} - -bool SCSD_WriteSectors (u32 sector, u8 writeNumber, void* buff) -{ - WriteSector((u16 *)buff,sector,writeNumber); - return true; -} - -IO_INTERFACE io_scsd = { - 0x44534353, // 'SCSD' - FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE, - (FN_MEDIUM_STARTUP)&SCSD_StartUp, - (FN_MEDIUM_ISINSERTED)&SCSD_Unlock, - (FN_MEDIUM_READSECTORS)&SCSD_ReadSectors, - (FN_MEDIUM_WRITESECTORS)&SCSD_WriteSectors, - (FN_MEDIUM_CLEARSTATUS)&MPCF_ClearStatus, - (FN_MEDIUM_SHUTDOWN)&SCSD_Shutdown -} ; - - -LPIO_INTERFACE SCSD_GetInterface(void) { - return &io_scsd ; -} ; diff --git a/backends/platform/ds/arm9/source/scummconsole.c b/backends/platform/ds/arm9/source/scummconsole.c index e526e921e5..b2b312e25d 100644 --- a/backends/platform/ds/arm9/source/scummconsole.c +++ b/backends/platform/ds/arm9/source/scummconsole.c @@ -31,7 +31,7 @@ ////////////////////////////////////////////////////////////////////// -#include +#include #include "scummconsole.h" #include diff --git a/backends/platform/ds/arm9/source/touchkeyboard.cpp b/backends/platform/ds/arm9/source/touchkeyboard.cpp index d3e8a61077..ee14bafced 100644 --- a/backends/platform/ds/arm9/source/touchkeyboard.cpp +++ b/backends/platform/ds/arm9/source/touchkeyboard.cpp @@ -16,320 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ -#include -#include "touchkeyboard.h" -#include "keyboard_raw.h" -#include "keyboard_pal_raw.h" -#include "dsmain.h" -#include "osystem_ds.h" - -namespace DS { - -struct key_data { - char keyNum; - char x, y; - int character; - bool pressed; -}; - -#define DS_NUM_KEYS 60 -#define DS_SHIFT 0 -#define DS_BACKSPACE 8 -#define DS_RETURN 13 -#define DS_CAPSLOCK 1 - - -key_data keys[DS_NUM_KEYS] = { - // Key number x y character - - // Numbers - {28, 3, 0, '1'}, - {29, 5, 0, '2'}, - {30, 7, 0, '3'}, - {31, 9, 0, '4'}, - {32, 11, 0, '5'}, - {33, 13, 0, '6'}, - {34, 15, 0, '7'}, - {35, 17, 0, '8'}, - {36, 19, 0, '9'}, - {27, 21, 0, '0'}, - {45, 23, 0, SDLK_MINUS}, - {50, 25, 0, SDLK_EQUALS}, - {52, 27, 0, SDLK_BACKSPACE}, - - // Top row - {'Q'-'A' + 1, 4, 2, 'Q'}, - {'W'-'A' + 1, 6, 2, 'W'}, - {'E'-'A' + 1, 8, 2, 'E'}, - {'R'-'A' + 1, 10, 2, 'R'}, - {'T'-'A' + 1, 12, 2, 'T'}, - {'Y'-'A' + 1, 14, 2, 'Y'}, - {'U'-'A' + 1, 16, 2, 'U'}, - {'I'-'A' + 1, 18, 2, 'I'}, - {'O'-'A' + 1, 20, 2, 'O'}, - {'P'-'A' + 1, 22, 2, 'P'}, - {43, 24, 2, SDLK_LEFTBRACKET}, - {44, 26, 2, SDLK_RIGHTBRACKET}, - - // Middle row - {55, 3, 4, DS_CAPSLOCK}, - {'A'-'A' + 1, 5, 4, 'A'}, - {'S'-'A' + 1, 7, 4, 'S'}, - {'D'-'A' + 1, 9, 4, 'D'}, - {'F'-'A' + 1, 11, 4, 'F'}, - {'G'-'A' + 1, 13, 4, 'G'}, - {'H'-'A' + 1, 15, 4, 'H'}, - {'J'-'A' + 1, 17, 4, 'J'}, - {'K'-'A' + 1, 19, 4, 'K'}, - {'L'-'A' + 1, 21, 4, 'L'}, - {42, 23, 4, SDLK_SEMICOLON}, - {41, 25, 4, SDLK_QUOTE}, - {46, 27, 4, SDLK_RETURN}, - - // Bottom row - {51, 4, 6, DS_SHIFT}, - {'Z'-'A' + 1, 6, 6, 'Z'}, - {'X'-'A' + 1, 8, 6, 'X'}, - {'C'-'A' + 1, 10, 6, 'C'}, - {'V'-'A' + 1, 12, 6, 'V'}, - {'B'-'A' + 1, 14, 6, 'B'}, - {'N'-'A' + 1, 16, 6, 'N'}, - {'M'-'A' + 1, 18, 6, 'M'}, - {38, 20, 6, SDLK_COMMA}, - {39, 22, 6, SDLK_PERIOD}, - {40, 24, 6, SDLK_SLASH}, - - // Space bar - {47, 9, 8, SDLK_SPACE}, - {48, 11, 8, SDLK_SPACE}, - {48, 13, 8, SDLK_SPACE}, - {48, 15, 8, SDLK_SPACE}, - {48, 17, 8, SDLK_SPACE}, - {49, 19, 8, SDLK_SPACE}, - - // Cursor arrows - {52, 27, 8, SDLK_LEFT}, - {54, 29, 8, SDLK_DOWN}, - {53, 31, 8, SDLK_RIGHT}, - {51, 29, 6, SDLK_UP}, - - // Close button - {56, 30, 0, SDLK_UNKNOWN}, - -}; - -int keyboardX; -int keyboardY; - -int mapBase; -int tileBase; - -bool shiftState; -bool capsLockState; - -bool closed; - -void restoreVRAM(int tileBase, int mapBase, u16* saveSpace) { - for (int r = 0; r < 32 * 32; r++) { - ((u16 *) SCREEN_BASE_BLOCK_SUB(mapBase))[r] = *saveSpace++; - } - - for (int r = 0; r < 4096; r++) { - ((u16 *) CHAR_BASE_BLOCK_SUB(tileBase))[r] = *saveSpace++; - } -} - -void drawKeyboard(int tileBase, int mapBase, u16* saveSpace) { - - - for (int r = 0; r < 32 * 32; r++) { -// *saveSpace++ = ((u16 *) SCREEN_BASE_BLOCK_SUB(mapBase))[r]; - ((u16 *) SCREEN_BASE_BLOCK_SUB(mapBase))[r] = 127; - } - - for (int r = 0; r < 4096; r++) { -// *saveSpace++ = ((u16 *) CHAR_BASE_BLOCK_SUB(tileBase))[r]; - ((u16 *) CHAR_BASE_BLOCK_SUB(tileBase))[r] = ((u16 *) (keyboard_raw))[r]; - } - - for (int r = 0; r < 16; r++) { - BG_PALETTE_SUB[r] = ((u16 *) (keyboard_pal_raw))[r]; - } - - for (int r = 0; r < 16; r++) { - int col = ((u16 *) (keyboard_pal_raw))[r]; - - int red = col & 0x001F; - int green = (col & 0x03E0) >> 5; - int blue = (col & 0x7C00) >> 10; - - red = (red * 8) / 16; - green = (green * 8) / 16; - blue = (blue * 8) / 16; - - BG_PALETTE_SUB[16 + r] = red | (green << 5) | (blue << 10); - } - - keyboardX = -2; - keyboardY = 2; - - mapBase = mapBase; - tileBase = tileBase; - - shiftState = false; - capsLockState = false; - - int x = keyboardX; - int y = keyboardY; - - u16* base = ((u16 *) SCREEN_BASE_BLOCK_SUB(mapBase)); - - for (int r = 0; r < DS_NUM_KEYS; r++) { - base[(y + keys[r].y) * 32 + x + keys[r].x] = keys[r].keyNum * 2; - base[(y + keys[r].y) * 32 + x + keys[r].x + 1] = keys[r].keyNum * 2 + 1; - - base[(y + keys[r].y + 1) * 32 + x + keys[r].x] = 128 + keys[r].keyNum * 2; - base[(y + keys[r].y + 1) * 32 + x + keys[r].x + 1] = 128 + keys[r].keyNum * 2 + 1; - - keys[r].pressed = false; - } - - closed = false; -} - -bool getKeyboardClosed() { - return closed; -} - -void setKeyHighlight(int key, bool highlight) { - u16* base = ((u16 *) SCREEN_BASE_BLOCK_SUB(DS::mapBase)); - - if (highlight) { - base[(keyboardY + keys[key].y) * 32 + keyboardX + keys[key].x] |= 0x1000; - base[(keyboardY + keys[key].y) * 32 + keyboardX + keys[key].x + 1] |= 0x1000; - base[(keyboardY + keys[key].y + 1) * 32 + keyboardX + keys[key].x] |= 0x1000; - base[(keyboardY + keys[key].y + 1) * 32 + keyboardX + keys[key].x + 1] |= 0x1000; - } else { - base[(keyboardY + keys[key].y) * 32 + keyboardX + keys[key].x] &= ~0x1000; - base[(keyboardY + keys[key].y) * 32 + keyboardX + keys[key].x + 1] &= ~0x1000; - base[(keyboardY + keys[key].y + 1) * 32 + keyboardX + keys[key].x] &= ~0x1000; - base[(keyboardY + keys[key].y + 1) * 32 + keyboardX + keys[key].x + 1] &= ~0x1000; - } -} - -void addKeyboardEvents() { - if (DS::getPenDown()) { - int x = IPC->touchXpx; - int y = IPC->touchYpx; - - int tx = (x >> 3) - keyboardX; - int ty = (y >> 3) - keyboardY; - -// consolePrintf("x=%d y=%d\n", tx, ty); - - for (int r = 0; r < DS_NUM_KEYS; r++) { - if (( (tx >= keys[r].x) && (tx <= keys[r].x + 1)) && - (ty >= keys[r].y) && (ty <= keys[r].y + 1)) { - OSystem_DS* system = OSystem_DS::instance(); - OSystem::Event event; - -// consolePrintf("Key: %d\n", r); - if ((keys[r].character == SDLK_UNKNOWN)) { - // Close button - DS::closed = true; - } else if ((keys[r].character >= '0') && (keys[r].character <= '9')) { - event.kbd.ascii = keys[r].character; - event.kbd.keycode = 0; - - } else if ((keys[r].character >= 'A') && (keys[r].character <= 'Z')) { - - if ((!DS::shiftState) && (!DS::capsLockState)) { - event.kbd.ascii = keys[r].character + 32; // Make key lowercase. - } else { - event.kbd.ascii = keys[r].character; - } - - event.kbd.keycode = event.kbd.ascii; - } else { - event.kbd.ascii = keys[r].character; - event.kbd.keycode = keys[r].character; - } - - - - //event.kbd.keycode = keys[r].character; - //event.kbd.ascii = keys[r].character; - event.type = OSystem::EVENT_KEYDOWN; - event.kbd.flags = 0; - system->addEvent(event); - - event.type = OSystem::EVENT_KEYUP; - system->addEvent(event); - - switch (keys[r].character) { - case DS_SHIFT: { - DS::shiftState = !DS::shiftState; - DS::setKeyHighlight(r, DS::shiftState); - break; - } - - case DS_CAPSLOCK: { - DS::capsLockState = !DS::capsLockState; - DS::setKeyHighlight(r, DS::capsLockState); - break; - } - - default: { - DS::setKeyHighlight(r, true); - keys[r].pressed = true; - - if (DS::shiftState) { - DS::shiftState = false; - for (int t = 0; t < DS_NUM_KEYS; t++) { - if (keys[t].character == DS_SHIFT) { - DS::setKeyHighlight(t, false); - } - } - } - break; - } - } - - } - } - } - - if (DS::getPenReleased()) { - for (int r = 0; r < DS_NUM_KEYS; r++) { - if (keys[r].pressed) { - DS::setKeyHighlight(r, false); - keys[r].pressed = false; - } - } - } -} - -} - -/* 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 +#include #include "touchkeyboard.h" #include "keyboard_raw.h" #include "keyboard_pal_raw.h" diff --git a/backends/platform/ds/arm9/source/zipreader.cpp b/backends/platform/ds/arm9/source/zipreader.cpp index b8780913ec..e23e920a50 100644 --- a/backends/platform/ds/arm9/source/zipreader.cpp +++ b/backends/platform/ds/arm9/source/zipreader.cpp @@ -151,227 +151,6 @@ bool ZipFile::skipFile() { -u32 ZipFile::misaligned32(u32* v) { - char* b = (char *) v; - return (b[0] << 24) + (b[1] << 16) + (b[2] << 8) + b[3]; -} - -u16 ZipFile::misaligned16(u16* v) { - char* b = (char *) v; - return (b[0] << 8) + b[1]; -} - -int ZipFile::getFileSize() { - return _currentFile->fileSize; -} - -bool ZipFile::isDirectory() { - return _currentFile->fileSize == 0; // This is a bit wrong, but seems to work. -} - -char* ZipFile::getFile() { - return ((char *) (_currentFile)) + sizeof(*_currentFile) + _currentFile->nameLength + _currentFile->extraLength; -} - -bool ZipFile::findFile(char* search) { - changeToRoot(); - restartFile(); - - char searchName[128]; - strcpy(searchName, search); - for (int r = 0; r < (int) strlen(searchName); r++) { - if (searchName[r] == '/') searchName[r] = '\\'; - } - - if (*(searchName + strlen(searchName) - 1) == '\\') { // Directories have a terminating slash - *(searchName + strlen(searchName) - 1) = '\0'; // which we need to dispose of. - } - - - do { - char name[128]; - getFileName(name); - if (*(name + strlen(name) - 1) == '\\') { // Directories have a terminating slash - *(name + strlen(name) - 1) = '\0'; // which we need to dispose of. - } - - - if (!stricmp(name, searchName)) { -// consolePrintf("'%s'=='%s'\n", name, searchName); - return true; // Got it! - } else { -// consolePrintf("'%s'!='%s'\n", name, searchName); - } - } while (skipFile()); - - return false; // File wasn't found -} - -void ZipFile::changeToRoot() { - _directory[0] = 0; -} - -void ZipFile::changeDirectory(char* dir) { -// consolePrintf("Current dir now '%s'\n", dir); - strcpy(_directory, dir); -} - -ZipFile::~ZipFile() { - -} -/* Zip File Reader - * Copyright (C) 2002-2004 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 "zipreader.h" - -#define SWAP_U16(v) (((v & 0xFF) << 8) + (v & 0xFF00)) -#define SWAP_U32(v) ((SWAP_U16((v & 0XFFFF0000) >> 16) + (SWAP_U16(v & 0x0000FFFF) << 16))) - - -ZipFile::ZipFile() { - // Locate a zip file in cartridge memory space - - consolePrintf("ZIP file check..."); - - char* p = (char *) ZF_SEARCH_START; - bool found = false; - - _zipFile = NULL; - - while ((p != (char *) ZF_SEARCH_END) && (!found)) { - // Zip file header is: 0x504B0304 - - if ( (*p == 0x50) && (*(p + 1) == 0x4B) && (*(p + 2) == 0x03) && (*(p + 3) == 0x04) ) { - // Found header! - found = true; - _zipFile = p; - } - - if (!found) p += ZF_SEARCH_STRIDE; - - } - - if (_zipFile) { - consolePrintf("Ok!\n"); - } else { - consolePrintf("Not in use!\n"); - return; - } - - changeToRoot(); - restartFile(); - - if (_currentFile->compSize != (u32) getFileSize()) { - consolePrintf("Error: ZIP file contains compression!\n"); - } - - _allFilesVisible = false; -} - -bool ZipFile::isReady() { - return _zipFile != NULL; -} - -bool ZipFile::restartFile() { - _currentFile = (FileHeader *) _zipFile; - char name[128]; - getFileName(name); - - bool more = true; - - while (!currentFileInFolder() && more) { - char name[128]; - getFileName(name); - more = skipFile(); - } - - return more; -} - -bool ZipFile::currentFileInFolder() { - char name[128]; - - if (_allFilesVisible) return true; - - getFileName(name); - - if (_directory[0] == 0) { // Root directory - name[strlen(name) - 1] = 0; - return !strchr(name, '\\'); // Not in root if contains a / character before the last character - } else { -/* if (name starts with directory && it's not the directory - && (no slashes after the directory || it's the last character) - && (slash follows directory) - */ - if ((strstr(name, _directory) == name) && (strlen(name) != strlen(_directory)) - && ((strchr(name + strlen(_directory) + 1, '\\') == NULL) - || (strchr(name + strlen(_directory) + 1, '\\') == name + strlen(name) - 1)) - && (*(name + strlen(_directory)) == '\\')) { - return true; - } - } - - return false; -} - -void ZipFile::getFileName(char* name) { - strncpy(name, (char *) (_currentFile + 1), _currentFile->nameLength); - - for (int r = 0; r < (int) strlen(name); r++) { - if (name[r] == '/') name[r] = '\\'; - } - - name[_currentFile->nameLength] = 0; - - if (name[strlen(name) - 1] == '\\') { - name[strlen(name) - 1] = 0; - } -} - -bool ZipFile::skipFile() { - bool valid; - - do { - - // Move on to the next file - _currentFile = (FileHeader *) ( - ((char *) (_currentFile)) + sizeof(*_currentFile) + _currentFile->nameLength + _currentFile->fileSize + _currentFile->extraLength - ); - - // Return true if there are more files. Check this by looking for the magic number - valid = (_currentFile->magic[0] == 0x50) && - (_currentFile->magic[1] == 0x4B) && - (_currentFile->magic[2] == 0x03) && - (_currentFile->magic[3] == 0x04); - - - } while (valid && !currentFileInFolder()); - - return valid; - - // Currently doesn't handle data descriptors! -} - - - u32 ZipFile::misaligned32(u32* v) { char* b = (char *) v; return (b[0] << 24) + (b[1] << 16) + (b[2] << 8) + b[3]; diff --git a/backends/platform/ds/makefile b/backends/platform/ds/makefile index 1a7b38c449..9c88932a7f 100644 --- a/backends/platform/ds/makefile +++ b/backends/platform/ds/makefile @@ -18,25 +18,3 @@ clean: export: @for i in $(SUBDIRS); do if test -d $$i; then make -C $$i export; fi; done; - -#SUBDIRS:= `ls | egrep -v '^(CVS|tools)$$'` - - - - -export PATH := $(DEVKITARM)/bin:$(PATH) - -export portdir = $(CURDIR)/arm9 -export srcdir = $(CURDIR)/../../.. - - -SUBDIRS := arm7 arm9 - -all: - @for i in $(SUBDIRS); do if test -d $$i; then make -C $$i; fi; done; -clean: - @for i in $(SUBDIRS); do if test -d $$i; then make -C $$i clean; fi; done; - -export: - @for i in $(SUBDIRS); do if test -d $$i; then make -C $$i export; fi; done; - -- cgit v1.2.3