From eb65e0122b86c10ee306817fa68dea6b3cc5cde7 Mon Sep 17 00:00:00 2001
From: adelikat <adelikat@users.sf.net>
Date: Sun, 23 Nov 2008 21:28:22 +0000
Subject: [PATCH] Movie subtitle system installed

---
 changelog.txt              |  1 +
 src/drivers/win/replay.cpp | 50 +++++++++++++++++++++++++++++++++++
 src/fceu.cpp               |  1 +
 src/movie.cpp              | 54 +++++++++++++++++++++++++++++++++++---
 src/movie.h                |  7 +++++
 5 files changed, 110 insertions(+), 3 deletions(-)

diff --git a/changelog.txt b/changelog.txt
index d1cad559..9d257da3 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,4 +1,5 @@
 ---version 2.0.4 yet to be released---
+23-nov-2008 - adelikat - movie subtitle system installed
 22-nov-2008 - adelikat - win32 - added help menu item to TASEdit and Hex Editor, Minor TASEdit clean up
 22-nov-2008 - adelikat - win32 - fixed so that turbo works with VBlank sync settings
 21-nov-2008 - qfox - Lua - added joypad.write and joypad.get for naming consistency. Added plane display toggle for lua: FCEU.fceu_setrenderplanes(sprites, background) which accepts two boolean args and toggles the drawing of those planes from Lua. Changed movie.framecount() to always return a number, even when no movie is playing. Should return the same number as in view; the number of frames since last reset, if no movie is playing.
diff --git a/src/drivers/win/replay.cpp b/src/drivers/win/replay.cpp
index 268e15cf..cf398691 100644
--- a/src/drivers/win/replay.cpp
+++ b/src/drivers/win/replay.cpp
@@ -14,6 +14,9 @@ static bool stopframeWasEditedByUser = false;
 //the comments contained in the currently-displayed movie
 static std::vector<std::wstring> currComments;
 
+//the subtitles contained in the currently-displayed movie
+static std::vector<std::string> currSubtitles;
+
 extern FCEUGI *GameInfo;
 
 //retains the state of the readonly checkbox and stopframe value
@@ -219,6 +222,7 @@ void UpdateReplayDialog(HWND hwndDlg)
 			EnableWindow(GetDlgItem(hwndDlg,IDOK),TRUE);  
 			EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON_METADATA),TRUE);
 			currComments = info.comments;
+			currSubtitles = info.subtitles;
 
 			doClear = 0;
 		}
@@ -311,6 +315,50 @@ BOOL CALLBACK ReplayMetadataDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, L
 			lvc.cx = listRect.right - 100;
 			ListView_InsertColumn(hwndList, colidx++, &lvc);
 
+						
+			//Display the Subtitles into the Metadata as well
+			for(uint32 i=0;i<currSubtitles.size();i++)
+			{
+				std::string& subtitle = currSubtitles[i];
+				size_t splitat = subtitle.find_first_of(' ');
+				std::wstring key, value;
+				//if we can't split it then call it an unnamed key
+				if(splitat == std::string::npos)
+				{
+					value = mbstowcs(subtitle);
+				} else
+				{
+					key = mbstowcs(subtitle.substr(0,splitat));
+					value = mbstowcs(subtitle.substr(splitat+1));
+				}
+
+				LVITEM lvi;
+				lvi.iItem = i;
+				lvi.mask = LVIF_TEXT;
+				lvi.iSubItem = 0;
+				lvi.pszText = (LPSTR)key.c_str();
+				SendMessageW(hwndList, LVM_INSERTITEMW, 0, (LPARAM)&lvi);
+				
+				lvi.iSubItem = 1;
+				lvi.pszText = (LPSTR)value.c_str();
+				SendMessageW(hwndList, LVM_SETITEMTEXTW, i, (LPARAM)&lvi);
+			}
+			
+			//Display Subtitle Heading
+			if (currSubtitles.size() > 0)	//If no subtitles, don't bother with this heading
+			{
+			string Heading = "SUBTITLES";
+			std::wstring& rHeading = mbstowcs(Heading);
+						
+			LVITEM lvSubtitle;
+				lvSubtitle.iItem = 0;
+				lvSubtitle.mask = LVIF_TEXT;
+				lvSubtitle.iSubItem = 0;
+				lvSubtitle.pszText = (LPSTR)rHeading.c_str();
+				SendMessageW(hwndList, LVM_INSERTITEMW, 0, (LPARAM)&lvSubtitle);
+			}
+				
+			//Display the comments in the movie data
 			for(uint32 i=0;i<currComments.size();i++)
 			{
 				std::wstring& comment = currComments[i];
@@ -338,6 +386,8 @@ BOOL CALLBACK ReplayMetadataDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, L
 				SendMessageW(hwndList, LVM_SETITEMTEXTW, i, (LPARAM)&lvi);
 			}
 			
+			
+			
 		}
 		break;
 
diff --git a/src/fceu.cpp b/src/fceu.cpp
index 53b176ea..4e7d4789 100644
--- a/src/fceu.cpp
+++ b/src/fceu.cpp
@@ -632,6 +632,7 @@ void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int ski
 	}
 	else justLagged = false;
 
