Corrected alpha blending (it was wrong all along, not very noticeable with current colors)

DrawBoxFilledGradient can modify the midpoint of the color gradient
Waits user to release the buttons (to avoid accidental restores)
Shows Memory Card free blocks in restore/backup mode
Shows page number in file selector
Icon won't try to load in raw modes.
Now can hold up/down to scroll the list. Also can use left/right to jump 5 elements up or down (can also be hold)
File list will always have the same order (previously looping back from first item filled the page, leading to repeated savegame entries when returning to page 1)
Uses retracecount as default method for icon animation (same timing as IPL and wii system menu)
Fixed sd gecko slot selection in GC mode (previous tried to use the same slot for memory card and sd gecko)
Shows filename when prompted to overwrite
Double check when raw restoring to ensure restore is correct (makes it a little slower, from 11 blocks/second to 9/blocks second roughly)
This commit is contained in:
sulokutdcmago 2012-10-07 11:18:19 +00:00
parent bc4b511ff1
commit 071e9d9b60
8 changed files with 484 additions and 122 deletions

View File

@ -35,24 +35,37 @@ u32 Decode5A3(u16 val, int row) {
//the following code relies in DrawBoxFilledGradient() being called
//in showSaveInfo() in freetype.c to have these colors and being 37 pixel height (y2-y1 = 37)
//also, icon and banner must be displayed over it
//Blue color 5 10 140
//Purple color 55 15 95
//To do: get the actual color in the screen to make true alpha blending
int r3,g3,b3;
int r1 = (BLUECOL&0x0000FF) >> 0; int g1 = (BLUECOL&0x00FF00) >> 8; int b1 = (BLUECOL&0xFF0000) >> 16;
int r2 = (PURPLECOL&0x0000FF) >> 0; int g2 = (PURPLECOL&0x00FF00) >> 8; int b2 = (PURPLECOL&0xFF0000) >> 16;
int midr, midg, midb;
midr = (r1 * 0.5) + (r2 * (1 - 0.5));
midg = (g1 * 0.5) + (g2 * (1 - 0.5));
midb = (b1 * 0.5) + (b2 * (1 - 0.5));
float p;
float boxheight = 37.0; //DrawBoxFilledGradient() y2-y1
int temp = 0;
//correct icon displacement over the gradient box
temp = row +3;
p = (float)((float)(37-temp)/(float)37.0);
r3 = (r1 * p) + (r2 * (1 - p));
g3 = (g1 * p) + (g2 * (1 - p));
b3 = (b1 * p) + (b2 * (1 - p));
bg_color = (b3<<16)|(g3<<8)|r3;
if (boxheight-temp > boxheight*LOCATION)
{
p = ((float)(boxheight-temp)-(boxheight*LOCATION))/((float)(boxheight)-((boxheight)*LOCATION));
r3 = (r1 * p) + (midr * (1 - p));
g3 = (g1 * p) + (midg * (1 - p));
b3 = (b1 * p) + (midb * (1 - p));
}
else
{
p = ((float)(boxheight-temp))/((float)(boxheight)*LOCATION);
r3 = (midr * p) + (r2 * (1 - p));
g3 = (midg * p) + (g2 * (1 - p));
b3 = (midb * p) + (b2 * (1 - p));
}
bg_color = (b3<<16)|(g3<<8)|r3;
int r, g, b, a;
//use 0x8000 as a bit mask
if ((val & 0x8000)) {
@ -94,14 +107,18 @@ void bannerloadRGB(u16 *gamebanner) {
RGBA = Decode5A3(src[ix], row);
dst[ (y + iy) * CARD_BANNER_W + (x + ix)] = RGBA;
}
}
//keep track of pixel rows
count+=4;
if (count == CARD_BANNER_W/4)
{
//keep track of pixel rows
row++;
count = 0;
}
count++;
if (count == 4*4*3*2)
{
count = 0;
}
else if (!(row%4))
{
row -=4;
}
}
}
}
@ -144,13 +161,17 @@ void bannerloadCI(u8 *gamebanner, u16* lookupdata) {
temp = src[ix];
dst[(y + iy) * CARD_BANNER_W + (x + ix)] = Decode5A3(lookupdata[temp], row);
}
}
count+=8;
if (count == CARD_BANNER_W/4)
{
row++;
count = 0;
}
count++;
if (count == 4*4*3)
{
count = 0;
}
else if (!(row%4))
{
row -=4;
}
}
}
}
@ -191,13 +212,17 @@ void iconloadRGB(u16 *gameicon) {
//Decode for straight RGB
dst[(y + iy) * CARD_ICON_W + (x + ix)] = Decode5A3(src[ix], row);
}
}
count++;
if (count % 2 == 0)
{
row++;
count = 0;
}
count++;
if (count == 4*4*2)
{
count = 0;
}
else if (!(row%4))
{
row -=4;
}
}
}
}
@ -239,14 +264,21 @@ void iconloadCI(u8 *gameicon, u16* lookupdata) {
temp = src[ix];
dst[(y + iy) * CARD_ICON_W + (x + ix)] = Decode5A3(lookupdata[temp], row);
}
}
count+=CARD_BANNER_W/16;
if (count % 2 == 0)
{
row++;
count = 0;
}
count++;
if (count == 4*4)
{
count = 0;
}
else if (!(row%4))
{
row -=4;
}
}
//count++;
}
}
//Build the final array; 3 pixel values = 3*3072 or 9216 size bmp info

