mirror of
https://github.com/Fledge68/WiiFlow_Lite.git
synced 2024-11-27 21:54:15 +01:00
-added real nand mios installation, it just wont ask for a emu nand partition when you select a mios
-added checks before asking if you want to install a wad to make sure its a channel for emu nand or a mios wad for real nand
This commit is contained in:
parent
97a6aadc71
commit
1afd473be8
@ -40,6 +40,8 @@ struct _hdr {
|
|||||||
} ATTRIBUTE_PACKED hdr;
|
} ATTRIBUTE_PACKED hdr;
|
||||||
|
|
||||||
TexData m_wadBg;
|
TexData m_wadBg;
|
||||||
|
bool mios = false;
|
||||||
|
char ISFS_Path[ISFS_MAXPATH];
|
||||||
|
|
||||||
void skip_align(FILE *f, u32 size)
|
void skip_align(FILE *f, u32 size)
|
||||||
{
|
{
|
||||||
@ -49,18 +51,26 @@ void skip_align(FILE *f, u32 size)
|
|||||||
fseek(f, align_missing, SEEK_CUR);
|
fseek(f, align_missing, SEEK_CUR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int isfs_WriteFile(const char *app_name, const void *content, u32 size)
|
||||||
|
{
|
||||||
|
memset(&ISFS_Path, 0, ISFS_MAXPATH);
|
||||||
|
strcpy(ISFS_Path, app_name);
|
||||||
|
ISFS_Delete(ISFS_Path);
|
||||||
|
ISFS_CreateFile(ISFS_Path, 0, 3, 3, 3);
|
||||||
|
s32 fd = ISFS_Open(ISFS_Path, ISFS_OPEN_WRITE);
|
||||||
|
if(fd < 0)
|
||||||
|
return fd;
|
||||||
|
s32 ret = ISFS_Write(fd, content, size);
|
||||||
|
ISFS_Close(fd);
|
||||||
|
gprintf("Writing %s returned %i\n", ISFS_Path, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int installWad(const char *path)
|
int installWad(const char *path)
|
||||||
{
|
{
|
||||||
gprintf("Installing %s\n", path);
|
gprintf("Installing %s\n", path);
|
||||||
const char *EmuNAND = NandHandle.GetPath();
|
|
||||||
|
|
||||||
if(!fsop_FileExist(path))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
u32 size = 0;
|
u32 size = 0;
|
||||||
fsop_GetFileSizeBytes(path, &size);
|
fsop_GetFileSizeBytes(path, &size);
|
||||||
if(size < sizeof(hdr))
|
|
||||||
return -2;
|
|
||||||
|
|
||||||
FILE *wad_file = fopen(path, "rb");
|
FILE *wad_file = fopen(path, "rb");
|
||||||
fread(&hdr, sizeof(hdr), 1, wad_file);
|
fread(&hdr, sizeof(hdr), 1, wad_file);
|
||||||
@ -92,69 +102,64 @@ int installWad(const char *path)
|
|||||||
|
|
||||||
const tmd *tmd_ptr = (const tmd*)SIGNATURE_PAYLOAD(tmd_buf);
|
const tmd *tmd_ptr = (const tmd*)SIGNATURE_PAYLOAD(tmd_buf);
|
||||||
u64 tid = tmd_ptr->title_id;
|
u64 tid = tmd_ptr->title_id;
|
||||||
|
const char *EmuNAND = NULL;
|
||||||
/* ONLY allow wii channels for now */
|
if(mios == false)
|
||||||
if((u32)(tid>>32) != 0x00010001)
|
|
||||||
{
|
{
|
||||||
gprintf("No Wii Channel!\n");
|
EmuNAND = NandHandle.GetPath();
|
||||||
free(tmd_buf);
|
u32 uid_size = 0;
|
||||||
free(tik_buf);
|
u8 *uid_buf = fsop_ReadFile(fmt("%s/sys/uid.sys", EmuNAND), &uid_size);
|
||||||
return -4;
|
if(uid_buf == NULL)
|
||||||
}
|
{
|
||||||
u32 uid_size = 0;
|
gprintf("No uid.sys found!\n");
|
||||||
u8 *uid_buf = fsop_ReadFile(fmt("%s/sys/uid.sys", EmuNAND), &uid_size);
|
free(tmd_buf);
|
||||||
if(uid_buf == NULL)
|
free(tik_buf);
|
||||||
{
|
return -5;
|
||||||
gprintf("No uid.sys found!\n");
|
}
|
||||||
free(tmd_buf);
|
else if(uid_size % 0xC != 0)
|
||||||
free(tik_buf);
|
{
|
||||||
return -5;
|
gprintf("uid.sys size is invalid!\n");
|
||||||
}
|
free(tmd_buf);
|
||||||
else if(uid_size % 0xC != 0)
|
free(tik_buf);
|
||||||
{
|
free(uid_buf);
|
||||||
gprintf("uid.sys size is invalid!\n");
|
return -6;
|
||||||
free(tmd_buf);
|
}
|
||||||
free(tik_buf);
|
|
||||||
free(uid_buf);
|
|
||||||
return -6;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool chan_exist = false;
|
bool chan_exist = false;
|
||||||
uid *uid_file = (uid*)uid_buf;
|
uid *uid_file = (uid*)uid_buf;
|
||||||
u32 chans = uid_size/sizeof(uid);
|
u32 chans = uid_size/sizeof(uid);
|
||||||
for(u32 i = 0; i < chans; ++i)
|
for(u32 i = 0; i < chans; ++i)
|
||||||
{
|
{
|
||||||
if(uid_file[i].TitleID == tid)
|
if(uid_file[i].TitleID == tid)
|
||||||
chan_exist = true;
|
chan_exist = true;
|
||||||
|
}
|
||||||
|
if(chan_exist == false)
|
||||||
|
{
|
||||||
|
gprintf("Updating uid.sys\n");
|
||||||
|
u32 new_uid_size = (chans+1)*sizeof(uid);
|
||||||
|
u8 *new_uid_buf = (u8*)MEM2_alloc(new_uid_size);
|
||||||
|
memset(new_uid_buf, 0, new_uid_size);
|
||||||
|
/* copy over old uid */
|
||||||
|
memcpy(new_uid_buf, uid_buf, chans*sizeof(uid));
|
||||||
|
uid *new_uid_file = (uid*)new_uid_buf;
|
||||||
|
new_uid_file[chans].TitleID = tid;
|
||||||
|
new_uid_file[chans].uid = 0x1000+chans;
|
||||||
|
fsop_WriteFile(fmt("%s/sys/uid.sys", EmuNAND), new_uid_file, new_uid_size);
|
||||||
|
}
|
||||||
|
/* clear old tik */
|
||||||
|
fsop_deleteFile(fmt("%s/ticket/%08x/%08x.tik", EmuNAND, (u32)(tid>>32), (u32)tid&0xFFFFFFFF));
|
||||||
|
/* clear old content */
|
||||||
|
fsop_deleteFolder(fmt("%s/title/%08x/%08x/content", EmuNAND, (u32)(tid>>32), (u32)tid&0xFFFFFFFF));
|
||||||
|
|
||||||
|
/* (re)create folder structure */
|
||||||
|
fsop_MakeFolder(fmt("%s/ticket", EmuNAND));
|
||||||
|
fsop_MakeFolder(fmt("%s/ticket/%08x", EmuNAND, (u32)(tid>>32)));
|
||||||
|
|
||||||
|
fsop_MakeFolder(fmt("%s/title", EmuNAND));
|
||||||
|
fsop_MakeFolder(fmt("%s/title/%08x", EmuNAND, (u32)(tid>>32)));
|
||||||
|
fsop_MakeFolder(fmt("%s/title/%08x/%08x", EmuNAND, (u32)(tid>>32), (u32)tid&0xFFFFFFFF));
|
||||||
|
fsop_MakeFolder(fmt("%s/title/%08x/%08x/content", EmuNAND, (u32)(tid>>32), (u32)tid&0xFFFFFFFF));
|
||||||
|
fsop_MakeFolder(fmt("%s/title/%08x/%08x/data", EmuNAND, (u32)(tid>>32), (u32)tid&0xFFFFFFFF));
|
||||||
}
|
}
|
||||||
if(chan_exist == false)
|
|
||||||
{
|
|
||||||
gprintf("Updating uid.sys\n");
|
|
||||||
u32 new_uid_size = (chans+1)*sizeof(uid);
|
|
||||||
u8 *new_uid_buf = (u8*)MEM2_alloc(new_uid_size);
|
|
||||||
memset(new_uid_buf, 0, new_uid_size);
|
|
||||||
/* copy over old uid */
|
|
||||||
memcpy(new_uid_buf, uid_buf, chans*sizeof(uid));
|
|
||||||
uid *new_uid_file = (uid*)new_uid_buf;
|
|
||||||
new_uid_file[chans].TitleID = tid;
|
|
||||||
new_uid_file[chans].uid = 0x1000+chans;
|
|
||||||
fsop_WriteFile(fmt("%s/sys/uid.sys", EmuNAND), new_uid_file, new_uid_size);
|
|
||||||
}
|
|
||||||
/* clear old tik */
|
|
||||||
fsop_deleteFile(fmt("%s/ticket/%08x/%08x.tik", EmuNAND, (u32)(tid>>32), (u32)tid&0xFFFFFFFF));
|
|
||||||
/* clear old content */
|
|
||||||
fsop_deleteFolder(fmt("%s/title/%08x/%08x/content", EmuNAND, (u32)(tid>>32), (u32)tid&0xFFFFFFFF));
|
|
||||||
|
|
||||||
/* (re)create folder structure */
|
|
||||||
fsop_MakeFolder(fmt("%s/ticket", EmuNAND));
|
|
||||||
fsop_MakeFolder(fmt("%s/ticket/%08x", EmuNAND, (u32)(tid>>32)));
|
|
||||||
|
|
||||||
fsop_MakeFolder(fmt("%s/title", EmuNAND));
|
|
||||||
fsop_MakeFolder(fmt("%s/title/%08x", EmuNAND, (u32)(tid>>32)));
|
|
||||||
fsop_MakeFolder(fmt("%s/title/%08x/%08x", EmuNAND, (u32)(tid>>32), (u32)tid&0xFFFFFFFF));
|
|
||||||
fsop_MakeFolder(fmt("%s/title/%08x/%08x/content", EmuNAND, (u32)(tid>>32), (u32)tid&0xFFFFFFFF));
|
|
||||||
fsop_MakeFolder(fmt("%s/title/%08x/%08x/data", EmuNAND, (u32)(tid>>32), (u32)tid&0xFFFFFFFF));
|
|
||||||
|
|
||||||
int hash_errors = 0;
|
int hash_errors = 0;
|
||||||
|
|
||||||
/* decrypt and write app files */
|
/* decrypt and write app files */
|
||||||
@ -166,10 +171,28 @@ int installWad(const char *path)
|
|||||||
memset(iv, 0, 16);
|
memset(iv, 0, 16);
|
||||||
memcpy(iv, &content_index, 2);
|
memcpy(iv, &content_index, 2);
|
||||||
/* longass filename */
|
/* longass filename */
|
||||||
const char *app_name = fmt("%s/title/%08x/%08x/content/%08x.app", EmuNAND,
|
FILE *app_file = NULL;
|
||||||
(u32)(tid>>32), (u32)tid&0xFFFFFFFF, content->cid);
|
s32 fd = -1;
|
||||||
FILE *app_file = fopen(app_name, "wb");
|
if(mios == false)
|
||||||
|
{
|
||||||
|
const char *app_name = fmt("%s/title/%08x/%08x/content/%08x.app", EmuNAND,
|
||||||
|
(u32)(tid>>32), (u32)tid&0xFFFFFFFF, content->cid);
|
||||||
|
app_file = fopen(app_name, "wb");
|
||||||
|
gprintf("Writing Emu NAND File %s\n", app_name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* delete then create file */
|
||||||
|
memset(&ISFS_Path, 0, ISFS_MAXPATH);
|
||||||
|
const char *app_name = fmt("/title/%08x/%08x/content/%08x.app",
|
||||||
|
(u32)(tid>>32), (u32)tid&0xFFFFFFFF, content->cid);
|
||||||
|
strcpy(ISFS_Path, app_name);
|
||||||
|
ISFS_Delete(ISFS_Path);
|
||||||
|
ISFS_CreateFile(ISFS_Path, 0, 3, 3, 3);
|
||||||
|
fd = ISFS_Open(ISFS_Path, ISFS_OPEN_WRITE);
|
||||||
|
if(fd >= 0)
|
||||||
|
gprintf("Writing Real NAND File %s\n", ISFS_Path);
|
||||||
|
}
|
||||||
u64 read = 0;
|
u64 read = 0;
|
||||||
u8 *encBuf = (u8*)MEM2_alloc(WAD_BUF);
|
u8 *encBuf = (u8*)MEM2_alloc(WAD_BUF);
|
||||||
u8 *decBuf = (u8*)MEM2_alloc(WAD_BUF);
|
u8 *decBuf = (u8*)MEM2_alloc(WAD_BUF);
|
||||||
@ -205,15 +228,21 @@ int installWad(const char *path)
|
|||||||
if(size_dec > WAD_BUF)
|
if(size_dec > WAD_BUF)
|
||||||
size_dec = WAD_BUF;
|
size_dec = WAD_BUF;
|
||||||
SHA1Update(&ctx, decBuf, size_dec);
|
SHA1Update(&ctx, decBuf, size_dec);
|
||||||
fwrite(decBuf, size_dec, 1, app_file);
|
if(mios == false)
|
||||||
|
fwrite(decBuf, size_dec, 1, app_file);
|
||||||
|
else if(fd >= 0)
|
||||||
|
ISFS_Write(fd, decBuf, size_dec);
|
||||||
/* dont forget to increase the read size */
|
/* dont forget to increase the read size */
|
||||||
read += size_enc;
|
read += size_enc;
|
||||||
}
|
}
|
||||||
sha1 app_sha1;
|
sha1 app_sha1;
|
||||||
SHA1Final(app_sha1, &ctx);
|
SHA1Final(app_sha1, &ctx);
|
||||||
skip_align(wad_file, size_enc_full);
|
skip_align(wad_file, size_enc_full);
|
||||||
gprintf("Wrote %s\n", app_name);
|
|
||||||
fclose(app_file);
|
if(mios == false)
|
||||||
|
fclose(app_file);
|
||||||
|
else if(fd >= 0)
|
||||||
|
ISFS_Close(fd);
|
||||||
|
|
||||||
if(memcmp(app_sha1, content->hash, sizeof(sha1)) == 0)
|
if(memcmp(app_sha1, content->hash, sizeof(sha1)) == 0)
|
||||||
gprintf("sha1 matches on %08x.app, success!\n", content->cid);
|
gprintf("sha1 matches on %08x.app, success!\n", content->cid);
|
||||||
@ -223,10 +252,16 @@ int installWad(const char *path)
|
|||||||
hash_errors++;
|
hash_errors++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(mios == false)
|
||||||
fsop_WriteFile(fmt("%s/ticket/%08x/%08x.tik", EmuNAND, (u32)(tid>>32), (u32)tid&0xFFFFFFFF), tik_buf, hdr.tik_len);
|
{
|
||||||
fsop_WriteFile(fmt("%s/title/%08x/%08x/content/title.tmd", EmuNAND, (u32)(tid>>32), (u32)tid&0xFFFFFFFF), tmd_buf, hdr.tmd_len);
|
fsop_WriteFile(fmt("%s/ticket/%08x/%08x.tik", EmuNAND, (u32)(tid>>32), (u32)tid&0xFFFFFFFF), tik_buf, hdr.tik_len);
|
||||||
|
fsop_WriteFile(fmt("%s/title/%08x/%08x/content/title.tmd", EmuNAND, (u32)(tid>>32), (u32)tid&0xFFFFFFFF), tmd_buf, hdr.tmd_len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isfs_WriteFile(fmt("/ticket/%08x/%08x.tik", (u32)(tid>>32), (u32)tid&0xFFFFFFFF), tik_buf, hdr.tik_len);
|
||||||
|
isfs_WriteFile(fmt("/title/%08x/%08x/content/title.tmd", (u32)(tid>>32), (u32)tid&0xFFFFFFFF), tmd_buf, hdr.tmd_len);
|
||||||
|
}
|
||||||
free(tik_buf);
|
free(tik_buf);
|
||||||
free(tmd_buf);
|
free(tmd_buf);
|
||||||
|
|
||||||
@ -244,10 +279,13 @@ void CMenu::_showWad()
|
|||||||
m_btnMgr.show(m_wadLblTitle);
|
m_btnMgr.show(m_wadLblTitle);
|
||||||
m_btnMgr.show(m_wadLblDialog);
|
m_btnMgr.show(m_wadLblDialog);
|
||||||
/* partition selection */
|
/* partition selection */
|
||||||
m_btnMgr.show(m_configLblPartitionName);
|
if(mios == false)
|
||||||
m_btnMgr.show(m_configLblPartition);
|
{
|
||||||
m_btnMgr.show(m_configBtnPartitionP);
|
m_btnMgr.show(m_configLblPartitionName);
|
||||||
m_btnMgr.show(m_configBtnPartitionM);
|
m_btnMgr.show(m_configLblPartition);
|
||||||
|
m_btnMgr.show(m_configBtnPartitionP);
|
||||||
|
m_btnMgr.show(m_configBtnPartitionM);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMenu::_hideWad(bool instant)
|
void CMenu::_hideWad(bool instant)
|
||||||
@ -256,16 +294,71 @@ void CMenu::_hideWad(bool instant)
|
|||||||
m_btnMgr.hide(m_wadLblTitle, instant);
|
m_btnMgr.hide(m_wadLblTitle, instant);
|
||||||
m_btnMgr.hide(m_wadLblDialog, instant);
|
m_btnMgr.hide(m_wadLblDialog, instant);
|
||||||
/* partition selection */
|
/* partition selection */
|
||||||
m_btnMgr.hide(m_configLblPartitionName);
|
if(mios == false)
|
||||||
m_btnMgr.hide(m_configLblPartition);
|
{
|
||||||
m_btnMgr.hide(m_configBtnPartitionP);
|
m_btnMgr.hide(m_configLblPartitionName);
|
||||||
m_btnMgr.hide(m_configBtnPartitionM);
|
m_btnMgr.hide(m_configLblPartition);
|
||||||
|
m_btnMgr.hide(m_configBtnPartitionP);
|
||||||
|
m_btnMgr.hide(m_configBtnPartitionM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int getTID(const char *path, u64 *tid)
|
||||||
|
{
|
||||||
|
if(!fsop_FileExist(path))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
u32 size = 0;
|
||||||
|
fsop_GetFileSizeBytes(path, &size);
|
||||||
|
if(size < sizeof(hdr))
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
FILE *wad_file = fopen(path, "rb");
|
||||||
|
fread(&hdr, sizeof(hdr), 1, wad_file);
|
||||||
|
|
||||||
|
/* skip to tmd */
|
||||||
|
skip_align(wad_file, sizeof(hdr));
|
||||||
|
fseek(wad_file, ALIGN(64, hdr.certs_len), SEEK_CUR);
|
||||||
|
fseek(wad_file, ALIGN(64, hdr.crl_len), SEEK_CUR);
|
||||||
|
fseek(wad_file, ALIGN(64, hdr.tik_len), SEEK_CUR);
|
||||||
|
|
||||||
|
/* read tmd and close wad */
|
||||||
|
signed_blob *tmd_buf = (signed_blob*)MEM2_alloc(hdr.tmd_len);
|
||||||
|
fread(tmd_buf, hdr.tmd_len, 1, wad_file);
|
||||||
|
fclose(wad_file);
|
||||||
|
|
||||||
|
/* get its tid, return and free mem */
|
||||||
|
const tmd *tmd_ptr = (const tmd*)SIGNATURE_PAYLOAD(tmd_buf);
|
||||||
|
(*tid) = tmd_ptr->title_id;
|
||||||
|
free(tmd_buf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMenu::_Wad(const char *wad_path)
|
void CMenu::_Wad(const char *wad_path)
|
||||||
{
|
{
|
||||||
if(wad_path == NULL)
|
if(wad_path == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* precheck */
|
||||||
|
mios = false;
|
||||||
|
u64 tid;
|
||||||
|
if(getTID(wad_path, &tid) < 0)
|
||||||
|
return;
|
||||||
|
if((u32)(tid>>32) != 0x00010001)
|
||||||
|
{
|
||||||
|
if(tid == 0x0000000100000101ull)
|
||||||
|
{
|
||||||
|
gprintf("MIOS Detected\n");
|
||||||
|
mios = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gprintf("No Wii Channel!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
u8 part = currentPartition;
|
u8 part = currentPartition;
|
||||||
m_btnMgr.setText(m_wadLblDialog, wfmt(_fmt("wad3", L"Selected %s, after the installation you return to the explorer."), (strrchr(wad_path, '/')+1)));
|
m_btnMgr.setText(m_wadLblDialog, wfmt(_fmt("wad3", L"Selected %s, after the installation you return to the explorer."), (strrchr(wad_path, '/')+1)));
|
||||||
m_btnMgr.setText(m_configLblPartition, upperCase(DeviceName[currentPartition]));
|
m_btnMgr.setText(m_configLblPartition, upperCase(DeviceName[currentPartition]));
|
||||||
@ -286,9 +379,12 @@ void CMenu::_Wad(const char *wad_path)
|
|||||||
/* who cares about making a thread, just refresh a second */
|
/* who cares about making a thread, just refresh a second */
|
||||||
for(u8 i = 0; i < 60; ++i)
|
for(u8 i = 0; i < 60; ++i)
|
||||||
_mainLoopCommon();
|
_mainLoopCommon();
|
||||||
/* setup emu nand paths */
|
/* mios is real nand, chans are emu */
|
||||||
const char *emu_char = m_cfg.getString(CHANNEL_DOMAIN, "path", "/").c_str();
|
if(mios == false)
|
||||||
NandHandle.SetPaths(emu_char, DeviceName[currentPartition]);
|
{
|
||||||
|
const char *emu_char = m_cfg.getString(CHANNEL_DOMAIN, "path", "/").c_str();
|
||||||
|
NandHandle.SetPaths(emu_char, DeviceName[currentPartition]);
|
||||||
|
}
|
||||||
int result = installWad(wad_path);
|
int result = installWad(wad_path);
|
||||||
if(result < 0)
|
if(result < 0)
|
||||||
m_btnMgr.setText(m_wbfsLblMessage, wfmt(_fmt("wad5", L"Installation error %i!"), result));
|
m_btnMgr.setText(m_wbfsLblMessage, wfmt(_fmt("wad5", L"Installation error %i!"), result));
|
||||||
|
Loading…
Reference in New Issue
Block a user