]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - radiant/preferences.cpp
- Updated Windows build doc, very slight revision. Changed 37 targets to 38.
[xonotic/netradiant.git] / radiant / preferences.cpp
index 021dc9372cf598d07b0886b9efae5d3b0bbaac6b..f85075bdfdd6ae6a48164d6e31f6393d0b2a78fd 100644 (file)
@@ -96,6 +96,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #define WIDETOOLBAR_KEY         "WideToolBar"
 #define PLUGINTOOLBAR_KEY "PluginToolBar"
 #define NOCLAMP_KEY             "NoClamp"
+#define SNAP_KEY                "Snap"
 #define PREFAB_KEY              "PrefabPath"
 #define USERINI_KEY             "UserINIPath"
 #define ROTATION_KEY            "Rotation"
@@ -129,6 +130,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #define LEAKSTOP_KEY            "LeakStop"
 #define DOSLEEP_KEY             "SleepMode"
 #define SUBDIVISIONS_KEY        "Subdivisions"
+#define DEFAULTTEXURESCALE_KEY  "DefaultTextureScale"
 #define CLIPCAULK_KEY           "ClipCaulk"
 #define PATCHSHOWBOUNDS_KEY     "PatchShowBounds"
 #define NATIVEGUI_KEY           "NativeGUI"
@@ -146,7 +148,14 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #define TEXTURECOMPRESSIONFORMAT_KEY "TextureCompressionFormat"
 #define LIGHTRADIUS_KEY "LightRadiuses"
 #define Q3MAP2TEX_KEY "Q3Map2Tex"
+
+#ifdef ATIHACK_812
 #define ATIHACK_KEY "ATIHack"
+#endif
+
+#ifdef NVIDIA_AERO_HACK
+#define NVAEROHACK_KEY "NvidiaAeroHack"
+#endif
 
 // window stuff
 #define ENTITYSPLIT1_KEY  "EntitySplit1"
@@ -635,6 +644,7 @@ PrefsDlg::PrefsDlg ()
   m_bWideToolbar = TRUE;
   m_bPluginToolbar = TRUE;
   m_bNoClamp = FALSE;
+  m_bSnap = TRUE;
   m_strUserPath = "";
   m_nRotation = 0;
   m_bChaseMouse = FALSE;
@@ -684,7 +694,11 @@ PrefsDlg::PrefsDlg ()
   m_nLightRadiuses = 1;
   m_bQ3Map2Texturing = TRUE;
 #ifdef ATIHACK_812
-       m_bGlATIHack = FALSE;
+  m_bGlATIHack = FALSE;
+#endif
+#ifdef NVIDIA_AERO_HACK
+  m_bGlNvidiaAeroHack = TRUE;
+  m_bGlNvidiaAeroHackPrevState = -1; // -1 is uninitialized, 0 is FALSE, 1 is TRUE
 #endif
 }
 
@@ -695,30 +709,24 @@ Games selection dialog
 */
 
 #if defined(WIN32)
+#define TOOLS_ATTRIBUTE "gametools_win32"
 #define ENGINE_ATTRIBUTE "engine_win32"
+#define ENGINEPATH_ATTRIBUTE "enginepath_win32"
 #define MP_ENGINE_ATTRIBUTE "mp_engine_win32"
 #elif defined(__linux__) || defined (__FreeBSD__)
+#define TOOLS_ATTRIBUTE "gametools_linux"
 #define ENGINE_ATTRIBUTE "engine_linux"
+#define ENGINEPATH_ATTRIBUTE "enginepath_linux"
 #define MP_ENGINE_ATTRIBUTE "mp_engine_linux"
 #elif defined(__APPLE__)
+#define TOOLS_ATTRIBUTE "gametools_macos"
 #define ENGINE_ATTRIBUTE "engine_macos"
+#define ENGINEPATH_ATTRIBUTE "enginepath_macos"
 #define MP_ENGINE_ATTRIBUTE "mp_engine_macos"
 #else
 #error "unsupported platform"
 #endif
 
