fceugx/source/ngc/memcardop.cpp

394 lines
8.9 KiB
C++
Raw Normal View History

2008-09-02 03:57:21 +02:00
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* memcardop.c
*
* Memory Card routines
****************************************************************************/
#include <gccore.h>
#include <ogcsys.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
2009-03-28 18:23:08 +01:00
#include <malloc.h>
2008-09-02 03:57:21 +02:00
#include "fceugx.h"
2009-03-28 18:23:08 +01:00
#include "common.h"
#include "gcvideo.h"
2008-09-02 03:57:21 +02:00
#include "menu.h"
2009-03-28 18:23:08 +01:00
#include "preferences.h"
#include "filebrowser.h"
2008-09-02 03:57:21 +02:00
#include "fileop.h"
2009-03-28 18:23:08 +01:00
#include "dvd.h"
#include "images/saveicon.h"
2008-09-02 03:57:21 +02:00
2009-03-28 18:23:08 +01:00
static u8 * SysArea = NULL;
static char savecomments[2][32];
2009-06-13 03:57:34 +02:00
static u8 * verifybuffer = NULL;
2008-09-02 03:57:21 +02:00
/****************************************************************************
2009-03-28 18:23:08 +01:00
* MountMC
*
* Mounts the memory card in the given slot.
* Returns the result of the last attempted CARD_Mount command.
***************************************************************************/
2009-03-28 18:23:08 +01:00
static int MountMC(int slot, bool silent)
{
int ret = -1;
int tries = 0;
2009-03-28 18:23:08 +01:00
// Initialize Card System
SysArea = (u8 *)memalign(32, CARD_WORKAREA);
memset (SysArea, 0, CARD_WORKAREA);
CARD_Init ("FCEU", "00");
// Mount the card
2009-03-28 18:23:08 +01:00
while(tries < 10 && ret != 0)
{
2009-03-28 18:23:08 +01:00
EXI_ProbeReset();
ret = CARD_Mount (slot, SysArea, NULL);
VIDEO_WaitVSync();
tries++;
}
2009-03-28 18:23:08 +01:00
if(ret != 0 && !silent)
{
if (slot == CARD_SLOTA)
ErrorPrompt("Unable to mount Slot A Memory Card!");
else
ErrorPrompt("Unable to mount Slot B Memory Card!");
}
return ret;
}
2008-09-02 03:57:21 +02:00
/****************************************************************************
2009-03-28 18:23:08 +01:00
* TestMC
2008-09-02 03:57:21 +02:00
*
* Checks to see if a card is in the card slot specified
2008-11-12 09:40:09 +01:00
***************************************************************************/
2009-03-28 18:23:08 +01:00
bool TestMC(int slot, bool silent)
2008-09-02 03:57:21 +02:00
{
// Memory Cards do not work in Wii mode - disable
#ifdef HW_RVL
return false;
#endif
2009-03-28 18:23:08 +01:00
bool ret = false;
2008-09-02 03:57:21 +02:00
2009-03-28 18:23:08 +01:00
// Try to mount the card
if (MountMC(slot, silent) == 0)
2008-09-02 03:57:21 +02:00
{
// Mount successful!
CARD_Unmount (slot);
2009-03-28 18:23:08 +01:00
ret = true;
2008-09-02 03:57:21 +02:00
}
2009-03-28 18:23:08 +01:00
free(SysArea);
return ret;
}
/****************************************************************************
* ParseMCDirectory
*
* Parses a list of all files on the specified memory card
***************************************************************************/
int
ParseMCDirectory (int slot)
{
card_dir CardDir;
int CardError;
int entryNum = 0;
// Try to mount the card
CardError = MountMC(slot, NOTSILENT);
if (CardError == 0)
2008-09-02 03:57:21 +02:00
{
2009-03-28 18:23:08 +01:00
CardError = CARD_FindFirst (slot, &CardDir, TRUE);
while (CardError != CARD_ERROR_NOFILE)
2008-09-02 03:57:21 +02:00
{
2009-03-28 18:23:08 +01:00
BROWSERENTRY * newBrowserList = (BROWSERENTRY *)realloc(browserList, (entryNum+1) * sizeof(BROWSERENTRY));
if(!newBrowserList) // failed to allocate required memory
{
ResetBrowser();
ErrorPrompt("Out of memory: too many files!");
entryNum = -1;
break;
}
2008-09-02 03:57:21 +02:00
else
2009-03-28 18:23:08 +01:00
{
browserList = newBrowserList;
}
memset(&(browserList[entryNum]), 0, sizeof(BROWSERENTRY)); // clear the new entry
2008-09-02 03:57:21 +02:00
2009-03-28 18:23:08 +01:00
strncpy(browserList[entryNum].filename, (char *)CardDir.filename, MAXJOLIET);
StripExt(browserList[entryNum].displayname, browserList[entryNum].filename); // hide file extension
2009-03-28 18:23:08 +01:00
browserList[entryNum].length = CardDir.filelen;
entryNum++;
CardError = CARD_FindNext (&CardDir);
}
CARD_Unmount(slot);
2008-09-02 03:57:21 +02:00
}
2009-03-28 18:23:08 +01:00
// Sort the file list
qsort(browserList, entryNum, sizeof(BROWSERENTRY), FileSortCallback);
CancelAction();
browser.numEntries = entryNum;
return entryNum;
2008-09-02 03:57:21 +02:00
}
/****************************************************************************
* Verify Memory Card file against buffer
2008-11-12 09:40:09 +01:00
***************************************************************************/
static int
2008-11-12 09:40:09 +01:00
VerifyMCFile (char *buf, int slot, char *filename, int datasize)
2008-09-02 03:57:21 +02:00
{
card_file CardFile;
2008-09-02 03:57:21 +02:00
int CardError;
unsigned int blocks;
unsigned int SectorSize;
2009-03-28 18:23:08 +01:00
int bytesleft = 0;
int bytesread = 0;
2008-09-02 03:57:21 +02:00
2009-06-13 03:57:34 +02:00
verifybuffer = (u8 *)memalign(32, 262144);
memset (verifybuffer, 0, 262144);
2008-09-02 03:57:21 +02:00
2009-03-28 18:23:08 +01:00
// Get Sector Size
CARD_GetSectorSize (slot, &SectorSize);
2008-09-02 03:57:21 +02:00
2009-03-28 18:23:08 +01:00
memset (&CardFile, 0, sizeof (CardFile));
CardError = CARD_Open (slot, filename, &CardFile);
2008-09-02 03:57:21 +02:00
2009-03-28 18:23:08 +01:00
if(CardError)
{
ErrorPrompt("Unable to open file!");
}
else
{
2008-09-02 03:57:21 +02:00
blocks = CardFile.len;
if (blocks < SectorSize)
blocks = SectorSize;
if (blocks % SectorSize)
blocks += SectorSize;
2009-03-28 18:23:08 +01:00
if (blocks > (unsigned int)datasize)
blocks = datasize;
2008-09-02 03:57:21 +02:00
bytesleft = blocks;
bytesread = 0;
while (bytesleft > 0)
{
2009-03-28 18:23:08 +01:00
CardError = CARD_Read (&CardFile, verifybuffer, SectorSize, bytesread);
if (CardError || memcmp (buf + bytesread, verifybuffer, (unsigned int)bytesleft < SectorSize ? bytesleft : SectorSize) )
{
bytesread = 0;
ErrorPrompt("File integrity could not be verified!");
break;
}
2008-09-02 03:57:21 +02:00
bytesleft -= SectorSize;
bytesread += SectorSize;
2009-03-28 18:23:08 +01:00
ShowProgress ("Verifying...", bytesread, blocks);
2008-09-02 03:57:21 +02:00
}
CARD_Close (&CardFile);
2009-03-28 18:23:08 +01:00
CancelAction();
2008-09-02 03:57:21 +02:00
}
2009-06-13 03:57:34 +02:00
free(verifybuffer);
2009-03-28 18:23:08 +01:00
return bytesread;
2008-09-02 03:57:21 +02:00
}
/****************************************************************************
2008-11-12 09:40:09 +01:00
* LoadMCFile
2008-09-02 03:57:21 +02:00
* Load savebuffer from Memory Card file
2008-11-12 09:40:09 +01:00
***************************************************************************/
2008-09-02 03:57:21 +02:00
int
2008-11-12 09:40:09 +01:00
LoadMCFile (char *buf, int slot, char *filename, bool silent)
2008-09-02 03:57:21 +02:00
{
card_file CardFile;
2008-09-02 03:57:21 +02:00
int CardError;
unsigned int blocks;
unsigned int SectorSize;
2009-03-28 18:23:08 +01:00
int bytesleft = 0;
int bytesread = 0;
2008-09-02 03:57:21 +02:00
2009-03-28 18:23:08 +01:00
// Try to mount the card
CardError = MountMC(slot, NOTSILENT);
2008-09-02 03:57:21 +02:00
if (CardError == 0)
{
2009-03-28 18:23:08 +01:00
// Get Sector Size
2008-09-02 03:57:21 +02:00
CARD_GetSectorSize (slot, &SectorSize);
memset (&CardFile, 0, sizeof (CardFile));
CardError = CARD_Open (slot, filename, &CardFile);
2009-03-28 18:23:08 +01:00
if(CardError)
{
if(!silent)
ErrorPrompt("Unable to open file!");
}
else
{
blocks = CardFile.len;
2008-09-02 03:57:21 +02:00
2009-03-28 18:23:08 +01:00
if (blocks < SectorSize)
blocks = SectorSize;
2008-09-02 03:57:21 +02:00
2009-03-28 18:23:08 +01:00
if (blocks % SectorSize)
blocks += SectorSize;
bytesleft = blocks;
bytesread = 0;
while (bytesleft > 0)
{
CardError = CARD_Read (&CardFile, buf + bytesread, SectorSize, bytesread);
2008-09-02 03:57:21 +02:00
2009-03-28 18:23:08 +01:00
if(CardError)
{
ErrorPrompt("Error loading file!");
bytesread = 0;
break;
}
2008-09-02 03:57:21 +02:00
2009-03-28 18:23:08 +01:00
bytesleft -= SectorSize;
bytesread += SectorSize;
ShowProgress ("Loading...", bytesread, blocks);
}
CARD_Close (&CardFile);
CancelAction();
2008-09-02 03:57:21 +02:00
}
2009-03-28 18:23:08 +01:00
CARD_Unmount(slot);
2008-09-02 03:57:21 +02:00
}
2009-03-28 18:23:08 +01:00
// discard save icon and comments
memmove(buf, buf+sizeof(saveicon)+64, bytesread);
bytesread -= (sizeof(saveicon)+64);
free(SysArea);
2008-09-02 03:57:21 +02:00
return bytesread;
}
/****************************************************************************
2008-11-12 09:40:09 +01:00
* SaveMCFile
2008-09-02 03:57:21 +02:00
* Write savebuffer to Memory Card file
2008-11-12 09:40:09 +01:00
***************************************************************************/
2008-09-02 03:57:21 +02:00
int
2008-11-12 09:40:09 +01:00
SaveMCFile (char *buf, int slot, char *filename, int datasize, bool silent)
2008-09-02 03:57:21 +02:00
{
card_file CardFile;
card_stat CardStatus;
2008-09-02 03:57:21 +02:00
int CardError;
unsigned int blocks;
unsigned int SectorSize;
2009-03-28 18:23:08 +01:00
int byteswritten = 0;
int bytesleft = 0;
2008-09-02 03:57:21 +02:00
2008-12-24 08:58:23 +01:00
if(datasize <= 0)
return 0;
2009-03-28 18:23:08 +01:00
// add save icon and comments
memmove(buf+sizeof(saveicon)+64, buf, datasize);
memcpy(buf, saveicon, sizeof(saveicon));
memcpy(buf+sizeof(saveicon), savecomments, 64);
datasize += (sizeof(saveicon)+64);
2008-09-02 03:57:21 +02:00
2009-03-28 18:23:08 +01:00
// Try to mount the card
CardError = MountMC(slot, NOTSILENT);
2008-09-02 03:57:21 +02:00
if (CardError == 0)
{
2009-03-28 18:23:08 +01:00
// Get Sector Size
2008-09-02 03:57:21 +02:00
CARD_GetSectorSize (slot, &SectorSize);
2009-03-28 18:23:08 +01:00
// Calculate number of blocks required
2008-12-24 08:58:23 +01:00
blocks = (datasize / SectorSize) * SectorSize;
if (datasize % SectorSize)
blocks += SectorSize;
2009-03-28 18:23:08 +01:00
// Delete existing file (if present)
memset(&CardStatus, 0, sizeof(card_stat));
CardError = CARD_Open (slot, filename, &CardFile);
if(CardError == 0)
2008-09-02 03:57:21 +02:00
{
2009-03-28 18:23:08 +01:00
CARD_Close (&CardFile);
CardError = CARD_Delete(slot, filename);
2008-12-24 08:58:23 +01:00
if (CardError)
{
2009-03-28 18:23:08 +01:00
ErrorPrompt("Unable to delete existing file!");
goto done;
2008-12-24 08:58:23 +01:00
}
}
2009-03-28 18:23:08 +01:00
// Create new file
memset(&CardStatus, 0, sizeof(card_stat));
CardError = CARD_Create (slot, filename, blocks, &CardFile);
if (CardError)
2008-12-24 08:58:23 +01:00
{
2009-03-28 18:23:08 +01:00
if (CardError == CARD_ERROR_INSSPACE)
ErrorPrompt("Insufficient space to create file!");
else
ErrorPrompt("Unable to create card file!");
goto done;
2008-12-24 08:58:23 +01:00
}
2008-09-02 03:57:21 +02:00
2009-03-28 18:23:08 +01:00
// Now, have an open file handle, ready to send out the data
2008-12-24 08:58:23 +01:00
CARD_GetStatus (slot, CardFile.filenum, &CardStatus);
CardStatus.icon_addr = 0x0;
CardStatus.icon_fmt = 2;
CardStatus.icon_speed = 1;
CardStatus.comment_addr = 2048;
CARD_SetStatus (slot, CardFile.filenum, &CardStatus);
2008-09-02 03:57:21 +02:00
2009-03-28 18:23:08 +01:00
bytesleft = blocks;
2008-12-24 08:58:23 +01:00
while (bytesleft > 0)
{
CardError =
2009-03-28 18:23:08 +01:00
CARD_Write (&CardFile, buf + byteswritten, SectorSize, byteswritten);
if(CardError)
{
ErrorPrompt("Error writing file!");
byteswritten = 0;
break;
}
2008-12-24 08:58:23 +01:00
bytesleft -= SectorSize;
byteswritten += SectorSize;
2009-03-28 18:23:08 +01:00
ShowProgress ("Saving...", byteswritten, blocks);
2008-12-24 08:58:23 +01:00
}
CARD_Close (&CardFile);
2009-03-28 18:23:08 +01:00
CancelAction();
2008-12-24 08:58:23 +01:00
2009-03-28 18:23:08 +01:00
if (byteswritten > 0 && GCSettings.VerifySaves)
2008-12-24 08:58:23 +01:00
{
2009-03-28 18:23:08 +01:00
// Verify the written file
if (!VerifyMCFile (buf, slot, filename, byteswritten) )
byteswritten = 0;
2008-09-02 03:57:21 +02:00
}
2009-03-28 18:23:08 +01:00
done:
CARD_Unmount (slot);
2008-09-02 03:57:21 +02:00
}
2009-03-28 18:23:08 +01:00
free(SysArea);
return byteswritten;
}
void SetMCSaveComments(char comments[2][32])
{
memcpy(savecomments, comments, 64);
2008-09-02 03:57:21 +02:00
}