- Fixed: M_CreateMenus() is too soon to call UpdateJoystickMenu(). It needs to happen after

I_InitInput(), which happens during V_Init2().

SVN r3501 (trunk)
This commit is contained in:
Randy Heit 2012-04-01 03:03:53 +00:00
parent 19ec79d4f3
commit 6ea93d28e2
3 changed files with 379 additions and 379 deletions

View file

@ -2328,6 +2328,7 @@ void D_DoomMain (void)
} }
V_Init2(); V_Init2();
UpdateJoystickMenu(NULL);
v = Args->CheckValue ("-loadgame"); v = Args->CheckValue ("-loadgame");
if (v) if (v)

View file

@ -1224,7 +1224,6 @@ void M_CreateMenus()
BuildPlayerclassMenu(); BuildPlayerclassMenu();
InitCrosshairsList(); InitCrosshairsList();
InitKeySections(); InitKeySections();
UpdateJoystickMenu(NULL);
FOptionValues **opt = OptionValues.CheckKey(NAME_Mididevices); FOptionValues **opt = OptionValues.CheckKey(NAME_Mididevices);
if (opt != NULL) if (opt != NULL)

View file

@ -1,379 +1,379 @@
/* /*
** i_main.cpp ** i_main.cpp
** System-specific startup code. Eventually calls D_DoomMain. ** System-specific startup code. Eventually calls D_DoomMain.
** **
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
** Copyright 1998-2007 Randy Heit ** Copyright 1998-2007 Randy Heit
** All rights reserved. ** All rights reserved.
** **
** Redistribution and use in source and binary forms, with or without ** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions ** modification, are permitted provided that the following conditions
** are met: ** are met:
** **
** 1. Redistributions of source code must retain the above copyright ** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer. ** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright ** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the ** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution. ** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products ** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission. ** derived from this software without specific prior written permission.
** **
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
** **
*/ */
// HEADER FILES ------------------------------------------------------------ // HEADER FILES ------------------------------------------------------------
#include <SDL.h> #include <SDL.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <signal.h> #include <signal.h>
#include <new> #include <new>
#include <sys/param.h> #include <sys/param.h>
#ifndef NO_GTK #ifndef NO_GTK
#include <gtk/gtk.h> #include <gtk/gtk.h>
#endif #endif
#include <locale.h> #include <locale.h>
#if defined(__MACH__) && !defined(NOASM) #if defined(__MACH__) && !defined(NOASM)
#include <sys/types.h> #include <sys/types.h>
#include <sys/mman.h> #include <sys/mman.h>
#endif #endif
#include "doomerrors.h" #include "doomerrors.h"
#include "m_argv.h" #include "m_argv.h"
#include "d_main.h" #include "d_main.h"
#include "i_system.h" #include "i_system.h"
#include "i_video.h" #include "i_video.h"
#include "c_console.h" #include "c_console.h"
#include "errors.h" #include "errors.h"
#include "version.h" #include "version.h"
#include "w_wad.h" #include "w_wad.h"
#include "g_level.h" #include "g_level.h"
#include "r_state.h" #include "r_state.h"
#include "cmdlib.h" #include "cmdlib.h"
#include "r_utility.h" #include "r_utility.h"
#include "doomstat.h" #include "doomstat.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
// The maximum number of functions that can be registered with atterm. // The maximum number of functions that can be registered with atterm.
#define MAX_TERMS 64 #define MAX_TERMS 64
// TYPES ------------------------------------------------------------------- // TYPES -------------------------------------------------------------------
// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
extern "C" int cc_install_handlers(int, char**, int, int*, const char*, int(*)(char*, char*)); extern "C" int cc_install_handlers(int, char**, int, int*, const char*, int(*)(char*, char*));
// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
// EXTERNAL DATA DECLARATIONS ---------------------------------------------- // EXTERNAL DATA DECLARATIONS ----------------------------------------------
#ifdef USE_XCURSOR #ifdef USE_XCURSOR
extern bool UseXCursor; extern bool UseXCursor;
#endif #endif
// PUBLIC DATA DEFINITIONS ------------------------------------------------- // PUBLIC DATA DEFINITIONS -------------------------------------------------
#ifndef NO_GTK #ifndef NO_GTK
bool GtkAvailable; bool GtkAvailable;
#endif #endif
// The command line arguments. // The command line arguments.
DArgs *Args; DArgs *Args;
// PRIVATE DATA DEFINITIONS ------------------------------------------------ // PRIVATE DATA DEFINITIONS ------------------------------------------------
static void (*TermFuncs[MAX_TERMS]) (); static void (*TermFuncs[MAX_TERMS]) ();
static const char *TermNames[MAX_TERMS]; static const char *TermNames[MAX_TERMS];
static int NumTerms; static int NumTerms;
// CODE -------------------------------------------------------------------- // CODE --------------------------------------------------------------------
void addterm (void (*func) (), const char *name) void addterm (void (*func) (), const char *name)
{ {
// Make sure this function wasn't already registered. // Make sure this function wasn't already registered.
for (int i = 0; i < NumTerms; ++i) for (int i = 0; i < NumTerms; ++i)
{ {
if (TermFuncs[i] == func) if (TermFuncs[i] == func)
{ {
return; return;
} }
} }
if (NumTerms == MAX_TERMS) if (NumTerms == MAX_TERMS)
{ {
func (); func ();
I_FatalError ( I_FatalError (
"Too many exit functions registered.\n" "Too many exit functions registered.\n"
"Increase MAX_TERMS in i_main.cpp"); "Increase MAX_TERMS in i_main.cpp");
} }
TermNames[NumTerms] = name; TermNames[NumTerms] = name;
TermFuncs[NumTerms++] = func; TermFuncs[NumTerms++] = func;
} }
void popterm () void popterm ()
{ {
if (NumTerms) if (NumTerms)
NumTerms--; NumTerms--;
} }
void STACK_ARGS call_terms () void STACK_ARGS call_terms ()
{ {
while (NumTerms > 0) while (NumTerms > 0)
{ {
// printf ("term %d - %s\n", NumTerms, TermNames[NumTerms-1]); // printf ("term %d - %s\n", NumTerms, TermNames[NumTerms-1]);
TermFuncs[--NumTerms] (); TermFuncs[--NumTerms] ();
} }
} }
//========================================================================== //==========================================================================
// //
// FinalGC // FinalGC
// //
// Collect garbage one last time before exiting. // Collect garbage one last time before exiting.
// //
//========================================================================== //==========================================================================
static void FinalGC() static void FinalGC()
{ {
Args = NULL; Args = NULL;
GC::FullGC(); GC::FullGC();
} }
static void STACK_ARGS NewFailure () static void STACK_ARGS NewFailure ()
{ {
I_FatalError ("Failed to allocate memory from system heap"); I_FatalError ("Failed to allocate memory from system heap");
} }
static int DoomSpecificInfo (char *buffer, char *end) static int DoomSpecificInfo (char *buffer, char *end)
{ {
const char *arg; const char *arg;
int size = end-buffer-2; int size = end-buffer-2;
int i, p; int i, p;
p = 0; p = 0;
p += snprintf (buffer+p, size-p, GAMENAME" version " DOTVERSIONSTR " (" __DATE__ ")\n"); p += snprintf (buffer+p, size-p, GAMENAME" version " DOTVERSIONSTR " (" __DATE__ ")\n");
#ifdef __VERSION__ #ifdef __VERSION__
p += snprintf (buffer+p, size-p, "Compiler version: %s\n", __VERSION__); p += snprintf (buffer+p, size-p, "Compiler version: %s\n", __VERSION__);
#endif #endif
p += snprintf (buffer+p, size-p, "\nCommand line:"); p += snprintf (buffer+p, size-p, "\nCommand line:");
for (i = 0; i < Args->NumArgs(); ++i) for (i = 0; i < Args->NumArgs(); ++i)
{ {
p += snprintf (buffer+p, size-p, " %s", Args->GetArg(i)); p += snprintf (buffer+p, size-p, " %s", Args->GetArg(i));
} }
p += snprintf (buffer+p, size-p, "\n"); p += snprintf (buffer+p, size-p, "\n");
for (i = 0; (arg = Wads.GetWadName (i)) != NULL; ++i) for (i = 0; (arg = Wads.GetWadName (i)) != NULL; ++i)
{ {
p += snprintf (buffer+p, size-p, "\nWad %d: %s", i, arg); p += snprintf (buffer+p, size-p, "\nWad %d: %s", i, arg);
} }
if (gamestate != GS_LEVEL && gamestate != GS_TITLELEVEL) if (gamestate != GS_LEVEL && gamestate != GS_TITLELEVEL)
{ {
p += snprintf (buffer+p, size-p, "\n\nNot in a level."); p += snprintf (buffer+p, size-p, "\n\nNot in a level.");
} }
else else
{ {
char name[9]; char name[9];
strncpy (name, level.mapname, 8); strncpy (name, level.mapname, 8);
name[8] = 0; name[8] = 0;
p += snprintf (buffer+p, size-p, "\n\nCurrent map: %s", name); p += snprintf (buffer+p, size-p, "\n\nCurrent map: %s", name);
if (!viewactive) if (!viewactive)
{ {
p += snprintf (buffer+p, size-p, "\n\nView not active."); p += snprintf (buffer+p, size-p, "\n\nView not active.");
} }
else else
{ {
p += snprintf (buffer+p, size-p, "\n\nviewx = %d", (int)viewx); p += snprintf (buffer+p, size-p, "\n\nviewx = %d", (int)viewx);
p += snprintf (buffer+p, size-p, "\nviewy = %d", (int)viewy); p += snprintf (buffer+p, size-p, "\nviewy = %d", (int)viewy);
p += snprintf (buffer+p, size-p, "\nviewz = %d", (int)viewz); p += snprintf (buffer+p, size-p, "\nviewz = %d", (int)viewz);
p += snprintf (buffer+p, size-p, "\nviewangle = %x", (unsigned int)viewangle); p += snprintf (buffer+p, size-p, "\nviewangle = %x", (unsigned int)viewangle);
} }
} }
buffer[p++] = '\n'; buffer[p++] = '\n';
buffer[p++] = '\0'; buffer[p++] = '\0';
return p; return p;
} }
#if defined(__MACH__) && !defined(NOASM) #if defined(__MACH__) && !defined(NOASM)
// NASM won't let us create custom sections for Mach-O. Whether that's a limitation of NASM // NASM won't let us create custom sections for Mach-O. Whether that's a limitation of NASM
// or of Mach-O, I don't know, but since we're using NASM for the assembly, it doesn't much // or of Mach-O, I don't know, but since we're using NASM for the assembly, it doesn't much
// matter. // matter.
extern "C" extern "C"
{ {
extern void *rtext_a_start, *rtext_a_end; extern void *rtext_a_start, *rtext_a_end;
extern void *rtext_tmap_start, *rtext_tmap_end; extern void *rtext_tmap_start, *rtext_tmap_end;
extern void *rtext_tmap2_start, *rtext_tmap2_end; extern void *rtext_tmap2_start, *rtext_tmap2_end;
extern void *rtext_tmap3_start, *rtext_tmap3_end; extern void *rtext_tmap3_start, *rtext_tmap3_end;
}; };
static void unprotect_pages(long pagesize, void *start, void *end) static void unprotect_pages(long pagesize, void *start, void *end)
{ {
char *page = (char *)((intptr_t)start & ~(pagesize - 1)); char *page = (char *)((intptr_t)start & ~(pagesize - 1));
size_t len = (char *)end - (char *)start; size_t len = (char *)end - (char *)start;
if (mprotect(page, len, PROT_READ|PROT_WRITE|PROT_EXEC) != 0) if (mprotect(page, len, PROT_READ|PROT_WRITE|PROT_EXEC) != 0)
{ {
fprintf(stderr, "mprotect failed\n"); fprintf(stderr, "mprotect failed\n");
exit(1); exit(1);
} }
} }
static void unprotect_rtext() static void unprotect_rtext()
{ {
static void *const pages[] = static void *const pages[] =
{ {
rtext_a_start, rtext_a_end, rtext_a_start, rtext_a_end,
rtext_tmap_start, rtext_tmap_end, rtext_tmap_start, rtext_tmap_end,
rtext_tmap2_start, rtext_tmap2_end, rtext_tmap2_start, rtext_tmap2_end,
rtext_tmap3_start, rtext_tmap3_end rtext_tmap3_start, rtext_tmap3_end
}; };
long pagesize = sysconf(_SC_PAGESIZE); long pagesize = sysconf(_SC_PAGESIZE);
for (void *const *p = pages; p < &pages[countof(pages)]; p += 2) for (void *const *p = pages; p < &pages[countof(pages)]; p += 2)
{ {
unprotect_pages(pagesize, p[0], p[1]); unprotect_pages(pagesize, p[0], p[1]);
} }
} }
#endif #endif
void I_StartupJoysticks(); void I_StartupJoysticks();
void I_ShutdownJoysticks(); void I_ShutdownJoysticks();
int main (int argc, char **argv) int main (int argc, char **argv)
{ {
#if !defined (__APPLE__) #if !defined (__APPLE__)
{ {
int s[4] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS }; int s[4] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS };
cc_install_handlers(argc, argv, 4, s, "zdoom-crash.log", DoomSpecificInfo); cc_install_handlers(argc, argv, 4, s, "zdoom-crash.log", DoomSpecificInfo);
} }
#endif // !__APPLE__ #endif // !__APPLE__
printf(GAMENAME" v%s - SVN revision %s - SDL version\nCompiled on %s\n", printf(GAMENAME" v%s - SVN revision %s - SDL version\nCompiled on %s\n",
DOTVERSIONSTR_NOREV,SVN_REVISION_STRING,__DATE__); DOTVERSIONSTR_NOREV,SVN_REVISION_STRING,__DATE__);
seteuid (getuid ()); seteuid (getuid ());
std::set_new_handler (NewFailure); std::set_new_handler (NewFailure);
#if defined(__MACH__) && !defined(NOASM) #if defined(__MACH__) && !defined(NOASM)
unprotect_rtext(); unprotect_rtext();
#endif #endif
#ifndef NO_GTK #ifndef NO_GTK
GtkAvailable = gtk_init_check (&argc, &argv); GtkAvailable = gtk_init_check (&argc, &argv);
#endif #endif
setlocale (LC_ALL, "C"); setlocale (LC_ALL, "C");
if (SDL_Init (SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_NOPARACHUTE|SDL_INIT_JOYSTICK) == -1) if (SDL_Init (SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_NOPARACHUTE|SDL_INIT_JOYSTICK) == -1)
{ {
fprintf (stderr, "Could not initialize SDL:\n%s\n", SDL_GetError()); fprintf (stderr, "Could not initialize SDL:\n%s\n", SDL_GetError());
return -1; return -1;
} }
atterm (SDL_Quit); atterm (SDL_Quit);
{ {
char viddriver[80]; char viddriver[80];
if (SDL_VideoDriverName(viddriver, sizeof(viddriver)) != NULL) if (SDL_VideoDriverName(viddriver, sizeof(viddriver)) != NULL)
{ {
printf("Using video driver %s\n", viddriver); printf("Using video driver %s\n", viddriver);
#ifdef USE_XCURSOR #ifdef USE_XCURSOR
UseXCursor = (strcmp(viddriver, "x11") == 0); UseXCursor = (strcmp(viddriver, "x11") == 0);
#endif #endif
} }
printf("\n"); printf("\n");
} }
SDL_WM_SetCaption (GAMESIG " " DOTVERSIONSTR " (" __DATE__ ")", NULL); SDL_WM_SetCaption (GAMESIG " " DOTVERSIONSTR " (" __DATE__ ")", NULL);
#ifdef __APPLE__ #ifdef __APPLE__
const SDL_VideoInfo* videoInfo = SDL_GetVideoInfo(); const SDL_VideoInfo* videoInfo = SDL_GetVideoInfo();
if ( NULL != videoInfo ) if ( NULL != videoInfo )
{ {
EXTERN_CVAR( Int, vid_defwidth ) EXTERN_CVAR( Int, vid_defwidth )
EXTERN_CVAR( Int, vid_defheight ) EXTERN_CVAR( Int, vid_defheight )
EXTERN_CVAR( Int, vid_defbits ) EXTERN_CVAR( Int, vid_defbits )
EXTERN_CVAR( Bool, vid_vsync ) EXTERN_CVAR( Bool, vid_vsync )
EXTERN_CVAR( Bool, fullscreen ) EXTERN_CVAR( Bool, fullscreen )
vid_defwidth = videoInfo->current_w; vid_defwidth = videoInfo->current_w;
vid_defheight = videoInfo->current_h; vid_defheight = videoInfo->current_h;
vid_defbits = videoInfo->vfmt->BitsPerPixel; vid_defbits = videoInfo->vfmt->BitsPerPixel;
vid_vsync = True; vid_vsync = True;
fullscreen = True; fullscreen = True;
} }
#endif // __APPLE__ #endif // __APPLE__
try try
{ {
Args = new DArgs(argc, argv); Args = new DArgs(argc, argv);
atterm(FinalGC); atterm(FinalGC);
/* /*
killough 1/98: killough 1/98:
This fixes some problems with exit handling This fixes some problems with exit handling
during abnormal situations. during abnormal situations.
The old code called I_Quit() to end program, The old code called I_Quit() to end program,
while now I_Quit() is installed as an exit while now I_Quit() is installed as an exit
handler and exit() is called to exit, either handler and exit() is called to exit, either
normally or abnormally. Seg faults are caught normally or abnormally. Seg faults are caught
and the error handler is used, to prevent and the error handler is used, to prevent
being left in graphics mode or having very being left in graphics mode or having very
loud SFX noise because the sound card is loud SFX noise because the sound card is
left in an unstable state. left in an unstable state.
*/ */
atexit (call_terms); atexit (call_terms);
atterm (I_Quit); atterm (I_Quit);
// Should we even be doing anything with progdir on Unix systems? // Should we even be doing anything with progdir on Unix systems?
char program[PATH_MAX]; char program[PATH_MAX];
if (realpath (argv[0], program) == NULL) if (realpath (argv[0], program) == NULL)
strcpy (program, argv[0]); strcpy (program, argv[0]);
char *slash = strrchr (program, '/'); char *slash = strrchr (program, '/');
if (slash != NULL) if (slash != NULL)
{ {
*(slash + 1) = '\0'; *(slash + 1) = '\0';
progdir = program; progdir = program;
} }
else else
{ {
progdir = "./"; progdir = "./";
} }
I_StartupJoysticks(); I_StartupJoysticks();
C_InitConsole (80*8, 25*8, false); C_InitConsole (80*8, 25*8, false);
D_DoomMain (); D_DoomMain ();
} }
catch (class CDoomError &error) catch (class CDoomError &error)
{ {
I_ShutdownJoysticks(); I_ShutdownJoysticks();
if (error.GetMessage ()) if (error.GetMessage ())
fprintf (stderr, "%s\n", error.GetMessage ()); fprintf (stderr, "%s\n", error.GetMessage ());
exit (-1); exit (-1);
} }
catch (...) catch (...)
{ {
call_terms (); call_terms ();
throw; throw;
} }
return 0; return 0;
} }