mirror of
https://codeberg.org/Nixietab/EOSSDK-Holos.git
synced 2026-08-21 20:23:28 -04:00
Created launcher to manage the config
This commit is contained in:
parent
2cf9a9756a
commit
98af2b4034
7 changed files with 630 additions and 0 deletions
3
Launcher/.gitignore
vendored
Normal file
3
Launcher/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
*.exe
|
||||
*.o
|
||||
icon.ico
|
||||
9
Launcher/build.sh
Executable file
9
Launcher/build.sh
Executable file
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
python3 gen_icon.py
|
||||
x86_64-w64-mingw32-windres resource.rc -O coff -o resource.o
|
||||
x86_64-w64-mingw32-g++ -mwindows -O2 -s -o EOSHoloLauncher.exe main.cpp resource.o -static
|
||||
echo "Built: EOSHoloLauncher.exe"
|
||||
31
Launcher/gen_icon.py
Normal file
31
Launcher/gen_icon.py
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import struct, os
|
||||
from io import BytesIO
|
||||
from PIL import Image
|
||||
|
||||
SRC = os.path.join(os.path.dirname(__file__), "holos.png")
|
||||
DST = os.path.join(os.path.dirname(__file__), "icon.ico")
|
||||
SIZES = [16, 24, 32, 48, 64, 128, 256]
|
||||
|
||||
src = Image.open(SRC).convert("RGBA")
|
||||
entries = []
|
||||
|
||||
for size in SIZES:
|
||||
img = src.resize((size, size), Image.LANCZOS)
|
||||
buf = BytesIO()
|
||||
img.save(buf, format='PNG')
|
||||
data = buf.getvalue()
|
||||
w = size if size < 256 else 0
|
||||
h = size if size < 256 else 0
|
||||
entries.append((w, h, 32, len(data), data))
|
||||
|
||||
with open(DST, 'wb') as f:
|
||||
f.write(struct.pack('<HHH', 0, 1, len(SIZES)))
|
||||
dir_offset = 6 + len(SIZES) * 16
|
||||
for entry in entries:
|
||||
f.write(struct.pack('<BBBBHHII',
|
||||
entry[0], entry[1], 0, 0, 1, entry[2], entry[3], dir_offset))
|
||||
dir_offset += entry[3]
|
||||
for entry in entries:
|
||||
f.write(entry[4])
|
||||
|
||||
print(f"Created {DST} ({os.path.getsize(DST)} bytes, {len(SIZES)} sizes)")
|
||||
BIN
Launcher/holos.png
Normal file
BIN
Launcher/holos.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 71 KiB |
486
Launcher/main.cpp
Normal file
486
Launcher/main.cpp
Normal file
|
|
@ -0,0 +1,486 @@
|
|||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
#include <stdio.h>
|
||||
#include "resource.h"
|
||||
|
||||
static const char *INI_RELATIVE = "\\HolosHanafuda_Data\\Plugins\\x86_64\\directip.ini";
|
||||
static const char *TENOKE_RELATIVE = "\\HolosHanafuda_Data\\Plugins\\x86_64\\tenoke.ini";
|
||||
static const char *GAME_EXE = "\\HolosHanafuda.exe";
|
||||
static const char *SECTION = "Network";
|
||||
|
||||
static const char *KEYS[] = {
|
||||
"Role", "IP", "Port", "MaxMembers", "Platform",
|
||||
"WinRate", "IsCrossPlatform", "AppVersion", "OnlineRule"
|
||||
};
|
||||
static const char *DEFAULTS[] = {
|
||||
"Client", "127.0.0.1", "7777", "4", "Steam",
|
||||
"10", "true", "1.2.0", "Koikoi"
|
||||
};
|
||||
static const char *COMMENTS[] = {
|
||||
"Client or Host", "Target IP address", "UDP port",
|
||||
"Maximum lobby members", "Lobby platform identifier",
|
||||
"Win rate (for matchmaking)", "Cross-platform flag (true/false)",
|
||||
"App version (for matchmaking)", "Online rule (for matchmaking)"
|
||||
};
|
||||
|
||||
static char g_gameDir[MAX_PATH];
|
||||
|
||||
static void GetIniPath(char *buf, size_t size) {
|
||||
_snprintf(buf, size, "%s%s", g_gameDir, INI_RELATIVE);
|
||||
}
|
||||
static void GetTenokePath(char *buf, size_t size) {
|
||||
_snprintf(buf, size, "%s%s", g_gameDir, TENOKE_RELATIVE);
|
||||
}
|
||||
static void GetExePath(char *buf, size_t size) {
|
||||
_snprintf(buf, size, "%s%s", g_gameDir, GAME_EXE);
|
||||
}
|
||||
|
||||
static char *ReadFileContent(const char *path, DWORD *outSize) {
|
||||
*outSize = 0;
|
||||
HANDLE hFile = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE) return NULL;
|
||||
DWORD size = GetFileSize(hFile, NULL);
|
||||
if (size == 0 || size > 65536) { CloseHandle(hFile); return NULL; }
|
||||
char *content = (char *)malloc(size + 2);
|
||||
DWORD read;
|
||||
if (!ReadFile(hFile, content, size, &read, NULL) || read != size) {
|
||||
free(content); CloseHandle(hFile); return NULL;
|
||||
}
|
||||
content[size] = '\0';
|
||||
content[size + 1] = '\0';
|
||||
CloseHandle(hFile);
|
||||
*outSize = size;
|
||||
return content;
|
||||
}
|
||||
|
||||
static int WriteFileContent(const char *path, const char *data, DWORD len) {
|
||||
HANDLE hFile = CreateFileA(path, GENERIC_WRITE, FILE_SHARE_READ, NULL,
|
||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE) return 0;
|
||||
DWORD written;
|
||||
int ok = WriteFile(hFile, data, len, &written, NULL) && written == len;
|
||||
CloseHandle(hFile);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static const char *ReadTenokeUser(const char *path) {
|
||||
static char value[128];
|
||||
value[0] = '\0';
|
||||
|
||||
DWORD size;
|
||||
char *content = ReadFileContent(path, &size);
|
||||
if (!content) return value;
|
||||
|
||||
// Check for UTF-16LE BOM
|
||||
char *p = content;
|
||||
if (size >= 2 && (BYTE)p[0] == 0xFF && (BYTE)p[1] == 0xFE) {
|
||||
// Convert UTF-16LE to ASCII: skip BOM, take low bytes
|
||||
char *ascii = (char *)malloc(size / 2 + 1);
|
||||
int j = 0;
|
||||
for (DWORD i = 2; i + 1 < size; i += 2) {
|
||||
if (p[i] == '\r') continue;
|
||||
ascii[j++] = p[i];
|
||||
}
|
||||
ascii[j] = '\0';
|
||||
free(content);
|
||||
content = ascii;
|
||||
size = j;
|
||||
}
|
||||
|
||||
// Find "user =" and extract quoted value
|
||||
char *userPos = strstr(content, "user");
|
||||
while (userPos) {
|
||||
char *after = userPos + 4;
|
||||
while (*after == ' ' || *after == '\t') after++;
|
||||
if (*after == '=') {
|
||||
after++;
|
||||
while (*after == ' ' || *after == '\t') after++;
|
||||
if (*after == '"') {
|
||||
after++;
|
||||
int i = 0;
|
||||
while (*after && *after != '"' && i < (int)sizeof(value) - 1)
|
||||
value[i++] = *after++;
|
||||
value[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
userPos = strstr(after, "user");
|
||||
}
|
||||
|
||||
free(content);
|
||||
return value;
|
||||
}
|
||||
|
||||
static void WriteTenokeUser(const char *path, const char *newUser) {
|
||||
DWORD size;
|
||||
char *content = ReadFileContent(path, &size);
|
||||
if (!content) return;
|
||||
|
||||
int isUtf16 = (size >= 2 && (BYTE)content[0] == 0xFF && (BYTE)content[1] == 0xFE);
|
||||
char *work = content;
|
||||
DWORD workSize = size;
|
||||
|
||||
if (isUtf16) {
|
||||
char *ascii = (char *)malloc(size / 2 + 1);
|
||||
int j = 0;
|
||||
for (DWORD i = 2; i + 1 < size; i += 2)
|
||||
ascii[j++] = content[i];
|
||||
ascii[j] = '\0';
|
||||
work = ascii;
|
||||
workSize = j;
|
||||
}
|
||||
|
||||
char *valueStart = NULL;
|
||||
char *valueEnd = NULL;
|
||||
char *userPos = strstr(work, "user");
|
||||
|
||||
while (userPos) {
|
||||
char *after = userPos + 4;
|
||||
while (*after == ' ' || *after == '\t') after++;
|
||||
if (*after == '=') {
|
||||
after++;
|
||||
while (*after == ' ' || *after == '\t') after++;
|
||||
if (*after == '"') {
|
||||
valueStart = after + 1;
|
||||
valueEnd = valueStart;
|
||||
while (*valueEnd && *valueEnd != '"') valueEnd++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
userPos = strstr(after, "user");
|
||||
}
|
||||
|
||||
char asciiBuf[32768];
|
||||
int pos = 0;
|
||||
|
||||
if (valueStart) {
|
||||
int beforeQuote = (int)(valueStart - work);
|
||||
memcpy(asciiBuf, work, beforeQuote);
|
||||
pos = beforeQuote;
|
||||
int newLen = (int)strlen(newUser);
|
||||
memcpy(asciiBuf + pos, newUser, newLen);
|
||||
pos += newLen;
|
||||
int afterQuote = (int)(work + workSize - valueEnd);
|
||||
memcpy(asciiBuf + pos, valueEnd, afterQuote);
|
||||
pos += afterQuote;
|
||||
} else {
|
||||
pos = _snprintf(asciiBuf, sizeof(asciiBuf),
|
||||
"%s\r\nuser = \"%s\"\r\n", work, newUser);
|
||||
}
|
||||
|
||||
if (isUtf16) {
|
||||
char utf16Buf[65536];
|
||||
int upos = 0;
|
||||
utf16Buf[upos++] = (char)0xFF;
|
||||
utf16Buf[upos++] = (char)0xFE;
|
||||
for (int i = 0; i < pos; i++) {
|
||||
utf16Buf[upos++] = asciiBuf[i];
|
||||
utf16Buf[upos++] = '\0';
|
||||
}
|
||||
WriteFileContent(path, utf16Buf, upos);
|
||||
free(work);
|
||||
} else {
|
||||
WriteFileContent(path, asciiBuf, pos);
|
||||
}
|
||||
|
||||
free(content);
|
||||
}
|
||||
|
||||
static void LoadConfig(HWND dlg) {
|
||||
char ini[MAX_PATH];
|
||||
GetIniPath(ini, sizeof(ini));
|
||||
char buf[256];
|
||||
|
||||
GetPrivateProfileStringA(SECTION, KEYS[0], DEFAULTS[0], buf, sizeof(buf), ini);
|
||||
if (SendDlgItemMessageA(dlg, IDC_ROLE, CB_SELECTSTRING, -1, (LPARAM)buf) == CB_ERR)
|
||||
SendDlgItemMessageA(dlg, IDC_ROLE, CB_SETCURSEL, 0, 0);
|
||||
|
||||
GetPrivateProfileStringA(SECTION, KEYS[1], DEFAULTS[1], buf, sizeof(buf), ini);
|
||||
SetDlgItemTextA(dlg, IDC_IP, buf);
|
||||
|
||||
GetPrivateProfileStringA(SECTION, KEYS[2], DEFAULTS[2], buf, sizeof(buf), ini);
|
||||
SetDlgItemTextA(dlg, IDC_PORT, buf);
|
||||
|
||||
GetPrivateProfileStringA(SECTION, KEYS[3], DEFAULTS[3], buf, sizeof(buf), ini);
|
||||
SetDlgItemTextA(dlg, IDC_MAX_MEMBERS, buf);
|
||||
|
||||
GetPrivateProfileStringA(SECTION, KEYS[4], DEFAULTS[4], buf, sizeof(buf), ini);
|
||||
SetDlgItemTextA(dlg, IDC_PLATFORM, buf);
|
||||
|
||||
GetPrivateProfileStringA(SECTION, KEYS[5], DEFAULTS[5], buf, sizeof(buf), ini);
|
||||
SetDlgItemTextA(dlg, IDC_WIN_RATE, buf);
|
||||
|
||||
GetPrivateProfileStringA(SECTION, KEYS[6], DEFAULTS[6], buf, sizeof(buf), ini);
|
||||
if (SendDlgItemMessageA(dlg, IDC_CROSS_PLATFORM, CB_SELECTSTRING, -1, (LPARAM)buf) == CB_ERR)
|
||||
SendDlgItemMessageA(dlg, IDC_CROSS_PLATFORM, CB_SETCURSEL, 0, 0);
|
||||
|
||||
GetPrivateProfileStringA(SECTION, KEYS[7], DEFAULTS[7], buf, sizeof(buf), ini);
|
||||
SetDlgItemTextA(dlg, IDC_APP_VERSION, buf);
|
||||
|
||||
GetPrivateProfileStringA(SECTION, KEYS[8], DEFAULTS[8], buf, sizeof(buf), ini);
|
||||
SetDlgItemTextA(dlg, IDC_ONLINE_RULE, buf);
|
||||
|
||||
char tenoke[MAX_PATH];
|
||||
GetTenokePath(tenoke, sizeof(tenoke));
|
||||
if (GetFileAttributesA(tenoke) != INVALID_FILE_ATTRIBUTES) {
|
||||
ShowWindow(GetDlgItem(dlg, IDC_TENOKE_USER), SW_SHOW);
|
||||
ShowWindow(GetDlgItem(dlg, IDC_TENOKE_LABEL), SW_SHOW);
|
||||
const char *user = ReadTenokeUser(tenoke);
|
||||
SetDlgItemTextA(dlg, IDC_TENOKE_USER, user);
|
||||
} else {
|
||||
ShowWindow(GetDlgItem(dlg, IDC_TENOKE_USER), SW_HIDE);
|
||||
ShowWindow(GetDlgItem(dlg, IDC_TENOKE_LABEL), SW_HIDE);
|
||||
}
|
||||
}
|
||||
|
||||
static void EnsurePathExists(const char *path) {
|
||||
char dir[MAX_PATH];
|
||||
strncpy(dir, path, MAX_PATH);
|
||||
for (char *p = dir; *p; p++) {
|
||||
if (*p == '\\' || *p == '/') {
|
||||
char sep = *p;
|
||||
*p = '\0';
|
||||
CreateDirectoryA(dir, NULL);
|
||||
*p = sep;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SaveConfig(HWND dlg) {
|
||||
char ini[MAX_PATH];
|
||||
GetIniPath(ini, sizeof(ini));
|
||||
char buf[256];
|
||||
|
||||
EnsurePathExists(ini);
|
||||
|
||||
for (int i = 0; i < 9; i++) {
|
||||
GetDlgItemTextA(dlg, IDC_ROLE + i, buf, sizeof(buf));
|
||||
if (buf[0])
|
||||
WritePrivateProfileStringA(SECTION, KEYS[i], buf, ini);
|
||||
}
|
||||
|
||||
char tenoke[MAX_PATH];
|
||||
GetTenokePath(tenoke, sizeof(tenoke));
|
||||
HWND hTenoke = GetDlgItem(dlg, IDC_TENOKE_USER);
|
||||
if (hTenoke && IsWindowVisible(hTenoke)) {
|
||||
GetDlgItemTextA(dlg, IDC_TENOKE_USER, buf, sizeof(buf));
|
||||
if (buf[0])
|
||||
WriteTenokeUser(tenoke, buf);
|
||||
}
|
||||
|
||||
MessageBoxA(dlg, "Configuration saved.", "EOSHoloLauncher",
|
||||
MB_OK | MB_ICONINFORMATION);
|
||||
}
|
||||
|
||||
static void ResetConfig(HWND dlg) {
|
||||
char ini[MAX_PATH];
|
||||
GetIniPath(ini, sizeof(ini));
|
||||
|
||||
EnsurePathExists(ini);
|
||||
|
||||
for (int i = 0; i < 9; i++)
|
||||
WritePrivateProfileStringA(SECTION, KEYS[i], NULL, ini);
|
||||
|
||||
HANDLE hFile = CreateFileA(ini, GENERIC_WRITE, FILE_SHARE_READ, NULL,
|
||||
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile != INVALID_HANDLE_VALUE) {
|
||||
DWORD read;
|
||||
char old[4096] = {0};
|
||||
DWORD oldLen = GetFileSize(hFile, NULL);
|
||||
if (oldLen > 0 && oldLen < sizeof(old) - 1)
|
||||
ReadFile(hFile, old, oldLen, &read, NULL);
|
||||
|
||||
char tmp[8192];
|
||||
int pos = _snprintf(tmp, sizeof(tmp),
|
||||
"; To override default values, uncomment and edit the lines below:\n"
|
||||
"\n"
|
||||
"[Network]\n");
|
||||
|
||||
for (int i = 0; i < 9; i++)
|
||||
pos += _snprintf(tmp + pos, sizeof(tmp) - pos,
|
||||
"; %s=%s ; %s\n", KEYS[i], DEFAULTS[i], COMMENTS[i]);
|
||||
|
||||
pos += _snprintf(tmp + pos, sizeof(tmp) - pos, "\n");
|
||||
|
||||
char *line = old;
|
||||
bool inNetwork = false;
|
||||
while (line && *line && (size_t)(line - old) < oldLen) {
|
||||
char *nl = strchr(line, '\n');
|
||||
size_t len = nl ? (size_t)(nl - line) : strlen(line);
|
||||
char saved = line[len];
|
||||
line[len] = '\0';
|
||||
|
||||
char *trim = line;
|
||||
while (*trim == ' ' || *trim == '\t' || *trim == '\r') trim++;
|
||||
if (trim[0] == '[')
|
||||
inNetwork = (_stricmp(trim, "[Network]") == 0);
|
||||
|
||||
if (!inNetwork) {
|
||||
memcpy(tmp + pos, line, len);
|
||||
pos += (int)len;
|
||||
tmp[pos++] = '\r';
|
||||
tmp[pos++] = '\n';
|
||||
}
|
||||
|
||||
if (nl) {
|
||||
line[len] = saved;
|
||||
line = nl + 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
|
||||
SetEndOfFile(hFile);
|
||||
DWORD written;
|
||||
WriteFile(hFile, tmp, pos, &written, NULL);
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
|
||||
LoadConfig(dlg);
|
||||
MessageBoxA(dlg, "Settings reset to defaults.\nExample lines kept for reference.",
|
||||
"EOSHoloLauncher", MB_OK | MB_ICONINFORMATION);
|
||||
}
|
||||
|
||||
static INT_PTR CALLBACK AboutDlgProc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam) {
|
||||
if (msg == WM_INITDIALOG) {
|
||||
HICON hIcon = (HICON)LoadImageA(GetModuleHandleA(NULL),
|
||||
MAKEINTRESOURCEA(IDI_MAIN), IMAGE_ICON, 64, 64, LR_DEFAULTCOLOR);
|
||||
if (hIcon) {
|
||||
SendDlgItemMessageA(dlg, IDC_ABOUT_ICON, STM_SETICON, (WPARAM)hIcon, 0);
|
||||
SetPropA(dlg, "ABOUT_ICON", hIcon);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
if (msg == WM_CTLCOLORSTATIC) {
|
||||
HWND hCtrl = (HWND)lParam;
|
||||
if (hCtrl == GetDlgItem(dlg, IDC_ABOUT_LINK)) {
|
||||
HDC dc = (HDC)wParam;
|
||||
SetTextColor(dc, RGB(0, 102, 204));
|
||||
SetBkMode(dc, TRANSPARENT);
|
||||
return (INT_PTR)GetStockObject(HOLLOW_BRUSH);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
if (msg == WM_SETCURSOR) {
|
||||
if ((HWND)wParam == GetDlgItem(dlg, IDC_ABOUT_LINK)) {
|
||||
SetCursor(LoadCursorA(NULL, IDC_HAND));
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
if (msg == WM_COMMAND) {
|
||||
if (LOWORD(wParam) == IDC_ABOUT_LINK && HIWORD(wParam) == STN_CLICKED) {
|
||||
ShellExecuteA(NULL, "open", "https://codeberg.org/Nixietab/EOSSDK-Holos",
|
||||
NULL, NULL, SW_SHOWNORMAL);
|
||||
return TRUE;
|
||||
}
|
||||
if (LOWORD(wParam) == IDOK) {
|
||||
EndDialog(dlg, IDOK);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
if (msg == WM_CLOSE) {
|
||||
EndDialog(dlg, IDCANCEL);
|
||||
return TRUE;
|
||||
}
|
||||
if (msg == WM_NCDESTROY) {
|
||||
HICON hIcon = (HICON)RemovePropA(dlg, "ABOUT_ICON");
|
||||
if (hIcon) DestroyIcon(hIcon);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void LaunchGame(HWND dlg) {
|
||||
char exe[MAX_PATH];
|
||||
GetExePath(exe, sizeof(exe));
|
||||
|
||||
if (GetFileAttributesA(exe) == INVALID_FILE_ATTRIBUTES) {
|
||||
char msg[512];
|
||||
_snprintf(msg, sizeof(msg),
|
||||
"Game executable not found:\n%s\n\n"
|
||||
"Make sure the launcher is in the game's root directory.", exe);
|
||||
MessageBoxA(dlg, msg, "Error", MB_OK | MB_ICONERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
SaveConfig(dlg);
|
||||
|
||||
HINSTANCE r = ShellExecuteA(dlg, "open", exe, NULL, g_gameDir, SW_SHOWNORMAL);
|
||||
if ((INT_PTR)r <= 32) {
|
||||
char msg[256];
|
||||
_snprintf(msg, sizeof(msg), "Failed to launch game. Error code: %d.", (INT_PTR)r);
|
||||
MessageBoxA(dlg, msg, "Error", MB_OK | MB_ICONERROR);
|
||||
} else {
|
||||
EndDialog(dlg, IDOK);
|
||||
}
|
||||
}
|
||||
|
||||
static INT_PTR CALLBACK DlgProc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam) {
|
||||
switch (msg) {
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
HICON hIcon = LoadIconA(GetModuleHandleA(NULL), MAKEINTRESOURCEA(IDI_MAIN));
|
||||
SendMessageA(dlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
|
||||
SendMessageA(dlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
|
||||
}
|
||||
SendDlgItemMessageA(dlg, IDC_ROLE, CB_ADDSTRING, 0, (LPARAM)"Client");
|
||||
SendDlgItemMessageA(dlg, IDC_ROLE, CB_ADDSTRING, 0, (LPARAM)"Host");
|
||||
SendDlgItemMessageA(dlg, IDC_CROSS_PLATFORM, CB_ADDSTRING, 0, (LPARAM)"true");
|
||||
SendDlgItemMessageA(dlg, IDC_CROSS_PLATFORM, CB_ADDSTRING, 0, (LPARAM)"false");
|
||||
LoadConfig(dlg);
|
||||
{
|
||||
int sel = (int)SendDlgItemMessageA(dlg, IDC_ROLE, CB_GETCURSEL, 0, 0);
|
||||
EnableWindow(GetDlgItem(dlg, IDC_IP), sel == 0);
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
case WM_COMMAND:
|
||||
if (HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_ROLE) {
|
||||
int sel = (int)SendDlgItemMessageA(dlg, IDC_ROLE, CB_GETCURSEL, 0, 0);
|
||||
EnableWindow(GetDlgItem(dlg, IDC_IP), sel == 0);
|
||||
return TRUE;
|
||||
}
|
||||
switch (LOWORD(wParam)) {
|
||||
case IDC_SAVE:
|
||||
SaveConfig(dlg);
|
||||
return TRUE;
|
||||
case IDC_RESET:
|
||||
case IDM_RESET:
|
||||
ResetConfig(dlg);
|
||||
return TRUE;
|
||||
case IDC_LAUNCH:
|
||||
LaunchGame(dlg);
|
||||
return TRUE;
|
||||
case IDM_ABOUT:
|
||||
DialogBoxParamA(GetModuleHandleA(NULL), MAKEINTRESOURCEA(IDD_ABOUT),
|
||||
dlg, AboutDlgProc, 0);
|
||||
return TRUE;
|
||||
case IDM_EXIT:
|
||||
EndDialog(dlg, IDCANCEL);
|
||||
return TRUE;
|
||||
case IDCANCEL:
|
||||
EndDialog(dlg, IDCANCEL);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
case WM_CLOSE:
|
||||
EndDialog(dlg, IDCANCEL);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int) {
|
||||
GetModuleFileNameA(NULL, g_gameDir, MAX_PATH);
|
||||
char *s = strrchr(g_gameDir, '\\');
|
||||
if (!s) s = strrchr(g_gameDir, '/');
|
||||
if (s) *s = '\0';
|
||||
else g_gameDir[0] = '\0';
|
||||
|
||||
DialogBoxParamA(hInst, MAKEINTRESOURCEA(IDD_MAIN), NULL, DlgProc, 0);
|
||||
return 0;
|
||||
}
|
||||
23
Launcher/resource.h
Normal file
23
Launcher/resource.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#define IDD_MAIN 101
|
||||
#define IDI_MAIN 102
|
||||
#define IDD_ABOUT 103
|
||||
#define IDR_MENU 104
|
||||
#define IDM_RESET 40000
|
||||
#define IDM_ABOUT 40001
|
||||
#define IDM_EXIT 40002
|
||||
#define IDC_ROLE 1001
|
||||
#define IDC_IP 1002
|
||||
#define IDC_PORT 1003
|
||||
#define IDC_MAX_MEMBERS 1004
|
||||
#define IDC_PLATFORM 1005
|
||||
#define IDC_WIN_RATE 1006
|
||||
#define IDC_CROSS_PLATFORM 1007
|
||||
#define IDC_APP_VERSION 1008
|
||||
#define IDC_ONLINE_RULE 1009
|
||||
#define IDC_SAVE 1010
|
||||
#define IDC_RESET 1011
|
||||
#define IDC_LAUNCH 1012
|
||||
#define IDC_TENOKE_USER 1013
|
||||
#define IDC_TENOKE_LABEL 1014
|
||||
#define IDC_ABOUT_ICON 1015
|
||||
#define IDC_ABOUT_LINK 1016
|
||||
78
Launcher/resource.rc
Normal file
78
Launcher/resource.rc
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
#include <windows.h>
|
||||
#include "resource.h"
|
||||
|
||||
IDI_MAIN ICON "icon.ico"
|
||||
|
||||
IDR_MENU MENU
|
||||
BEGIN
|
||||
POPUP "File"
|
||||
BEGIN
|
||||
MENUITEM "Reset Config", IDM_RESET
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "About", IDM_ABOUT
|
||||
MENUITEM "Exit", IDM_EXIT
|
||||
END
|
||||
END
|
||||
|
||||
IDD_MAIN DIALOGEX 0, 0, 340, 186
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "EOSHoloLauncher"
|
||||
MENU IDR_MENU
|
||||
FONT 9, "Segoe UI", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "Role:", -1, 8, 8, 25, 10
|
||||
COMBOBOX IDC_ROLE, 35, 6, 65, 100, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
|
||||
LTEXT "IP:", -1, 108, 8, 16, 10
|
||||
EDITTEXT IDC_IP, 124, 6, 85, 13, ES_AUTOHSCROLL
|
||||
|
||||
LTEXT "Port:", -1, 217, 8, 22, 10
|
||||
EDITTEXT IDC_PORT, 239, 6, 45, 13, ES_AUTOHSCROLL | ES_NUMBER
|
||||
|
||||
LTEXT "User:", IDC_TENOKE_LABEL, 8, 26, 25, 10
|
||||
EDITTEXT IDC_TENOKE_USER, 35, 24, 249, 13, ES_AUTOHSCROLL
|
||||
|
||||
GROUPBOX "Advanced Settings", -1, 5, 46, 330, 80
|
||||
|
||||
LTEXT "Max Members:", -1, 12, 60, 58, 10
|
||||
EDITTEXT IDC_MAX_MEMBERS, 72, 58, 40, 13, ES_AUTOHSCROLL | ES_NUMBER
|
||||
|
||||
LTEXT "Platform:", -1, 160, 60, 38, 10
|
||||
EDITTEXT IDC_PLATFORM, 200, 58, 125, 13, ES_AUTOHSCROLL
|
||||
|
||||
LTEXT "Win Rate:", -1, 12, 78, 42, 10
|
||||
EDITTEXT IDC_WIN_RATE, 72, 76, 40, 13, ES_AUTOHSCROLL | ES_NUMBER
|
||||
|
||||
LTEXT "Cross-Platform:", -1, 160, 78, 62, 10
|
||||
COMBOBOX IDC_CROSS_PLATFORM, 225, 76, 100, 80, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
|
||||
LTEXT "App Version:", -1, 12, 96, 52, 10
|
||||
EDITTEXT IDC_APP_VERSION, 72, 94, 40, 13, ES_AUTOHSCROLL
|
||||
|
||||
LTEXT "Online Rule:", -1, 160, 96, 52, 10
|
||||
EDITTEXT IDC_ONLINE_RULE, 225, 94, 100, 13, ES_AUTOHSCROLL
|
||||
|
||||
LTEXT "Note: Online Rule, App Version, and Win Rate are for matchmaking purposes.\nLeave at defaults unless you know what you are doing.",
|
||||
-1, 8, 136, 324, 20
|
||||
|
||||
DEFPUSHBUTTON "Launch", IDC_LAUNCH, 25, 164, 90, 16
|
||||
PUSHBUTTON "Save Config", IDC_SAVE, 125, 164, 90, 16
|
||||
END
|
||||
|
||||
IDD_ABOUT DIALOGEX 0, 0, 300, 130
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "About EOSHoloLauncher"
|
||||
FONT 9, "Segoe UI", 400, 0, 0x1
|
||||
BEGIN
|
||||
ICON IDI_MAIN, IDC_ABOUT_ICON, 10, 10, 64, 64
|
||||
LTEXT "EOSHoloLauncher v1.0", -1, 82, 12, 200, 12
|
||||
LTEXT "A graphical configuration tool for the EOSSDK-Holos\n"
|
||||
"proxy project. Provides a simple interface to configure\n"
|
||||
"direct IP multiplayer settings for Holos Hanafuda.\n"
|
||||
"\n"
|
||||
"Licensed under the GNU General Public License v2.0.",
|
||||
-1, 82, 28, 200, 48
|
||||
LTEXT "https://codeberg.org/Nixietab/EOSSDK-Holos",
|
||||
IDC_ABOUT_LINK, 82, 80, 200, 10, SS_NOTIFY
|
||||
DEFPUSHBUTTON "OK", IDOK, 235, 104, 50, 16
|
||||
END
|
||||
Loading…
Add table
Add a link
Reference in a new issue