mirror of
https://github.com/Fledge68/WiiFlow_Lite.git
synced 2025-01-12 03:49:08 +01:00
-added devolution support, simply grab the devolution source
and place the loader.bin into your wiiflow data folder, wiiflow will automatically find the binary and use devolution to boot the gamecube game (only works with iso files, games extracted with gcreex doesnt work)
This commit is contained in:
parent
ac3816d7e9
commit
8aa08dee60
289
source/gc/gc.c
289
source/gc/gc.c
@ -1,7 +1,6 @@
|
||||
#include <gccore.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include "gc.h"
|
||||
#include "gecko.h"
|
||||
@ -9,6 +8,188 @@
|
||||
#include "utils.h"
|
||||
#include "memory/mem2.hpp"
|
||||
|
||||
// for directory parsing and low-level file I/O
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
|
||||
// DIOS-MIOS
|
||||
DML_CFG *DMLCfg = NULL;
|
||||
|
||||
void DML_New_SetOptions(const char *GamePath, char *CheatPath, char *NewCheatPath, bool cheats, bool debugger, u8 NMM, u8 nodisc, u8 DMLvideoMode, bool force)
|
||||
{
|
||||
gprintf("Wiiflow DML: Launch game '%s' through memory (new method)\n", GamePath);
|
||||
|
||||
DMLCfg = (DML_CFG*)MEM1_alloc(sizeof(DML_CFG));
|
||||
if(DMLCfg == NULL)
|
||||
return;
|
||||
memset(DMLCfg, 0, sizeof(DML_CFG));
|
||||
|
||||
DMLCfg->Magicbytes = 0xD1050CF6;
|
||||
DMLCfg->CfgVersion = 0x00000001;
|
||||
if(force)
|
||||
DMLCfg->VideoMode |= DML_VID_FORCE;
|
||||
else
|
||||
DMLCfg->VideoMode |= DML_VID_DML_AUTO;
|
||||
|
||||
DMLCfg->Config |= DML_CFG_ACTIVITY_LED; //Sorry but I like it lol, option will may follow
|
||||
DMLCfg->Config |= DML_CFG_PADHOOK; //Makes life easier, l+z+b+digital down...
|
||||
|
||||
if(GamePath != NULL)
|
||||
{
|
||||
strncpy(DMLCfg->GamePath, GamePath, sizeof(DMLCfg->GamePath));
|
||||
DMLCfg->Config |= DML_CFG_GAME_PATH;
|
||||
}
|
||||
|
||||
if(CheatPath != NULL && NewCheatPath != NULL && cheats)
|
||||
{
|
||||
char *ptr;
|
||||
if(strstr(CheatPath, "sd:/") == NULL)
|
||||
{
|
||||
fsop_CopyFile(CheatPath, NewCheatPath, NULL, NULL);
|
||||
ptr = &NewCheatPath[3];
|
||||
}
|
||||
else
|
||||
ptr = &CheatPath[3];
|
||||
strncpy(DMLCfg->CheatPath, ptr, sizeof(DMLCfg->CheatPath));
|
||||
DMLCfg->Config |= DML_CFG_CHEAT_PATH;
|
||||
}
|
||||
|
||||
if(cheats)
|
||||
DMLCfg->Config |= DML_CFG_CHEATS;
|
||||
if(debugger)
|
||||
DMLCfg->Config |= DML_CFG_DEBUGGER;
|
||||
if(NMM > 0)
|
||||
DMLCfg->Config |= DML_CFG_NMM;
|
||||
if(NMM > 1)
|
||||
DMLCfg->Config |= DML_CFG_NMM_DEBUG;
|
||||
if(nodisc > 0)
|
||||
DMLCfg->Config |= DML_CFG_NODISC;
|
||||
|
||||
if(DMLvideoMode > 3)
|
||||
DMLCfg->VideoMode |= DML_VID_PROG_PATCH;
|
||||
}
|
||||
|
||||
void DML_Old_SetOptions(char *GamePath, char *CheatPath, char *NewCheatPath, bool cheats)
|
||||
{
|
||||
gprintf("Wiiflow DML: Launch game '%s' through boot.bin (old method)\n", GamePath);
|
||||
FILE *f;
|
||||
f = fopen("sd:/games/boot.bin", "wb");
|
||||
fwrite(GamePath, 1, strlen(GamePath) + 1, f);
|
||||
fclose(f);
|
||||
|
||||
if(cheats && strstr(CheatPath, NewCheatPath) == NULL)
|
||||
fsop_CopyFile(CheatPath, NewCheatPath, NULL, NULL);
|
||||
|
||||
//Tell DML to boot the game from sd card
|
||||
*(vu32*)0x80001800 = 0xB002D105;
|
||||
DCFlushRange((void *)(0x80001800), 4);
|
||||
ICInvalidateRange((void *)(0x80001800), 4);
|
||||
|
||||
*(vu32*)0xCC003024 |= 7;
|
||||
}
|
||||
|
||||
void DML_New_SetBootDiscOption()
|
||||
{
|
||||
gprintf("Booting GC game\n");
|
||||
|
||||
DMLCfg = (DML_CFG*)MEM1_alloc(sizeof(DML_CFG));
|
||||
if(DMLCfg == NULL)
|
||||
return;
|
||||
memset(DMLCfg, 0, sizeof(DML_CFG));
|
||||
|
||||
DMLCfg->Magicbytes = 0xD1050CF6;
|
||||
DMLCfg->CfgVersion = 0x00000001;
|
||||
DMLCfg->VideoMode |= DML_VID_DML_AUTO;
|
||||
|
||||
DMLCfg->Config |= DML_CFG_BOOT_DISC;
|
||||
}
|
||||
|
||||
void DML_New_WriteOptions()
|
||||
{
|
||||
if(DMLCfg == NULL)
|
||||
return;
|
||||
|
||||
//Write options into memory
|
||||
memcpy((void *)0x80001700, DMLCfg, sizeof(DML_CFG));
|
||||
DCFlushRange((void *)(0x80001700), sizeof(DML_CFG));
|
||||
|
||||
//DML v1.2+
|
||||
memcpy((void *)0x81200000, DMLCfg, sizeof(DML_CFG));
|
||||
DCFlushRange((void *)(0x81200000), sizeof(DML_CFG));
|
||||
|
||||
MEM1_free(DMLCfg);
|
||||
}
|
||||
|
||||
|
||||
// Devolution
|
||||
static gconfig *DEVO_CONFIG = (gconfig*)0x80000020;
|
||||
|
||||
void DEVO_SetOptions(const char *path, const char *partition)
|
||||
{
|
||||
struct stat st;
|
||||
char full_path[256];
|
||||
int data_fd;
|
||||
|
||||
stat(path, &st);
|
||||
u8 *lowmem = (u8*)0x80000000;
|
||||
FILE *iso_file = fopen(path, "rb");
|
||||
fread(lowmem, 1, 32, iso_file);
|
||||
fclose(iso_file);
|
||||
|
||||
// fill out the Devolution config struct
|
||||
memset(DEVO_CONFIG, 0, sizeof(*DEVO_CONFIG));
|
||||
DEVO_CONFIG->signature = 0x3EF9DB23;
|
||||
DEVO_CONFIG->version = 0x00000100;
|
||||
DEVO_CONFIG->device_signature = st.st_dev;
|
||||
DEVO_CONFIG->disc1_cluster = st.st_ino;
|
||||
|
||||
// make sure these directories exist, they are required for Devolution to function correctly
|
||||
snprintf(full_path, sizeof(full_path), "%s:/apps", partition);
|
||||
fsop_MakeFolder(full_path);
|
||||
snprintf(full_path, sizeof(full_path), "%s:/apps/gc_devo", partition);
|
||||
fsop_MakeFolder(full_path);
|
||||
|
||||
// find or create a 16MB memcard file for emulation
|
||||
// this file can be located anywhere since it's passed by cluster, not name
|
||||
// it must be at least 16MB though
|
||||
snprintf(full_path, sizeof(full_path), "%s:/apps/gc_devo/memcard.bin", partition);
|
||||
|
||||
// check if file doesn't exist or is less than 16MB
|
||||
if(stat(full_path, &st) == -1 || st.st_size < 16<<20)
|
||||
{
|
||||
// need to enlarge or create it
|
||||
data_fd = open(full_path, O_WRONLY|O_CREAT);
|
||||
if (data_fd>=0)
|
||||
{
|
||||
// make it 16MB
|
||||
printf("Resizing memcard file...\n");
|
||||
ftruncate(data_fd, 16<<20);
|
||||
if (fstat(data_fd, &st)==-1 || st.st_size < 16<<20)
|
||||
{
|
||||
// it still isn't big enough. Give up.
|
||||
st.st_ino = 0;
|
||||
}
|
||||
close(data_fd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// couldn't open or create the memory card file
|
||||
st.st_ino = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// set FAT cluster for start of memory card file
|
||||
// if this is zero memory card emulation will not be used
|
||||
DEVO_CONFIG->memcard_cluster = st.st_ino;
|
||||
|
||||
// flush disc ID and Devolution config out to memory
|
||||
DCFlushRange(lowmem, 64);
|
||||
}
|
||||
|
||||
|
||||
// General
|
||||
#define SRAM_ENGLISH 0
|
||||
#define SRAM_GERMAN 1
|
||||
#define SRAM_FRENCH 2
|
||||
@ -19,7 +200,6 @@
|
||||
syssram* __SYS_LockSram();
|
||||
u32 __SYS_UnlockSram(u32 write);
|
||||
u32 __SYS_SyncSram(void);
|
||||
DML_CFG *DMLCfg = NULL;
|
||||
|
||||
void GC_SetVideoMode(u8 videomode, bool force)
|
||||
{
|
||||
@ -158,108 +338,3 @@ int GC_GameIsInstalled(char *discid, const char* partition, const char* dmlgamed
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DML_New_SetOptions(const char *GamePath, char *CheatPath, char *NewCheatPath, bool cheats, bool debugger, u8 NMM, u8 nodisc, u8 DMLvideoMode, bool force)
|
||||
{
|
||||
gprintf("Wiiflow DML: Launch game '%s' through memory (new method)\n", GamePath);
|
||||
|
||||
DMLCfg = (DML_CFG*)MEM1_alloc(sizeof(DML_CFG));
|
||||
if(DMLCfg == NULL)
|
||||
return;
|
||||
memset(DMLCfg, 0, sizeof(DML_CFG));
|
||||
|
||||
DMLCfg->Magicbytes = 0xD1050CF6;
|
||||
DMLCfg->CfgVersion = 0x00000001;
|
||||
if(force)
|
||||
DMLCfg->VideoMode |= DML_VID_FORCE;
|
||||
else
|
||||
DMLCfg->VideoMode |= DML_VID_DML_AUTO;
|
||||
|
||||
DMLCfg->Config |= DML_CFG_ACTIVITY_LED; //Sorry but I like it lol, option will may follow
|
||||
DMLCfg->Config |= DML_CFG_PADHOOK; //Makes life easier, l+z+b+digital down...
|
||||
|
||||
if(GamePath != NULL)
|
||||
{
|
||||
strncpy(DMLCfg->GamePath, GamePath, sizeof(DMLCfg->GamePath));
|
||||
DMLCfg->Config |= DML_CFG_GAME_PATH;
|
||||
}
|
||||
|
||||
if(CheatPath != NULL && NewCheatPath != NULL && cheats)
|
||||
{
|
||||
char *ptr;
|
||||
if(strstr(CheatPath, "sd:/") == NULL)
|
||||
{
|
||||
fsop_CopyFile(CheatPath, NewCheatPath, NULL, NULL);
|
||||
ptr = &NewCheatPath[3];
|
||||
}
|
||||
else
|
||||
ptr = &CheatPath[3];
|
||||
strncpy(DMLCfg->CheatPath, ptr, sizeof(DMLCfg->CheatPath));
|
||||
DMLCfg->Config |= DML_CFG_CHEAT_PATH;
|
||||
}
|
||||
|
||||
if(cheats)
|
||||
DMLCfg->Config |= DML_CFG_CHEATS;
|
||||
if(debugger)
|
||||
DMLCfg->Config |= DML_CFG_DEBUGGER;
|
||||
if(NMM > 0)
|
||||
DMLCfg->Config |= DML_CFG_NMM;
|
||||
if(NMM > 1)
|
||||
DMLCfg->Config |= DML_CFG_NMM_DEBUG;
|
||||
if(nodisc > 0)
|
||||
DMLCfg->Config |= DML_CFG_NODISC;
|
||||
|
||||
if(DMLvideoMode > 3)
|
||||
DMLCfg->VideoMode |= DML_VID_PROG_PATCH;
|
||||
}
|
||||
|
||||
void DML_Old_SetOptions(char *GamePath, char *CheatPath, char *NewCheatPath, bool cheats)
|
||||
{
|
||||
gprintf("Wiiflow DML: Launch game '%s' through boot.bin (old method)\n", GamePath);
|
||||
FILE *f;
|
||||
f = fopen("sd:/games/boot.bin", "wb");
|
||||
fwrite(GamePath, 1, strlen(GamePath) + 1, f);
|
||||
fclose(f);
|
||||
|
||||
if(cheats && strstr(CheatPath, NewCheatPath) == NULL)
|
||||
fsop_CopyFile(CheatPath, NewCheatPath, NULL, NULL);
|
||||
|
||||
//Tell DML to boot the game from sd card
|
||||
*(vu32*)0x80001800 = 0xB002D105;
|
||||
DCFlushRange((void *)(0x80001800), 4);
|
||||
ICInvalidateRange((void *)(0x80001800), 4);
|
||||
|
||||
*(vu32*)0xCC003024 |= 7;
|
||||
}
|
||||
|
||||
void DML_New_SetBootDiscOption()
|
||||
{
|
||||
gprintf("Booting GC game\n");
|
||||
|
||||
DMLCfg = (DML_CFG*)MEM1_alloc(sizeof(DML_CFG));
|
||||
if(DMLCfg == NULL)
|
||||
return;
|
||||
memset(DMLCfg, 0, sizeof(DML_CFG));
|
||||
|
||||
DMLCfg->Magicbytes = 0xD1050CF6;
|
||||
DMLCfg->CfgVersion = 0x00000001;
|
||||
DMLCfg->VideoMode |= DML_VID_DML_AUTO;
|
||||
|
||||
DMLCfg->Config |= DML_CFG_BOOT_DISC;
|
||||
}
|
||||
|
||||
void DML_New_WriteOptions()
|
||||
{
|
||||
if(DMLCfg == NULL)
|
||||
return;
|
||||
|
||||
//Write options into memory
|
||||
memcpy((void *)0x80001700, DMLCfg, sizeof(DML_CFG));
|
||||
DCFlushRange((void *)(0x80001700), sizeof(DML_CFG));
|
||||
|
||||
//DML v1.2+
|
||||
memcpy((void *)0x81200000, DMLCfg, sizeof(DML_CFG));
|
||||
DCFlushRange((void *)(0x81200000), sizeof(DML_CFG));
|
||||
|
||||
MEM1_free(DMLCfg);
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ extern "C"
|
||||
#ifndef GC_H_
|
||||
#define GC_H_
|
||||
|
||||
// DIOS-MIOS
|
||||
typedef struct DML_CFG
|
||||
{
|
||||
u32 Magicbytes; //0xD1050CF6
|
||||
@ -45,14 +46,31 @@ enum dmlvideomode
|
||||
DML_VID_PROG_PATCH = (1<<4),
|
||||
};
|
||||
|
||||
void GC_SetVideoMode(u8 videomode, bool force);
|
||||
void GC_SetLanguage(u8 lang);
|
||||
int GC_GameIsInstalled(char *discid, const char* partition, const char* dmlgamedir);
|
||||
|
||||
void DML_New_SetOptions(const char *GamePath, char *CheatPath, char *NewCheatPath, bool cheats, bool debugger, u8 NMM, u8 nodisc, u8 DMLvideoMode, bool force);
|
||||
void DML_Old_SetOptions(char *GamePath, char *CheatPath, char *NewCheatPath, bool cheats);
|
||||
void DML_New_SetBootDiscOption();
|
||||
void DML_New_WriteOptions();
|
||||
|
||||
|
||||
// Devolution
|
||||
typedef struct global_config
|
||||
{
|
||||
u32 signature; //0x3EF9DB23
|
||||
u16 version; //0x00000100
|
||||
u16 device_signature;
|
||||
u32 memcard_cluster;
|
||||
u32 disc1_cluster;
|
||||
u32 disc2_cluster;
|
||||
} gconfig;
|
||||
|
||||
void DEVO_SetOptions(const char* path, const char *partition);
|
||||
|
||||
|
||||
// General
|
||||
void GC_SetVideoMode(u8 videomode, bool force);
|
||||
void GC_SetLanguage(u8 lang);
|
||||
int GC_GameIsInstalled(char *discid, const char* partition, const char* dmlgamedir);
|
||||
|
||||
#endif //GC_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -788,6 +788,21 @@ void CMenu::_launchGC(dir_discHdr *hdr, bool DML)
|
||||
if(has_enabled_providers() && _initNetwork() == 0)
|
||||
add_game_to_card(id.c_str());
|
||||
|
||||
bool devo = false;
|
||||
u8 *loader_bin = NULL;
|
||||
FILE *f = fopen(fmt("%s/loader.bin", m_dataDir.c_str()), "rb");
|
||||
if(f)
|
||||
{
|
||||
devo = true;
|
||||
fseek(f, 0, SEEK_END);
|
||||
u32 size = ftell(f);
|
||||
rewind(f);
|
||||
loader_bin = (u8*)MEM2_alloc(size);
|
||||
fread(loader_bin, 1, size, f);
|
||||
puts((const char*)loader_bin + 4);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
u8 GClanguage = min((u32)m_gcfg2.getInt(id, "gc_language", 0), ARRAY_SIZE(CMenu::_GClanguages) - 1u);
|
||||
GClanguage = (GClanguage == 0) ? min((u32)m_cfg.getInt("DML", "game_language", 0), ARRAY_SIZE(CMenu::_GlobalGClanguages) - 1u) : GClanguage-1;
|
||||
|
||||
@ -824,7 +839,11 @@ void CMenu::_launchGC(dir_discHdr *hdr, bool DML)
|
||||
newPath.erase(newPath.end() - 12, newPath.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
newPath = &path[path.find_first_of(":/")+1];
|
||||
if(devo)
|
||||
DEVO_SetOptions(path.c_str(), DeviceName[currentPartition]);
|
||||
}
|
||||
if(m_new_dml)
|
||||
DML_New_SetOptions(newPath.c_str(), CheatPath, NewCheatPath, cheats, DML_debug, NMM, nodisc, DMLvideoMode, false);
|
||||
else
|
||||
@ -851,11 +870,18 @@ void CMenu::_launchGC(dir_discHdr *hdr, bool DML)
|
||||
|
||||
GC_SetVideoMode(DMLvideoMode, false);
|
||||
GC_SetLanguage(GClanguage);
|
||||
DML_New_WriteOptions();
|
||||
|
||||
WII_Initialize();
|
||||
if(WII_LaunchTitle(0x100000100LL) < 0)
|
||||
Sys_LoadMenu();
|
||||
if(!devo)
|
||||
{
|
||||
DML_New_WriteOptions();
|
||||
WII_Initialize();
|
||||
if(WII_LaunchTitle(0x100000100LL) < 0)
|
||||
Sys_LoadMenu();
|
||||
}
|
||||
else
|
||||
{
|
||||
#define LAUNCH() ((void(*)(void))loader_bin)()
|
||||
LAUNCH();
|
||||
}
|
||||
}
|
||||
|
||||
void CMenu::_launchHomebrew(const char *filepath, vector<string> arguments)
|
||||
|
Loading…
x
Reference in New Issue
Block a user