mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-18 09:19:17 +01:00
* Fixed installation destination for multi-Disc based games.
Second ISO is now properly going into the existing folder instead of using the Disc's internal Game Title. * Prevent deleting a folder when installation is canceled if the folder still contains another disc number. * Added a new setting to select GameCube game source: SD, USB, Auto Auto = based on DIOS MIOS (Lite). This new setting fix two known problems: - Device selection for Devolution is no more dependent of the installed DM(L) type. (Select manually before launching a game) - Installation of a game on a device if the game is already on another device is now possible.
This commit is contained in:
parent
77f7daf9dc
commit
9e993326e5
@ -2,8 +2,8 @@
|
|||||||
<app version="1">
|
<app version="1">
|
||||||
<name> USB Loader GX</name>
|
<name> USB Loader GX</name>
|
||||||
<coder>USB Loader GX Team</coder>
|
<coder>USB Loader GX Team</coder>
|
||||||
<version>3.0 r1206</version>
|
<version>3.0 r1207</version>
|
||||||
<release_date>20121209202238</release_date>
|
<release_date>20121209211824</release_date>
|
||||||
<!-- // remove this line to enable arguments
|
<!-- // remove this line to enable arguments
|
||||||
<arguments>
|
<arguments>
|
||||||
<arg>--ios=250</arg>
|
<arg>--ios=250</arg>
|
||||||
|
@ -201,7 +201,7 @@ int GCDumper::ReadDiscInfo(const u64 &game_offset)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 GCDumper::InstallGame(const char *installpath, u32 game)
|
s32 GCDumper::InstallGame(const char *installpath, u32 game, const char *installedGamePath)
|
||||||
{
|
{
|
||||||
if(!ReadBuffer || game >= discHeaders.size() || game >= gameOffsets.size() || game >= gameSizes.size())
|
if(!ReadBuffer || game >= discHeaders.size() || game >= gameOffsets.size() || game >= gameSizes.size())
|
||||||
return -1;
|
return -1;
|
||||||
@ -266,6 +266,10 @@ s32 GCDumper::InstallGame(const char *installpath, u32 game)
|
|||||||
// snprintf(gamepath, sizeof(gamepath), "%s%s [%.6s]%s/", installpath, gametitle, gcheader.id, Disc ? "2" : ""); // Disc2 currently needs to be on the same folder.
|
// snprintf(gamepath, sizeof(gamepath), "%s%s [%.6s]%s/", installpath, gametitle, gcheader.id, Disc ? "2" : ""); // Disc2 currently needs to be on the same folder.
|
||||||
snprintf(gamepath, sizeof(gamepath), "%s%s [%.6s]/", installpath, gametitle, gcheader.id);
|
snprintf(gamepath, sizeof(gamepath), "%s%s [%.6s]/", installpath, gametitle, gcheader.id);
|
||||||
|
|
||||||
|
// If another Disc from the same gameID already exists, let's use that path
|
||||||
|
if(strlen((char *)installedGamePath) != 0)
|
||||||
|
snprintf(gamepath, sizeof(gamepath), "%s/", installedGamePath);
|
||||||
|
|
||||||
CreateSubfolder(gamepath);
|
CreateSubfolder(gamepath);
|
||||||
|
|
||||||
// snprintf(gamepath, sizeof(gamepath), "%s%s [%.6s]%s/game.iso", installpath, gametitle, gcheader.id, Disc ? "2" : ""); // Disc2 currently needs to be on the same folder.
|
// snprintf(gamepath, sizeof(gamepath), "%s%s [%.6s]%s/game.iso", installpath, gametitle, gcheader.id, Disc ? "2" : ""); // Disc2 currently needs to be on the same folder.
|
||||||
@ -384,9 +388,12 @@ s32 GCDumper::InstallGame(const char *installpath, u32 game)
|
|||||||
if(result < 0)
|
if(result < 0)
|
||||||
{
|
{
|
||||||
RemoveFile(gamepath);
|
RemoveFile(gamepath);
|
||||||
char *pathPtr = strrchr(gamepath, '/');
|
if(strlen((char *)installedGamePath) == 0) // If no other disc is installed in that folder, delete it.
|
||||||
if(pathPtr) *pathPtr = 0;
|
{
|
||||||
RemoveFile(gamepath);
|
char *pathPtr = strrchr(gamepath, '/');
|
||||||
|
if(pathPtr) *pathPtr = 0;
|
||||||
|
RemoveFile(gamepath);
|
||||||
|
}
|
||||||
|
|
||||||
if(result != PROGRESS_CANCELED)
|
if(result != PROGRESS_CANCELED)
|
||||||
ShowError(tr("Disc read error."));
|
ShowError(tr("Disc read error."));
|
||||||
|
@ -37,7 +37,7 @@ class GCDumper
|
|||||||
public:
|
public:
|
||||||
GCDumper();
|
GCDumper();
|
||||||
~GCDumper();
|
~GCDumper();
|
||||||
s32 InstallGame(const char *installpath, u32 game);
|
s32 InstallGame(const char *installpath, u32 game, const char *installedGamePath);
|
||||||
s32 ReadDiscHeader(void);
|
s32 ReadDiscHeader(void);
|
||||||
int ReadDiscInfo(const u64 &game_offset);
|
int ReadDiscInfo(const u64 &game_offset);
|
||||||
void SetForceAlign(bool b) { force_align32 = b; }
|
void SetForceAlign(bool b) { force_align32 = b; }
|
||||||
|
@ -222,38 +222,47 @@ u32 GCGames::LoadAllGames(void)
|
|||||||
sdGCList.clear();
|
sdGCList.clear();
|
||||||
sdGCPathList.clear();
|
sdGCPathList.clear();
|
||||||
|
|
||||||
LoadGameList(Settings.GameCubePath, HeaderList, PathList);
|
if(strcmp(Settings.GameCubePath, Settings.GameCubeSDPath) == 0 || Settings.GameCubeSource != GC_SOURCE_SD)
|
||||||
|
LoadGameList(Settings.GameCubePath, HeaderList, PathList);
|
||||||
|
|
||||||
if(strcmp(Settings.GameCubePath, Settings.GameCubeSDPath) != 0)
|
if(strcmp(Settings.GameCubePath, Settings.GameCubeSDPath) != 0 && (Settings.GameCubeSource != GC_SOURCE_MAIN))
|
||||||
{
|
{
|
||||||
LoadGameList(Settings.GameCubeSDPath, sdGCList, sdGCPathList);
|
LoadGameList(Settings.GameCubeSDPath, sdGCList, sdGCPathList);
|
||||||
|
|
||||||
for(u32 i = 0; i < sdGCList.size(); ++i)
|
for(u32 i = 0; i < sdGCList.size(); ++i)
|
||||||
{
|
{
|
||||||
u32 n;
|
if(Settings.GameCubeSource == GC_SOURCE_AUTO)
|
||||||
for(n = 0; n < HeaderList.size(); ++n)
|
|
||||||
{
|
{
|
||||||
//! Display only one game if it is present on both SD and USB.
|
u32 n;
|
||||||
if(memcmp(HeaderList[n].id, sdGCList[i].id, 6) == 0)
|
for(n = 0; n < HeaderList.size(); ++n)
|
||||||
{
|
{
|
||||||
if(IosLoader::GetMIOSInfo() == DIOS_MIOS) // DIOS MIOS - Show only the game on USB
|
//! Display only one game if it is present on both SD and USB.
|
||||||
|
if(memcmp(HeaderList[n].id, sdGCList[i].id, 6) == 0)
|
||||||
{
|
{
|
||||||
break;
|
if(IosLoader::GetMIOSInfo() == DIOS_MIOS) // DIOS MIOS - Show only the game on USB
|
||||||
}
|
{
|
||||||
else // replace the one loaded from USB with the same games on SD since we can load them directly
|
break;
|
||||||
{
|
}
|
||||||
memcpy(&HeaderList[n], &sdGCList[i], sizeof(struct discHdr));
|
else // replace the one loaded from USB with the same games on SD since we can load them directly
|
||||||
PathList[n] = sdGCPathList[i];
|
{
|
||||||
break;
|
memcpy(&HeaderList[n], &sdGCList[i], sizeof(struct discHdr));
|
||||||
|
PathList[n] = sdGCPathList[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Not available in the main GC path
|
// Not available in the main GC path
|
||||||
if(n == HeaderList.size()) {
|
if(n == HeaderList.size()) {
|
||||||
HeaderList.push_back(sdGCList[i]);
|
HeaderList.push_back(sdGCList[i]);
|
||||||
PathList.push_back(sdGCPathList[i]);
|
PathList.push_back(sdGCPathList[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else // GC_SOURCE_SD, or GC_SOURCE_BOTH (show duplicates)
|
||||||
|
{
|
||||||
|
HeaderList.push_back(sdGCList[i]);
|
||||||
|
PathList.push_back(sdGCPathList[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,7 +395,7 @@ bool GCGames::IsInstalled(const char *gameID, u8 disc_number) const
|
|||||||
{
|
{
|
||||||
if(memcmp(HeaderList[n].id, gameID, 6) == 0)
|
if(memcmp(HeaderList[n].id, gameID, 6) == 0)
|
||||||
{
|
{
|
||||||
if(HeaderList[n].type == TYPE_GAME_GC_EXTRACTED)
|
if(HeaderList[n].type == TYPE_GAME_GC_EXTRACTED || Settings.GCInstallCompressed)
|
||||||
return true; // Multi-disc games in extracted form are currently unsupported by DML, no need to check further.
|
return true; // Multi-disc games in extracted form are currently unsupported by DML, no need to check further.
|
||||||
|
|
||||||
if(HeaderList[n].disc_no == disc_number) // Disc number already in headerList. If Disc2 is loaded in headerList, then Disc1 is not installed yet
|
if(HeaderList[n].disc_no == disc_number) // Disc number already in headerList. If Disc2 is loaded in headerList, then Disc1 is not installed yet
|
||||||
|
@ -84,6 +84,11 @@ int MenuGCInstall()
|
|||||||
return MENU_DISCLIST;
|
return MENU_DISCLIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load only available games from the selected device
|
||||||
|
int oldGameCubeSource = Settings.GameCubeSource;
|
||||||
|
Settings.GameCubeSource = destination-1;
|
||||||
|
GCGames::Instance()->LoadAllGames();
|
||||||
|
|
||||||
const char *InstallPath = destination == 1 ? Settings.GameCubePath : Settings.GameCubeSDPath;
|
const char *InstallPath = destination == 1 ? Settings.GameCubePath : Settings.GameCubeSDPath;
|
||||||
|
|
||||||
//! Start of install process, enable wii slot light
|
//! Start of install process, enable wii slot light
|
||||||
@ -125,8 +130,20 @@ int MenuGCInstall()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if another Disc number from the same game is already installed on this device
|
||||||
|
GCGames::Instance()->LoadAllGames(); // refresh installed game list
|
||||||
|
char installedGamePath[512];
|
||||||
|
if(GCGames::Instance()->IsInstalled((char *)gcDumper.GetDiscHeaders().at(installGames[i]).id, gcDumper.GetDiscHeaders().at(installGames[i]).disc_no == 0 ? 1 : 0))
|
||||||
|
{
|
||||||
|
snprintf(installedGamePath, sizeof(installedGamePath), GCGames::Instance()->GetPath((char *)gcDumper.GetDiscHeaders().at(installGames[i]).id));
|
||||||
|
char *pathPtr = strrchr(installedGamePath, '/');
|
||||||
|
if(pathPtr) *pathPtr = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
installedGamePath[0] = 0;
|
||||||
|
|
||||||
// game is not yet installed so let's install it
|
// game is not yet installed so let's install it
|
||||||
int ret = gcDumper.InstallGame(InstallPath, installGames[i]);
|
int ret = gcDumper.InstallGame(InstallPath, installGames[i], installedGamePath);
|
||||||
if(ret >= 0) {
|
if(ret >= 0) {
|
||||||
//! success
|
//! success
|
||||||
installed_games++;
|
installed_games++;
|
||||||
@ -157,6 +174,7 @@ int MenuGCInstall()
|
|||||||
}
|
}
|
||||||
|
|
||||||
wiilight(0);
|
wiilight(0);
|
||||||
|
Settings.GameCubeSource = oldGameCubeSource;
|
||||||
GCGames::Instance()->LoadAllGames();
|
GCGames::Instance()->LoadAllGames();
|
||||||
|
|
||||||
//! no game was installed so don't show successfully installed prompt
|
//! no game was installed so don't show successfully installed prompt
|
||||||
|
@ -169,6 +169,7 @@ void CSettings::SetDefault()
|
|||||||
BannerProjectionHeight = (Settings.PAL50 ? 448.0f : (NTSC ? 470.0f : 464.0f));
|
BannerProjectionHeight = (Settings.PAL50 ? 448.0f : (NTSC ? 470.0f : 464.0f));
|
||||||
GCBannerScale = 1.5f;
|
GCBannerScale = 1.5f;
|
||||||
GameCubeMode = GC_MODE_MIOS;
|
GameCubeMode = GC_MODE_MIOS;
|
||||||
|
GameCubeSource = AUTO;
|
||||||
DMLVideo = DML_VIDEO_AUTO;
|
DMLVideo = DML_VIDEO_AUTO;
|
||||||
DMLProgPatch = OFF;
|
DMLProgPatch = OFF;
|
||||||
DMLNMM = OFF;
|
DMLNMM = OFF;
|
||||||
@ -398,6 +399,7 @@ bool CSettings::Save()
|
|||||||
fprintf(file, "GameCubePath = %s\n", GameCubePath);
|
fprintf(file, "GameCubePath = %s\n", GameCubePath);
|
||||||
fprintf(file, "GameCubeSDPath = %s\n", GameCubeSDPath);
|
fprintf(file, "GameCubeSDPath = %s\n", GameCubeSDPath);
|
||||||
fprintf(file, "GameCubeMode = %d\n", GameCubeMode);
|
fprintf(file, "GameCubeMode = %d\n", GameCubeMode);
|
||||||
|
fprintf(file, "GameCubeSource = %d\n", GameCubeSource);
|
||||||
fprintf(file, "DMLVideo = %d\n", DMLVideo);
|
fprintf(file, "DMLVideo = %d\n", DMLVideo);
|
||||||
fprintf(file, "DMLProgPatch = %d\n", DMLProgPatch);
|
fprintf(file, "DMLProgPatch = %d\n", DMLProgPatch);
|
||||||
fprintf(file, "DMLNMM = %d\n", DMLNMM);
|
fprintf(file, "DMLNMM = %d\n", DMLNMM);
|
||||||
@ -806,6 +808,11 @@ bool CSettings::SetSetting(char *name, char *value)
|
|||||||
GameCubeMode = atoi(value);
|
GameCubeMode = atoi(value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (strcmp(name, "GameCubeSource") == 0)
|
||||||
|
{
|
||||||
|
GameCubeSource = atoi(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
else if (strcmp(name, "DMLVideo") == 0)
|
else if (strcmp(name, "DMLVideo") == 0)
|
||||||
{
|
{
|
||||||
DMLVideo = atoi(value);
|
DMLVideo = atoi(value);
|
||||||
|
@ -171,6 +171,7 @@ class CSettings
|
|||||||
float BannerProjectionHeight;
|
float BannerProjectionHeight;
|
||||||
float GCBannerScale;
|
float GCBannerScale;
|
||||||
short GameCubeMode;
|
short GameCubeMode;
|
||||||
|
short GameCubeSource;
|
||||||
short DMLVideo;
|
short DMLVideo;
|
||||||
short DMLProgPatch;
|
short DMLProgPatch;
|
||||||
short DMLNMM;
|
short DMLNMM;
|
||||||
|
@ -280,6 +280,16 @@ enum
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
GC_SOURCE_MAIN,
|
||||||
|
GC_SOURCE_SD,
|
||||||
|
GC_SOURCE_AUTO,
|
||||||
|
// GC_SOURCE_BOTH, // GCGames::getPath(GameID) always returns the first encountered path in the gameList
|
||||||
|
CG_SOURCE_MAX_CHOICE
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
DEVO_MC_OFF,
|
DEVO_MC_OFF,
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include "usbloader/GameList.h"
|
#include "usbloader/GameList.h"
|
||||||
#include "utils/tools.h"
|
#include "utils/tools.h"
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
|
#include "gamecube/GCGames.h"
|
||||||
|
|
||||||
static const char * OnOffText[] =
|
static const char * OnOffText[] =
|
||||||
{
|
{
|
||||||
@ -115,6 +116,14 @@ static const char * GCMode[] =
|
|||||||
trNOOP( "Devolution" ),
|
trNOOP( "Devolution" ),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char * GCSourceText[] =
|
||||||
|
{
|
||||||
|
trNOOP( "Main Path" ),
|
||||||
|
trNOOP( "SD Path" ),
|
||||||
|
trNOOP( "Auto" ),
|
||||||
|
trNOOP( "Both" ),
|
||||||
|
};
|
||||||
|
|
||||||
static const char * DMLVideoText[] =
|
static const char * DMLVideoText[] =
|
||||||
{
|
{
|
||||||
trNOOP( "DML Auto" ),
|
trNOOP( "DML Auto" ),
|
||||||
@ -167,6 +176,7 @@ LoaderSettings::LoaderSettings()
|
|||||||
Options->SetName(Idx++, "%s", tr( "Debugger Paused Start" ));
|
Options->SetName(Idx++, "%s", tr( "Debugger Paused Start" ));
|
||||||
Options->SetName(Idx++, "%s", tr( "Channel Launcher" ));
|
Options->SetName(Idx++, "%s", tr( "Channel Launcher" ));
|
||||||
Options->SetName(Idx++, "%s", tr( "GameCube Mode" ));
|
Options->SetName(Idx++, "%s", tr( "GameCube Mode" ));
|
||||||
|
Options->SetName(Idx++, "%s", tr( "GameCube Source" ));
|
||||||
Options->SetName(Idx++, "%s", tr( "DML Video Mode" ));
|
Options->SetName(Idx++, "%s", tr( "DML Video Mode" ));
|
||||||
Options->SetName(Idx++, "%s", tr( "DML Progressive Patch" ));
|
Options->SetName(Idx++, "%s", tr( "DML Progressive Patch" ));
|
||||||
Options->SetName(Idx++, "%s", tr( "DML NMM Mode" ));
|
Options->SetName(Idx++, "%s", tr( "DML NMM Mode" ));
|
||||||
@ -184,6 +194,7 @@ LoaderSettings::LoaderSettings()
|
|||||||
SetOptionValues();
|
SetOptionValues();
|
||||||
|
|
||||||
oldLoaderMode = Settings.LoaderMode;
|
oldLoaderMode = Settings.LoaderMode;
|
||||||
|
oldGameCubeSource = Settings.GameCubeSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
LoaderSettings::~LoaderSettings()
|
LoaderSettings::~LoaderSettings()
|
||||||
@ -199,6 +210,11 @@ LoaderSettings::~LoaderSettings()
|
|||||||
gameList.LoadUnfiltered();
|
gameList.LoadUnfiltered();
|
||||||
GameTitles.LoadTitlesFromGameTDB(Settings.titlestxt_path, false);
|
GameTitles.LoadTitlesFromGameTDB(Settings.titlestxt_path, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(oldGameCubeSource != Settings.GameCubeSource)
|
||||||
|
{
|
||||||
|
GCGames::Instance()->LoadAllGames();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoaderSettings::SetOptionValues()
|
void LoaderSettings::SetOptionValues()
|
||||||
@ -270,6 +286,9 @@ void LoaderSettings::SetOptionValues()
|
|||||||
//! Settings: GameCube Mode
|
//! Settings: GameCube Mode
|
||||||
Options->SetValue(Idx++, "%s", tr(GCMode[Settings.GameCubeMode]));
|
Options->SetValue(Idx++, "%s", tr(GCMode[Settings.GameCubeMode]));
|
||||||
|
|
||||||
|
//! Settings: GameCube Source
|
||||||
|
Options->SetValue(Idx++, "%s", tr(GCSourceText[Settings.GameCubeSource]));
|
||||||
|
|
||||||
//! Settings: DML Video Mode
|
//! Settings: DML Video Mode
|
||||||
Options->SetValue(Idx++, "%s", tr(DMLVideoText[Settings.DMLVideo]));
|
Options->SetValue(Idx++, "%s", tr(DMLVideoText[Settings.DMLVideo]));
|
||||||
|
|
||||||
@ -458,6 +477,12 @@ int LoaderSettings::GetMenuInternal()
|
|||||||
if (++Settings.GameCubeMode >= CG_MODE_MAX_CHOICE) Settings.GameCubeMode = 0;
|
if (++Settings.GameCubeMode >= CG_MODE_MAX_CHOICE) Settings.GameCubeMode = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Settings: GameCube Source
|
||||||
|
else if (ret == ++Idx)
|
||||||
|
{
|
||||||
|
if (++Settings.GameCubeSource >= CG_SOURCE_MAX_CHOICE) Settings.GameCubeSource = 0;
|
||||||
|
}
|
||||||
|
|
||||||
//! Settings: DML Video Mode
|
//! Settings: DML Video Mode
|
||||||
else if (ret == ++Idx)
|
else if (ret == ++Idx)
|
||||||
{
|
{
|
||||||
|
@ -36,6 +36,7 @@ class LoaderSettings : public SettingsMenu
|
|||||||
int GetMenuInternal();
|
int GetMenuInternal();
|
||||||
|
|
||||||
short oldLoaderMode;
|
short oldLoaderMode;
|
||||||
|
short oldGameCubeSource;
|
||||||
OptionList GuiOptions;
|
OptionList GuiOptions;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user