15 if (MultiByteToWideChar(CP_UTF8, 0, path, -1, out, MAX_PATH) == 0) {
20 out[MAX_PATH - 1] = L
'\0';
25static bool get_full_path(
char *out,
size_t out_size,
const char *path) {
26 const DWORD len = GetFullPathNameA(path, (
DWORD)out_size, out,
NULL);
27 return len > 0 && len < out_size;
32 const DWORD len = GetEnvironmentVariableA(
"LOCALAPPDATA", buf, (
DWORD)buf_size);
34 if (len > 0 && len < buf_size) {
38 const DWORD temp_len = GetTempPathA((
DWORD)buf_size, buf);
39 return temp_len > 0 && temp_len < buf_size;
43static bool try_path(WCHAR *out,
const WCHAR *dir,
const WCHAR *subpath) {
44 WCHAR candidate[MAX_PATH];
45 _snwprintf(candidate, MAX_PATH, L
"%s\\%s", dir, subpath);
46 candidate[MAX_PATH - 1] = L
'\0';
48 if (GetFileAttributesW(candidate) == INVALID_FILE_ATTRIBUTES) {
52 wcscpy(out, candidate);
57static bool try_dir(WCHAR *out,
const WCHAR *dir) {
60 for (
size_t i = 0; i < subpath_count; i++) {
70static void copy_path(
char *out,
size_t out_size,
const char *path) {
83 const char *cache_root,
99 const char *cache_root,
113 char pkg_path[MAX_PATH];
138 const char *iso_path,
141 char full_iso_path[MAX_PATH];
143 if (!
get_full_path(full_iso_path,
sizeof(full_iso_path), iso_path)) {
148 char cache_base_dir[MAX_PATH];
157 DTTR_LOG_ERROR(
"Could not build ISO cache path for %s", full_iso_path);
166 "Could not open ISO directly: %s (%s)",
173 char exe_path[MAX_PATH];
186 DTTR_LOG_ERROR(
"Could not convert cached ISO executable path: %s", exe_path);
190 iso_context->
is_iso =
true;
207 const char *iso_path,
215 memset(iso_context, 0,
sizeof(*iso_context));
222 "DttR: ISO Load Failed",
223 "DttR could not read the selected ISO. Consider using the extracted game files "
232 const char *configured_path,
235 WCHAR wide_path[MAX_PATH];
237 DTTR_LOG_ERROR(
"Could not convert configured path: %s", configured_path);
242 DTTR_LOG_INFO(
"Using configured ISO path: %s", configured_path);
243 return resolve_iso(out, configured_path, iso_context);
247 DTTR_LOG_INFO(
"Using configured PCDOGS path: %s", configured_path);
259 snprintf(candidate->
label,
sizeof(candidate->
label),
"Open Disc %c:", drive);
260 snprintf(candidate->
path,
sizeof(candidate->
path),
"%c:\\", drive);
268 (filelist && filelist[0]) ? filelist[0] :
NULL
278 while (WaitForSingleObject(
browse_event, 0) == WAIT_TIMEOUT) {
291 "Could not save selected game path to %s; continuing for this launch",
300 size_t *candidate_count
302 *candidate_count = 0;
303 const DWORD drives = GetLogicalDrives();
305 for (
char drive =
'A'; drive <=
'Z'; drive++) {
306 const DWORD bit = 1u << (drive -
'A');
308 if ((drives & bit) == 0) {
312 WCHAR root_w[] = {drive, L
':', L
'\\', L
'\0'};
313 const UINT drive_type = GetDriveTypeW(root_w);
315 if (drive_type == DRIVE_UNKNOWN || drive_type == DRIVE_NO_ROOT_DIR) {
319 WCHAR game_path[MAX_PATH];
321 if (!
try_dir(game_path, root_w)) {
327 (*candidate_count)++;
337 WCHAR wide_path[MAX_PATH];
340 "DttR: Disc Not Found",
341 "The selected disc no longer contains pcdogs.exe."
370 const SDL_DialogFileFilter filters[] = {{
"ISO images",
"iso"}};
396 WCHAR wide_path[MAX_PATH];
399 "DttR: Game Not Found",
400 "The selected folder does not contain pcdogs.exe."
414 "DttR: Game Not Found",
415 "The selected folder does not contain pcdogs.exe."
423 size_t disc_candidate_count = 0;
432 size_t disc_index = 0;
435 if (disc_index < disc_candidate_count
461 const char *configured_path,
464 if (configured_path && configured_path[0]
static bool try_path(WCHAR *out, const WCHAR *dir, const WCHAR *subpath)
static char browse_result[MAX_PATH]
static bool resolve_iso_direct(WCHAR *out, const char *iso_path, DTTR_LoaderIsoContext *iso_context)
static bool get_os_cache_base_dir(char *buf, size_t buf_size)
static void fill_disc_candidate(DTTR_LoaderUIDiscCandidate *candidate, char drive)
static bool prompt_browse_for_path(WCHAR *out, DTTR_LoaderIsoContext *iso_context)
static bool extract_iso_file(DTTR_IsoImage *iso, const char *cache_root, const char *iso_path, char *out_path, size_t out_path_size)
static bool wait_for_browse_result()
static bool try_browse_choice(WCHAR *out, DTTR_LoaderUIChoice choice, DTTR_LoaderIsoContext *iso_context)
static bool run_browse_dialog(DTTR_LoaderUIChoice choice)
static void scan_disc_candidates(DTTR_LoaderUIDiscCandidate *candidates, size_t *candidate_count)
static bool try_browsed_path(WCHAR *out, DTTR_LoaderUIChoice choice, DTTR_LoaderIsoContext *iso_context)
static void copy_path(char *out, size_t out_size, const char *path)
static bool extract_iso_game_cache(DTTR_IsoImage *iso, const char *cache_root, char *exe_path, size_t exe_path_size)
static bool try_dir(WCHAR *out, const WCHAR *dir)
static bool resolve_iso(WCHAR *out, const char *iso_path, DTTR_LoaderIsoContext *iso_context)
static HANDLE browse_event
bool DTTR_Loader_ResolveEXEPath(WCHAR *out, const char *configured_path, DTTR_LoaderIsoContext *iso_context)
static bool get_full_path(char *out, size_t out_size, const char *path)
static bool try_disc_candidate(WCHAR *out, const DTTR_LoaderUIDiscCandidate *candidate)
static bool try_configured_path(WCHAR *out, const char *configured_path, DTTR_LoaderIsoContext *iso_context)
static void SDLCALL browse_callback(void *, const char *const *filelist, int)
static bool utf8_to_wide_path(WCHAR *out, const char *path)
static void save_selected_path(const char *path)
DTTR_Graphics_COM_Direct3DDevice7 DWORD block DTTR_Graphics_COM_Direct3DDevice7 DWORD block DTTR_Graphics_COM_Direct3DDevice7 void void void void DWORD f FALSE
DTTR_Graphics_COM_DirectDrawSurface7 DWORD flags void NULL
bool DTTR_Config_Save(const char *filename, const DTTR_Config *config)
Saves config values back to a strict JSON file.
bool DTTR_ISO_ExtractFile(DTTR_IsoImage *iso, const char *iso_relative_path, const char *cache_root, char *out_path, size_t out_path_size)
void DTTR_ISO_Close(DTTR_IsoImage *iso)
bool DTTR_ISO_Open(DTTR_IsoImage *iso, const char *iso_path)
bool DTTR_ISO_ExtractTree(DTTR_IsoImage *iso, const char *iso_relative_path, const char *cache_root)
const char * DTTR_ISO_LastError()
const char * dttr_config_path
const char * DTTR_LoaderISO_GameEXEPath()
size_t DTTR_Loader_GameSubpathCount()
const char * DTTR_LoaderISO_GameDataPath()
bool DTTR_LoaderISO_CacheRootForPath(const char *cache_base_dir, const char *iso_path, char *out_path, size_t out_path_size)
const wchar_t * DTTR_Loader_GameSubpathAt(size_t index)
const char * DTTR_LoaderISO_GameRoot()
bool DTTR_LoaderPath_IsISOW(const wchar_t *path)
const char * DTTR_LoaderISO_GamePkgPath()
@ DTTR_LOADER_UI_MAX_DISC_CANDIDATES
DTTR_LoaderUIChoice DTTR_LoaderUI_ChooseGameSource(const DTTR_LoaderUIDiscCandidate *disc_candidates, size_t disc_candidate_count)
bool DTTR_LoaderUI_ChoiceIsBrowse(DTTR_LoaderUIChoice choice)
@ DTTR_LOADER_UI_CHOICE_BROWSE_ISO
@ DTTR_LOADER_UI_CHOICE_BROWSE_FOLDER
bool DTTR_LoaderUI_ChoiceIsDisc(DTTR_LoaderUIChoice choice, size_t *out_index)
void DTTR_LoaderUI_ShowError(const char *title, const char *message)
#define DTTR_LOG_INFO(...)
#define DTTR_LOG_ERROR(...)
bool DTTR_Path_CopyString(char *out, size_t out_size, const char *value)
void DTTR_SDL_Delay(Uint32 ms)
void DTTR_SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const SDL_DialogFileFilter *filters, int nfilters, const char *default_location, bool allow_many)
void DTTR_SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const char *default_location, bool allow_many)
void DTTR_SDL_PumpEvents()
char cache_root[MAX_PATH]