summaryrefslogtreecommitdiff
path: root/gui
diff options
context:
space:
mode:
authorSND\ckain_cp <SND\ckain_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97>2014-05-22 10:36:14 +0000
committerSND\ckain_cp <SND\ckain_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97>2014-05-22 10:36:14 +0000
commit4e6b79edcc8d9a1d8d2d7c30d850aebb17c05cfc (patch)
tree4c2ae8edb85882857b8986b81f3a42c417bbcb07 /gui
parentbc9abb12a5632d450f6f6ba831c48ac0c020386e (diff)
downloadpcsxr-4e6b79edcc8d9a1d8d2d7c30d850aebb17c05cfc.tar.gz
gtk/memcard: fragmented multi block copy/delete fix..
git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@90494 e17a0e51-4ae3-4d35-97c3-1a29b211df97
Diffstat (limited to 'gui')
-rwxr-xr-xgui/GtkGui.c4
-rwxr-xr-xgui/MemcardDlg.c161
2 files changed, 104 insertions, 61 deletions
diff --git a/gui/GtkGui.c b/gui/GtkGui.c
index f783c669..04fbcd36 100755
--- a/gui/GtkGui.c
+++ b/gui/GtkGui.c
@@ -1182,7 +1182,7 @@ void SysErrorMessage(gchar *primary, gchar *secondary) {
primary,
NULL);
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(message_dialog),
- "s", secondary);
+ "%s", secondary);
gtk_dialog_run(GTK_DIALOG(message_dialog));
gtk_widget_destroy(message_dialog);
@@ -1201,7 +1201,7 @@ void SysInfoMessage(gchar *primary, gchar *secondary) {
primary,
NULL);
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(message_dialog),
- "s", secondary);
+ "%s", secondary);
gtk_dialog_run(GTK_DIALOG(message_dialog));
gtk_widget_destroy(message_dialog);
diff --git a/gui/MemcardDlg.c b/gui/MemcardDlg.c
index 49659516..9d4fd5bb 100755
--- a/gui/MemcardDlg.c
+++ b/gui/MemcardDlg.c
@@ -35,7 +35,9 @@
#define ISLINKBLOCK(Info) (ISLINKENDBLOCK((Info)) || ISLINKMIDBLOCK((Info)))
#define ISDELETED(Info) (((Info)->Flags & 0xF) >= 1 && ((Info)->Flags & 0xF) <= 3)
#define ISBLOCKDELETED(Info) (((Info)->Flags & 0xF0) == 0xA0)
-#define ISSTATUSDELETED(Info) (ISBLOCKDELETED(Info) && ISDELETED(Info))
+#define ISSTATUSDELETED(Info) (ISBLOCKDELETED(Info) && ISDELETED(Info))
+#define ISLINKED(Data) ((Data) != 0xFFFFU)
+#define GETLINKFORBLOCK(Data, block) (*((Data)+(((block)*128)+0x08)))
static gboolean quit;
static unsigned int currentIcon;
@@ -139,6 +141,17 @@ static gchar* MCDStatusToChar(McdBlock *Info) {
return state;
}
+u8 GetLinkReference(char* mcddata, const u8 block) {
+ u8 i;
+ for (i=0; i < MAX_MEMCARD_BLOCKS; i++) {
+ u16 link = GETLINKFORBLOCK(mcddata, i);
+ if (link == block) {
+ return i;
+ }
+ }
+ return 0;
+}
+
static void OnTreeSelectionChanged(GtkTreeSelection *selection, gpointer user_data);
static void LoadListItems(int mcd, boolean newstore) {
int i;
@@ -148,11 +161,17 @@ static void LoadListItems(int mcd, boolean newstore) {
GtkTreeIter iter;
GdkPixbuf *pixbuf;
gchar *title;
+ char *mcddata;
dialog = GTK_WIDGET(gtk_builder_get_object(builder, "McdsDlg"));
- if (mcd == 1) List = GTK_WIDGET(gtk_builder_get_object(builder, "GtkCList_McdList1"));
- else List = GTK_WIDGET(gtk_builder_get_object(builder, "GtkCList_McdList2"));
+ if (mcd == 1) {
+ mcddata = Mcd1Data;
+ List = GTK_WIDGET(gtk_builder_get_object(builder, "GtkCList_McdList1"));
+ } else {
+ mcddata = Mcd2Data;
+ List = GTK_WIDGET(gtk_builder_get_object(builder, "GtkCList_McdList2"));
+ }
if (newstore) {
store = gtk_list_store_new(NUM_CL, GDK_TYPE_PIXBUF, G_TYPE_STRING,
@@ -165,7 +184,7 @@ static void LoadListItems(int mcd, boolean newstore) {
for (i = 0; i < MAX_MEMCARD_BLOCKS; i++) {
McdBlock *Info;
const gchar *state;
- short* iconlinkptr;
+ short* iconlinkptr, iconcount;
Info = &Blocks[mcd - 1][i];
IconC[mcd - 1][i] = 0;
@@ -173,11 +192,10 @@ static void LoadListItems(int mcd, boolean newstore) {
if (ISSTATUSDELETED(Info)) {
iconlinkptr = IconDeleted;
- } else if (!newstore && Info->IconCount > 0) {
- iconlinkptr = &Info->Icon[(currentIcon % Info->IconCount) * ICON_SIZE];
- } else if (!ISLINKBLOCK(Info)) {
- //} else if (strcmp(state, _("Link")) != 0 && strcmp(state, _("End link")) != 0) {
- iconlinkptr = Info->Icon;
+ //} else if (ISLINKBLOCK(Info)) { // TODO link icons exists or not?
+ } else {
+ iconcount = Info->IconCount>0?Info->IconCount:1;
+ iconlinkptr = &Info->Icon[(currentIcon % iconcount) * ICON_SIZE];
}
pixbuf = SetIcon(dialog, iconlinkptr, 2);
@@ -375,15 +393,16 @@ static void OnMcd_New(GtkWidget *widget, gpointer user_data) {
g_free(path);
}
-static int GetFreeMemcardSlot(gint target_card, gint count) {
+static int GetFreeMemcardSlot(gint target_card, gint count, u8* blocks) {
McdBlock *Info;
gint foundcount=0, i=-1;
- // search for empty (formatted) blocks first
+ /* If we want to prefer consecutive blocks...
+ // search for consecutive blocks
while (i < MAX_MEMCARD_BLOCKS && foundcount < count) {
Info = &Blocks[target_card][++i];
if ((Info->Flags & 0xFF) == 0xA0) { // if A0 but not A1
- foundcount++;
+ blocks[foundcount++] = i+1;
} else if (foundcount >= 1) { // need to find n count consecutive blocks
foundcount=0;
} else {
@@ -392,24 +411,34 @@ static int GetFreeMemcardSlot(gint target_card, gint count) {
}
if (foundcount == count)
- return (i-foundcount+1);
+ return foundcount;
+ memset(blocks, 0x0, MAX_MEMCARD_BLOCKS*sizeof(u8));
+ */
- // no free formatted slots, try to find a deleted one
- foundcount=0;
- i = -1;
+ // search for empty (formatted) blocks first
while (i < MAX_MEMCARD_BLOCKS && foundcount < count) {
Info = &Blocks[target_card][++i];
- if ((Info->Flags & 0xF0) == 0xA0) { // A2 or A6 f.e.
- foundcount++;
- } else if (foundcount >= 1) { // need to find n count consecutive blocks
- foundcount=0;
- } else {
+ if ((Info->Flags & 0xFF) == 0xA0) { // if A0 but not A1
+ blocks[foundcount++] = i+1;
}
- //printf("delstatus=%x\n", Info->Flags);
}
+ //printf("formatstatus1=%i %i\n", foundcount, count);
if (foundcount == count)
- return (i-foundcount+1);
+ return foundcount;
+
+ // not enough free formatted slots, try to find deleted ones
+ i = -1;
+ while (i < MAX_MEMCARD_BLOCKS && foundcount < count) {
+ Info = &Blocks[target_card][++i];
+ if ((Info->Flags & 0xFF) > 0xA0) { // A2 or A6 f.e.
+ blocks[foundcount++] = i+1;
+ } //printf("delstatus=%x\n", Info->Flags);
+ }
+
+ //printf("formatstatus2=%i %i\n", foundcount, count);
+ if (foundcount == count)
+ return foundcount;
return -1;
}
@@ -418,7 +447,7 @@ void CopyMemcardData(char *from, char *to, gint srci, gint dsti,
gchar *str, u16 linkindex) {
u16* linkptr;
u8* checksumptr;
- dsti += 1; srci += 1;
+
// header
memcpy(to + dsti * 128, from + srci * 128, 128);
@@ -444,23 +473,22 @@ void CopyMemcardData(char *from, char *to, gint srci, gint dsti,
//printf("data = %s\n", from + (srci+1) * 128);
}
-gint GetMcdBlockCount(gint mcd, gint startblock) {
- McdBlock b;
- gint i;
-
- // check status on startblock+1...n
- for (i=1; i <= (MAX_MEMCARD_BLOCKS-startblock); i++) {
- GetMcdBlockInfo(mcd, startblock+i, &b);
- //printf("i=%i, mcd=%i, startblock=%i, diff=%i, flags=%x\n", i, mcd, startblock, (MAX_MEMCARD_BLOCKS-startblock), b.Flags);
- if (ISLINKENDBLOCK(&b)) {
- return i+1;
- } else if (ISLINKMIDBLOCK(&b)) {
- //i++
- } else {
- return i;
- }
- }
- return i; // startblock was the last block so count = 1
+gint GetMcdBlockCount(gint mcd, u8 startblock, u8* blocks) {
+ gint i=0;
+ u8 *data, *dataT, curblock=startblock;
+ u16 linkblock;
+
+ if (mcd == 1) data = Mcd1Data;
+ if (mcd == 2) data = Mcd2Data;
+
+ blocks[i++] = startblock;
+ do {
+ dataT = data+((curblock*128)+0x08);
+ linkblock = ((u16*)dataT)[0];
+ blocks[i++] = curblock = linkblock+1;
+ //printf("LINKS %i %x\n", i-1, linkblock);
+ } while (ISLINKED(linkblock));
+ return i-1;
}
static void OnMcd_CopyTo(GtkWidget *widget, gpointer user_data) {
@@ -470,10 +498,12 @@ static void OnMcd_CopyTo(GtkWidget *widget, gpointer user_data) {
GtkTreeIter iter;
GtkTreeModel *model;
GtkTreePath *path;
- gint *i, j, count, srci, first_free_slot;
+ gint *i, j, count, srci, free_slots;
GtkTreeSelection *treesel;
gchar *str;
char *source, *destination;
+ u8* srctbl = calloc(MAX_MEMCARD_BLOCKS, sizeof(u8));
+ u8* dsttbl = calloc(MAX_MEMCARD_BLOCKS, sizeof(u8));
if (dstmcd == 1) {
treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(GtkCList_McdList2));
@@ -492,16 +522,16 @@ static void OnMcd_CopyTo(GtkWidget *widget, gpointer user_data) {
gtk_tree_path_free(path);
}
- // get how many blocks there are including linked blocks
- count = GetMcdBlockCount(srcmcd, (srci+1));
+ // get how many blocks source is (including linked blocks)
+ count = GetMcdBlockCount(srcmcd, (srci+1), srctbl);
// Determine the first free slot in the target memory card
- first_free_slot = GetFreeMemcardSlot((dstmcd - 1), count);
- if (first_free_slot == -1) {
+ free_slots = GetFreeMemcardSlot((dstmcd - 1), count, dsttbl);
+ if (free_slots == -1) {
// No free slots available on the destination card
SysErrorMessage(_("No free space on memory card"),
_("There are no free slots available on the target memory card. Please delete a slot first."));
- return;
+ goto ret;
}
if (dstmcd == 1) {
@@ -514,20 +544,24 @@ static void OnMcd_CopyTo(GtkWidget *widget, gpointer user_data) {
destination = Mcd2Data;
}
- for (j=0; j < count; j++) {
- // TODO: possibility of copying multi block saves around card
- // when specifying last parameter linkindex with next index
+ for (j=0; srctbl[j] > 0; j++) {
+ // last parameter specifies link index (next block)
CopyMemcardData(source, destination,
- (srci+j), (first_free_slot+j), str, (first_free_slot+j+1));
- //printf("count = %i, firstfree=%i, i=%i\n", count, first_free_slot, j);
+ srctbl[j], dsttbl[j], str, dsttbl[j+1]);
+ //printf("count = %i, indices=(%x,%x) jindex=%i\n", count, srctbl[j], dsttbl[j], j);
}
UpdateMcdDlg(widget);
+
+ret:
+ free(srctbl);
+ free(dsttbl);
}
static void OnMemcardDelete(GtkWidget *widget, gpointer user_data) {
- McdBlock *Info, *NextInfo;
- int i, xorsum, j;
+ McdBlock *Info;
+ int xorsum, j;
+ u16 i, starti;
char *data, *ptr;
GtkTreeIter iter;
GtkTreeModel *model;
@@ -555,14 +589,20 @@ static void OnMemcardDelete(GtkWidget *widget, gpointer user_data) {
if (selected) {
path = gtk_tree_model_get_path(model, &iter);
- i = *gtk_tree_path_get_indices(path);
+ i = starti = *gtk_tree_path_get_indices(path) + 1;
// Delete selected file and all linked blocks also (flag value 2 or 3)
do {
- i++;
ptr = data + i * 128;
Info = &Blocks[memcard - 1][i - 1];
- NextInfo = &Blocks[memcard - 1][i - 0];
+ //printf("Deleting %s %x (%i)\n", Info->ID, Info->Flags, i);
+
+ // N iter: check if link was valid but pointed to normal block
+ if (i!=starti && !ISLINKBLOCK(Info)) {
+ SysErrorMessage(_("Memory card is corrupted"),
+ _("Link block pointed to normal block which is not allowed."));
+ break;
+ }
if ((Info->Flags & 0xF0) == 0xA0) {
if ((Info->Flags & 0xF) >= 1 &&
@@ -577,9 +617,12 @@ static void OnMemcardDelete(GtkWidget *widget, gpointer user_data) {
xorsum ^= *ptr++;
}
*ptr = xorsum;
- //printf("Info %s %i NextInfo %s %i (%i)\n", Info->ID, Info->Flags, NextInfo->ID, NextInfo->Flags, i);
+
SaveMcd((char *)filename, data, i * 128, 128);
- } while (i < MAX_MEMCARD_BLOCKS && (ISLINKBLOCK(NextInfo)));
+
+ // Check links
+ i = GETLINKFORBLOCK(data, i);
+ } while (i <= MAX_MEMCARD_BLOCKS);
UpdateMcdDlg(widget);
}