diff --git a/docs/rh-log.txt b/docs/rh-log.txt
index 8c839701c..2bae0ae55 100644
--- a/docs/rh-log.txt
+++ b/docs/rh-log.txt
@@ -1,4 +1,24 @@
-August 4, 2009
+August 6, 2009
+- Fixed: M_QuitResponse() tried to play a sound even when none was specified
+  in the gameinfo.
+- Added Yes/No selections for Y/N messages so that you can answer them
+  entirely with a joystick.
+- Fixed: Starting the menu at the title screen with a key other than Escape
+  left the top level menu out of the menu stack.
+- Changed the save menu so that cancelling input of a new save name only
+  deactivates that control and does not completely close the menus.
+- Fixed "any key" messages to override input to menus hidden beneath them and
+  to work with joysticks.
+- Removed the input parameter from M_StartMessage and the corresponding
+  messageNeedsInput global, because it was redundant. Any messages that want
+  a Y/N response also supply a callback, and messages that don't care which
+  key you press don't supply a callback.
+- Changed MKEY_Back so that it cancels out of text entry fields before
+  backing to the previous menu, which it already did for the keyboard.
+- Changed the menu responder so that key downs always produce results,
+  regardless of whether or not an equivalent key is already down.
+
+August 4, 2009
 - Added the MF6_STEPMISSILE flag so that the Whirlwind can "walk" up steps.
 - Changed the dword definition of PalEntry to uint32 so that it has one
   consistent definition across all source files.
diff --git a/src/d_event.h b/src/d_event.h
index d5e6c8e10..513ea10b4 100644
--- a/src/d_event.h
+++ b/src/d_event.h
@@ -115,6 +115,7 @@ typedef enum
 
 // Called by IO functions when input is detected.
 void D_PostEvent (const event_t* ev);
+void D_RemoveNextCharEvent();
 
 
 //
diff --git a/src/d_main.cpp b/src/d_main.cpp
index 83141b0e0..f3224713e 100644
--- a/src/d_main.cpp
+++ b/src/d_main.cpp
@@ -241,6 +241,8 @@ void D_ProcessEvents (void)
 	for (; eventtail != eventhead ; eventtail = (eventtail+1)&(MAXEVENTS-1))
 	{
 		ev = &events[eventtail];
+		if (ev->type == EV_None)
+			continue;
 		if (ev->type == EV_DeviceChange)
 			UpdateJoystickMenu(I_UpdateDeviceList());
 		if (C_Responder (ev))
@@ -293,6 +295,41 @@ void D_PostEvent (const event_t *ev)
 	eventhead = (eventhead+1)&(MAXEVENTS-1);
 }
 
+//==========================================================================
+//
+// D_RemoveNextCharEvent
+//
+// Removes the next EV_GUI_Char event in the input queue. Used by the menu,
+// since it (generally) consumes EV_GUI_KeyDown events and not EV_GUI_Char
+// events, and it needs to ensure that there is no left over input when it's
+// done. If there are multiple EV_GUI_KeyDowns before the EV_GUI_Char, then
+// there are dead chars involved, so those should be removed, too. We do
+// this by changing the message type to EV_None rather than by actually
+// removing the event from the queue.
+// 
+//==========================================================================
+
+void D_RemoveNextCharEvent()
+{
+	assert(events[eventtail].type == EV_GUI_Event && events[eventtail].subtype == EV_GUI_KeyDown);
+	for (int evnum = eventtail; evnum != eventhead; evnum = (evnum+1) & (MAXEVENTS-1))
+	{
+		event_t *ev = &events[evnum];
+		if (ev->type != EV_GUI_Event)
+			break;
+		if (ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_Char)
+		{
+			ev->type = EV_None;
+			if (ev->subtype == EV_GUI_Char)
+				break;
+		}
+		else
+		{
+			break;
+		}
+	}
+}
+
 //==========================================================================
 //
 // CVAR dmflags
