-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:
fix94.1 2012-07-12 13:21:14 +00:00
parent ac3816d7e9
commit 8aa08dee60
3 changed files with 235 additions and 116 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -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)