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 "language/resource.h"
26 #include "NstApplicationException.hpp"
27 #include "NstWindowCustom.hpp"
28 
29 namespace Nestopia
30 {
31 	namespace Window
32 	{
33 		Custom::Timers Custom::timers;
34 
Timer(const TimerCallback & t)35 		Custom::Timer::Timer(const TimerCallback& t)
36 		: TimerCallback(t) {}
37 
StartTimer(const TimerCallback timer,const uint duration) const38 		void Custom::StartTimer(const TimerCallback timer,const uint duration) const
39 		{
40 			NST_ASSERT( hWnd );
41 
42 			uint id = 0;
43 
44 			for (Timers::ConstIterator it(timers.Begin()), end(timers.End()); ; ++it, ++id)
45 			{
46 				if (it == end)
47 				{
48 					timers.PushBack( timer );
49 					break;
50 				}
51 				else if (*it == timer)
52 				{
53 					break;
54 				}
55 			}
56 
57 			timers[id].active = true;
58 
59 			if (!::SetTimer( hWnd, id, duration, &TimerProc ))
60 				throw Application::Exception( IDS_ERR_FAILED, L"SetTimer()" );
61 		}
62 
StopTimer(const TimerCallback timer) const63 		bool Custom::StopTimer(const TimerCallback timer) const
64 		{
65 			for (Timers::Iterator it(timers.Begin()), end(timers.End()); it != end; ++it)
66 			{
67 				if (*it == timer && it->active)
68 				{
69 					it->active = false;
70 					::KillTimer( hWnd, it - timers.Begin() );
71 					return true;
72 				}
73 			}
74 
75 			return false;
76 		}
77 
78 		#ifdef NST_MSVC_OPTIMIZE
79 		#pragma optimize("t", on)
80 		#endif
81 
TimerProc(HWND const hWnd,uint,const UINT_PTR id,DWORD)82 		void CALLBACK Custom::TimerProc(HWND const hWnd,uint,const UINT_PTR id,DWORD)
83 		{
84 			NST_ASSERT( id < timers.Size() );
85 
86 			const uint next = timers[id]();
87 
88 			if (timers[id].active)
89 			{
90 				if (next == 0)
91 				{
92 					timers[id].active = false;
93 					::KillTimer( hWnd, id );
94 				}
95 				else if (next != 1)
96 				{
97 					::SetTimer( hWnd, id, next, &TimerProc );
98 				}
99 			}
100 		}
101 
102 		#ifdef NST_MSVC_OPTIMIZE
103 		#pragma optimize("t", on)
104 		#endif
105 	}
106 }
107