diff --git a/src/g_game.cpp b/src/g_game.cpp
index 47a93df71..44d8eb5cf 100644
--- a/src/g_game.cpp
+++ b/src/g_game.cpp
@@ -859,7 +859,7 @@ bool G_Responder (event_t *ev)
 				stricmp (cmd, "bumpgamma") &&
 				stricmp (cmd, "screenshot")))
 			{
-				M_StartControlPanel (true);
+				M_StartControlPanel (true, true);
 				return true;
 			}
 			else
diff --git a/src/m_menu.cpp b/src/m_menu.cpp
index 054885a4a..97335382d 100644
--- a/src/m_menu.cpp
+++ b/src/m_menu.cpp
@@ -172,7 +172,8 @@ void M_DrawFrame (int x, int y, int width, int height);
 static void M_DrawSaveLoadBorder (int x,int y, int len);
 static void M_DrawSaveLoadCommon ();
 static void M_SetupNextMenu (oldmenu_t *menudef);
-static void M_StartMessage (const char *string, void(*routine)(int), bool input);
+static void M_StartMessage (const char *string, void(*routine)(int));
+static void M_EndMessage (int key);
 
 // [RH] For player setup menu.
 	   void M_PlayerSetup ();
@@ -222,9 +223,9 @@ static FSaveGameNode *lastSaveSlot;	// Used for highlighting the most recently u
 static int 		messageToPrint;			// 1 = message to be printed
 static const char *messageString;		// ...and here is the message string!
 static EMenuState messageLastMenuActive;
-static bool		messageNeedsInput;		// timed message = no input from user
-static void	  (*messageRoutine)(int response);
+static void	  (*messageRoutine)(int response);	// Non-NULL if only Y/N should close message
 static int		showSharewareMessage;
+static int		messageSelection;		// 0 {Yes) or 1 (No) [if messageRoutine is non-NULL]
 
 static int 		genStringEnter;	// we are going to be entering a savegame string
 static size_t	genStringLen;	// [RH] Max # of chars that can be entered
@@ -606,8 +607,7 @@ static oldmenu_t SaveDef =
 // through console commands.
 CCMD (menu_main)
 {
-	M_StartControlPanel (true);
-	M_SetupNextMenu (TopLevelMenu);
+	M_StartControlPanel (true, true);
 }
 
 CCMD (menu_load)
@@ -1295,9 +1295,9 @@ void M_LoadGame (int choice)
 	if (netgame)
 	{
 		if(gameinfo.gametype == GAME_Chex)
-			M_StartMessage (GStrings("CLOADNET"), NULL, false);
+			M_StartMessage (GStrings("CLOADNET"), NULL);
 		else
-			M_StartMessage (GStrings("LOADNET"), NULL, false);
+			M_StartMessage (GStrings("LOADNET"), NULL);
 		return;
 	}
 		
@@ -1370,7 +1370,7 @@ void M_SaveGame (int choice)
 {
 	if (!usergame || (players[consoleplayer].health <= 0 && !multiplayer))
 	{
-		M_StartMessage (GStrings("SAVEDEAD"), NULL, false);
+		M_StartMessage (GStrings("SAVEDEAD"), NULL);
 		return;
 	}
 
@@ -1430,7 +1430,7 @@ void M_QuickSave ()
 	else
 		mysnprintf (tempstring, countof(tempstring), GStrings("QSPROMPT"), quickSaveSlot->Title);
 	strcpy (savegamestring, quickSaveSlot->Title);
-	M_StartMessage (tempstring, M_QuickSaveResponse, true);
+	M_StartMessage (tempstring, M_QuickSaveResponse);
 }
 
 
