@@ -2736,11 +2736,6 @@ static qboolean COM_IsValidFlavorDir (const char *dir, int flavor)
27362736 return false;
27372737}
27382738
2739- static qboolean COM_IsValidBaseDir (const char * dir )
2740- {
2741- return COM_IsValidFlavorDir (dir , -1 );
2742- }
2743-
27442739/*
27452740=================
27462741COM_RequestedQuakeFlavor
@@ -2757,28 +2752,41 @@ static int COM_RequestedQuakeFlavor (void)
27572752 return -1 ;
27582753}
27592754
2755+ /*
2756+ =================
2757+ COM_FOpenPrefFile
2758+
2759+ Opens a file in the per-user preferences directory
2760+ (%APPDATA%\vkQuake on Windows)
2761+ =================
2762+ */
2763+ FILE * COM_FOpenPrefFile (const char * filename , const char * mode )
2764+ {
2765+ char * pref_path = SDL_GetPrefPath ("" , "vkQuake" );
2766+ FILE * f = fopen (va ("%s/%s" , pref_path , filename ), mode );
2767+ SDL_free (pref_path );
2768+ return f ;
2769+ }
2770+
27602771#ifdef USE_SDL3
27612772/*
27622773=================
2763- COM_LoadSelectedBaseDirs / COM_SaveSelectedBaseDirs
2774+ COM_LoadSelectedBaseDirs
27642775
2765- Game folders the user picked in the folder dialog, kept in the pref
2766- dir. A new pick is only written once the engine is fully initialized
2767- (COM_WriteSelectedBaseDir) so a folder with broken data can't get
2768- remembered.
2776+ Game folders the user picked in the folder dialog, kept in basedirs.txt
2777+ in the pref dir. A new pick is only written back once the engine is
2778+ fully initialized (COM_WriteSelectedBaseDir) so a folder with broken
2779+ data can't get remembered.
27692780=================
27702781*/
2771- static int com_pendingbasedirflavor = -1 ;
2772- static char com_pendingbasedir [ MAX_OSPATH ] ;
2782+ static char com_storedbasedirs [ 2 ][ MAX_OSPATH ]; // indexed by quakeflavor_t
2783+ static qboolean com_pendingbasedirwrite ;
27732784
2774- static void COM_LoadSelectedBaseDirs (char * original , size_t originalsize , char * remastered , size_t remasteredsize )
2785+ static void COM_LoadSelectedBaseDirs (void )
27752786{
27762787 char line [MAX_OSPATH + 16 ];
2777- FILE * f ;
2778- char * pref_path = SDL_GetPrefPath ("" , "vkQuake" );
2788+ FILE * f = COM_FOpenPrefFile ("basedirs.txt" , "r" );
27792789
2780- f = fopen (va ("%s/basedirs.txt" , pref_path ), "r" );
2781- SDL_free (pref_path );
27822790 if (!f )
27832791 return ;
27842792
@@ -2790,74 +2798,70 @@ static void COM_LoadSelectedBaseDirs (char *original, size_t originalsize, char
27902798 * path ++ = '\0' ;
27912799 path [strcspn (path , "\r\n" )] = '\0' ;
27922800 if (!strcmp (line , "classic" ))
2793- q_strlcpy (original , path , originalsize );
2801+ q_strlcpy (com_storedbasedirs [ QUAKE_FLAVOR_ORIGINAL ] , path , MAX_OSPATH );
27942802 else if (!strcmp (line , "remastered" ))
2795- q_strlcpy (remastered , path , remasteredsize );
2803+ q_strlcpy (com_storedbasedirs [ QUAKE_FLAVOR_REMASTERED ] , path , MAX_OSPATH );
27962804 }
27972805
27982806 fclose (f );
27992807}
28002808
2801- static void COM_SaveSelectedBaseDirs (const char * original , const char * remastered )
2802- {
2803- FILE * f ;
2804- char * pref_path = SDL_GetPrefPath ("" , "vkQuake" );
2805-
2806- f = fopen (va ("%s/basedirs.txt" , pref_path ), "w" );
2807- SDL_free (pref_path );
2808- if (!f )
2809- return ;
2810-
2811- if (original [0 ])
2812- fprintf (f , "classic %s\n" , original );
2813- if (remastered [0 ])
2814- fprintf (f , "remastered %s\n" , remastered );
2815-
2816- fclose (f );
2817- }
2818-
28192809/*
28202810=================
28212811COM_SelectBaseDir
28222812
28232813Asks the user for a game folder until it contains data for the wanted
2824- flavor (-1 accepts either); returns false if the dialog was cancelled
2814+ flavor (-1 accepts either), starting at the folder remembered from a
2815+ previous run. Exits cleanly when the user cancels the dialog; returns
2816+ false when no dialog could be shown so the caller falls through to
2817+ the regular missing-data error
28252818=================
28262819*/
2827- static qboolean COM_SelectBaseDir (int flavor , const char * default_location , char * dst , size_t dstsize )
2820+ static qboolean COM_SelectBaseDir (int flavor , char * dst , size_t dstsize )
28282821{
2829- const char * title , * complaint ;
2822+ const char * title , * complaint , * default_location ;
2823+ int result ;
28302824
28312825 switch (flavor )
28322826 {
28332827 case QUAKE_FLAVOR_ORIGINAL :
28342828 title = "Select your classic Quake folder" ;
28352829 complaint = "The selected folder does not contain " GAMENAME "/pak0.pak." ;
2830+ default_location = com_storedbasedirs [QUAKE_FLAVOR_ORIGINAL ];
28362831 break ;
28372832 case QUAKE_FLAVOR_REMASTERED :
28382833 title = "Select your remastered Quake folder" ;
28392834 complaint = "The selected folder does not contain QuakeEX.kpf." ;
2835+ default_location = com_storedbasedirs [QUAKE_FLAVOR_REMASTERED ];
28402836 break ;
28412837 default :
28422838 title = "Select your Quake folder" ;
28432839 complaint = "The selected folder does not contain Quake game data (" GAMENAME "/pak0.pak or QuakeEX.kpf)." ;
2840+ default_location =
2841+ com_storedbasedirs [QUAKE_FLAVOR_REMASTERED ][0 ] ? com_storedbasedirs [QUAKE_FLAVOR_REMASTERED ] : com_storedbasedirs [QUAKE_FLAVOR_ORIGINAL ];
28442842 break ;
28452843 }
28462844
2847- while (Sys_SelectFolder (title , default_location , dst , dstsize ))
2845+ while (( result = Sys_SelectFolder (title , default_location , dst , dstsize )) > 0 )
28482846 {
28492847 if (COM_IsValidFlavorDir (dst , flavor ))
28502848 return true;
28512849 SDL_ShowSimpleMessageBox (SDL_MESSAGEBOX_WARNING , "vkQuake" , complaint , NULL );
28522850 }
28532851
2854- return false;
2852+ if (result == 0 ) // cancelled
2853+ {
2854+ SDL_Quit ();
2855+ exit (0 );
2856+ }
2857+
2858+ return false; // no dialog could be shown
28552859}
28562860
28572861static void COM_SetPendingBaseDir (int flavor , const char * dir )
28582862{
2859- com_pendingbasedirflavor = flavor ;
2860- q_strlcpy ( com_pendingbasedir , dir , sizeof ( com_pendingbasedir )) ;
2863+ q_strlcpy ( com_storedbasedirs [ flavor ], dir , MAX_OSPATH ) ;
2864+ com_pendingbasedirwrite = true ;
28612865}
28622866#endif
28632867
@@ -2872,20 +2876,22 @@ fully initialized as proof the folder contains working game data
28722876void COM_WriteSelectedBaseDir (void )
28732877{
28742878#ifdef USE_SDL3
2875- char original [MAX_OSPATH ] = {0 };
2876- char remastered [MAX_OSPATH ] = {0 };
2879+ FILE * f ;
28772880
2878- if (com_pendingbasedirflavor < 0 )
2881+ if (! com_pendingbasedirwrite )
28792882 return ;
28802883
2881- COM_LoadSelectedBaseDirs (original , sizeof (original ), remastered , sizeof (remastered ));
2882- if (com_pendingbasedirflavor == QUAKE_FLAVOR_REMASTERED )
2883- q_strlcpy (remastered , com_pendingbasedir , sizeof (remastered ));
2884- else
2885- q_strlcpy (original , com_pendingbasedir , sizeof (original ));
2886- COM_SaveSelectedBaseDirs (original , remastered );
2884+ f = COM_FOpenPrefFile ("basedirs.txt" , "w" );
2885+ if (!f )
2886+ return ;
28872887
2888- com_pendingbasedirflavor = -1 ;
2888+ if (com_storedbasedirs [QUAKE_FLAVOR_ORIGINAL ][0 ])
2889+ fprintf (f , "classic %s\n" , com_storedbasedirs [QUAKE_FLAVOR_ORIGINAL ]);
2890+ if (com_storedbasedirs [QUAKE_FLAVOR_REMASTERED ][0 ])
2891+ fprintf (f , "remastered %s\n" , com_storedbasedirs [QUAKE_FLAVOR_REMASTERED ]);
2892+
2893+ fclose (f );
2894+ com_pendingbasedirwrite = false;
28892895#endif
28902896}
28912897
@@ -2945,56 +2951,45 @@ static void COM_FindStoreBaseDir (void)
29452951 if (!forced && !isDedicated )
29462952 {
29472953#ifdef USE_SDL3
2948- char stored_original [MAX_OSPATH ] = {0 };
2949- char stored_remastered [MAX_OSPATH ] = {0 };
2950-
2951- COM_LoadSelectedBaseDirs (stored_original , sizeof (stored_original ), stored_remastered , sizeof (stored_remastered ));
2954+ COM_LoadSelectedBaseDirs ();
29522955
29532956 // use the folder picked in a previous run unless the user wants a new one
29542957 if (!COM_CheckParm ("-select-basedir" ))
29552958 {
2956- if (!original [0 ] && stored_original [0 ] && COM_IsValidFlavorDir (stored_original , QUAKE_FLAVOR_ORIGINAL ))
2957- q_strlcpy (original , stored_original , sizeof (original ));
2958- if (!remastered [0 ] && stored_remastered [0 ] && COM_IsValidFlavorDir (stored_remastered , QUAKE_FLAVOR_REMASTERED ))
2959- q_strlcpy (remastered , stored_remastered , sizeof (remastered ));
2959+ if (!original [0 ] && com_storedbasedirs [QUAKE_FLAVOR_ORIGINAL ][0 ] &&
2960+ COM_IsValidFlavorDir (com_storedbasedirs [QUAKE_FLAVOR_ORIGINAL ], QUAKE_FLAVOR_ORIGINAL ))
2961+ q_strlcpy (original , com_storedbasedirs [QUAKE_FLAVOR_ORIGINAL ], sizeof (original ));
2962+ if (!remastered [0 ] && com_storedbasedirs [QUAKE_FLAVOR_REMASTERED ][0 ] &&
2963+ COM_IsValidFlavorDir (com_storedbasedirs [QUAKE_FLAVOR_REMASTERED ], QUAKE_FLAVOR_REMASTERED ))
2964+ q_strlcpy (remastered , com_storedbasedirs [QUAKE_FLAVOR_REMASTERED ], sizeof (remastered ));
29602965 }
29612966
2962- // still missing: ask for the folder, starting the dialog at the previous pick
2967+ // still missing: ask for the folder, remember it only once it's usable
29632968 if (requested == QUAKE_FLAVOR_ORIGINAL && !original [0 ])
29642969 {
2965- if (!COM_SelectBaseDir (QUAKE_FLAVOR_ORIGINAL , stored_original , original , sizeof (original )))
2966- {
2967- SDL_Quit ();
2968- exit (0 );
2969- }
2970- COM_SetPendingBaseDir (QUAKE_FLAVOR_ORIGINAL , original );
2970+ if (COM_SelectBaseDir (QUAKE_FLAVOR_ORIGINAL , original , sizeof (original )))
2971+ COM_SetPendingBaseDir (QUAKE_FLAVOR_ORIGINAL , original );
29712972 }
29722973 else if (requested == QUAKE_FLAVOR_REMASTERED && !remastered [0 ])
29732974 {
2974- if (!COM_SelectBaseDir (QUAKE_FLAVOR_REMASTERED , stored_remastered , remastered , sizeof (remastered )))
2975- {
2976- SDL_Quit ();
2977- exit (0 );
2978- }
2979- COM_SetPendingBaseDir (QUAKE_FLAVOR_REMASTERED , remastered );
2975+ if (COM_SelectBaseDir (QUAKE_FLAVOR_REMASTERED , remastered , sizeof (remastered )))
2976+ COM_SetPendingBaseDir (QUAKE_FLAVOR_REMASTERED , remastered );
29802977 }
29812978 else if (requested < 0 && !original [0 ] && !remastered [0 ])
29822979 {
29832980 char selected [MAX_OSPATH ];
2984- if (! COM_SelectBaseDir (-1 , stored_remastered [ 0 ] ? stored_remastered : stored_original , selected , sizeof (selected )))
2981+ if (COM_SelectBaseDir (-1 , selected , sizeof (selected )))
29852982 {
2986- SDL_Quit ();
2987- exit (0 );
2988- }
2989- if (COM_IsValidFlavorDir (selected , QUAKE_FLAVOR_REMASTERED ))
2990- {
2991- q_strlcpy (remastered , selected , sizeof (remastered ));
2992- COM_SetPendingBaseDir (QUAKE_FLAVOR_REMASTERED , selected );
2993- }
2994- else
2995- {
2996- q_strlcpy (original , selected , sizeof (original ));
2997- COM_SetPendingBaseDir (QUAKE_FLAVOR_ORIGINAL , selected );
2983+ if (COM_IsValidFlavorDir (selected , QUAKE_FLAVOR_REMASTERED ))
2984+ {
2985+ q_strlcpy (remastered , selected , sizeof (remastered ));
2986+ COM_SetPendingBaseDir (QUAKE_FLAVOR_REMASTERED , selected );
2987+ }
2988+ else
2989+ {
2990+ q_strlcpy (original , selected , sizeof (original ));
2991+ COM_SetPendingBaseDir (QUAKE_FLAVOR_ORIGINAL , selected );
2992+ }
29982993 }
29992994 }
30002995#else
@@ -3137,8 +3132,10 @@ void COM_InitFilesystem (void) // johnfitz -- modified based on topaz's tutorial
31373132 com_basedir [j - 1 ] = 0 ;
31383133
31393134 // no explicit -basedir: run store detection if the working directory has no
3140- // game data, or if a store version was requested explicitly on the command line
3141- if (!i && (!COM_IsValidBaseDir (com_basedir ) || COM_CheckParm ("-steam" ) || COM_CheckParm ("-gog" ) || COM_CheckParm ("-egs" ) || COM_CheckParm ("-epic" )))
3135+ // game data for the requested version (any version if none was requested),
3136+ // or if a store was named explicitly on the command line
3137+ if (!i && (!COM_IsValidFlavorDir (com_basedir , COM_RequestedQuakeFlavor ()) || COM_CheckParm ("-steam" ) || COM_CheckParm ("-gog" ) ||
3138+ COM_CheckParm ("-egs" ) || COM_CheckParm ("-epic" )))
31423139 COM_FindStoreBaseDir ();
31433140
31443141 // achievements/rich presence if the game data comes from the Steam install,
0 commit comments