-
-#if defined(WIN32)
-#define ENGINEPATH_ATTRIBUTE "enginepath_win32"
-#elif defined(__linux__) || defined (__FreeBSD__)
-#define ENGINEPATH_ATTRIBUTE "enginepath_linux"
-#elif defined(__APPLE__)
-#define ENGINEPATH_ATTRIBUTE "enginepath_macos"
-#else
-#error "unknown platform"
-#endif
-
-
 CGameDescription::CGameDescription(xmlDocPtr pDoc, const Str &GameFile)
 {
   char *p, *prop;
@@ -733,9 +741,9 @@ CGameDescription::CGameDescription(xmlDocPtr pDoc, const Str &GameFile)
     Error("Didn't find 'game' node in the game description file '%s'\n", pDoc->URL);
   }
   // on win32, game tools path can now be specified relative to the exe's cwd
-  prop = (char*)xmlGetProp( pNode, (xmlChar*)"gametools" );
+  prop = (char*)xmlGetProp( pNode, (xmlChar*)TOOLS_ATTRIBUTE);
   if ( prop == NULL ) {
-       Error( "Didn't find 'gametools' node in the game description file '%s'\n", pDoc->URL );
+       Error( "Didn't find '"TOOLS_ATTRIBUTE"' node in the game description file '%s'\n", pDoc->URL );
   }
   {
        char full[PATH_MAX];
@@ -1724,6 +1732,11 @@ void PrefsDlg::BuildDialog ()
           gtk_tree_store_append(store, &tab, &group);
           gtk_tree_store_set(store, &tab, 0, _("Paths"), 1, (gpointer)PTAB_PATHS, -1);
         }
+        {
+          GtkTreeIter tab;
+          gtk_tree_store_append(store, &tab, &group);
+          gtk_tree_store_set(store, &tab, 0, _("Brush"), 1, (gpointer)PTAB_BRUSH, -1);
+        }
         {
           GtkTreeIter tab;
           gtk_tree_store_append(store, &tab, &group);
@@ -1816,11 +1829,18 @@ void PrefsDlg::BuildDialog ()
   g_list_free (combo_list);
 
 #ifdef ATIHACK_812
-       // ATI bugs
-       check = gtk_check_button_new_with_label (_("ATI cards with broken drivers - bug #802"));
-       gtk_widget_show(check);
-       gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
-       AddDialogData(check, &m_bGlATIHack, DLG_CHECK_BOOL);
+  // ATI bugs
+  check = gtk_check_button_new_with_label (_("ATI and Intel cards w/ buggy drivers (disappearing polygons)"));
+  gtk_widget_show(check);
+  gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
+  AddDialogData(check, &m_bGlATIHack, DLG_CHECK_BOOL);
+#endif
+
+#ifdef NVIDIA_AERO_HACK
+  check = gtk_check_button_new_with_label (_("NVIDIA/Aero bug - disable Windows composition"));
+  gtk_widget_show(check);
+  gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
+  AddDialogData(check, &m_bGlNvidiaAeroHack, DLG_CHECK_BOOL);
 #endif
 
   // Add the page to the notebook
@@ -2222,7 +2242,7 @@ void PrefsDlg::BuildDialog ()
 
 #ifdef _WIN32
   // win32 file dialog
-  check = gtk_check_button_new_with_label (_("Use win32 file load dialog"));
+  check = gtk_check_button_new_with_label (_("Use win32 file dialog (hacky)"));
   gtk_widget_show (check);
   // gtk_container_add (GTK_CONTAINER (vbox), check);
   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
@@ -2342,6 +2362,12 @@ void PrefsDlg::BuildDialog ()
   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
   AddDialogData (check, &m_bNoClamp, DLG_CHECK_BOOL);
 
+  // Snap to grid
+  check = gtk_check_button_new_with_label (_("Snap to grid"));
+  gtk_widget_show (check);
+  gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
+  AddDialogData (check, &m_bSnap, DLG_CHECK_BOOL);
+
   // Select patch by bounding box
   check = gtk_check_button_new_with_label (_("Select patches by bounding box"));
   gtk_widget_show (check);
@@ -2540,6 +2566,47 @@ void PrefsDlg::BuildDialog ()
   // Add the page to the notebook
   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
 
+  /******** Brush group ********/
+  preflabel = gtk_label_new(_("Brush"));
+  gtk_widget_show(preflabel);
+  pageframe = gtk_frame_new(_("Brush"));
+  gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5);
+  gtk_widget_show(pageframe);
+  vbox = gtk_vbox_new(FALSE, 5);
+  gtk_widget_show(vbox);
+  gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
+  gtk_container_add(GTK_CONTAINER(pageframe), vbox);
+
+  // default texture scale
+  // table
+  table = gtk_table_new(2, 1, FALSE); // I believe that the 2 and 1 are switched here, and this is
+                                      // intentional to be consistent with other calls to gtk_table_new()
+                                      // [that are probably also switched].
+  gtk_widget_show(table);
+  gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, TRUE, 0);
+  gtk_table_set_row_spacings(GTK_TABLE(table), 5);
+  gtk_table_set_col_spacings(GTK_TABLE(table), 5);
+
+  // label
+  label = gtk_label_new(_("Default texture scale:"));
+  gtk_widget_show(label);
+  gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
+  gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1,
+                   (GtkAttachOptions) (0),
+                   (GtkAttachOptions) (0), 0, 0);
+
+  // scale entry
+  entry = gtk_entry_new();
+  gtk_widget_show(entry);
+  gtk_widget_set_usize(GTK_WIDGET(entry), 60, -2);
+  gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 0, 1,
+                   (GtkAttachOptions) (GTK_FILL),
+                   (GtkAttachOptions) (0), 0, 0);
+  AddDialogData(entry, &m_fDefTextureScale, DLG_ENTRY_FLOAT);
+
+  // Add the page to the notebook
+  gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
+
   /******** Misc group *********/
   preflabel = gtk_label_new(_("Misc"));
   gtk_widget_show(preflabel);