+	ProcessSubtitles();
 }
 
 void FCEUI_CloseGame(void)
diff --git a/src/movie.cpp b/src/movie.cpp
index 7acefa28..15edbcc4 100644
--- a/src/movie.cpp
+++ b/src/movie.cpp
@@ -24,6 +24,7 @@
 #include "utils/memory.h"
 #include "utils/memorystream.h"
 #include "utils/xstring.h"
+#include <sstream>
 
 #ifdef CREATE_AVI
 #include "drivers/videolog/nesvideos-piece.h"
@@ -35,12 +36,12 @@
 
 using namespace std;
 
-
 #define MOVIE_VERSION           3 
 
 extern char FileBase[];
 
-using namespace std;
+std::vector<int> subtitleFrames;
+std::vector<string> subtitleMessages;
 
 //TODO - remove the synchack stuff from the replay gui and require it to be put into the fm2 file
 //which the user would have already converted from fcm
@@ -350,6 +351,8 @@ void MovieData::installValue(std::string& key, std::string& val)
 		installBool(val,binaryFlag);
 	else if(key == "comment")
 		comments.push_back(mbstowcs(val));
+	else if (key == "subtitle")
+		subtitles.push_back(val); //mbstowcs(val));
 	else if(key == "savestate")
 	{
 		int len = Base64StringToBytesLength(val);
@@ -379,6 +382,9 @@ int MovieData::dump(std::ostream *os, bool binary)
 
 	for(uint32 i=0;i<comments.size();i++)
 		*os << "comment " << wcstombs(comments[i]) << endl;
+
+	for(uint32 i=0;i<subtitles.size();i++)
+		*os << "subtitle " << subtitles[i] << endl;
 	
 	if(binary)
 		*os << "binary 1" << endl;
@@ -492,7 +498,7 @@ static bool LoadFM2(MovieData& movieData, std::istream* fp, int size, bool stopA
 
 	std::string key,value;
 	enum {
-		NEWLINE, KEY, SEPARATOR, VALUE, RECORD, COMMENT
+		NEWLINE, KEY, SEPARATOR, VALUE, RECORD, COMMENT, SUBTITLE
 	} state = NEWLINE;
 	bool bail = false;
 	for(;;)
@@ -721,6 +727,7 @@ void FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, int _paus
 	}
 
 	LoadFM2(currMovieData, fp->stream, INT_MAX, false);
+	LoadSubtitles();
 	delete fp;
 
 	//fully reload the game to reinitialize everything before playing any movie
@@ -1168,6 +1175,47 @@ bool FCEUI_MovieGetInfo(FCEUFILE* fp, MOVIE_INFO& info, bool skipFrameCount)
 	info.name_of_rom_used = md.romFilename;
 	info.rerecord_count = md.rerecordCount;
 	info.comments = md.comments;
+	info.subtitles = md.subtitles;
 
 	return true;
 }
+
+//This function creates an array of frame numbers and corresponding strings for displaying subtitles
+void LoadSubtitles(void)
+{
+	
+	extern std::vector<string> subtitles;
+	for(uint32 i=0;i<currMovieData.subtitles.size();i++)
+	{
+		std::string& subtitle = currMovieData.subtitles[i];
+		size_t splitat = subtitle.find_first_of(' ');
+		std::string key, value;
+		
+		//If we can't split them, then don't process this one
+		if(splitat == std::string::npos)
+			{
+			}
+		//Else split the subtitle into the int and string arrays
+		else
+			{
+				key = subtitle.substr(0,splitat);
+				value = subtitle.substr(splitat+1);
+
+				subtitleFrames.push_back(atoi(key.c_str()));
+				subtitleMessages.push_back(value);
+			}
+	}
+
+}
+
+//Every frame, this will be called to determine if a subtitle should be displayed, which one, and then to display it
+void ProcessSubtitles(void)
+{
+	if (movieMode == MOVIEMODE_INACTIVE) return;
+
+	for(uint32 i=0;i<currMovieData.subtitles.size();i++)
+	{
+		if (currFrameCounter == subtitleFrames[i])
+			FCEUI_DispMessage("%s",subtitleMessages[i].c_str());
+	}
+}
\ No newline at end of file
diff --git a/src/movie.h b/src/movie.h
index 7a4a8e8a..ab538ac7 100644
--- a/src/movie.h
+++ b/src/movie.h
@@ -42,6 +42,7 @@ typedef struct
 	std::string name_of_rom_used;
 
 	std::vector<std::wstring> comments;
+	std::vector<std::string> subtitles;
 } MOVIE_INFO;
 
 
@@ -159,6 +160,7 @@ public:
 	std::vector<char> savestate;
 	std::vector<MovieRecord> records;
 	std::vector<std::wstring> comments;
+	std::vector<std::string> subtitles;
 	//this is the RERECORD COUNT. please rename variable.
 	int rerecordCount;
 	FCEU_Guid guid;
@@ -243,4 +245,9 @@ bool FCEUI_GetMovieToggleReadOnly();
 void FCEUI_MovieToggleFrameDisplay();
 void FCEUI_ToggleInputDisplay(void);
 
+void LoadSubtitles(void);
+void ProcessSubtitles(void);
+
+
+
 #endif //__MOVIE_H_