1 /****
2 
3 Windows functionality that is definitely
4 not project specific.
5 
6 ****/
7 
8 // To link code to main C functions
9 
10 extern "C" {
11 
12 #include "3dc.h"
13 #include "inline.h"
14 
15 // For modifications necessary to make Alt-Tabbing
16 // behaviour (WM_ACTIVATEAPP) work full screen.
17 // This is necessary to support full screen
18 // ActiveMovie play.
19 
20 #define SupportAltTab Yes
21 
22 // Globals
23 
24 static HANDLE RasterThread;
25 
26 // Externs
27 
28 extern BOOL bActive;
29 
30 // These function are here solely to provide a clean
31 // interface layer, since Win32 include files are fully
32 // available in both C and C++.
33 // All functions linking to standard windows code are
34 // in win_func.cpp or win_proj.cpp, and all DirectX
35 // interface functions
36 // should be in dd_func.cpp (in the Win95 directory)
37 // or d3_func.cpp, dp_func.cpp, ds_func.cpp etc.
38 // Project specific platfrom functionality for Win95
39 // should be in project/win95, in files called
40 // dd_proj.cpp etc.
41 
42 
43 // GetTickCount is the standard windows return
44 // millisecond time function, which isn't actually
45 // accurate to a millisecond.  In order to get FRI
46 // to work properly with GetTickCount at high frame
47 // rates, you will have to switch KalmanTimer to Yes
48 // at the start of io.c to turn on a filtering algorithm
49 // in the frame counter handler.
50 // Alternately, we can use the mm function
51 // timeGetTime to get the time accurate to a millisecond.
52 // There is still enough variation in this to make
53 // the kalman filter probably worthwhile, however.
54 
GetWindowsTickCount(void)55 long GetWindowsTickCount(void)
56 
57 {
58     #if 0
59 	return GetTickCount();
60 	#else
61 	return timeGetTime();
62 	#endif
63 }
64 
65 // This function is set up using a PeekMessage check,
66 // with a return on a failure of GetMessage, on the
67 // grounds that it might be more stable than just
68 // GetMessage.  But then again, maybe not.
69 // PM_NOREMOVE means do not take this message out of
70 // the queue.  The while loop is designed to ensure
71 // that all messages are sent through to the Windows
72 // Procedure are associated with a maximum of one frame's
73 // delay in the main engine cycle, ensuring that e.g.
74 // keydown messages do not build up in the queue.
75 
76 // if necessary, one could extern this flag
77 // to determine if a task-switch has occurred which might
78 // have trashed a static display, to decide whether to
79 // redraw the screen. After doing so, one should reset
80 // the flag
81 
82 BOOL g_bMustRedrawScreen = FALSE;
83 
CheckForWindowsMessages(void)84 void CheckForWindowsMessages(void)
85 {
86 	MSG         msg;
87 	extern signed int MouseWheelStatus;
88 
89 	MouseWheelStatus = 0;
90 
91 	// Initialisation for the current embarassingly primitive mouse
92 	// handler...
93 
94 	do
95 	{
96 		while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
97 		{
98 			if (!GetMessage(&msg, NULL, 0, 0))
99 				return;
100 
101 			TranslateMessage(&msg);
102 			DispatchMessage(&msg);
103 
104 			#if (!SupportAltTab)
105 			// Panic
106 			if (!bActive)
107 			{
108 				// Dubious hack...
109 				#if 0
110 				ExitSystem();
111 				#else
112 				ReleaseDirect3D();
113 				exit(0x00);
114 				#endif
115 			}
116 			#endif
117 		}
118 
119 		// JH 13/2/98 - if the app is not active we should not return from the message lopp
120 		// until the app is re-activated
121 
122 		if (!bActive)
123 		{
124 			ResetFrameCounter();
125 			Sleep(0);
126 			g_bMustRedrawScreen = TRUE;
127 		}
128 	}
129 		while (!bActive);
130 }
131 
132 
133 
134 
135 // Experimental functions to handle a separate
136 // thread to run rasterisation on hardware at low
137 // priority.
138 
139 // Note that the RenderD3DScene function does not need
140 // to call ExitThread explictly - the return at the
141 // end of the function will do this for this, giving
142 // thread exit code equal to the return value from
143 // the function.
144 
145 /*
146   Note that this assumes DrawPerFrame mode!!!
147   necessary for some hardware accelerators anyway
148   (deferred texturing problem!!!)
149 */
150 
SpawnRasterThread()151 BOOL SpawnRasterThread()
152 
153 {
154 	DWORD RasterThreadId;
155 	// Stack size of new thread in bytes.
156 	// For the moment, we will set it to
157 	// 128K, the normal size for the engine
158 	// process.
159 	// Note that this is in bytes.
160 	// Note that stack size should grow as
161 	// necessary.  We hope.
162 	DWORD StackSize = 128 * 1024;
163 
164 
165     // Create the thread
166     RasterThread = CreateThread(
167 	   NULL,     // no security
168 	   StackSize,        // default stack size
169 	   (LPTHREAD_START_ROUTINE) RenderD3DScene,
170 	   0,        // no argument for function
171 	   0,        // default creation flags
172 	   &RasterThreadId); // get thread ID
173 
174     if (RasterThread == NULL)
175 	  {
176        #if debug
177 	   ReleaseDirect3D();
178 	   exit(0xabab);
179 	   #else
180 	   return FALSE;
181        #endif
182 	  }
183 
184     #if 1
185 	// Set the priority on the thread to
186 	// below normal, since we want this thread
187 	// to be unimportant --- it is only monitoring
188 	// the hardware rasteriser.  Hopefully.
189 	// Note that this priority value maybe should
190 	// be THREAD_PRIORITY_LOWEST or THREAD_PRIORITY_IDLE,
191 	// or maybe we shouldn't call this function at all.
192 	// Also, we must have a THREAD_SET_INFORMATION
193 	// access right associated with the thread for this
194 	// to work.  Hopefully, this should be the default
195 	// when using CreateThread.
196 	SetThreadPriority(RasterThread,
197 	   THREAD_PRIORITY_NORMAL);
198 	#endif
199 
200 	return TRUE;
201 }
202 
WaitForRasterThread()203 BOOL WaitForRasterThread()
204 
205 {
206     BOOL RetVal;
207 	DWORD ThreadStatus;
208 	int i;
209 
210     // Note that if this is to work the
211     // rasterisation thread must have a
212 	// THREAD_QUERY_INFORMATION access right,
213 	// but we believe CreateThread should supply
214 	// this as a default.
215 
216     // Note!!! At some stage we may want to put a
217 	// delay loop in the statement below, in the
218 	// time honoured Saturn fashion, depending on how
219 	// much impact calling GetExitCodeThread has on the
220 	// rest of the system - hopefully not much...
221 
222     do
223 	  {
224        RetVal = GetExitCodeThread(RasterThread,
225 	                    &ThreadStatus);
226 	  }
227 	while ((RetVal == TRUE) &&
228 	      (ThreadStatus == STILL_ACTIVE));
229 
230     // Failed to get a status report on the thread
231 	if (RetVal == FALSE)
232 	  {
233 	   #if debug
234 	   ReleaseDirect3D();
235 	   exit(0xabbb);
236 	   #else
237 	   return FALSE;
238 	   #endif
239 	  }
240 
241 	return TRUE;
242 }
243 
244 
245 /*
246   Pick up processor types,
247   either from assembler test (note
248   I have asm to do this, but it must
249   be converted from as / Motorola format
250   to masm / Intel), or (more likely) from
251   a text file left by the launcher, which
252   can use GetProcessorType from the
253   mssetup api
254 */
255 
256 #if defined(_MSC_VER)
257 
GetCPUId(void)258 static unsigned int GetCPUId(void)
259 {
260 	unsigned int retval;
261 	_asm
262 	{
263 		mov eax,1
264 		_emit 0x0f   ; CPUID (00001111 10100010) - This is a Pentium
265 		             ; specific instruction which gets information on the
266 		_emit 0xa2   ; processor. A Pentium family processor should set
267 		             ; bits 11-8 of eax to 5.
268 		mov retval,edx
269 	}
270 	return retval;
271 }
272 
273 #else
274 
275 #error "Unknown compiler"
276 
277 #endif
278 
279 
ReadProcessorType(void)280 PROCESSORTYPES ReadProcessorType(void)
281 {
282 	SYSTEM_INFO SystemInfo;
283 	int ProcessorType;
284 	PROCESSORTYPES RetVal;
285 
286     GetSystemInfo(&SystemInfo);
287 
288     ProcessorType = SystemInfo.dwProcessorType;
289 
290     switch (ProcessorType)
291 	  {
292 	   case PROCESSOR_INTEL_386:
293 		 RetVal = PType_OffBottomOfScale;
294 		 break;
295 
296 	   case PROCESSOR_INTEL_486:
297 		 RetVal = PType_486;
298 		 break;
299 
300 	   case PROCESSOR_INTEL_PENTIUM:
301 		 if (GetCPUId() & 0x00800000)
302 		 	RetVal = PType_PentiumMMX;
303 		 else
304 		 	RetVal = PType_Pentium;
305 		 break;
306 
307        #if 0
308 	   case PROCESSOR_INTEL_SOMETHING:
309 		 RetVal = PType_Klamath;
310 		 break;
311 	   #endif
312 
313 	   default:
314 	     RetVal = PType_OffTopOfScale;
315 		 break;
316 	  }
317 
318 	return RetVal;
319 }
320 
321 
322 
323 // End of extern C declaration
324 
325 };
326 
327 
328 
329 
330