@@ -1453,9 +1453,9 @@ void M_QuickLoad ()
 	if (netgame)
 	{
 		if(gameinfo.gametype == GAME_Chex)
-			M_StartMessage (GStrings("CQLOADNET"), NULL, false);
+			M_StartMessage (GStrings("CQLOADNET"), NULL);
 		else
-			M_StartMessage (GStrings("QLOADNET"), NULL, false);
+			M_StartMessage (GStrings("QLOADNET"), NULL);
 		return;
 	}
 		
@@ -1471,7 +1471,7 @@ void M_QuickLoad ()
 		mysnprintf (tempstring, countof(tempstring), GStrings("CQLPROMPT"), quickSaveSlot->Title);
 	else
 		mysnprintf (tempstring, countof(tempstring), GStrings("QLPROMPT"), quickSaveSlot->Title);
-	M_StartMessage (tempstring, M_QuickLoadResponse, true);
+	M_StartMessage (tempstring, M_QuickLoadResponse);
 }
 
 //
@@ -1574,9 +1574,9 @@ void M_NewGame(int choice)
 	if (netgame && !demoplayback)
 	{
 		if(gameinfo.gametype == GAME_Chex)
-			M_StartMessage (GStrings("CNEWGAME"), NULL, false);
+			M_StartMessage (GStrings("CNEWGAME"), NULL);
 		else
-			M_StartMessage (GStrings("NEWGAME"), NULL, false);
+			M_StartMessage (GStrings("NEWGAME"), NULL);
 		return;
 	}
 
@@ -1794,7 +1794,7 @@ void M_ChooseSkill (int choice)
 		if (*msg==0) msg = GStrings("NIGHTMARE");
 		if (*msg=='$') msg = GStrings(msg+1);
 		confirmskill = choice;
-		M_StartMessage (msg, M_VerifyNightmare, true);
+		M_StartMessage (msg, M_VerifyNightmare);
 		return;
 	}
 
