mirror of
https://github.com/suloku/gcmm.git
synced 2026-03-30 14:14:43 -05:00
1428 lines
32 KiB
C
1428 lines
32 KiB
C
/****************************************************************************
|
|
* ds bomb gamecube memory card manager
|
|
* based on libOGC Memory Card Backup by askot
|
|
* delete support + saves information made by dsbomb
|
|
* Gui original design by dsbomb
|
|
* Gui adds and user interaction by justb
|
|
* Banner/Icon display updates by Dronesplitter
|
|
* Uses freetype.
|
|
* libFreeType is available from the downloads sections.
|
|
*****************************************************************************/
|
|
#include <gccore.h>
|
|
#include <ogcsys.h>
|
|
#include <network.h>
|
|
#include <smb.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <sys/dir.h>
|
|
#include <sys/time.h>
|
|
#include <fat.h>
|
|
#include <sdcard/gcsd.h>
|
|
|
|
#ifdef HW_RVL
|
|
#include <wiiuse/wpad.h>
|
|
#include <sdcard/wiisd_io.h>
|
|
#endif
|
|
|
|
|
|
#include "mcard.h"
|
|
#include "raw.h"
|
|
#include "sdsupp.h"
|
|
#include "freetype.h"
|
|
#include "bitmap.h"
|
|
|
|
#ifndef HW_RVL
|
|
#include "aram/sidestep.h"
|
|
#endif
|
|
|
|
#define PSOSDLOADID 0x7c6000a6
|
|
//Comment FLASHIDCHECK to allow writing any image to any mc. This will corrupt official cards.
|
|
#define FLASHIDCHECK
|
|
|
|
#define SDGECKOA_PATH "sda"
|
|
#define SDGECKOB_PATH "sdb"
|
|
#define SD2SP2_PATH "sdc"
|
|
#define GCLOADER_PATH "gcl"
|
|
#define WIISD_PATH "wsd"
|
|
#define WIIUSB_PATH "usb"
|
|
char fatpath[4];
|
|
|
|
const char appversion[] = "v1.5.2";
|
|
int mode;
|
|
int cancel;
|
|
int doall;
|
|
|
|
/*** 2D Video Globals ***/
|
|
GXRModeObj *vmode; /*** Graphics Mode Object ***/
|
|
u32 *xfb[2] = { NULL, NULL }; /*** Framebuffers ***/
|
|
int whichfb = 0; /*** Frame buffer toggle ***/
|
|
int screenheight;
|
|
int vmode_60hz = 0;
|
|
u32 retraceCount;
|
|
|
|
extern u8 filelist[1024][1024];
|
|
extern bool offsetchanged;
|
|
extern u8 currFolder[260];
|
|
extern int folderCount;
|
|
extern int displaypath;
|
|
u8 selector_flag;
|
|
|
|
s32 MEM_CARD = CARD_SLOTB;
|
|
extern syssramex *sramex;
|
|
extern u8 imageserial[12];
|
|
|
|
#define NOFAT_MSG "No FAT device detected. You may run device selector again."
|
|
|
|
static void updatePAD(u32 retrace)
|
|
{
|
|
retraceCount = retrace;
|
|
PAD_ScanPads();
|
|
#ifdef HW_RVL
|
|
WPAD_ScanPads();
|
|
#endif
|
|
}
|
|
|
|
/* DEfinitions in sdsupp.h
|
|
#define DEV_NUM 0
|
|
#define DEV_GCSDA 1
|
|
#define DEV_GCSDB 2
|
|
#define DEV_GCSDC 3
|
|
#define DEV_GCODE 4
|
|
#define DEV_WIISD 5
|
|
#define DEV_WIIUSB 6
|
|
|
|
#define DEV_TOTAL 6
|
|
|
|
#define DEV_ND 0
|
|
#define DEV_AVAIL 1
|
|
#define DEV_MOUNTED 2
|
|
*/
|
|
u8 DEVICES [DEV_TOTAL+1];
|
|
bool have_sd;
|
|
u8 CUR_DEVICE; //Current device index
|
|
|
|
static void detect_devices(){
|
|
|
|
int i = 0;
|
|
DEVICES[DEV_NUM]=0;
|
|
for (i=0;i<=DEV_TOTAL;i++) DEVICES[i]=0;
|
|
|
|
if (__io_gcsda.startup()&&__io_gcsda.shutdown()){
|
|
DEVICES[DEV_GCSDA] = DEV_AVAIL;
|
|
DEVICES[DEV_NUM] +=1;
|
|
}
|
|
if (__io_gcsdb.startup()&&__io_gcsdb.shutdown()){
|
|
DEVICES[DEV_GCSDB] = DEV_AVAIL;
|
|
DEVICES[DEV_NUM] +=1;
|
|
}
|
|
#ifdef HW_DOL
|
|
if (__io_gcsd2.startup()&&__io_gcsd2.shutdown()){
|
|
DEVICES[DEV_GCSDC] = DEV_AVAIL;
|
|
DEVICES[DEV_NUM] +=1;
|
|
}
|
|
if (__io_gcode.startup()&&__io_gcode.shutdown()){
|
|
DEVICES[DEV_GCODE] = DEV_AVAIL;
|
|
DEVICES[DEV_NUM] +=1;
|
|
}
|
|
#endif
|
|
#ifdef HW_RVL
|
|
if (__io_wiisd.startup()&&__io_wiisd.shutdown()){
|
|
DEVICES[DEV_WIISD] = DEV_AVAIL;
|
|
DEVICES[DEV_NUM] +=1;
|
|
}
|
|
if (__io_usbstorage.startup())
|
|
{
|
|
if (__io_usbstorage.isInserted())
|
|
{
|
|
DEVICES[DEV_WIIUSB] = DEV_AVAIL;
|
|
DEVICES[DEV_NUM] +=1;
|
|
__io_usbstorage.shutdown();
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
1 GC SD Gecko slot A
|
|
2 GC SD Gecko slot B
|
|
3 GC SD2SP2
|
|
4 GC Loader
|
|
5 Wii SD
|
|
6 Wii uSB
|
|
*/
|
|
static bool initFAT(int device)
|
|
{
|
|
ShowAction("Mounting device...");
|
|
char msg[128];
|
|
if (DEVICES[device] != DEV_AVAIL){
|
|
sprintf (msg, "Failed to mount device %d (device not available %d)", device, DEVICES[device]);
|
|
WaitPrompt(msg);
|
|
return false;
|
|
}
|
|
//sprintf (msg, "Mounting device... %d", device);
|
|
//WaitPrompt(msg);
|
|
switch (device)
|
|
{
|
|
case DEV_GCSDA:
|
|
__io_gcsda.startup();
|
|
if (!__io_gcsda.isInserted())
|
|
{
|
|
WaitPrompt("No SD Gecko inserted in SLOT A!");
|
|
return false;
|
|
}
|
|
if (!fatMountSimple (SDGECKOA_PATH, &__io_gcsda))
|
|
{
|
|
WaitPrompt("Error Mounting slot A SD fat!");
|
|
return false;
|
|
}
|
|
DEVICES[DEV_GCSDA] = DEV_MOUNTED;
|
|
sprintf(fatpath, "%s", SDGECKOA_PATH);
|
|
break;
|
|
|
|
case DEV_GCSDB:
|
|
__io_gcsdb.startup();
|
|
if (!__io_gcsdb.isInserted())
|
|
{
|
|
WaitPrompt("No SD card inserted in SLOT B!");
|
|
return false;
|
|
}
|
|
if (!fatMountSimple (SDGECKOB_PATH, &__io_gcsdb))
|
|
{
|
|
WaitPrompt("Error Mounting slot B SD fat!");
|
|
return false;
|
|
}
|
|
DEVICES[DEV_GCSDB] = DEV_MOUNTED;
|
|
sprintf(fatpath, "%s", SDGECKOB_PATH);
|
|
break;
|
|
#ifdef HW_DOL
|
|
case DEV_GCSDC:
|
|
__io_gcsd2.startup();
|
|
if (!__io_gcsd2.isInserted())
|
|
{
|
|
WaitPrompt("No SD card inserted in SD2SP2!");
|
|
return false;
|
|
}
|
|
if (!fatMountSimple (SD2SP2_PATH, &__io_gcsd2))
|
|
{
|
|
WaitPrompt("Error Mounting SD2SP2 SD fat!");
|
|
return false;
|
|
}
|
|
DEVICES[DEV_GCSDC] = DEV_MOUNTED;
|
|
sprintf(fatpath, "%s", SD2SP2_PATH);
|
|
break;
|
|
|
|
case DEV_GCODE:
|
|
__io_gcode.startup();
|
|
if (!__io_gcode.isInserted())
|
|
{
|
|
WaitPrompt("No SD card inserted in GCLoader!");
|
|
return false;
|
|
}
|
|
if (!fatMountSimple (GCLOADER_PATH, &__io_gcode))
|
|
{
|
|
WaitPrompt("Error Mounting GCLoader SD fat!");
|
|
return false;
|
|
}
|
|
DEVICES[DEV_GCODE] = DEV_MOUNTED;
|
|
sprintf(fatpath, "%s", GCLOADER_PATH);
|
|
break;
|
|
#elif HW_RVL
|
|
case DEV_WIISD:
|
|
__io_wiisd.startup();
|
|
if (!__io_wiisd.isInserted())
|
|
{
|
|
WaitPrompt("No SD card inserted in front SD slot!");
|
|
return false;
|
|
}
|
|
if (!fatMountSimple (WIISD_PATH, &__io_wiisd))
|
|
{
|
|
WaitPrompt("Error Mounting Wii SD fat!");
|
|
return false;
|
|
}
|
|
DEVICES[DEV_WIISD] = DEV_MOUNTED;
|
|
sprintf(fatpath, "%s", WIISD_PATH);
|
|
break;
|
|
|
|
case DEV_WIIUSB:
|
|
__io_usbstorage.startup();
|
|
if (!__io_usbstorage.isInserted())
|
|
{
|
|
WaitPrompt("No USB device inserted!");
|
|
return false;
|
|
}
|
|
if (!fatMountSimple (WIIUSB_PATH, &__io_usbstorage))
|
|
{
|
|
WaitPrompt("Error Mounting USB fat!");
|
|
return false;
|
|
}
|
|
DEVICES[DEV_WIIUSB] = DEV_MOUNTED;
|
|
sprintf(fatpath, "%s", WIIUSB_PATH);
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
WaitPrompt("Unwknown error mounting device");
|
|
return false;
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void deinitFAT()
|
|
{
|
|
//First unmount all the devs...
|
|
fatUnmount (fatpath);
|
|
fatpath[0]='/0';
|
|
have_sd = 0;
|
|
CUR_DEVICE = 0;
|
|
//...and then shutdown em!
|
|
if (DEVICES[DEV_GCSDA] == DEV_MOUNTED){
|
|
__io_gcsda.shutdown();
|
|
DEVICES[DEV_GCSDA]=DEV_AVAIL;
|
|
}
|
|
if (DEVICES[DEV_GCSDB] == DEV_MOUNTED){
|
|
__io_gcsdb.shutdown();
|
|
DEVICES[DEV_GCSDB]=DEV_AVAIL;
|
|
}
|
|
#ifdef HW_DOL
|
|
if (DEVICES[DEV_GCSDC] == DEV_MOUNTED){
|
|
__io_gcsd2.shutdown();
|
|
DEVICES[DEV_GCSDC]=DEV_AVAIL;
|
|
}
|
|
if (DEVICES[DEV_GCODE] == DEV_MOUNTED){
|
|
__io_gcode.shutdown();
|
|
DEVICES[DEV_GCODE]=DEV_AVAIL;
|
|
}
|
|
#endif
|
|
#ifdef HW_RVL
|
|
if (DEVICES[DEV_WIISD] == DEV_MOUNTED){
|
|
__io_wiisd.shutdown();
|
|
DEVICES[DEV_WIISD]=DEV_AVAIL;
|
|
}
|
|
if (DEVICES[DEV_WIIUSB] == DEV_MOUNTED){
|
|
__io_usbstorage.shutdown();
|
|
DEVICES[DEV_WIIUSB]=DEV_AVAIL;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
u8 skip_selector = 1;
|
|
int device_select()
|
|
{
|
|
u32 p, ph;
|
|
#ifdef HW_RVL
|
|
u32 wp, wph;
|
|
#endif
|
|
|
|
int x = 170;
|
|
int y = 280;
|
|
int x_text = x+15;
|
|
int y_text = y+20;
|
|
int selected = 0;
|
|
u8 draw = 1;
|
|
setfontsize(14);
|
|
setfontcolour(COL_FONT);
|
|
|
|
int i = 0;
|
|
u8 selected2device[4] = {0, 0, 0, 0};
|
|
//If there are no fat devices skip
|
|
if (!DEVICES[DEV_NUM]){
|
|
WaitPrompt (NOFAT_MSG);
|
|
return 0;
|
|
}else if (DEVICES[DEV_NUM] == 1 && skip_selector ){ //Only one device was detected, so mount it, but only on first boot
|
|
skip_selector = 0;
|
|
for (i=1;i<=DEV_TOTAL;i++)
|
|
{
|
|
if (DEVICES[i])
|
|
return i;
|
|
}
|
|
}else{
|
|
skip_selector = 0;
|
|
//Selector screen
|
|
while(1)
|
|
{
|
|
//Draw device selector
|
|
if (draw){
|
|
writeStatusBar("Press A to select","");
|
|
draw = 0;
|
|
DrawBoxFilled(x, y, x+290, y+90, COL_BG1);
|
|
y_text= y+20;
|
|
x_text = x+15;
|
|
DrawText(x_text, y_text, "Please select your device:");
|
|
y_text+=20;
|
|
x_text += 24;
|
|
#ifdef HW_RVL
|
|
if(DEVICES[DEV_WIISD]){
|
|
DrawText(x_text, y_text, "Wii Front SD slot");
|
|
y_text+=15;
|
|
for (i=0;i<4;i++)
|
|
{
|
|
if (!selected2device[i])
|
|
{
|
|
selected2device[i]=DEV_WIISD;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(DEVICES[DEV_WIIUSB]){
|
|
DrawText(x_text, y_text, "USB storage device");
|
|
y_text+=15;
|
|
for (i=0;i<4;i++)
|
|
{
|
|
if (!selected2device[i])
|
|
{
|
|
selected2device[i]=DEV_WIIUSB;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(DEVICES[DEV_GCSDA]){
|
|
DrawText(x_text, y_text, "Slot A SD Gecko");
|
|
y_text+=15;
|
|
for (i=0;i<4;i++)
|
|
{
|
|
if (!selected2device[i])
|
|
{
|
|
selected2device[i]=DEV_GCSDA;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(DEVICES[DEV_GCSDB]){
|
|
DrawText(x_text, y_text, "Slot B SD Gecko");
|
|
y_text=15;
|
|
for (i=0;i<4;i++)
|
|
{
|
|
if (!selected2device[i])
|
|
{
|
|
selected2device[i]=DEV_GCSDB;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
if(DEVICES[DEV_GCSDC]){
|
|
DrawText(x_text, y_text, "SD2SP2");
|
|
y_text+=15;
|
|
for (i=0;i<4;i++)
|
|
{
|
|
if (!selected2device[i])
|
|
{
|
|
selected2device[i]=DEV_GCSDC;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(DEVICES[DEV_GCSDA]){
|
|
DrawText(x_text, y_text, "Slot A SD Gecko");
|
|
y_text+=15;
|
|
for (i=0;i<4;i++)
|
|
{
|
|
if (!selected2device[i])
|
|
{
|
|
selected2device[i]=DEV_GCSDA;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(DEVICES[DEV_GCSDB]){
|
|
DrawText(x_text, y_text, "Slot B SD Gecko");
|
|
y_text+=15;
|
|
for (i=0;i<4;i++)
|
|
{
|
|
if (!selected2device[i])
|
|
{
|
|
selected2device[i]=DEV_GCSDB;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(DEVICES[DEV_GCODE]){
|
|
DrawText(x_text, y_text, "GC Loader");
|
|
y_text+=15;
|
|
for (i=0;i<4;i++)
|
|
{
|
|
if (!selected2device[i])
|
|
{
|
|
selected2device[i]=DEV_GCODE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//Draw cursor
|
|
y_text= y+40;
|
|
x_text = x+20;
|
|
switch (selected)
|
|
{
|
|
case 0:
|
|
DrawText(x_text, y_text, ">>");
|
|
break;
|
|
case 1:
|
|
DrawText(x_text, y_text+15, ">>");
|
|
break;
|
|
case 2:
|
|
DrawText(x_text, y_text+15+15, ">>");
|
|
break;
|
|
case 3:
|
|
DrawText(x_text, y_text+15+15+15, ">>");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}//end if (draw)
|
|
|
|
p = PAD_ButtonsDown (0);
|
|
#ifdef HW_RVL
|
|
wp = WPAD_ButtonsDown (0);
|
|
#endif
|
|
|
|
if (p & PAD_BUTTON_A
|
|
#ifdef HW_RVL
|
|
|| wp & WPAD_BUTTON_A
|
|
#endif
|
|
)
|
|
{
|
|
//Do something
|
|
return selected2device[selected];
|
|
}
|
|
if (p & PAD_BUTTON_DOWN
|
|
#ifdef HW_RVL
|
|
|| wp & WPAD_BUTTON_DOWN
|
|
#endif
|
|
)
|
|
{
|
|
selected +=1;
|
|
if (selected >= DEVICES[DEV_NUM]) selected = 0;
|
|
draw = 1;
|
|
}
|
|
if (p & PAD_BUTTON_UP
|
|
#ifdef HW_RVL
|
|
|| wp & WPAD_BUTTON_UP
|
|
#endif
|
|
)
|
|
{
|
|
selected -=1;
|
|
if (selected < 0) selected = DEVICES[DEV_NUM]-1;
|
|
draw = 1;
|
|
}
|
|
//char msg[256];
|
|
//sprintf(msg, "Selected device: %d Total %d DN%d SDA%d SDB%d SDC%d GL%d WSD%d WU%d", selected, DEVICES[DEV_NUM], DEVICES[1],DEVICES[2],DEVICES[3],DEVICES[4],DEVICES[5],DEVICES[6] );
|
|
/*
|
|
#define DEV_NUM 0
|
|
#define DEV_GCSDA 1
|
|
#define DEV_GCSDB 2
|
|
#define DEV_GCSDC 3
|
|
#define DEV_GCODE 4
|
|
#define DEV_WIISD 5
|
|
#define DEV_WIIUSB 6
|
|
*/
|
|
//writeStatusBar(msg, "");
|
|
ShowScreen();
|
|
}//end while(1)
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Initialise Video
|
|
*
|
|
* Before doing anything in libogc, it's recommended to configure a video
|
|
* output.
|
|
****************************************************************************/
|
|
static void
|
|
Initialise (void)
|
|
{
|
|
VIDEO_Init (); /*** ALWAYS CALL FIRST IN ANY LIBOGC PROJECT!
|
|
Not only does it initialise the video
|
|
subsystem, but also sets up the ogc os
|
|
***/
|
|
|
|
PAD_Init (); /*** Initialise pads for input ***/
|
|
#ifdef HW_RVL
|
|
WPAD_Init ();
|
|
#endif
|
|
|
|
// get default video mode
|
|
vmode = VIDEO_GetPreferredMode(NULL);
|
|
|
|
switch (vmode->viTVMode >> 2)
|
|
{
|
|
case VI_PAL:
|
|
// 576 lines (PAL 50Hz)
|
|
// display should be centered vertically (borders)
|
|
//Make all video modes the same size so menus doesn't screw up
|
|
vmode = &TVPal576IntDfScale;
|
|
vmode->xfbHeight = 480;
|
|
vmode->viYOrigin = (VI_MAX_HEIGHT_PAL - 480)/2;
|
|
vmode->viHeight = 480;
|
|
|
|
vmode_60hz = 0;
|
|
break;
|
|
|
|
case VI_NTSC:
|
|
// 480 lines (NTSC 60hz)
|
|
vmode_60hz = 1;
|
|
break;
|
|
|
|
default:
|
|
// 480 lines (PAL 60Hz)
|
|
vmode_60hz = 1;
|
|
break;
|
|
}
|
|
|
|
#ifdef HW_DOL
|
|
/* we have component cables, but the preferred mode is interlaced
|
|
* why don't we switch into progressive?
|
|
* (user may not have progressive compatible display but component input)
|
|
* on the Wii, the user can do this themselves on their Wii Settings */
|
|
if(VIDEO_HaveComponentCable())
|
|
vmode = &TVNtsc480Prog;
|
|
#endif
|
|
|
|
/* // check for progressive scan // bool progressive = FALSE;
|
|
if (vmode->viTVMode == VI_TVMODE_NTSC_PROG)
|
|
progressive = true;
|
|
*/
|
|
|
|
#ifdef HW_RVL
|
|
// widescreen fix
|
|
if(CONF_GetAspectRatio())
|
|
{
|
|
vmode->viWidth = 678;
|
|
vmode->viXOrigin = (VI_MAX_WIDTH_PAL - 678) / 2;
|
|
}
|
|
#endif
|
|
|
|
// configure VI
|
|
VIDEO_Configure (vmode);
|
|
|
|
// always 480 lines /*** Update screen height for font engine ***/
|
|
screenheight = vmode->xfbHeight;
|
|
|
|
/*** Now configure the framebuffer.
|
|
Really a framebuffer is just a chunk of memory
|
|
to hold the display line by line.
|
|
***/
|
|
// Allocate the video buffers
|
|
xfb[0] = (u32 *) MEM_K0_TO_K1 (SYS_AllocateFramebuffer (vmode));
|
|
/*** I prefer also to have a second buffer for double-buffering.
|
|
This is not needed for the console demo.
|
|
***/
|
|
xfb[1] = (u32 *) MEM_K0_TO_K1 (SYS_AllocateFramebuffer (vmode));
|
|
|
|
/*** Define a console ***/
|
|
console_init (xfb[0], 20, 64, vmode->fbWidth, vmode->xfbHeight, vmode->fbWidth * 2);
|
|
|
|
/*** Clear framebuffer to black ***/
|
|
VIDEO_ClearFrameBuffer (vmode, xfb[0], COLOR_BLACK);
|
|
VIDEO_ClearFrameBuffer (vmode, xfb[1], COLOR_BLACK);
|
|
|
|
/*** Set the framebuffer to be displayed at next VBlank ***/
|
|
VIDEO_SetNextFramebuffer (xfb[0]);
|
|
|
|
/*** Get the PAD status updated by libogc ***/
|
|
VIDEO_SetPostRetraceCallback (updatePAD);
|
|
VIDEO_SetBlack (0);
|
|
|
|
/*** Update the video for next vblank ***/
|
|
VIDEO_Flush ();
|
|
|
|
VIDEO_WaitVSync (); /*** Wait for VBL ***/
|
|
if (vmode->viTVMode & VI_NON_INTERLACE)
|
|
VIDEO_WaitVSync ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
* BackupMode -SD Mode
|
|
*
|
|
* Perform backup of a memory card file to a SD Card.
|
|
****************************************************************************/
|
|
void SD_BackupMode ()
|
|
{
|
|
int memitems;
|
|
int selected = 0;
|
|
int bytestodo;
|
|
char buffer[256], text[64];
|
|
|
|
displaypath = 0;
|
|
|
|
clearRightPane();
|
|
DrawText(386,130,"B a c k u p M o d e");
|
|
DrawText(386,134,"_____________________");
|
|
writeStatusBar("Reading memory card... ", "");
|
|
/*** Get the directory listing from the memory card ***/
|
|
memitems = CardGetDirectory (MEM_CARD);
|
|
|
|
setfontsize (14);
|
|
writeStatusBar("Pick a file using UP or DOWN ", "Press A to backup savegame") ;
|
|
#ifdef HW_RVL
|
|
DrawText(40, 50, "Press R/1 to backup ALL savegames");
|
|
#else
|
|
DrawText(40, 50, "Press R to backup ALL savegames");
|
|
#endif
|
|
|
|
/*** If it's a blank card, get out of here ***/
|
|
if (!memitems)
|
|
{
|
|
WaitPrompt ("No saved games to backup!");
|
|
}
|
|
else
|
|
{
|
|
selected = ShowSelector (1);
|
|
if (cancel)
|
|
{
|
|
WaitPrompt ("Backup action cancelled!");
|
|
}
|
|
else if(doall)
|
|
{
|
|
doall = WaitPromptChoice("Are you sure you want to backup all files?", "No", "Yes");
|
|
if (doall)
|
|
{
|
|
//Backup All files
|
|
for ( selected = 0; selected < memitems; selected++ ) {
|
|
/*** Backup files ***/
|
|
sprintf(buffer, "[%d/%d] Reading from MC slot %s", selected+1, memitems, (MEM_CARD) ? "B" : "A");
|
|
ShowAction(buffer);
|
|
bytestodo = CardReadFile(MEM_CARD, selected);
|
|
if (bytestodo)
|
|
{
|
|
sprintf(buffer, "[%d/%d] Saving to FAT device", selected+1, memitems);
|
|
ShowAction(buffer);
|
|
if (!SDSaveMCImage())
|
|
{
|
|
strncpy(text, (char*)filelist[selected], 32);
|
|
text[32]='\0';
|
|
sprintf(buffer, "Error during backup (%s). Continue?", text);
|
|
doall = WaitPromptChoice(buffer, "Yes", "No");
|
|
if (doall)
|
|
{
|
|
WaitPrompt ("Backup action cancelled due to error!");
|
|
return;
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
WaitPrompt ("Error reading MC file");
|
|
return;
|
|
}
|
|
}
|
|
|
|
WaitPrompt("Full card backup done!");
|
|
return;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
/*** Backup the file ***/
|
|
ShowAction ("Reading File From MC SLOT B");
|
|
bytestodo = CardReadFile (MEM_CARD, selected);
|
|
if (bytestodo)
|
|
{
|
|
ShowAction ("Saving to FAT device");
|
|
if (SDSaveMCImage())
|
|
{
|
|
WaitPrompt ("Backup complete");
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
WaitPrompt ("Backup failed");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WaitPrompt ("Error reading MC file");
|
|
return;
|
|
}
|
|
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
* BackupModeAllFiles - SD Mode
|
|
* Copy all files on the Memory Card to the SD card
|
|
****************************************************************************/
|
|
void SD_BackupModeAllFiles ()
|
|
{
|
|
int memitems;
|
|
int selected = 0;
|
|
int bytestodo;
|
|
|
|
char buffer[128];
|
|
|
|
displaypath = 0;
|
|
|
|
clearRightPane();
|
|
DrawText(386,130," B a c k u p A l l ");
|
|
DrawText(386,134,"_____________________");
|
|
|
|
setfontsize (14);
|
|
writeStatusBar("Backing up all files.", "This may take a while.");
|
|
/*** Get the directory listing from the memory card ***/
|
|
memitems = CardGetDirectory (MEM_CARD);
|
|
|
|
/*** If it's a blank card, get out of here ***/
|
|
if (!memitems)
|
|
{
|
|
WaitPrompt ("No saved games to backup!");
|
|
}
|
|
else
|
|
{
|
|
for ( selected = 0; selected < memitems; selected++ ) {
|
|
/*** Backup files ***/
|
|
sprintf(buffer, "[%d/%d] Reading from MC slot B", selected+1, memitems);
|
|
ShowAction(buffer);
|
|
bytestodo = CardReadFile(MEM_CARD, selected);
|
|
if (bytestodo)
|
|
{
|
|
sprintf(buffer, "[%d/%d] Saving to FAT device", selected+1, memitems);
|
|
ShowAction(buffer);
|
|
SDSaveMCImage();
|
|
}
|
|
else
|
|
{
|
|
WaitPrompt ("Error reading MC file");
|
|
return;
|
|
}
|
|
}
|
|
|
|
WaitPrompt("Full card backup done!");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
* RestoreMode
|
|
*
|
|
* Restore a file to Memory Card from SD Card
|
|
****************************************************************************/
|
|
void SD_RestoreMode ()
|
|
{
|
|
int files;
|
|
int selected;
|
|
char buffer[256], text[64];
|
|
int inProgress = 1;
|
|
|
|
displaypath = 1;
|
|
|
|
clearRightPane();
|
|
DrawText(380,130,"R e s t o r e M o d e");
|
|
DrawText(380,134,"______________________");
|
|
writeStatusBar("Reading files... ", "");
|
|
|
|
//Dragonbane: Curr Folder to default
|
|
|
|
sprintf((char*)currFolder, "MCBACKUP");
|
|
|
|
files = SDGetFileList (1);
|
|
|
|
setfontsize (14);
|
|
#ifdef HW_RVL
|
|
DrawText(40, 50, "Press R/1 to restore ALL savegames");
|
|
#else
|
|
DrawText(40, 50, "Press R to restore ALL savegames");
|
|
#endif
|
|
|
|
if (!files)
|
|
{
|
|
WaitPrompt ("No saved games in FAT device to restore !");
|
|
}
|
|
else
|
|
{
|
|
while(inProgress == 1)
|
|
{
|
|
writeStatusBar("Pick a file using UP or DOWN", "Press A to restore to Memory Card ") ;
|
|
|
|
//It will wait here until user selected a file
|
|
selected = ShowSelector (1);
|
|
|
|
if (cancel)
|
|
{
|
|
if (strcmp((char*)currFolder, "MCBACKUP") == 0)
|
|
{
|
|
WaitPrompt ("Restore action cancelled !");
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
//Go back one folder
|
|
char* pos = strrchr( (char*)currFolder, '/' );
|
|
|
|
currFolder[(pos-(char*)currFolder)] = 0;
|
|
|
|
files = SDGetFileList (1);
|
|
|
|
cancel = 0;
|
|
offsetchanged = true;
|
|
usleep(300000);
|
|
continue;
|
|
}
|
|
}
|
|
else if (doall)
|
|
{
|
|
doall = WaitPromptChoice("Are you sure you want to restore -ALL- files from this folder?", "Yes", "No");
|
|
if (!doall)
|
|
{
|
|
//Restore All files (from current folder)
|
|
for ( selected = folderCount; selected < files; selected++ ) {
|
|
/*** Restore files ***/
|
|
sprintf(buffer, "[%d/%d] Reading from FAT device", selected+1, files);
|
|
ShowAction(buffer);
|
|
if (SDLoadMCImage ((char*)filelist[selected]))
|
|
{
|
|
sprintf(buffer, "[%d/%d] Saving to MC slot %s", selected+1, files, (MEM_CARD) ? "B" : "A");
|
|
ShowAction(buffer);
|
|
if (!CardWriteFile (MEM_CARD))
|
|
{
|
|
strncpy(text, (char*)filelist[selected], 32);
|
|
text[32]='\0';
|
|
sprintf(buffer, "Error during restore (%s). Continue?", text);
|
|
doall = WaitPromptChoice(buffer, "Yes", "No");
|
|
if (doall)
|
|
{
|
|
WaitPrompt ("Restore action cancelled due to error!");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WaitPrompt ("Error reading image");
|
|
return;
|
|
}
|
|
}
|
|
|
|
WaitPrompt("Full card restore done!");
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//Check if selection is folder
|
|
char folder[1024];
|
|
sprintf (folder, "%s:/%s/%s",fatpath, currFolder, (char*)filelist[selected]);
|
|
|
|
if(isdir_sd(folder) == 1)
|
|
{
|
|
//Enter folder
|
|
sprintf((char*)currFolder, "%s/%s", currFolder, (char*)filelist[selected]);
|
|
|
|
files = SDGetFileList (1);
|
|
if (!files)
|
|
{
|
|
WaitPrompt("Folder is empty!");
|
|
|
|
//Go back again
|
|
char* pos = strrchr( (char*)currFolder, '/' );
|
|
|
|
currFolder[(pos-(char*)currFolder)] = 0;
|
|
|
|
files = SDGetFileList (1);
|
|
}
|
|
|
|
offsetchanged = true;
|
|
usleep(300000);
|
|
continue;
|
|
}
|
|
else //Selection is a file
|
|
{
|
|
ShowAction ("Reading from FAT device");
|
|
if (SDLoadMCImage ((char*)filelist[selected]))
|
|
{
|
|
ShowAction ("Updating Memory Card");
|
|
if (CardWriteFile (MEM_CARD))
|
|
{
|
|
WaitPrompt ("Restore Complete");
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
WaitPrompt ("Error during restore");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WaitPrompt ("Error reading image");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* RawBackupMode -SD Mode
|
|
*
|
|
* Perform backup of full memory card (in raw format) to a SD Card.
|
|
****************************************************************************/
|
|
void SD_RawBackupMode ()
|
|
{
|
|
s32 writen = 0;
|
|
char msg[64];
|
|
|
|
displaypath = 0;
|
|
|
|
clearRightPane();
|
|
|
|
DrawText(394,224,"___________________");
|
|
DrawText(394,248,"R A W B a c k u p");
|
|
DrawText(454,268,"M o d e");
|
|
DrawText(394,272,"___________________");
|
|
|
|
setfontsize (14);
|
|
writeStatusBar("Reading memory card... ", "");
|
|
|
|
if (BackupRawImage(MEM_CARD, &writen) == 1)
|
|
{
|
|
sprintf(msg, "Backup complete! Wrote %d bytes to FAT device",writen);
|
|
WaitPrompt(msg);
|
|
}else{
|
|
|
|
WaitPrompt("Backup failed!");
|
|
}
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
* 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;
|
|
int inProgress = 1;
|
|
|
|
displaypath = 1;
|
|
|
|
clearRightPane();
|
|
DrawText(380,130,"R A W R e s t o r e");
|
|
DrawText(450,150,"M o d e");
|
|
DrawText(380,154,"_____________________");
|
|
|
|
writeStatusBar("Reading files... ", "");
|
|
|
|
//Curr Folder to default
|
|
sprintf((char*)currFolder, "MCBACKUP");
|
|
|
|
files = SDGetFileList (0);
|
|
|
|
setfontsize (14);
|
|
writeStatusBar("Pick a file using UP or DOWN", "Press A to restore to Memory Card ");
|
|
|
|
if (!files)
|
|
{
|
|
WaitPrompt ("No raw backups in FAT device to restore !");
|
|
}else
|
|
{
|
|
while(inProgress == 1)
|
|
{
|
|
setfontsize (14);
|
|
writeStatusBar("Pick a file using UP or DOWN", "Press A to restore to Memory Card ") ;
|
|
|
|
//It will wait here until user selected a file
|
|
selected = ShowSelector (0);
|
|
|
|
if (cancel)
|
|
{
|
|
if (strcmp((char*)currFolder, "MCBACKUP") == 0)
|
|
{
|
|
WaitPrompt ("Restore action cancelled !");
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
//Go back one folder
|
|
char* pos = strrchr( (char*)currFolder, '/' );
|
|
|
|
currFolder[(pos-(char*)currFolder)] = 0;
|
|
|
|
files = SDGetFileList (0);
|
|
|
|
cancel = 0;
|
|
offsetchanged = true;
|
|
usleep(300000);
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//Check if selection is folder
|
|
char folder[1024];
|
|
sprintf (folder, "%s:/%s/%s",fatpath, currFolder, (char*)filelist[selected]);
|
|
|
|
if(isdir_sd(folder) == 1)
|
|
{
|
|
//Enter folder
|
|
sprintf((char*)currFolder, "%s/%s", currFolder, (char*)filelist[selected]);
|
|
|
|
files = SDGetFileList (0);
|
|
if (!files)
|
|
{
|
|
WaitPrompt("Folder is empty!");
|
|
|
|
//Go back again
|
|
char* pos = strrchr( (char*)currFolder, '/' );
|
|
|
|
currFolder[(pos-(char*)currFolder)] = 0;
|
|
|
|
files = SDGetFileList (0);
|
|
}
|
|
|
|
offsetchanged = true;
|
|
usleep(300000);
|
|
continue;
|
|
}
|
|
else //Selection is a file
|
|
{
|
|
#ifdef FLASHIDCHECK
|
|
//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;
|
|
}
|
|
}
|
|
#endif
|
|
ShowAction ("Reading from FAT device...");
|
|
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!");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Main
|
|
****************************************************************************/
|
|
int main (int argc, char *argv[])
|
|
{
|
|
|
|
have_sd = false;
|
|
CUR_DEVICE = 0;
|
|
|
|
#ifdef HW_DOL
|
|
int *psoid = (int *) 0x80001800;
|
|
void (*PSOReload) () = (void (*)()) 0x80001800;
|
|
#endif
|
|
|
|
Initialise (); /*** Start video ***/
|
|
FT_Init (); /*** Start FreeType ***/
|
|
|
|
#ifdef HW_RVL
|
|
initialise_power();
|
|
#endif
|
|
|
|
detect_devices();
|
|
|
|
//Check for command line
|
|
if (argc > 1)
|
|
{
|
|
if (!strcasecmp(argv[1], "ask"))
|
|
{
|
|
//Run device selection screen
|
|
skip_selector = 0;
|
|
selector_flag = 1;
|
|
ClearScreen();
|
|
ShowScreen();
|
|
|
|
CUR_DEVICE = device_select();
|
|
}
|
|
else if (!strcasecmp(argv[1], "sdgecko"))
|
|
{
|
|
if (DEVICES[DEV_GCSDA] == DEV_AVAIL && !(DEVICES[DEV_GCSDB] == DEV_AVAIL))
|
|
{
|
|
CUR_DEVICE = DEV_GCSDA;
|
|
}
|
|
else if (DEVICES[DEV_GCSDB] == DEV_AVAIL && !(DEVICES[DEV_GCSDA] == DEV_AVAIL))
|
|
{
|
|
CUR_DEVICE = DEV_GCSDB;
|
|
}
|
|
else //Run selector screen if there are both an SDGecko in slot A and Slot B...you won't be able to do anything with that setup though
|
|
{
|
|
//Run device selection screen
|
|
selector_flag = 1;
|
|
ClearScreen();
|
|
ShowScreen();
|
|
|
|
CUR_DEVICE = device_select();
|
|
}
|
|
}
|
|
else if (!strcasecmp(argv[1], "sdgeckoA"))
|
|
{
|
|
if (DEVICES[DEV_GCSDA] == DEV_AVAIL)
|
|
{
|
|
CUR_DEVICE = DEV_GCSDA;
|
|
}
|
|
}
|
|
else if (!strcasecmp(argv[1], "sdgeckoB"))
|
|
{
|
|
if (DEVICES[DEV_GCSDB] == DEV_AVAIL)
|
|
{
|
|
CUR_DEVICE = DEV_GCSDB;
|
|
}
|
|
}
|
|
#ifdef HW_DOL
|
|
else if (!strcasecmp(argv[1], "gcloader"))
|
|
{
|
|
if (DEVICES[DEV_GCODE] == DEV_AVAIL)
|
|
{
|
|
CUR_DEVICE = DEV_GCODE;
|
|
}
|
|
}
|
|
else if (!strcasecmp(argv[1], "sd2sp2"))
|
|
{
|
|
if (DEVICES[DEV_GCSDC] == DEV_AVAIL)
|
|
{
|
|
CUR_DEVICE = DEV_GCSDC;
|
|
}
|
|
}
|
|
#endif
|
|
#ifdef HW_RVL
|
|
else if (!strcasecmp(argv[1], "wiisd"))
|
|
{
|
|
if (DEVICES[DEV_WIISD] == DEV_AVAIL)
|
|
{
|
|
CUR_DEVICE = DEV_WIISD;
|
|
}
|
|
}
|
|
else if (!strcasecmp(argv[1], "wiiusb"))
|
|
{
|
|
if (DEVICES[DEV_WIIUSB] == DEV_AVAIL)
|
|
{
|
|
CUR_DEVICE = DEV_WIIUSB;
|
|
}
|
|
}
|
|
#endif
|
|
//If command line failed to set a CUR_DEVICE, run selector screen
|
|
if (CUR_DEVICE == 0)
|
|
{
|
|
selector_flag = 1;
|
|
ClearScreen();
|
|
ShowScreen();
|
|
|
|
CUR_DEVICE = device_select();
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
//Run device selection screen (will be skipped at first run if there's only one available device)
|
|
selector_flag = 1;
|
|
ClearScreen();
|
|
ShowScreen();
|
|
|
|
CUR_DEVICE = device_select();
|
|
}
|
|
|
|
if (CUR_DEVICE) have_sd = initFAT(CUR_DEVICE);
|
|
|
|
//Set correct memory card slot when SD gecko is selected device
|
|
if (CUR_DEVICE == DEV_GCSDB) MEM_CARD = 0;
|
|
else if (CUR_DEVICE == DEV_GCSDA) MEM_CARD = 1;
|
|
|
|
selector_flag = 0;
|
|
skip_selector = 0;
|
|
for (;;)
|
|
{
|
|
/*** Select Mode ***/
|
|
ClearScreen();
|
|
setfontsize (FONT_SIZE);
|
|
freecardbuf();
|
|
cancel = 0;/******a global value to track action aborted by user pressing button B********/
|
|
doall = 0;
|
|
mode = SelectMode ();
|
|
|
|
//Allow memory card selection for some devices
|
|
if ((mode != 500 ) && (mode != 100) && (mode != 600) && (mode != 1000 ) && (CUR_DEVICE==DEV_WIISD || CUR_DEVICE==DEV_WIIUSB || CUR_DEVICE==DEV_GCSDC || CUR_DEVICE==DEV_GCODE) ){
|
|
if (WaitPromptChoice ("Please select a memory card slot", "Slot B", "Slot A") == 1)
|
|
{
|
|
MEM_CARD = CARD_SLOTA;
|
|
}else
|
|
{
|
|
MEM_CARD = CARD_SLOTB;
|
|
}
|
|
}
|
|
|
|
/*** Mode == 100 for backup, 200 for restore ***/
|
|
switch (mode)
|
|
{
|
|
case 100 : //User pressed A so keep looping
|
|
//SMB_BackupMode();
|
|
//WaitPrompt ("Inactive");
|
|
break;
|
|
case 200 : //User wants to delete
|
|
MC_DeleteMode(MEM_CARD);
|
|
break;
|
|
case 300 : //User wants to backup
|
|
if (have_sd) SD_BackupMode();
|
|
else WaitPrompt(NOFAT_MSG);
|
|
break;
|
|
case 400 : //User wants to restore
|
|
if (have_sd) SD_RestoreMode();
|
|
else WaitPrompt(NOFAT_MSG);
|
|
break;
|
|
case 500 ://exit
|
|
ShowAction ("Exiting...");
|
|
#ifdef HW_RVL
|
|
deinitFAT();
|
|
//if there's a loader stub load it, if not return to wii menu.
|
|
if (!!*(u32*)0x80001800){ShowAction ("Exiting...Loader"); exit(1);}
|
|
else {ShowAction ("Exiting...SysMenu");SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);}
|
|
#else
|
|
if (psoid[0] == PSOSDLOADID){
|
|
deinitFAT();
|
|
ShowAction ("Exiting...Loader");
|
|
PSOReload ();
|
|
}
|
|
if (have_sd){
|
|
char exitdol[64];
|
|
sprintf(exitdol, "%s:/autoexec.dol",fatpath);
|
|
FILE *fp = fopen(exitdol, "rb");
|
|
if (fp) {
|
|
ShowAction ("Exiting...autoexec.dol");
|
|
fseek(fp, 0, SEEK_END);
|
|
int size = ftell(fp);
|
|
fseek(fp, 0, SEEK_SET);
|
|
if ((size > 0) && (size < (AR_GetSize() - (64*1024)))) {
|
|
u8 *dol = (u8*) memalign(32, size);
|
|
if (dol) {
|
|
fread(dol, 1, size, fp);
|
|
fclose(fp);
|
|
deinitFAT();
|
|
DOLtoARAM(dol, 0, NULL);
|
|
}
|
|
WaitPrompt ("Something went wrong with autoexec.dol. Press A to reboot.");
|
|
//We shouldn't reach this point
|
|
if (dol != NULL) free(dol);
|
|
}
|
|
fclose(fp);//We shouldn't reach here either
|
|
}
|
|
char msg[64];
|
|
sprintf(msg, "Couldn't open %s. Press A to reboot.", exitdol);
|
|
WaitPrompt (msg);
|
|
}
|
|
deinitFAT();
|
|
ShowAction ("Exiting...Reboot");
|
|
SYS_ResetSystem(SYS_HOTRESET, 0, 0);
|
|
#endif
|
|
break; //PSO_Reload
|
|
case 600 : //User wants to backup full card
|
|
/*
|
|
if (have_sd) SD_BackupModeAllFiles();
|
|
else WaitPrompt("Reboot aplication with an SD card");
|
|
*/
|
|
break;
|
|
case 700 : //Raw backup mode
|
|
if (have_sd)
|
|
{
|
|
SD_RawBackupMode();
|
|
}else
|
|
{
|
|
WaitPrompt(NOFAT_MSG);
|
|
}
|
|
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(NOFAT_MSG);
|
|
|
|
}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)
|
|
{
|
|
clearRightPane();
|
|
DrawText(390,224,"____________________");
|
|
DrawText(390,248,"F o r m a t C a r d");
|
|
DrawText(460,268,"M o d e");
|
|
DrawText(390,272,"____________________");
|
|
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;
|
|
case 1000: //Device select mode
|
|
deinitFAT();
|
|
WaitPrompt("Device unmounted. Insert/Remove any devices now.");
|
|
selector_flag = 1;
|
|
ShowScreen();
|
|
ClearScreen();
|
|
detect_devices();
|
|
CUR_DEVICE = device_select();
|
|
if (CUR_DEVICE) have_sd = initFAT(CUR_DEVICE);
|
|
//Set correct memory card slot when SD gecko is selected device
|
|
if (CUR_DEVICE == DEV_GCSDB) MEM_CARD = 0;
|
|
else if (CUR_DEVICE == DEV_GCSDA) MEM_CARD = 1;
|
|
selector_flag = 0;
|
|
break;
|
|
}
|
|
|
|
offsetchanged = true;
|
|
}
|
|
while (1);
|
|
//Should never reach this point...
|
|
#ifdef HW_RVL
|
|
//if there's a loader stub load it, if not return to wii menu.
|
|
if (!!*(u32*)0x80001800) exit(1);
|
|
else SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
|
|
#else
|
|
SYS_ResetSystem(SYS_HOTRESET, 0, 0);
|
|
#endif
|
|
return 0;
|
|
}
|