Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
716 | lvd | 1 | #include "std.h" |
2 | |||
3 | #include "resource.h" |
||
4 | #include "emul.h" |
||
5 | #include "vars.h" |
||
6 | #include "init.h" |
||
7 | #include "dx.h" |
||
8 | #include "draw.h" |
||
9 | #include "dxrend.h" |
||
10 | #include "dxrendch.h" |
||
11 | #include "dxrframe.h" |
||
12 | #include "dxr_text.h" |
||
13 | #include "dxr_rsm.h" |
||
14 | #include "dxr_advm.h" |
||
15 | #include "dxovr.h" |
||
16 | #include "dxerr.h" |
||
17 | #include "sound.h" |
||
18 | #include "savesnd.h" |
||
19 | #include "emulkeys.h" |
||
20 | #include "util.h" |
||
21 | |||
22 | unsigned char active = 0, pause = 0; |
||
23 | |||
24 | static const DWORD SCU_SCALE1 = 0x10; |
||
25 | static const DWORD SCU_SCALE2 = 0x20; |
||
26 | static const DWORD SCU_SCALE3 = 0x30; |
||
27 | static const DWORD SCU_SCALE4 = 0x40; |
||
28 | static const DWORD SCU_LOCK_MOUSE = 0x50; |
||
29 | |||
30 | #define MAXDSPIECE (48000*4/20) |
||
31 | #define DSBUFFER_SZ (2*conf.sound.fq*4) |
||
32 | |||
33 | #define SLEEP_DELAY 2 |
||
34 | |||
35 | static HMODULE D3d9Dll = 0; |
||
36 | static IDirect3D9 *D3d9 = 0; |
||
37 | static IDirect3DDevice9 *D3dDev = 0; |
||
38 | static IDirect3DTexture9 *Texture = 0; |
||
39 | static IDirect3DSurface9 *SurfTexture = 0; |
||
40 | |||
41 | LPDIRECTDRAW2 dd; |
||
42 | LPDIRECTDRAWSURFACE sprim, surf0, surf1, surf2; |
||
43 | static PVOID SurfMem1 = 0; |
||
44 | static ULONG SurfPitch1 = 0; |
||
45 | |||
46 | LPDIRECTINPUTDEVICE dikeyboard; |
||
47 | LPDIRECTINPUTDEVICE dimouse; |
||
48 | LPDIRECTINPUTDEVICE2 dijoyst; |
||
49 | |||
50 | LPDIRECTSOUND ds; |
||
51 | LPDIRECTSOUNDBUFFER dsbf; |
||
52 | LPDIRECTDRAWPALETTE pal; |
||
53 | LPDIRECTDRAWCLIPPER clip; |
||
54 | |||
55 | static HANDLE EventBufStop = 0; |
||
56 | unsigned dsoffset, dsbuffer_sz; |
||
57 | |||
58 | static void FlipBltAlign4(); |
||
59 | static void FlipBltAlign16(); |
||
60 | |||
61 | static void (*FlipBltMethod)() = 0; |
||
62 | |||
63 | static void StartD3d(HWND Wnd); |
||
64 | static void DoneD3d(bool DeInitDll = true); |
||
65 | static void SetVideoModeD3d(bool Exclusive); |
||
66 | |||
67 | /* ---------------------- renders ------------------------- */ |
||
68 | |||
69 | RENDER renders[] = |
||
70 | { |
||
71 | { "Normal", render_small, "normal", RF_DRIVER | RF_1X }, |
||
72 | { "Double size", render_dbl, "double", RF_DRIVER | RF_2X }, |
||
73 | { "Triple size", render_3x, "triple", RF_DRIVER | RF_3X }, |
||
74 | { "Quad size", render_quad, "quad", RF_DRIVER | RF_4X }, |
||
75 | { "Anti-Text64", render_text, "text", RF_DRIVER | RF_2X | RF_USEFONT }, |
||
76 | { "Frame resampler", render_rsm, "resampler", RF_DRIVER | RF_8BPCH }, |
||
77 | |||
78 | { "TV Emulation", render_tv, "tv", RF_YUY2 | RF_OVR }, |
||
79 | { "Bilinear filter (MMX,fullscr)", render_bil, "bilinear", RF_2X | RF_PALB }, |
||
80 | { "Vector scaling (fullscr)", render_scale, "scale", RF_2X }, |
||
81 | { "AdvMAME scale (fullscr)", render_advmame, "advmame", RF_DRIVER }, |
||
82 | |||
83 | { "Chunky overlay (fast!)", render_ch_ov, "ch_ov", RF_OVR | 0*RF_128x96 | 0*RF_64x48 | RF_BORDER | RF_USE32AS16 }, |
||
84 | { "Chunky 32bit hardware (flt,fullscr)", render_ch_hw, "ch_hw", RF_CLIP | 0*RF_128x96 | 0*RF_64x48 | RF_BORDER | RF_32 | RF_USEC32 }, |
||
85 | |||
86 | { "Chunky 16bit, low-res, (flt,fullscr)",render_c16bl, "ch_bl", RF_16 | RF_BORDER | RF_USEC32 }, |
||
87 | { "Chunky 16bit, hi-res, (flt,fullscr)", render_c16b, "ch_b", RF_16 | RF_2X | RF_BORDER | RF_USEC32 }, |
||
88 | { "Ch4x4 true color (fullscr)",render_c4x32b, "ch4true", RF_32 | RF_2X | RF_BORDER | RF_USEC32 }, |
||
89 | |||
90 | { 0,0,0,0 } |
||
91 | }; |
||
92 | |||
93 | size_t renders_count = _countof(renders); |
||
94 | |||
95 | const RENDER drivers[] = |
||
96 | { |
||
97 | { "video memory (8bpp)", 0, "ddraw", RF_8 }, |
||
98 | { "video memory (16bpp)", 0, "ddrawh", RF_16 }, |
||
99 | { "video memory (32bpp)", 0, "ddrawt", RF_32 }, |
||
100 | { "gdi device context", 0, "gdi", RF_GDI }, |
||
101 | { "overlay", 0, "ovr", RF_OVR }, |
||
102 | { "hardware blitter", 0, "blt", RF_CLIP }, |
||
103 | { "hardware 3d", 0, "d3d", RF_D3D }, |
||
104 | { "hardware 3d exclusive",0, "d3de", RF_D3DE }, |
||
105 | { 0,0,0,0 } |
||
106 | }; |
||
107 | |||
108 | inline void switch_video() |
||
109 | { |
||
110 | static unsigned char eff7 = -1; |
||
111 | if ((comp.pEFF7 ^ eff7) & EFF7_HWMC) |
||
112 | { |
||
113 | video_timing_tables(); |
||
114 | eff7 = comp.pEFF7; |
||
115 | } |
||
116 | } |
||
117 | |||
118 | static void FlipGdi() |
||
119 | { |
||
120 | if (needclr) |
||
121 | { |
||
122 | needclr--; |
||
123 | gdi_frame(); |
||
124 | } |
||
125 | renders[conf.render].func(gdibuf, temp.ox*temp.obpp/8); // render to memory buffer |
||
126 | // copy bitmap to gdi dc |
||
127 | SetDIBitsToDevice(temp.gdidc, temp.gx, temp.gy, temp.ox, temp.oy, 0, 0, 0, temp.oy, gdibuf, &gdibmp.header, DIB_RGB_COLORS); |
||
128 | } |
||
129 | |||
130 | static void FlipBltAlign16() |
||
131 | { |
||
132 | // Отрисовка в буфер выравненный на 16 байт (необходимо для запси через sse2) |
||
133 | renders[conf.render].func(PUCHAR(SurfMem1), SurfPitch1); |
||
134 | |||
135 | restore_lost:; |
||
136 | DDSURFACEDESC desc; |
||
137 | desc.dwSize = sizeof(desc); |
||
138 | HRESULT r = surf1->Lock(0, &desc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT | DDLOCK_WRITEONLY, 0); |
||
139 | if (r != DD_OK) |
||
140 | { |
||
141 | if(r == DDERR_SURFACELOST) |
||
142 | { |
||
143 | surf1->Restore(); |
||
144 | HRESULT r2 = surf1->IsLost(); |
||
145 | if(r2 == DDERR_SURFACELOST) |
||
146 | Sleep(1); |
||
147 | |||
148 | if(r2 == DD_OK || r2 == DDERR_SURFACELOST) |
||
149 | goto restore_lost; |
||
150 | } |
||
151 | if (!active) |
||
152 | return; |
||
153 | printrdd("IDirectDrawSurface2::Lock() [buffer]", r); |
||
154 | exit(); |
||
155 | } |
||
156 | |||
157 | PUCHAR SrcPtr, DstPtr; |
||
158 | SrcPtr = PUCHAR(SurfMem1); |
||
159 | DstPtr = PUCHAR(desc.lpSurface); |
||
160 | |||
161 | size_t LineSize = temp.ox * (temp.obpp >> 3); |
||
162 | for(unsigned y = 0; y < temp.oy; y++) |
||
163 | { |
||
164 | memcpy(DstPtr, SrcPtr, LineSize); |
||
165 | SrcPtr += SurfPitch1; |
||
166 | DstPtr += desc.lPitch; |
||
167 | } |
||
168 | |||
169 | r = surf1->Unlock(0); |
||
170 | if(r != DD_OK) |
||
171 | { |
||
172 | if(r == DDERR_SURFACELOST) |
||
173 | { |
||
174 | surf1->Restore(); |
||
175 | HRESULT r2 = surf1->IsLost(); |
||
176 | if(r2 == DDERR_SURFACELOST) |
||
177 | Sleep(1); |
||
178 | |||
179 | if(r2 == DD_OK || r2 == DDERR_SURFACELOST) |
||
180 | goto restore_lost; |
||
181 | } |
||
182 | printrdd("IDirectDrawSurface2::Unlock() [buffer]", r); |
||
183 | exit(); |
||
184 | } |
||
185 | } |
||
186 | |||
187 | static void FlipBltAlign4() |
||
188 | { |
||
189 | restore_lost:; |
||
190 | DDSURFACEDESC desc; |
||
191 | desc.dwSize = sizeof(desc); |
||
192 | HRESULT r = surf1->Lock(0, &desc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT | DDLOCK_WRITEONLY, 0); |
||
193 | if (r != DD_OK) |
||
194 | { |
||
195 | if(r == DDERR_SURFACELOST) |
||
196 | { |
||
197 | surf1->Restore(); |
||
198 | HRESULT r2 = surf1->IsLost(); |
||
199 | if(r2 == DDERR_SURFACELOST) |
||
200 | Sleep(1); |
||
201 | |||
202 | if(r2 == DD_OK || r2 == DDERR_SURFACELOST) |
||
203 | goto restore_lost; |
||
204 | } |
||
205 | if (!active) |
||
206 | return; |
||
207 | printrdd("IDirectDrawSurface2::Lock() [buffer]", r); |
||
208 | exit(); |
||
209 | } |
||
210 | |||
211 | // Отрисовка в буфер выравненный на 4 байта |
||
212 | renders[conf.render].func(PUCHAR(desc.lpSurface), desc.lPitch); |
||
213 | |||
214 | r = surf1->Unlock(0); |
||
215 | if(r != DD_OK) |
||
216 | { |
||
217 | if(r == DDERR_SURFACELOST) |
||
218 | { |
||
219 | surf1->Restore(); |
||
220 | HRESULT r2 = surf1->IsLost(); |
||
221 | if(r2 == DDERR_SURFACELOST) |
||
222 | Sleep(1); |
||
223 | |||
224 | if(r2 == DD_OK || r2 == DDERR_SURFACELOST) |
||
225 | goto restore_lost; |
||
226 | } |
||
227 | printrdd("IDirectDrawSurface2::Unlock() [buffer]", r); |
||
228 | exit(); |
||
229 | } |
||
230 | } |
||
231 | |||
232 | static bool CalcFlipRect(LPRECT R) |
||
233 | { |
||
234 | int w = temp.client.right - temp.client.left; |
||
235 | int h = temp.client.bottom - temp.client.top; |
||
236 | int n = min(w / temp.ox, h / temp.oy); |
||
237 | |||
238 | POINT P = { 0, 0 }; |
||
239 | ClientToScreen(wnd, &P); |
||
240 | int x0 = P.x; |
||
241 | int y0 = P.y; |
||
242 | R->left = (w - (temp.ox*n)) / 2; |
||
243 | R->right = (w + (temp.ox*n)) / 2; |
||
244 | R->top = (h - (temp.oy*n)) / 2; |
||
245 | R->bottom = (h + (temp.oy*n)) / 2; |
||
246 | OffsetRect(R, x0, y0); |
||
247 | return IsRectEmpty(R) == FALSE; |
||
248 | } |
||
249 | |||
250 | static void FlipBlt() |
||
251 | { |
||
252 | HRESULT r; |
||
253 | |||
254 | restore_lost:; |
||
255 | FlipBltMethod(); |
||
256 | |||
257 | assert(!IsRectEmpty(&temp.client)); |
||
258 | |||
259 | static int cnt = 0; |
||
260 | |||
261 | DDBLTFX Fx; |
||
262 | Fx.dwSize = sizeof(Fx); |
||
263 | Fx.dwDDFX = 0; |
||
264 | |||
265 | RECT R; |
||
266 | if(!CalcFlipRect(&R)) |
||
267 | return; |
||
268 | |||
269 | // Очистка back буфера |
||
270 | Fx.dwFillColor = 0; |
||
271 | r = surf2->Blt(0, 0, 0, DDBLT_WAIT | DDBLT_ASYNC | DDBLT_COLORFILL, &Fx); |
||
272 | if (r != DD_OK) |
||
273 | { |
||
274 | if(r == DDERR_SURFACELOST) |
||
275 | { |
||
276 | surf2->Restore(); |
||
277 | if(surf2->IsLost() == DDERR_SURFACELOST) |
||
278 | Sleep(1); |
||
279 | goto restore_lost; |
||
280 | } |
||
281 | printrdd("IDirectDrawSurface2::Blt(1)", r); |
||
282 | exit(); |
||
283 | } |
||
284 | |||
285 | // Рисование картинки с масштабированием в n раз из surf1 (320x240) -> surf2 (размер экрана) |
||
286 | r = surf2->Blt(&R, surf1, 0, DDBLT_WAIT | DDBLT_ASYNC | DDBLT_DDFX, &Fx); |
||
287 | if (r != DD_OK) |
||
288 | { |
||
289 | if(r == DDERR_SURFACELOST) |
||
290 | { |
||
291 | surf1->Restore(); |
||
292 | surf2->Restore(); |
||
293 | if(surf1->IsLost() == DDERR_SURFACELOST || surf2->IsLost() == DDERR_SURFACELOST) |
||
294 | Sleep(1); |
||
295 | goto restore_lost; |
||
296 | } |
||
297 | printrdd("IDirectDrawSurface2::Blt(2)", r); |
||
298 | exit(); |
||
299 | } |
||
300 | |||
301 | // Копирование surf2 на surf0 (экран, размер экрана) |
||
302 | r = surf0->Blt(0, surf2, 0, DDBLT_WAIT | DDBLT_ASYNC | DDBLT_DDFX, &Fx); |
||
303 | if (r != DD_OK) |
||
304 | { |
||
305 | if(r == DDERR_SURFACELOST) |
||
306 | { |
||
307 | surf0->Restore(); |
||
308 | surf2->Restore(); |
||
309 | if(surf0->IsLost() == DDERR_SURFACELOST || surf2->IsLost() == DDERR_SURFACELOST) |
||
310 | Sleep(1); |
||
311 | goto restore_lost; |
||
312 | } |
||
313 | printrdd("IDirectDrawSurface2::Blt(3)", r); |
||
314 | exit(); |
||
315 | } |
||
316 | } |
||
317 | |||
318 | static bool CalcFlipRectD3d(LPRECT R) |
||
319 | { |
||
320 | int w = temp.client.right - temp.client.left; |
||
321 | int h = temp.client.bottom - temp.client.top; |
||
322 | int n = min(w / temp.ox, h / temp.oy); |
||
323 | |||
324 | R->left = (w - (temp.ox*n)) / 2; |
||
325 | R->right = (w + (temp.ox*n)) / 2; |
||
326 | R->top = (h - (temp.oy*n)) / 2; |
||
327 | R->bottom = (h + (temp.oy*n)) / 2; |
||
328 | |||
329 | return IsRectEmpty(R) == FALSE; |
||
330 | } |
||
331 | |||
332 | static void FlipD3d() |
||
333 | { |
||
334 | if(!SUCCEEDED(D3dDev->BeginScene())) |
||
335 | return; |
||
336 | |||
337 | HRESULT Hr; |
||
338 | IDirect3DSurface9 *SurfBackBuffer0 = 0; |
||
339 | |||
340 | Hr = D3dDev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &SurfBackBuffer0); |
||
341 | if (Hr != DD_OK) |
||
342 | { printrdd("IDirect3DDevice9::GetBackBuffer(0)", Hr); exit(); } |
||
343 | |||
344 | D3DLOCKED_RECT Rect = { 0 }; |
||
345 | |||
346 | Hr = SurfTexture->LockRect(&Rect, 0, D3DLOCK_DISCARD); |
||
347 | if(FAILED(Hr)) |
||
348 | { |
||
349 | printrdd("IDirect3DDevice9::LockRect()", Hr); |
||
350 | // __debugbreak(); |
||
351 | exit(); |
||
352 | } |
||
353 | |||
354 | renders[conf.render].func((u8 *)Rect.pBits, Rect.Pitch); |
||
355 | |||
356 | SurfTexture->UnlockRect(); |
||
357 | |||
358 | Hr = D3dDev->ColorFill(SurfBackBuffer0, 0, D3DCOLOR_XRGB(0, 0, 0)); |
||
359 | if(FAILED(Hr)) |
||
360 | { |
||
361 | printrdd("IDirect3DDevice9::ColorFill()", Hr); |
||
362 | // __debugbreak(); |
||
363 | exit(); |
||
364 | } |
||
365 | |||
366 | RECT R; |
||
367 | if(!CalcFlipRectD3d(&R)) |
||
368 | { |
||
369 | D3dDev->EndScene(); |
||
370 | SurfBackBuffer0->Release(); |
||
371 | return; |
||
372 | } |
||
373 | |||
374 | Hr = D3dDev->StretchRect(SurfTexture, 0, SurfBackBuffer0, &R, D3DTEXF_POINT); |
||
375 | if(FAILED(Hr)) |
||
376 | { |
||
377 | printrdd("IDirect3DDevice9::StretchRect()", Hr); |
||
378 | // __debugbreak(); |
||
379 | exit(); |
||
380 | } |
||
381 | D3dDev->EndScene(); |
||
382 | |||
383 | // Present the backbuffer contents to the display |
||
384 | Hr = D3dDev->Present(0, 0, 0, 0); |
||
385 | SurfBackBuffer0->Release(); |
||
386 | |||
387 | if(FAILED(Hr)) |
||
388 | { |
||
389 | if(Hr == D3DERR_DEVICELOST) |
||
390 | { |
||
391 | SetVideoModeD3d((temp.rflags & RF_D3DE) != 0); |
||
392 | return; |
||
393 | } |
||
394 | |||
395 | printrdd("IDirect3DDevice9::Present()", Hr); |
||
396 | // __debugbreak(); |
||
397 | exit(); |
||
398 | } |
||
399 | } |
||
400 | |||
401 | static void FlipVideoMem() |
||
402 | { |
||
403 | // draw direct to video memory, overlay |
||
404 | LPDIRECTDRAWSURFACE drawsurf = conf.flip ? surf1 : surf0; |
||
405 | |||
406 | DDSURFACEDESC desc; |
||
407 | desc.dwSize = sizeof desc; |
||
408 | restore_lost:; |
||
409 | HRESULT r = drawsurf->Lock(0, &desc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT | DDLOCK_WRITEONLY, 0); |
||
410 | if (r != DD_OK) |
||
411 | { |
||
412 | if (!active) |
||
413 | return; |
||
414 | if(r == DDERR_SURFACELOST) |
||
415 | { |
||
416 | drawsurf->Restore(); |
||
417 | if(drawsurf->IsLost() == DDERR_SURFACELOST) |
||
418 | Sleep(1); |
||
419 | goto restore_lost; |
||
420 | } |
||
421 | printrdd("IDirectDrawSurface2::Lock()", r); |
||
422 | if (!exitflag) |
||
423 | exit(); |
||
424 | } |
||
425 | if (needclr) |
||
426 | { |
||
427 | needclr--; |
||
428 | _render_black((unsigned char*)desc.lpSurface, desc.lPitch); |
||
429 | } |
||
430 | renders[conf.render].func((unsigned char*)desc.lpSurface + desc.lPitch*temp.ody + temp.odx, desc.lPitch); |
||
431 | drawsurf->Unlock(0); |
||
432 | |||
433 | if (conf.flip) // draw direct to video memory |
||
434 | { |
||
435 | r = surf0->Flip(0, DDFLIP_WAIT); |
||
436 | if (r != DD_OK) |
||
437 | { |
||
438 | if(r == DDERR_SURFACELOST) |
||
439 | { |
||
440 | surf0->Restore(); |
||
441 | if(surf0->IsLost() == DDERR_SURFACELOST) |
||
442 | Sleep(1); |
||
443 | goto restore_lost; |
||
444 | } |
||
445 | printrdd("IDirectDrawSurface2::Flip()", r); |
||
446 | exit(); |
||
447 | } |
||
448 | } |
||
449 | } |
||
450 | |||
451 | void flip() |
||
452 | { |
||
453 | if(temp.Minimized) |
||
454 | return; |
||
455 | switch_video(); |
||
456 | |||
457 | if (conf.flip && (temp.rflags & (RF_GDI | RF_CLIP))) |
||
458 | dd->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0); |
||
459 | |||
460 | if (temp.rflags & RF_GDI) // gdi |
||
461 | { |
||
462 | FlipGdi(); |
||
463 | return; |
||
464 | } |
||
465 | |||
466 | if (surf0 && surf0->IsLost() == DDERR_SURFACELOST) |
||
467 | surf0->Restore(); |
||
468 | if (surf1 && surf1->IsLost() == DDERR_SURFACELOST) |
||
469 | surf1->Restore(); |
||
470 | |||
471 | if (temp.rflags & RF_CLIP) // hardware blitter |
||
472 | { |
||
473 | if(IsRectEmpty(&temp.client)) // client area is empty |
||
474 | return; |
||
475 | |||
476 | FlipBlt(); |
||
477 | return; |
||
478 | } |
||
479 | |||
480 | if (temp.rflags & (RF_D3D | RF_D3DE)) // direct 3d |
||
481 | { |
||
482 | if(IsRectEmpty(&temp.client)) // client area is empty |
||
483 | return; |
||
484 | |||
485 | FlipD3d(); |
||
486 | return; |
||
487 | } |
||
488 | |||
489 | // draw direct to video memory, overlay |
||
490 | FlipVideoMem(); |
||
491 | } |
||
492 | |||
493 | static HWAVEOUT hwo = 0; |
||
494 | static WAVEHDR wq[MAXWQSIZE]; |
||
495 | static unsigned char wbuffer[MAXWQSIZE*MAXDSPIECE]; |
||
496 | static unsigned wqhead, wqtail; |
||
497 | |||
498 | void __fastcall do_sound_none() |
||
499 | { |
||
500 | |||
501 | } |
||
502 | |||
503 | void __fastcall do_sound_wave() |
||
504 | { |
||
505 | HRESULT r; |
||
506 | |||
507 | for (;;) // release all done items |
||
508 | { |
||
509 | while ((wqtail != wqhead) && (wq[wqtail].dwFlags & WHDR_DONE)) |
||
510 | { // ready! |
||
511 | if ((r = waveOutUnprepareHeader(hwo, &wq[wqtail], sizeof(WAVEHDR))) != MMSYSERR_NOERROR) |
||
512 | { |
||
513 | printrmm("waveOutUnprepareHeader()", r); |
||
514 | exit(); |
||
515 | } |
||
516 | if (++wqtail == conf.soundbuffer) |
||
517 | wqtail = 0; |
||
518 | } |
||
519 | if ((wqhead+1)%conf.soundbuffer != wqtail) |
||
520 | break; // some empty item in queue |
||
521 | /* [vv] |
||
522 | */ |
||
523 | if (conf.sleepidle) |
||
524 | Sleep(SLEEP_DELAY); |
||
525 | } |
||
526 | |||
527 | if(!spbsize) |
||
528 | return; |
||
529 | |||
530 | // __debugbreak(); |
||
531 | // put new item and play |
||
532 | PCHAR bfpos = PCHAR(wbuffer + wqhead*MAXDSPIECE); |
||
533 | memcpy(bfpos, sndplaybuf, spbsize); |
||
534 | wq[wqhead].lpData = bfpos; |
||
535 | wq[wqhead].dwBufferLength = spbsize; |
||
536 | wq[wqhead].dwFlags = 0; |
||
537 | |||
538 | if ((r = waveOutPrepareHeader(hwo, &wq[wqhead], sizeof(WAVEHDR))) != MMSYSERR_NOERROR) |
||
539 | { |
||
540 | printrmm("waveOutPrepareHeader()", r); |
||
541 | exit(); |
||
542 | } |
||
543 | |||
544 | if ((r = waveOutWrite(hwo, &wq[wqhead], sizeof(WAVEHDR))) != MMSYSERR_NOERROR) |
||
545 | { |
||
546 | printrmm("waveOutWrite()", r); |
||
547 | exit(); |
||
548 | } |
||
549 | |||
550 | if (++wqhead == conf.soundbuffer) |
||
551 | wqhead = 0; |
||
552 | |||
553 | // int bs = wqhead-wqtail; if (bs<0)bs+=conf.soundbuffer; if (bs < 8) goto again; |
||
554 | |||
555 | } |
||
556 | |||
557 | // directsound part |
||
558 | // begin |
||
559 | void restore_sound_buffer() |
||
560 | { |
||
561 | // for (;;) { |
||
562 | DWORD status = 0; |
||
563 | dsbf->GetStatus(&status); |
||
564 | if (status & DSBSTATUS_BUFFERLOST) |
||
565 | { |
||
566 | printf("%s\n", __FUNCTION__); |
||
567 | Sleep(18); |
||
568 | dsbf->Restore(); |
||
569 | // Sleep(200); |
||
570 | } |
||
571 | // else break; |
||
572 | // } |
||
573 | } |
||
574 | |||
575 | void clear_buffer() |
||
576 | { |
||
577 | // printf("%s\n", __FUNCTION__); |
||
578 | // __debugbreak(); |
||
579 | |||
580 | restore_sound_buffer(); |
||
581 | HRESULT r; |
||
582 | void *ptr1, *ptr2; |
||
583 | DWORD sz1, sz2; |
||
584 | r = dsbf->Lock(0, 0, &ptr1, &sz1, &ptr2, &sz2, DSBLOCK_ENTIREBUFFER); |
||
585 | if (r != DS_OK) |
||
586 | return; |
||
587 | memset(ptr1, 0, sz1); |
||
588 | //memset(ptr2, 0, sz2); |
||
589 | dsbf->Unlock(ptr1, sz1, ptr2, sz2); |
||
590 | } |
||
591 | |||
592 | int maxgap; |
||
593 | |||
594 | void __fastcall do_sound_ds() |
||
595 | { |
||
596 | HRESULT r; |
||
597 | |||
598 | do |
||
599 | { |
||
600 | int play, write; |
||
601 | if ((r = dsbf->GetCurrentPosition((DWORD*)&play, (DWORD*)&write)) != DS_OK) |
||
602 | { |
||
603 | if (r == DSERR_BUFFERLOST) |
||
604 | { |
||
605 | restore_sound_buffer(); |
||
606 | return; |
||
607 | } |
||
608 | |||
609 | printrds("IDirectSoundBuffer::GetCurrentPosition()", r); |
||
610 | exit(); |
||
611 | } |
||
612 | |||
613 | int gap = write - play; |
||
614 | if (gap < 0) |
||
615 | gap += dsbuffer_sz; |
||
616 | |||
617 | int pos = dsoffset - play; |
||
618 | if (pos < 0) |
||
619 | pos += dsbuffer_sz; |
||
620 | maxgap = max(maxgap, gap); |
||
621 | |||
622 | if (pos < maxgap || pos > 10 * (int)maxgap) |
||
623 | { |
||
624 | dsoffset = 3 * maxgap; |
||
625 | clear_buffer(); |
||
626 | dsbf->Stop(); |
||
627 | dsbf->SetCurrentPosition(0); |
||
628 | break; |
||
629 | } |
||
630 | |||
631 | if (pos < 2 * maxgap) |
||
632 | break; |
||
633 | |||
634 | if ((r = dsbf->Play(0, 0, DSBPLAY_LOOPING)) != DS_OK) |
||
635 | { |
||
636 | if (r == DSERR_BUFFERLOST) |
||
637 | { |
||
638 | restore_sound_buffer(); |
||
639 | return; |
||
640 | } |
||
641 | |||
642 | printrds("IDirectSoundBuffer::Play()", r); |
||
643 | exit(); |
||
644 | } |
||
645 | |||
646 | if ((conf.SyncMode == SM_SOUND) && conf.sleepidle) |
||
647 | Sleep(SLEEP_DELAY); |
||
648 | } while(conf.SyncMode == SM_SOUND); |
||
649 | |||
650 | dsoffset %= dsbuffer_sz; |
||
651 | |||
652 | if(!spbsize) |
||
653 | return; |
||
654 | |||
655 | void *ptr1, *ptr2; |
||
656 | DWORD sz1, sz2; |
||
657 | r = dsbf->Lock(dsoffset, spbsize, &ptr1, &sz1, &ptr2, &sz2, 0); |
||
658 | if (r != DS_OK) |
||
659 | { |
||
660 | if (r == DSERR_BUFFERLOST) |
||
661 | { |
||
662 | restore_sound_buffer(); |
||
663 | return; |
||
664 | } |
||
665 | // __debugbreak(); |
||
666 | printf("dsbuffer_sz=%d, dsoffset=%d, spbsize=%d\n", dsbuffer_sz, dsoffset, spbsize); |
||
667 | printrds("IDirectSoundBuffer::Lock()", r); |
||
668 | exit(); |
||
669 | } |
||
670 | memcpy(ptr1, sndplaybuf, sz1); |
||
671 | if (ptr2) |
||
672 | memcpy(ptr2, ((char *)sndplaybuf)+sz1, sz2); |
||
673 | |||
674 | r = dsbf->Unlock(ptr1, sz1, ptr2, sz2); |
||
675 | if (r != DS_OK) |
||
676 | { |
||
677 | if (r == DSERR_BUFFERLOST) |
||
678 | { |
||
679 | restore_sound_buffer(); |
||
680 | return; |
||
681 | } |
||
682 | // __debugbreak(); |
||
683 | printf("dsbuffer_sz=%d, dsoffset=%d, spbsize=%d\n", dsbuffer_sz, dsoffset, spbsize); |
||
684 | printrds("IDirectSoundBuffer::Unlock()", r); |
||
685 | exit(); |
||
686 | } |
||
687 | |||
688 | dsoffset += spbsize; |
||
689 | dsoffset %= dsbuffer_sz; |
||
690 | } |
||
691 | // directsound part |
||
692 | // end |
||
693 | |||
694 | static int OldRflags = 0; |
||
695 | |||
696 | void sound_play() |
||
697 | { |
||
698 | // printf("%s\n", __FUNCTION__); |
||
699 | maxgap = 2000; |
||
700 | restart_sound(); |
||
701 | } |
||
702 | |||
703 | |||
704 | void sound_stop() |
||
705 | { |
||
706 | // printf("%s\n", __FUNCTION__); |
||
707 | // __debugbreak(); |
||
708 | if(dsbf) |
||
709 | { |
||
710 | dsbf->Stop(); // don't check |
||
711 | clear_buffer(); |
||
712 | } |
||
713 | } |
||
714 | |||
715 | void do_sound() |
||
716 | { |
||
717 | if (savesndtype == 1) |
||
718 | if (fwrite(sndplaybuf,1,spbsize,savesnd)!=spbsize) |
||
719 | savesnddialog(); // write error - disk full - close file |
||
720 | |||
721 | conf.sound.do_sound(); |
||
722 | } |
||
723 | |||
724 | void OnEnterGui() |
||
725 | { |
||
726 | // printf("%s->%p\n", __FUNCTION__, D3dDev); |
||
727 | sound_stop(); |
||
728 | |||
729 | // Вывод GUI при активном d3d exclusive режиме |
||
730 | // на время вывода GUI переход в non exclusive fullscreen |
||
731 | if((temp.rflags & RF_D3DE) && D3dDev) |
||
732 | { |
||
733 | OldRflags = temp.rflags; |
||
734 | SetVideoModeD3d(false); |
||
735 | SendMessage(wnd, WM_USER, 0, 0); |
||
736 | flip(); |
||
737 | } |
||
738 | } |
||
739 | |||
740 | void OnExitGui(bool RestoreVideo) |
||
741 | { |
||
742 | // printf("%s->%p, %d\n", __FUNCTION__, D3dDev, RestoreVideo); |
||
743 | sound_play(); |
||
744 | if(!RestoreVideo) |
||
745 | { |
||
746 | return; |
||
747 | } |
||
748 | |||
749 | if(!D3dDev) |
||
750 | { |
||
751 | return; |
||
752 | } |
||
753 | |||
754 | // Возврат из GUI в d3d exclusive режим |
||
755 | if((temp.rflags & RF_D3DE)) |
||
756 | { |
||
757 | SetVideoModeD3d(true); |
||
758 | } |
||
759 | |||
760 | // Переключение RF_D3DE->RF_D3D (в меню настроек переключен видеодрайвер) |
||
761 | if((OldRflags & RF_D3DE) && (temp.rflags & RF_D3D)) |
||
762 | { |
||
763 | SetVideoModeD3d(false); |
||
764 | } |
||
765 | } |
||
766 | |||
767 | #define STATUS_PRIVILEGE_NOT_HELD ((NTSTATUS)0xC0000061L) |
||
768 | #define SE_INC_BASE_PRIORITY_PRIVILEGE (14L) |
||
769 | #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) |
||
770 | |||
771 | typedef NTSTATUS (NTAPI *TRtlAdjustPrivilege)(ULONG Privilege, BOOLEAN Enable, BOOLEAN Client, PBOOLEAN WasEnabled); |
||
772 | |||
773 | void set_priority() |
||
774 | { |
||
775 | if (!conf.highpriority || !conf.sleepidle) |
||
776 | return; |
||
777 | |||
778 | SYSTEM_INFO SysInfo; |
||
779 | GetSystemInfo(&SysInfo); |
||
780 | ULONG Cpus = SysInfo.dwNumberOfProcessors; |
||
781 | |||
782 | ULONG HighestPriorityClass = HIGH_PRIORITY_CLASS; |
||
783 | |||
784 | if(Cpus > 1) |
||
785 | { |
||
786 | HMODULE NtDll = GetModuleHandle("ntdll.dll"); |
||
787 | TRtlAdjustPrivilege RtlAdjustPrivilege = (TRtlAdjustPrivilege)GetProcAddress(NtDll, "RtlAdjustPrivilege"); |
||
788 | |||
789 | BOOLEAN WasEnabled = FALSE; |
||
790 | NTSTATUS Status = RtlAdjustPrivilege(SE_INC_BASE_PRIORITY_PRIVILEGE, TRUE, FALSE, &WasEnabled); |
||
791 | if(!NT_SUCCESS(Status)) |
||
792 | { |
||
793 | err_printf("enabling SE_INC_BASE_PRIORITY_PRIVILEGE, %X", Status); |
||
794 | if(Status == STATUS_PRIVILEGE_NOT_HELD) |
||
795 | { |
||
796 | err_printf("program not run as administrator or SE_INC_BASE_PRIORITY_PRIVILEGE is not enabled via group policy"); |
||
797 | } |
||
798 | printf("REALTIME_PRIORITY_CLASS not available, fallback to HIGH_PRIORITY_CLASS\n"); |
||
799 | } |
||
800 | else |
||
801 | { |
||
802 | HighestPriorityClass = REALTIME_PRIORITY_CLASS; |
||
803 | } |
||
804 | } |
||
805 | |||
806 | SetPriorityClass(GetCurrentProcess(), HighestPriorityClass); |
||
807 | SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); |
||
808 | } |
||
809 | |||
810 | void adjust_mouse_cursor() |
||
811 | { |
||
812 | unsigned showcurs = conf.input.joymouse || !active || !(conf.fullscr || conf.lockmouse) || dbgbreak; |
||
813 | while (ShowCursor(0) >= 0); // hide cursor |
||
814 | if (showcurs) while (ShowCursor(1) <= 0); // show cursor |
||
815 | if (active && conf.lockmouse && !dbgbreak) |
||
816 | { |
||
817 | RECT rc; GetClientRect(wnd, &rc); |
||
818 | POINT p = { rc.left, rc.top }; |
||
819 | ClientToScreen(wnd, &p); rc.left=p.x, rc.top=p.y; |
||
820 | p.x = rc.right, p.y = rc.bottom; |
||
821 | ClientToScreen(wnd, &p); rc.right=p.x, rc.bottom=p.y; |
||
822 | ClipCursor(&rc); |
||
823 | } else ClipCursor(0); |
||
824 | } |
||
825 | |||
826 | HCURSOR crs[9]; |
||
827 | unsigned char mousedirs[9] = { 10, 8, 9, 2, 0, 1, 6, 4, 5 }; |
||
828 | |||
829 | void updatebitmap() |
||
830 | { |
||
831 | RECT rc; |
||
832 | GetClientRect(wnd, &rc); |
||
833 | DWORD newdx = rc.right - rc.left, newdy = rc.bottom - rc.top; |
||
834 | if (hbm && (bm_dx != newdx || bm_dy != newdy)) |
||
835 | { |
||
836 | DeleteObject(hbm); |
||
837 | hbm = 0; |
||
838 | } |
||
839 | if(sprim) |
||
840 | return; // don't trace window contents in overlay mode |
||
841 | |||
842 | if(hbm) |
||
843 | { |
||
844 | DeleteObject(hbm); |
||
845 | hbm = 0; // keeping bitmap is unsafe - screen paramaters may change |
||
846 | } |
||
847 | |||
848 | if(!hbm) |
||
849 | hbm = CreateCompatibleBitmap(temp.gdidc, newdx, newdy); |
||
850 | |||
851 | HDC dc = CreateCompatibleDC(temp.gdidc); |
||
852 | |||
853 | bm_dx = newdx; bm_dy = newdy; |
||
854 | HGDIOBJ PrevObj = SelectObject(dc, hbm); |
||
855 | //SetDIBColorTable(dc, 0, 0x100, (RGBQUAD*)pal0); |
||
856 | BitBlt(dc, 0, 0, newdx, newdy, temp.gdidc, 0, 0, SRCCOPY); |
||
857 | SelectObject(dc, PrevObj); |
||
858 | DeleteDC(dc); |
||
859 | } |
||
860 | |||
861 | /* |
||
862 | movesize.c |
||
863 | These values are indexes that represent rect sides. These indexes are |
||
864 | used as indexes into rgimpiwx and rgimpiwy (which are indexes into the |
||
865 | the rect structure) which tell the move code where to store the new x & y |
||
866 | coordinates. Notice that when two of these values that represent sides |
||
867 | are added together, we get a unique list of contiguous values starting at |
||
868 | 1 that represent all the ways we can size a rect. That also leaves 0 free |
||
869 | a initialization value. |
||
870 | |||
871 | The reason we need rgimpimpiw is for the keyboard interface - we |
||
872 | incrementally decide what our 'move command' is. With the mouse interface |
||
873 | we know immediately because we registered a mouse hit on the segment(s) |
||
874 | we're moving. |
||
875 | |||
876 | 4 5 |
||
877 | \ ___3___ / |
||
878 | | | |
||
879 | 1 2 |
||
880 | |_______| |
||
881 | / 6 \ |
||
882 | 7 8 |
||
883 | */ |
||
884 | |||
885 | static const int rgimpimpiw[] = {1, 3, 2, 6}; |
||
886 | static const int rgimpiwx[] = |
||
887 | { |
||
888 | 0, // WMSZ_KEYSIZE |
||
889 | 0, // WMSZ_LEFT |
||
890 | 2, // WMSZ_RIGHT |
||
891 | -1, // WMSZ_TOP |
||
892 | 0, // WMSZ_TOPLEFT |
||
893 | 2, // WMSZ_TOPRIGHT |
||
894 | -1, // WMSZ_BOTTOM |
||
895 | 0, // WMSZ_BOTTOMLEFT |
||
896 | 2, // WMSZ_BOTTOMRIGHT |
||
897 | |||
898 | }; |
||
899 | static const int rgimpiwy[] = {0, -1, -1, 1, 1, 1, 3, 3, 3, 1}; |
||
900 | |||
901 | #define WMSZ_KEYSIZE 0 // ;Internal |
||
902 | #define WMSZ_LEFT 1 |
||
903 | #define WMSZ_RIGHT 2 |
||
904 | #define WMSZ_TOP 3 |
||
905 | #define WMSZ_TOPLEFT 4 |
||
906 | #define WMSZ_TOPRIGHT 5 |
||
907 | #define WMSZ_BOTTOM 6 |
||
908 | #define WMSZ_BOTTOMLEFT 7 |
||
909 | #define WMSZ_BOTTOMRIGHT 8 |
||
910 | #define WMSZ_MOVE 9 // ;Internal |
||
911 | #define WMSZ_KEYMOVE 10 // ;Internal |
||
912 | #define WMSZ_SIZEFIRST WMSZ_LEFT // ;Internal |
||
913 | |||
914 | struct MOVESIZEDATA |
||
915 | { |
||
916 | RECT rcDragCursor; |
||
917 | POINT ptMinTrack; |
||
918 | POINT ptMaxTrack; |
||
919 | int cmd; |
||
920 | }; |
||
921 | |||
922 | static void SizeRectX(MOVESIZEDATA *Msd, ULONG Pt) |
||
923 | { |
||
924 | PINT psideDragCursor = ((PINT)(&Msd->rcDragCursor)); |
||
925 | /* |
||
926 | * DO HORIZONTAL |
||
927 | */ |
||
928 | |||
929 | /* |
||
930 | * We know what part of the rect we're moving based on |
||
931 | * what's in cmd. We use cmd as an index into rgimpiw? which |
||
932 | * tells us what part of the rect we're dragging. |
||
933 | */ |
||
934 | |||
935 | /* |
||
936 | * Get the approriate array entry. |
||
937 | */ |
||
938 | int index = (int)rgimpiwx[Msd->cmd]; // AX |
||
939 | // printf("Msd.cmd = %d, idx_x=%d\n", Msd->cmd, index); |
||
940 | |||
941 | /* |
||
942 | * Is it one of the entries we don't map (i.e. -1)? |
||
943 | */ |
||
944 | if (index < 0) |
||
945 | return; |
||
946 | |||
947 | psideDragCursor[index] = GET_X_LPARAM(Pt); |
||
948 | |||
949 | int indexOpp = index ^ 0x2; |
||
950 | |||
951 | /* |
||
952 | * Now check to see if we're below the min or above the max. Get the width |
||
953 | * of the rect in this direction (either x or y) and see if it's bad. If |
||
954 | * so, map the side we're moving to the min or max. |
||
955 | */ |
||
956 | int w = psideDragCursor[index] - psideDragCursor[indexOpp]; |
||
957 | |||
958 | if (indexOpp & 0x2) |
||
959 | { |
||
960 | w = -w; |
||
961 | } |
||
962 | |||
963 | int x; |
||
964 | if(w < Msd->ptMinTrack.x) |
||
965 | { |
||
966 | x = Msd->ptMinTrack.x; |
||
967 | } |
||
968 | else if(w > Msd->ptMaxTrack.x) |
||
969 | { |
||
970 | x = Msd->ptMaxTrack.x; |
||
971 | } |
||
972 | else |
||
973 | { |
||
974 | return; |
||
975 | } |
||
976 | |||
977 | if (indexOpp & 0x2) |
||
978 | { |
||
979 | x = -x; |
||
980 | } |
||
981 | |||
982 | psideDragCursor[index] = x + psideDragCursor[indexOpp]; |
||
983 | } |
||
984 | |||
985 | static void SizeRectY(MOVESIZEDATA *Msd, ULONG Pt) |
||
986 | { |
||
987 | PINT psideDragCursor = ((PINT)(&Msd->rcDragCursor)); |
||
988 | /* |
||
989 | * DO VERTICAL |
||
990 | */ |
||
991 | |||
992 | /* |
||
993 | * We know what part of the rect we're moving based on |
||
994 | * what's in cmd. We use cmd as an index into rgimpiw? which |
||
995 | * tells us what part of the rect we're dragging. |
||
996 | */ |
||
997 | |||
998 | /* |
||
999 | * Get the approriate array entry. |
||
1000 | */ |
||
1001 | int index = (int)rgimpiwy[Msd->cmd]; // AX |
||
1002 | |||
1003 | // printf("idx_y=%d\n", index); |
||
1004 | /* |
||
1005 | * Is it one of the entries we don't map (i.e. -1)? |
||
1006 | */ |
||
1007 | if (index < 0) |
||
1008 | return; |
||
1009 | |||
1010 | psideDragCursor[index] = GET_Y_LPARAM(Pt); |
||
1011 | |||
1012 | int indexOpp = index ^ 0x2; |
||
1013 | |||
1014 | /* |
||
1015 | * Now check to see if we're below the min or above the max. Get the width |
||
1016 | * of the rect in this direction (either x or y) and see if it's bad. If |
||
1017 | * so, map the side we're moving to the min or max. |
||
1018 | */ |
||
1019 | int h = psideDragCursor[index] - psideDragCursor[indexOpp]; |
||
1020 | |||
1021 | if (indexOpp & 0x2) |
||
1022 | { |
||
1023 | h = -h; |
||
1024 | } |
||
1025 | |||
1026 | int y; |
||
1027 | if(h < Msd->ptMinTrack.y) |
||
1028 | { |
||
1029 | y = Msd->ptMinTrack.y; |
||
1030 | } |
||
1031 | else if(h > Msd->ptMaxTrack.y) |
||
1032 | { |
||
1033 | y = Msd->ptMaxTrack.y; |
||
1034 | } |
||
1035 | else |
||
1036 | { |
||
1037 | return; |
||
1038 | } |
||
1039 | |||
1040 | if (indexOpp & 0x2) |
||
1041 | { |
||
1042 | y = -y; |
||
1043 | } |
||
1044 | |||
1045 | psideDragCursor[index] = y + psideDragCursor[indexOpp]; |
||
1046 | } |
||
1047 | |||
1048 | static void SizeRect(MOVESIZEDATA *Msd, ULONG Pt) |
||
1049 | { |
||
1050 | if(Msd->cmd >= _countof(rgimpiwx)) |
||
1051 | { |
||
1052 | return; |
||
1053 | } |
||
1054 | |||
1055 | SizeRectX(Msd, Pt); |
||
1056 | SizeRectY(Msd, Pt); |
||
1057 | } |
||
1058 | |||
1059 | LRESULT CALLBACK WndProc(HWND hwnd,UINT uMessage,WPARAM wparam,LPARAM lparam) |
||
1060 | { |
||
1061 | static bool moving = false; |
||
1062 | |||
1063 | if(uMessage == WM_QUIT) // never heppens |
||
1064 | { |
||
1065 | // __debugbreak(); |
||
1066 | // printf("WM_QUIT\n"); |
||
1067 | exit(); |
||
1068 | } |
||
1069 | |||
1070 | if(uMessage == WM_CLOSE) // never heppens |
||
1071 | { |
||
1072 | // __debugbreak(); |
||
1073 | // printf("WM_CLOSE\n"); |
||
1074 | return 1; |
||
1075 | } |
||
1076 | |||
1077 | #if 1 |
||
1078 | if (uMessage == WM_SETFOCUS && !pause) |
||
1079 | { |
||
1080 | active = 1; setpal(0); |
||
1081 | // sound_play(); |
||
1082 | adjust_mouse_cursor(); |
||
1083 | uMessage = WM_USER; |
||
1084 | } |
||
1085 | |||
1086 | if (uMessage == WM_KILLFOCUS && !pause) |
||
1087 | { |
||
1088 | if (dd) |
||
1089 | dd->FlipToGDISurface(); |
||
1090 | updatebitmap(); |
||
1091 | setpal(1); |
||
1092 | active = 0; |
||
1093 | // sound_stop(); |
||
1094 | conf.lockmouse = 0; |
||
1095 | adjust_mouse_cursor(); |
||
1096 | } |
||
1097 | |||
1098 | if(uMessage == WM_SIZING) |
||
1099 | { |
||
1100 | // printf("WM_SIZING(0x%X)\n", uMessage); |
||
1101 | return TRUE; |
||
1102 | } |
||
1103 | |||
1104 | static bool Captured = false; |
||
1105 | static int x = 0, y = 0; |
||
1106 | static ULONG Mode; |
||
1107 | static MOVESIZEDATA Msd; |
||
1108 | |||
1109 | if(uMessage == WM_LBUTTONUP && Captured) |
||
1110 | { |
||
1111 | // printf("WM_LBUTTONUP(0x%X)\n", uMessage); |
||
1112 | Captured = false; |
||
1113 | ReleaseCapture(); |
||
1114 | return 0; |
||
1115 | } |
||
1116 | |||
1117 | if(uMessage == WM_MOUSEMOVE) |
||
1118 | { |
||
1119 | if(Captured) |
||
1120 | { |
||
1121 | // printf("WM_MOUSEMOVE(0x%X), w=%d\n", uMessage, wparam); |
||
1122 | if(Mode == SC_MOVE) |
||
1123 | { |
||
1124 | POINT p = { GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam) }; |
||
1125 | ClientToScreen(hwnd, &p); |
||
1126 | // printf("nx=%d,ny=%d\n", p.x, p.y); |
||
1127 | int dx=p.x-x, dy=p.y-y; |
||
1128 | // printf("dx=%d,dy=%d\n", dx, dy); |
||
1129 | if(dx == 0 && dy == 0) |
||
1130 | { |
||
1131 | return 0; |
||
1132 | } |
||
1133 | RECT r={}; |
||
1134 | GetWindowRect(hwnd, &r); |
||
1135 | SetWindowPos(hwnd, NULL, r.left+dx, r.top+dy, 0, 0, SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOSIZE | SWP_NOSENDCHANGING); |
||
1136 | x=p.x;y=p.y; |
||
1137 | return 0; |
||
1138 | } |
||
1139 | else if(Mode == SC_SIZE) |
||
1140 | { |
||
1141 | POINT p = { GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam) }; |
||
1142 | ClientToScreen(hwnd, &p); |
||
1143 | ULONG pt = (p.y << 16) | (p.x & 0xFFFF); |
||
1144 | SizeRect(&Msd, pt); |
||
1145 | const RECT &r = Msd.rcDragCursor; |
||
1146 | // printf("r={%d,%d,%d,%d} [%dx%d]\n", r.left, r.top, r.right, r.bottom, r.right - r.left, r.bottom - r.top); |
||
1147 | SetWindowPos(hwnd, NULL, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOSENDCHANGING); |
||
1148 | return 0; |
||
1149 | } |
||
1150 | } |
||
1151 | } |
||
1152 | |||
1153 | // WM_NCLBUTTONDOWN -> WM_SYSCOMMAND(SC_MOVE) -|-> WM_CAPTURECHANGED -> WM_GETMINMAXINFO -> WM_ENTERSIZEMOVE |
||
1154 | // При получении WM_SYSCOMMAND(SC_MOVE) стандартная процедура обработки сообщения запускает модальный цикл |
||
1155 | if(uMessage == WM_SYSCOMMAND) |
||
1156 | { |
||
1157 | // printf("WM_SYSCOMMAND(0x%X), w=%X, l=%X\n", uMessage, wparam, lparam); |
||
1158 | // Кодирование сторон рамки окна для SC_SIZE (код угла получается суммированием кодов смежных сторон) |
||
1159 | // 4 5 |
||
1160 | // \ ___3___ / |
||
1161 | // | | |
||
1162 | // 1 2 |
||
1163 | // |_______| |
||
1164 | // / 6 \ |
||
1165 | // 7 8 |
||
1166 | |||
1167 | ULONG Cmd = (wparam & 0xFFF0); |
||
1168 | ULONG BrdSide = (wparam & 0xF); |
||
1169 | if(Cmd == SC_MOVE) |
||
1170 | { |
||
1171 | x = GET_X_LPARAM(lparam); |
||
1172 | y = GET_Y_LPARAM(lparam); |
||
1173 | SetCapture(hwnd); |
||
1174 | Captured = true; |
||
1175 | Mode = SC_MOVE; |
||
1176 | return 0; |
||
1177 | } |
||
1178 | else if(Cmd == SC_SIZE) |
||
1179 | { |
||
1180 | Mode = SC_SIZE; |
||
1181 | |||
1182 | RECT rcWindow; |
||
1183 | GetWindowRect(hwnd, &rcWindow); |
||
1184 | RECT rcClient; |
||
1185 | GetClientRect(hwnd, &rcClient); |
||
1186 | RECT rcDesktop; |
||
1187 | GetWindowRect(GetDesktopWindow(), &rcDesktop); |
||
1188 | |||
1189 | Msd.cmd = BrdSide; |
||
1190 | CopyRect(&Msd.rcDragCursor, &rcWindow); |
||
1191 | LONG cw = rcClient.right - rcClient.left, ch = rcClient.bottom - rcClient.top; |
||
1192 | LONG ww = rcWindow.right - rcWindow.left, wh = rcWindow.bottom - rcWindow.top; |
||
1193 | LONG dw = rcDesktop.right - rcDesktop.left, dh = rcDesktop.bottom - rcDesktop.top; |
||
1194 | //Msd.ptMinTrack = { LONG(temp.ox) + (ww - cw), LONG(temp.oy) + (wh - ch) }; |
||
1195 | Msd.ptMinTrack.x = LONG(temp.ox) + (ww - cw); // lvd |
||
1196 | Msd.ptMinTrack.y = LONG(temp.oy) + (wh - ch); // lvd |
||
1197 | //Msd.ptMaxTrack = { dw, dh }; |
||
1198 | Msd.ptMaxTrack.x = dw; //lvd |
||
1199 | Msd.ptMaxTrack.y = dh; //lvd |
||
1200 | |||
1201 | SetCapture(hwnd); |
||
1202 | Captured = true; |
||
1203 | SizeRect(&Msd, ULONG(lparam)); |
||
1204 | return 0; |
||
1205 | } |
||
1206 | } |
||
1207 | |||
1208 | /* |
||
1209 | #define WM_NCUAHDRAWCAPTION 0x00AE |
||
1210 | #define WM_NCUAHDRAWFRAME 0x00AF |
||
1211 | if(!(uMessage == WM_SIZING || uMessage == WM_SIZE || uMessage == WM_PAINT || uMessage == WM_NCPAINT |
||
1212 | || uMessage == WM_MOUSEMOVE || uMessage == WM_SETCURSOR || uMessage == WM_GETICON |
||
1213 | || uMessage == WM_IME_SETCONTEXT || uMessage == WM_IME_NOTIFY || uMessage == WM_ACTIVATE |
||
1214 | || uMessage == WM_NCUAHDRAWCAPTION || uMessage == WM_NCUAHDRAWFRAME)) |
||
1215 | { |
||
1216 | printf("MSG(0x%X)\n", uMessage); |
||
1217 | } |
||
1218 | */ |
||
1219 | |||
1220 | if (conf.input.joymouse) |
||
1221 | { |
||
1222 | if (uMessage == WM_LBUTTONDOWN || uMessage == WM_LBUTTONUP) |
||
1223 | { |
||
1224 | input.mousejoy = (input.mousejoy & 0x0F) | (uMessage == WM_LBUTTONDOWN ? 0x10 : 0); |
||
1225 | input.kjoy = (input.kjoy & 0x0F) | (uMessage == WM_LBUTTONDOWN ? 0x10 : 0); |
||
1226 | } |
||
1227 | |||
1228 | if (uMessage == WM_MOUSEMOVE) |
||
1229 | { |
||
1230 | RECT rc; GetClientRect(hwnd, &rc); |
||
1231 | unsigned xx = LOWORD(lparam)*3/(rc.right - rc.left); |
||
1232 | unsigned yy = HIWORD(lparam)*3/(rc.bottom - rc.top); |
||
1233 | unsigned nn = yy*3 + xx; |
||
1234 | // SetClassLongPtr(hwnd, GCLP_HCURSOR, (LONG)crs[nn]); //Alone Coder |
||
1235 | SetCursor(crs[nn]); //Alone Coder |
||
1236 | input.mousejoy = (input.mousejoy & 0x10) | mousedirs[nn]; |
||
1237 | input.kjoy = (input.kjoy & 0x10) | mousedirs[nn]; |
||
1238 | return 0; |
||
1239 | } |
||
1240 | } |
||
1241 | else if (uMessage == WM_LBUTTONDOWN && !conf.lockmouse) |
||
1242 | { |
||
1243 | // printf("%s\n", __FUNCTION__); |
||
1244 | input.nomouse = 20; |
||
1245 | main_mouse(); |
||
1246 | } |
||
1247 | |||
1248 | if(uMessage == WM_ENTERSIZEMOVE) |
||
1249 | { |
||
1250 | // printf("WM_ENTERSIZEMOVE(0x%X)\n", uMessage); |
||
1251 | sound_stop(); |
||
1252 | } |
||
1253 | |||
1254 | if(uMessage == WM_EXITSIZEMOVE) |
||
1255 | { |
||
1256 | sound_play(); |
||
1257 | } |
||
1258 | |||
1259 | if (uMessage == WM_SIZE || uMessage == WM_MOVE || uMessage == WM_USER) |
||
1260 | { |
||
1261 | #if 0 |
||
1262 | printf("%s(WM_SIZE || WM_MOVE || WM_USER)\n", __FUNCTION__); |
||
1263 | RECT rr = {}; |
||
1264 | GetWindowRect(wnd, &rr); |
||
1265 | printf("r={%d,%d,%d,%d} [%dx%d]\n", rr.left, rr.top, rr.right, rr.bottom, rr.right - rr.left, rr.bottom - rr.top); |
||
1266 | #endif |
||
1267 | |||
1268 | GetClientRect(wnd, &temp.client); |
||
1269 | temp.gdx = temp.client.right-temp.client.left; |
||
1270 | temp.gdy = temp.client.bottom-temp.client.top; |
||
1271 | temp.gx = (temp.gdx > temp.ox) ? (temp.gdx-temp.ox)/2 : 0; |
||
1272 | temp.gy = (temp.gdy > temp.oy) ? (temp.gdy-temp.oy)/2 : 0; |
||
1273 | ClientToScreen(wnd, (POINT*)&temp.client.left); |
||
1274 | ClientToScreen(wnd, (POINT*)&temp.client.right); |
||
1275 | adjust_mouse_cursor(); |
||
1276 | if (sprim) |
||
1277 | uMessage = WM_PAINT; |
||
1278 | needclr = 2; |
||
1279 | |||
1280 | if((uMessage == WM_SIZE) && (wparam != SIZE_MINIMIZED) && temp.ox && temp.oy) |
||
1281 | { |
||
1282 | if(wnd && (temp.rflags & RF_D3D)) // skip call from CreateWindow |
||
1283 | { |
||
1284 | // printf("%s(WM_SIZE, temp.rflags & RF_D3D)\n", __FUNCTION__); |
||
1285 | SetVideoModeD3d(false); |
||
1286 | } |
||
1287 | } |
||
1288 | } |
||
1289 | |||
1290 | if (uMessage == WM_PAINT) |
||
1291 | { |
||
1292 | if (sprim) |
||
1293 | { // background for overlay |
||
1294 | RECT rc; |
||
1295 | GetClientRect(hwnd, &rc); |
||
1296 | HBRUSH br = CreateSolidBrush(RGB(0xFF,0x00,0xFF)); |
||
1297 | FillRect(temp.gdidc, &rc, br); |
||
1298 | DeleteObject(br); |
||
1299 | update_overlay(); |
||
1300 | } |
||
1301 | else if (hbm && !active) |
||
1302 | { |
||
1303 | // printf("%s, WM_PAINT\n", __FUNCTION__); |
||
1304 | HDC hcom = CreateCompatibleDC(temp.gdidc); |
||
1305 | HGDIOBJ PrevObj = SelectObject(hcom, hbm); |
||
1306 | BitBlt(temp.gdidc, 0, 0, bm_dx, bm_dy, hcom, 0, 0, SRCCOPY); |
||
1307 | SelectObject(hcom, PrevObj); |
||
1308 | DeleteDC(hcom); |
||
1309 | } |
||
1310 | } |
||
1311 | |||
1312 | if (uMessage == WM_SYSCOMMAND) |
||
1313 | { |
||
1314 | // printf("%s, WM_SYSCOMMAND 0x%04X\n", __FUNCTION__, (ULONG)wparam); |
||
1315 | |||
1316 | switch(wparam & 0xFFF0) |
||
1317 | { |
||
1318 | case SCU_SCALE1: temp.scale = 1; wnd_resize(1); return 0; |
||
1319 | case SCU_SCALE2: temp.scale = 2; wnd_resize(2); return 0; |
||
1320 | case SCU_SCALE3: temp.scale = 3; wnd_resize(3); return 0; |
||
1321 | case SCU_SCALE4: temp.scale = 4; wnd_resize(4); return 0; |
||
1322 | case SCU_LOCK_MOUSE: main_mouse(); return 0; |
||
1323 | case SC_CLOSE: |
||
1324 | if(ConfirmExit()) |
||
1325 | correct_exit(); |
||
1326 | return 0; |
||
1327 | case SC_MINIMIZE: temp.Minimized = true; break; |
||
1328 | |||
1329 | case SC_RESTORE: temp.Minimized = false; break; |
||
1330 | } |
||
1331 | } |
||
1332 | |||
1333 | if (uMessage == WM_DROPFILES) |
||
1334 | { |
||
1335 | HDROP hDrop = (HDROP)wparam; |
||
1336 | DragQueryFile(hDrop, 0, droppedFile, sizeof(droppedFile)); |
||
1337 | DragFinish(hDrop); |
||
1338 | return 0; |
||
1339 | } |
||
1340 | #endif |
||
1341 | |||
1342 | return DefWindowProc(hwnd, uMessage, wparam, lparam); |
||
1343 | } |
||
1344 | |||
1345 | void readdevice(VOID *md, DWORD sz, LPDIRECTINPUTDEVICE dev) |
||
1346 | { |
||
1347 | if (!active || !dev) |
||
1348 | return; |
||
1349 | HRESULT r = dev->GetDeviceState(sz, md); |
||
1350 | if(r == DIERR_INPUTLOST || r == DIERR_NOTACQUIRED) |
||
1351 | { |
||
1352 | r = dev->Acquire(); |
||
1353 | while(r == DIERR_INPUTLOST) |
||
1354 | r = dev->Acquire(); |
||
1355 | |||
1356 | if(r == DIERR_OTHERAPPHASPRIO) // Приложение находится в background |
||
1357 | return; |
||
1358 | |||
1359 | if (r != DI_OK) |
||
1360 | { |
||
1361 | printrdi("IDirectInputDevice::Acquire()", r); |
||
1362 | exit(); |
||
1363 | } |
||
1364 | r = dev->GetDeviceState(sz, md); |
||
1365 | } |
||
1366 | if(r != DI_OK) |
||
1367 | { |
||
1368 | printrdi("IDirectInputDevice::GetDeviceState()", r); |
||
1369 | exit(); |
||
1370 | } |
||
1371 | } |
||
1372 | |||
1373 | void readmouse(DIMOUSESTATE *md) |
||
1374 | { |
||
1375 | memset(md, 0, sizeof *md); |
||
1376 | readdevice(md, sizeof *md, dimouse); |
||
1377 | } |
||
1378 | |||
1379 | void ReadKeyboard(PVOID KbdData) |
||
1380 | { |
||
1381 | readdevice(KbdData, 256, dikeyboard); |
||
1382 | } |
||
1383 | |||
1384 | void setpal(char system) |
||
1385 | { |
||
1386 | if (!active || !dd || !surf0 || !pal) return; |
||
1387 | HRESULT r; |
||
1388 | if (surf0->IsLost() == DDERR_SURFACELOST) surf0->Restore(); |
||
1389 | if ((r = pal->SetEntries(0, 0, 0x100, system ? syspalette : pal0)) != DD_OK) |
||
1390 | { printrdd("IDirectDrawPalette::SetEntries()", r); exit(); } |
||
1391 | } |
||
1392 | |||
1393 | void trim_right(char *str) |
||
1394 | { |
||
1395 | unsigned i; //Alone Coder 0.36.7 |
||
1396 | for (/*unsigned*/ i = strlen(str); i && str[i-1] == ' '; i--); |
||
1397 | str[i] = 0; |
||
1398 | } |
||
1399 | |||
1400 | #define MAX_MODES 512 |
||
1401 | struct MODEPARAM { |
||
1402 | unsigned x,y,b,f; |
||
1403 | } modes[MAX_MODES]; |
||
1404 | unsigned max_modes; |
||
1405 | |||
1406 | // Для инициализации fullscreen режима необходимо выполнение несколтких условий: |
||
1407 | // 1. Размер окна должен совпадать с разрешением экрана, координаты левого верхнего угла должны быть 0, 0 |
||
1408 | // 2. Окно должно иметь расширенный стиль WS_EX_TOPMOST |
||
1409 | // При не выполнении хотя бы одного из пунктов при возврате из fullscreen к окнному режиму на vista и выше будет |
||
1410 | // откючен DWM и окно приобретет "устаревший" вид бордюра |
||
1411 | |||
1412 | static void SetVideoModeD3d(bool Exclusive) |
||
1413 | { |
||
1414 | HRESULT r; |
||
1415 | // printf("%s\n", __FUNCTION__); |
||
1416 | |||
1417 | if(!wnd) |
||
1418 | { |
||
1419 | __debugbreak(); |
||
1420 | } |
||
1421 | |||
1422 | // release textures if exist |
||
1423 | if(SurfTexture) |
||
1424 | { |
||
1425 | r = SurfTexture->Release(); |
||
1426 | if(FAILED(r)) |
||
1427 | { |
||
1428 | __debugbreak(); |
||
1429 | } |
||
1430 | SurfTexture = 0; |
||
1431 | } |
||
1432 | |||
1433 | if(Texture) |
||
1434 | { |
||
1435 | r = Texture->Release(); |
||
1436 | if(FAILED(r)) |
||
1437 | { |
||
1438 | __debugbreak(); |
||
1439 | } |
||
1440 | Texture = 0; |
||
1441 | } |
||
1442 | |||
1443 | bool CreateDevice = false; |
||
1444 | if(!D3dDev) |
||
1445 | { |
||
1446 | CreateDevice = true; |
||
1447 | if(!D3d9) |
||
1448 | { |
||
1449 | StartD3d(wnd); |
||
1450 | } |
||
1451 | } |
||
1452 | |||
1453 | D3DDISPLAYMODE DispMode; |
||
1454 | r = D3d9->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &DispMode); |
||
1455 | if(r != D3D_OK) |
||
1456 | { |
||
1457 | printrdd("IDirect3D::GetAdapterDisplayMode()", r); exit(); |
||
1458 | } |
||
1459 | |||
1460 | D3DPRESENT_PARAMETERS D3dPp = { 0 }; |
||
1461 | if(Exclusive) // exclusive full screen |
||
1462 | { |
||
1463 | #if 0 |
||
1464 | printf("exclusive full screen (%ux%u %uHz)\n", DispMode.Width, DispMode.Height, temp.ofq); |
||
1465 | RECT rr = { }; |
||
1466 | GetWindowRect(wnd, &rr); |
||
1467 | printf("r1={%d,%d,%d,%d} [%dx%d]\n", rr.left, rr.top, rr.right, rr.bottom, rr.right - rr.left, rr.bottom - rr.top); |
||
1468 | printf("SetWindowPos(%p, HWND_TOPMOST, 0, 0, %u, %u)\n", wnd, DispMode.Width, DispMode.Height); |
||
1469 | #endif |
||
1470 | if(!SetWindowPos(wnd, HWND_TOPMOST, 0, 0, DispMode.Width, DispMode.Height, 0)) // Установка WS_EX_TOPMOST |
||
1471 | { |
||
1472 | __debugbreak(); |
||
1473 | } |
||
1474 | #if 0 |
||
1475 | rr = { }; |
||
1476 | GetWindowRect(wnd, &rr); |
||
1477 | printf("r2={%d,%d,%d,%d} [%dx%d]\n", rr.left, rr.top, rr.right, rr.bottom, rr.right - rr.left, rr.bottom - rr.top); |
||
1478 | #endif |
||
1479 | D3dPp.Windowed = FALSE; |
||
1480 | D3dPp.BackBufferWidth = DispMode.Width; |
||
1481 | D3dPp.BackBufferHeight = DispMode.Height; |
||
1482 | D3dPp.BackBufferFormat = DispMode.Format; |
||
1483 | D3dPp.FullScreen_RefreshRateInHz = temp.ofq; |
||
1484 | D3dPp.PresentationInterval = conf.flip ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; |
||
1485 | } |
||
1486 | else // windowed mode |
||
1487 | { |
||
1488 | #if 0 |
||
1489 | printf("windowed mode\n"); |
||
1490 | RECT rr = { }; |
||
1491 | GetWindowRect(wnd, &rr); |
||
1492 | printf("w=%p, r={%d,%d,%d,%d} [%dx%d]\n", wnd, rr.left, rr.top, rr.right, rr.bottom, rr.right - rr.left, rr.bottom - rr.top); |
||
1493 | #endif |
||
1494 | D3dPp.Windowed = TRUE; |
||
1495 | } |
||
1496 | D3dPp.SwapEffect = D3DSWAPEFFECT_DISCARD; |
||
1497 | D3dPp.BackBufferCount = 1; |
||
1498 | D3dPp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; |
||
1499 | D3dPp.hDeviceWindow = wnd; |
||
1500 | |||
1501 | if(CreateDevice) |
||
1502 | { |
||
1503 | r = D3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &D3dPp, &D3dDev); |
||
1504 | if(r != D3D_OK) |
||
1505 | { |
||
1506 | printrdd("IDirect3D::CreateDevice()", r); |
||
1507 | exit(); |
||
1508 | } |
||
1509 | |||
1510 | if(!SUCCEEDED(r = D3dDev->TestCooperativeLevel())) |
||
1511 | { |
||
1512 | printrdd("IDirect3DDevice::TestCooperativeLevel()", r); |
||
1513 | exit(); |
||
1514 | } |
||
1515 | } |
||
1516 | else // reset existing device |
||
1517 | { |
||
1518 | r = D3D_OK; |
||
1519 | do |
||
1520 | { |
||
1521 | if(r != D3D_OK) |
||
1522 | { |
||
1523 | Sleep(10); |
||
1524 | } |
||
1525 | r = D3dDev->Reset(&D3dPp); |
||
1526 | } while(r == D3DERR_DEVICELOST); |
||
1527 | |||
1528 | if (r != DD_OK) |
||
1529 | { |
||
1530 | printrdd("IDirect3DDevice9::Reset()", r); |
||
1531 | // __debugbreak(); |
||
1532 | exit(); |
||
1533 | } |
||
1534 | // printf("D3dDev->Reset(%d, %d)\n", D3dPp.BackBufferWidth, D3dPp.BackBufferHeight); |
||
1535 | } |
||
1536 | |||
1537 | // recreate textures |
||
1538 | // printf("IDirect3DDevice9::CreateTexture(%d,%d)\n", temp.ox, temp.oy); |
||
1539 | r = D3dDev->CreateTexture(temp.ox, temp.oy, 1, D3DUSAGE_DYNAMIC, DispMode.Format, D3DPOOL_DEFAULT, &Texture, 0); |
||
1540 | if (r != DD_OK) |
||
1541 | { printrdd("IDirect3DDevice9::CreateTexture()", r); exit(); } |
||
1542 | r = Texture->GetSurfaceLevel(0, &SurfTexture); |
||
1543 | if (r != DD_OK) |
||
1544 | { printrdd("IDirect3DTexture::GetSurfaceLevel()", r); exit(); } |
||
1545 | if(!SurfTexture) |
||
1546 | __debugbreak(); |
||
1547 | } |
||
1548 | |||
1549 | static bool NeedRestoreDisplayMode = false; |
||
1550 | |||
1551 | void set_vidmode() |
||
1552 | { |
||
1553 | // printf("%s\n", __FUNCTION__); |
||
1554 | if (pal) |
||
1555 | { |
||
1556 | pal->Release(); |
||
1557 | pal = 0; |
||
1558 | } |
||
1559 | |||
1560 | if (surf2) |
||
1561 | { |
||
1562 | surf2->Release(); |
||
1563 | surf2 = 0; |
||
1564 | } |
||
1565 | |||
1566 | if (surf1) |
||
1567 | { |
||
1568 | surf1->Release(); |
||
1569 | surf1 = 0; |
||
1570 | } |
||
1571 | |||
1572 | if (surf0) |
||
1573 | { |
||
1574 | HRESULT r = surf0->Release(); |
||
1575 | if (r != DD_OK) |
||
1576 | { printrdd("surf0->Release()", r); exit(); } |
||
1577 | surf0 = 0; |
||
1578 | } |
||
1579 | |||
1580 | if (sprim) |
||
1581 | { |
||
1582 | sprim->Release(); |
||
1583 | sprim = 0; |
||
1584 | } |
||
1585 | |||
1586 | if (clip) |
||
1587 | { |
||
1588 | clip->Release(); |
||
1589 | clip = 0; |
||
1590 | } |
||
1591 | |||
1592 | if(SurfTexture) |
||
1593 | { |
||
1594 | SurfTexture->Release(); |
||
1595 | SurfTexture = 0; |
||
1596 | } |
||
1597 | |||
1598 | if(Texture) |
||
1599 | { |
||
1600 | HRESULT r = Texture->Release(); |
||
1601 | if(FAILED(r)) |
||
1602 | { |
||
1603 | __debugbreak(); |
||
1604 | } |
||
1605 | Texture = 0; |
||
1606 | } |
||
1607 | |||
1608 | HRESULT r; |
||
1609 | |||
1610 | DDSURFACEDESC desc; |
||
1611 | desc.dwSize = sizeof desc; |
||
1612 | r = dd->GetDisplayMode(&desc); |
||
1613 | if (r != DD_OK) { printrdd("IDirectDraw2::GetDisplayMode()", r); exit(); } |
||
1614 | temp.ofq = desc.dwRefreshRate; // nt only? |
||
1615 | if (!temp.ofq) |
||
1616 | temp.ofq = conf.refresh; |
||
1617 | |||
1618 | // Проверка наличия hw overlay |
||
1619 | if(drivers[conf.driver].flags & RF_OVR) |
||
1620 | { |
||
1621 | DDCAPS Caps; |
||
1622 | Caps.dwSize = sizeof(Caps); |
||
1623 | |||
1624 | if((r = dd->GetCaps(&Caps, NULL)) == DD_OK) |
||
1625 | { |
||
1626 | if(Caps.dwMaxVisibleOverlays == 0) |
||
1627 | { |
||
1628 | errexit("HW Overlay not supported"); |
||
1629 | } |
||
1630 | } |
||
1631 | } |
||
1632 | |||
1633 | // select fullscreen, set window style |
||
1634 | if (temp.rflags & RF_DRIVER) |
||
1635 | temp.rflags |= drivers[conf.driver].flags; |
||
1636 | if (!(temp.rflags & (RF_GDI | RF_OVR | RF_CLIP | RF_D3D))) |
||
1637 | conf.fullscr = 1; |
||
1638 | if ((temp.rflags & RF_32) && desc.ddpfPixelFormat.dwRGBBitCount != 32) |
||
1639 | conf.fullscr = 1; // for chunks via blitter |
||
1640 | |||
1641 | static RECT rc; |
||
1642 | DWORD oldstyle = GetWindowLong(wnd, GWL_STYLE); |
||
1643 | if (oldstyle & WS_CAPTION) |
||
1644 | GetWindowRect(wnd, &rc); |
||
1645 | |||
1646 | unsigned style = conf.fullscr ? WS_VISIBLE | WS_POPUP : WS_VISIBLE | WS_OVERLAPPEDWINDOW; |
||
1647 | if ((oldstyle ^ style) & WS_CAPTION) |
||
1648 | { |
||
1649 | // printf("set style=%X, fullscr=%d\n", style, conf.fullscr); |
||
1650 | SetWindowLong(wnd, GWL_STYLE, style); |
||
1651 | } |
||
1652 | |||
1653 | // select exclusive |
||
1654 | char excl = conf.fullscr; |
||
1655 | if ((temp.rflags & RF_CLIP) && (desc.ddpfPixelFormat.dwRGBBitCount == 8)) |
||
1656 | excl = 1; |
||
1657 | |||
1658 | if (!(temp.rflags & (RF_MON | RF_D3D | RF_D3DE))) |
||
1659 | { |
||
1660 | r = dd->SetCooperativeLevel(wnd, excl ? DDSCL_ALLOWREBOOT | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN : DDSCL_ALLOWREBOOT | DDSCL_NORMAL); |
||
1661 | if (r != DD_OK) { printrdd("IDirectDraw2::SetCooperativeLevel()", r); exit(); } |
||
1662 | } |
||
1663 | |||
1664 | // select resolution |
||
1665 | const unsigned size_x[3] = { 256U, conf.mcx_small, conf.mcx_full }; |
||
1666 | const unsigned size_y[3] = { 192U, conf.mcy_small, conf.mcy_full }; |
||
1667 | temp.ox = temp.scx = size_x[conf.bordersize]; |
||
1668 | temp.oy = temp.scy = size_y[conf.bordersize]; |
||
1669 | |||
1670 | if (temp.rflags & RF_2X) |
||
1671 | { |
||
1672 | temp.ox *=2; temp.oy *= 2; |
||
1673 | if (conf.fast_sl && (temp.rflags & RF_DRIVER) && (temp.rflags & (RF_CLIP | RF_OVR))) |
||
1674 | temp.oy /= 2; |
||
1675 | } |
||
1676 | |||
1677 | if (temp.rflags & RF_3X) temp.ox *= 3, temp.oy *= 3; |
||
1678 | if (temp.rflags & RF_4X) temp.ox *= 4, temp.oy *= 4; |
||
1679 | if (temp.rflags & RF_64x48) temp.ox = 64, temp.oy = 48; |
||
1680 | if (temp.rflags & RF_128x96) temp.ox = 128, temp.oy = 96; |
||
1681 | if (temp.rflags & RF_MON) temp.ox = 640, temp.oy = 480; |
||
1682 | |||
1683 | // printf("temp.ox=%d, temp.oy=%d\n", temp.ox, temp.oy); |
||
1684 | |||
1685 | // select color depth |
||
1686 | temp.obpp = 8; |
||
1687 | if (temp.rflags & (RF_CLIP | RF_D3D | RF_D3DE)) |
||
1688 | temp.obpp = desc.ddpfPixelFormat.dwRGBBitCount; |
||
1689 | if (temp.rflags & (RF_16 | RF_OVR)) |
||
1690 | temp.obpp = 16; |
||
1691 | if (temp.rflags & RF_32) |
||
1692 | temp.obpp = 32; |
||
1693 | if ((temp.rflags & (RF_GDI|RF_8BPCH)) == (RF_GDI|RF_8BPCH)) |
||
1694 | temp.obpp = 32; |
||
1695 | |||
1696 | if (conf.fullscr || ((temp.rflags & RF_MON) && desc.dwHeight < 480)) |
||
1697 | { |
||
1698 | // select minimal screen mode |
||
1699 | unsigned newx = 100000, newy = 100000, newfq = conf.refresh ? conf.refresh : temp.ofq, newb = temp.obpp; |
||
1700 | unsigned minx = temp.ox, miny = temp.oy, needb = temp.obpp; |
||
1701 | |||
1702 | if (temp.rflags & (RF_64x48 | RF_128x96)) |
||
1703 | { |
||
1704 | needb = (temp.rflags & RF_16)? 16:32; |
||
1705 | minx = desc.dwWidth; if (minx < 640) minx = 640; |
||
1706 | miny = desc.dwHeight; if (miny < 480) miny = 480; |
||
1707 | } |
||
1708 | // if (temp.rflags & RF_MON) // - ox=640, oy=480 - set above |
||
1709 | |||
1710 | for (unsigned i = 0; i < max_modes; i++) |
||
1711 | { |
||
1712 | if (modes[i].y < miny || modes[i].x < minx) |
||
1713 | continue; |
||
1714 | if (!(temp.rflags & RF_MON) && modes[i].b != temp.obpp) |
||
1715 | continue; |
||
1716 | if (modes[i].y < conf.minres) |
||
1717 | continue; |
||
1718 | |||
1719 | if ((modes[i].x < newx || modes[i].y < newy) && (!conf.refresh || (modes[i].f == newfq))) |
||
1720 | { |
||
1721 | newx = modes[i].x, newy = modes[i].y; |
||
1722 | if (!conf.refresh && modes[i].f > newfq) |
||
1723 | newfq = modes[i].f; |
||
1724 | } |
||
1725 | } |
||
1726 | |||
1727 | if (newx==100000) |
||
1728 | { |
||
1729 | color(CONSCLR_ERROR); |
||
1730 | printf("can't find situable mode for %d x %d * %d bits\n", temp.ox, temp.oy, temp.obpp); |
||
1731 | exit(); |
||
1732 | } |
||
1733 | |||
1734 | // use minimal or current mode |
||
1735 | if (temp.rflags & (RF_OVR | RF_GDI | RF_CLIP | RF_D3D | RF_D3DE)) |
||
1736 | { |
||
1737 | // leave screen size, if enough width/height |
||
1738 | newx = desc.dwWidth, newy = desc.dwHeight; |
||
1739 | if (newx < minx || newy < miny) |
||
1740 | { |
||
1741 | newx = minx; |
||
1742 | newy = miny; |
||
1743 | } |
||
1744 | // leave color depth, until specified directly |
||
1745 | if (!(temp.rflags & (RF_16 | RF_32))) |
||
1746 | newb = desc.ddpfPixelFormat.dwRGBBitCount; |
||
1747 | } |
||
1748 | |||
1749 | if (desc.dwWidth != newx || desc.dwHeight != newy || temp.ofq != newfq || desc.ddpfPixelFormat.dwRGBBitCount != newb) |
||
1750 | { |
||
1751 | // printf("SetDisplayMode:%ux%u %uHz\n", newx, newy, newfq); |
||
1752 | if ((r = dd->SetDisplayMode(newx, newy, newb, newfq, 0)) != DD_OK) |
||
1753 | { printrdd("IDirectDraw2::SetDisplayMode()", r); exit(); } |
||
1754 | GetSystemPaletteEntries(temp.gdidc, 0, 0x100, syspalette); |
||
1755 | if (newfq) |
||
1756 | temp.ofq = newfq; |
||
1757 | |||
1758 | NeedRestoreDisplayMode = true; |
||
1759 | } |
||
1760 | temp.odx = temp.obpp*(newx - temp.ox)/16, temp.ody = (newy - temp.oy)/2; |
||
1761 | temp.rsx = newx, temp.rsy = newy; |
||
1762 | // printf("vmode=%ux%u %uHz\n", newx, newy, newfq); |
||
1763 | // ShowWindow(wnd, SW_SHOWMAXIMIZED); |
||
1764 | // printf("SetWindowPos(%p, HWND_TOPMOST, 0, 0, %u, %u)\n", wnd, newx, newy); |
||
1765 | if(!SetWindowPos(wnd, HWND_TOPMOST, 0, 0, newx, newy, 0)) // Установка WS_EX_TOPMOST |
||
1766 | { |
||
1767 | __debugbreak(); |
||
1768 | } |
||
1769 | } |
||
1770 | else |
||
1771 | { |
||
1772 | // Восстановление предыдущего видеорежима при возврате из fullscreen (если была переустановка видеорежима) |
||
1773 | if(NeedRestoreDisplayMode) |
||
1774 | { |
||
1775 | if ((r = dd->RestoreDisplayMode()) != DD_OK) |
||
1776 | { printrdd("IDirectDraw2::SetDisplayMode()", r); exit(); } |
||
1777 | NeedRestoreDisplayMode = false; |
||
1778 | } |
||
1779 | // restore window position to last saved position in non-fullscreen mode |
||
1780 | ShowWindow(wnd, SW_SHOWNORMAL); |
||
1781 | if (temp.rflags & RF_GDI) |
||
1782 | { |
||
1783 | RECT client = { 0,0, LONG(temp.ox), LONG(temp.oy) }; |
||
1784 | AdjustWindowRect(&client, WS_VISIBLE | WS_OVERLAPPEDWINDOW, 0); |
||
1785 | rc.right = rc.left + (client.right - client.left); |
||
1786 | rc.bottom = rc.top + (client.bottom - client.top); |
||
1787 | } |
||
1788 | MoveWindow(wnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, 1); |
||
1789 | } |
||
1790 | |||
1791 | if (!(temp.rflags & (RF_D3D | RF_D3DE))) |
||
1792 | { |
||
1793 | dd->FlipToGDISurface(); // don't check result |
||
1794 | } |
||
1795 | |||
1796 | desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; |
||
1797 | desc.dwFlags = DDSD_CAPS; |
||
1798 | |||
1799 | DWORD pl[0x101]; pl[0] = 0x01000300; memcpy(pl+1, pal0, 0x400); |
||
1800 | HPALETTE hpal = CreatePalette((LOGPALETTE*)&pl); |
||
1801 | DeleteObject(SelectPalette(temp.gdidc, hpal, 0)); |
||
1802 | RealizePalette(temp.gdidc); // for RF_GDI and for bitmap, used in WM_PAINT |
||
1803 | |||
1804 | if (temp.rflags & RF_GDI) |
||
1805 | { |
||
1806 | |||
1807 | gdibmp.header.bmiHeader.biWidth = temp.ox; |
||
1808 | gdibmp.header.bmiHeader.biHeight = -(int)temp.oy; |
||
1809 | gdibmp.header.bmiHeader.biBitCount = temp.obpp; |
||
1810 | |||
1811 | } |
||
1812 | else if (temp.rflags & RF_OVR) |
||
1813 | { |
||
1814 | |||
1815 | temp.odx = temp.ody = 0; |
||
1816 | if ((r = dd->CreateSurface(&desc, &sprim, 0)) != DD_OK) |
||
1817 | { printrdd("IDirectDraw2::CreateSurface() [primary,test]", r); exit(); } |
||
1818 | |||
1819 | desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; |
||
1820 | desc.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY; |
||
1821 | desc.dwWidth = temp.ox, desc.dwHeight = temp.oy; |
||
1822 | |||
1823 | // conf.flip = 0; // overlay always synchronized without Flip()! on radeon videocards |
||
1824 | // double flip causes fps drop |
||
1825 | |||
1826 | if (conf.flip) |
||
1827 | { |
||
1828 | desc.dwBackBufferCount = 1; |
||
1829 | desc.dwFlags |= DDSD_BACKBUFFERCOUNT; |
||
1830 | desc.ddsCaps.dwCaps |= DDSCAPS_FLIP | DDSCAPS_COMPLEX; |
||
1831 | } |
||
1832 | |||
1833 | static DDPIXELFORMAT ddpfOverlayFormat16 = { sizeof(DDPIXELFORMAT), DDPF_RGB, 0, {16}, {0xF800}, {0x07E0}, {0x001F}, {0} }; |
||
1834 | static DDPIXELFORMAT ddpfOverlayFormat15 = { sizeof(DDPIXELFORMAT), DDPF_RGB, 0, {16}, {0x7C00}, {0x03E0}, {0x001F}, {0} }; |
||
1835 | static DDPIXELFORMAT ddpfOverlayFormatYUY2 = { sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y','U','Y','2'), {0},{0},{0},{0},{0} }; |
||
1836 | |||
1837 | if (temp.rflags & RF_YUY2) |
||
1838 | goto YUY2; |
||
1839 | |||
1840 | temp.hi15 = 0; |
||
1841 | desc.ddpfPixelFormat = ddpfOverlayFormat16; |
||
1842 | r = dd->CreateSurface(&desc, &surf0, 0); |
||
1843 | |||
1844 | if (r == DDERR_INVALIDPIXELFORMAT) |
||
1845 | { |
||
1846 | temp.hi15 = 1; |
||
1847 | desc.ddpfPixelFormat = ddpfOverlayFormat15; |
||
1848 | r = dd->CreateSurface(&desc, &surf0, 0); |
||
1849 | } |
||
1850 | |||
1851 | if (r == DDERR_INVALIDPIXELFORMAT /*&& !(temp.rflags & RF_RGB)*/) |
||
1852 | { |
||
1853 | YUY2: |
||
1854 | temp.hi15 = 2; |
||
1855 | desc.ddpfPixelFormat = ddpfOverlayFormatYUY2; |
||
1856 | r = dd->CreateSurface(&desc, &surf0, 0); |
||
1857 | } |
||
1858 | |||
1859 | if (r != DD_OK) |
||
1860 | { printrdd("IDirectDraw2::CreateSurface() [overlay]", r); exit(); } |
||
1861 | |||
1862 | } |
||
1863 | else if(temp.rflags & (RF_D3D | RF_D3DE)) // d3d windowed, d3d full screen exclusive |
||
1864 | { |
||
1865 | // printf("%s(RF_D3D)\n", __FUNCTION__); |
||
1866 | // Сначала нужно отмасштабировать окно до нужного размера, а только потом устанавливать видеорежим |
||
1867 | // т.к. видеорежим определяет размеры back buffer'а из размеров окна. |
||
1868 | } |
||
1869 | else // blt, direct video mem |
||
1870 | { |
||
1871 | // desc.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM; |
||
1872 | if (conf.flip && !(temp.rflags & RF_CLIP)) |
||
1873 | { |
||
1874 | desc.dwBackBufferCount = 1; |
||
1875 | desc.dwFlags |= DDSD_BACKBUFFERCOUNT; |
||
1876 | desc.ddsCaps.dwCaps |= DDSCAPS_FLIP | DDSCAPS_COMPLEX; |
||
1877 | } |
||
1878 | |||
1879 | if ((r = dd->CreateSurface(&desc, &surf0, 0)) != DD_OK) |
||
1880 | { printrdd("IDirectDraw2::CreateSurface() [primary1]", r); exit(); } |
||
1881 | |||
1882 | if (temp.rflags & RF_CLIP) |
||
1883 | { |
||
1884 | DDSURFACEDESC SurfDesc; |
||
1885 | SurfDesc.dwSize = sizeof(SurfDesc); |
||
1886 | if((r = surf0->GetSurfaceDesc(&SurfDesc)) != DD_OK) |
||
1887 | { printrdd("IDirectDrawSurface::GetSurfaceDesc()", r); exit(); } |
||
1888 | |||
1889 | desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; |
||
1890 | desc.dwWidth = SurfDesc.dwWidth; desc.dwHeight = SurfDesc.dwHeight; |
||
1891 | desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM; |
||
1892 | |||
1893 | if ((r = dd->CreateSurface(&desc, &surf2, 0)) != DD_OK) |
||
1894 | { printrdd("IDirectDraw2::CreateSurface() [2]", r); exit(); } |
||
1895 | |||
1896 | r = dd->CreateClipper(0, &clip, 0); |
||
1897 | if (r != DD_OK) { printrdd("IDirectDraw2::CreateClipper()", r); exit(); } |
||
1898 | |||
1899 | r = clip->SetHWnd(0, wnd); |
||
1900 | if (r != DD_OK) { printrdd("IDirectDraw2::SetHWnd()", r); exit(); } |
||
1901 | |||
1902 | r = surf0->SetClipper(clip); |
||
1903 | if (r != DD_OK) { printrdd("surf0, IDirectDrawSurface2::SetClipper()", r); exit(); } |
||
1904 | |||
1905 | r = surf2->SetClipper(clip); |
||
1906 | if (r != DD_OK) { printrdd("surf2, IDirectDrawSurface2::SetClipper()", r); exit(); } |
||
1907 | |||
1908 | r = dd->GetDisplayMode(&desc); |
||
1909 | if (r != DD_OK) { printrdd("IDirectDraw2::GetDisplayMode()", r); exit(); } |
||
1910 | if ((temp.rflags & RF_32) && desc.ddpfPixelFormat.dwRGBBitCount != 32) |
||
1911 | errexit("video driver requires 32bit color depth on desktop for this mode"); |
||
1912 | |||
1913 | desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; |
||
1914 | desc.dwWidth = temp.ox; desc.dwHeight = temp.oy; |
||
1915 | |||
1916 | // Видеокарты AMD Radeon HD не поддерживают surface в системной памяти |
||
1917 | // из за этого приходится отдельный буфер в системно памяти и делать программное |
||
1918 | // копирование в surface выделенный в видеопамяти иначе никак не задать выравнивание на 16 байт |
||
1919 | desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM; |
||
1920 | |||
1921 | #ifdef MOD_SSE2 |
||
1922 | if(!(renders[conf.render].flags & RF_1X)) |
||
1923 | { |
||
1924 | SurfPitch1 = (temp.ox * temp.obpp) >> 3; |
||
1925 | SurfPitch1 = (SurfPitch1 + 15) & ~15; // Выравнивание на 16 |
||
1926 | |||
1927 | if(SurfMem1) |
||
1928 | _aligned_free(SurfMem1); |
||
1929 | SurfMem1 = _aligned_malloc(SurfPitch1 * temp.oy, 16); |
||
1930 | FlipBltMethod = FlipBltAlign16; |
||
1931 | } |
||
1932 | else |
||
1933 | #endif |
||
1934 | { |
||
1935 | FlipBltMethod = FlipBltAlign4; |
||
1936 | } |
||
1937 | |||
1938 | r = dd->CreateSurface(&desc, &surf1, 0); |
||
1939 | if (r != DD_OK) { printrdd("IDirectDraw2::CreateSurface()", r); exit(); } |
||
1940 | } |
||
1941 | |||
1942 | if (temp.obpp == 16) |
||
1943 | { |
||
1944 | DDPIXELFORMAT fm; fm.dwSize = sizeof fm; |
||
1945 | if ((r = surf0->GetPixelFormat(&fm)) != DD_OK) |
||
1946 | { printrdd("IDirectDrawSurface2::GetPixelFormat()", r); exit(); } |
||
1947 | |||
1948 | if (fm.dwRBitMask == 0xF800 && fm.dwGBitMask == 0x07E0 && fm.dwBBitMask == 0x001F) |
||
1949 | temp.hi15 = 0; |
||
1950 | else if (fm.dwRBitMask == 0x7C00 && fm.dwGBitMask == 0x03E0 && fm.dwBBitMask == 0x001F) |
||
1951 | temp.hi15 = 1; |
||
1952 | else |
||
1953 | errexit("invalid pixel format (need RGB:5-6-5 or URGB:1-5-5-5)"); |
||
1954 | |||
1955 | } |
||
1956 | else if (temp.obpp == 8) |
||
1957 | { |
||
1958 | |||
1959 | if ((r = dd->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256, syspalette, &pal, 0)) != DD_OK) |
||
1960 | { printrdd("IDirectDraw2::CreatePalette()", r); exit(); } |
||
1961 | if ((r = surf0->SetPalette(pal)) != DD_OK) |
||
1962 | { printrdd("IDirectDrawSurface2::SetPalette()", r); exit(); } |
||
1963 | } |
||
1964 | } |
||
1965 | |||
1966 | if (conf.flip && !(temp.rflags & (RF_GDI|RF_CLIP|RF_D3D|RF_D3DE))) |
||
1967 | { |
||
1968 | DDSCAPS caps = { DDSCAPS_BACKBUFFER }; |
||
1969 | if ((r = surf0->GetAttachedSurface(&caps, &surf1)) != DD_OK) |
||
1970 | { printrdd("IDirectDraw2::GetAttachedSurface()", r); exit(); } |
||
1971 | } |
||
1972 | |||
1973 | // Настраиваем функцию конвертирования из текущего формата в BGR24 |
||
1974 | switch(temp.obpp) |
||
1975 | { |
||
1976 | case 8: ConvBgr24 = ConvPal8ToBgr24; break; |
||
1977 | case 16: |
||
1978 | switch(temp.hi15) |
||
1979 | { |
||
1980 | case 0: ConvBgr24 = ConvRgb16ToBgr24; break; // RGB16 |
||
1981 | case 1: ConvBgr24 = ConvRgb15ToBgr24; break; // RGB15 |
||
1982 | case 2: ConvBgr24 = ConvYuy2ToBgr24; break; // YUY2 |
||
1983 | } |
||
1984 | case 32: ConvBgr24 = ConvBgr32ToBgr24; break; |
||
1985 | } |
||
1986 | |||
1987 | SendMessage(wnd, WM_USER, 0, 0); // setup rectangle for RF_GDI,OVR,CLIP, adjust cursor |
||
1988 | if(!conf.fullscr) |
||
1989 | scale_normal(); |
||
1990 | |||
1991 | if(temp.rflags & (RF_D3D | RF_D3DE)) // d3d windowed, d3d full screen exclusive |
||
1992 | { |
||
1993 | // Сначала нужно отмасштабировать окно до нужного размера, а только потом устанавливать видеорежим |
||
1994 | // т.к. видеорежим определяет размеры back buffer'а из размеров окна. |
||
1995 | SetVideoModeD3d((temp.rflags & RF_D3DE) != 0); |
||
1996 | } |
||
1997 | } |
||
1998 | |||
1999 | HRESULT SetDIDwordProperty(LPDIRECTINPUTDEVICE pdev, REFGUID guidProperty, |
||
2000 | DWORD dwObject, DWORD dwHow, DWORD dwValue) |
||
2001 | { |
||
2002 | DIPROPDWORD dipdw; |
||
2003 | dipdw.diph.dwSize = sizeof(dipdw); |
||
2004 | dipdw.diph.dwHeaderSize = sizeof(dipdw.diph); |
||
2005 | dipdw.diph.dwObj = dwObject; |
||
2006 | dipdw.diph.dwHow = dwHow; |
||
2007 | dipdw.dwData = dwValue; |
||
2008 | return pdev->SetProperty(guidProperty, &dipdw.diph); |
||
2009 | } |
||
2010 | |||
2011 | BOOL CALLBACK InitJoystickInput(LPCDIDEVICEINSTANCE pdinst, LPVOID pvRef) |
||
2012 | { |
||
2013 | HRESULT r; |
||
2014 | LPDIRECTINPUT pdi = (LPDIRECTINPUT)pvRef; |
||
2015 | LPDIRECTINPUTDEVICE dijoyst1; |
||
2016 | LPDIRECTINPUTDEVICE2 dijoyst; |
||
2017 | if ((r = pdi->CreateDevice(pdinst->guidInstance, &dijoyst1, 0)) != DI_OK) |
||
2018 | { |
||
2019 | printrdi("IDirectInput::CreateDevice() (joystick)", r); |
||
2020 | return DIENUM_CONTINUE; |
||
2021 | } |
||
2022 | |||
2023 | r = dijoyst1->QueryInterface(IID_IDirectInputDevice2, (void**)&dijoyst); |
||
2024 | if (r != S_OK) |
||
2025 | { |
||
2026 | printrdi("IDirectInputDevice::QueryInterface(IID_IDirectInputDevice2) [dx5 not found]", r); |
||
2027 | dijoyst1->Release(); |
||
2028 | dijoyst1=0; |
||
2029 | return DIENUM_CONTINUE; |
||
2030 | } |
||
2031 | dijoyst1->Release(); |
||
2032 | |||
2033 | DIDEVICEINSTANCE dide = { sizeof dide }; |
||
2034 | if ((r = dijoyst->GetDeviceInfo(&dide)) != DI_OK) |
||
2035 | { |
||
2036 | printrdi("IDirectInputDevice::GetDeviceInfo()", r); |
||
2037 | return DIENUM_STOP; |
||
2038 | } |
||
2039 | |||
2040 | DIDEVCAPS dc = { sizeof dc }; |
||
2041 | if ((r = dijoyst->GetCapabilities(&dc)) != DI_OK) |
||
2042 | { |
||
2043 | printrdi("IDirectInputDevice::GetCapabilities()", r); |
||
2044 | return DIENUM_STOP; |
||
2045 | } |
||
2046 | |||
2047 | DIPROPDWORD JoyId; |
||
2048 | JoyId.diph.dwSize = sizeof(JoyId); |
||
2049 | JoyId.diph.dwHeaderSize = sizeof(JoyId.diph); |
||
2050 | JoyId.diph.dwObj = 0; |
||
2051 | JoyId.diph.dwHow = DIPH_DEVICE; |
||
2052 | if ((r = dijoyst->GetProperty(DIPROP_JOYSTICKID, &JoyId.diph)) != DI_OK) |
||
2053 | { printrdi("IDirectInputDevice::GetProperty(DIPROP_JOYSTICKID)", r); exit(); } |
||
2054 | |||
2055 | trim_right(dide.tszInstanceName); |
||
2056 | trim_right(dide.tszProductName); |
||
2057 | |||
2058 | CharToOem(dide.tszInstanceName, dide.tszInstanceName); |
||
2059 | CharToOem(dide.tszProductName, dide.tszProductName); |
||
2060 | if (strcmp(dide.tszProductName, dide.tszInstanceName)) |
||
2061 | strcat(dide.tszInstanceName, ", "); |
||
2062 | else |
||
2063 | dide.tszInstanceName[0] = 0; |
||
2064 | |||
2065 | bool UseJoy = (JoyId.dwData == conf.input.JoyId); |
||
2066 | color(CONSCLR_HARDINFO); |
||
2067 | printf("%cjoy(%lu): %s%s (%lu axes, %lu buttons, %lu POVs)\n", UseJoy ? '*' : ' ', JoyId.dwData, |
||
2068 | dide.tszInstanceName, dide.tszProductName, dc.dwAxes, dc.dwButtons, dc.dwPOVs); |
||
2069 | |||
2070 | if(UseJoy) |
||
2071 | { |
||
2072 | if ((r = dijoyst->SetDataFormat(&c_dfDIJoystick)) != DI_OK) |
||
2073 | { |
||
2074 | printrdi("IDirectInputDevice::SetDataFormat() (joystick)", r); |
||
2075 | exit(); |
||
2076 | } |
||
2077 | |||
2078 | if ((r = dijoyst->SetCooperativeLevel(wnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND)) != DI_OK) |
||
2079 | { |
||
2080 | printrdi("IDirectInputDevice::SetCooperativeLevel() (joystick)", r); |
||
2081 | exit(); |
||
2082 | } |
||
2083 | |||
2084 | DIPROPRANGE diprg; |
||
2085 | diprg.diph.dwSize = sizeof(diprg); |
||
2086 | diprg.diph.dwHeaderSize = sizeof(diprg.diph); |
||
2087 | diprg.diph.dwObj = DIJOFS_X; |
||
2088 | diprg.diph.dwHow = DIPH_BYOFFSET; |
||
2089 | diprg.lMin = -1000; |
||
2090 | diprg.lMax = +1000; |
||
2091 | |||
2092 | if ((r = dijoyst->SetProperty(DIPROP_RANGE, &diprg.diph)) != DI_OK) |
||
2093 | { printrdi("IDirectInputDevice::SetProperty(DIPH_RANGE)", r); exit(); } |
||
2094 | |||
2095 | diprg.diph.dwObj = DIJOFS_Y; |
||
2096 | |||
2097 | if ((r = dijoyst->SetProperty(DIPROP_RANGE, &diprg.diph)) != DI_OK) |
||
2098 | { printrdi("IDirectInputDevice::SetProperty(DIPH_RANGE) (y)", r); exit(); } |
||
2099 | |||
2100 | if ((r = SetDIDwordProperty(dijoyst, DIPROP_DEADZONE, DIJOFS_X, DIPH_BYOFFSET, 2000)) != DI_OK) |
||
2101 | { printrdi("IDirectInputDevice::SetProperty(DIPH_DEADZONE)", r); exit(); } |
||
2102 | |||
2103 | if ((r = SetDIDwordProperty(dijoyst, DIPROP_DEADZONE, DIJOFS_Y, DIPH_BYOFFSET, 2000)) != DI_OK) |
||
2104 | { printrdi("IDirectInputDevice::SetProperty(DIPH_DEADZONE) (y)", r); exit(); } |
||
2105 | ::dijoyst = dijoyst; |
||
2106 | } |
||
2107 | else |
||
2108 | { |
||
2109 | dijoyst->Release(); |
||
2110 | } |
||
2111 | return DIENUM_CONTINUE; |
||
2112 | } |
||
2113 | |||
2114 | HRESULT WINAPI callb(LPDDSURFACEDESC surf, void *lpContext) |
||
2115 | { |
||
2116 | if (max_modes >= MAX_MODES) |
||
2117 | return DDENUMRET_CANCEL; |
||
2118 | modes[max_modes].x = surf->dwWidth; |
||
2119 | modes[max_modes].y = surf->dwHeight; |
||
2120 | modes[max_modes].b = surf->ddpfPixelFormat.dwRGBBitCount; |
||
2121 | modes[max_modes].f = surf->dwRefreshRate; |
||
2122 | max_modes++; |
||
2123 | return DDENUMRET_OK; |
||
2124 | } |
||
2125 | |||
2126 | void scale_normal() |
||
2127 | { |
||
2128 | ULONG cmd; |
||
2129 | switch(temp.scale) |
||
2130 | { |
||
2131 | default: |
||
2132 | case 1: cmd = SCU_SCALE1; break; |
||
2133 | case 2: cmd = SCU_SCALE2; break; |
||
2134 | case 3: cmd = SCU_SCALE3; break; |
||
2135 | case 4: cmd = SCU_SCALE4; break; |
||
2136 | } |
||
2137 | SendMessage(wnd, WM_SYSCOMMAND, cmd, 0); // set window size |
||
2138 | } |
||
2139 | |||
2140 | #ifdef _DEBUG |
||
2141 | #define D3D_DLL_NAME "d3d9d.dll" |
||
2142 | #else |
||
2143 | #endif |
||
2144 | #define D3D_DLL_NAME "d3d9.dll" |
||
2145 | |||
2146 | void DbgPrint(const char *s) |
||
2147 | { |
||
2148 | OutputDebugStringA(s); |
||
2149 | } |
||
2150 | |||
2151 | static void StartD3d(HWND Wnd) |
||
2152 | { |
||
2153 | #if 0 |
||
2154 | OutputDebugString(__FUNCTION__"\n"); |
||
2155 | printf("%s\n", __FUNCTION__); |
||
2156 | #endif |
||
2157 | HRESULT r; |
||
2158 | if(!D3d9Dll) |
||
2159 | { |
||
2160 | D3d9Dll = LoadLibrary(D3D_DLL_NAME); |
||
2161 | |||
2162 | if(!D3d9Dll) |
||
2163 | { |
||
2164 | errexit("unable load d3d9.dll"); |
||
2165 | } |
||
2166 | } |
||
2167 | |||
2168 | if(!D3d9) |
||
2169 | { |
||
2170 | typedef IDirect3D9 * (WINAPI *TDirect3DCreate9)(UINT SDKVersion); |
||
2171 | TDirect3DCreate9 Direct3DCreate9 = (TDirect3DCreate9)GetProcAddress(D3d9Dll, "Direct3DCreate9"); |
||
2172 | D3d9 = Direct3DCreate9(D3D_SDK_VERSION); |
||
2173 | if(!D3d9) |
||
2174 | return; |
||
2175 | } |
||
2176 | |||
2177 | } |
||
2178 | |||
2179 | static void CalcWindowSize() |
||
2180 | { |
||
2181 | temp.rflags = renders[conf.render].flags; |
||
2182 | |||
2183 | if (renders[conf.render].func == render_advmame) |
||
2184 | { |
||
2185 | if (conf.videoscale == 2) |
||
2186 | temp.rflags |= RF_2X; |
||
2187 | if (conf.videoscale == 3) |
||
2188 | temp.rflags |= RF_3X; |
||
2189 | if (conf.videoscale == 4) |
||
2190 | temp.rflags |= RF_4X; |
||
2191 | } |
||
2192 | if (temp.rflags & RF_DRIVER) |
||
2193 | temp.rflags |= drivers[conf.driver].flags; |
||
2194 | |||
2195 | // select resolution |
||
2196 | const unsigned size_x[3] = { 256U, conf.mcx_small, conf.mcx_full }; |
||
2197 | const unsigned size_y[3] = { 192U, conf.mcy_small, conf.mcy_full }; |
||
2198 | temp.ox = temp.scx = size_x[conf.bordersize]; |
||
2199 | temp.oy = temp.scy = size_y[conf.bordersize]; |
||
2200 | |||
2201 | if (temp.rflags & RF_2X) |
||
2202 | { |
||
2203 | temp.ox *=2; temp.oy *= 2; |
||
2204 | if (conf.fast_sl && (temp.rflags & RF_DRIVER) && (temp.rflags & (RF_CLIP | RF_OVR))) |
||
2205 | temp.oy /= 2; |
||
2206 | } |
||
2207 | |||
2208 | if (temp.rflags & RF_3X) temp.ox *= 3, temp.oy *= 3; |
||
2209 | if (temp.rflags & RF_4X) temp.ox *= 4, temp.oy *= 4; |
||
2210 | if (temp.rflags & RF_64x48) temp.ox = 64, temp.oy = 48; |
||
2211 | if (temp.rflags & RF_128x96) temp.ox = 128, temp.oy = 96; |
||
2212 | if (temp.rflags & RF_MON) temp.ox = 640, temp.oy = 480; |
||
2213 | } |
||
2214 | |||
2215 | static BOOL WINAPI DdEnumDevs(GUID *DevGuid, PSTR DrvDesc, PSTR DrvName, PVOID Ctx, HMONITOR Hm) |
||
2216 | { |
||
2217 | if(DevGuid) |
||
2218 | { |
||
2219 | memcpy(Ctx, DevGuid, sizeof(GUID)); |
||
2220 | return FALSE; |
||
2221 | } |
||
2222 | return TRUE; |
||
2223 | } |
||
2224 | |||
2225 | void start_dx() |
||
2226 | { |
||
2227 | // printf("%s\n", __FUNCTION__); |
||
2228 | dsbuffer_sz = DSBUFFER_SZ; |
||
2229 | |||
2230 | WNDCLASSEX wc = { 0 }; |
||
2231 | |||
2232 | wc.cbSize = sizeof(WNDCLASSEX); |
||
2233 | |||
2234 | wc.lpfnWndProc = WndProc; |
||
2235 | hIn = wc.hInstance = GetModuleHandle(0); |
||
2236 | wc.lpszClassName = "EMUL_WND"; |
||
2237 | wc.hIcon = LoadIcon(hIn, MAKEINTRESOURCE(IDI_ICON2)); |
||
2238 | wc.hCursor = LoadCursor(0, IDC_ARROW); |
||
2239 | wc.style = CS_HREDRAW | CS_VREDRAW; |
||
2240 | RegisterClassEx(&wc); |
||
2241 | |||
2242 | for (int i = 0; i < 9; i++) |
||
2243 | crs[i] = LoadCursor(hIn, MAKEINTRESOURCE(IDC_C0+i)); |
||
2244 | //Alone Coder 0.36.6 |
||
2245 | RECT rect1; |
||
2246 | SystemParametersInfo(SPI_GETWORKAREA, 0, &rect1, 0); |
||
2247 | //~ |
||
2248 | CalcWindowSize(); |
||
2249 | |||
2250 | int cx = temp.ox*temp.scale, cy = temp.oy*temp.scale; |
||
2251 | |||
2252 | RECT Client = { 0, 0, cx, cy }; |
||
2253 | AdjustWindowRect(&Client, WS_VISIBLE | WS_OVERLAPPEDWINDOW, 0); |
||
2254 | cx = Client.right - Client.left; |
||
2255 | cy = Client.bottom - Client.top; |
||
2256 | int winx = rect1.left + (rect1.right - rect1.left - cx) / 2; |
||
2257 | int winy = rect1.top + (rect1.bottom - rect1.top - cy) / 2; |
||
2258 | |||
2259 | wnd = CreateWindowEx(0, "EMUL_WND", "UnrealSpeccy", WS_VISIBLE|WS_OVERLAPPEDWINDOW, |
||
2260 | winx, winy, cx, cy, NULL, NULL, hIn, NULL); |
||
2261 | |||
2262 | if(!wnd) |
||
2263 | { |
||
2264 | __debugbreak(); |
||
2265 | } |
||
2266 | |||
2267 | DragAcceptFiles(wnd, 1); |
||
2268 | |||
2269 | temp.gdidc = GetDC(wnd); |
||
2270 | GetSystemPaletteEntries(temp.gdidc, 0, 0x100, syspalette); |
||
2271 | |||
2272 | HMENU sys = GetSystemMenu(wnd, 0); |
||
2273 | if(sys) |
||
2274 | { |
||
2275 | AppendMenu(sys, MF_SEPARATOR, 0, 0); |
||
2276 | AppendMenu(sys, MF_STRING, SCU_SCALE1, "x1"); |
||
2277 | AppendMenu(sys, MF_STRING, SCU_SCALE2, "x2"); |
||
2278 | AppendMenu(sys, MF_STRING, SCU_SCALE3, "x3"); |
||
2279 | AppendMenu(sys, MF_STRING, SCU_SCALE4, "x4"); |
||
2280 | AppendMenu(sys, MF_STRING, SCU_LOCK_MOUSE, "&Lock mouse"); |
||
2281 | } |
||
2282 | |||
2283 | InitCommonControls(); |
||
2284 | |||
2285 | HRESULT r; |
||
2286 | GUID DdDevGuid; |
||
2287 | if((r = DirectDrawEnumerateEx(DdEnumDevs, &DdDevGuid, DDENUM_ATTACHEDSECONDARYDEVICES)) != DD_OK) |
||
2288 | { printrdd("DirectDrawEnumerate()", r); exit(); } |
||
2289 | |||
2290 | LPDIRECTDRAW dd0; |
||
2291 | if ((r = DirectDrawCreate(0 /*&DdDevGuid*/, &dd0, 0)) != DD_OK) |
||
2292 | { printrdd("DirectDrawCreate()", r); exit(); } |
||
2293 | |||
2294 | if ((r = dd0->QueryInterface(IID_IDirectDraw2, (void**)&dd)) != DD_OK) |
||
2295 | { printrdd("IDirectDraw::QueryInterface(IID_IDirectDraw2)", r); exit(); } |
||
2296 | |||
2297 | dd0->Release(); |
||
2298 | |||
2299 | color(CONSCLR_HARDITEM); printf("gfx: "); |
||
2300 | |||
2301 | char vmodel[MAX_DDDEVICEID_STRING + 32]; *vmodel = 0; |
||
2302 | if (conf.detect_video) |
||
2303 | { |
||
2304 | LPDIRECTDRAW4 dd4; |
||
2305 | if ((r = dd->QueryInterface(IID_IDirectDraw4, (void**)&dd4)) == DD_OK) |
||
2306 | { |
||
2307 | DDDEVICEIDENTIFIER di; |
||
2308 | if (dd4->GetDeviceIdentifier(&di, 0) == DD_OK) |
||
2309 | { |
||
2310 | trim_right(di.szDescription); |
||
2311 | CharToOem(di.szDescription, di.szDescription); |
||
2312 | sprintf(vmodel, "%04lX-%04lX (%s)", di.dwVendorId, di.dwDeviceId, di.szDescription); |
||
2313 | } |
||
2314 | else |
||
2315 | sprintf(vmodel, "unknown device"); |
||
2316 | dd4->Release(); |
||
2317 | } |
||
2318 | if (*vmodel) |
||
2319 | strcat(vmodel, ", "); |
||
2320 | } |
||
2321 | DDCAPS caps; |
||
2322 | caps.dwSize = sizeof caps; |
||
2323 | dd->GetCaps(&caps, 0); |
||
2324 | |||
2325 | color(CONSCLR_HARDINFO); |
||
2326 | |||
2327 | const u32 Vmem = caps.dwVidMemTotal; |
||
2328 | printf("%s%uMb VRAM available\n", vmodel, Vmem/(1024U*1024U)+((Vmem%(1024U*1024U))>512U*1024U)); |
||
2329 | |||
2330 | max_modes = 0; |
||
2331 | dd->EnumDisplayModes(DDEDM_REFRESHRATES | DDEDM_STANDARDVGAMODES, 0, 0, callb); |
||
2332 | |||
2333 | if((temp.rflags & (RF_D3D | RF_D3DE))) |
||
2334 | StartD3d(wnd); |
||
2335 | |||
2336 | WAVEFORMATEX wf = { 0 }; |
||
2337 | wf.wFormatTag = WAVE_FORMAT_PCM; |
||
2338 | wf.nSamplesPerSec = conf.sound.fq; |
||
2339 | wf.nChannels = 2; |
||
2340 | wf.wBitsPerSample = 16; |
||
2341 | wf.nBlockAlign = 4; |
||
2342 | wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign; |
||
2343 | |||
2344 | if (conf.sound.do_sound == do_sound_wave) |
||
2345 | { |
||
2346 | if ((r = waveOutOpen(&hwo, WAVE_MAPPER, &wf, 0, 0, CALLBACK_NULL)) != MMSYSERR_NOERROR) |
||
2347 | { printrmm("waveOutOpen()", r); hwo = 0; goto sfail; } |
||
2348 | wqhead = 0, wqtail = 0; |
||
2349 | } |
||
2350 | else if (conf.sound.do_sound == do_sound_ds) |
||
2351 | { |
||
2352 | |||
2353 | if ((r = DirectSoundCreate(0, &ds, 0)) != DS_OK) |
||
2354 | { printrds("DirectSoundCreate()", r); goto sfail; } |
||
2355 | |||
2356 | r = -1; |
||
2357 | if (conf.sound.dsprimary) r = ds->SetCooperativeLevel(wnd, DSSCL_WRITEPRIMARY); |
||
2358 | if (r != DS_OK) r = ds->SetCooperativeLevel(wnd, DSSCL_NORMAL), conf.sound.dsprimary = 0; |
||
2359 | if (r != DS_OK) { printrds("IDirectSound::SetCooperativeLevel()", r); goto sfail; } |
||
2360 | |||
2361 | DSBUFFERDESC dsdesc = { sizeof(DSBUFFERDESC) }; |
||
2362 | r = -1; |
||
2363 | |||
2364 | if (conf.sound.dsprimary) |
||
2365 | { |
||
2366 | |||
2367 | dsdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_PRIMARYBUFFER; |
||
2368 | dsdesc.dwBufferBytes = 0; |
||
2369 | dsdesc.lpwfxFormat = 0; |
||
2370 | r = ds->CreateSoundBuffer(&dsdesc, &dsbf, 0); |
||
2371 | |||
2372 | if (r != DS_OK) { printrds("IDirectSound::CreateSoundBuffer() [primary]", r); } |
||
2373 | else |
||
2374 | { |
||
2375 | r = dsbf->SetFormat(&wf); |
||
2376 | if (r != DS_OK) { printrds("IDirectSoundBuffer::SetFormat()", r); goto sfail; } |
||
2377 | DSBCAPS caps; caps.dwSize = sizeof caps; dsbf->GetCaps(&caps); |
||
2378 | dsbuffer_sz = caps.dwBufferBytes; |
||
2379 | } |
||
2380 | } |
||
2381 | |||
2382 | if (r != DS_OK) |
||
2383 | { |
||
2384 | dsdesc.lpwfxFormat = &wf; |
||
2385 | dsdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS; |
||
2386 | dsbuffer_sz = dsdesc.dwBufferBytes = DSBUFFER_SZ; |
||
2387 | if ((r = ds->CreateSoundBuffer(&dsdesc, &dsbf, 0)) != DS_OK) |
||
2388 | { |
||
2389 | printrds("IDirectSound::CreateSoundBuffer()", r); |
||
2390 | goto sfail; |
||
2391 | } |
||
2392 | |||
2393 | conf.sound.dsprimary = 0; |
||
2394 | } |
||
2395 | |||
2396 | dsoffset = dsbuffer_sz/4; |
||
2397 | |||
2398 | } |
||
2399 | else |
||
2400 | { |
||
2401 | sfail: |
||
2402 | conf.sound.do_sound = do_sound_none; |
||
2403 | } |
||
2404 | |||
2405 | LPDIRECTINPUT di; |
||
2406 | r = DirectInputCreate(hIn,DIRECTINPUT_VERSION,&di,0); |
||
2407 | |||
2408 | if ((r != DI_OK) && (r = DirectInputCreate(hIn,0x0300,&di,0)) != DI_OK) |
||
2409 | { |
||
2410 | printrdi("DirectInputCreate()", r); |
||
2411 | exit(); |
||
2412 | } |
||
2413 | |||
2414 | if((r = di->CreateDevice(GUID_SysKeyboard, &dikeyboard, 0)) != DI_OK) |
||
2415 | { |
||
2416 | printrdi("IDirectInputDevice::CreateDevice() (keyboard)", r); |
||
2417 | exit(); |
||
2418 | } |
||
2419 | |||
2420 | if((r = dikeyboard->SetDataFormat(&c_dfDIKeyboard)) != DI_OK) |
||
2421 | { |
||
2422 | printrdi("IDirectInputDevice::SetDataFormat() (keyboard)", r); |
||
2423 | exit(); |
||
2424 | } |
||
2425 | |||
2426 | if((r = dikeyboard->SetCooperativeLevel(wnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE)) != DI_OK) |
||
2427 | { |
||
2428 | printrdi("IDirectInputDevice::SetCooperativeLevel() (keyboard)", r); |
||
2429 | exit(); |
||
2430 | } |
||
2431 | |||
2432 | if ((r = di->CreateDevice(GUID_SysMouse, &dimouse, 0)) == DI_OK) |
||
2433 | { |
||
2434 | if ((r = dimouse->SetDataFormat(&c_dfDIMouse)) != DI_OK) |
||
2435 | { |
||
2436 | printrdi("IDirectInputDevice::SetDataFormat() (mouse)", r); |
||
2437 | exit(); |
||
2438 | } |
||
2439 | |||
2440 | if ((r = dimouse->SetCooperativeLevel(wnd, DISCL_FOREGROUND|DISCL_NONEXCLUSIVE)) != DI_OK) |
||
2441 | { |
||
2442 | printrdi("IDirectInputDevice::SetCooperativeLevel() (mouse)", r); |
||
2443 | exit(); |
||
2444 | } |
||
2445 | DIPROPDWORD dipdw = { 0 }; |
||
2446 | dipdw.diph.dwSize = sizeof(dipdw); |
||
2447 | dipdw.diph.dwHeaderSize = sizeof(dipdw.diph); |
||
2448 | dipdw.diph.dwHow = DIPH_DEVICE; |
||
2449 | dipdw.dwData = DIPROPAXISMODE_ABS; |
||
2450 | if ((r = dimouse->SetProperty(DIPROP_AXISMODE, &dipdw.diph)) != DI_OK) |
||
2451 | { |
||
2452 | printrdi("IDirectInputDevice::SetProperty() (mouse)", r); |
||
2453 | exit(); |
||
2454 | } |
||
2455 | } |
||
2456 | else |
||
2457 | { |
||
2458 | color(CONSCLR_WARNING); |
||
2459 | printf("warning: no mouse\n"); |
||
2460 | dimouse = 0; |
||
2461 | } |
||
2462 | |||
2463 | if ((r = di->EnumDevices(DIDEVTYPE_JOYSTICK, InitJoystickInput, di, DIEDFL_ATTACHEDONLY)) != DI_OK) |
||
2464 | { |
||
2465 | printrdi("IDirectInput::EnumDevices(DIDEVTYPE_JOYSTICK,...)", r); |
||
2466 | exit(); |
||
2467 | } |
||
2468 | |||
2469 | di->Release(); |
||
2470 | //[vv] SetKeyboardState(kbdpc); // fix bug in win95 |
||
2471 | } |
||
2472 | |||
2473 | static void DoneD3d(bool DeInitDll) |
||
2474 | { |
||
2475 | // printf("%s(%d)\n", __FUNCTION__, DeInitDll); |
||
2476 | HRESULT r; |
||
2477 | if(SurfTexture) |
||
2478 | { |
||
2479 | r = SurfTexture->Release(); |
||
2480 | if(FAILED(r)) |
||
2481 | { |
||
2482 | __debugbreak(); |
||
2483 | } |
||
2484 | SurfTexture = 0; |
||
2485 | } |
||
2486 | if(Texture) |
||
2487 | { |
||
2488 | r = Texture->Release(); |
||
2489 | if(FAILED(r)) |
||
2490 | { |
||
2491 | __debugbreak(); |
||
2492 | } |
||
2493 | Texture = 0; |
||
2494 | } |
||
2495 | if(D3dDev) |
||
2496 | { |
||
2497 | r = D3dDev->Release(); |
||
2498 | if(FAILED(r)) |
||
2499 | { |
||
2500 | __debugbreak(); |
||
2501 | } |
||
2502 | D3dDev = 0; |
||
2503 | } |
||
2504 | if(D3d9) |
||
2505 | { |
||
2506 | r = D3d9->Release(); |
||
2507 | if(FAILED(r)) |
||
2508 | { |
||
2509 | __debugbreak(); |
||
2510 | } |
||
2511 | D3d9 = 0; |
||
2512 | } |
||
2513 | if(DeInitDll && D3d9Dll) |
||
2514 | { |
||
2515 | FreeLibrary(D3d9Dll); |
||
2516 | D3d9Dll = 0; |
||
2517 | } |
||
2518 | } |
||
2519 | |||
2520 | void done_dx() |
||
2521 | { |
||
2522 | sound_stop(); |
||
2523 | if (pal) pal->Release(); pal = 0; |
||
2524 | if (surf2) surf2->Release(); surf2 = 0; |
||
2525 | if (surf1) surf1->Release(); surf1 = 0; |
||
2526 | if (surf0) surf0->Release(); surf0 = 0; |
||
2527 | if (sprim) sprim->Release(); sprim = 0; |
||
2528 | if (clip) clip->Release(); clip = 0; |
||
2529 | if (dd) dd->Release(); dd = 0; |
||
2530 | if (SurfMem1) _aligned_free(SurfMem1); SurfMem1 = 0; |
||
2531 | if (dikeyboard) dikeyboard->Unacquire(), dikeyboard->Release(); dikeyboard = 0; |
||
2532 | if (dimouse) dimouse->Unacquire(), dimouse->Release(); dimouse = 0; |
||
2533 | if (dijoyst) dijoyst->Unacquire(), dijoyst->Release(); dijoyst = 0; |
||
2534 | if (hwo) { waveOutReset(hwo); /* waveOutUnprepareHeader()'s ? */ waveOutClose(hwo); } |
||
2535 | if (dsbf) dsbf->Release(); dsbf = 0; |
||
2536 | if (ds) ds->Release(); ds = 0; |
||
2537 | if (hbm) DeleteObject(hbm); hbm = 0; |
||
2538 | if (temp.gdidc) ReleaseDC(wnd, temp.gdidc); temp.gdidc = 0; |
||
2539 | DoneD3d(); |
||
2540 | if (wnd) DestroyWindow(wnd); |
||
2541 | } |