Subversion Repositories pentevo

Rev

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
}