| 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 |
|
|---|