mirror of
https://github.com/Team-Resurgent/UIXLiteFTP.git
synced 2026-08-15 11:18:21 -07:00
884 lines
31 KiB
C++
884 lines
31 KiB
C++
#include "stdafx.h"
|
|
#include <xtl.h>
|
|
#include <string>
|
|
|
|
#include "audioPlayer.h"
|
|
#include "component.h"
|
|
#include "context.h"
|
|
#include "drawing.h"
|
|
#include "inputManager.h"
|
|
#include "xboxinternals.h"
|
|
#include "meshUtility.h"
|
|
#include "utils.h"
|
|
#include "resources.h"
|
|
#include "stringUtility.h"
|
|
#include "theme.h"
|
|
#include "ssfn.h"
|
|
#include "ftpServer.h"
|
|
#include "driveManager.h"
|
|
#include "network.h"
|
|
|
|
#include <xgraphics.h>
|
|
#include "xbeParser.h"
|
|
#include "xunzip.h"
|
|
#include "IniUtility.h"
|
|
|
|
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_TEX1)
|
|
#define MAX_MENU_DEPTH 5
|
|
|
|
typedef struct MenuEntry {
|
|
const char* label;
|
|
void (*action)();
|
|
struct MenuEntry* subMenu;
|
|
int subMenuSize;
|
|
} MenuEntry;
|
|
|
|
char* StatusMsg = NULL;
|
|
char* zipFile = NULL;
|
|
char* UDATA = strdup("HDD0-E:\\UDATA");
|
|
bool unzipfile = false;
|
|
bool chkVersion = false;
|
|
bool msgAutoClear = false;
|
|
bool indexed = false;
|
|
bool legacySoftMod = false;
|
|
bool addUDATA = false;
|
|
DWORD StatusSetTime = 0;
|
|
DWORD menuNavDelay = 0;
|
|
HANDLE hThread = NULL;
|
|
|
|
MenuEntry* currentMenu = NULL;
|
|
int currentMenuSize = 0;
|
|
int mSelectedControl = 0;
|
|
|
|
MenuEntry* menuStack[MAX_MENU_DEPTH];
|
|
int menuSizeStack[MAX_MENU_DEPTH];
|
|
int menuDepth = 0;
|
|
|
|
void updateStatusMsg(char* msg,bool autoClear);
|
|
void clearStatusMsg();
|
|
void DownloadCallback(char* StatusMsg);
|
|
void refreshicons();
|
|
bool isBusy(HANDLE* hThreadPtr);
|
|
void backupDash(bool restore = false);
|
|
void installFromZipThread();
|
|
int compareVersions(const char* versionA, const char* versionB);
|
|
char* appendNumber(const char* original, int number);
|
|
void enterSubMenu(MenuEntry* subMenu, int size);
|
|
void goBack();
|
|
void installFromZip();
|
|
|
|
char* appendNumber(const char* original, int number) {
|
|
// Buffer to hold the integer as a string
|
|
char numberStr[20];
|
|
std::sprintf(numberStr, "%d", number);
|
|
|
|
// Calculate total length
|
|
size_t originalLen = std::strlen(original);
|
|
size_t numberLen = std::strlen(numberStr);
|
|
size_t totalLen = originalLen + numberLen;
|
|
|
|
// Allocate memory for the new string
|
|
char* result = new char[totalLen + 1]; // +1 for null terminator
|
|
|
|
// Copy original and append number
|
|
std::strcpy(result, original);
|
|
std::strcat(result, numberStr);
|
|
|
|
return result;
|
|
}
|
|
|
|
void DownloadCallback(void* data) {
|
|
if (!data) return;
|
|
char* msg = strdup(reinterpret_cast<char*>(data));
|
|
bool autoClear = strstr(msg,"Downloaded") == NULL;
|
|
updateStatusMsg(msg,autoClear);
|
|
if (strstr(msg,"Download complete.") != NULL) {
|
|
if (unzipfile) {
|
|
if (strstr(zipFile,"MSDash") != NULL) {
|
|
fileSystem::directoryDelete("HDD0-C:\\xboxdashdata.185ead00",true);
|
|
}
|
|
installFromZip();
|
|
} else if (chkVersion) {
|
|
chkVersion = false;
|
|
char* localVersion = IniUtility::GetValue("HDD0-E:\\TDATA\\fffe0000\\version", "default", "version");
|
|
char* latestVersion = IniUtility::GetValue("HDD0-E:\\TDATA\\fffe0000\\latest.ver", "", "version");
|
|
fileSystem::fileDelete("HDD0-E:\\TDATA\\fffe0000\\latest.ver");
|
|
if (!localVersion || !latestVersion) {
|
|
updateStatusMsg(strdup("Failed to read version files."), true);
|
|
if (localVersion) free(localVersion);
|
|
if (latestVersion) free(latestVersion);
|
|
return;
|
|
}
|
|
int result = compareVersions(localVersion,latestVersion);
|
|
free(localVersion);
|
|
free(latestVersion);
|
|
switch (result){
|
|
case 0:
|
|
updateStatusMsg(strdup("You have the latest version."),true);
|
|
break;
|
|
case -1:
|
|
updateStatusMsg(strdup("There is an updated version available."),true);
|
|
break;
|
|
default:
|
|
updateStatusMsg(strdup("You're using an experimental build"),true);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool isBusy(HANDLE* hThreadPtr){
|
|
DWORD exitCode;
|
|
if (hThreadPtr == NULL) return false;
|
|
if (GetExitCodeThread(*hThreadPtr, &exitCode)){
|
|
if (exitCode == STILL_ACTIVE) {
|
|
return true;
|
|
} else {
|
|
CloseHandle(*hThreadPtr);
|
|
*hThreadPtr = NULL;
|
|
return false;
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void action_installUIX();
|
|
void action_installMSDash();
|
|
void action_installDiscord();
|
|
void action_installBlacknWhiteSkin();
|
|
void action_installBlueSkin();
|
|
void action_installBloodRedSkin();
|
|
void action_installCrystalSkin();
|
|
void action_installDenimSkin();
|
|
void action_installPurpleSkin();
|
|
void action_installSkySkin();
|
|
void action_installStockSkin();
|
|
void action_checkForUpdate();
|
|
void action_refreshIcons();
|
|
void action_addMissingUDATA();
|
|
|
|
void action_exit() { utils::ReturnToDashboard(); }
|
|
|
|
MenuEntry submenu_updateUIX[] = {
|
|
{ "Check for Update", action_checkForUpdate, NULL, 0 },
|
|
{ "Install Latest Version", action_installUIX, NULL, 0 },
|
|
{ "Install Discord Presence", action_installDiscord, NULL, 0 },
|
|
{ "Install MSDash 5960", action_installMSDash, NULL, 0 },
|
|
};
|
|
|
|
MenuEntry submenu_manageIcons[] = {
|
|
{ "Refresh Icons.ini", action_refreshIcons, NULL, 0 },
|
|
{ "Add Missing UDATA", action_addMissingUDATA, NULL, 0 },
|
|
//{ "Install Audio", action_installAudio, NULL, 0 },
|
|
};
|
|
|
|
MenuEntry submenu_changeSkinMore[] = {
|
|
{ "Install Denim Skin", action_installDenimSkin, NULL, 0 },
|
|
{ "Install Purple Skin", action_installPurpleSkin, NULL, 0 },
|
|
{ "Install Sky Skin", action_installSkySkin, NULL, 0 },
|
|
{ "Install Stock Skin", action_installStockSkin, NULL, 0 },
|
|
};
|
|
|
|
MenuEntry submenu_changeSkin[] = {
|
|
{ "Install Black & White Skin", action_installBlacknWhiteSkin, NULL, 0 },
|
|
{ "Install Blood Red Skin", action_installBloodRedSkin, NULL, 0 },
|
|
{ "Install Blue Skin", action_installBlueSkin, NULL, 0 },
|
|
{ "Install Crystal Skin", action_installCrystalSkin, NULL, 0 },
|
|
{ "More Skins...", NULL, submenu_changeSkinMore, sizeof(submenu_changeSkinMore) / sizeof(MenuEntry) },
|
|
};
|
|
|
|
MenuEntry submenu_manageUIX[] = {
|
|
{ "Manage Launcher Icons", NULL, submenu_manageIcons, sizeof(submenu_manageIcons) / sizeof(MenuEntry) },
|
|
{ "Change UIX Lite Skin", NULL, submenu_changeSkin, sizeof(submenu_changeSkin) / sizeof(MenuEntry) },
|
|
{ "Update UIX Lite", NULL, submenu_updateUIX, sizeof(submenu_updateUIX) / sizeof(MenuEntry) },
|
|
};
|
|
|
|
MenuEntry mainMenu[] = {
|
|
{ "Manage UIX Lite", NULL, submenu_manageUIX, sizeof(submenu_manageUIX)/sizeof(MenuEntry) },
|
|
{ "Return to Dashboard", action_exit, NULL, 0 }
|
|
};
|
|
|
|
void enterSubMenu(MenuEntry* subMenu, int size) {
|
|
if (menuDepth < MAX_MENU_DEPTH) {
|
|
menuStack[menuDepth] = currentMenu;
|
|
menuSizeStack[menuDepth] = currentMenuSize;
|
|
menuDepth++;
|
|
currentMenu = subMenu;
|
|
currentMenuSize = size;
|
|
mSelectedControl = 0;
|
|
}
|
|
}
|
|
|
|
void action_installUIX() {
|
|
if(isBusy(&hThread)) return;
|
|
updateStatusMsg(strdup("Downloading UIX Lite..."),false);
|
|
hThread = socketUtility::downloadFile("TeamUIX.net", "/uix-lite/latest/uix-lite-latest.zip", "HDD0-E:\\TDATA\\fffe0000\\latest.zip", DownloadCallback);
|
|
zipFile = strdup("HDD0-E:\\TDATA\\fffe0000\\latest.zip");
|
|
unzipfile = true;
|
|
}
|
|
|
|
void action_installMSDash() {
|
|
if(isBusy(&hThread)) return;
|
|
updateStatusMsg(strdup("Downloading UIX Lite..."),false);
|
|
hThread = socketUtility::downloadFile("TeamUIX.net", "/uix-lite/MSDash/185ead00.zip", "HDD0-E:\\TDATA\\fffe0000\\MSDash.zip", DownloadCallback);
|
|
zipFile = strdup("HDD0-E:\\TDATA\\fffe0000\\MSDash.zip");
|
|
unzipfile = true;
|
|
}
|
|
|
|
void action_installDiscord() {
|
|
if(isBusy(&hThread)) return;
|
|
bool exists = false;
|
|
fileSystem::directoryExists("HDD0-C:\\Discord Presence", exists);
|
|
if (!exists) { fileSystem::directoryCreate("HDD0-C:\\Discord Presence"); }
|
|
updateStatusMsg(strdup("Downloading Discord Presence..."),false);
|
|
hThread = socketUtility::downloadFile("TeamUIX.net", "/uix-lite/ShortcutRelayXBE/default.xbe", "HDD0-C:\\Discord Presence\\Discord.xbe", DownloadCallback);
|
|
}
|
|
|
|
void action_installBlacknWhiteSkin(){
|
|
if(isBusy(&hThread)) return;
|
|
updateStatusMsg(strdup("Downloading Black & White Skin..."),false);
|
|
hThread = socketUtility::downloadFile("TeamUIX.net", "/uix-lite/skins/blacknwhite.zip", "HDD0-E:\\TDATA\\fffe0000\\skin.zip", DownloadCallback);
|
|
zipFile = strdup("HDD0-E:\\TDATA\\fffe0000\\skin.zip");
|
|
unzipfile = true;
|
|
}
|
|
|
|
void action_installBlueSkin(){
|
|
if(isBusy(&hThread)) return;
|
|
updateStatusMsg(strdup("Downloading Blue Skin..."),false);
|
|
hThread = socketUtility::downloadFile("TeamUIX.net", "/uix-lite/skins/blue.zip", "HDD0-E:\\TDATA\\fffe0000\\skin.zip", DownloadCallback);
|
|
zipFile = strdup("HDD0-E:\\TDATA\\fffe0000\\skin.zip");
|
|
unzipfile = true;
|
|
}
|
|
|
|
void action_installBloodRedSkin(){
|
|
if(isBusy(&hThread)) return;
|
|
updateStatusMsg(strdup("Downloading Blood Red Skin..."),false);
|
|
hThread = socketUtility::downloadFile("TeamUIX.net", "/uix-lite/skins/bloodred.zip", "HDD0-E:\\TDATA\\fffe0000\\skin.zip", DownloadCallback);
|
|
zipFile = strdup("HDD0-E:\\TDATA\\fffe0000\\skin.zip");
|
|
unzipfile = true;
|
|
}
|
|
|
|
void action_installCrystalSkin(){
|
|
if(isBusy(&hThread)) return;
|
|
updateStatusMsg(strdup("Downloading Crystal Skin..."),false);
|
|
hThread = socketUtility::downloadFile("TeamUIX.net", "/uix-lite/skins/crystal.zip", "HDD0-E:\\TDATA\\fffe0000\\skin.zip", DownloadCallback);
|
|
zipFile = strdup("HDD0-E:\\TDATA\\fffe0000\\skin.zip");
|
|
unzipfile = true;
|
|
}
|
|
|
|
void action_installDenimSkin(){
|
|
if(isBusy(&hThread)) return;
|
|
updateStatusMsg(strdup("Downloading Denim Skin..."),false);
|
|
hThread = socketUtility::downloadFile("TeamUIX.net", "/uix-lite/skins/denim.zip", "HDD0-E:\\TDATA\\fffe0000\\skin.zip", DownloadCallback);
|
|
zipFile = strdup("HDD0-E:\\TDATA\\fffe0000\\skin.zip");
|
|
unzipfile = true;
|
|
}
|
|
|
|
void action_installPurpleSkin(){
|
|
if(isBusy(&hThread)) return;
|
|
updateStatusMsg(strdup("Downloading Purple Skin..."),false);
|
|
hThread = socketUtility::downloadFile("TeamUIX.net", "/uix-lite/skins/purple.zip", "HDD0-E:\\TDATA\\fffe0000\\skin.zip", DownloadCallback);
|
|
zipFile = strdup("HDD0-E:\\TDATA\\fffe0000\\skin.zip");
|
|
unzipfile = true;
|
|
}
|
|
|
|
void action_installSkySkin(){
|
|
if(isBusy(&hThread)) return;
|
|
updateStatusMsg(strdup("Downloading Sky Skin..."),false);
|
|
hThread = socketUtility::downloadFile("TeamUIX.net", "/uix-lite/skins/sky.zip", "HDD0-E:\\TDATA\\fffe0000\\skin.zip", DownloadCallback);
|
|
zipFile = strdup("HDD0-E:\\TDATA\\fffe0000\\skin.zip");
|
|
unzipfile = true;
|
|
}
|
|
|
|
void action_installStockSkin(){
|
|
if(isBusy(&hThread)) return;
|
|
updateStatusMsg(strdup("Downloading Stock Skin..."),false);
|
|
hThread = socketUtility::downloadFile("TeamUIX.net", "/uix-lite/skins/stock.zip", "HDD0-E:\\TDATA\\fffe0000\\skin.zip", DownloadCallback);
|
|
zipFile = strdup("HDD0-E:\\TDATA\\fffe0000\\skin.zip");
|
|
unzipfile = true;
|
|
}
|
|
|
|
void action_checkForUpdate(){
|
|
if(isBusy(&hThread)) return;
|
|
updateStatusMsg(strdup("Downloading UIX Lite..."),false);
|
|
hThread = socketUtility::downloadFile("TeamUIX.net", "/uix-lite/latest/version", "HDD0-E:\\TDATA\\fffe0000\\latest.ver", DownloadCallback);
|
|
chkVersion = true;
|
|
}
|
|
|
|
void action_addMissingUDATA() {
|
|
addUDATA = true;
|
|
action_refreshIcons();
|
|
}
|
|
|
|
void backupDash(bool restore) {
|
|
if (restore) {
|
|
fileSystem::fileDelete("HDD0-C:\\xb0xdash.xbe");
|
|
fileSystem::fileMove("HDD0-C:\\xboxdash.xbe","HDD0-C:\\xb0xdash.xbe");
|
|
fileSystem::fileMove("HDD0-C:\\xboxdash.bak","HDD0-C:\\xboxdash.xbe");
|
|
} else {
|
|
fileSystem::fileMove("HDD0-C:\\xboxdash.xbe","HDD0-C:\\xboxdash.bak");
|
|
}
|
|
}
|
|
|
|
// Quick implementation of CrunchBite's xunzip library
|
|
void installFromZipThread(){
|
|
if (legacySoftMod) backupDash();
|
|
bool success = xExtractZip(strdup(zipFile), "HDD0-C:\\", true, true);
|
|
updateStatusMsg(strdup(success ? "Install complete." : "Install failed."),true);
|
|
if (legacySoftMod) backupDash(true);
|
|
zipFile = NULL;
|
|
unzipfile = false;
|
|
}
|
|
|
|
void installFromZip() {
|
|
updateStatusMsg(strdup("Installing..."),false);
|
|
hThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)installFromZipThread, 0, 0, NULL);
|
|
}
|
|
|
|
int compareVersions(const char* versionA, const char* versionB) {
|
|
const char* ptrA = versionA;
|
|
const char* ptrB = versionB;
|
|
|
|
while (*ptrA != '\0' || *ptrB != '\0') {
|
|
int numA = 0;
|
|
while (*ptrA >= '0' && *ptrA <= '9') {
|
|
numA = numA * 10 + (*ptrA - '0');
|
|
ptrA++;
|
|
}
|
|
int numB = 0;
|
|
while (*ptrB >= '0' && *ptrB <= '9') {
|
|
numB = numB * 10 + (*ptrB - '0');
|
|
ptrB++;
|
|
}
|
|
if (numA < numB) return -1;
|
|
if (numA > numB) return 1;
|
|
if (*ptrA == '.') ptrA++;
|
|
if (*ptrB == '.') ptrB++;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void scanForDefaultXBE(const char* basePath) {
|
|
WIN32_FIND_DATAA findFileData;
|
|
char searchPath[256];
|
|
sprintf(searchPath, "%s\\*",basePath);
|
|
|
|
HANDLE hFind = FindFirstFileA(searchPath, &findFileData);
|
|
if (hFind == INVALID_HANDLE_VALUE) return;
|
|
|
|
do {
|
|
if (strcmp(findFileData.cFileName, ".") == 0 || strcmp(findFileData.cFileName, "..") == 0)
|
|
continue;
|
|
|
|
char fullPath[256];
|
|
sprintf(fullPath, "%s\\%s", basePath, findFileData.cFileName);
|
|
|
|
if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
|
// Check if default.xbe exists in this subdirectory
|
|
bool Exists;
|
|
char xbePath[MAX_PATH];
|
|
|
|
sprintf(xbePath, "%s\\default.xbe", fullPath);
|
|
fileSystem::fileExists(xbePath,Exists);
|
|
|
|
if (Exists) {
|
|
updateStatusMsg(strdup(xbePath),false);
|
|
XBEParser parser;
|
|
parser.LoadXBE(xbePath);
|
|
uint32_t titleId = 0;
|
|
char* titleName = NULL;
|
|
if (parser.GetTitleName(titleName) && parser.GetTitleID(titleId)) {
|
|
char TitleId[9];
|
|
sprintf(TitleId, "%08x", titleId);
|
|
|
|
// Update Iconss.ini
|
|
if (!IniUtility::SetValue("HDD0-C:\\UIX Configs\\Icons.ini","default",findFileData.cFileName,TitleId)) {
|
|
updateStatusMsg(strdup("Failed to write Icons.ini"),true);
|
|
return;
|
|
}
|
|
|
|
// Update TitleNames.ini
|
|
char* existingTitle = IniUtility::GetValue("HDD0-C:\\UIX Configs\\TitleNames.ini", "default", findFileData.cFileName);
|
|
if (strlen(existingTitle) == 0) {
|
|
IniUtility::SetValue("HDD0-C:\\UIX Configs\\TitleNames.ini","default",findFileData.cFileName,titleName);
|
|
}
|
|
free(existingTitle);
|
|
if (addUDATA && parser.HasTitleImage()) {
|
|
bool Exists = false;
|
|
char* udataPath = fileSystem::combinePath(UDATA, TitleId);
|
|
if (!udataPath) return;
|
|
fileSystem::directoryExists(udataPath, Exists);
|
|
if (!Exists) {
|
|
fileSystem::directoryCreate(udataPath);
|
|
char* titleImagePath = fileSystem::combinePath(udataPath, "TitleImage.xbx");
|
|
parser.SaveTitleImage(titleImagePath);
|
|
free(titleImagePath);
|
|
char* metaPath = fileSystem::combinePath(udataPath, "TitleMeta.xbx");
|
|
IniUtility::SetValue(metaPath, "", "TitleName", titleName);
|
|
free(metaPath);
|
|
} else {
|
|
char* titleImagePath = fileSystem::combinePath(udataPath, "TitleImage.xbx");
|
|
fileSystem::fileExists(titleImagePath, Exists);
|
|
if (!Exists) parser.SaveTitleImage(titleImagePath);
|
|
free(titleImagePath);
|
|
char* metaPath = fileSystem::combinePath(udataPath, "TitleMeta.xbx");
|
|
fileSystem::fileExists(metaPath, Exists);
|
|
if (!Exists) IniUtility::SetValue(metaPath, "", "TitleName", titleName);
|
|
free(metaPath);
|
|
}
|
|
free(udataPath);
|
|
}
|
|
} else {
|
|
updateStatusMsg(strdup("Failed to get TitleID and TitleName."),true);
|
|
}
|
|
free(titleName);
|
|
}
|
|
}
|
|
} while (FindNextFileA(hFind, &findFileData));
|
|
|
|
FindClose(hFind);
|
|
}
|
|
void refreshIcons(){
|
|
IniUtility::DeleteSection("HDD0-C:\\UIX Configs\\Icons.ini","default");
|
|
pointerVector<char*>* Locations = new pointerVector<char*>(true);
|
|
int MaxLauncherItems = stringUtility::toInt(IniUtility::GetValue("HDD0-C:\\UIX Configs\\config.ini","LauncherMenu","MaxLauncherMenuItems"));
|
|
if (MaxLauncherItems == 0) MaxLauncherItems = 8;
|
|
for (int i = 0; i < MaxLauncherItems; i++)
|
|
{
|
|
char* value = IniUtility::GetValue("HDD0-C:\\UIX Configs\\config.ini","LauncherMenu",appendNumber("Path",i));
|
|
if (*value != '\0') {
|
|
pointerVector<char*>* Paths = stringUtility::split(value,";",true);
|
|
for (size_t p = 0; p < Paths->count(); p++){
|
|
Locations->add(strdup(Paths->get(p)));
|
|
}
|
|
delete Paths;
|
|
}
|
|
free(value);
|
|
}
|
|
|
|
pointerVector<char*>* drives = driveManager::getMountedDrives();
|
|
updateStatusMsg(strdup((addUDATA) ? "Adding Missing UDATA..." : "Refreshing the Icons.ini..."),false);
|
|
for (size_t d = 0; d < drives->count(); d++)
|
|
{
|
|
//Skip the C:,X:,Y:,and Z: partitions
|
|
if (strstr(drives->get(d), "C") ||
|
|
strstr(drives->get(d), "X") ||
|
|
strstr(drives->get(d), "Y") ||
|
|
strstr(drives->get(d), "Z")
|
|
) continue;
|
|
for (size_t L = 0; L < Locations->count(); L++)
|
|
{
|
|
char searchPath[256];
|
|
sprintf(searchPath, "%s:\\%s", drives->get(d),Locations->get(L));
|
|
scanForDefaultXBE(searchPath);
|
|
}
|
|
}
|
|
delete Locations;
|
|
delete drives;
|
|
indexed = true;
|
|
updateStatusMsg(strdup((addUDATA) ? "Missing UDATA Added!" : "Icons.ini refreshed!"), true);
|
|
addUDATA = false;
|
|
}
|
|
|
|
void action_refreshIcons() {
|
|
if (isBusy(&hThread)) return;
|
|
updateStatusMsg(strdup(indexed ? (addUDATA) ? "Adding Missing UDATA..." : "Refreshing the Icons.ini..." : "Indexing the extended partitions..."),false);
|
|
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)refreshIcons, 0, 0, NULL);
|
|
}
|
|
|
|
typedef struct {
|
|
DWORD dwWidth;
|
|
DWORD dwHeight;
|
|
BOOL fProgressive;
|
|
BOOL fWideScreen;
|
|
DWORD dwFreq;
|
|
} DISPLAY_MODE;
|
|
|
|
DISPLAY_MODE displayModes[] =
|
|
{
|
|
//{ 720, 480, TRUE, TRUE, 60 }, // 720x480 progressive 16x9
|
|
//{ 720, 480, TRUE, FALSE, 60 }, // 720x480 progressive 4x3
|
|
//{ 720, 480, FALSE, TRUE, 50 }, // 720x480 interlaced 16x9 50Hz
|
|
//{ 720, 480, FALSE, FALSE, 50 }, // 720x480 interlaced 4x3 50Hz
|
|
//{ 720, 480, FALSE, TRUE, 60 }, // 720x480 interlaced 16x9
|
|
//{ 720, 480, FALSE, FALSE, 60 }, // 720x480 interlaced 4x3
|
|
|
|
|
|
// Width Height Progressive Widescreen
|
|
|
|
// HDTV Progressive Modes
|
|
{ 1280, 720, TRUE, TRUE, 60 }, // 1280x720 progressive 16x9
|
|
|
|
// EDTV Progressive Modes
|
|
{ 720, 480, TRUE, TRUE, 60 }, // 720x480 progressive 16x9
|
|
{ 640, 480, TRUE, TRUE, 60 }, // 640x480 progressive 16x9
|
|
{ 720, 480, TRUE, FALSE, 60 }, // 720x480 progressive 4x3
|
|
{ 640, 480, TRUE, FALSE, 60 }, // 640x480 progressive 4x3
|
|
|
|
// HDTV Interlaced Modes
|
|
// { 1920, 1080, FALSE, TRUE, 60 }, // 1920x1080 interlaced 16x9
|
|
|
|
// SDTV PAL-50 Interlaced Modes
|
|
{ 720, 480, FALSE, TRUE, 50 }, // 720x480 interlaced 16x9 50Hz
|
|
{ 640, 480, FALSE, TRUE, 50 }, // 640x480 interlaced 16x9 50Hz
|
|
{ 720, 480, FALSE, FALSE, 50 }, // 720x480 interlaced 4x3 50Hz
|
|
{ 640, 480, FALSE, FALSE, 50 }, // 640x480 interlaced 4x3 50Hz
|
|
|
|
// SDTV NTSC / PAL-60 Interlaced Modes
|
|
{ 720, 480, FALSE, TRUE, 60 }, // 720x480 interlaced 16x9
|
|
{ 640, 480, FALSE, TRUE, 60 }, // 640x480 interlaced 16x9
|
|
{ 720, 480, FALSE, FALSE, 60 }, // 720x480 interlaced 4x3
|
|
{ 640, 480, FALSE, FALSE, 60 }, // 640x480 interlaced 4x3
|
|
};
|
|
|
|
#define NUM_MODES (sizeof(displayModes) / sizeof(displayModes[0]))
|
|
|
|
bool supportsMode(DISPLAY_MODE mode, DWORD dwVideoStandard, DWORD dwVideoFlags)
|
|
{
|
|
if (mode.dwFreq == 60 && !(dwVideoFlags & XC_VIDEO_FLAGS_PAL_60Hz) && (dwVideoStandard == XC_VIDEO_STANDARD_PAL_I))
|
|
{
|
|
return false;
|
|
}
|
|
if (mode.dwFreq == 50 && (dwVideoStandard != XC_VIDEO_STANDARD_PAL_I))
|
|
{
|
|
return false;
|
|
}
|
|
if (mode.dwHeight == 480 && mode.fWideScreen && !(dwVideoFlags & XC_VIDEO_FLAGS_WIDESCREEN ))
|
|
{
|
|
return false;
|
|
}
|
|
if (mode.dwHeight == 480 && mode.fProgressive && !(dwVideoFlags & XC_VIDEO_FLAGS_HDTV_480p))
|
|
{
|
|
return false;
|
|
}
|
|
if (mode.dwHeight == 720 && !(dwVideoFlags & XC_VIDEO_FLAGS_HDTV_720p))
|
|
{
|
|
return false;
|
|
}
|
|
if (mode.dwHeight == 1080 && !(dwVideoFlags & XC_VIDEO_FLAGS_HDTV_1080i))
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool createDevice()
|
|
{
|
|
uint32_t videoFlags = XGetVideoFlags();
|
|
uint32_t videoStandard = XGetVideoStandard();
|
|
uint32_t currentMode;
|
|
for (currentMode = 0; currentMode < NUM_MODES-1; currentMode++)
|
|
{
|
|
if (supportsMode(displayModes[currentMode], videoStandard, videoFlags))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
LPDIRECT3D8 d3d = Direct3DCreate8(D3D_SDK_VERSION);
|
|
if(d3d == NULL)
|
|
{
|
|
utils::debugPrint("Failed to create d3d\n");
|
|
return false;
|
|
}
|
|
|
|
context::setBufferWidth(720);
|
|
context::setBufferHeight(480);
|
|
//context::setBufferWidth(displayModes[currentMode].dwWidth);
|
|
//context::setBufferHeight(displayModes[currentMode].dwHeight);
|
|
|
|
D3DPRESENT_PARAMETERS params;
|
|
ZeroMemory(¶ms, sizeof(params));
|
|
params.BackBufferWidth = displayModes[currentMode].dwWidth;
|
|
params.BackBufferHeight = displayModes[currentMode].dwHeight;
|
|
params.Flags = displayModes[currentMode].fProgressive ? D3DPRESENTFLAG_PROGRESSIVE : D3DPRESENTFLAG_INTERLACED;
|
|
params.Flags |= displayModes[currentMode].fWideScreen ? D3DPRESENTFLAG_WIDESCREEN : 0;
|
|
params.FullScreen_RefreshRateInHz = displayModes[currentMode].dwFreq;
|
|
params.BackBufferFormat = D3DFMT_X8R8G8B8;
|
|
params.BackBufferCount = 1;
|
|
params.EnableAutoDepthStencil = FALSE;
|
|
params.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
|
params.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
|
|
|
|
LPDIRECT3DDEVICE8 d3dDevice;
|
|
if (FAILED(d3d->CreateDevice(0, D3DDEVTYPE_HAL, NULL, D3DCREATE_HARDWARE_VERTEXPROCESSING, ¶ms, &d3dDevice)))
|
|
{
|
|
utils::debugPrint("Failed to create device\n");
|
|
return false;
|
|
}
|
|
context::setD3dDevice(d3dDevice);
|
|
|
|
context::getD3dDevice()->SetRenderState(D3DRS_ZFUNC, D3DCMP_NEVER);
|
|
context::getD3dDevice()->SetRenderState(D3DRS_LIGHTING, FALSE);
|
|
context::getD3dDevice()->SetVertexShader(D3DFVF_CUSTOMVERTEX);
|
|
context::getD3dDevice()->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
|
context::getD3dDevice()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
|
context::getD3dDevice()->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
|
|
|
context::getD3dDevice()->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
|
context::getD3dDevice()->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
|
|
context::getD3dDevice()->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
|
|
context::getD3dDevice()->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TFACTOR);
|
|
context::getD3dDevice()->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
|
context::getD3dDevice()->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
|
|
|
|
context::getD3dDevice()->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
|
|
context::getD3dDevice()->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
|
|
context::getD3dDevice()->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
|
|
|
|
context::getD3dDevice()->BeginScene();
|
|
context::getD3dDevice()->Clear(0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, 0xff000000, 1.0f, 0L);
|
|
context::getD3dDevice()->EndScene();
|
|
context::getD3dDevice()->Present(NULL, NULL, NULL, NULL);
|
|
|
|
return true;
|
|
}
|
|
|
|
void render_sphere(float angle, utils::dataContainer* sphereMesh)
|
|
{
|
|
const float deg_to_rad = 0.01745329252f;
|
|
|
|
D3DXMATRIX matWorld;
|
|
D3DXMatrixRotationY(&matWorld, -angle * deg_to_rad);
|
|
|
|
D3DXVECTOR3 cameraPosition(0.0f, 0.1f, 8.0f);
|
|
D3DXVECTOR3 target(0.0f, 0.0f, 7.0f);
|
|
D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
|
|
|
|
D3DXMATRIX matView;
|
|
D3DXMatrixLookAtLH(&matView, &cameraPosition, &target, &up);
|
|
|
|
D3DXMATRIX matProjection;
|
|
D3DXMatrixIdentity(&matProjection);
|
|
D3DXMatrixPerspectiveFovLH(&matProjection, 45 * deg_to_rad, (float)context::getBufferWidth() / (float)context::getBufferHeight(), 0.1f, 100.0f);
|
|
|
|
context::getD3dDevice()->SetTransform( D3DTS_WORLD, &matWorld);
|
|
context::getD3dDevice()->SetTransform(D3DTS_VIEW, &matView);
|
|
context::getD3dDevice()->SetTransform(D3DTS_PROJECTION, &matProjection);
|
|
|
|
context::getD3dDevice()->SetRenderState(D3DRS_TEXTUREFACTOR, 0xff004000);
|
|
context::getD3dDevice()->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
|
context::getD3dDevice()->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
|
|
|
|
image* imageToDraw = drawing::getImage("base");
|
|
context::getD3dDevice()->SetTexture(0, imageToDraw->texture);
|
|
context::getD3dDevice()->DrawPrimitiveUP(D3DPT_TRIANGLELIST, (sphereMesh->size / sizeof(meshUtility::vertex)) / 3, sphereMesh->data, sizeof(meshUtility::vertex));
|
|
}
|
|
|
|
void update_scene() {
|
|
if (inputManager::buttonPressed(ButtonA)) {
|
|
if (GetTickCount() - menuNavDelay < 100) return; else menuNavDelay=GetTickCount();
|
|
MenuEntry* entry = ¤tMenu[mSelectedControl];
|
|
if (entry->subMenu != NULL) {
|
|
enterSubMenu(entry->subMenu, entry->subMenuSize);
|
|
} else if (entry->action != NULL) {
|
|
entry->action();
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (inputManager::buttonPressed(ButtonB)) {
|
|
if (GetTickCount() - menuNavDelay < 100) return; else menuNavDelay=GetTickCount();
|
|
if (menuDepth > 0) {
|
|
menuDepth--;
|
|
currentMenu = menuStack[menuDepth];
|
|
currentMenuSize = menuSizeStack[menuDepth];
|
|
mSelectedControl = 0;
|
|
}
|
|
}
|
|
|
|
if (inputManager::buttonPressed(ButtonDpadDown)) {
|
|
if (GetTickCount() - menuNavDelay < 100) return; else menuNavDelay=GetTickCount();
|
|
mSelectedControl = (mSelectedControl + 1) % currentMenuSize;
|
|
}
|
|
|
|
if (inputManager::buttonPressed(ButtonDpadUp)) {
|
|
if (GetTickCount() - menuNavDelay < 100) return; else menuNavDelay=GetTickCount();
|
|
mSelectedControl = (mSelectedControl - 1 + currentMenuSize) % currentMenuSize;
|
|
}
|
|
|
|
isBusy(&hThread);
|
|
clearStatusMsg();
|
|
network::init();
|
|
}
|
|
|
|
void render_scene()
|
|
{
|
|
// Setup Ortho Camera
|
|
D3DXMATRIX matIdentity;
|
|
D3DXMatrixIdentity(&matIdentity);
|
|
|
|
D3DXMATRIX matProjection;
|
|
D3DXMatrixOrthoOffCenterLH(&matProjection, 0, (float)context::getBufferWidth(), 0, (float)context::getBufferHeight(), 1.0f, 800.0f);
|
|
|
|
context::getD3dDevice()->SetTransform(D3DTS_VIEW, &matIdentity);
|
|
context::getD3dDevice()->SetTransform(D3DTS_WORLD, &matIdentity);
|
|
context::getD3dDevice()->SetTransform(D3DTS_PROJECTION, &matProjection);
|
|
context::getD3dDevice()->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
|
|
context::getD3dDevice()->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
|
|
|
|
// Render Menu Panel
|
|
component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
|
|
|
|
int menuItemCount = currentMenuSize;
|
|
int32_t yPos = (context::getBufferHeight() - (menuItemCount * 40) - 10) / 2;
|
|
yPos += theme::getCenterOffset();
|
|
|
|
drawing::drawBitmapStringAligned(
|
|
context::getBitmapFontSmall(),
|
|
"Welcome to UIX Toolbox. FTPd Powered by PrometheOS.",
|
|
theme::getFooterTextColor(),
|
|
horizAlignmentCenter,
|
|
193,
|
|
yPos,
|
|
322
|
|
);
|
|
|
|
yPos += 40;
|
|
|
|
for (int i = 0; i < menuItemCount; ++i) {
|
|
component::button(mSelectedControl == i, false, currentMenu[i].label, 193, yPos, 322, 30);
|
|
yPos += 40;
|
|
}
|
|
|
|
// Footer Info (IP + Status)
|
|
char* currentIp = context::getCurrentIp();
|
|
char* ip = stringUtility::formatString("IP: %s - Username: xbox - Password: xbox", currentIp);
|
|
|
|
if (StatusMsg) {
|
|
drawing::drawBitmapStringAligned(
|
|
context::getBitmapFontSmall(),
|
|
StatusMsg,
|
|
theme::getFooterTextColor(),
|
|
horizAlignmentCenter,
|
|
193,
|
|
theme::getFooterY() - 30,
|
|
322
|
|
);
|
|
}
|
|
|
|
drawing::drawBitmapStringAligned(
|
|
context::getBitmapFontSmall(),
|
|
ip,
|
|
theme::getFooterTextColor(),
|
|
horizAlignmentCenter,
|
|
193,
|
|
theme::getFooterY(),
|
|
322
|
|
);
|
|
|
|
free(ip);
|
|
free(currentIp);
|
|
}
|
|
|
|
void refreshInfo()
|
|
{
|
|
if (network::isReady() == true)
|
|
{
|
|
XNADDR addr;
|
|
memset(&addr, 0, sizeof(addr));
|
|
DWORD dwState = XNetGetTitleXnAddr(&addr);
|
|
if (dwState != XNET_GET_XNADDR_PENDING)
|
|
{
|
|
char* ipAddress = (XNetGetEthernetLinkStatus() & XNET_ETHERNET_LINK_ACTIVE) ? stringUtility::formatString("%i.%i.%i.%i",
|
|
addr.ina.S_un.S_un_b.s_b1,
|
|
addr.ina.S_un.S_un_b.s_b2,
|
|
addr.ina.S_un.S_un_b.s_b3,
|
|
addr.ina.S_un.S_un_b.s_b4) : strdup("0.0.0.0");
|
|
char* currentIp = context::getCurrentIp();
|
|
if (stringUtility::equals(ipAddress, currentIp, false) == false)
|
|
{
|
|
context::setCurrentIp(ipAddress);
|
|
}
|
|
free(ipAddress);
|
|
free(currentIp);
|
|
}
|
|
}
|
|
}
|
|
void updateStatusMsg(char * msg, bool autoClear) {
|
|
if (StatusMsg) free(StatusMsg);
|
|
msgAutoClear = autoClear;
|
|
StatusSetTime = GetTickCount();
|
|
StatusMsg = msg;
|
|
}
|
|
|
|
void clearStatusMsg() {
|
|
if (StatusMsg) {
|
|
if (GetTickCount() - StatusSetTime > 4000 && msgAutoClear) {
|
|
free(StatusMsg);
|
|
StatusMsg = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
void __cdecl main()
|
|
{
|
|
utils::debugPrint("Welcome to PrometheOS Launcher\n");
|
|
|
|
bool deviceCreated = createDevice();
|
|
|
|
context::setNetworkInitialized(false);
|
|
|
|
driveManager::mountDrive("HDD0-C");
|
|
driveManager::mountDrive("HDD0-E");
|
|
|
|
context::setImageMap(new pointerMap<image*>(true));
|
|
theme::loadSkin();
|
|
|
|
if (deviceCreated == false)
|
|
{
|
|
network::init();
|
|
}
|
|
|
|
fileSystem::fileExists("HDD0-C:\\xb0xdash.xbe",legacySoftMod);
|
|
drawing::loadFont(&font_sfn[0]);
|
|
|
|
bitmapFont* fontSmall = drawing::generateBitmapFont("FreeSans", SSFN_STYLE_REGULAR, 18, 18, 0, 256);
|
|
context::setBitmapFontSmall(fontSmall);
|
|
bitmapFont* fontMedium = drawing::generateBitmapFont("FreeSans", SSFN_STYLE_REGULAR, 25, 25, 0, 256);
|
|
context::setBitmapFontMedium(fontMedium);
|
|
bitmapFont* fontLarge = drawing::generateBitmapFont("FreeSans", SSFN_STYLE_REGULAR, 32, 32, 0, 512);
|
|
context::setBitmapFontLarge(fontLarge);
|
|
|
|
drawing::renderRoundedRect("panel-fill", 24, 24, 6, 0xffffffff, 0x00000000, 0);
|
|
drawing::renderRoundedRect("panel-stroke", 24, 24, 6, 0x01010100, 0xffffffff, 2);
|
|
|
|
utils::dataContainer* sphereMesh = meshUtility::createSphere();
|
|
drawing::loadImage((char*)base_jpg, sizeof(base_jpg), "base");
|
|
|
|
audioPlayer::init();
|
|
audioPlayer::play();
|
|
|
|
currentMenu = mainMenu;
|
|
currentMenuSize = sizeof(mainMenu) / sizeof(MenuEntry);
|
|
|
|
float angle = 0;
|
|
while (TRUE)
|
|
{
|
|
inputManager::processController();
|
|
refreshInfo();
|
|
|
|
drawing::clearBackground((uint32_t)0);
|
|
|
|
// Render Sphere Background
|
|
|
|
render_sphere(angle, sphereMesh);
|
|
|
|
// Process Input / Render Menu
|
|
|
|
update_scene();
|
|
render_scene();
|
|
|
|
// Present Rendered Results
|
|
|
|
context::getD3dDevice()->EndScene();
|
|
context::getD3dDevice()->Present(NULL, NULL, NULL, NULL);
|
|
|
|
angle += 0.05f;
|
|
if (angle > 360.0f)
|
|
{
|
|
angle -= 360.f;
|
|
}
|
|
}
|
|
} |