@@ -2810,6 +2877,40 @@ void PrefsDlg::UpdateATIHack() {
 }
 #endif
 
+#ifdef NVIDIA_AERO_HACK
+void PrefsDlg::UpdateNvidiaAeroHack() {
+  if (m_bGlNvidiaAeroHack && m_bGlNvidiaAeroHackPrevState == 1) { return; }
+  if ((!m_bGlNvidiaAeroHack) && m_bGlNvidiaAeroHackPrevState == 0) { return; }
+  if ((!m_bGlNvidiaAeroHack) && m_bGlNvidiaAeroHackPrevState < 0) {
+    // The hack state is uninitialized, meaning that this is the first call
+    // to this function.  I prefer not to explicitly enable composition because
+    // the user may have set the application to disable it, and I don't want to
+    // override that.  Leave the state of composition as-is if the hack checkbox
+    // isn't checked.
+    m_bGlNvidiaAeroHackPrevState = 0;
+    return;
+  }
+  HMODULE lib = LoadLibrary("dwmapi.dll");
+  if (lib) {
+    void (WINAPI *qDwmEnableComposition) (bool bEnable) =
+      (void (WINAPI *) (bool bEnable)) GetProcAddress(lib, "DwmEnableComposition");
+    if (qDwmEnableComposition) {
+      if (m_bGlNvidiaAeroHack) {
+        Sys_Printf("Disabling Windows composition\n");
+        qDwmEnableComposition(0);
+        m_bGlNvidiaAeroHackPrevState = 1;
+      }
+      else {
+        Sys_Printf("Enabling Windows composition\n");
+        qDwmEnableComposition(1);
+        m_bGlNvidiaAeroHackPrevState = 0;
+      }
+    }
+    FreeLibrary(lib);
+  }
+}
+#endif
+
 // TTimo: m_strEnginePath has a special status, if not found in registry we need to
 // initiliaze it for sure. It is not totally failsafe but we can use the same
 // code than in q3map, expecting to find some "quake" above us. If not, we prompt
@@ -2912,6 +3013,7 @@ void PrefsDlg::LoadPrefs ()
   m_nShader = m_nLatchedShader;
 
   mLocalPrefs.GetPref(NOCLAMP_KEY,            &m_bNoClamp,                    FALSE);