@@ -1813,12 +1813,12 @@ void M_Episode (int choice)
 	{
 		if (gameinfo.gametype == GAME_Doom)
 		{
-			M_StartMessage(GStrings("SWSTRING"),NULL,false);
+			M_StartMessage(GStrings("SWSTRING"), NULL);
 			//M_SetupNextMenu(&ReadDef);
 		}
 		else if (gameinfo.gametype == GAME_Chex)
 		{
-			M_StartMessage(GStrings("CSWSTRING"),NULL,false);
+			M_StartMessage(GStrings("CSWSTRING"), NULL);
 		}
 		else
 		{
@@ -1856,9 +1856,9 @@ static void SCClass (int option)
 	if (netgame)
 	{
 		if(gameinfo.gametype == GAME_Chex)
-			M_StartMessage (GStrings("CNEWGAME"), NULL, false);
+			M_StartMessage (GStrings("CNEWGAME"), NULL);
 		else
-			M_StartMessage (GStrings("NEWGAME"), NULL, false);
+			M_StartMessage (GStrings("NEWGAME"), NULL);
 		return;
 	}
 
@@ -1892,9 +1892,9 @@ static void M_ChooseClass (int choice)
 	if (netgame)
 	{
 		if(gameinfo.gametype == GAME_Chex)
-			M_StartMessage (GStrings("CNEWGAME"), NULL, false);
+			M_StartMessage (GStrings("CNEWGAME"), NULL);
 		else
-			M_StartMessage (GStrings("NEWGAME"), NULL, false);
+			M_StartMessage (GStrings("NEWGAME"), NULL);
 		return;
 	}
 
@@ -1953,16 +1953,16 @@ void M_EndGame(int choice)
 	if (netgame)
 	{
 		if(gameinfo.gametype == GAME_Chex)
-			M_StartMessage(GStrings("CNETEND"),NULL,false);
+			M_StartMessage(GStrings("CNETEND"), NULL);
 		else
-			M_StartMessage(GStrings("NETEND"),NULL,false);
+			M_StartMessage(GStrings("NETEND"), NULL);
 		return;
 	}
 
 	if(gameinfo.gametype == GAME_Chex)
-		M_StartMessage(GStrings("CENDGAME"),M_EndGameResponse,true);
+		M_StartMessage(GStrings("CENDGAME"), M_EndGameResponse);
 	else
-		M_StartMessage(GStrings("ENDGAME"),M_EndGameResponse,true);
+		M_StartMessage(GStrings("ENDGAME"), M_EndGameResponse);
 }
 
 
@@ -2005,7 +2005,7 @@ void M_QuitResponse(int ch)
 		return;
 	if (!netgame)
 	{
-		if (gameinfo.quitSound)
+		if (gameinfo.quitSound.IsNotEmpty())
 		{
 			S_Sound (CHAN_VOICE | CHAN_UI, gameinfo.quitSound, 1, ATTN_NONE);
 			I_WaitVBL (105);
@@ -2049,7 +2049,7 @@ void M_QuitGame (int choice)
 		EndString = GStrings("RAVENQUITMSG");
 	}
 
-	M_StartMessage (EndString, M_QuitResponse, true);
+	M_StartMessage (EndString, M_QuitResponse);
 }
 
 
@@ -2736,19 +2736,19 @@ static void M_SlidePlayerBlue (int choice)
 //
 //		Menu Functions
 //
-void M_StartMessage (const char *string, void (*routine)(int), bool input)
+void M_StartMessage (const char *string, void (*routine)(int))
 {
 	C_HideConsole ();
 	messageLastMenuActive = menuactive;
 	messageToPrint = 1;
 	messageString = string;
 	messageRoutine = routine;
-	messageNeedsInput = input;
+	messageSelection = 0;
 	if (menuactive == MENU_Off)
 	{
 		M_ActivateMenuInput ();
 	}
-	if (input)
+	if (messageRoutine != NULL)
 	{
 		S_StopSound (CHAN_VOICE);
 		S_Sound (CHAN_VOICE | CHAN_UI, "menu/prompt", 1, ATTN_NONE);
@@ -2756,6 +2756,22 @@ void M_StartMessage (const char *string, void (*routine)(int), bool input)
 	return;
 }
 
+void M_EndMessage(int key)
+{
+	menuactive = messageLastMenuActive;
+	messageToPrint = 0;
+	if (messageRoutine != NULL)
+	{
+		messageRoutine(key);
+	}
+	if (menuactive != MENU_Off)
+	{
+		M_DeactivateMenuInput();
+	}
+	SB_state = screen->GetPageCount();	// refresh the status bar
+	BorderNeedRefresh = screen->GetPageCount();
+	S_Sound(CHAN_VOICE | CHAN_UI, "menu/dismiss", 1, ATTN_NONE);
+}
 
 
 //
@@ -2803,8 +2819,7 @@ bool M_Responder (event_t *ev)
 		// Pop-up menu?
 		if (ev->data1 == KEY_ESCAPE)
 		{
-			M_StartControlPanel(true);
-			M_SetupNextMenu(TopLevelMenu);
+			M_StartControlPanel(true, true);
 			return true;
 		}
 		// If devparm is set, pressing F1 always takes a screenshot no matter
@@ -2900,6 +2915,15 @@ bool M_Responder (event_t *ev)
 		}
 		ch = ev->data1;
 		keyup = ev->subtype == EV_GUI_KeyUp;
+		if (messageToPrint && messageRoutine == NULL)
+		{
+			if (!keyup && !OptionsActive)
+			{
+				D_RemoveNextCharEvent();
+				M_EndMessage(ch);
+				return true;
+			}
+		}
 		switch (ch)
 		{
 		case GK_ESCAPE:			mkey = MKEY_Back;		break;
@@ -2923,37 +2947,13 @@ bool M_Responder (event_t *ev)
 				{
 					// Take care of any messages that need input
 					ch = tolower (ch);
-					if (messageNeedsInput)
+					assert(messageRoutine != NULL);
+					if (ch != ' ' && ch != 'n' && ch != 'y')
 					{
-						// For each printable keystroke, both EV_GUI_KeyDown and
-						// EV_GUI_Char will be generated, in that order. If we close
-						// the menu after the first event arrives and the fullscreen
-						// console is up, the console will get the EV_GUI_Char event
-						// next. Therefore, the message input should only respond to
-						// EV_GUI_Char events (sans Escape, which only generates
-						// EV_GUI_KeyDown.)
-						if (ev->subtype != EV_GUI_Char && ch != GK_ESCAPE)
-						{
-//							return false;
-						}
-						if (ch != ' ' && ch != 'n' && ch != 'y' && ch != GK_ESCAPE)
-						{
-							return false;
-						}
+						return false;
 					}
-
-					menuactive = messageLastMenuActive;
-					messageToPrint = 0;
-					if (messageRoutine)
-						messageRoutine (ch);
-
-					if (menuactive != MENU_Off)
-					{
-						M_DeactivateMenuInput();
-					}
-					SB_state = screen->GetPageCount();	// refresh the status bar
-					BorderNeedRefresh = screen->GetPageCount();
-					S_Sound(CHAN_VOICE | CHAN_UI, "menu/dismiss", 1, ATTN_NONE);
+					D_RemoveNextCharEvent();
+					M_EndMessage(ch);
 					return true;
 				}
 				else
@@ -3038,6 +3038,12 @@ bool M_Responder (event_t *ev)
 			mkey = MKEY_Right;
 			break;
 		}
+		// Any button press will work for messages without callbacks
+		if (!keyup && messageToPrint && messageRoutine == NULL)
+		{
+			M_EndMessage(ch);
+			return true;
+		}
 	}
 
 	if (mkey != NUM_MKEYS)
