mirror of
https://github.com/Ryuzaki-MrL/savemii.git
synced 2026-03-21 17:54:06 -05:00
Working on CBHC, add Title sorting, add L-Stick to navigate menus, show number of Titles, show user ID beside <this user>
This commit is contained in:
parent
15db7f0390
commit
46b5b08f32
|
|
@ -2,14 +2,14 @@
|
|||
<app version="1">
|
||||
<name>SaveMii</name>
|
||||
<coder>Ryuzaki_MrL original (GabyPCgeeK mod)</coder>
|
||||
<version>1.2.0.m1</version>
|
||||
<release_date>20170429000000</release_date>
|
||||
<version>1.2.0.m2</version>
|
||||
<release_date>20170707000000</release_date>
|
||||
<short_description>WiiU/vWii Save Manager</short_description>
|
||||
<long_description>WiiU/vWii Save Manager
|
||||
|
||||
You need to run iosuhax/mocha cfw first in order for this homebrew to work.
|
||||
You need to run haxchi/iosuhax/mocha cfw first in order for this homebrew to work.
|
||||
|
||||
This homebrew allows you to backup your Wii U and vWii savegames to the SD card and also restore them. Can also copy saves from NAND<->USB if title is installed to both. Up to 256 backups can be made per title. Backups are stored in sd:/wiiu/backups.</long_description>
|
||||
<category>tool</category>
|
||||
<url>https://github.com/Ryuzaki-MrL/savemii/releases</url>
|
||||
</app>
|
||||
</app>
|
||||
|
|
|
|||
|
|
@ -51,6 +51,21 @@ void updateReleasedButtons() {
|
|||
buttons_released = vpad.btns_r;
|
||||
}
|
||||
|
||||
bool stickPos(u8 stick, f32 value) {
|
||||
switch(stick) {
|
||||
case 0 :
|
||||
return (value > 0) ? (vpad.lstick.x > value): (vpad.lstick.x < value);
|
||||
case 1 :
|
||||
return ((value > 0) ? (vpad.lstick.y > value): (vpad.lstick.y < value));
|
||||
case 2 :
|
||||
return (value > 0) ? (vpad.rstick.x > value): (vpad.rstick.x < value);
|
||||
case 3 :
|
||||
return (value > 0) ? (vpad.rstick.y > value): (vpad.rstick.y < value);
|
||||
default :
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int isPressed(int button) {
|
||||
return (buttons_pressed&button);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ void flipBuffers();
|
|||
void updatePressedButtons();
|
||||
void updateHeldButtons();
|
||||
void updateReleasedButtons();
|
||||
bool stickPos(u8 stick, f32 value);
|
||||
int isPressed(int button);
|
||||
int isHeld(int button);
|
||||
int isReleased(int button);
|
||||
|
|
|
|||
91
src/main.c
91
src/main.c
|
|
@ -15,10 +15,11 @@
|
|||
|
||||
u8 slot = 0;
|
||||
bool allusers = 0, common = 1;
|
||||
int menu = 0, mode = 0, task = 0, targ = 0;
|
||||
int menu = 0, mode = 0, task = 0, targ = 0, tsort = 0, sorta = 1;
|
||||
int cursor = 0, scroll = 0;
|
||||
int cursorb = 0, scrollb = 0;
|
||||
int titleswiiu = 0, titlesvwii = 0;
|
||||
const char *sortn[4] = {"None", "Name", "Storage", "Storage+Name"};
|
||||
|
||||
//just to be able to call async
|
||||
void someFunc(void *arg) {
|
||||
|
|
@ -51,17 +52,45 @@ void MCPHookClose() {
|
|||
mcp_hook_fd = -1;
|
||||
}
|
||||
|
||||
Title* loadWiiUTitles() {
|
||||
int titleSort(const void *c1, const void *c2)
|
||||
{
|
||||
if (tsort==0) {
|
||||
return ((Title*)c1)->listID - ((Title*)c2)->listID;
|
||||
} else if (tsort==1) {
|
||||
return strcmp(((Title*)c1)->shortName,((Title*)c2)->shortName) * sorta;
|
||||
} else if (tsort==2) {
|
||||
if (((Title*)c1)->isTitleOnUSB == ((Title*)c2)->isTitleOnUSB)
|
||||
return 0;
|
||||
if (((Title*)c1)->isTitleOnUSB)
|
||||
return 1 * sorta;
|
||||
if (((Title*)c2)->isTitleOnUSB)
|
||||
return -1 * sorta;
|
||||
return 0;
|
||||
} else if (tsort==3) {
|
||||
if (((Title*)c1)->isTitleOnUSB && !((Title*)c2)->isTitleOnUSB)
|
||||
return 1 * sorta;
|
||||
if (!((Title*)c1)->isTitleOnUSB && ((Title*)c2)->isTitleOnUSB)
|
||||
return -1 * sorta;
|
||||
|
||||
return strcmp(((Title*)c1)->shortName,((Title*)c2)->shortName) * sorta;
|
||||
}
|
||||
}
|
||||
|
||||
Title* loadWiiUTitles(int run) {
|
||||
static char *tList;
|
||||
static int receivedCount;
|
||||
// Source: haxchi installer
|
||||
int mcp_handle = MCP_Open();
|
||||
int count = MCP_TitleCount(mcp_handle);
|
||||
int listSize = count*0x61;
|
||||
char *tList = memalign(32, listSize);
|
||||
memset(tList, 0, listSize);
|
||||
int receivedCount = count;
|
||||
MCP_TitleList(mcp_handle, &receivedCount, tList, listSize);
|
||||
MCP_Close(mcp_handle);
|
||||
if (run == 0) {
|
||||
int mcp_handle = MCP_Open();
|
||||
int count = MCP_TitleCount(mcp_handle);
|
||||
int listSize = count*0x61;
|
||||
tList = memalign(32, listSize);
|
||||
memset(tList, 0, listSize);
|
||||
receivedCount = count;
|
||||
MCP_TitleList(mcp_handle, &receivedCount, tList, listSize);
|
||||
MCP_Close(mcp_handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Title* titles = malloc(receivedCount*sizeof(Title));
|
||||
if (!titles) {
|
||||
|
|
@ -111,9 +140,9 @@ Title* loadWiiUTitles() {
|
|||
free(xmlBuf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
titles[titleswiiu].isTitleDupe = false;
|
||||
for (int i = 0; i < titleswiiu; i++) {
|
||||
for (int i = 0; i < titleswiiu; i++) {
|
||||
if ((titles[i].highID == highID) && (titles[i].lowID == lowID)) {
|
||||
titles[titleswiiu].isTitleDupe = true;
|
||||
titles[titleswiiu].dupeID = i;
|
||||
|
|
@ -125,6 +154,7 @@ Title* loadWiiUTitles() {
|
|||
titles[titleswiiu].highID = highID;
|
||||
titles[titleswiiu].lowID = lowID;
|
||||
titles[titleswiiu].isTitleOnUSB = isTitleOnUSB;
|
||||
titles[titleswiiu].listID = titleswiiu;
|
||||
titleswiiu++;
|
||||
|
||||
OSScreenClearBufferEx(0, 0);
|
||||
|
|
@ -205,6 +235,7 @@ void unloadTitles(Title* titles) {
|
|||
int Menu_Main(void) {
|
||||
|
||||
mount_sd_fat("sd");
|
||||
loadWiiUTitles(0);
|
||||
|
||||
int res = IOSUHAX_Open(NULL);
|
||||
if (res < 0) {
|
||||
|
|
@ -233,7 +264,7 @@ int Menu_Main(void) {
|
|||
mount_fs("storage_odd", fsaFd, "/dev/odd03", "/vol/storage_odd_content");
|
||||
|
||||
ucls();
|
||||
Title* wiiutitles = loadWiiUTitles();
|
||||
Title* wiiutitles = loadWiiUTitles(1);
|
||||
Title* wiititles = loadWiiTitles();
|
||||
int* versionList = (int*)malloc(0x100*sizeof(int));
|
||||
|
||||
|
|
@ -242,7 +273,7 @@ int Menu_Main(void) {
|
|||
OSScreenClearBufferEx(0, 0);
|
||||
OSScreenClearBufferEx(1, 0);
|
||||
|
||||
console_print_pos(0, 0, "SaveMii v%u.%u.%u", VERSION_MAJOR, VERSION_MINOR, VERSION_MICRO);
|
||||
console_print_pos(0, 0, "SaveMii v%u.%u.%u.%s", VERSION_MAJOR, VERSION_MINOR, VERSION_MICRO, "mod2");
|
||||
console_print_pos(0, 1, "--------------------------------------------------");
|
||||
|
||||
Title* titles = mode ? wiititles : wiiutitles;
|
||||
|
|
@ -252,11 +283,12 @@ int Menu_Main(void) {
|
|||
switch(menu) {
|
||||
case 0: { // Main Menu
|
||||
entrycount = 2;
|
||||
console_print_pos(0, 2, " Wii U Save Management");
|
||||
console_print_pos(0, 3, " vWii Save Management");
|
||||
console_print_pos(0, 2, " Wii U Save Management (%u Title%s)", titleswiiu, (titleswiiu > 1) ? "s": "");
|
||||
console_print_pos(0, 3, " vWii Save Management (%u Title%s)", titlesvwii, (titlesvwii > 1) ? "s": "");
|
||||
console_print_pos(0, 2 + cursor, "->");
|
||||
} break;
|
||||
case 1: { // Select Title
|
||||
console_print_pos(30, 0, "Sort: %s %s", sortn[tsort], (tsort > 0) ? ((sorta == 1) ? "v": "^"): "");
|
||||
entrycount = count;
|
||||
for (int i = 0; i < 14; i++) {
|
||||
if (i+scroll<0 || i+scroll>=count) break;
|
||||
|
|
@ -276,7 +308,7 @@ int Menu_Main(void) {
|
|||
console_print_pos(0, 7, " Copy Savedata to Title in %s", titles[targ].isTitleOnUSB ? "NAND" : "USB");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
console_print_pos(0, 2 + cursor, "->");
|
||||
} break;
|
||||
|
|
@ -288,7 +320,9 @@ int Menu_Main(void) {
|
|||
else console_print_pos(0, 3, " < %03u > (%s)", slot, isSlotEmpty(titles[targ].highID, titles[targ].lowID, slot) ? "Empty" : "Used");
|
||||
if (mode==0) {
|
||||
console_print_pos(0, 5, "Select user:");
|
||||
console_print_pos(0, 6, " < %s >", (allusers&&((task<3) || task==5)) ? "all users" : "this user");
|
||||
char usrPath[16];
|
||||
getUserID(usrPath);
|
||||
console_print_pos(0, 6, " < %s > %s", (allusers&&((task<3) || task==5)) ? "all users" : "this user", (allusers&&((task<3) || task==5)) ? "" : usrPath);
|
||||
console_print_pos(0, 8, "Include 'common' save?");
|
||||
console_print_pos(0, 9, " < %s >", common ? "yes" : "no ");
|
||||
console_print_pos(0, 3 + cursor*3, "->");
|
||||
|
|
@ -305,13 +339,13 @@ int Menu_Main(void) {
|
|||
updatePressedButtons();
|
||||
updateHeldButtons();
|
||||
|
||||
if (isPressed(VPAD_BUTTON_DOWN) || isHeld(VPAD_BUTTON_DOWN)) {
|
||||
if (isPressed(VPAD_BUTTON_DOWN) || isHeld(VPAD_BUTTON_DOWN) || stickPos(1, -0.7)) {
|
||||
if (entrycount<=14) cursor = (cursor + 1) % entrycount;
|
||||
else if (cursor < 6) cursor++;
|
||||
else if ((cursor+scroll+1) % entrycount) scroll++;
|
||||
else cursor = scroll = 0;
|
||||
usleep(100000);
|
||||
} else if (isPressed(VPAD_BUTTON_UP) || isHeld(VPAD_BUTTON_UP)) {
|
||||
} else if (isPressed(VPAD_BUTTON_UP) || isHeld(VPAD_BUTTON_UP) || stickPos(1, 0.7)) {
|
||||
if (scroll > 0) cursor -= (cursor>6) ? 1 : 0*(scroll--);
|
||||
else if (cursor > 0) cursor--;
|
||||
else if (entrycount>14) scroll = entrycount - (cursor = 6) - 1;
|
||||
|
|
@ -319,7 +353,7 @@ int Menu_Main(void) {
|
|||
usleep(100000);
|
||||
}
|
||||
|
||||
if (isPressed(VPAD_BUTTON_LEFT) || isHeld(VPAD_BUTTON_LEFT)) {
|
||||
if (isPressed(VPAD_BUTTON_LEFT) || isHeld(VPAD_BUTTON_LEFT) || stickPos(0, -0.7)) {
|
||||
if (menu==3) {
|
||||
switch(cursor) {
|
||||
case 0: slot--; break;
|
||||
|
|
@ -328,7 +362,7 @@ int Menu_Main(void) {
|
|||
}
|
||||
}
|
||||
usleep(100000);
|
||||
} else if (isPressed(VPAD_BUTTON_RIGHT) || isHeld(VPAD_BUTTON_RIGHT)) {
|
||||
} else if (isPressed(VPAD_BUTTON_RIGHT) || isHeld(VPAD_BUTTON_RIGHT) || stickPos(0, 0.7)) {
|
||||
if (menu==3) {
|
||||
switch(cursor) {
|
||||
case 0: slot++; break;
|
||||
|
|
@ -339,6 +373,15 @@ int Menu_Main(void) {
|
|||
usleep(100000);
|
||||
}
|
||||
|
||||
if (isPressed(VPAD_BUTTON_R) && (menu==1)) {
|
||||
tsort = (tsort + 1) % 4;
|
||||
qsort(wiiutitles, titleswiiu, sizeof(Title), titleSort);
|
||||
}
|
||||
|
||||
if (isPressed(VPAD_BUTTON_L) && (menu==1) && (tsort > 0)) {
|
||||
sorta *= -1;
|
||||
qsort(wiiutitles, titleswiiu, sizeof(Title), titleSort);
|
||||
}
|
||||
if (isPressed(VPAD_BUTTON_A)) {
|
||||
ucls();
|
||||
if (menu<3) {
|
||||
|
|
@ -355,8 +398,8 @@ int Menu_Main(void) {
|
|||
}
|
||||
if (menu==1) {
|
||||
targ = cursor+scroll;
|
||||
cursorb = cursor;
|
||||
scrollb = scroll;
|
||||
cursorb = cursor;
|
||||
scrollb = scroll;
|
||||
if (titles[targ].highID==0 || titles[targ].lowID==0) continue;
|
||||
}
|
||||
if (menu==2) {
|
||||
|
|
|
|||
|
|
@ -328,8 +328,8 @@ void copySavedata(Title* title, Title* titleb, bool allusers, bool common) {
|
|||
if (!promptConfirm("Are you sure?")) return;
|
||||
int slotb = getEmptySlot(titleb->highID, titleb->lowID);
|
||||
if (slotb>=0 && promptConfirm("Backup current savedata first?")) {
|
||||
backupSavedata(titleb, slotb, allusers, common);
|
||||
promptError("Backup done. Now copying Savedata.");
|
||||
backupSavedata(titleb, slotb, allusers, common);
|
||||
promptError("Backup done. Now copying Savedata.");
|
||||
}
|
||||
|
||||
char srcPath[PATH_SIZE];
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ extern "C" {
|
|||
typedef struct {
|
||||
u32 highID;
|
||||
u32 lowID;
|
||||
u16 listID;
|
||||
char shortName[256];
|
||||
char productCode[32];
|
||||
bool isTitleOnUSB;
|
||||
|
|
@ -29,6 +30,7 @@ typedef struct {
|
|||
void console_print_pos(int x, int y, const char* format, ...);
|
||||
bool promptConfirm(const char* question);
|
||||
void promptError(const char* message);
|
||||
void getUserID(char* out);
|
||||
|
||||
int getLoadiineGameSaveDir(char* out, const char* productCode);
|
||||
int getLoadiineSaveVersionList(int* out, const char* gamePath);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user