+  mLocalPrefs.GetPref(SNAP_KEY,               &m_bSnap,                       TRUE);
   mLocalPrefs.GetPref(USERINI_KEY,            &m_strUserPath,                 "");
   mLocalPrefs.GetPref(ROTATION_KEY,           &m_nRotation,                   45);
   mLocalPrefs.GetPref(CHASEMOUSE_KEY,         &m_bChaseMouse,                 TRUE);
@@ -2960,6 +3062,7 @@ void PrefsDlg::LoadPrefs ()
   mLocalPrefs.GetPref(SELECTCURVES_KEY,       &m_bSelectCurves,               TRUE);
   mLocalPrefs.GetPref(SELECTMODELS_KEY,       &m_bSelectModels,               TRUE);
   mLocalPrefs.GetPref(SHADERLISTONLY_KEY,     &m_bTexturesShaderlistOnly,     FALSE);
+  mLocalPrefs.GetPref(DEFAULTTEXURESCALE_KEY, &m_fDefTextureScale,            g_pGameDescription->mTextureDefaultScale);
   mLocalPrefs.GetPref(SUBDIVISIONS_KEY,       &m_nSubdivisions,               SUBDIVISIONS_DEF);
   mLocalPrefs.GetPref(CLIPCAULK_KEY,          &m_bClipCaulk,                  FALSE);
   mLocalPrefs.GetPref(SNAPTTOGRID_KEY,        &m_bSnapTToGrid,                FALSE);
@@ -3088,6 +3191,10 @@ void PrefsDlg::LoadPrefs ()
        mLocalPrefs.GetPref(ATIHACK_KEY, &m_bGlATIHack, FALSE);
 #endif
 
+#ifdef NVIDIA_AERO_HACK
+  mLocalPrefs.GetPref(NVAEROHACK_KEY, &m_bGlNvidiaAeroHack, TRUE);
+#endif
+
   Undo_SetMaxSize(m_nUndoLevels); // set it internally as well / FIXME: why not just have one global value?
 
   UpdateTextureCompression();
@@ -3096,6 +3203,10 @@ void PrefsDlg::LoadPrefs ()
   UpdateATIHack();
 #endif
 
+#ifdef NVIDIA_AERO_HACK
+  UpdateNvidiaAeroHack();
+#endif
+
   if (mLocalPrefs.mbEmpty)
   {
     mLocalPrefs.mbEmpty = false;
@@ -3140,9 +3251,12 @@ void PrefsDlg::PostModal (int code)
     SavePrefs();
     // make sure the logfile is ok
     Sys_LogFile();
-    #ifdef ATIHACK_812
-      UpdateATIHack();
-    #endif
+#ifdef ATIHACK_812
+    UpdateATIHack();
+#endif
+#ifdef NVIDIA_AERO_HACK
+    UpdateNvidiaAeroHack();
+#endif
     if (g_pParentWnd)
       g_pParentWnd->SetGridStatus();
     Sys_UpdateWindows(W_ALL);
@@ -3226,14 +3340,14 @@ void CGameInstall::OnBtnBrowseEngine( GtkWidget *widget, gpointer data ) {
        Sys_Printf( "OnBtnBrowseEngine\n" );
 
        CGameInstall* i = static_cast<CGameInstall*>( data );
-       char *dir = dir_dialog( widget, _("Select game directory"), NULL );
+       char *dir = dir_dialog( i->m_pWidget, _("Select game directory"), NULL );
 
        i->UpdateData( TRUE );
 
        if ( dir != NULL ) {
                i->m_strEngine = dir;
                i->UpdateData( FALSE );
-               free( dir );
+               g_free( dir );
        }
 }
 
@@ -3292,6 +3406,12 @@ void CGameInstall::BuildDialog() {
                case GAME_TREMULOUS:
                        gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), _("Tremulous") );
                        break;
+               case GAME_JA:
+                       gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), _("Jedi Academy and mods") );
+                       break;
+               case GAME_REACTION:
+                       gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), _("Reaction Quake 3") );
+                       break;
                }
                iGame++;
        }