@@ -3048,14 +3054,12 @@ bool M_Responder (event_t *ev)
 		}
 		else
 		{
-			if (MenuButtons[mkey].PressKey(ch))
+			MenuButtons[mkey].PressKey(ch);
+			if (mkey <= MKEY_PageDown)
 			{
-				if (mkey <= MKEY_PageDown)
-				{
-					MenuButtonTickers[mkey] = KEY_REPEAT_DELAY;
-				}
-				M_ButtonHandler(mkey, false);
+				MenuButtonTickers[mkey] = KEY_REPEAT_DELAY;
 			}
+			M_ButtonHandler(mkey, false);
 		}
 	}
 
@@ -3077,10 +3081,35 @@ void M_ButtonHandler(EMenuKey key, bool repeat)
 	}
 	if (key == MKEY_Back)
 	{
-		// Save the cursor position on the current menu, and pop it off the stack
-		// to go back to the previous menu.
-		currentMenu->lastOn = itemOn;
-		M_PopMenuStack();
+		if (genStringEnter)
+		{
+			// Cancel string entry.
+			genStringEnter = 0;
+			genStringCancel();
+		}
+		else if (messageToPrint)
+		{
+			M_EndMessage(GK_ESCAPE);
+		}
+		else
+		{
+			// Save the cursor position on the current menu, and pop it off the stack
+			// to go back to the previous menu.
+			currentMenu->lastOn = itemOn;
+			M_PopMenuStack();
+		}
+		return;
+	}
+	if (messageToPrint)
+	{
+		if (key == MKEY_Down || key == MKEY_Up)
+		{
+			messageSelection ^= 1;
+		}
+		else if (key == MKEY_Enter)
+		{
+			M_EndMessage(messageSelection == 0 ? 'y' : 'n');
+		}
 		return;
 	}
 	if (currentMenu == &SaveDef || currentMenu == &LoadDef)
@@ -3244,7 +3273,7 @@ static bool M_SaveLoadResponder (event_t *ev)
 				EndString.Format("%s" TEXTCOLOR_WHITE "%s" TEXTCOLOR_NORMAL "?\n\n%s",
 					GStrings("MNU_DELETESG"), SelSaveGame->Title, GStrings("PRESSYN"));
 					
