2012-12-27 00:22:44 +01:00
|
|
|
/****************************************************************************
|
|
|
|
* Copyright (C) 2012 FIX94
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
****************************************************************************/
|
|
|
|
#include <malloc.h>
|
2020-06-26 01:11:58 +02:00
|
|
|
#include "memory/mem2.hpp"
|
2012-12-27 00:22:44 +01:00
|
|
|
#include "nand_save.hpp"
|
|
|
|
#include "nand.hpp"
|
|
|
|
#include "gecko/gecko.hpp"
|
|
|
|
#include "loader/fs.h"
|
|
|
|
#include "loader/sys.h"
|
2013-01-06 19:33:29 +01:00
|
|
|
#include "banner/AnimatedBanner.h"
|
2012-12-27 00:22:44 +01:00
|
|
|
#include "unzip/U8Archive.h"
|
|
|
|
|
|
|
|
extern const u8 save_bin[];
|
|
|
|
extern const u32 save_bin_size;
|
|
|
|
|
|
|
|
NandSave InternalSave;
|
2013-04-08 23:45:13 +02:00
|
|
|
bool cur_load = false;
|
|
|
|
u8 cur_ios = 0;
|
2012-12-27 00:22:44 +01:00
|
|
|
|
|
|
|
#define BANNER_PATH "/title/00010000/57465346/data/banner.bin"
|
|
|
|
#define IOS_SAVE_PATH "/title/00010000/57465346/data/ios"
|
2013-02-14 22:30:48 +01:00
|
|
|
#define PORT_SAVE_PATH "/title/00010000/57465346/data/port"
|
2022-06-18 00:29:09 +02:00
|
|
|
#define SD_SAVE_PATH "/title/00010000/57465346/data/sdonly"
|
2012-12-27 00:22:44 +01:00
|
|
|
|
|
|
|
NandSave::NandSave()
|
|
|
|
{
|
|
|
|
ret = 0;
|
|
|
|
fd = 0;
|
|
|
|
memset(&ISFS_Path, 0, ISFS_MAXPATH);
|
|
|
|
loaded = false;
|
|
|
|
}
|
|
|
|
|
2019-04-29 15:14:54 +02:00
|
|
|
/* checks for wiiflow save WFSF by searching for the banner.bin. if found then wiiflow save found. */
|
|
|
|
/* if not found then we use save.bin to create banner.bin, tik.bin, and tmd.bin which are compressed into save.bin. */
|
|
|
|
/* the IOS and port settings are only created if they are changed in startup settings menu. */
|
|
|
|
/* also the ticket and its folder are deleted after the tmd is created. */
|
2012-12-27 00:22:44 +01:00
|
|
|
bool NandSave::CheckSave()
|
|
|
|
{
|
|
|
|
/* 10 million variables */
|
|
|
|
u32 u8_bin_size = 0;
|
|
|
|
u8 *u8_bin = NULL;
|
|
|
|
u32 certSize = 0;
|
|
|
|
signed_blob *certBuffer = NULL;
|
|
|
|
u32 tmd_bin_size = 0;
|
|
|
|
const signed_blob *tmd_bin = NULL;
|
|
|
|
u32 tik_bin_size = 0;
|
|
|
|
const signed_blob *tik_bin = NULL;
|
|
|
|
u32 banner_bin_size = 0;
|
|
|
|
const u8 *banner_bin = NULL;
|
|
|
|
u32 entries = 0;
|
2022-06-18 00:29:09 +02:00
|
|
|
/* Maybe our banner already exist */
|
2012-12-27 00:22:44 +01:00
|
|
|
memset(&ISFS_Path, 0, ISFS_MAXPATH);
|
|
|
|
strcpy(ISFS_Path, BANNER_PATH);
|
|
|
|
fd = ISFS_Open(ISFS_Path, ISFS_OPEN_READ);
|
|
|
|
if(fd >= 0)
|
|
|
|
{
|
|
|
|
ISFS_Close(fd);
|
|
|
|
gprintf("Found WiiFlow Save\n");
|
|
|
|
goto done;
|
|
|
|
}
|
2022-06-18 00:29:09 +02:00
|
|
|
// save_bin only contains the tik.bin, tmd.bin, and banner.bin
|
|
|
|
// tik.bin and tmd.bin are used to install "/title/00010000/57465346/data/banner.bin"
|
|
|
|
// "/title/00010000/57465346/data/ios and port" are not written until you change them in startup settings menu.
|
2012-12-27 00:22:44 +01:00
|
|
|
/* extract our archive */
|
2013-01-06 19:33:29 +01:00
|
|
|
u8_bin = DecompressCopy(save_bin, save_bin_size, &u8_bin_size);
|
2012-12-27 00:22:44 +01:00
|
|
|
if(u8_bin == NULL || u8_bin_size == 0)
|
|
|
|
goto error;
|
|
|
|
/* grab cert.sys */
|
|
|
|
memset(&ISFS_Path, 0, ISFS_MAXPATH);
|
|
|
|
strcpy(ISFS_Path, "/sys/cert.sys");
|
|
|
|
certBuffer = (signed_blob*)ISFS_GetFile(ISFS_Path, &certSize, -1);
|
|
|
|
if(certBuffer == NULL || certSize == 0)
|
|
|
|
goto error;
|
|
|
|
/* Install tik and tmd */
|
|
|
|
tik_bin = (const signed_blob*)u8_get_file(u8_bin, "tik.bin", &tik_bin_size);
|
|
|
|
if(tik_bin == NULL || tik_bin_size == 0)
|
|
|
|
goto error;
|
|
|
|
ret = ES_AddTicket(tik_bin, tik_bin_size, certBuffer, certSize, NULL, 0);
|
|
|
|
if(ret < 0)
|
|
|
|
goto error;
|
|
|
|
tmd_bin = (const signed_blob*)u8_get_file(u8_bin, "tmd.bin", &tmd_bin_size);
|
|
|
|
if(tmd_bin == NULL || tmd_bin_size == 0)
|
|
|
|
goto error;
|
|
|
|
ret = ES_AddTitleStart(tmd_bin, tmd_bin_size, certBuffer, certSize, NULL, 0);
|
|
|
|
if(ret < 0)
|
|
|
|
goto error;
|
|
|
|
ret = ES_AddTitleFinish();
|
|
|
|
if(ret < 0)
|
|
|
|
goto error;
|
|
|
|
/* WARNING dirty, delete tik again */
|
|
|
|
memset(&ISFS_Path, 0, ISFS_MAXPATH);
|
|
|
|
strcpy(ISFS_Path, "/ticket/00010000/57465346.tik");
|
|
|
|
ret = ISFS_Delete(ISFS_Path);
|
|
|
|
if(ret < 0)
|
|
|
|
goto error;
|
|
|
|
/* Delete the unused ticket folder */
|
|
|
|
memset(&ISFS_Path, 0, ISFS_MAXPATH);
|
|
|
|
strcpy(ISFS_Path, "/ticket/00010000");
|
|
|
|
ret = ISFS_ReadDir(ISFS_Path, NULL, &entries);
|
|
|
|
if(ret < 0)
|
|
|
|
goto error;
|
|
|
|
if(entries == 0)
|
|
|
|
{
|
|
|
|
ret = ISFS_Delete(ISFS_Path);
|
|
|
|
if(ret < 0)
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
banner_bin = u8_get_file(u8_bin, "banner.bin", &banner_bin_size);
|
|
|
|
if(banner_bin == NULL || banner_bin_size == 0)
|
|
|
|
goto error;
|
|
|
|
memset(&ISFS_Path, 0, ISFS_MAXPATH);
|
|
|
|
strcpy(ISFS_Path, BANNER_PATH);
|
|
|
|
/* Write our banner */
|
|
|
|
ISFS_CreateFile(ISFS_Path, 0, 3, 3, 3);
|
|
|
|
fd = ISFS_Open(ISFS_Path, ISFS_OPEN_WRITE);
|
|
|
|
if(fd < 0)
|
|
|
|
goto error;
|
|
|
|
ret = ISFS_Write(fd, banner_bin, banner_bin_size);
|
|
|
|
ISFS_Close(fd);
|
|
|
|
if(ret < 0)
|
|
|
|
{
|
|
|
|
ISFS_Delete(ISFS_Path);
|
|
|
|
goto error;
|
|
|
|
}
|
2020-06-26 01:11:58 +02:00
|
|
|
MEM2_free(certBuffer);
|
2014-03-01 00:11:02 +01:00
|
|
|
if(u8_bin != save_bin)
|
|
|
|
free(u8_bin);
|
2012-12-27 00:22:44 +01:00
|
|
|
gprintf("Created WiiFlow Save\n");
|
|
|
|
done:
|
|
|
|
loaded = true;
|
|
|
|
return loaded;
|
|
|
|
|
|
|
|
error:
|
|
|
|
gprintf("Error while creating WiiFlow Save\n");
|
|
|
|
loaded = false;
|
|
|
|
ES_AddTitleCancel();
|
|
|
|
if(certBuffer != NULL)
|
2020-06-26 01:11:58 +02:00
|
|
|
MEM2_free(certBuffer);
|
2012-12-27 00:22:44 +01:00
|
|
|
certBuffer = NULL;
|
|
|
|
if(u8_bin != NULL)
|
|
|
|
free(u8_bin);
|
|
|
|
u8_bin = NULL;
|
|
|
|
tik_bin = NULL;
|
|
|
|
tmd_bin = NULL;
|
|
|
|
banner_bin = NULL;
|
|
|
|
return loaded;
|
|
|
|
}
|
|
|
|
|
2013-02-14 22:30:48 +01:00
|
|
|
void NandSave::LoadSettings()
|
2012-12-27 00:22:44 +01:00
|
|
|
{
|
|
|
|
if(loaded == false)
|
|
|
|
return;
|
2013-02-14 22:30:48 +01:00
|
|
|
|
2012-12-27 00:22:44 +01:00
|
|
|
u32 size = 0;
|
|
|
|
memset(&ISFS_Path, 0, ISFS_MAXPATH);
|
2022-06-18 00:29:09 +02:00
|
|
|
// on very first boot (no save file exist yet)
|
|
|
|
// "/title/00010000/57465346/data/ios"
|
|
|
|
// "/title/00010000/57465346/data/port"
|
|
|
|
// will not exist. wiiflow will simply use useMainIOS and mainIOS defined in main.cpp
|
|
|
|
// they are only created when you change settings in the startup settings menu.
|
|
|
|
|
2012-12-27 00:22:44 +01:00
|
|
|
strcpy(ISFS_Path, IOS_SAVE_PATH);
|
|
|
|
ios_settings_t *file = (ios_settings_t*)ISFS_GetFile(ISFS_Path, &size, -1);
|
2013-02-14 22:30:48 +01:00
|
|
|
if(file != NULL && size == sizeof(ios_settings_t))
|
2012-12-27 00:22:44 +01:00
|
|
|
{
|
2018-08-01 14:27:12 +02:00
|
|
|
gprintf("Loading IOS Settings from wiiflow save\n");
|
2013-04-08 23:45:13 +02:00
|
|
|
cur_ios = file->cios;
|
|
|
|
if(cur_ios > 0)
|
|
|
|
mainIOS = cur_ios;
|
|
|
|
cur_load = file->use_cios;
|
|
|
|
useMainIOS = cur_load;
|
2012-12-27 00:22:44 +01:00
|
|
|
}
|
2013-02-14 22:30:48 +01:00
|
|
|
if(file != NULL)
|
2020-06-26 01:11:58 +02:00
|
|
|
MEM2_free(file);
|
2013-02-14 22:30:48 +01:00
|
|
|
|
|
|
|
strcpy(ISFS_Path, PORT_SAVE_PATH);
|
|
|
|
u8 *port = ISFS_GetFile(ISFS_Path, &size, -1);
|
|
|
|
if(port != NULL && size == sizeof(u8))
|
|
|
|
{
|
2018-08-01 14:27:12 +02:00
|
|
|
gprintf("Using Port Settings from wiiflow save\n");
|
2013-02-14 22:30:48 +01:00
|
|
|
currentPort = port[0] & 1;
|
|
|
|
}
|
|
|
|
if(port != NULL)
|
2020-06-26 01:11:58 +02:00
|
|
|
MEM2_free(port);
|
2022-06-18 00:29:09 +02:00
|
|
|
|
|
|
|
strcpy(ISFS_Path, SD_SAVE_PATH);
|
|
|
|
u8 *sdonly = ISFS_GetFile(ISFS_Path, &size, -1);
|
|
|
|
if(sdonly != NULL && size == sizeof(u8))
|
|
|
|
{
|
|
|
|
gprintf("Using SD Only Settings from wiiflow save\n");
|
|
|
|
sdOnly = ((sdonly[0] & 1) == 1);
|
|
|
|
}
|
|
|
|
if(sdonly != NULL)
|
|
|
|
MEM2_free(sdonly);
|
2012-12-27 00:22:44 +01:00
|
|
|
}
|
|
|
|
|
2013-04-08 23:45:13 +02:00
|
|
|
void NandSave::SaveIOS()
|
2012-12-27 00:22:44 +01:00
|
|
|
{
|
|
|
|
if(loaded == false)
|
|
|
|
return;
|
2012-12-27 02:08:16 +01:00
|
|
|
memset(&ios_settings, 0, sizeof(ios_settings_t));
|
2013-04-08 23:45:13 +02:00
|
|
|
ios_settings.cios = cur_ios;
|
|
|
|
ios_settings.use_cios = cur_load;
|
2018-08-01 14:27:12 +02:00
|
|
|
gprintf("Saving IOS Settings to wiiflow save\n");
|
2013-02-14 22:30:48 +01:00
|
|
|
WriteFile(IOS_SAVE_PATH, (u8*)&ios_settings, sizeof(ios_settings_t));
|
|
|
|
}
|
|
|
|
|
|
|
|
void NandSave::SavePort(u8 port)
|
|
|
|
{
|
|
|
|
if(loaded == false)
|
|
|
|
return;
|
2022-06-18 00:29:09 +02:00
|
|
|
gprintf("Saving Port Setting to wiiflow save\n");
|
2013-02-14 22:30:48 +01:00
|
|
|
WriteFile(PORT_SAVE_PATH, &port, sizeof(port));
|
|
|
|
}
|
|
|
|
|
2022-06-18 00:29:09 +02:00
|
|
|
void NandSave::SaveSDOnly(bool sd_only)
|
|
|
|
{
|
|
|
|
if(loaded == false)
|
|
|
|
return;
|
|
|
|
gprintf("Saving SD Only Setting to wiiflow save\n");
|
|
|
|
u8 sdonly = sd_only ? 1 : 0;
|
|
|
|
WriteFile(SD_SAVE_PATH, &sdonly, sizeof(sdonly));
|
|
|
|
}
|
|
|
|
|
2013-02-14 22:30:48 +01:00
|
|
|
void NandSave::WriteFile(const char *file_name, u8 *content, u32 size)
|
|
|
|
{
|
2012-12-27 00:22:44 +01:00
|
|
|
memset(&ISFS_Path, 0, ISFS_MAXPATH);
|
2013-02-14 22:30:48 +01:00
|
|
|
if(file_name == NULL || content == NULL || size == 0)
|
|
|
|
return;
|
|
|
|
strcpy(ISFS_Path, file_name);
|
2012-12-27 00:22:44 +01:00
|
|
|
ISFS_CreateFile(ISFS_Path, 0, 3, 3, 3);
|
|
|
|
fd = ISFS_Open(ISFS_Path, ISFS_OPEN_WRITE);
|
|
|
|
if(fd < 0)
|
|
|
|
return;
|
2013-02-14 22:30:48 +01:00
|
|
|
ret = ISFS_Write(fd, content, size);
|
2012-12-27 00:22:44 +01:00
|
|
|
ISFS_Close(fd);
|
|
|
|
if(ret < 0)
|
|
|
|
ISFS_Delete(ISFS_Path);
|
|
|
|
}
|