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.24 2001/12/28 15:26:28 strigeus Exp $
|
---|
19 | */
|
---|
20 |
|
---|
21 | /*
|
---|
22 | (Very ugly) DirectX additions by Gregory Montoir (cyx@frenchkiss.net)
|
---|
23 | The scrolling window seems not correct (bounds are out of the screen)... i'll see...
|
---|
24 | 2002.02.12
|
---|
25 | */
|
---|
26 |
|
---|
27 | #include <windows.h>
|
---|
28 | #include <windowsx.h>
|
---|
29 |
|
---|
30 | #include "stdafx.h"
|
---|
31 | #include <assert.h>
|
---|
32 |
|
---|
33 | #include "scumm.h"
|
---|
34 | #include "sound.h"
|
---|
35 | #include "gui.h"
|
---|
36 |
|
---|
37 | #if !defined(ALLOW_GDI)
|
---|
38 | #error The GDI driver is not as complete as the SDL driver. You need to define ALLOW_GDI to use this driver.
|
---|
39 | #endif
|
---|
40 |
|
---|
41 | #define SRC_WIDTH 320
|
---|
42 | #define SRC_HEIGHT 200
|
---|
43 | #define SRC_PITCH (320)
|
---|
44 |
|
---|
45 | #define DEST_WIDTH 320
|
---|
46 | #define DEST_HEIGHT 200
|
---|
47 |
|
---|
48 | #define USE_DIRECTX 1
|
---|
49 | #define USE_DRAWDIB 0
|
---|
50 | #define USE_GDI 0
|
---|
51 |
|
---|
52 | #if USE_DIRECTX
|
---|
53 | #include <ddraw.h>
|
---|
54 | #endif
|
---|
55 |
|
---|
56 | #define SAMPLES_PER_SEC 22050
|
---|
57 | #define BUFFER_SIZE (8192)
|
---|
58 | #define BITS_PER_SAMPLE 16
|
---|
59 |
|
---|
60 | //static bool shutdown;
|
---|
61 |
|
---|
62 |
|
---|
63 | #if USE_GDI
|
---|
64 | typedef struct DIB {
|
---|
65 | HBITMAP hSect;
|
---|
66 | byte *buf;
|
---|
67 | RGBQUAD *pal;
|
---|
68 | bool new_pal;
|
---|
69 | } DIB;
|
---|
70 | #endif
|
---|
71 |
|
---|
72 | class WndMan {
|
---|
73 | HMODULE hInst;
|
---|
74 | HWND hWnd;
|
---|
75 |
|
---|
76 |
|
---|
77 | bool terminated;
|
---|
78 |
|
---|
79 | #if USE_DIRECTX
|
---|
80 | LPDIRECTDRAW lpdd;
|
---|
81 | LPDIRECTDRAWSURFACE lpddsPrimary;
|
---|
82 | LPDIRECTDRAWSURFACE lpddsSecondary;
|
---|
83 | #endif
|
---|
84 |
|
---|
85 | #if USE_GDI
|
---|
86 | public:
|
---|
87 | DIB dib;
|
---|
88 | private:
|
---|
89 | #endif
|
---|
90 |
|
---|
91 | public:
|
---|
92 | byte *_vgabuf;
|
---|
93 |
|
---|
94 | Scumm *_scumm;
|
---|
95 |
|
---|
96 | HANDLE _event;
|
---|
97 | DWORD _threadId;
|
---|
98 | HWAVEOUT _handle;
|
---|
99 | WAVEHDR _hdr[2];
|
---|
100 |
|
---|
101 | public:
|
---|
102 | void init();
|
---|
103 |
|
---|
104 | bool handleMessage();
|
---|
105 | void run();
|
---|
106 | void setPalette(byte *ctab, int first, int num);
|
---|
107 | void writeToScreen();
|
---|
108 |
|
---|
109 | void prepare_header(WAVEHDR *wh, int i);
|
---|
110 | void sound_init();
|
---|
111 | static DWORD _stdcall sound_thread(WndMan *wm);
|
---|
112 |
|
---|
113 | #if USE_GDI
|
---|
114 | bool allocateDIB(int w, int h);
|
---|
115 | #endif
|
---|
116 |
|
---|
117 | #if USE_DIRECTX
|
---|
118 | byte _realbuf[SRC_WIDTH*SRC_HEIGHT];
|
---|
119 | BOOL ddrawInit();
|
---|
120 | void ddrawReleaseSurfaces();
|
---|
121 | void ddrawRelease();
|
---|
122 | void ddrawUpdateBuffer();
|
---|
123 | #endif
|
---|
124 | };
|
---|
125 |
|
---|
126 | #if USE_DIRECTX
|
---|
127 |
|
---|
128 | static unsigned char GetLowestBit(unsigned long p)
|
---|
129 | {
|
---|
130 | unsigned char pos = 0;
|
---|
131 | while((p & 1) == 0) {
|
---|
132 | ++pos;
|
---|
133 | p >>= 1;
|
---|
134 | }
|
---|
135 | return pos;
|
---|
136 | }
|
---|
137 | #endif
|
---|
138 |
|
---|
139 | void Error(const char *msg) {
|
---|
140 | OutputDebugString(msg);
|
---|
141 | MessageBoxA(0, msg, "Error", MB_ICONSTOP);
|
---|
142 | exit(1);
|
---|
143 | }
|
---|
144 |
|
---|
145 | int sel;
|
---|
146 | Scumm scumm;
|
---|
147 | ScummDebugger debugger;
|
---|
148 | Gui gui;
|
---|
149 | SoundEngine sound;
|
---|
150 | SOUND_DRIVER_TYPE snd_driv;
|
---|
151 |
|
---|
152 | WndMan wm[1];
|
---|
153 | byte veryFastMode;
|
---|
154 |
|
---|
155 | void modifyslot(int sel, int what);
|
---|
156 |
|
---|
157 | int mapKey(int key) {
|
---|
158 | if (key>=VK_F1 && key<=VK_F9) {
|
---|
159 | return key - VK_F1 + 315;
|
---|
160 | }
|
---|
161 | return key;
|
---|
162 | }
|
---|
163 |
|
---|
164 | static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
|
---|
165 | WndMan *wm = (WndMan*)GetWindowLong(hWnd, GWL_USERDATA);
|
---|
166 |
|
---|
167 | switch (message)
|
---|
168 | {
|
---|
169 | case WM_DESTROY:
|
---|
170 | case WM_CLOSE:
|
---|
171 | exit(0);
|
---|
172 | break;
|
---|
173 |
|
---|
174 | case WM_KEYDOWN:
|
---|
175 | if (wParam>='0' && wParam<='9') {
|
---|
176 | wm->_scumm->_saveLoadSlot = wParam - '0';
|
---|
177 | if (GetAsyncKeyState(VK_SHIFT)<0) {
|
---|
178 | sprintf(wm->_scumm->_saveLoadName, "Quicksave %d", wm->_scumm->_saveLoadSlot);
|
---|
179 | wm->_scumm->_saveLoadFlag = 1;
|
---|
180 | } else if (GetAsyncKeyState(VK_CONTROL)<0)
|
---|
181 | wm->_scumm->_saveLoadFlag = 2;
|
---|
182 | wm->_scumm->_saveLoadCompatible = false;
|
---|
183 | }
|
---|
184 |
|
---|
185 | if (GetAsyncKeyState(VK_CONTROL)<0) {
|
---|
186 | if (wParam=='F') {
|
---|
187 | wm->_scumm->_fastMode ^= 1;
|
---|
188 | }
|
---|
189 |
|
---|
190 | if (wParam=='G') {
|
---|
191 | veryFastMode ^= 1;
|
---|
192 | }
|
---|
193 |
|
---|
194 | if (wParam=='D') {
|
---|
195 | debugger.attach(wm->_scumm);
|
---|
196 | }
|
---|
197 |
|
---|
198 | if (wParam=='S') {
|
---|
199 | wm->_scumm->resourceStats();
|
---|
200 | }
|
---|
201 | }
|
---|
202 |
|
---|
203 | wm->_scumm->_keyPressed = mapKey(wParam);
|
---|
204 | break;
|
---|
205 |
|
---|
206 | case WM_MOUSEMOVE:
|
---|
207 | #if USE_DIRECTX
|
---|
208 | RECT r;
|
---|
209 | GetClientRect(hWnd, &r);
|
---|
210 | wm->_scumm->mouse.x = (SRC_WIDTH * ((int16*)&lParam)[0]) / (r.right - r.left);
|
---|
211 | wm->_scumm->mouse.y = (SRC_HEIGHT * ((int16*)&lParam)[1]) / (r.bottom - r.top);
|
---|
212 | #else
|
---|
213 | wm->_scumm->mouse.x = ((int16*)&lParam)[0];
|
---|
214 | wm->_scumm->mouse.y = ((int16*)&lParam)[1];
|
---|
215 | #endif
|
---|
216 | break;
|
---|
217 | case WM_LBUTTONDOWN:
|
---|
218 | wm->_scumm->_leftBtnPressed |= msClicked|msDown;
|
---|
219 | break;
|
---|
220 | case WM_LBUTTONUP:
|
---|
221 | wm->_scumm->_leftBtnPressed &= ~msDown;
|
---|
222 | break;
|
---|
223 | case WM_RBUTTONDOWN:
|
---|
224 | wm->_scumm->_rightBtnPressed |= msClicked|msDown;
|
---|
225 | break;
|
---|
226 | case WM_RBUTTONUP:
|
---|
227 | wm->_scumm->_rightBtnPressed &= ~msDown;
|
---|
228 | break;
|
---|
229 | default:
|
---|
230 | return DefWindowProc(hWnd, message, wParam, lParam);
|
---|
231 | }
|
---|
232 | return 0;
|
---|
233 | }
|
---|
234 |
|
---|
235 | #if USE_GDI
|
---|
236 |
|
---|
237 | bool WndMan::allocateDIB(int w, int h) {
|
---|
238 | struct {
|
---|
239 | BITMAPINFOHEADER bih;
|
---|
240 | RGBQUAD rgb[256];
|
---|
241 | } d;
|
---|
242 |
|
---|
243 | if (dib.hSect)
|
---|
244 | return true;
|
---|
245 |
|
---|
246 | memset(&d.bih, 0, sizeof(d.bih));
|
---|
247 | d.bih.biSize = sizeof(d.bih);
|
---|
248 | d.bih.biWidth = w;
|
---|
249 | d.bih.biHeight = -h;
|
---|
250 | d.bih.biPlanes = 1;
|
---|
251 | d.bih.biBitCount = 8;
|
---|
252 | d.bih.biCompression = BI_RGB;
|
---|
253 |
|
---|
254 | memcpy(d.rgb, dib.pal, 256*sizeof(RGBQUAD));
|
---|
255 | dib.new_pal=false;
|
---|
256 |
|
---|
257 | dib.hSect = CreateDIBSection(0, (BITMAPINFO*)&d, DIB_RGB_COLORS, (void**)&dib.buf,
|
---|
258 | NULL, NULL);
|
---|
259 |
|
---|
260 | return dib.hSect != NULL;
|
---|
261 | }
|
---|
262 |
|
---|
263 | void WndMan::writeToScreen() {
|
---|
264 | RECT r;
|
---|
265 | HDC dc,bmpdc;
|
---|
266 | HBITMAP bmpOld;
|
---|
267 | #if DEST_WIDTH==320
|
---|
268 | if (_vgabuf) {
|
---|
269 | for (int y=0; y<200; y++) {
|
---|
270 | memcpy(dib.buf + y*320,_vgabuf + y*320, 320);
|
---|
271 | }
|
---|
272 | }
|
---|
273 | #endif
|
---|
274 |
|
---|
275 | r.left = r.top = 0;
|
---|
276 | r.right = DEST_WIDTH;
|
---|
277 | r.bottom = DEST_HEIGHT;
|
---|
278 |
|
---|
279 | dc = GetDC(hWnd);
|
---|
280 |
|
---|
281 | bmpdc = CreateCompatibleDC(dc);
|
---|
282 | bmpOld = (HBITMAP)SelectObject(bmpdc, dib.hSect);
|
---|
283 |
|
---|
284 | if (dib.new_pal) {
|
---|
285 | dib.new_pal = false;
|
---|
286 | SetDIBColorTable(bmpdc, 0, 256, dib.pal);
|
---|
287 | }
|
---|
288 |
|
---|
289 | SetStretchBltMode(dc, BLACKONWHITE);
|
---|
290 |
|
---|
291 | #if DEST_WIDTH==320
|
---|
292 | StretchBlt(dc, r.left, r.top, r.right-r.left, r.bottom-r.top, bmpdc, 0, 0, 320,200, SRCCOPY);
|
---|
293 | #endif
|
---|
294 |
|
---|
295 |
|
---|
296 | SelectObject(bmpdc, bmpOld);
|
---|
297 | DeleteDC(bmpdc);
|
---|
298 | ReleaseDC(hWnd, dc);
|
---|
299 | }
|
---|
300 |
|
---|
301 | void WndMan::setPalette(byte *ctab, int first, int num) {
|
---|
302 | int i;
|
---|
303 |
|
---|
304 | for (i=0; i<256; i++) {
|
---|
305 | dib.pal[i].rgbRed = ctab[i*3+0];
|
---|
306 | dib.pal[i].rgbGreen = ctab[i*3+1];
|
---|
307 | dib.pal[i].rgbBlue = ctab[i*3+2];
|
---|
308 | }
|
---|
309 |
|
---|
310 | dib.new_pal = true;
|
---|
311 | }
|
---|
312 |
|
---|
313 | #endif
|
---|
314 |
|
---|
315 | HWND globWnd;
|
---|
316 |
|
---|
317 | void WndMan::init() {
|
---|
318 |
|
---|
319 | /* Retrieve the handle of this module */
|
---|
320 | hInst = GetModuleHandle(NULL);
|
---|
321 |
|
---|
322 | /* Register the window class */
|
---|
323 | WNDCLASSEX wcex;
|
---|
324 | wcex.cbSize = sizeof(WNDCLASSEX);
|
---|
325 | wcex.style = CS_HREDRAW | CS_VREDRAW;
|
---|
326 | wcex.lpfnWndProc = (WNDPROC)WndProc;
|
---|
327 | wcex.cbClsExtra = 0;
|
---|
328 | wcex.cbWndExtra = 0;
|
---|
329 | wcex.hInstance = hInst;
|
---|
330 | wcex.hIcon = 0;
|
---|
331 | wcex.hCursor = ::LoadCursor(NULL, IDC_ARROW);
|
---|
332 | wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
|
---|
333 | wcex.lpszMenuName = 0;
|
---|
334 | wcex.lpszClassName = "ScummVM";
|
---|
335 | wcex.hIconSm = 0;
|
---|
336 | if (!RegisterClassEx(&wcex))
|
---|
337 | Error("Cannot register window class!");
|
---|
338 |
|
---|
339 | #if USE_GDI
|
---|
340 | globWnd = hWnd = CreateWindow("ScummVM", "ScummVM", WS_OVERLAPPEDWINDOW,
|
---|
341 | CW_USEDEFAULT, CW_USEDEFAULT, DEST_WIDTH+10, DEST_HEIGHT+30, NULL, NULL, hInst, NULL);
|
---|
342 | SetWindowLong(hWnd, GWL_USERDATA, (long)this);
|
---|
343 |
|
---|
344 | dib.pal = (RGBQUAD*)calloc(sizeof(RGBQUAD),256);
|
---|
345 | dib.new_pal = false;
|
---|
346 |
|
---|
347 | if (!allocateDIB(DEST_WIDTH, DEST_HEIGHT))
|
---|
348 | Error("allocateDIB failed!");
|
---|
349 |
|
---|
350 | ShowWindow(hWnd, SW_SHOW);
|
---|
351 | #endif
|
---|
352 |
|
---|
353 |
|
---|
354 | #if USE_DIRECTX
|
---|
355 |
|
---|
356 | HWND hwnd;
|
---|
357 | globWnd = hwnd = CreateWindow("ScummVM", "ScummVM",
|
---|
358 | WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_SIZEBOX,
|
---|
359 | 0, 0, 0, 0, NULL, NULL, hInst, NULL);
|
---|
360 | SetWindowLong(hwnd, GWL_USERDATA, (long)this);
|
---|
361 |
|
---|
362 | RECT r;
|
---|
363 | SetRect(&r, 0, 0, SRC_WIDTH, SRC_HEIGHT);
|
---|
364 | AdjustWindowRectEx(&r, GetWindowStyle(hwnd), GetMenu(hwnd) != NULL, GetWindowExStyle(hwnd));
|
---|
365 | MoveWindow(hwnd,
|
---|
366 | (GetSystemMetrics(SM_CXSCREEN) - SRC_WIDTH) / 2,
|
---|
367 | (GetSystemMetrics(SM_CYSCREEN) - SRC_HEIGHT) / 2,
|
---|
368 | r.right - r.left, r.bottom - r.top, FALSE);
|
---|
369 | if(!ddrawInit())
|
---|
370 | Error("Ddraw init failed!");
|
---|
371 | ShowWindow(hwnd, SW_SHOW);
|
---|
372 | #endif
|
---|
373 |
|
---|
374 | }
|
---|
375 |
|
---|
376 |
|
---|
377 | #ifdef USE_DIRECTX
|
---|
378 |
|
---|
379 |
|
---|
380 | void WndMan::ddrawUpdateBuffer()
|
---|
381 | {
|
---|
382 | DDSURFACEDESC ddsd;
|
---|
383 | memset(&ddsd, '\0', sizeof(ddsd));
|
---|
384 | ddsd.dwSize = sizeof(ddsd);
|
---|
385 |
|
---|
386 | HRESULT hr;
|
---|
387 | hr = lpddsSecondary->Lock(NULL, &ddsd, DDLOCK_WAIT|DDLOCK_WRITEONLY|DDLOCK_SURFACEMEMORYPTR, NULL);
|
---|
388 | if(hr == DDERR_SURFACELOST) {
|
---|
389 | // voir laquelle des surfaces il faut restaurer
|
---|
390 | lpddsPrimary->Restore();
|
---|
391 | lpddsSecondary->Restore();
|
---|
392 | // DDERR_WRONGMODE ?, si echoue reinit de tout ? voir la doc...
|
---|
393 | }
|
---|
394 | else if(hr == DD_OK) {
|
---|
395 | byte *p = _vgabuf ? _vgabuf : _realbuf;
|
---|
396 |
|
---|
397 | DDPIXELFORMAT ddpf = ddsd.ddpfPixelFormat;
|
---|
398 | int Rshift = GetLowestBit(ddpf.dwRBitMask);
|
---|
399 | int Gshift = GetLowestBit(ddpf.dwGBitMask);
|
---|
400 | int Bshift = GetLowestBit(ddpf.dwBBitMask);
|
---|
401 |
|
---|
402 | BYTE *dst = (BYTE*)ddsd.lpSurface;
|
---|
403 |
|
---|
404 | int size = ddsd.dwHeight * ddsd.dwWidth;
|
---|
405 | int i = 0;
|
---|
406 | while(i < size) {
|
---|
407 | BYTE r = _scumm->_currentPalette[p[i]*3];
|
---|
408 | BYTE g = _scumm->_currentPalette[p[i]*3+1];
|
---|
409 | BYTE b = _scumm->_currentPalette[p[i]*3+2];
|
---|
410 |
|
---|
411 | DWORD pixel = (r << Rshift) | (g << Gshift) | (b << Bshift);
|
---|
412 |
|
---|
413 | switch(ddpf.dwRGBBitCount) {
|
---|
414 | case 32:
|
---|
415 | //dst[0] = (BYTE)((pixel & 0xFF000000) >> 24);
|
---|
416 | //dst[1] = (BYTE)((pixel & 0x00FF0000) >> 16);
|
---|
417 | //dst[2] = (BYTE)((pixel & 0x0000FF00) >> 8);
|
---|
418 | //dst[3] = (BYTE)((pixel & 0x000000FF));
|
---|
419 | *((DWORD*)dst) = pixel;
|
---|
420 | break;
|
---|
421 | case 24:
|
---|
422 | dst[0] = (BYTE)((pixel & 0xFF0000) >> 16);
|
---|
423 | dst[1] = (BYTE)((pixel & 0x00FF00) >> 8);
|
---|
424 | dst[2] = (BYTE)((pixel & 0x0000FF));
|
---|
425 | break;
|
---|
426 | case 16:
|
---|
427 | //dst[0] = (BYTE)((pixel & 0xFF00) >> 8);
|
---|
428 | //dst[1] = (BYTE)((pixel & 0x00FF));
|
---|
429 | *((WORD*)dst) = (WORD)pixel;
|
---|
430 | break;
|
---|
431 | }
|
---|
432 | dst += ddpf.dwRGBBitCount >> 3; // / 8
|
---|
433 |
|
---|
434 | i++;
|
---|
435 | }
|
---|
436 | lpddsSecondary->Unlock(NULL);
|
---|
437 | }
|
---|
438 | }
|
---|
439 |
|
---|
440 | void WndMan::writeToScreen()
|
---|
441 | {
|
---|
442 | ddrawUpdateBuffer();
|
---|
443 | RECT r;
|
---|
444 | GetWindowRect(globWnd, &r);
|
---|
445 | lpddsPrimary->Blt(&r, lpddsSecondary, NULL, DDBLT_WAIT, NULL);
|
---|
446 | }
|
---|
447 |
|
---|
448 |
|
---|
449 | BOOL WndMan::ddrawInit()
|
---|
450 | {
|
---|
451 | DDSURFACEDESC ddsd;
|
---|
452 | LPDIRECTDRAWCLIPPER lpddc;
|
---|
453 |
|
---|
454 | if(DirectDrawCreate(NULL, &lpdd, NULL) != DD_OK)
|
---|
455 | return FALSE;
|
---|
456 |
|
---|
457 | if(lpdd->SetCooperativeLevel(globWnd, DDSCL_NORMAL) != DD_OK)
|
---|
458 | return FALSE;
|
---|
459 |
|
---|
460 | memset(&ddsd, '\0', sizeof(ddsd));
|
---|
461 | ddsd.dwSize = sizeof(ddsd);
|
---|
462 | ddsd.dwFlags = DDSD_CAPS;
|
---|
463 | ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY;
|
---|
464 | if(lpdd->CreateSurface(&ddsd, &lpddsPrimary, NULL) != DD_OK)
|
---|
465 | return FALSE;
|
---|
466 |
|
---|
467 | if(lpdd->CreateClipper(0, &lpddc, NULL) != DD_OK)
|
---|
468 | return FALSE;
|
---|
469 | if(lpddc->SetHWnd(0, globWnd) != DD_OK)
|
---|
470 | return FALSE;
|
---|
471 | if(lpddsPrimary->SetClipper(lpddc) != DD_OK)
|
---|
472 | return FALSE;
|
---|
473 | lpddc->Release();
|
---|
474 |
|
---|
475 | memset(&ddsd, '\0', sizeof(ddsd));
|
---|
476 | ddsd.dwSize = sizeof(ddsd);
|
---|
477 | ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT;
|
---|
478 | ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
|
---|
479 | ddsd.dwWidth = SRC_WIDTH;
|
---|
480 | ddsd.dwHeight = SRC_HEIGHT;
|
---|
481 | if(lpdd->CreateSurface(&ddsd, &lpddsSecondary, NULL) != DD_OK)
|
---|
482 | return FALSE;
|
---|
483 |
|
---|
484 | memset(_realbuf, '\0', sizeof(_realbuf));
|
---|
485 | return TRUE;
|
---|
486 | }
|
---|
487 |
|
---|
488 |
|
---|
489 | void WndMan::ddrawReleaseSurfaces()
|
---|
490 | {
|
---|
491 | if(lpddsPrimary != NULL) lpddsPrimary->Release();
|
---|
492 | if(lpddsSecondary != NULL) lpddsSecondary->Release();
|
---|
493 | }
|
---|
494 |
|
---|
495 |
|
---|
496 | void WndMan::ddrawRelease()
|
---|
497 | {
|
---|
498 | ddrawReleaseSurfaces();
|
---|
499 | if(lpdd != NULL) lpdd->Release();
|
---|
500 | }
|
---|
501 | #endif
|
---|
502 |
|
---|
503 |
|
---|
504 |
|
---|
505 | bool WndMan::handleMessage() {
|
---|
506 | MSG msg;
|
---|
507 |
|
---|
508 | if (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
---|
509 | return false;
|
---|
510 |
|
---|
511 | if (msg.message==WM_QUIT) {
|
---|
512 | terminated=true;
|
---|
513 | exit(1);
|
---|
514 | return true;
|
---|
515 | }
|
---|
516 |
|
---|
517 | TranslateMessage(&msg);
|
---|
518 | DispatchMessage(&msg);
|
---|
519 |
|
---|
520 | return true;
|
---|
521 | }
|
---|
522 |
|
---|
523 |
|
---|
524 | #if USE_DIRECTX
|
---|
525 | unsigned long rdtsc_timer;
|
---|
526 |
|
---|
527 | void _declspec(naked) beginpentiumtest() {
|
---|
528 | _asm {
|
---|
529 | rdtsc
|
---|
530 | mov rdtsc_timer,eax
|
---|
531 | ret
|
---|
532 | }
|
---|
533 | }
|
---|
534 |
|
---|
535 | int _declspec(naked) endpentiumtest() {
|
---|
536 | _asm {
|
---|
537 | rdtsc
|
---|
538 | sub eax,rdtsc_timer
|
---|
539 | ret
|
---|
540 | }
|
---|
541 | }
|
---|
542 | #endif
|
---|
543 |
|
---|
544 | void decompressMask(byte *d, byte *s, int w=320, int h=144) {
|
---|
545 | int x,y;
|
---|
546 |
|
---|
547 | for (y=0; y<h; y++) {
|
---|
548 | byte *p = s+y*40;
|
---|
549 | byte *pd = d + y*320;
|
---|
550 | byte bits = 0x80, bdata = *p++;
|
---|
551 | for (x=0; x<w; x++) {
|
---|
552 | *pd++ = (bdata & bits) ? 128 : 0;
|
---|
553 | bits>>=1;
|
---|
554 | if (!bits) {
|
---|
555 | bdata = *p++;
|
---|
556 | bits=0x80;
|
---|
557 | }
|
---|
558 | }
|
---|
559 | }
|
---|
560 | }
|
---|
561 |
|
---|
562 | void outputlittlemask(byte *mask, int w, int h) {
|
---|
563 | byte *old = wm->_vgabuf;
|
---|
564 | wm->_vgabuf = NULL;
|
---|
565 | #if !(USE_DIRECTX)
|
---|
566 | decompressMask(wm->dib.buf, mask, w, h);
|
---|
567 | #else
|
---|
568 | memset(wm->_realbuf, '\0', sizeof(wm->_realbuf));
|
---|
569 | decompressMask(wm->_realbuf, mask, w, h);
|
---|
570 | #endif
|
---|
571 | wm->writeToScreen();
|
---|
572 | wm->_vgabuf = old;
|
---|
573 | }
|
---|
574 |
|
---|
575 | void outputdisplay2(Scumm *s, int disp) {
|
---|
576 | byte *old = wm->_vgabuf;
|
---|
577 |
|
---|
578 | byte buf[64000];
|
---|
579 |
|
---|
580 | switch(disp) {
|
---|
581 | case 0:
|
---|
582 | wm->_vgabuf = buf;
|
---|
583 | memcpy(buf, wm->_vgabuf, 64000);
|
---|
584 | memcpy(buf,s->getResourceAddress(rtBuffer, 5),320*200);
|
---|
585 | break;
|
---|
586 | case 1:
|
---|
587 | wm->_vgabuf = buf;
|
---|
588 | memcpy(buf, wm->_vgabuf, 64000);
|
---|
589 | memcpy(buf,s->getResourceAddress(rtBuffer, 1),320*200);
|
---|
590 | break;
|
---|
591 | case 2:
|
---|
592 | wm->_vgabuf = NULL;
|
---|
593 | #if !(USE_DIRECTX)
|
---|
594 | decompressMask(wm->dib.buf, s->getResourceAddress(rtBuffer, 9)+s->_screenStartStrip);
|
---|
595 | #else
|
---|
596 | memset(wm->_realbuf, '\0', sizeof(wm->_realbuf));
|
---|
597 | decompressMask(wm->_realbuf, s->getResourceAddress(rtBuffer, 9)+s->_screenStartStrip);
|
---|
598 | #endif
|
---|
599 | break;
|
---|
600 | case 3:
|
---|
601 | wm->_vgabuf = NULL;
|
---|
602 | #if !(USE_DIRECTX)
|
---|
603 | decompressMask(wm->dib.buf, s->getResourceAddress(rtBuffer, 9)+8160+s->_screenStartStrip);
|
---|
604 | #else
|
---|
605 | memset(wm->_realbuf, '\0', sizeof(wm->_realbuf));
|
---|
606 | decompressMask(wm->_realbuf, s->getResourceAddress(rtBuffer, 9)+8160+s->_screenStartStrip);
|
---|
607 | #endif
|
---|
608 | break;
|
---|
609 | case 4:
|
---|
610 | wm->_vgabuf = NULL;
|
---|
611 | #if !(USE_DIRECTX)
|
---|
612 | decompressMask(wm->dib.buf, s->getResourceAddress(rtBuffer, 9)+8160*2+s->_screenStartStrip);
|
---|
613 | #else
|
---|
614 | memset(wm->_realbuf, '\0', sizeof(wm->_realbuf));
|
---|
615 | decompressMask(wm->_realbuf, s->getResourceAddress(rtBuffer, 9)+8160*2+s->_screenStartStrip);
|
---|
616 | #endif
|
---|
617 | break;
|
---|
618 | case 5:
|
---|
619 | wm->_vgabuf = NULL;
|
---|
620 | #if !(USE_DIRECTX)
|
---|
621 | decompressMask(wm->dib.buf, s->getResourceAddress(rtBuffer, 9)+8160*3+s->_screenStartStrip);
|
---|
622 | #else
|
---|
623 | memset(wm->_realbuf, '\0', sizeof(wm->_realbuf));
|
---|
624 | decompressMask(wm->_realbuf, s->getResourceAddress(rtBuffer, 9)+8160*2+s->_screenStartStrip);
|
---|
625 | #endif
|
---|
626 | break;
|
---|
627 | }
|
---|
628 | wm->writeToScreen();
|
---|
629 | wm->_vgabuf = old;
|
---|
630 | }
|
---|
631 |
|
---|
632 | void blitToScreen(Scumm *s, byte *src,int x, int y, int w, int h) {
|
---|
633 | byte *dst;
|
---|
634 | SDL_Rect *r;
|
---|
635 | int i;
|
---|
636 |
|
---|
637 | dst = (byte*)wm->_vgabuf + y*320 + x;
|
---|
638 |
|
---|
639 | do {
|
---|
640 | memcpy(dst, src, w);
|
---|
641 | dst += 320;
|
---|
642 | src += 320;
|
---|
643 | } while (--h);
|
---|
644 |
|
---|
645 | }
|
---|
646 |
|
---|
647 | void setShakePos(Scumm *s, int shake_pos) {}
|
---|
648 |
|
---|
649 |
|
---|
650 | int clock;
|
---|
651 |
|
---|
652 | void updateScreen(Scumm *s) {
|
---|
653 | if (s->_palDirtyMax != -1) {
|
---|
654 | #if !USE_DIRECTX
|
---|
655 | wm->setPalette(s->_currentPalette, 0, 256);
|
---|
656 | #endif
|
---|
657 | s->_palDirtyMax = -1;
|
---|
658 | }
|
---|
659 |
|
---|
660 | wm->writeToScreen();
|
---|
661 | }
|
---|
662 |
|
---|
663 | void waitForTimer(Scumm *s, int delay) {
|
---|
664 | wm->handleMessage();
|
---|
665 | if (!veryFastMode) {
|
---|
666 | assert(delay<5000);
|
---|
667 | if (s->_fastMode)
|
---|
668 | delay=10;
|
---|
669 | Sleep(delay);
|
---|
670 | }
|
---|
671 | }
|
---|
672 |
|
---|
673 | void initGraphics(Scumm *s, bool fullScreen) {
|
---|
674 | if(fullScreen)
|
---|
675 | warning("Use SDL for fullscreen support");
|
---|
676 | }
|
---|
677 |
|
---|
678 | void drawMouse(Scumm *s, int, int, int, byte*, bool) {
|
---|
679 | }
|
---|
680 |
|
---|
681 | void drawMouse(Scumm *s, int x, int y, int w, int h, byte *buf, bool visible) {
|
---|
682 | }
|
---|
683 |
|
---|
684 | void fill_buffer(int16 *buf, int len) {
|
---|
685 | scumm.mixWaves(buf, len);
|
---|
686 | }
|
---|
687 |
|
---|
688 | void WndMan::prepare_header(WAVEHDR *wh, int i) {
|
---|
689 | memset(wh, 0, sizeof(WAVEHDR));
|
---|
690 | wh->lpData = (char*)malloc(BUFFER_SIZE);
|
---|
691 | wh->dwBufferLength = BUFFER_SIZE;
|
---|
692 |
|
---|
693 | waveOutPrepareHeader(_handle, wh, sizeof(WAVEHDR));
|
---|
694 |
|
---|
695 | fill_buffer((int16*)wh->lpData, wh->dwBufferLength>>1);
|
---|
696 | waveOutWrite(_handle, wh, sizeof(WAVEHDR));
|
---|
697 | }
|
---|
698 |
|
---|
699 | void WndMan::sound_init() {
|
---|
700 | WAVEFORMATEX wfx;
|
---|
701 |
|
---|
702 | memset(&wfx, 0, sizeof(wfx));
|
---|
703 | wfx.wFormatTag = WAVE_FORMAT_PCM;
|
---|
704 | wfx.nChannels = 1;
|
---|
705 | wfx.nSamplesPerSec = SAMPLES_PER_SEC;
|
---|
706 | wfx.nAvgBytesPerSec = SAMPLES_PER_SEC * BITS_PER_SAMPLE / 8;
|
---|
707 | wfx.wBitsPerSample = BITS_PER_SAMPLE;
|
---|
708 | wfx.nBlockAlign = BITS_PER_SAMPLE * 1 / 8;
|
---|
709 |
|
---|
710 | CreateThread(NULL, 0, (unsigned long (__stdcall *)(void *))&sound_thread, this, 0, &_threadId);
|
---|
711 | SetThreadPriority((void*)_threadId, THREAD_PRIORITY_HIGHEST);
|
---|
712 |
|
---|
713 | _event = CreateEvent(NULL, false, false, NULL);
|
---|
714 |
|
---|
715 | memset(_hdr,0,sizeof(_hdr));
|
---|
716 |
|
---|
717 | waveOutOpen(&_handle, WAVE_MAPPER, &wfx, (long)_event, (long)this, CALLBACK_EVENT );
|
---|
718 |
|
---|
719 | prepare_header(&_hdr[0], 0);
|
---|
720 | prepare_header(&_hdr[1], 1);
|
---|
721 | }
|
---|
722 |
|
---|
723 | DWORD _stdcall WndMan::sound_thread(WndMan *wm) {
|
---|
724 | int i;
|
---|
725 | bool signaled;
|
---|
726 | int time = GetTickCount(), cur;
|
---|
727 |
|
---|
728 | while (1) {
|
---|
729 |
|
---|
730 | if (!snd_driv.wave_based()) {
|
---|
731 | cur = GetTickCount();
|
---|
732 | while (time < cur) {
|
---|
733 | sound.on_timer();
|
---|
734 | time += 10;
|
---|
735 | }
|
---|
736 | }
|
---|
737 |
|
---|
738 | signaled = WaitForSingleObject(wm->_event, time - cur) == WAIT_OBJECT_0;
|
---|
739 |
|
---|
740 | if (signaled) {
|
---|
741 | for(i=0; i<2; i++) {
|
---|
742 | WAVEHDR *hdr = &wm->_hdr[i];
|
---|
743 | if (hdr->dwFlags & WHDR_DONE) {
|
---|
744 | fill_buffer((int16*)hdr->lpData, hdr->dwBufferLength>>1);
|
---|
745 | waveOutWrite(wm->_handle, hdr, sizeof(WAVEHDR));
|
---|
746 | }
|
---|
747 | }
|
---|
748 | }
|
---|
749 | }
|
---|
750 | }
|
---|
751 |
|
---|
752 |
|
---|
753 | #undef main
|
---|
754 | int main(int argc, char* argv[]) {
|
---|
755 | int delta;
|
---|
756 |
|
---|
757 | wm->init();
|
---|
758 | wm->_vgabuf = (byte*)calloc(320,200);
|
---|
759 | wm->_scumm = &scumm;
|
---|
760 |
|
---|
761 | sound.initialize(&scumm,&snd_driv);
|
---|
762 |
|
---|
763 | wm->sound_init();
|
---|
764 |
|
---|
765 | scumm._gui = &gui;
|
---|
766 | scumm.scummMain(argc, argv);
|
---|
767 | gui.init(&scumm);
|
---|
768 |
|
---|
769 | delta = 0;
|
---|
770 | do {
|
---|
771 | updateScreen(&scumm);
|
---|
772 |
|
---|
773 | waitForTimer(&scumm, delta*15);
|
---|
774 |
|
---|
775 | if (gui._active) {
|
---|
776 | gui.loop();
|
---|
777 | delta = 3;
|
---|
778 | } else {
|
---|
779 | delta = scumm.scummLoop(delta);
|
---|
780 | }
|
---|
781 | } while(1);
|
---|
782 |
|
---|
783 | return 0;
|
---|
784 | }
|
---|
785 |
|
---|