1 | /* ScummVM - Scumm Interpreter
|
---|
2 | * Copyright (C) 2001 Ludvig Strigeus
|
---|
3 | *
|
---|
4 | * This program is free software; you can redistribute it and/or
|
---|
5 | * modify it under the terms of the GNU General Public License
|
---|
6 | * as published by the Free Software Foundation; either version 2
|
---|
7 | * of the License, or (at your option) any later version.
|
---|
8 |
|
---|
9 | * This program is distributed in the hope that it will be useful,
|
---|
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
12 | * GNU General Public License for more details.
|
---|
13 |
|
---|
14 | * You should have received a copy of the GNU General Public License
|
---|
15 | * along with this program; if not, write to the Free Software
|
---|
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
---|
17 | *
|
---|
18 | * $Header: /cvsroot/scummvm/scummvm/windows.cpp,v 1.25 2002/02/06 18:12:30 mcleod Exp $
|
---|
19 | */
|
---|
20 |
|
---|
21 | #include "stdafx.h"
|
---|
22 | #include <assert.h>
|
---|
23 |
|
---|
24 | #include "scumm.h"
|
---|
25 | #include "sound.h"
|
---|
26 | #include "gui.h"
|
---|
27 |
|
---|
28 | #if !defined(ALLOW_GDI)
|
---|
29 | #error The GDI driver is not as complete as the SDL driver. You need to define ALLOW_GDI to use this driver.
|
---|
30 | #endif
|
---|
31 |
|
---|
32 | #define SRC_WIDTH 320
|
---|
33 | #define SRC_HEIGHT 200
|
---|
34 | #define SRC_PITCH (320)
|
---|
35 |
|
---|
36 | #define DEST_WIDTH 640
|
---|
37 | #define DEST_HEIGHT 400
|
---|
38 |
|
---|
39 | #define USE_DIRECTX 0
|
---|
40 | #define USE_DRAWDIB 0
|
---|
41 | #define USE_GDI 1
|
---|
42 |
|
---|
43 | #define SAMPLES_PER_SEC 22050
|
---|
44 | #define BUFFER_SIZE (8192)
|
---|
45 | #define BITS_PER_SAMPLE 16
|
---|
46 |
|
---|
47 | #define WS_SCUMMWINDOW (WS_OVERLAPPEDWINDOW)
|
---|
48 | #define WS_SCUMMFULLSCREEN (WS_POPUPWINDOW | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX)
|
---|
49 |
|
---|
50 | static bool shutdown;
|
---|
51 |
|
---|
52 | #if USE_GDI
|
---|
53 | typedef struct DIB
|
---|
54 | {
|
---|
55 | HBITMAP hSect;
|
---|
56 | byte *buf;
|
---|
57 | RGBQUAD *pal;
|
---|
58 | bool new_pal;
|
---|
59 | } DIB;
|
---|
60 | #endif
|
---|
61 |
|
---|
62 | class WndMan
|
---|
63 | {
|
---|
64 | HMODULE hInst;
|
---|
65 | bool terminated;
|
---|
66 |
|
---|
67 | #if USE_GDI
|
---|
68 | public:
|
---|
69 | DIB dib;
|
---|
70 | private:
|
---|
71 | #endif
|
---|
72 |
|
---|
73 | public:
|
---|
74 | HWND hWnd;
|
---|
75 | bool fscreen;
|
---|
76 |
|
---|
77 | byte *_vgabuf;
|
---|
78 |
|
---|
79 | Scumm *_scumm;
|
---|
80 |
|
---|
81 | HANDLE _event;
|
---|
82 | DWORD _threadId;
|
---|
83 | HWAVEOUT _handle;
|
---|
84 | WAVEHDR _hdr[2];
|
---|
85 |
|
---|
86 | public:
|
---|
87 | void init();
|
---|
88 |
|
---|
89 | bool handleMessage();
|
---|
90 | void run();
|
---|
91 | void setPalette(byte *ctab, int first, int num);
|
---|
92 | void writeToScreen();
|
---|
93 | void switchFullScreen(bool fs);
|
---|
94 |
|
---|
95 | void prepare_header(WAVEHDR *wh, int i);
|
---|
96 | void sound_init();
|
---|
97 | static DWORD _stdcall sound_thread(WndMan *wm);
|
---|
98 |
|
---|
99 | #if USE_GDI
|
---|
100 | bool allocateDIB(int w, int h);
|
---|
101 | #endif
|
---|
102 | };
|
---|
103 |
|
---|
104 |
|
---|
105 | void Error(const char *msg)
|
---|
106 | {
|
---|
107 | OutputDebugString(msg);
|
---|
108 | MessageBoxA(0, msg, "Error", MB_ICONSTOP);
|
---|
109 | exit(1);
|
---|
110 | }
|
---|
111 |
|
---|
112 | int sel;
|
---|
113 | Scumm scumm;
|
---|
114 | ScummDebugger debugger;
|
---|
115 | Gui gui;
|
---|
116 | SoundEngine sound;
|
---|
117 | SOUND_DRIVER_TYPE snd_driv;
|
---|
118 |
|
---|
119 | WndMan wm[1];
|
---|
120 | byte veryFastMode;
|
---|
121 |
|
---|
122 | void modifyslot(int sel, int what);
|
---|
123 |
|
---|
124 | int mapKey(int key) {
|
---|
125 | if (key>=VK_F1 && key<=VK_F9) {
|
---|
126 | return key - VK_F1 + 315;
|
---|
127 | }
|
---|
128 | return key;
|
---|
129 | }
|
---|
130 |
|
---|
131 | static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
|
---|
132 | WndMan *wm = (WndMan*)GetWindowLong(hWnd, GWL_USERDATA);
|
---|
133 | RECT r;
|
---|
134 |
|
---|
135 | switch (message)
|
---|
136 | {
|
---|
137 | case WM_DESTROY:
|
---|
138 | case WM_CLOSE:
|
---|
139 | exit(0);
|
---|
140 | break;
|
---|
141 | case WM_KEYDOWN:
|
---|
142 | if (wParam>='0' && wParam<='9')
|
---|
143 | {
|
---|
144 | wm->_scumm->_saveLoadSlot = wParam - '0';
|
---|
145 | if (GetAsyncKeyState(VK_SHIFT)<0)
|
---|
146 | {
|
---|
147 | sprintf(wm->_scumm->_saveLoadName, "Quicksave %d", wm->_scumm->_saveLoadSlot);
|
---|
148 | wm->_scumm->_saveLoadFlag = 1;
|
---|
149 | }
|
---|
150 | else if (GetAsyncKeyState(VK_CONTROL)<0) wm->_scumm->_saveLoadFlag = 2;
|
---|
151 | wm->_scumm->_saveLoadCompatible = false;
|
---|
152 | }
|
---|
153 |
|
---|
154 | if (GetAsyncKeyState(VK_CONTROL)<0) {
|
---|
155 | if (wParam=='F') {
|
---|
156 | wm->_scumm->_fastMode ^= 1;
|
---|
157 | }
|
---|
158 |
|
---|
159 | if (wParam=='G') {
|
---|
160 | veryFastMode ^= 1;
|
---|
161 | }
|
---|
162 |
|
---|
163 | if (wParam=='D') {
|
---|
164 | debugger.attach(wm->_scumm);
|
---|
165 | }
|
---|
166 |
|
---|
167 | if (wParam=='S') {
|
---|
168 | wm->_scumm->resourceStats();
|
---|
169 | }
|
---|
170 | }
|
---|
171 |
|
---|
172 | if ((GetAsyncKeyState(VK_MENU)<0) && (wParam == VK_RETURN))
|
---|
173 | {
|
---|
174 | wm->switchFullScreen(!wm->fscreen);
|
---|
175 | }
|
---|
176 |
|
---|
177 | wm->_scumm->_keyPressed = mapKey(wParam);
|
---|
178 | break;
|
---|
179 |
|
---|
180 | case WM_MOUSEMOVE:
|
---|
181 | GetClientRect(hWnd, &r);
|
---|
182 | wm->_scumm->mouse.x = (SRC_WIDTH * ((int16*)&lParam)[0]) / (r.right - r.left);
|
---|
183 | wm->_scumm->mouse.y = (SRC_HEIGHT * ((int16*)&lParam)[1]) / (r.bottom - r.top);
|
---|
184 | break;
|
---|
185 | case WM_LBUTTONDOWN:
|
---|
186 | wm->_scumm->_leftBtnPressed |= msClicked|msDown;
|
---|
187 | break;
|
---|
188 | case WM_LBUTTONUP:
|
---|
189 | wm->_scumm->_leftBtnPressed &= ~msDown;
|
---|
190 | break;
|
---|
191 | case WM_RBUTTONDOWN:
|
---|
192 | wm->_scumm->_rightBtnPressed |= msClicked|msDown;
|
---|
193 | break;
|
---|
194 | case WM_RBUTTONUP:
|
---|
195 | wm->_scumm->_rightBtnPressed &= ~msDown;
|
---|
196 | break;
|
---|
197 |
|
---|
198 | case WM_SYSCOMMAND:
|
---|
199 |
|
---|
200 | switch (wParam)
|
---|
201 | {
|
---|
202 | case SC_MAXIMIZE:
|
---|
203 | wm->switchFullScreen(true);
|
---|
204 | break;
|
---|
205 | case SC_RESTORE:
|
---|
206 | wm->switchFullScreen(!wm->fscreen);
|
---|
207 | break;
|
---|
208 | default:
|
---|
209 | return DefWindowProc(hWnd, message, wParam, lParam);
|
---|
210 | }
|
---|
211 | break;
|
---|
212 |
|
---|
213 | default:
|
---|
214 | return DefWindowProc(hWnd, message, wParam, lParam);
|
---|
215 | }
|
---|
216 | return 0;
|
---|
217 | }
|
---|
218 |
|
---|
219 | #if USE_GDI
|
---|
220 |
|
---|
221 | bool WndMan::allocateDIB(int w, int h)
|
---|
222 | {
|
---|
223 | struct
|
---|
224 | {
|
---|
225 | BITMAPINFOHEADER bih;
|
---|
226 | RGBQUAD rgb[256];
|
---|
227 | } d;
|
---|
228 |
|
---|
229 | if (dib.hSect) return true;
|
---|
230 |
|
---|
231 | memset(&d.bih, 0, sizeof(d.bih));
|
---|
232 | d.bih.biSize = sizeof(d.bih);
|
---|
233 | d.bih.biWidth = w;
|
---|
234 | d.bih.biHeight = -h;
|
---|
235 | d.bih.biPlanes = 1;
|
---|
236 | d.bih.biBitCount = 8;
|
---|
237 | d.bih.biCompression = BI_RGB;
|
---|
238 |
|
---|
239 | memcpy(d.rgb, dib.pal, 256*sizeof(RGBQUAD));
|
---|
240 | dib.new_pal=false;
|
---|
241 |
|
---|
242 | dib.hSect = CreateDIBSection(0, (BITMAPINFO*)&d, DIB_RGB_COLORS, (void**)&dib.buf, NULL, NULL);
|
---|
243 |
|
---|
244 | return dib.hSect != NULL;
|
---|
245 | }
|
---|
246 |
|
---|
247 | void WndMan::writeToScreen() {
|
---|
248 | RECT r;
|
---|
249 | HDC dc,bmpdc;
|
---|
250 | HBITMAP bmpOld;
|
---|
251 |
|
---|
252 | if (_vgabuf) for (int y=0; y<200; y++) memcpy(dib.buf + y*320,_vgabuf + y*320, 320);
|
---|
253 |
|
---|
254 | GetClientRect(hWnd, &r);
|
---|
255 | dc = GetDC(hWnd);
|
---|
256 |
|
---|
257 | bmpdc = CreateCompatibleDC(dc);
|
---|
258 | bmpOld = (HBITMAP)SelectObject(bmpdc, dib.hSect);
|
---|
259 |
|
---|
260 | if (dib.new_pal)
|
---|
261 | {
|
---|
262 | dib.new_pal = false;
|
---|
263 | SetDIBColorTable(bmpdc, 0, 256, dib.pal);
|
---|
264 | }
|
---|
265 |
|
---|
266 | SetStretchBltMode(dc, BLACKONWHITE);
|
---|
267 |
|
---|
268 | StretchBlt(dc, r.left, r.top, r.right-r.left, r.bottom-r.top, bmpdc, 0, 0, SRC_WIDTH, SRC_HEIGHT, SRCCOPY);
|
---|
269 |
|
---|
270 | SelectObject(bmpdc, bmpOld);
|
---|
271 | DeleteDC(bmpdc);
|
---|
272 | ReleaseDC(hWnd, dc);
|
---|
273 | }
|
---|
274 |
|
---|
275 | void WndMan::setPalette(byte *ctab, int first, int num) {
|
---|
276 | int i;
|
---|
277 |
|
---|
278 | for (i=0; i<256; i++)
|
---|
279 | {
|
---|
280 | dib.pal[i].rgbRed = ctab[i*3+0];
|
---|
281 | dib.pal[i].rgbGreen = ctab[i*3+1];
|
---|
282 | dib.pal[i].rgbBlue = ctab[i*3+2];
|
---|
283 | }
|
---|
284 |
|
---|
285 | dib.new_pal = true;
|
---|
286 | }
|
---|
287 |
|
---|
288 | #endif
|
---|
289 |
|
---|
290 | HWND globWnd;
|
---|
291 |
|
---|
292 | void WndMan::init() {
|
---|
293 |
|
---|
294 | /* Retrieve the handle of this module */
|
---|
295 | hInst = GetModuleHandle(NULL);
|
---|
296 |
|
---|
297 | /* Register the window class */
|
---|
298 | WNDCLASSEX wcex;
|
---|
299 | wcex.cbSize = sizeof(WNDCLASSEX);
|
---|
300 | wcex.style = CS_HREDRAW | CS_VREDRAW;
|
---|
301 | wcex.lpfnWndProc = (WNDPROC)WndProc;
|
---|
302 | wcex.cbClsExtra = 0;
|
---|
303 | wcex.cbWndExtra = 0;
|
---|
304 | wcex.hInstance = hInst;
|
---|
305 | wcex.hIcon = 0;
|
---|
306 | wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
|
---|
307 | wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
|
---|
308 | wcex.lpszMenuName = 0;
|
---|
309 | wcex.lpszClassName = "ScummVM";
|
---|
310 | wcex.hIconSm = 0;
|
---|
311 | if (!RegisterClassEx(&wcex)) Error("Cannot register window class!");
|
---|
312 |
|
---|
313 | #if USE_GDI
|
---|
314 | globWnd = hWnd = CreateWindow("ScummVM", "ScummVM", WS_SCUMMWINDOW,
|
---|
315 | CW_USEDEFAULT, CW_USEDEFAULT, DEST_WIDTH+10, DEST_HEIGHT+30,
|
---|
316 | NULL, NULL, hInst, NULL);
|
---|
317 | SetWindowLong(hWnd, GWL_USERDATA, (long)this);
|
---|
318 |
|
---|
319 | dib.pal = (RGBQUAD*)calloc(sizeof(RGBQUAD),256);
|
---|
320 | dib.new_pal = false;
|
---|
321 |
|
---|
322 | if (!allocateDIB(SRC_WIDTH, SRC_HEIGHT)) Error("allocateDIB failed!");
|
---|
323 |
|
---|
324 | ShowWindow(hWnd, SW_SHOW);
|
---|
325 | #endif
|
---|
326 |
|
---|
327 | }
|
---|
328 |
|
---|
329 |
|
---|
330 | bool WndMan::handleMessage() {
|
---|
331 | MSG msg;
|
---|
332 |
|
---|
333 | if (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) return false;
|
---|
334 |
|
---|
335 | if (msg.message == WM_QUIT)
|
---|
336 | {
|
---|
337 | terminated=true;
|
---|
338 | exit(1);
|
---|
339 | return true;
|
---|
340 | }
|
---|
341 |
|
---|
342 | TranslateMessage(&msg);
|
---|
343 | DispatchMessage(&msg);
|
---|
344 |
|
---|
345 | return true;
|
---|
346 | }
|
---|
347 |
|
---|
348 | void WndMan::switchFullScreen(bool fs)
|
---|
349 | {
|
---|
350 | if (fs == TRUE)
|
---|
351 | {
|
---|
352 | SetWindowLong(wm->hWnd, GWL_STYLE, WS_SCUMMFULLSCREEN);
|
---|
353 | ShowWindow(wm->hWnd, SW_MAXIMIZE);
|
---|
354 | }
|
---|
355 | else
|
---|
356 | {
|
---|
357 | SetWindowLong(wm->hWnd, GWL_STYLE, WS_SCUMMWINDOW);
|
---|
358 | ShowWindow(wm->hWnd, SW_RESTORE);
|
---|
359 | MoveWindow(wm->hWnd, 0, 0, DEST_WIDTH+10, DEST_HEIGHT+30, TRUE);
|
---|
360 | }
|
---|
361 | wm->fscreen = fs;
|
---|
362 | }
|
---|
363 |
|
---|
364 |
|
---|
365 | unsigned long rdtsc_timer;
|
---|
366 |
|
---|
367 | void _declspec(naked) beginpentiumtest() {
|
---|
368 | _asm {
|
---|
369 | rdtsc
|
---|
370 | mov rdtsc_timer,eax
|
---|
371 | ret
|
---|
372 | }
|
---|
373 | }
|
---|
374 |
|
---|
375 | int _declspec(naked) endpentiumtest() {
|
---|
376 | _asm {
|
---|
377 | rdtsc
|
---|
378 | sub eax,rdtsc_timer
|
---|
379 | ret
|
---|
380 | }
|
---|
381 | }
|
---|
382 |
|
---|
383 |
|
---|
384 | void decompressMask(byte *d, byte *s, int w=320, int h=144)
|
---|
385 | {
|
---|
386 | int x,y;
|
---|
387 |
|
---|
388 | for (y=0; y<h; y++) {
|
---|
389 | byte *p = s+y*40;
|
---|
390 | byte *pd = d + y*320;
|
---|
391 | byte bits = 0x80, bdata = *p++;
|
---|
392 | for (x=0; x<w; x++) {
|
---|
393 | *pd++ = (bdata & bits) ? 128 : 0;
|
---|
394 | bits>>=1;
|
---|
395 | if (!bits) {
|
---|
396 | bdata = *p++;
|
---|
397 | bits=0x80;
|
---|
398 | }
|
---|
399 | }
|
---|
400 | }
|
---|
401 | }
|
---|
402 |
|
---|
403 | void outputlittlemask(byte *mask, int w, int h)
|
---|
404 | {
|
---|
405 | byte *old = wm->_vgabuf;
|
---|
406 | wm->_vgabuf = NULL;
|
---|
407 | decompressMask(wm->dib.buf, mask, w, h);
|
---|
408 | wm->writeToScreen();
|
---|
409 | wm->_vgabuf = old;
|
---|
410 | }
|
---|
411 |
|
---|
412 | void outputdisplay2(Scumm *s, int disp)
|
---|
413 | {
|
---|
414 | byte *old = wm->_vgabuf;
|
---|
415 |
|
---|
416 | byte buf[64000];
|
---|
417 |
|
---|
418 | switch(disp)
|
---|
419 | {
|
---|
420 | case 0:
|
---|
421 | wm->_vgabuf = buf;
|
---|
422 | memcpy(buf, wm->_vgabuf, 64000);
|
---|
423 | memcpy(buf,s->getResourceAddress(rtBuffer, 5),320*200);
|
---|
424 | break;
|
---|
425 | case 1:
|
---|
426 | wm->_vgabuf = buf;
|
---|
427 | memcpy(buf, wm->_vgabuf, 64000);
|
---|
428 | memcpy(buf,s->getResourceAddress(rtBuffer, 1),320*200);
|
---|
429 | break;
|
---|
430 | case 2:
|
---|
431 | wm->_vgabuf = NULL;
|
---|
432 | decompressMask(wm->dib.buf, s->getResourceAddress(rtBuffer, 9)+s->_screenStartStrip);
|
---|
433 | break;
|
---|
434 | case 3:
|
---|
435 | wm->_vgabuf = NULL;
|
---|
436 | decompressMask(wm->dib.buf, s->getResourceAddress(rtBuffer, 9)+8160+s->_screenStartStrip);
|
---|
437 | break;
|
---|
438 | case 4:
|
---|
439 | wm->_vgabuf = NULL;
|
---|
440 | decompressMask(wm->dib.buf, s->getResourceAddress(rtBuffer, 9)+8160*2+s->_screenStartStrip);
|
---|
441 | break;
|
---|
442 | case 5:
|
---|
443 | wm->_vgabuf = NULL;
|
---|
444 | decompressMask(wm->dib.buf, s->getResourceAddress(rtBuffer, 9)+8160*3+s->_screenStartStrip);
|
---|
445 | break;
|
---|
446 | }
|
---|
447 | wm->writeToScreen();
|
---|
448 | wm->_vgabuf = old;
|
---|
449 | }
|
---|
450 |
|
---|
451 | void blitToScreen(Scumm *s, byte *src,int x, int y, int w, int h)
|
---|
452 | {
|
---|
453 | byte *dst;
|
---|
454 | RECT *r;
|
---|
455 | int i;
|
---|
456 |
|
---|
457 | dst = (byte*)wm->_vgabuf + y*320 + x;
|
---|
458 |
|
---|
459 | do
|
---|
460 | {
|
---|
461 | memcpy(dst, src, w);
|
---|
462 | dst += 320;
|
---|
463 | src += 320;
|
---|
464 | } while (--h);
|
---|
465 |
|
---|
466 | }
|
---|
467 |
|
---|
468 | void setShakePos(Scumm *s, int shake_pos) {}
|
---|
469 |
|
---|
470 |
|
---|
471 | int clock;
|
---|
472 |
|
---|
473 | void updateScreen(Scumm *s)
|
---|
474 | {
|
---|
475 | if (s->_palDirtyMax != -1) {
|
---|
476 | wm->setPalette(s->_currentPalette, 0, 256);
|
---|
477 | s->_palDirtyMax = -1;
|
---|
478 | }
|
---|
479 |
|
---|
480 | wm->writeToScreen();
|
---|
481 | }
|
---|
482 |
|
---|
483 | void waitForTimer(Scumm *s, int delay)
|
---|
484 | {
|
---|
485 | wm->handleMessage();
|
---|
486 | if (!veryFastMode)
|
---|
487 | {
|
---|
488 | assert(delay<5000);
|
---|
489 | if (s->_fastMode) delay=10;
|
---|
490 | Sleep(delay);
|
---|
491 | }
|
---|
492 | }
|
---|
493 |
|
---|
494 | void initGraphics(Scumm *s, bool fullScreen)
|
---|
495 | {
|
---|
496 | SetWindowText(wm->hWnd, s->getGameName());
|
---|
497 | wm->switchFullScreen(fullScreen);
|
---|
498 | }
|
---|
499 |
|
---|
500 |
|
---|
501 | void drawMouse(Scumm *s, int x, int y, int w, int h, byte *buf, bool visible)
|
---|
502 | {
|
---|
503 | }
|
---|
504 |
|
---|
505 | void fill_buffer(int16 *buf, int len) {
|
---|
506 | scumm.mixWaves(buf, len);
|
---|
507 | }
|
---|
508 |
|
---|
509 | void WndMan::prepare_header(WAVEHDR *wh, int i) {
|
---|
510 | memset(wh, 0, sizeof(WAVEHDR));
|
---|
511 | wh->lpData = (char*)malloc(BUFFER_SIZE);
|
---|
512 | wh->dwBufferLength = BUFFER_SIZE;
|
---|
513 |
|
---|
514 | waveOutPrepareHeader(_handle, wh, sizeof(WAVEHDR));
|
---|
515 |
|
---|
516 | fill_buffer((int16*)wh->lpData, wh->dwBufferLength>>1);
|
---|
517 | waveOutWrite(_handle, wh, sizeof(WAVEHDR));
|
---|
518 | }
|
---|
519 |
|
---|
520 | void WndMan::sound_init() {
|
---|
521 | WAVEFORMATEX wfx;
|
---|
522 |
|
---|
523 | memset(&wfx, 0, sizeof(wfx));
|
---|
524 | wfx.wFormatTag = WAVE_FORMAT_PCM;
|
---|
525 | wfx.nChannels = 1;
|
---|
526 | wfx.nSamplesPerSec = SAMPLES_PER_SEC;
|
---|
527 | wfx.nAvgBytesPerSec = SAMPLES_PER_SEC * BITS_PER_SAMPLE / 8;
|
---|
528 | wfx.wBitsPerSample = BITS_PER_SAMPLE;
|
---|
529 | wfx.nBlockAlign = BITS_PER_SAMPLE * 1 / 8;
|
---|
530 |
|
---|
531 | CreateThread(NULL, 0, (unsigned long (__stdcall *)(void *))&sound_thread, this, 0, &_threadId);
|
---|
532 | SetThreadPriority((void*)_threadId, THREAD_PRIORITY_HIGHEST);
|
---|
533 |
|
---|
534 | _event = CreateEvent(NULL, false, false, NULL);
|
---|
535 |
|
---|
536 | memset(_hdr,0,sizeof(_hdr));
|
---|
537 |
|
---|
538 | waveOutOpen(&_handle, WAVE_MAPPER, &wfx, (long)_event, (long)this, CALLBACK_EVENT );
|
---|
539 |
|
---|
540 | prepare_header(&_hdr[0], 0);
|
---|
541 | prepare_header(&_hdr[1], 1);
|
---|
542 | }
|
---|
543 |
|
---|
544 | DWORD _stdcall WndMan::sound_thread(WndMan *wm) {
|
---|
545 | int i;
|
---|
546 | bool signaled;
|
---|
547 | int time = GetTickCount(), cur;
|
---|
548 |
|
---|
549 | while (1) {
|
---|
550 |
|
---|
551 | if (!snd_driv.wave_based()) {
|
---|
552 | cur = GetTickCount();
|
---|
553 | while (time < cur) {
|
---|
554 | sound.on_timer();
|
---|
555 | time += 10;
|
---|
556 | }
|
---|
557 | }
|
---|
558 |
|
---|
559 | signaled = WaitForSingleObject(wm->_event, time - cur) == WAIT_OBJECT_0;
|
---|
560 |
|
---|
561 | if (signaled) {
|
---|
562 | for(i=0; i<2; i++) {
|
---|
563 | WAVEHDR *hdr = &wm->_hdr[i];
|
---|
564 | if (hdr->dwFlags & WHDR_DONE) {
|
---|
565 | fill_buffer((int16*)hdr->lpData, hdr->dwBufferLength>>1);
|
---|
566 | waveOutWrite(wm->_handle, hdr, sizeof(WAVEHDR));
|
---|
567 | }
|
---|
568 | }
|
---|
569 | }
|
---|
570 | }
|
---|
571 | }
|
---|
572 |
|
---|
573 |
|
---|
574 | #undef main
|
---|
575 | int main(int argc, char* argv[]) {
|
---|
576 | int delta;
|
---|
577 |
|
---|
578 | wm->init();
|
---|
579 | wm->_vgabuf = (byte*)calloc(320,200);
|
---|
580 | wm->_scumm = &scumm;
|
---|
581 |
|
---|
582 | sound.initialize(&scumm,&snd_driv);
|
---|
583 |
|
---|
584 | wm->sound_init();
|
---|
585 |
|
---|
586 | scumm._gui = &gui;
|
---|
587 | scumm.scummMain(argc, argv);
|
---|
588 | gui.init(&scumm);
|
---|
589 | delta = 0;
|
---|
590 | do {
|
---|
591 | updateScreen(&scumm);
|
---|
592 |
|
---|
593 | waitForTimer(&scumm, delta*15);
|
---|
594 |
|
---|
595 | if (gui._active) {
|
---|
596 | gui.loop();
|
---|
597 | delta = 3;
|
---|
598 | } else {
|
---|
599 | delta = scumm.scummLoop(delta);
|
---|
600 | }
|
---|
601 | } while(1);
|
---|
602 |
|
---|
603 | return 0;
|
---|
604 | }
|
---|
605 |
|
---|