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