1 ////////////////////////////////////////////////////////////////////////////////////////
2 //
3 // Nestopia - NES/Famicom emulator written in C++
4 //
5 // Copyright (C) 2003-2008 Martin Freij
6 //
7 // This file is part of Nestopia.
8 //
9 // Nestopia is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation; either version 2 of the License, or
12 // (at your option) any later version.
13 //
14 // Nestopia is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with Nestopia; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 //
23 ////////////////////////////////////////////////////////////////////////////////////////
24 
25 #include "NstIoLog.hpp"
26 #include "NstDialogLogfile.hpp"
27 #include "NstManager.hpp"
28 #include "NstManagerPreferences.hpp"
29 #include "NstManagerLogfile.hpp"
30 #include "../core/api/NstApiUser.hpp"
31 
32 namespace Nestopia
33 {
34 	namespace Managers
35 	{
36 		struct Logfile::Callbacks
37 		{
DoOutputNestopia::Managers::Logfile::Callbacks38 			static void NST_CALLBACK DoOutput(Nes::User::UserData data,wcstring text,uint length)
39 			{
40 				NST_ASSERT( data && text );
41 
42 				if (length)
43 				{
44 				#ifdef NST_DEBUG
45 					::OutputDebugString( text );
46 				#endif
47 
48 					Logfile& log = *static_cast<Logfile*>(data);
49 
50 					if (log.preferences[Preferences::SAVE_LOGFILE])
51 					{
52 
53 						try
54 						{
55 							if (log.file.IsOpen())
56 							{
57 								if (log.file.Size() > MAX_SIZE)
58 									log.file.Truncate( log.msgOffset );
59 							}
60 							else
61 							{
62 								log.Open();
63 							}
64 
65 							log.file.Write( text, length * sizeof(wchar_t) );
66 						}
67 						catch (Io::File::Exception)
68 						{
69 							log.Close();
70 						}
71 					}
72 				}
73 			}
74 
DoCharOutputNestopia::Managers::Logfile::Callbacks75 			static void NST_CALLBACK DoCharOutput(Nes::User::UserData data,cstring text,ulong length)
76 			{
77 				NST_ASSERT( data && text );
78 
79 				Logfile& log = *static_cast<Logfile*>(data);
80 
81 				if (length && log.preferences[Preferences::SAVE_LOGFILE])
82 				{
83 					const HeapString string( text, length );
84 					DoOutput( data, string.Ptr(), string.Length() );
85 				}
86 			}
87 		};
88 
Logfile(Emulator & e,Window::Menu & m,const Preferences & p)89 		Logfile::Logfile(Emulator& e,Window::Menu& m,const Preferences& p)
90 		:
91 		Manager     ( e, m, this, &Logfile::OnEmuEvent, IDM_VIEW_LOGFILE, &Logfile::OnCommand ),
92 		preferences ( p )
93 		{
94 			Io::Log::SetCallback( this, Callbacks::DoOutput );
95 			Nes::User::logCallback.Set( &Callbacks::DoCharOutput, this );
96 
97 			UpdateMenu();
98 		}
99 
~Logfile()100 		Logfile::~Logfile()
101 		{
102 			Io::Log::UnsetCallback();
103 			Nes::User::logCallback.Unset();
104 		}
105 
Available() const106 		bool Logfile::Available() const
107 		{
108 			return emulator.NetPlayers() == 0 && file.IsOpen();
109 		}
110 
UpdateMenu() const111 		void Logfile::UpdateMenu() const
112 		{
113 			menu[IDM_VIEW_LOGFILE].Enable( Available() );
114 		}
115 
OnEmuEvent(const Emulator::Event event,Emulator::Data)116 		void Logfile::OnEmuEvent(const Emulator::Event event,Emulator::Data)
117 		{
118 			switch (event)
119 			{
120 				case Emulator::EVENT_NETPLAY_MODE:
121 
122 					UpdateMenu();
123 					break;
124 			}
125 		}
126 
OnCommand(uint)127 		void Logfile::OnCommand(uint)
128 		{
129 			if (file.IsOpen())
130 			{
131 				try
132 				{
133 					file.Rewind();
134 
135 					HeapString string;
136 					file.ReadText( string );
137 
138 					if (Window::Logfile().Open( string.Ptr() ))
139 						file.Truncate( msgOffset );
140 				}
141 				catch (Io::File::Exception)
142 				{
143 					Close();
144 				}
145 			}
146 		}
147 
Open()148 		void Logfile::Open()
149 		{
150 			file.Open
151 			(
152 				//Application::Instance::GetExePath(L"nestopia.log"),
153 				Application::Instance::GetConfigPath(L"nestopia.log"),//bg
154 				Io::File::READ|Io::File::WRITE|Io::File::EMPTY|Io::File::SEQUENTIAL_ACCESS
155 			);
156 
157 			HeapString text;
158 
159 			text << "Nestopia log file version "
160                  << Application::Instance::GetVersion()
161                  << "\r\n-----------------------------------\r\n\r\n";
162 
163 			file.WriteText( text.Ptr(), text.Length(), true );
164 			msgOffset = file.Position();
165 
166 			UpdateMenu();
167 		}
168 
Close()169 		void Logfile::Close()
170 		{
171 			Io::Log::UnsetCallback();
172 			Nes::User::logCallback.Unset();
173 
174 			file.Close();
175 
176 			UpdateMenu();
177 		}
178 	}
179 }
180