-				M_StartMessage (EndString, M_DeleteSaveResponse, true);
+				M_StartMessage (EndString, M_DeleteSaveResponse);
 			}
 			break;
 
@@ -3279,12 +3308,16 @@ static void M_LoadSelect (const FSaveGameNode *file)
 //
 // User wants to save. Start string input for M_Responder
 //
+static void M_CancelSaveName ()
+{
+}
+
 static void M_SaveSelect (const FSaveGameNode *file)
 {
 	// we are going to be intercepting all chars
 	genStringEnter = 1;
 	genStringEnd = M_DoSave;
-	genStringCancel = M_ClearMenus;
+	genStringCancel = M_CancelSaveName;
 	genStringLen = SAVESTRINGSIZE-1;
 
 	if (file != &NewSaveNode)
@@ -3323,7 +3356,7 @@ static void M_DeleteSaveResponse (int choice)
 //
 // M_StartControlPanel
 //
-void M_StartControlPanel (bool makeSound)
+void M_StartControlPanel (bool makeSound, bool wantTop)
 {
 	// intro might call this repeatedly
 	if (menuactive == MENU_On)
@@ -3331,12 +3364,20 @@ void M_StartControlPanel (bool makeSound)
 
 	for (int i = 0; i < NUM_MKEYS; ++i)
 	{
-		MenuButtons[i].ResetTriggers();
+		MenuButtons[i].ReleaseKey(0);
 	}
 	drawSkull = true;
 	MenuStackDepth = 0;
-	currentMenu = TopLevelMenu;
-	itemOn = currentMenu->lastOn;
+	if (wantTop)
+	{
+		M_SetupNextMenu(TopLevelMenu);
+	}
+	else
+	{
+		// Just a default. The caller ought to call M_SetupNextMenu() next.
+		currentMenu = TopLevelMenu;
+		itemOn = currentMenu->lastOn;
+	}
 	C_HideConsole ();				// [RH] Make sure console goes bye bye.
 	OptionsActive = false;			// [RH] Make sure none of the options menus appear.
 	M_ActivateMenuInput ();
@@ -3373,6 +3414,7 @@ void M_Drawer ()
 	// Horiz. & Vertically center string and print it.
 	if (messageToPrint)
 	{
+		int fontheight = SmallFont->GetHeight();
 		screen->Dim (fade);
 		BorderNeedRefresh = screen->GetPageCount ();
 		SB_state = screen->GetPageCount ();
@@ -3387,10 +3429,19 @@ void M_Drawer ()
 		{
 			screen->DrawText (SmallFont, CR_UNTRANSLATED, 160 - lines[i].Width/2, y, lines[i].Text,
 				DTA_Clean, true, TAG_DONE);
-			y += SmallFont->GetHeight ();
+			y += fontheight;
 		}
-
 		V_FreeBrokenLines (lines);
+		if (messageRoutine != NULL)
+		{
+			y += fontheight;
+			screen->DrawText(SmallFont, CR_UNTRANSLATED, 160, y, GStrings["TXT_YES"], DTA_Clean, true, TAG_DONE);
+			screen->DrawText(SmallFont, CR_UNTRANSLATED, 160, y + fontheight + 1, GStrings["TXT_NO"], DTA_Clean, true, TAG_DONE);
+			if (skullAnimCounter < 6)
+			{
+				M_DrawConText(CR_RED, 150, y + (fontheight + 1) * messageSelection, "\xd");
+			}
+		}
 	}
 	else if (menuactive != MENU_Off)
 	{
diff --git a/src/m_menu.h b/src/m_menu.h
index ff899511d..ce7ba99e2 100644
--- a/src/m_menu.h
+++ b/src/m_menu.h
@@ -52,7 +52,7 @@ void M_Deinit ();
 
 // Called by intro code to force menu up upon a keypress,
 // does nothing if menu is already up.
-void M_StartControlPanel (bool makeSound);
+void M_StartControlPanel (bool makeSound, bool wantTop=false);
 
 // Turns off the menu
 void M_ClearMenus ();
@@ -257,6 +257,7 @@ enum EMenuKey
 
 void M_ButtonHandler(EMenuKey key, bool repeat);
 void M_OptButtonHandler(EMenuKey key, bool repeat);
+void M_DrawConText (int color, int x, int y, const char *str);
 
 extern value_t YesNo[2];
 extern value_t NoYes[2];
diff --git a/src/m_options.cpp b/src/m_options.cpp
index 0241074c8..1f127ff26 100644
--- a/src/m_options.cpp
+++ b/src/m_options.cpp
@@ -1480,7 +1480,7 @@ CCMD (sizeup)
 
 // Draws a string in the console font, scaled to the 8x8 cells
 // used by the default console font.
-static void M_DrawConText (int color, int x, int y, const char *str)
+void M_DrawConText (int color, int x, int y, const char *str)
 {
 	int len = (int)strlen(str);
 
diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp
index e9b4c375e..0a09e69a0 100644
--- a/src/sound/fmodsound.cpp
+++ b/src/sound/fmodsound.cpp
@@ -772,7 +772,7 @@ bool FMODSoundRenderer::Init()
 	if (result == FMOD_OK)
 	{
 		// On Linux, FMOD defaults to OSS. If OSS is not present, it doesn't
-		// try ALSA, it just fails. We'll try for it, but only if OSS wasn't
+		// try ALSA; it just fails. We'll try for it, but only if OSS wasn't
 		// explicitly specified for snd_output.
 		if (driver == 0 && eval == FMOD_OUTPUTTYPE_AUTODETECT)
 		{
diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu
index dfe23836d..49a17d312 100644
--- a/wadsrc/static/language.enu
+++ b/wadsrc/static/language.enu
@@ -8,6 +8,8 @@ PRESSKEY = "press a key.";
 PRESSYN = "press y or n.";
 
 QUITMSG = "are you sure you want to\nquit this great game?";
+TXT_YES = "Yes";
+TXT_NO = "No";
 
 // Quit Doom 1 messages
 QUITMSG1 = "please don't leave, there's more\ndemons to toast!";
diff --git a/wadsrc/static/language.fr b/wadsrc/static/language.fr
index 6b2d41b87..1f06dd49b 100644
--- a/wadsrc/static/language.fr
+++ b/wadsrc/static/language.fr
@@ -13,6 +13,8 @@ D_CDROM = "VERSION CD-ROM: DEFAULT.CFG DANS C:\\DOOMDATA\n";
 PRESSKEY = "APPUYEZ SUR UNE TOUCHE.";
 PRESSYN = "APPUYEZ SUR Y OU N";
 QUITMSG = "VOUS VOULEZ VRAIMENT\nQUITTER CE SUPER JEU?";
+TXT_YES = "Oui";
+TXT_NO = "Non";
 
 // QuitDoom1 messages
 QUITMSG1 = "ne partez pas,Il ya encore\ndes d�mons a griller!";
diff --git a/wadsrc/static/language.ita b/wadsrc/static/language.ita
index 4bd8236ec..b284a2e41 100644
--- a/wadsrc/static/language.ita
+++ b/wadsrc/static/language.ita
@@ -10,6 +10,8 @@ PRESSKEY = "premi un tasto.";
 PRESSYN = "premi y oppure n.";
 
 QUITMSG = "Sei sicuro di volere uscire\nda questo grandioso gioco?";
+TXT_YES = "Si";
+TXT_NO = "No";
 
 // QuitDoom1 messages
 QUITMSG1 = "per favore non uscire, ci sono altri\ndemoni da ammazzare!";