Increased lenght of filenames in selector

Added raw backup and restore modes, as well as format mode.
Raw write still has the same issues as in ctr-gcs with official cards.

Flash ID is checked before raw restoring (can be bypassed if memory card is changed after selecting the image, however size check can't be bypassed). This behavior is intentional.

Changed STATUSOGC definition to gci.h (defining STATUSOGC makes GCMM use the normal CARD_GetStatus and CARD_SetStatus functions instead of the EX versions)
This commit is contained in:
sulokutdcmago 2012-09-05 11:14:16 +00:00
parent 3033611a67
commit 166ded3cf5
12 changed files with 936 additions and 104 deletions

View File

@ -181,10 +181,10 @@ static void __erase_callback(s32 chn,s32 result);
static void __dsp_donecallback(u32 chn);
static s32 __dounlock(s32 chn,u32 *key);
static s32 __card_readsegment(s32 chn,cardcallback callback);
static s32 __card_read(s32 chn,u32 address,u32 block_len,void *buffer,cardcallback callback);
s32 __card_read(s32 chn,u32 address,u32 block_len,void *buffer,cardcallback callback);
static s32 __card_updatefat(s32 chn,struct card_bat *fatblock,cardcallback callback);
static s32 __card_updatedir(s32 chn,cardcallback callback);
static s32 __card_write(s32 chn,u32 address,u32 block_len,void *buffer,cardcallback callback);
s32 __card_write(s32 chn,u32 address,u32 block_len,void *buffer,cardcallback callback);
static s32 __card_writepage(s32 chn,cardcallback callback);
static s32 __card_sectorerase(s32 chn,u32 sector,cardcallback callback);
static s32 __card_onreset(s32 final);
@ -278,7 +278,7 @@ static __inline__ struct card_bat* __card_getbatblock(card_block *card)
return card->curr_fat;
}
static s32 __card_sync(s32 chn)
s32 __card_sync(s32 chn)
{
s32 ret;
u32 level;
@ -1553,7 +1553,7 @@ static void __card_dirwritecallback(s32 chn,s32 result)
}
}
static s32 __card_write(s32 chn,u32 address,u32 block_len,void *buffer,cardcallback callback)
s32 __card_write(s32 chn,u32 address,u32 block_len,void *buffer,cardcallback callback)
{
s32 ret;
card_block *card = NULL;
@ -1574,7 +1574,7 @@ static s32 __card_write(s32 chn,u32 address,u32 block_len,void *buffer,cardcallb
return ret;
}
static s32 __card_read(s32 chn,u32 address,u32 block_len,void *buffer,cardcallback callback)
s32 __card_read(s32 chn,u32 address,u32 block_len,void *buffer,cardcallback callback)
{
s32 ret;
card_block *card = NULL;

View File

@ -607,7 +607,7 @@ s32 CARD_SetGamecode(const char *gamecode);
\return \ref card_errors "card error codes"
*/
s32 __card_getstatusex(s32 chn,s32 fileno,struct card_direntry *entry)
s32 __card_getstatusex(s32 chn,s32 fileno,struct card_direntry *entry);
/*! \fn s32 __card_setstatusex(s32 chn,s32 fileno,struct card_direntry *entry)
@ -618,7 +618,12 @@ s32 __card_getstatusex(s32 chn,s32 fileno,struct card_direntry *entry)
\return \ref card_errors "card error codes"
*/
s32 __card_setstatusex(s32 chn,s32 fileno,struct card_direntry *entry)
s32 __card_setstatusex(s32 chn,s32 fileno,struct card_direntry *entry);
// Raw read and write functions
s32 __card_read(s32 chn,u32 address,u32 block_len,void *buffer,cardcallback callback);
s32 __card_write(s32 chn,u32 address,u32 block_len,void *buffer,cardcallback callback);
s32 __card_sync(s32 chn);
#ifdef __cplusplus
}

View File

@ -6,6 +6,7 @@
* routines.
****************************************************************************/
#include <gccore.h>
#include <ogcsys.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -17,6 +18,7 @@
#include "mcard.h"
#include "sdsupp.h"
#include "bitmap.h"
#include "raw.h"
#ifdef HW_RVL
#include <wiiuse/wpad.h>
@ -34,13 +36,17 @@ FT_UInt glyph_index;
extern card_stat CardStatus;
extern int cancel;
extern int mode;
extern int MEM_CARD;
extern s32 MEM_CARD;
extern u16 bannerdata[CARD_BANNER_W*CARD_BANNER_H] ATTRIBUTE_ALIGN (32);
extern u8 bannerdataCI[CARD_BANNER_W*CARD_BANNER_H] ATTRIBUTE_ALIGN (32);
extern u8 icondata[1024] ATTRIBUTE_ALIGN (32);
extern u16 icondataRGB[1024] ATTRIBUTE_ALIGN (32);
extern u16 tlut[256] ATTRIBUTE_ALIGN (32);
extern u16 tlutbanner[256] ATTRIBUTE_ALIGN (32);
extern Header cardheader;
extern s32 memsize, sectsize;
extern syssramex *sramex;
extern u8 imageserial[12];
static int fonthi, fontlo;
@ -343,7 +349,7 @@ int SelectMode ()
}
return 100;
}
if (PAD_ButtonsHeld (0) & PAD_TRIGGER_Z)
if (PAD_ButtonsHeld (0) & PAD_TRIGGER_Z)//Delete mode
{
while ((PAD_ButtonsDown (0) & PAD_BUTTON_B))
{
@ -351,7 +357,7 @@ int SelectMode ()
}
return 200;
}
if (PAD_ButtonsHeld (0) & PAD_BUTTON_Y)
if (PAD_ButtonsHeld (0) & PAD_BUTTON_Y)//Backup mode
{
while ((PAD_ButtonsDown (0) & PAD_BUTTON_Y))
{
@ -359,7 +365,7 @@ int SelectMode ()
}
return 300;
}
if (PAD_ButtonsHeld (0) & PAD_BUTTON_X)
if (PAD_ButtonsHeld (0) & PAD_BUTTON_X)//Restore mode
{
while ((PAD_ButtonsDown (0) & PAD_BUTTON_X))
{
@ -367,7 +373,7 @@ int SelectMode ()
}
return 400;
}
if (PAD_ButtonsHeld (0) & PAD_BUTTON_START)
if (PAD_ButtonsHeld (0) & PAD_BUTTON_START)//Exit
{
while ((PAD_ButtonsDown (0) & PAD_BUTTON_START))
{
@ -375,7 +381,7 @@ int SelectMode ()
}
return 500;
}
if (PAD_ButtonsHeld (0) & PAD_TRIGGER_R)
if (PAD_ButtonsHeld (0) & PAD_TRIGGER_R)//Backup all mode
{
while ((PAD_ButtonsDown (0) & PAD_TRIGGER_R))
{
@ -383,7 +389,32 @@ int SelectMode ()
}
return 600;
}
while (PAD_ButtonsHeld (0) & PAD_TRIGGER_L)
{
if (PAD_ButtonsHeld (0) & PAD_BUTTON_Y){//Raw backup mode
while ((PAD_ButtonsDown (0) & PAD_TRIGGER_L) || (PAD_ButtonsDown (0) & PAD_BUTTON_Y))
{
VIDEO_WaitVSync ();
}
return 700;
}
if (PAD_ButtonsHeld (0) & PAD_BUTTON_X){//Raw restore mode
while ((PAD_ButtonsDown (0) & PAD_TRIGGER_L) || (PAD_ButtonsDown (0) & PAD_BUTTON_X))
{
VIDEO_WaitVSync ();
}
return 800;
}
if (PAD_ButtonsHeld (0) & PAD_TRIGGER_Z){//Format card mode
while ((PAD_ButtonsDown (0) & PAD_TRIGGER_L) || (PAD_ButtonsDown (0) & PAD_TRIGGER_Z))
{
VIDEO_WaitVSync ();
}
return 900;
}
}
#ifdef HW_RVL
if (WPAD_ButtonsHeld (0) & WPAD_BUTTON_A)
{
@ -395,13 +426,13 @@ int SelectMode ()
}
if (WPAD_ButtonsHeld (0) & WPAD_BUTTON_2)
{
while ((WPAD_ButtonsDown (0) & WPAD_BUTTON_2))
while ((WPAD_ButtonsDown (0) & WPAD_BUTTON_2))//Delete mode
{
VIDEO_WaitVSync ();
}
return 200;
}
if (WPAD_ButtonsHeld (0) & WPAD_BUTTON_MINUS)
if (WPAD_ButtonsHeld (0) & WPAD_BUTTON_MINUS)//Backup mode
{
while ((WPAD_ButtonsDown (0) & WPAD_BUTTON_MINUS))
{
@ -409,7 +440,7 @@ int SelectMode ()
}
return 300;
}
if (WPAD_ButtonsHeld (0) & WPAD_BUTTON_PLUS)
if (WPAD_ButtonsHeld (0) & WPAD_BUTTON_PLUS)//Restore mode
{
while ((WPAD_ButtonsDown (0) & WPAD_BUTTON_PLUS))
{
@ -417,7 +448,7 @@ int SelectMode ()
}
return 400;
}
if (WPAD_ButtonsHeld (0) & WPAD_BUTTON_HOME)
if (WPAD_ButtonsHeld (0) & WPAD_BUTTON_HOME)//Exit
{
while ((WPAD_ButtonsDown (0) & WPAD_BUTTON_HOME))
{
@ -425,7 +456,7 @@ int SelectMode ()
}
return 500;
}
if (WPAD_ButtonsHeld (0) & WPAD_BUTTON_1)
if (WPAD_ButtonsHeld (0) & WPAD_BUTTON_1)//Backup all mode
{
while ((WPAD_ButtonsDown (0) & WPAD_BUTTON_1))
{
@ -433,6 +464,32 @@ int SelectMode ()
}
return 600;
}
while (WPAD_ButtonsHeld (0) & WPAD_BUTTON_B)
{
if (WPAD_ButtonsHeld (0) & WPAD_BUTTON_MINUS){//Raw backup mode
while ((WPAD_ButtonsDown (0) & WPAD_BUTTON_B) || (WPAD_ButtonsDown (0) & WPAD_BUTTON_MINUS))
{
VIDEO_WaitVSync ();
}
return 700;
}
if (WPAD_ButtonsHeld (0) & WPAD_BUTTON_PLUS){//Raw restore mode
while ((WPAD_ButtonsDown (0) & WPAD_BUTTON_B) || (WPAD_ButtonsDown (0) & WPAD_BUTTON_PLUS))
{
VIDEO_WaitVSync ();
}
return 800;
}
if (WPAD_ButtonsHeld (0) & WPAD_BUTTON_2){//Format card mode
while ((WPAD_ButtonsDown (0) & WPAD_BUTTON_B) || (WPAD_ButtonsDown (0) & WPAD_BUTTON_2))
{
VIDEO_WaitVSync ();
}
return 900;
}
}
if (power)
{
PowerOff();
@ -515,6 +572,43 @@ int WaitButtonAB ()
#endif
}
/****************************************************************************
* Wait for user to press A or B. Returns 0 = Z/2; 1 = A
****************************************************************************/
int WaitButtonAZ ()
{
#ifdef HW_RVL
u32 gc_btns, wm_btns;
while ( (PAD_ButtonsDown (0) & (PAD_BUTTON_A | PAD_TRIGGER_Z))
|| (WPAD_ButtonsDown(0) & (WPAD_BUTTON_A | WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A | WPAD_CLASSIC_BUTTON_ZR | WPAD_CLASSIC_BUTTON_ZL))
) VIDEO_WaitVSync();
while (1)
{
gc_btns = PAD_ButtonsDown (0);
wm_btns = WPAD_ButtonsDown (0);
if ( (gc_btns & PAD_BUTTON_A) || (wm_btns & (WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A)) )
return 1;
else if ( (gc_btns & PAD_TRIGGER_Z) || (wm_btns & (WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_ZR | WPAD_CLASSIC_BUTTON_ZL)) )
return 0;
}
#else
u32 gc_btns;
while ( (PAD_ButtonsDown (0) & (PAD_BUTTON_A | PAD_TRIGGER_Z)) ) VIDEO_WaitVSync();
while (1)
{
gc_btns = PAD_ButtonsDown (0);
if ( gc_btns & PAD_BUTTON_A )
return 1;
else if ( gc_btns & PAD_TRIGGER_Z )
return 0;
}
#endif
}
/**
@ -551,7 +645,26 @@ int WaitPromptChoice ( char *msg, char *bmsg, char *amsg)
return ret;
}
/****************************************************************************
* Show a prompt with choice of two options. Returns 1 if A button was pressed
and 0 if Z/2 button was pressed.
****************************************************************************/
int WaitPromptChoiceAZ ( char *msg, char *bmsg, char *amsg)
{
char txt[80];
int ret;
#ifdef HW_RVL
sprintf (txt, "Z/2 = %s : A = %s", bmsg, amsg);
#else
sprintf (txt, "Z = %s : A = %s", bmsg, amsg);
#endif
writeStatusBar(msg, txt);
ret = WaitButtonAZ ();
//Clear the text
writeStatusBar("","");
return ret;
}
void DrawLineFast (int startx, int endx, int y, u8 r, u8 g, u8 b)
{
int width;
@ -567,6 +680,73 @@ void DrawLineFast (int startx, int endx, int y, u8 r, u8 g, u8 b)
xfb[whichfb][offset++] = colour;
}
void showCardInfo(int sel){
//clear right pane, but just the card info
int bgcolor = getcolour(84,174,211);
DrawBoxFilled(375, 165, 605, 390, bgcolor);
int y = 190, x = 375;
int err;
char txt[1024];
int i;
char temp[5];
//START card image info START
//put block 1 in cardheader
SDLoadCardImageHeader((char*)filelist[sel]);
//get the serial
getserial(imageserial);
sprintf(txt, "Card image flash ID");
DrawText(x, y, txt);
y += 20;
sprintf(txt, "%02X", imageserial[0]);
for (i=1; i<11; i++){
sprintf(temp, "%02X", imageserial[i]);
strcat(txt, temp);
}
DrawText(x,y,txt);
y+=20;
sprintf(txt, "Size: %d blocks", (cardheader.SizeMb[1]*16)-5);
DrawText(x, y, txt);
y+=40;
//END card image info END
//START real card info START
err = MountCard(MEM_CARD);
if (err < 0)
{
WaitCardError("CardMount", err);
return; /*** Unable to mount the card ***/
}
sramex = __SYS_LockSramEx();
__SYS_UnlockSramEx(0);
if (!MEM_CARD)
{
sprintf(txt, "Slot A card flash ID:");
}else
{
sprintf(txt, "Slot B card flash ID:");
}
DrawText(x,y,txt);
y+=20;
sprintf(txt, "%02X", sramex->flash_id[MEM_CARD][0]);
for (i=1; i<sizeof(sramex->flash_id[MEM_CARD])-1; i++){
sprintf(temp, "%02X", sramex->flash_id[MEM_CARD][i]);
strcat(txt, temp);
}
DrawText(x,y,txt);
y+=20;
sprintf(txt, "Size: %d blocks", (memsize*16)-5);
DrawText(x,y,txt);
//END real card info END
}
void showSaveInfo(int sel)
{
int y = 160, x = 375, j;
@ -714,12 +894,15 @@ void showSaveInfo(int sel)
}
static void ShowFiles (int offset, int selection, int upordown) {
// saveinfo 1: shows saveinfo (for gci/sav/gcs backup/restore)
// saveinfo 0: retrieves .raw, .gcp and .mci
static void ShowFiles (int offset, int selection, int upordown, int saveinfo) {
int i, j; //j helps us determine which entry to highlight
char text[23];
int ypos;
int w;
//int textlen = 22;
int textlen = 32;
//If the filelist offset changed, we have to redraw every entry
//This tracks switching "pages" of files in the list
if (offsetchanged) {
@ -738,8 +921,8 @@ static void ShowFiles (int offset, int selection, int upordown) {
for (i = offset; i < (offset + PAGESIZE) && (i < maxfile); i++){
//changed this to limit characters shown in filename since display gets weird
//if we let the entire filename appear
strncpy (text, (char*)filelist[i], 22);
text[22] = 0;
strncpy (text, (char*)filelist[i], textlen);
text[textlen] = 0;
if (j == (selection - offset)){
/*** Highlighted text entry ***/
for (w = 0; w < 20; w++){
@ -763,7 +946,11 @@ static void ShowFiles (int offset, int selection, int upordown) {
}
//set black font - info on right side of screen is printed in showSaveInfo
setfontcolour (28, 28, 28);
showSaveInfo(selection);
if (saveinfo){
showSaveInfo(selection);
}else if (!saveinfo){
showCardInfo(selection);
}
}
else {
//Filelist offset didn't change yet; Only redraw what matters
@ -773,8 +960,8 @@ static void ShowFiles (int offset, int selection, int upordown) {
setfontcolour (0xff, 0xff, 0xff);
//user just pressed up
if (upordown == 1) {
strncpy (text, (char*)filelist[selection+1], 22);
text[22] = 0;
strncpy (text, (char*)filelist[selection+1], textlen);
text[textlen] = 0;
for (w = 0; w < 20; w++){
DrawLineFast (35, 330, (((selection-offset)+1) * 20) + (ypos - 14) + w, 84, 174,211);
}
@ -782,8 +969,8 @@ static void ShowFiles (int offset, int selection, int upordown) {
}
//user just pressed down
else if (upordown == 2) {
strncpy (text, (char*)filelist[selection-1], 22);
text[22] = 0;
strncpy (text, (char*)filelist[selection-1], textlen);
text[textlen] = 0;
for (w = 0; w < 20; w++){
DrawLineFast (35, 330, (((selection-offset)-1) * 20) + (ypos - 14) + w, 84, 174,211);
}
@ -793,14 +980,18 @@ static void ShowFiles (int offset, int selection, int upordown) {
//appear faster - without it the highlight box glides too much
ShowScreen();
setfontcolour (28, 28, 28);
strncpy (text, (char*)filelist[selection], 22);
text[22] = 0;
strncpy (text, (char*)filelist[selection], textlen);
text[textlen] = 0;
//the current spot is always highlighted
for (w = 0; w < 20; w++){
DrawLineFast (35, 330, ((selection-offset) * 20) + (ypos - 14) + w, 0xff, 0xff, 0xff);
}
DrawText (35, ((selection-offset) * 20) + ypos, text);
showSaveInfo(selection);
if (saveinfo){
showSaveInfo(selection);
}else if (!saveinfo){
showCardInfo(selection);
}
}
//Need this to show info update from showSaveInfo
ShowScreen();
@ -841,8 +1032,10 @@ static void ShowFiles (int offset, int selection, int upordown) {
*
* Let's the user select a file to backup or restore.
* Returns index of file chosen.
* saveinfo 1: enables getting and displaying saveinformation
* saveinfo 0: disables save information (for raw mode)
****************************************************************************/
int ShowSelector ()
int ShowSelector (int saveinfo)
{
u32 p;
#ifdef HW_RVL
@ -858,7 +1051,7 @@ int ShowSelector ()
{
if (redraw)
{
ShowFiles (offset, selection, upordown);
ShowFiles (offset, selection, upordown, saveinfo);
redraw = 0;
}
p = PAD_ButtonsDown (0);

View File

@ -25,7 +25,8 @@ void ShowScreen ();
void ShowAction (char *msg);
void WaitPrompt (char *msg);
int WaitPromptChoice ( char *msg, char *bmsg, char *amsg);
int ShowSelector ();
int WaitPromptChoiceAZ ( char *msg, char *bmsg, char *amsg);
int ShowSelector (int saveinfo);
int SelectMode ();
void writeStatusBar(char *line1, char *line2);
void clearLeftPane();

View File

@ -8,6 +8,13 @@
#include <gccore.h>
// If STATUSOGC defined uses CARD_GetStatus and CARD_SetStatus
// Default (undefined) uses __card_getstatusex and __card_setstatusex
// Diference: when restoring a savegame with the ex functions original time, copy counter, etc are preserved
// Also, libogc creates card entries with time since 1970 and gamecube uses time since 2000... thus libogc adds 30 years!
//#define STATUSOGC
typedef struct {
u8 gamecode[4];
u8 company[2];

View File

@ -28,6 +28,8 @@
#endif
#include "mcard.h"
#include "card.h"
#include "raw.h"
#include "sdsupp.h"
#include "freetype.h"
#include "bitmap.h"
@ -45,7 +47,9 @@ static int vmode_60hz = 0;
extern u8 filelist[1024][1024];
extern bool offsetchanged;
int MEM_CARD = CARD_SLOTB;
s32 MEM_CARD = CARD_SLOTB;
extern syssramex *sramex;
extern u8 imageserial[12];
static void updatePAD()
{
@ -281,7 +285,7 @@ void SD_BackupMode ()
}
else
{
selected = ShowSelector ();
selected = ShowSelector (1);
if (cancel)
{
WaitPrompt ("Backup action cancelled!");
@ -378,7 +382,7 @@ void SD_RestoreMode ()
clearRightPane();
DrawText(390,130,"R e s t o r e M o d e");
writeStatusBar("Pick a file using UP or DOWN", "Press A to restore to Memory Card ") ;
files = SDGetFileList ();
files = SDGetFileList (1);
if (!files)
{
WaitPrompt ("No saved games in SD Card to restore !");
@ -386,7 +390,7 @@ void SD_RestoreMode ()
else
{
selected = ShowSelector ();
selected = ShowSelector (1);
if (cancel)
{
@ -413,56 +417,87 @@ void SD_RestoreMode ()
}
}
}
}
/****************************************************************************
* TestMode
*
* RawBackupMode -SD Mode
*
* Perform backup of full memory card (in raw format) to a SD Card.
****************************************************************************/
/*void testMode (){
void SD_RawBackupMode ()
{
s32 writen = 0;
char msg[64];
clearRightPane();
DrawText(50, 230, "R A W B a c k u p M o d e");
writeStatusBar("Reading memory card... ", "");
clearRightPane();
DrawText(390,130,"T e s t M o d e");
if (BackupRawImage(MEM_CARD, &writen) == 1)
{
sprintf(msg, "Backup complete! Wrote %d bytes to SD",writen);
WaitPrompt(msg);
}else{
WaitPrompt("Backup failed!");
}
int bytestodo;
clearRightPane();
ShowAction ("Reading From MC SLOT B");
bytestodo = testreadimage (MEM_CARD);
if (bytestodo){
ShowAction ("Saving to SD CARD");
if (SDSaveraw ()){
WaitPrompt ("Backup complete");
}
else{
WaitPrompt ("Backup failed");
}
}
else{
WaitPrompt ("Error reading MC file");
}
// writeStatusBar("Pick a file using UP or DOWN", "Press A to restore to Memory Card ") ;
//WaitPrompt ("No saved games in SD Card to restore !");
//ShowAction ("Reading from SD Card");
}*/
/* Reboot the system */
/*void Reboot() {
*((volatile u32*)0xCC003024) = 0x00000000;
}
*/
/****************************************************************************
* RawRestoreMode
*
* Restore a full raw backup to Memory Card from SD Card
****************************************************************************/
void SD_RawRestoreMode ()
{
int files;
int selected;
char msg[64];
s32 writen = 0;
int i;
clearRightPane();
DrawText(400,130,"R A W R e s t o r e");
DrawText(450,150,"M o d e");
writeStatusBar("Pick a file using UP or DOWN", "Press A to restore to Memory Card ");
files = SDGetFileList (0);
if (!files)
{
WaitPrompt ("No raw backups in SD Card to restore !");
}else
{
selected = ShowSelector (0);
if (cancel)
{
WaitPrompt ("Restore action cancelled !");
return;
}
else
{
//Now imageserial and sramex.flash_id[MEM_CARD] variables should hold the proper information
for (i=0;i<12;i++){
if (imageserial[i] != sramex->flash_id[MEM_CARD][i]){
WaitPrompt ("Card and image flash ID don't match !");
return;
}
}
ShowAction ("Reading from SD Card...");
if (RestoreRawImage(MEM_CARD, (char*)filelist[selected], &writen) == 1)
{
sprintf(msg, "Restore complete! Wrote %d bytes to card",writen);
WaitPrompt(msg);
}else
{
WaitPrompt("Restore failed!");
}
}
}
}
/****************************************************************************
* Main
****************************************************************************/
@ -492,10 +527,11 @@ int main ()
{
/*** Select Mode ***/
ClearScreen();
setfontsize (FONT_SIZE);
cancel = 0;/******a global value to track action aborted by user pressing button B********/
mode = SelectMode ();
#ifdef HW_RVL
if (mode != 100 && mode != 500){
if ((mode != 500 ) && (mode != 100)){
if (WaitPromptChoice ("Please select a memory card slot", "Slot B", "Slot A") == 1)
{
MEM_CARD = CARD_SLOTA;
@ -540,8 +576,53 @@ int main ()
if (have_sd) SD_BackupModeAllFiles();
else WaitPrompt("Reboot aplication with an SD card");
break;
case 700 : //Raw backup mode
if (have_sd)
{
DrawText(50, 230, "R A W B a c k u p M o d e");
SD_RawBackupMode();
}else
{
WaitPrompt("Reboot aplication with an SD card");
}
break;
case 800 : //Raw restore mode
//These two lines are a work around for the second call of CARD_Probe to detect a newly inserted memory card
CARD_Probe(MEM_CARD);
VIDEO_WaitVSync ();
if (CARD_Probe(MEM_CARD) > 0)
{
if (have_sd) SD_RawRestoreMode();
else WaitPrompt("Reboot aplication with an SD card");
}else if (MEM_CARD)
{
WaitPrompt("Please insert a memory card in slot B");
}else
{
WaitPrompt("Please insert a memory card in slot A");
}
break;
case 900 : //Format card mode
//These two lines are a work around for the second call of CARD_Probe to detect a newly inserted memory card
CARD_Probe(MEM_CARD);
VIDEO_WaitVSync ();
if (CARD_Probe(MEM_CARD) > 0)
{
DrawText(50, 230, "F o r m a t C a r d M o d e");
clearRightPane();
MC_FormatMode(MEM_CARD);
}else if (MEM_CARD)
{
WaitPrompt("Please insert a memory card in slot B");
}else
{
WaitPrompt("Please insert a memory card in slot A");
}
break;
}
offsetchanged = true;
}
while (1);

View File

@ -22,13 +22,6 @@
#include "gci.h"
#include "freetype.h"
// If STATUSOGC defined uses CARD_GetStatus and CARD_SetStatus
// Default (undefined) uses __card_getstatusex and __card_setstatusex
// Diference: when restoring a savegame with the ex functions original time, copy counter, etc are preserved
// Also, libogc creates card entries with time since 1970 and gamecube uses time since 2000... thus libogc adds 30 years!
//#define STATUSOGC
/*** Memory Card Work Area ***/
static u8 SysArea[CARD_WORKAREA] ATTRIBUTE_ALIGN (32);
@ -61,20 +54,21 @@ static card_file CardFile;
static card_stat CardStatus;
static int cardcount = 0;
static u8 permission;
s32 memsize, sectsize;
GCI gci;
/*---------------------------------------------------------------------------------
This function is called if a card is physically removed
---------------------------------------------------------------------------------*/
void card_removed(s32 chn,s32 result)
{
if (chn == CARD_SLOTA)
printf("Card was removed from slot A");
else
printf("Card was removed from slot B");
if (chn == CARD_SLOTA){
//printf("Card was removed from slot A");
}
else{
//printf("Card was removed from slot B");
}
CARD_Unmount(chn);
}
@ -89,8 +83,7 @@ int MountCard(int cslot)
{
s32 ret = -1;
int tries = 0;
int isMounted, memsize, sectsize;
char msg[64];
int isMounted;
// Mount the card, try several times as they are tricky
while ( (tries < 10) && (ret < 0))
@ -684,7 +677,7 @@ void MC_DeleteMode(int slot)
while(1)
{
// TODO: implement showselector
selected = ShowSelector();
selected = ShowSelector(1);
if (cancel)
{
WaitPrompt ("Delete action cancelled !");
@ -728,4 +721,58 @@ void MC_DeleteMode(int slot)
offsetchanged = true;
}
}
}
}
void MC_FormatMode(s32 slot)
{
int erase = 1;
int err;
//0 = B wass pressed -> ask again
if (!slot){
erase = WaitPromptChoice("Are you sure you want to format memory card in slot A?", "Format", "Cancel");
}else{
erase = WaitPromptChoice("Are you sure you want to format memory card in slot B?", "Format", "Cancel");
}
if (!erase){
if (!slot){
erase = WaitPromptChoiceAZ("All contents of memory card in slot A will be erased, continue?", "Format", "Cancel");
}else{
erase = WaitPromptChoiceAZ("All contents of memory card in slot B will be erased, continue?", "Format", "Cancel");
}
if (!erase)
{
/*** Try to mount the card ***/
err = MountCard(slot);
if (err < 0)
{
WaitCardError("MCFormat Mount", err);
return; /*** Unable to mount the card ***/
}
ShowAction("Formatting card...");
/*** Format the card ***/
CARD_Format(slot);
usleep(1000*1000);
/*** Try to mount the card ***/
err = MountCard(slot);
if (err < 0)
{
WaitCardError("MCFormat Mount", err);
return; /*** Unable to mount the card ***/
}else
{
WaitPrompt("Format completed successfully");
}
CARD_Unmount(slot);
return;
}
}
WaitPrompt("Format operation cancelled");
return;
}

View File

@ -12,7 +12,8 @@ void CardListFiles ();
int CardReadFileHeader (int slot, int id);
int CardReadFile (int slot, int id);
int CardWriteFile (int slot);
void MC_DeleteMode(int slot);
void MC_DeleteMode(int slot);
void MC_FormatMode(s32 slot);
void WaitCardError(char *src, int error);
static int OFFSET = 0;
#endif

368
source/raw.c Normal file
View File

@ -0,0 +1,368 @@
#include <gccore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <malloc.h>
#include <sys/dir.h>
#include <dirent.h>
#include <ogcsys.h>
#include "sdsupp.h"
#include "card.h"
#include "mcard.h"
#include "gci.h"
#include "freetype.h"
#include "raw.h"
u8 *CardBuffer = 0;
s8 read_data = 0;
Header cardheader;
extern syssram* __SYS_LockSram();
extern syssramex* __SYS_LockSramEx();
extern u32 __SYS_UnlockSram(u32 write);
extern u32 __SYS_UnlockSramEx(u32 write);
syssramex *sramex;
u8 imageserial[12];
//code from tueidj's Devolution
void getserial(u8 *serial)
{
int i;
uint64_t rand;
// rand() taken from K&R, lol
rand = cardheader.formatTime; // seed
for (i=0; i < 12; i++)
{
rand = (rand * 1103515245 + 12345) >> 16;
cardheader.serial[i] -= rand;
rand = ((uint32_t)rand * 1103515245 + 12345) >> 16;
rand &= 0x7FFF;
serial[i] = cardheader.serial[i];
}
serial[13]="\0";
}
void ClearFlashID(s32 chn){
int i;
sramex = __SYS_LockSramEx();
for (i=0; i<12; i++){
sramex->flash_id[chn][i] = 0x00;
}
__SYS_UnlockSramEx(1);
}
void _read_callback(s32 chn,s32 result)
{
read_data =1;
}
void _write_callback(s32 chn,s32 result)
{
read_data =1;
}
//output is 29 char long
void time2name(char *name)
{
int month, day, year, hour, min, sec;
month = day = year = hour = min = sec = 0;
char monthstr[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
"Aug", "Sep", "Oct", "Nov", "Dec"
};
// Taken from void SecondsToDate(int seconds, int *pYear, int *pMonth, int *pDay)
// Calculates year month and day since jan 1, 1970 from (t) seconds
// Reference: Fliegel, H. F. and van Flandern, T. C. (1968).
// Communications of the ACM, Vol. 11, No. 10 (October, 1968).
// Original code in Fortran
int I, J, K, L, N;
u32 t = time(NULL);
L = t / 86400 + 2509157;
N = 4 * L / 146097;
L = L - (146097 * N + 3) / 4;
I = 4000 * (L + 1) / 1461001;
L = L - 1461 * I / 4 + 31;
J = 80 * L / 2447;
K = L - 2447 * J / 80;
L = J / 11;
J = J + 2 - 12 * L;
I = 100 * (N - 49) + I + L;
year = I;
month = J;
day = K;
sec = t % 60;
t /= 60;
min = t % 60;
t /= 60;
hour = t % 24;
sprintf(name, "%04d_%02d%s_%02d_%02d-%02d-%02d", year, month, monthstr[month-1], day, hour, min, sec);
}
s8 BackupRawImage(s32 slot, s32 *bytes_writen )
{
int err;
char filename[1024];
char msg[1024];
FILE* dumpFd = 0;
u32 SectorSize = 0;
s32 BlockCount = 0;
CARD_Init(NULL,NULL);
EXI_ProbeReset();
err = MountCard(slot);
if (err < 0)
{
WaitCardError("BakRaw", err);
return -1; /*** Unable to mount the card ***/
}
usleep(10*1000);
err = CARD_GetSectorSize(slot,&SectorSize);
if(err < 0 )
{
WaitCardError("BakRaw Sectsize", err);
return -1;
}
err = CARD_GetBlockCount(slot,(u32*)&BlockCount);
if(err < 0 )
{
WaitCardError("BakRaw Blockcount", err);
return -1;
}
CardBuffer = (u8*)memalign(32,SectorSize*BlockCount);
if(CardBuffer == NULL)
{
//printf("failed to malloc memory. fail\n");
WaitPrompt("BackRaw: Failed to malloc memory.");
return -1;
}
s32 current_block = 0;
int read = 0;
s32 writen = 0;
char name[64];
int filenumber = 1;
time2name(name);
sprintf (filename, "fat:/%s/Backup_%s.raw", MCSAVES, name);
//not really needed because the filename has seconds in it and the same filename will "never" happen
while (file_exists(filename)){
sprintf (filename, "fat:/%s/Backup_%s_%02d.raw", MCSAVES, name, filenumber);
filenumber++;
}
dumpFd = fopen(filename,"wb");
if (dumpFd == NULL)
{
//printf("can not create file on SD\n");
WaitPrompt("BackRaw: cannot create file on SD.");
return -1;
}
//printf("dumping...\n");
while( 1 )
{
read_data = 0;
//printf("\rReading : %u bytes of %u (block %d)...",read,BlockCount*SectorSize,current_block);
sprintf(msg, "Reading : %u bytes of %u (block %d)...",read,BlockCount*SectorSize,current_block);
writeStatusBar(msg, "");
if( (err != 0) || current_block >= BlockCount)
break;
err = __card_read(slot,SectorSize*current_block,SectorSize,CardBuffer+SectorSize*current_block,_read_callback);
if(err == 0)
{
while(read_data == 0)
usleep(1*1000); //sleep untill the read is done
read = read + SectorSize;
current_block++;
}
else
{
//printf("\nerror reading data : %d...\n",err);
fclose(dumpFd);
WaitCardError("BakRaw __read", err);
return -1;
}
}
//printf("\n");
u8* ptr = (u8*)CardBuffer;
for(writen = 0;writen < read;writen=writen+16384)
{
fwrite((u8*)ptr+writen,16384,1,dumpFd);
//printf("\rWriting : %u bytes of %u",writen+16384,read);
sprintf(msg, "Writing : %u bytes of %u",writen+16384,read);
writeStatusBar(msg, "");
}
fclose(dumpFd);
if(bytes_writen != NULL)
*bytes_writen = writen;
return 1;
}
s8 RestoreRawImage( s32 slot, char *sdfilename, s32 *bytes_writen )
{
FILE *dumpFd = 0;
char filename[1024];
char msg[256];
int err;
u32 SectorSize = 0;
s32 BlockCount = 0;
s32 current_block = 0;
s32 writen = 0;
CARD_Init(NULL,NULL);
EXI_ProbeReset();
err = MountCard(slot);
if (err < 0)
{
WaitCardError("RestRaw", err);
return -1; /*** Unable to mount the card ***/
}
usleep(10*1000);
err = CARD_GetSectorSize(slot,&SectorSize);
if(err < 0 )
{
WaitCardError("RestRaw Sectsize", err);
return -1;
}
err = CARD_GetBlockCount(slot,(u32*)&BlockCount);
if(err < 0 )
{
WaitCardError("RestRaw Blockcount", err);
return -1;
}
CardBuffer = (u8*)memalign(32,SectorSize*BlockCount);
if(CardBuffer == NULL)
{
//printf("failed to malloc memory. fail\n");
WaitPrompt("RestRaw: Failed to malloc memory.");
return -1;
}
/*** Make fullpath filename ***/
sprintf (filename, "fat:/%s/%s", MCSAVES, sdfilename);
/*** Open the SD Card file ***/
dumpFd = fopen ( filename , "rb" );
if (dumpFd <= 0)
{
free(CardBuffer);
sprintf(msg, "Couldn't open %s", filename);
WaitPrompt (msg);
return -1;
}
//first read the content of the SD dump into the buffer.
u32 lSize;
fseek (dumpFd , 0 , SEEK_END);
lSize = ftell (dumpFd);
rewind (dumpFd);
if(lSize != BlockCount*SectorSize)
{
//check for mci raw image
if((lSize-64) != BlockCount*SectorSize){
//incorrect dump size D:<
fclose(dumpFd);
free(CardBuffer);
WaitPrompt ("Card and image sizes differ");
return -1;
}
}
//printf("are you -SURE- you want to recover? a faulty backup or even a program\nfailure will corrupt the memory card!\n");
int erase = 1;
//0 = B wass pressed -> ask again
if (!slot){
erase = WaitPromptChoice("Are you -SURE- you want to restore to memory card in slot A?", "Restore", "Cancel");
}else{
erase = WaitPromptChoice("Are you -SURE- you want to restore to memory card in slot B?", "Restore", "Cancel");
}
if (!erase)
{
if (!slot){
erase = WaitPromptChoiceAZ("All contents of memory card in slot A will be overwritten, continue?", "Restore", "Cancel");
}else{
erase = WaitPromptChoiceAZ("All contents of memory card in slot B will be erased, continue?", "Restore", "Cancel");
}
if (!erase)
{
if ((lSize-64) == BlockCount*SectorSize) fseek(dumpFd, 64, SEEK_SET);
fread(CardBuffer,BlockCount*0x2000,1,dumpFd);
fclose(dumpFd);
// Test code to see if raw image is correctly read
FILE *test = 0;
test = fopen ( "fat:/test.bin" , "wb" );
fwrite (CardBuffer , 1 , BlockCount*0x2000 , test );
fclose (test);
//printf("writing data to memory card...\n");
ShowAction ("Writing data to memory card...");
s32 upblock = 0;
s32 write_len = SectorSize;
//s32 write_len = 0x80;//pagesize o memory card
while( 1 )
{
//printf("\rWriting... : %d of %d (block %d)",writen,BlockCount*SectorSize,current_block);
sprintf(msg, "Writing... : Block %d (%d of %d)",current_block, writen,BlockCount*SectorSize);
ShowAction (msg);
//gprintf("\rWriting... : %d of %d (block %d of %d)",writen,BlockCount*SectorSize,current_block,BlockCount);
read_data = 0;
if( (err != 0) || current_block >= BlockCount || writen == BlockCount*SectorSize)
break;
//s32 __card_write(s32 chn,u32 address,u32 block_len,void *buffer,cardcallback callback)
err = __card_write(slot,writen,write_len,CardBuffer+writen,_read_callback);
if(err == 0)
{
while(read_data == 0)
usleep(1*1000); //sleep untill the write is done which sadly takes alot longer then read
__card_sync(slot);
writen = writen + write_len;
upblock=upblock+write_len;
if(upblock == SectorSize)
{
current_block++;
upblock = 0;
}
}
else
{
fclose(dumpFd);
free(CardBuffer);
//printf("\nerror writing data(%d) Memory card could be corrupt now!!!\n",err);
sprintf(msg, "error writing data(%d) Memory card could be corrupt now!!!",err);
WaitPrompt (msg);
return -1;
}
}
//printf("\n");
//gprintf("\n");
if(bytes_writen != NULL)
*bytes_writen = writen;
return 1;
}
}
return -1;
}

22
source/raw.h Normal file
View File

@ -0,0 +1,22 @@
typedef struct {
//Offset Size Description
// Serial in libogc
u8 serial[12]; //0x0000 12 ?
u64 formatTime; //0x000c 8 time of format (OSTime value)
u32 SramBias; //0x0014 4 sram bias at time of format
u32 SramLang; //0x0018 4 sram language
u8 Unk2[4]; //0x001c 4 ? almost always 0
// end Serial in libogc
u8 deviceID[2]; //0x0020 2 0 if formated in slot A 1 if formated in slot B
u8 SizeMb[2]; //0x0022 2 size of memcard in Mbits
u16 Encoding; //0x0024 2 encoding (ASCII or japanese)
u8 Unused1[468]; //0x0026 468 unused (0xff)
u16 UpdateCounter; //0x01fa 2 update Counter (?, probably unused)
u16 Checksum; //0x01fc 2 Additive Checksum
u16 Checksum_Inv; //0x01fe 2 Inverse Checksum
u8 Unused2[7680]; //0x0200 0x1e00 unused (0xff)
} __attribute__((__packed__)) Header;
void getserial(u8 *serial);
s8 BackupRawImage(s32 slot, s32 *bytes_writen);
s8 RestoreRawImage(s32 slot, char *sdfilename, s32 *bytes_writen);

View File

@ -15,6 +15,8 @@
#include "freetype.h"
#include "gci.h"
#include "mcard.h"
#include "card.h"
#include "raw.h"
#define PAGESIZE 20
#define PADCAL 80
@ -25,6 +27,7 @@
/*** Memory Card FileBuffer ***/
#define MAXFILEBUFFER (1024 * 2048) /*** 2MB Buffer ***/
extern u8 FileBuffer[MAXFILEBUFFER] ATTRIBUTE_ALIGN (32);
extern Header cardheader;
extern u8 CommentBuffer[64] ATTRIBUTE_ALIGN (32);
extern u16 bannerdata[CARD_BANNER_W*CARD_BANNER_H] ATTRIBUTE_ALIGN (32);
extern u8 bannerdataCI[CARD_BANNER_W*CARD_BANNER_H] ATTRIBUTE_ALIGN (32);
@ -377,10 +380,13 @@ int SDLoadMCImageHeader(char *sdfilename)
}
ExtractGCIHeader();
// GCIMakeHeader();
#ifdef STATUSOGC
GCIMakeHeader();
#else
//Let's get the full header as is, instead of populating it...
memset(&gci, 0xff, sizeof(GCI)); /*** Clear out the cgi header ***/
memcpy (&gci, FileBuffer, sizeof (GCI));
#endif
//Find how many icons are present
numicons = 8;
@ -464,6 +470,62 @@ int SDLoadMCImageHeader(char *sdfilename)
return bytesToRead;
}
int SDLoadCardImageHeader(char *sdfilename)
{
FILE *handle;
char filename[1024];
char msg[256];
long bytesToRead = 0;
/*** Clear the work buffers ***/
memset (&cardheader, 0, sizeof(Header));
/*** Make fullpath filename ***/
sprintf (filename, "fat:/%s/%s", MCSAVES, sdfilename);
/*** Open the SD Card file ***/
handle = fopen ( filename , "rb" );
if (handle <= 0)
{
sprintf(msg, "Couldn't open %s", filename);
WaitPrompt (msg);
return 0;
}
// obtain file size:
fseek (handle , 0 , SEEK_END);
bytesToRead = ftell (handle);
rewind (handle);
if (bytesToRead < 8192) //We don't want to read something smaller than the card header
{
sprintf(msg, "Incorrect file size %ld . Not raw image file or header", bytesToRead);
WaitPrompt (msg);
return 0;
}
char fileType[1024];
char * dot;
int pos = 4;
dot = strrchr(filename,'.');
strncpy(fileType, dot+1,pos);
fileType[pos]='\0';
if(!strcasecmp(fileType, "mci"))
{
//MCI files have a 64 byte header
fseek(handle, 64, SEEK_SET);
}
memset(&cardheader, 0, sizeof(cardheader));
/*** Read the file header ***/
fread (&cardheader,1,sizeof(cardheader),handle);
/*** Close the file ***/
fclose (handle);
return bytesToRead;
}
int isdir_sd(char *path)
{
DIR* dir = opendir(path);
@ -475,12 +537,43 @@ int isdir_sd(char *path)
return 1;
}
//Code from Kobie. Returns true if extension matches (also works with paths), should check only the last '.' in the string.
bool compare_extension(char *filename, char *extension)
{
/* Sanity checks */
if(filename == NULL || extension == NULL)
return false;
if(strlen(filename) == 0 || strlen(extension) == 0)
return false;
if(strchr(filename, '.') == NULL || strchr(extension, '.') == NULL)
return false;
/* Iterate backwards through respective strings and compare each char one at a time */
int i;
for(i = 0; i < strlen(filename); i++)
{
if(tolower(filename[strlen(filename) - i - 1]) == tolower(extension[strlen(extension) - i - 1]))
{
if(i == strlen(extension) - 1)
return true;
} else
break;
}
return false;
}
/****************************************************************************
* SDGetFileList
*
* Get the directory listing from SD Card
* Mode 1: retrieves .gci, .sav and .gcs
* Mode 0: retrieves .raw, .gcp and .mci
****************************************************************************/
int SDGetFileList()
int SDGetFileList(int mode)
{
int filecount = 0;
DIR *dir;
@ -501,11 +594,23 @@ int SDGetFileList()
{
if(strncmp(dit->d_name, ".", 1) != 0 && strncmp(dit->d_name, "..", 2) != 0)
{
strcpy((char *)filelist[filecount], dit->d_name);
sprintf(namefile, "%s%s", filename, dit->d_name);
dirtype = ((isdir_sd(namefile) == 1) ? DIRENT_T_DIR : DIRENT_T_FILE);
if (mode){
if (compare_extension(dit->d_name, ".gci") || compare_extension(dit->d_name, ".sav") || compare_extension(dit->d_name, ".gcs")){
strcpy((char *)filelist[filecount], dit->d_name);
sprintf(namefile, "%s%s", filename, dit->d_name);
dirtype = ((isdir_sd(namefile) == 1) ? DIRENT_T_DIR : DIRENT_T_FILE);
filecount++;
filecount++;
}
}else if (!mode){
if (compare_extension(dit->d_name, ".raw") || compare_extension(dit->d_name, ".gcp") || compare_extension(dit->d_name, ".mci")){
strcpy((char *)filelist[filecount], dit->d_name);
sprintf(namefile, "%s%s", filename, dit->d_name);
dirtype = ((isdir_sd(namefile) == 1) ? DIRENT_T_DIR : DIRENT_T_FILE);
filecount++;
}
}
}
}

View File

@ -3,5 +3,7 @@
int SDSaveMCImage();
int SDLoadMCImage(char *sdfilename);
int SDLoadMCImageHeader(char *sdfilename);
int SDLoadCardImageHeader(char *sdfilename);
int isdir_sd(char *path);
int SDGetFileList();
int SDGetFileList(int mode);
bool file_exists(const char * filename);