View File

@ -3,18 +3,23 @@
Project. These functions serve to decode the RGB5A3 format that GCN Banner/Icon Files use
and create an array of BGR values, used later by the ShowBanner function.
ShowBanner is a simple modification of ShowBMP.
Files from Dolphin Project that were used as the basis for this code:
BannerLoaderGC.cpp, ColorUtil.cpp, and TextureDecoder.cpp
(http://dolphin-emu.googlecode.com/svn/trunk/)
***/
//this is the background color in RGB for alpha blending
//values are BGR
//Blue color 5 10 140
//Purple color 55 15 95
#define BLUECOL ((140<<16)|(10<<8)|5)
#define PURPLECOL ((95<<16)|(15<<8)|55)
//this is the background color in RGB for alpha blending (values are BGR)
//This ones look almost the same in dolphin as GC IPL
//#define BLUECOL ((140<<16)|(0<<8)|0)
//#define PURPLECOL ((100<<16)|(0<<8)|70)
//This ones look more like IPL on real TV
#define BLUECOL ((170<<16)|(30<<8)|30)
#define PURPLECOL ((130<<16)|(30<<8)|100)
#define LOCATION 0.5
//This is the blueish background color
//#define BLENDCOL ((211<<16)|(174<<8)|84)

View File

@ -317,6 +317,17 @@ void ShowAction (char *msg)
ShowScreen ();
}
void WaitRelease()
{
//Wait for user to release the button
while (PAD_ButtonsHeld (0)
#ifdef HW_RVL
| WPAD_ButtonsHeld(0)
#endif
)
VIDEO_WaitVSync ();
}
/****************************************************************************
* SelectMode
****************************************************************************/
@ -342,12 +353,7 @@ int SelectMode ()
writeStatusBar("Choose your mode","");
ShowScreen();
/*** Clear any pending buttons - button 'debounce' ***/
while (PAD_ButtonsHeld (0)
#ifdef HW_RVL
| WPAD_ButtonsHeld(0)
#endif
)
VIDEO_WaitVSync ();
WaitRelease();
for (;;)
{
@ -392,6 +398,7 @@ int SelectMode ()
}
return 500;
}
/*
if (PAD_ButtonsHeld (0) & PAD_TRIGGER_R)//Backup all mode
{
while ((PAD_ButtonsDown (0) & PAD_TRIGGER_R))
@ -400,6 +407,7 @@ int SelectMode ()
}
return 600;
}
*/
while (PAD_ButtonsHeld (0) & PAD_TRIGGER_L)
{
if (PAD_ButtonsHeld (0) & PAD_BUTTON_Y){//Raw backup mode
@ -467,6 +475,7 @@ int SelectMode ()
}
return 500;
}
/*
if (WPAD_ButtonsHeld (0) & WPAD_BUTTON_1)//Backup all mode
{
while ((WPAD_ButtonsDown (0) & WPAD_BUTTON_1))
@ -475,6 +484,7 @@ int SelectMode ()
}
return 600;
}
*/
while (WPAD_ButtonsHeld (0) & WPAD_BUTTON_B)
{
if (WPAD_ButtonsHeld (0) & WPAD_BUTTON_MINUS){//Raw backup mode
@ -543,6 +553,7 @@ void WaitButtonA ()
}
}
#endif
WaitRelease();
}
/****************************************************************************
@ -563,9 +574,15 @@ int WaitButtonAB ()
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)) )
{
WaitRelease();
return 1;
}
else if ( (gc_btns & PAD_BUTTON_B) || (wm_btns & (WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B)) )
{
WaitRelease();
return 0;
}
}
#else
u32 gc_btns;
@ -576,11 +593,18 @@ int WaitButtonAB ()
{
gc_btns = PAD_ButtonsDown (0);
if ( gc_btns & PAD_BUTTON_A )
{
WaitRelease();
return 1;
}
else if ( gc_btns & PAD_BUTTON_B )
{
WaitRelease();
return 0;
}
}
#endif
}
/****************************************************************************
@ -601,9 +625,15 @@ int WaitButtonAZ ()
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)) )
{
WaitRelease();
return 1;
}
else if ( (gc_btns & PAD_TRIGGER_Z) || (wm_btns & (WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_ZR | WPAD_CLASSIC_BUTTON_ZL)) )
{
WaitRelease();
return 0;
}
}
#else
u32 gc_btns;
@ -614,11 +644,18 @@ int WaitButtonAZ ()
{
gc_btns = PAD_ButtonsDown (0);
if ( gc_btns & PAD_BUTTON_A )
{
WaitRelease();
return 1;
}
else if ( gc_btns & PAD_TRIGGER_Z )
{
WaitRelease();
return 0;
}
}
#endif
}
@ -812,14 +849,14 @@ void showSaveInfo(int sel)
DrawHLine (410, 410+160, 162, getcolour (255,255,255));
DrawBox (410, 163, 410+160, 163+39, getcolour (255,255,255));
DrawHLine (410, 410+160, 164+39, getcolour (255,255,255));
DrawBoxFilledGradient(412, 164, (410+158), (164+37), BLUECOL, PURPLECOL);
DrawBoxFilledGradient(412, 164, (410+158), (164+37), BLUECOL, PURPLECOL, LOCATION);
}else
{
//Box for icon
DrawHLine (468, 468+42, 162, getcolour (255,255,255));
DrawBox (468, 163, 468+42, 163+39, getcolour (255,255,255));
DrawHLine (468, 468+42, 164+39, getcolour (255,255,255));
DrawBoxFilledGradient(468+2, 164, (468+40), (164+37), BLUECOL, PURPLECOL);
DrawBoxFilledGradient(468+2, 164, (468+40), (164+37), BLUECOL, PURPLECOL, LOCATION);
}
//Show banner if there is one
@ -919,7 +956,7 @@ void showSaveInfo(int sel)
sprintf(txt, "Time: %02d:%02d:%02d", hour, min, sec);
DrawText(x, y, txt);
y += 20;
sprintf(txt, "Blocks: %d", gci.filesize8);
sprintf(txt, "Blocks: %02d (%d free)", gci.filesize8, FreeBlocks(MEM_CARD));
DrawText(x, y, txt);
y += 20;
//M-> Cant' move the file //C->can't copy the file //P->public file //Most frecuent: xxP
@ -970,7 +1007,7 @@ static void ShowFiles (int offset, int selection, int upordown, int saveinfo) {
ypos = (screenheight - (PAGESIZE * 20+40)) >> 1;
ypos += 26;
j = 0;
for (i = offset; i < (offset + PAGESIZE) && (i < maxfile); i++){
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], textlen);
@ -1010,24 +1047,13 @@ static void ShowFiles (int offset, int selection, int upordown, int saveinfo) {
ypos = (screenheight - (PAGESIZE * 20+40)) >> 1;
ypos += 26;
setfontcolour (0xff, 0xff, 0xff);
//user just pressed up
if (upordown == 1) {
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);
}
DrawText (35, (((selection-offset)+1) * 20) + ypos, text);
}
//user just pressed down
else if (upordown == 2) {
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);
}
DrawText (35, (((selection-offset)-1) * 20) + ypos, text);
//user just pressed up, down, left or right, upordown holds the correction needded
strncpy (text, (char*)filelist[selection+upordown], textlen);
text[textlen] = 0;
for (w = 0; w < 20; w++){
DrawLineFast (35, 330, (((selection-offset)+upordown) * 20) + (ypos - 14) + w, 84, 174,211);
}
DrawText (35, (((selection-offset)+upordown) * 20) + ypos, text);
//Important to call ShowScreen here if we want the redraw to
//appear faster - without it the highlight box glides too much
ShowScreen();
@ -1045,6 +1071,11 @@ static void ShowFiles (int offset, int selection, int upordown, int saveinfo) {
showCardInfo(selection);
}
}
//Draw the page we are on
sprintf (text, "%02.0f/%02.0f", (((selection)/PAGESIZE)+0.9), (((maxfile)/PAGESIZE)+0.9) );
setfontsize(10);
DrawText(298, 80, text);
setfontsize(14);
//Need this to show info update from showSaveInfo
ShowScreen();
}
@ -1140,7 +1171,7 @@ int ShowSelector (int saveinfo)
#ifdef DEBUG_VALUES
u8 fps = 0;
char test[1024];
char text[1024];
#endif
while (quit == 0)
@ -1148,31 +1179,36 @@ int ShowSelector (int saveinfo)
if (redraw)
{
//clear buffers
memset((u8*)bannerdata, 0, CARD_BANNER_W*CARD_BANNER_H*2);
memset((u8*)bannerdataCI, 0, CARD_BANNER_W*CARD_BANNER_H);
memset((u8*)icondata, 0, 8*1024);
memset((u8*)icondataRGB, 0, 8*1024*2);
memset((u8*)tlut, 0, 9*512);
memset((u8*)tlutbanner, 0, 512);
if (saveinfo){
//clear buffers
memset((u8*)bannerdata, 0, CARD_BANNER_W*CARD_BANNER_H*2);
memset((u8*)bannerdataCI, 0, CARD_BANNER_W*CARD_BANNER_H);
memset((u8*)icondata, 0, 8*1024);
memset((u8*)icondataRGB, 0, 8*1024*2);
memset((u8*)tlut, 0, 9*512);
memset((u8*)tlutbanner, 0, 512);
}
ShowFiles (offset, selection, upordown, saveinfo);
//reinit variables
redraw = 0;
currframe = 0;
bounceindex = CARD_MAXICONS;//This ensures getting correct duration values for non-bouncing animations
if (SDCARD_GetIconAnim(gci.banner_fmt) == CARD_ANIM_BOUNCE)
{
bounceindex = 0;
while(SDCARD_GetIconSpeed(gci.icon_speed, bounceindex) != 0 && bounceindex < CARD_MAXICONS)
{
bounceindex++;
}
}
if (saveinfo)
{
currframe = 0;
bounceindex = CARD_MAXICONS;//This ensures getting correct duration values for non-bouncing animations
if (SDCARD_GetIconAnim(gci.banner_fmt) == CARD_ANIM_BOUNCE)
{
bounceindex = 0;
while(SDCARD_GetIconSpeed(gci.icon_speed, bounceindex) != 0 && bounceindex < CARD_MAXICONS)
{
bounceindex++;
}
}
#ifdef USE_TIME
lasttime -= 250;//to ensure first icon will be loaded
#endif
lasttime -= 250;//to ensure first icon will be loaded
#endif
}
}
#ifdef DEBUG_VALUES
@ -1180,7 +1216,7 @@ int ShowSelector (int saveinfo)
sprintf (test, "%d FPS%d numicons%02d lasticon%02d CF%02d LF%03d FT%03d II%02d animtype%d speed%02d", retraceCount, fps, numicons, lasticon, currframe, lastframe, frametable[currframe], iconindex[currframe], SDCARD_GetIconAnim(gci.banner_fmt), SDCARD_GetIconSpeedBounce(gci.icon_speed,currframe,bounceindex)*4 );
ShowAction(test);
#endif
if (lastframe)
if (lastframe && saveinfo)
{
#ifdef USE_TIME
currtime = ticks_to_millisecs(gettime());
@ -1208,7 +1244,7 @@ int ShowSelector (int saveinfo)
else if ( SDCARD_GetIconFmt(gci.icon_fmt,iconindex[currframe])== 2) {
iconloadRGB(icondataRGB[iconindex[currframe]]);
}
//ShowScreen();
ShowScreen();
currframe ++;
if (currframe > lasticon)
@ -1221,10 +1257,21 @@ int ShowSelector (int saveinfo)
#endif
}
p = PAD_ButtonsDown (0);
p = PAD_ButtonsHeld (0);
#ifdef HW_RVL
wp = WPAD_ButtonsDown (0);
wp = WPAD_ButtonsHeld (0);
#endif
//Slow down scrolling a little
if ( (p & PAD_BUTTON_DOWN) | (p & PAD_BUTTON_UP) | (p & PAD_BUTTON_LEFT) | (p & PAD_BUTTON_RIGHT)
#ifdef HW_RVL
| (wp & WPAD_BUTTON_DOWN) | (wp & WPAD_BUTTON_UP) | (wp & WPAD_BUTTON_LEFT) | (wp & WPAD_BUTTON_RIGHT)
#endif
)
{
usleep(50000);
}
if ((p & PAD_BUTTON_B )
#ifdef HW_RVL
| (wp & WPAD_BUTTON_B)
@ -1233,41 +1280,44 @@ int ShowSelector (int saveinfo)
{
offsetchanged = true;
cancel = 1;
lastframe = 0;
return -1;
}
if ((p & PAD_TRIGGER_R)
else if ((p & PAD_TRIGGER_R)
#ifdef HW_RVL
| (wp & WPAD_BUTTON_1)
#endif
)
{
doall = 1;
doall = 1;
lastframe = 0;
return -1;
}
#ifdef HW_RVL
if (power)
else if (power)
{
PowerOff();
}
#endif
if ((p & PAD_BUTTON_A)
else if ((p & PAD_BUTTON_A)
#ifdef HW_RVL
| (wp & WPAD_BUTTON_A)
#endif
)
{
lastframe = 0;
return selection;
}
if ((p & PAD_BUTTON_DOWN)
else if ((p & PAD_BUTTON_DOWN)
#ifdef HW_RVL
| (wp & WPAD_BUTTON_DOWN)
#endif
)
{
upordown = 2;
upordown = -1;
selection++;
if (selection == maxfile)
{
@ -1281,7 +1331,7 @@ int ShowSelector (int saveinfo)
}
redraw = 1;
}
if ((p & PAD_BUTTON_UP)
else if ((p & PAD_BUTTON_UP)
#ifdef HW_RVL
| (wp & WPAD_BUTTON_UP)
#endif
@ -1292,7 +1342,53 @@ int ShowSelector (int saveinfo)
if (selection < 0)
{
selection = maxfile - 1;
offset = selection - PAGESIZE + 1;
offset = selection - PAGESIZE + 1 + (PAGESIZE-(maxfile%PAGESIZE));
offsetchanged = true;
}
if (selection < offset)
{
offset -= PAGESIZE;
offsetchanged = true;
}
if (offset < 0)
{
offset = 0;
}
redraw = 1;
}
else if ((p & PAD_BUTTON_RIGHT)
#ifdef HW_RVL
| (wp & WPAD_BUTTON_RIGHT)
#endif
)
{
upordown = -5;
selection+=5;
if (selection >= maxfile)
{
selection = offset = 0;
offsetchanged = true;
}
if ((selection - offset) >= PAGESIZE)
{
offset += PAGESIZE;
offsetchanged = true;
}
redraw = 1;
}
else if ((p & PAD_BUTTON_LEFT)
#ifdef HW_RVL
| (wp & WPAD_BUTTON_LEFT)
#endif
)
{
upordown = 5;
selection-=5;
if (selection < 0)
{
selection = maxfile - 1;
offset = selection - PAGESIZE + 1 + (PAGESIZE-(maxfile%PAGESIZE));
offsetchanged = true;
}
if (selection < offset)
@ -1324,7 +1420,7 @@ void writeStatusBar( char *line1, char *line2)
void clearLeftPane()
{
int bgcolor = getcolour(84,174,211);
DrawBoxFilled(34, 110, 333, 392, bgcolor);
DrawBoxFilled(34, 72, 333, 392, bgcolor);
}
void clearRightPane()
@ -1372,19 +1468,32 @@ void DrawBoxFilled (int x1, int y1, int x2, int y2, int color)
DrawHLine (x1, x2, h, color);
}
void DrawBoxFilledGradient (int x1, int y1, int x2, int y2, u32 color1, u32 color2)
void DrawBoxFilledGradient (int x1, int y1, int x2, int y2, u32 color1, u32 color2, float location)
{
int r1 = (color1&0x0000FF) >> 0; int g1 = (color1&0x00FF00) >> 8; int b1 = (color1&0xFF0000) >> 16;
int r2 = (color2&0x0000FF) >> 0; int g2 = (color2&0x00FF00) >> 8; int b2 = (color2&0xFF0000) >> 16;
int r,g,b;
int r,g,b, midr, midg, midb;
midr = (r1 * 0.5) + (r2 * (1 - 0.5));
midg = (g1 * 0.5) + (g2 * (1 - 0.5));
midb = (b1 * 0.5) + (b2 * (1 - 0.5));
float p;
int h;
for (h = y1; h <= y2; h++){
p = ((float)(y2-h))/((float)(y2-y1));
r = (r1 * p) + (r2 * (1 - p));
g = (g1 * p) + (g2 * (1 - p));
b = (b1 * p) + (b2 * (1 - p));
if ((y2-h) > (y2-y1)*location)
{
p = ((float)(y2-h)-((y2-y1)*location))/((float)(y2-y1)-((y2-y1)*location));
r = (r1 * p) + (midr * (1 - p));
g = (g1 * p) + (midg * (1 - p));
b = (b1 * p) + (midb * (1 - p));
}
else
{
p = ((float)(y2-h))/((float)(y2-y1)*location);
r = (midr * p) + (r2 * (1 - p));
g = (midg * p) + (g2 * (1 - p));
b = (midb * p) + (b2 * (1 - p));
}
DrawHLine (x1, x2, h, getcolour(r,g,b));
}
}

View File

@ -17,7 +17,7 @@
//Uncomment this definiton to use time lapse for icon duration instead of retrace count
//Time code is mantained as an alternative example of animating the icons
#define USE_TIME
//#define USE_TIME
#ifdef HW_RVL
void initialise_power() ;
@ -45,7 +45,7 @@ void DrawHLine (int x1, int x2, int y, int color);
void DrawVLine (int x, int y1, int y2, int color);
void DrawBox (int x1, int y1, int x2, int y2, int color);
void DrawBoxFilled (int x1, int y1, int x2, int y2, int color);
void DrawBoxFilledGradient (int x1, int y1, int x2, int y2, u32 color1, u32 color2);
void DrawBoxFilledGradient (int x1, int y1, int x2, int y2, u32 color1, u32 color2, float location);
#endif

View File

@ -123,7 +123,8 @@ static int initFAT(int device)
}
}
#else
if (!device){
if (device)
{//Memcard in SLOT B, SD gecko in SLOT A
__io_gcsda.startup();
if (!__io_gcsda.isInserted())
{
@ -137,7 +138,7 @@ static int initFAT(int device)
sleep(1);
return 0;
}
}else
}else //Memcard in SLOT A, SD gecko in SLOT B
{
__io_gcsdb.startup();
if (!__io_gcsdb.isInserted())
@ -644,7 +645,8 @@ int main ()
initialise_power();
have_sd = initFAT(WaitPromptChoice ("Use internal SD or FAT 32 USB device?", "USB", "SD"));
#else
MEM_CARD ^= WaitPromptChoice ("Please select the slot where SD Gecko is inserted", "SLOT B", "SLOT A");
//Returns 1 (memory card in slot B, sd gecko in slot A) if A button was pressed and 0 if B button was pressed
MEM_CARD = WaitPromptChoice ("Please select the slot where SD Gecko is inserted", "SLOT B", "SLOT A");
have_sd = initFAT(MEM_CARD);
#endif

View File

@ -117,9 +117,54 @@ int MountCard(int cslot)
return isMounted;
}
/*** If this point is reached, something went wrong ***/
CARD_Unmount(cslot);
return ret;
}
u16 FreeBlocks(s32 chn)
{
s32 err;
static u8 noinserted = 0;
u16 freeblocks = 0;
/*** Try to mount the card ***/
err = MountCard(chn);
if (err < 0)
{
//We want to allow browsing saves in sd even with no card
if (err == CARD_ERROR_NOCARD)
{
noinserted = 1;
if(chn) ShowAction("No card inserted in slot B!");
else ShowAction("No card inserted in slot A!");
return 0;
}else
{
WaitCardError("CardMount", err);
return 0; /*** Unable to mount the card ***/
}
}else{
err = CARD_GetFreeBlocks(chn, &freeblocks);
if (err < 0)
{
CARD_Unmount(chn);
//We want to allow browsing saves in sd even with no card
if (err == CARD_ERROR_NOCARD)
{
noinserted = 1;
if(chn) ShowAction("No card inserted in slot B!");
else ShowAction("No card inserted in slot A!");
return 0;
}else
{
WaitCardError("FreeBlocks", err);
return 0;
}
}
}
if (noinserted) ShowAction("");
CARD_Unmount(chn);
return freeblocks;
}
/****************************************************************************
* GCIMakeHeader
@ -541,6 +586,7 @@ int CardWriteFile (int slot)
int offset;
int written;
int filelen;
char txt[128];
company[2] = gamecode[4] = 0;
@ -572,9 +618,11 @@ int CardWriteFile (int slot)
if (((u32)CardDir.gamecode == (u32)gamecode) && (strcmp ((char *) CardDir.filename, (char *)filename) == 0))
{
/*** Found the file - prompt user ***/
ret = WaitPromptChoice("File already exists. Overwrite?", "Overwrite", "Cancel");
sprintf(txt, "File %s already exists. Overwrite?", (char *)filename);
ret = WaitPromptChoice(txt, "Overwrite", "Cancel");
if (!ret){
ret = WaitPromptChoiceAZ("Are you -SURE- you want to overwrite?", "Overwrite", "Cancel");
sprintf(txt, "Are you -SURE- you want to overwrite %s?", (char *)filename);
ret = WaitPromptChoiceAZ(txt, "Overwrite", "Cancel");
if(!ret){
err = CARD_Delete(slot, (char *) &filename);
if (err < 0)
@ -609,9 +657,11 @@ tryagain:
if (err == CARD_ERROR_EXIST)
{
/*** Found the file - prompt user ***/
ret = WaitPromptChoice("File already exists. Overwrite?", "Overwrite", "Cancel");
sprintf(txt, "File %s already exists. Overwrite?", (char *) filename);
ret = WaitPromptChoice(txt, "Overwrite", "Cancel");
if (!ret){
ret = WaitPromptChoiceAZ("Are you -SURE- you want to overwrite?", "Overwrite", "Cancel");
sprintf(txt, "Are you -SURE- you want to overwrite %s?", (char *) filename);
ret = WaitPromptChoiceAZ(txt, "Overwrite", "Cancel");
if(!ret){
err = CARD_Delete(slot, (char *) &filename);
if (err < 0)

View File

@ -6,7 +6,8 @@
void GCIMakeHeader();
void ExtractGCIHeader();
int MountCard(int cslot);
int MountCard(int cslot);
u16 FreeBlocks(s32 chn);
int CardGetDirectory (int slot);
void CardListFiles ();
int CardReadFileHeader (int slot, int id);

View File

@ -17,8 +17,14 @@
#include "raw.h"
#define mem_free(x) {free(x);x=NULL;}
//Enabling this definition will enable additional checks to ensure raw restore worked
#define DEBUGRAW
u8 *CardBuffer = 0;
#ifdef DEBUGRAW
u8 *CheckBuffer = 0;
u8 *EraseCheckBuffer = 0;
#endif
s8 read_data = 0;
s8 write_data = 0;
s8 erase_data = 0;
@ -109,6 +115,7 @@ u64 Card_SerialNo(s32 slot)
if(err < 0 )
{
WaitCardError("SerialNo Sectsize", err);
CARD_Unmount(slot);
return -1;
}
@ -116,6 +123,7 @@ u64 Card_SerialNo(s32 slot)
if(CardBuffer == NULL)
{
WaitPrompt("SerialNo: Failed to malloc memory.");
CARD_Unmount(slot);
return -1;
}
s32 current_block = 0;
@ -127,6 +135,7 @@ u64 Card_SerialNo(s32 slot)
if( (err != 0) || current_block >= 1)
break;
DCInvalidateRange(CardBuffer+SectorSize*current_block,SectorSize);
err = __card_read(slot,0,SectorSize,CardBuffer+SectorSize*current_block,_read_callback);
if(err == 0)
{
@ -140,6 +149,7 @@ u64 Card_SerialNo(s32 slot)
{
mem_free(CardBuffer);
WaitCardError("BakRaw __read", err);
CARD_Unmount(slot);
return -1;
}
}
@ -153,6 +163,7 @@ u64 Card_SerialNo(s32 slot)
u64 serialA = serial1[0]^serial1[1]^serial1[2]^serial1[3];
mem_free(CardBuffer);
CARD_Unmount(slot);
return serialA;
}
@ -222,6 +233,7 @@ s8 BackupRawImage(s32 slot, s32 *bytes_writen )
if(err < 0 )
{
WaitCardError("BakRaw Sectsize", err);
CARD_Unmount(slot);
return -1;
}
@ -229,6 +241,7 @@ s8 BackupRawImage(s32 slot, s32 *bytes_writen )
if(err < 0 )
{
WaitCardError("BakRaw Blockcount", err);
CARD_Unmount(slot);
return -1;
}
CardBuffer = (u8*)memalign(32,SectorSize*BlockCount);
@ -236,6 +249,7 @@ s8 BackupRawImage(s32 slot, s32 *bytes_writen )
{
//printf("failed to malloc memory. fail\n");
WaitPrompt("BackRaw: Failed to malloc memory.");
CARD_Unmount(slot);
return -1;
}
s32 current_block = 0;
@ -260,6 +274,7 @@ s8 BackupRawImage(s32 slot, s32 *bytes_writen )
mem_free(CardBuffer);
//printf("can not create file on SD\n");
WaitPrompt("BackRaw: cannot create file on SD.");
CARD_Unmount(slot);
return -1;
}
//printf("dumping...\n");
@ -267,10 +282,11 @@ s8 BackupRawImage(s32 slot, s32 *bytes_writen )
{
read_data = 0;
//printf("\rReading : %u bytes of %u (block %d)...",read,BlockCount*SectorSize,current_block);
sprintf(msg, "Reading... : Block %d of %d (%u bytes of %u)",current_block,BlockCount,read,BlockCount*SectorSize);
sprintf(msg, "Reading...: Block %d of %d (%u bytes of %u)",current_block,BlockCount,read,BlockCount*SectorSize);
writeStatusBar(msg, "");
if( (err != 0) || current_block >= BlockCount)
break;
DCInvalidateRange(CardBuffer+SectorSize*current_block,SectorSize);
err = __card_read(slot,SectorSize*current_block,SectorSize,CardBuffer+SectorSize*current_block,_read_callback);
if(err == 0)
{
@ -286,6 +302,7 @@ s8 BackupRawImage(s32 slot, s32 *bytes_writen )
//printf("\nerror reading data : %d...\n",err);
fclose(dumpFd);
WaitCardError("BakRaw __read", err);
CARD_Unmount(slot);
return -1;
}
}
@ -302,6 +319,7 @@ s8 BackupRawImage(s32 slot, s32 *bytes_writen )
if(bytes_writen != NULL)
*bytes_writen = writen;
mem_free(CardBuffer);
CARD_Unmount(slot);
return 1;
}
@ -329,6 +347,7 @@ s8 RestoreRawImage( s32 slot, char *sdfilename, s32 *bytes_writen )
if(err < 0 )
{
WaitCardError("RestRaw Sectsize", err);
CARD_Unmount(slot);
return -1;
}
@ -336,6 +355,7 @@ s8 RestoreRawImage( s32 slot, char *sdfilename, s32 *bytes_writen )
if(err < 0 )
{
WaitCardError("RestRaw Blockcount", err);
CARD_Unmount(slot);
return -1;
}
CardBuffer = (u8*)memalign(32,SectorSize*BlockCount);
@ -343,8 +363,29 @@ s8 RestoreRawImage( s32 slot, char *sdfilename, s32 *bytes_writen )
{
//printf("failed to malloc memory. fail\n");
WaitPrompt("RestRaw: Failed to malloc memory.");
CARD_Unmount(slot);
return -1;
}
#ifdef DEBUGRAW
CheckBuffer = (u8*)memalign(32,SectorSize);
if(CheckBuffer == NULL)
{
mem_free(CardBuffer);
WaitPrompt("RestRaw: Failed to malloc memory (CheckBuffer)");
CARD_Unmount(slot);
return -1;
}
EraseCheckBuffer = (u8*)memalign(32,SectorSize);
if(CheckBuffer == NULL)
{
mem_free(CardBuffer);
mem_free(CheckBuffer);
WaitPrompt("RestRaw: Failed to malloc memory (EraseCheckBuffer)");
CARD_Unmount(slot);
return -1;
}
memset(EraseCheckBuffer, 0xFF, SectorSize);
#endif
/*** Make fullpath filename ***/
@ -355,8 +396,13 @@ s8 RestoreRawImage( s32 slot, char *sdfilename, s32 *bytes_writen )
if (dumpFd <= 0)
{
mem_free(CardBuffer);
#ifdef DEBUGRAW
mem_free(CheckBuffer);
mem_free(EraseCheckBuffer);
#endif
sprintf(msg, "Couldn't open %s", filename);
WaitPrompt (msg);
CARD_Unmount(slot);
return -1;
}
@ -372,7 +418,12 @@ s8 RestoreRawImage( s32 slot, char *sdfilename, s32 *bytes_writen )
//incorrect dump size D:<
fclose(dumpFd);
mem_free(CardBuffer);
#ifdef DEBUGRAW
mem_free(CheckBuffer);
mem_free(EraseCheckBuffer);
#endif
WaitPrompt ("Card and image sizes differ");
CARD_Unmount(slot);
return -1;
}
}
@ -416,7 +467,7 @@ s8 RestoreRawImage( s32 slot, char *sdfilename, s32 *bytes_writen )
while( 1 )
{
//printf("\rWriting... : %d of %d (block %d)",writen,BlockCount*SectorSize,current_block);
sprintf(msg, "Writing... : Block %d of %d (%d of %d)",current_block,BlockCount,writen,BlockCount*SectorSize);
sprintf(msg, "Writing...: Block %d of %d (%d of %d)",current_block,BlockCount,writen,BlockCount*SectorSize);
ShowAction (msg);
//gprintf("\rWriting... : %d of %d (block %d of %d)",writen,BlockCount*SectorSize,current_block,BlockCount);
write_data = 0;
@ -424,6 +475,7 @@ s8 RestoreRawImage( s32 slot, char *sdfilename, s32 *bytes_writen )
if( (err != 0) || current_block >= BlockCount || writen == BlockCount*SectorSize)
break;
//DCStoreRange is called in card.c before actual writing to the card
DCStoreRange(CardBuffer+writen,write_len);
if(writen == 0 || !(writen%SectorSize)){
//s32 __card_sectorerase(s32 chn,u32 sector,cardcallback callback);
@ -433,13 +485,63 @@ s8 RestoreRawImage( s32 slot, char *sdfilename, s32 *bytes_writen )
while(erase_data == 0)
usleep(1*1000); //sleep untill the erase is done which sadly takes alot longer then read
__card_sync(slot);
#ifdef DEBUGRAW
memset(CheckBuffer,0,write_len);
DCInvalidateRange(CheckBuffer,write_len);
read_data = 0;
err = __card_read(slot,writen,write_len,CheckBuffer,_read_callback);
while(read_data == 0)
usleep(1*1000);
if(err == 0)
{
if(!memcmp(EraseCheckBuffer,CheckBuffer,write_len))
{
//printf("read and write are the same y0\n");
}
else
{
//Uncomment to dump contents that where read
FILE* dump = fopen("fat:/sectcheck_dump.bin","wb");
//fwrite((u8*)ptr+writen,sizeof(u32),1,dumpFd);
fwrite(CheckBuffer,1,write_len,dump);
fclose(dump);
fclose(dumpFd);
mem_free(CardBuffer);
mem_free(CheckBuffer);
mem_free(EraseCheckBuffer);
sprintf(msg, "Error! _sectorerase failed for unknown reasons at sector %d!", current_block);
WaitPrompt (msg);
CARD_Unmount(slot);
return -1;
}
}
else
{
fclose(dumpFd);
mem_free(CardBuffer);
mem_free(CheckBuffer);
mem_free(EraseCheckBuffer);
sprintf(msg, "Error reading data(%d) Memory card could be corrupt now!!!",err);
WaitPrompt (msg);
CARD_Unmount(slot);
return -1;
}
#endif
}else
{
fclose(dumpFd);
mem_free(CardBuffer);
#ifdef DEBUGRAW
mem_free(CheckBuffer);
mem_free(EraseCheckBuffer);
#endif
//printf("\nerror writing data(%d) Memory card could be corrupt now!!!\n",err);
sprintf(msg, "error erasing sector(%d) Memory card could be corrupt now!!!",err);
WaitPrompt (msg);
CARD_Unmount(slot);
return -1;
}
}
@ -451,7 +553,53 @@ s8 RestoreRawImage( s32 slot, char *sdfilename, s32 *bytes_writen )
usleep(1*1000); //sleep untill the write is done which sadly takes alot longer then read
__card_sync(slot);
#ifdef DEBUGRAW
memset(CheckBuffer,0,write_len);
DCInvalidateRange(CheckBuffer,write_len);
read_data = 0;
//err = __card_read(slot,SectorSize*current_block,SectorSize,CheckBuffer,_read_callback);
err = __card_read(slot,writen,write_len,CheckBuffer,_read_callback);
while(read_data == 0)
usleep(1*1000);
if(err == 0)
{
if(!memcmp(CardBuffer+writen,CheckBuffer,write_len))
{
//printf("read and write are the same y0\n");
}
else
{
//printf("different data. writing to SD (0x%08X), error %d\n",*check,CardError);
//Uncomment to dump contents that where read
FILE* dump = fopen("fat:/check_dump.bin","wb");
//fwrite((u8*)ptr+writen,sizeof(u32),1,dumpFd);
fwrite(CheckBuffer,1,write_len,dump);
fclose(dump);
fclose(dumpFd);
mem_free(CardBuffer);
mem_free(CheckBuffer);
mem_free(EraseCheckBuffer);
sprintf(msg, "Error! Writing failed for unknown reasons at block %d!", current_block);
WaitPrompt (msg);
CARD_Unmount(slot);
return -1;
}
}
else
{
fclose(dumpFd);
mem_free(CardBuffer);
mem_free(CheckBuffer);
mem_free(EraseCheckBuffer);
sprintf(msg, "Error reading data(%d) Memory card could be corrupt now!!!",err);
WaitPrompt (msg);
CARD_Unmount(slot);
return -1;
}
#endif
writen = writen + write_len;
upblock=upblock+write_len;
if(upblock == SectorSize)
@ -464,9 +612,14 @@ s8 RestoreRawImage( s32 slot, char *sdfilename, s32 *bytes_writen )
{
fclose(dumpFd);
mem_free(CardBuffer);
#ifdef DEBUGRAW
mem_free(CheckBuffer);
mem_free(EraseCheckBuffer);
#endif
//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);
CARD_Unmount(slot);
return -1;
}
}
@ -475,11 +628,21 @@ s8 RestoreRawImage( s32 slot, char *sdfilename, s32 *bytes_writen )
if(bytes_writen != NULL)
*bytes_writen = writen;
mem_free(CardBuffer);
#ifdef DEBUGRAW
mem_free(CheckBuffer);
mem_free(EraseCheckBuffer);
#endif
CARD_Unmount(slot);
return 1;
}
}
mem_free(CardBuffer);
#ifdef DEBUGRAW
mem_free(CheckBuffer);
mem_free(EraseCheckBuffer);
#endif
CARD_Unmount(slot);
return -1;
}