| 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.28 2002/02/26 18:00:00 mcleod2032 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 |
|
|---|
| 51 | static bool shutdown;
|
|---|
| 52 |
|
|---|
| 53 | #if USE_GDI
|
|---|
| 54 | typedef struct DIB
|
|---|
| 55 | {
|
|---|
| 56 | HBITMAP hSect;
|
|---|
| 57 | byte *buf;
|
|---|
| 58 | RGBQUAD *pal;
|
|---|
| 59 | bool new_pal;
|
|---|
| 60 | } DIB;
|
|---|
| 61 | #endif
|
|---|
| 62 |
|
|---|
| 63 | class WndMan
|
|---|
| 64 | {
|
|---|
| 65 | HMODULE hInst;
|
|---|
| 66 | bool terminated;
|
|---|
| 67 |
|
|---|
| 68 | #if USE_GDI
|
|---|
| 69 | public:
|
|---|
| 70 | DIB dib;
|
|---|
| 71 | private:
|
|---|
| 72 | #endif
|
|---|
| 73 |
|
|---|
| 74 | public:
|
|---|
| 75 | HWND hWnd;
|
|---|
| 76 | bool fscreen;
|
|---|
| 77 |
|
|---|
| 78 | byte *_vgabuf;
|
|---|
| 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 | {
|
|---|
| 126 | if (key>=VK_F1 && key<=VK_F9) return key - VK_F1 + 315;
|
|---|
| 127 | return key;
|
|---|
| 128 | }
|
|---|
| 129 |
|
|---|
| 130 | static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|---|
| 131 | {
|
|---|
| 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 | {
|
|---|
| 156 | if (wParam=='F') wm->_scumm->_fastMode ^= 1;
|
|---|
| 157 | if (wParam=='G') veryFastMode ^= 1;
|
|---|
| 158 | if (wParam=='D') debugger.attach(wm->_scumm);
|
|---|
| 159 | if (wParam=='S') wm->_scumm->resourceStats();
|
|---|
| 160 | }
|
|---|
| 161 |
|
|---|
| 162 | if ((GetAsyncKeyState(VK_MENU)<0) && (wParam == VK_RETURN)) wm->switchFullScreen(!wm->fscreen);
|
|---|
| 163 |
|
|---|
| 164 | wm->_scumm->_keyPressed = mapKey(wParam);
|
|---|
| 165 | break;
|
|---|
| 166 |
|
|---|
| 167 | case WM_MOUSEMOVE:
|
|---|
| 168 | GetClientRect(hWnd, &r);
|
|---|
| 169 | wm->_scumm->mouse.x = (SRC_WIDTH * ((int16*)&lParam)[0]) / (r.right - r.left);
|
|---|
| 170 | wm->_scumm->mouse.y = (SRC_HEIGHT * ((int16*)&lParam)[1]) / (r.bottom - r.top);
|
|---|
| 171 | break;
|
|---|
| 172 | case WM_LBUTTONDOWN:
|
|---|
| 173 | wm->_scumm->_leftBtnPressed |= msClicked|msDown;
|
|---|
| 174 | break;
|
|---|
| 175 | case WM_LBUTTONUP:
|
|---|
| 176 | wm->_scumm->_leftBtnPressed &= ~msDown;
|
|---|
| 177 | break;
|
|---|
| 178 | case WM_RBUTTONDOWN:
|
|---|
| 179 | wm->_scumm->_rightBtnPressed |= msClicked|msDown;
|
|---|
| 180 | break;
|
|---|
| 181 | case WM_RBUTTONUP:
|
|---|
| 182 | wm->_scumm->_rightBtnPressed &= ~msDown;
|
|---|
| 183 | break;
|
|---|
| 184 |
|
|---|
| 185 | case WM_SYSCOMMAND:
|
|---|
| 186 | switch (wParam)
|
|---|
| 187 | {
|
|---|
| 188 | case SC_MAXIMIZE:
|
|---|
| 189 | wm->switchFullScreen(true);
|
|---|
| 190 | break;
|
|---|
| 191 | case SC_RESTORE:
|
|---|
| 192 | wm->switchFullScreen(!wm->fscreen);
|
|---|
| 193 | break;
|
|---|
| 194 | default:
|
|---|
| 195 | return DefWindowProc(hWnd, message, wParam, lParam);
|
|---|
| 196 | }
|
|---|
| 197 | break;
|
|---|
| 198 |
|
|---|
| 199 | default:
|
|---|
| 200 | return DefWindowProc(hWnd, message, wParam, lParam);
|
|---|
| 201 | }
|
|---|
| 202 | return 0;
|
|---|
| 203 | }
|
|---|
| 204 |
|
|---|
| 205 | #if USE_GDI
|
|---|
| 206 |
|
|---|
| 207 | bool WndMan::allocateDIB(int w, int h)
|
|---|
| 208 | {
|
|---|
| 209 | struct
|
|---|
| 210 | {
|
|---|
| 211 | BITMAPINFOHEADER bih;
|
|---|
| 212 | RGBQUAD rgb[256];
|
|---|
| 213 | } d;
|
|---|
| 214 |
|
|---|
| 215 | if (dib.hSect) return true;
|
|---|
| 216 |
|
|---|
| 217 | memset(&d.bih, 0, sizeof(d.bih));
|
|---|
| 218 | d.bih.biSize = sizeof(d.bih);
|
|---|
| 219 | d.bih.biWidth = w;
|
|---|
| 220 | d.bih.biHeight = -h;
|
|---|
| 221 | d.bih.biPlanes = 1;
|
|---|
| 222 | d.bih.biBitCount = 8;
|
|---|
| 223 | d.bih.biCompression = BI_RGB;
|
|---|
| 224 |
|
|---|
| 225 | memcpy(d.rgb, dib.pal, 256*sizeof(RGBQUAD));
|
|---|
| 226 | dib.new_pal=false;
|
|---|
| 227 |
|
|---|
| 228 | dib.hSect = CreateDIBSection(0, (BITMAPINFO*)&d, DIB_RGB_COLORS, (void**)&dib.buf, NULL, NULL);
|
|---|
| 229 |
|
|---|
| 230 | return dib.hSect != NULL;
|
|---|
| 231 | }
|
|---|
| 232 |
|
|---|
| 233 | void WndMan::writeToScreen() {
|
|---|
| 234 | RECT r;
|
|---|
| 235 | HDC dc,bmpdc;
|
|---|
| 236 | HBITMAP bmpOld;
|
|---|
| 237 |
|
|---|
| 238 | if (_vgabuf) for (int y=0; y<200; y++) memcpy(dib.buf + y*320,_vgabuf + y*320, 320);
|
|---|
| 239 |
|
|---|
| 240 | GetClientRect(hWnd, &r);
|
|---|
| 241 | dc = GetDC(hWnd);
|
|---|
| 242 |
|
|---|
| 243 | bmpdc = CreateCompatibleDC(dc);
|
|---|
| 244 | bmpOld = (HBITMAP)SelectObject(bmpdc, dib.hSect);
|
|---|
| 245 |
|
|---|
| 246 | if (dib.new_pal)
|
|---|
| 247 | {
|
|---|
| 248 | dib.new_pal = false;
|
|---|
| 249 | SetDIBColorTable(bmpdc, 0, 256, dib.pal);
|
|---|
| 250 | }
|
|---|
| 251 |
|
|---|
| 252 | SetStretchBltMode(dc, BLACKONWHITE);
|
|---|
| 253 |
|
|---|
| 254 | StretchBlt(dc, r.left, r.top, r.right-r.left, r.bottom-r.top, bmpdc, 0, 0, SRC_WIDTH, SRC_HEIGHT, SRCCOPY);
|
|---|
| 255 |
|
|---|
| 256 | SelectObject(bmpdc, bmpOld);
|
|---|
| 257 | DeleteDC(bmpdc);
|
|---|
| 258 | ReleaseDC(hWnd, dc);
|
|---|
| 259 | }
|
|---|
| 260 |
|
|---|
| 261 | void WndMan::setPalette(byte *ctab, int first, int num)
|
|---|
| 262 | {
|
|---|
| 263 | int i;
|
|---|
| 264 |
|
|---|
| 265 | for (i=0; i<256; i++)
|
|---|
| 266 | {
|
|---|
| 267 | dib.pal[i].rgbRed = ctab[i*3+0];
|
|---|
| 268 | dib.pal[i].rgbGreen = ctab[i*3+1];
|
|---|
| 269 | dib.pal[i].rgbBlue = ctab[i*3+2];
|
|---|
| 270 | }
|
|---|
| 271 |
|
|---|
| 272 | dib.new_pal = true;
|
|---|
| 273 | }
|
|---|
| 274 |
|
|---|
| 275 | #endif
|
|---|
| 276 |
|
|---|
| 277 | HWND globWnd;
|
|---|
| 278 |
|
|---|
| 279 | void WndMan::init()
|
|---|
| 280 | {
|
|---|
| 281 |
|
|---|
| 282 | /* Retrieve the handle of this module */
|
|---|
| 283 | hInst = GetModuleHandle(NULL);
|
|---|
| 284 |
|
|---|
| 285 | /* Register the window class */
|
|---|
| 286 | WNDCLASSEX wcex;
|
|---|
| 287 | wcex.cbSize = sizeof(WNDCLASSEX);
|
|---|
| 288 | wcex.style = CS_HREDRAW | CS_VREDRAW;
|
|---|
| 289 | wcex.lpfnWndProc = (WNDPROC)WndProc;
|
|---|
| 290 | wcex.cbClsExtra = 0;
|
|---|
| 291 | wcex.cbWndExtra = 0;
|
|---|
| 292 | wcex.hInstance = hInst;
|
|---|
| 293 | wcex.hIcon = 0;
|
|---|
| 294 | wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|---|
| 295 | wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
|
|---|
| 296 | wcex.lpszMenuName = 0;
|
|---|
| 297 | wcex.lpszClassName = "ScummVM";
|
|---|
| 298 | wcex.hIconSm = 0;
|
|---|
| 299 | if (!RegisterClassEx(&wcex)) Error("Cannot register window class!");
|
|---|
| 300 |
|
|---|
| 301 | #if USE_GDI
|
|---|
| 302 | globWnd = hWnd = CreateWindow("ScummVM", "ScummVM", WS_SCUMMWINDOW,
|
|---|
| 303 | CW_USEDEFAULT, CW_USEDEFAULT, DEST_WIDTH+10, DEST_HEIGHT+30,
|
|---|
| 304 | NULL, NULL, hInst, NULL);
|
|---|
| 305 | SetWindowLong(hWnd, GWL_USERDATA, (long)this);
|
|---|
| 306 |
|
|---|
| 307 | dib.pal = (RGBQUAD*)calloc(sizeof(RGBQUAD),256);
|
|---|
| 308 | dib.new_pal = false;
|
|---|
| 309 |
|
|---|
| 310 | if (!allocateDIB(SRC_WIDTH, SRC_HEIGHT)) Error("allocateDIB failed!");
|
|---|
| 311 |
|
|---|
| 312 | ShowWindow(hWnd, SW_SHOW);
|
|---|
| 313 | // FreeConsole();
|
|---|
| 314 | #endif
|
|---|
| 315 |
|
|---|
| 316 | }
|
|---|
| 317 |
|
|---|
| 318 |
|
|---|
| 319 | bool WndMan::handleMessage()
|
|---|
| 320 | {
|
|---|
| 321 | MSG msg;
|
|---|
| 322 |
|
|---|
| 323 | if (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) return false;
|
|---|
| 324 |
|
|---|
| 325 | if (msg.message == WM_QUIT)
|
|---|
| 326 | {
|
|---|
| 327 | terminated=true;
|
|---|
| 328 | exit(1);
|
|---|
| 329 | return true;
|
|---|
| 330 | }
|
|---|
| 331 |
|
|---|
| 332 | TranslateMessage(&msg);
|
|---|
| 333 | DispatchMessage(&msg);
|
|---|
| 334 |
|
|---|
| 335 | return true;
|
|---|
| 336 | }
|
|---|
| 337 |
|
|---|
| 338 | void WndMan::switchFullScreen(bool fs)
|
|---|
| 339 | {
|
|---|
| 340 | if (fs == TRUE)
|
|---|
| 341 | {
|
|---|
| 342 | SetWindowLong(wm->hWnd, GWL_STYLE, WS_SCUMMFULLSCREEN);
|
|---|
| 343 | ShowWindow(wm->hWnd, SW_MAXIMIZE);
|
|---|
| 344 | }
|
|---|
| 345 | else
|
|---|
| 346 | {
|
|---|
| 347 | SetWindowLong(wm->hWnd, GWL_STYLE, WS_SCUMMWINDOW);
|
|---|
| 348 | ShowWindow(wm->hWnd, SW_RESTORE);
|
|---|
| 349 | MoveWindow(wm->hWnd, 0, 0, DEST_WIDTH+10, DEST_HEIGHT+30, TRUE);
|
|---|
| 350 | }
|
|---|
| 351 | wm->fscreen = fs;
|
|---|
| 352 | }
|
|---|
| 353 |
|
|---|
| 354 |
|
|---|
| 355 | unsigned long rdtsc_timer;
|
|---|
| 356 |
|
|---|
| 357 | void _declspec(naked) beginpentiumtest() {
|
|---|
| 358 | _asm {
|
|---|
| 359 | rdtsc
|
|---|
| 360 | mov rdtsc_timer,eax
|
|---|
| 361 | ret
|
|---|
| 362 | }
|
|---|
| 363 | }
|
|---|
| 364 |
|
|---|
| 365 | int _declspec(naked) endpentiumtest() {
|
|---|
| 366 | _asm {
|
|---|
| 367 | rdtsc
|
|---|
| 368 | sub eax,rdtsc_timer
|
|---|
| 369 | ret
|
|---|
| 370 | }
|
|---|
| 371 | }
|
|---|
| 372 |
|
|---|
| 373 |
|
|---|
| 374 | void decompressMask(byte *d, byte *s, int w=320, int h=144)
|
|---|
| 375 | {
|
|---|
| 376 | int x,y;
|
|---|
| 377 |
|
|---|
| 378 | for (y=0; y<h; y++) {
|
|---|
| 379 | byte *p = s+y*40;
|
|---|
| 380 | byte *pd = d + y*320;
|
|---|
| 381 | byte bits = 0x80, bdata = *p++;
|
|---|
| 382 | for (x=0; x<w; x++) {
|
|---|
| 383 | *pd++ = (bdata & bits) ? 128 : 0;
|
|---|
| 384 | bits>>=1;
|
|---|
| 385 | if (!bits) {
|
|---|
| 386 | bdata = *p++;
|
|---|
| 387 | bits=0x80;
|
|---|
| 388 | }
|
|---|
| 389 | }
|
|---|
| 390 | }
|
|---|
| 391 | }
|
|---|
| 392 |
|
|---|
| 393 | void outputlittlemask(byte *mask, int w, int h)
|
|---|
| 394 | {
|
|---|
| 395 | byte *old = wm->_vgabuf;
|
|---|
| 396 | wm->_vgabuf = NULL;
|
|---|
| 397 | decompressMask(wm->dib.buf, mask, w, h);
|
|---|
| 398 | wm->writeToScreen();
|
|---|
| 399 | wm->_vgabuf = old;
|
|---|
| 400 | }
|
|---|
| 401 |
|
|---|
| 402 | void outputdisplay2(Scumm *s, int disp)
|
|---|
| 403 | {
|
|---|
| 404 | byte *old = wm->_vgabuf;
|
|---|
| 405 |
|
|---|
| 406 | byte buf[64000];
|
|---|
| 407 |
|
|---|
| 408 | switch(disp)
|
|---|
| 409 | {
|
|---|
| 410 | case 0:
|
|---|
| 411 | wm->_vgabuf = buf;
|
|---|
| 412 | memcpy(buf, wm->_vgabuf, 64000);
|
|---|
| 413 | memcpy(buf,s->getResourceAddress(rtBuffer, 5),320*200);
|
|---|
| 414 | break;
|
|---|
| 415 | case 1:
|
|---|
| 416 | wm->_vgabuf = buf;
|
|---|
| 417 | memcpy(buf, wm->_vgabuf, 64000);
|
|---|
| 418 | memcpy(buf,s->getResourceAddress(rtBuffer, 1),320*200);
|
|---|
| 419 | break;
|
|---|
| 420 | case 2:
|
|---|
| 421 | wm->_vgabuf = NULL;
|
|---|
| 422 | decompressMask(wm->dib.buf, s->getResourceAddress(rtBuffer, 9)+s->_screenStartStrip);
|
|---|
| 423 | break;
|
|---|
| 424 | case 3:
|
|---|
| 425 | wm->_vgabuf = NULL;
|
|---|
| 426 | decompressMask(wm->dib.buf, s->getResourceAddress(rtBuffer, 9)+8160+s->_screenStartStrip);
|
|---|
| 427 | break;
|
|---|
| 428 | case 4:
|
|---|
| 429 | wm->_vgabuf = NULL;
|
|---|
| 430 | decompressMask(wm->dib.buf, s->getResourceAddress(rtBuffer, 9)+8160*2+s->_screenStartStrip);
|
|---|
| 431 | break;
|
|---|
| 432 | case 5:
|
|---|
| 433 | wm->_vgabuf = NULL;
|
|---|
| 434 | decompressMask(wm->dib.buf, s->getResourceAddress(rtBuffer, 9)+8160*3+s->_screenStartStrip);
|
|---|
| 435 | break;
|
|---|
| 436 | }
|
|---|
| 437 | wm->writeToScreen();
|
|---|
| 438 | wm->_vgabuf = old;
|
|---|
| 439 | }
|
|---|
| 440 |
|
|---|
| 441 | void blitToScreen(Scumm *s, byte *src,int x, int y, int w, int h)
|
|---|
| 442 | {
|
|---|
| 443 | byte *dst;
|
|---|
| 444 | RECT *r;
|
|---|
| 445 | int i;
|
|---|
| 446 |
|
|---|
| 447 | dst = (byte*)wm->_vgabuf + y*320 + x;
|
|---|
| 448 |
|
|---|
| 449 | do
|
|---|
| 450 | {
|
|---|
| 451 | memcpy(dst, src, w);
|
|---|
| 452 | dst += 320;
|
|---|
| 453 | src += 320;
|
|---|
| 454 | } while (--h);
|
|---|
| 455 |
|
|---|
| 456 | }
|
|---|
| 457 |
|
|---|
| 458 | void setShakePos(Scumm *s, int shake_pos) {}
|
|---|
| 459 |
|
|---|
| 460 | int clock;
|
|---|
| 461 |
|
|---|
| 462 | void updateScreen(Scumm *s)
|
|---|
| 463 | {
|
|---|
| 464 | if (s->_palDirtyMax != -1)
|
|---|
| 465 | {
|
|---|
| 466 | wm->setPalette(s->_currentPalette, 0, 256);
|
|---|
| 467 | s->_palDirtyMax = -1;
|
|---|
| 468 | }
|
|---|
| 469 | wm->writeToScreen();
|
|---|
| 470 | }
|
|---|
| 471 |
|
|---|
| 472 | void waitForTimer(Scumm *s, int delay)
|
|---|
| 473 | {
|
|---|
| 474 | wm->handleMessage();
|
|---|
| 475 | if (!veryFastMode)
|
|---|
| 476 | {
|
|---|
| 477 | assert(delay<5000);
|
|---|
| 478 | if (s->_fastMode) delay=10;
|
|---|
| 479 | Sleep(delay);
|
|---|
| 480 | }
|
|---|
| 481 | }
|
|---|
| 482 |
|
|---|
| 483 | void initGraphics(Scumm *s, bool fullScreen)
|
|---|
| 484 | {
|
|---|
| 485 | SetWindowText(wm->hWnd, s->getGameName());
|
|---|
| 486 | wm->switchFullScreen(fullScreen);
|
|---|
| 487 | }
|
|---|
| 488 |
|
|---|
| 489 |
|
|---|
| 490 | void drawMouse(Scumm *s, int x, int y, int w, int h, byte *buf, bool visible) {}
|
|---|
| 491 |
|
|---|
| 492 | void fill_buffer(int16 *buf, int len) { scumm.mixWaves(buf, len); }
|
|---|
| 493 |
|
|---|
| 494 | void cd_playtrack(int track, int offset, int delay)
|
|---|
| 495 | {
|
|---|
| 496 | UINT wDeviceID;
|
|---|
| 497 | DWORD dwReturn;
|
|---|
| 498 | MCI_OPEN_PARMS mciOpenParms;
|
|---|
| 499 | MCI_SET_PARMS mciSetParms;
|
|---|
| 500 | MCI_PLAY_PARMS mciPlayParms;
|
|---|
| 501 | int start, end;
|
|---|
| 502 |
|
|---|
| 503 | start = (offset / 24);
|
|---|
| 504 | end = (start + delay / 24);
|
|---|
| 505 |
|
|---|
| 506 | mciOpenParms.lpstrDeviceType = "cdaudio";
|
|---|
| 507 | if (dwReturn = mciSendCommand(NULL, MCI_OPEN, MCI_OPEN_TYPE, (DWORD)(LPVOID) &mciOpenParms)) return;
|
|---|
| 508 |
|
|---|
| 509 | wDeviceID = mciOpenParms.wDeviceID;
|
|---|
| 510 | mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF;
|
|---|
| 511 | if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD)(LPVOID) &mciSetParms))
|
|---|
| 512 | {
|
|---|
| 513 | mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
|
|---|
| 514 | return;
|
|---|
| 515 | }
|
|---|
| 516 |
|
|---|
| 517 | mciPlayParms.dwFrom = MCI_MAKE_TMSF(track, start / 60, start % 60, 0);
|
|---|
| 518 | mciPlayParms.dwTo = MCI_MAKE_TMSF(track, end / 60, end % 60, 0);
|
|---|
| 519 |
|
|---|
| 520 | if (dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_FROM | MCI_TO | MCI_NOTIFY | MCI_TRACK, (DWORD)(LPVOID) &mciPlayParms))
|
|---|
| 521 | mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
|
|---|
| 522 | }
|
|---|
| 523 |
|
|---|
| 524 | void WndMan::prepare_header(WAVEHDR *wh, int i)
|
|---|
| 525 | {
|
|---|
| 526 | memset(wh, 0, sizeof(WAVEHDR));
|
|---|
| 527 | wh->lpData = (char*)malloc(BUFFER_SIZE);
|
|---|
| 528 | wh->dwBufferLength = BUFFER_SIZE;
|
|---|
| 529 |
|
|---|
| 530 | waveOutPrepareHeader(_handle, wh, sizeof(WAVEHDR));
|
|---|
| 531 |
|
|---|
| 532 | fill_buffer((int16*)wh->lpData, wh->dwBufferLength>>1);
|
|---|
| 533 | waveOutWrite(_handle, wh, sizeof(WAVEHDR));
|
|---|
| 534 | }
|
|---|
| 535 |
|
|---|
| 536 | void WndMan::sound_init()
|
|---|
| 537 | {
|
|---|
| 538 | WAVEFORMATEX wfx;
|
|---|
| 539 |
|
|---|
| 540 | memset(&wfx, 0, sizeof(wfx));
|
|---|
| 541 | wfx.wFormatTag = WAVE_FORMAT_PCM;
|
|---|
| 542 | wfx.nChannels = 1;
|
|---|
| 543 | wfx.nSamplesPerSec = SAMPLES_PER_SEC;
|
|---|
| 544 | wfx.nAvgBytesPerSec = SAMPLES_PER_SEC * BITS_PER_SAMPLE / 8;
|
|---|
| 545 | wfx.wBitsPerSample = BITS_PER_SAMPLE;
|
|---|
| 546 | wfx.nBlockAlign = BITS_PER_SAMPLE * 1 / 8;
|
|---|
| 547 |
|
|---|
| 548 | CreateThread(NULL, 0, (unsigned long (__stdcall *)(void *))&sound_thread, this, 0, &_threadId);
|
|---|
| 549 | SetThreadPriority((void*)_threadId, THREAD_PRIORITY_HIGHEST);
|
|---|
| 550 |
|
|---|
| 551 | _event = CreateEvent(NULL, false, false, NULL);
|
|---|
| 552 |
|
|---|
| 553 | memset(_hdr,0,sizeof(_hdr));
|
|---|
| 554 |
|
|---|
| 555 | waveOutOpen(&_handle, WAVE_MAPPER, &wfx, (long)_event, (long)this, CALLBACK_EVENT);
|
|---|
| 556 |
|
|---|
| 557 | prepare_header(&_hdr[0], 0);
|
|---|
| 558 | prepare_header(&_hdr[1], 1);
|
|---|
| 559 | }
|
|---|
| 560 |
|
|---|
| 561 | DWORD _stdcall WndMan::sound_thread(WndMan *wm)
|
|---|
| 562 | {
|
|---|
| 563 | int i;
|
|---|
| 564 | bool signaled;
|
|---|
| 565 | int time = GetTickCount(), cur;
|
|---|
| 566 |
|
|---|
| 567 | while (1)
|
|---|
| 568 | {
|
|---|
| 569 |
|
|---|
| 570 | if (!snd_driv.wave_based())
|
|---|
| 571 | {
|
|---|
| 572 | cur = GetTickCount();
|
|---|
| 573 | while (time < cur)
|
|---|
| 574 | {
|
|---|
| 575 | sound.on_timer();
|
|---|
| 576 | time += 10;
|
|---|
| 577 | }
|
|---|
| 578 | }
|
|---|
| 579 |
|
|---|
| 580 | signaled = WaitForSingleObject(wm->_event, time - cur) == WAIT_OBJECT_0;
|
|---|
| 581 |
|
|---|
| 582 | if (signaled)
|
|---|
| 583 | {
|
|---|
| 584 | for(i=0; i<2; i++)
|
|---|
| 585 | {
|
|---|
| 586 | WAVEHDR *hdr = &wm->_hdr[i];
|
|---|
| 587 | if (hdr->dwFlags & WHDR_DONE)
|
|---|
| 588 | {
|
|---|
| 589 | fill_buffer((int16*)hdr->lpData, hdr->dwBufferLength>>1);
|
|---|
| 590 | waveOutWrite(wm->_handle, hdr, sizeof(WAVEHDR));
|
|---|
| 591 | }
|
|---|
| 592 | }
|
|---|
| 593 | }
|
|---|
| 594 | }
|
|---|
| 595 | }
|
|---|
| 596 |
|
|---|
| 597 |
|
|---|
| 598 | #undef main
|
|---|
| 599 | int main(int argc, char* argv[])
|
|---|
| 600 | {
|
|---|
| 601 | int delta;
|
|---|
| 602 |
|
|---|
| 603 | wm->init();
|
|---|
| 604 | wm->_vgabuf = (byte*)calloc(320,200);
|
|---|
| 605 | wm->_scumm = &scumm;
|
|---|
| 606 |
|
|---|
| 607 | sound.initialize(&scumm,&snd_driv);
|
|---|
| 608 |
|
|---|
| 609 | wm->sound_init();
|
|---|
| 610 |
|
|---|
| 611 | scumm._gui = &gui;
|
|---|
| 612 | scumm.scummMain(argc, argv);
|
|---|
| 613 |
|
|---|
| 614 | if (!(scumm._features & GF_SMALL_HEADER)) gui.init(&scumm);
|
|---|
| 615 |
|
|---|
| 616 | delta = 0;
|
|---|
| 617 |
|
|---|
| 618 | while(1)
|
|---|
| 619 | {
|
|---|
| 620 | updateScreen(&scumm);
|
|---|
| 621 | waitForTimer(&scumm, delta*15);
|
|---|
| 622 |
|
|---|
| 623 | if (gui._active)
|
|---|
| 624 | {
|
|---|
| 625 | gui.loop();
|
|---|
| 626 | delta = 3;
|
|---|
| 627 | }
|
|---|
| 628 | else delta = scumm.scummLoop(delta);
|
|---|
| 629 | };
|
|---|
| 630 |
|
|---|
| 631 | return 0;
|
|---|
| 632 | }
|
|---|
| 633 |
|
|---|
| 634 | void BoxTest(int num) {;} // Test code
|
|---|
| 635 |
|
|---|
| 636 |
|
|---|