@@ -3353,6 +3473,9 @@ void CGameInstall::BuildDialog() {
 
 void CGameInstall::Run() {
        ScanGames();
+       if ( m_availGames[0] == GAME_NONE ) {
+               return;
+       }
        if ( DoModal() == IDCANCEL ) {
                Sys_Printf( "game dialog cancelled\n" );
                return;
@@ -3366,7 +3489,7 @@ void CGameInstall::Run() {
        gameFilePath += ".game";
        Sys_Printf( "game file: %s\n", gameFilePath.GetBuffer() );
 
-       FILE *fg = fopen( gameFilePath.GetBuffer(), "w" );
+       FILE * fg = fopen( gameFilePath.GetBuffer(), "w" );
        if ( fg == NULL ) {
                Error( "Failed to open %s for writing\n", gameFilePath.GetBuffer() );
        }
@@ -3375,7 +3498,7 @@ void CGameInstall::Run() {
        fprintf( fg, "  "ENGINEPATH_ATTRIBUTE"=\"%s\"\n", m_strEngine.GetBuffer() );
        switch ( m_availGames[ m_nComboSelect ] ) {
        case GAME_Q2: {
-               fprintf( fg, "  gametools=\"%sinstalls/Quake2Pack/game\"\n", g_strAppPath.GetBuffer() );
+               fprintf( fg, "  "TOOLS_ATTRIBUTE"=\"%sinstalls/Quake2Pack/game\"\n", g_strAppPath.GetBuffer() );
                fprintf( fg, "  prefix=\".quake2\"\n" );
                Str source = g_strAppPath.GetBuffer();
                source += "installs/";
@@ -3387,7 +3510,7 @@ void CGameInstall::Run() {
                break;
        }
        case GAME_Q3: {
-               fprintf( fg, "  gametools=\"%sinstalls/Q3Pack/game\"\n", g_strAppPath.GetBuffer() );
+               fprintf( fg, "  "TOOLS_ATTRIBUTE"=\"%sinstalls/Q3Pack/game\"\n", g_strAppPath.GetBuffer() );
                fprintf( fg, "  prefix=\".q3a\"\n" );
                Str source = g_strAppPath.GetBuffer();
                source += "installs/";
@@ -3399,7 +3522,7 @@ void CGameInstall::Run() {
                break;
        }
        case GAME_URT: {
-               fprintf( fg, "  gametools=\"%sinstalls/UrTPack/game\"\n", g_strAppPath.GetBuffer() );
+               fprintf( fg, "  "TOOLS_ATTRIBUTE"=\"%sinstalls/UrTPack/game\"\n", g_strAppPath.GetBuffer() );
                fprintf( fg, "  prefix=\".q3a\"\n" );
                Str source = g_strAppPath.GetBuffer();
                source += "installs/";
@@ -3411,7 +3534,7 @@ void CGameInstall::Run() {
                break;
        }
        case GAME_UFOAI: {
-               fprintf( fg, "  gametools=\"%sinstalls/UFOAIPack/game\"\n", g_strAppPath.GetBuffer() );
+               fprintf( fg, "  "TOOLS_ATTRIBUTE"=\"%sinstalls/UFOAIPack/game\"\n", g_strAppPath.GetBuffer() );
                fprintf( fg, "  prefix=\".ufoai\"\n" );
                Str source = g_strAppPath.GetBuffer();
                source += "installs/";
@@ -3423,7 +3546,7 @@ void CGameInstall::Run() {
                break;
        }
        case GAME_Q2W: {
-               fprintf( fg, "  gametools=\"%sinstalls/Q2WPack/game\"\n", g_strAppPath.GetBuffer() );
+               fprintf( fg, "  "TOOLS_ATTRIBUTE"=\"%sinstalls/Q2WPack/game\"\n", g_strAppPath.GetBuffer() );
                fprintf( fg, "  prefix=\".quake2world\"\n" );
                Str source = g_strAppPath.GetBuffer();
                source += "installs/";
@@ -3435,7 +3558,7 @@ void CGameInstall::Run() {
                break;
        }
        case GAME_WARSOW: {
-               fprintf( fg, "  gametools=\"%sinstalls/WarsowPack/game\"\n", g_strAppPath.GetBuffer() );
+               fprintf( fg, "  "TOOLS_ATTRIBUTE"=\"%sinstalls/WarsowPack/game\"\n", g_strAppPath.GetBuffer() );
                fprintf( fg, "  prefix=\".warsow\"\n" );
                Str source = g_strAppPath.GetBuffer();
                source += "installs/";
@@ -3447,7 +3570,7 @@ void CGameInstall::Run() {
                break;
        }
        case GAME_NEXUIZ: {
-               fprintf( fg, "  gametools=\"%sinstalls/NexuizPack/game\"\n", g_strAppPath.GetBuffer() );
+               fprintf( fg, "  "TOOLS_ATTRIBUTE"=\"%sinstalls/NexuizPack/game\"\n", g_strAppPath.GetBuffer() );
                fprintf( fg, "  prefix=\".nexuiz\"\n" );
                Str source = g_strAppPath.GetBuffer();
                source += "installs/";
@@ -3459,7 +3582,7 @@ void CGameInstall::Run() {
                break;
        }
        case GAME_TREMULOUS: {
-               fprintf( fg, "  gametools=\"%sinstalls/TremulousPack/game\"\n", g_strAppPath.GetBuffer() );
+               fprintf( fg, "  "TOOLS_ATTRIBUTE"=\"%sinstalls/TremulousPack/game\"\n", g_strAppPath.GetBuffer() );
                fprintf( fg, "  prefix=\".tremulous\"\n" );
                Str source = g_strAppPath.GetBuffer();
                source += "installs/";
@@ -3470,6 +3593,33 @@ void CGameInstall::Run() {
                fprintf( fg, "  basegame=\"base\"\n" );
                break;
        }
+       case GAME_JA: {
+               fprintf( fg, "  "TOOLS_ATTRIBUTE"=\"%sinstalls/JAPack/game\"\n", g_strAppPath.GetBuffer() );
+               fprintf( fg, "  prefix=\".ja\"\n" );
+               Str source = g_strAppPath.GetBuffer();
+               source += "installs/";
+               source += JA_PACK;
+               source += "/install/";
+               Str dest = m_strEngine.GetBuffer();
+               CopyTree( source.GetBuffer(), dest.GetBuffer() );
+               fprintf( fg, "  basegame=\"base\"\n" );
+               break;
+       }
+       case GAME_REACTION: {
+               fprintf( fg, "  "TOOLS_ATTRIBUTE"=\"%sinstalls/"REACTION_PACK"/game\"\n", g_strAppPath.GetBuffer() );
+               fprintf( fg, "  prefix=\".Reaction\"\n" );
+               Str source = g_strAppPath.GetBuffer();
+               source += "installs/";
+               source += REACTION_PACK;
+               source += "/install/";
+               Str dest = m_strEngine.GetBuffer();
+               CopyTree( source.GetBuffer(), dest.GetBuffer() );
+               fprintf( fg, "  basegame=\"Boomstick\"\n" );
+               fprintf( fg, "  default_scale=\"0.5\"\n" ); // Superfluous because the default is already 0.5,
+                                                       // but demonstrates how to set the default texture scale
+                                                       // for a specific game.
+               break;
+       }
        }
        fprintf( fg, "/>\n" );
        fclose( fg );
@@ -3513,6 +3663,14 @@ void CGameInstall::ScanGames() {
                if ( stricmp( dirname, TREMULOUS_PACK ) == 0 ) {
                        m_availGames[ iGame++ ] = GAME_TREMULOUS;
                }
+               if ( stricmp( dirname, JA_PACK ) == 0 ) {
+                       m_availGames[ iGame++ ] = GAME_JA;
+               }
+               if ( stricmp( dirname, REACTION_PACK ) == 0 ) {
+                       m_availGames[ iGame++ ] = GAME_REACTION;
+               }
        }
+       Sys_Printf("No installable games found in: %s\n",
+               pakPaths.GetBuffer() );
 }