diff options
Diffstat (limited to 'win32.c')
-rw-r--r-- | win32.c | 1040 |
1 files changed, 13 insertions, 1027 deletions
@@ -2,1050 +2,37 @@ #include "openttd.h" #include "debug.h" #include "functions.h" +#include "macros.h" #include "saveload.h" #include "string.h" #include "table/strings.h" #include "gfx.h" -#include "mixer.h" #include "window.h" -#include "gui.h" #include <windows.h> -#include <mmsystem.h> -#include "hal.h" #include <winnt.h> #include <wininet.h> #include <io.h> #include <fcntl.h> -#include "network.h" #include "variables.h" -#define SMART_PALETTE_ANIM - -static struct { - HWND main_wnd; - HBITMAP dib_sect; - Pixel *bitmap_bits; - Pixel *buffer_bits; - Pixel *alloced_bits; - HPALETTE gdi_palette; - int width,height; - int width_org, height_org; - bool cursor_visible; - bool switch_driver; - bool fullscreen; - bool double_size; - bool has_focus; - bool running; -} _wnd; - -static HINSTANCE _inst; -static bool _has_console; - -#if defined(__MINGW32__) || defined(__CYGWIN__) - #define __TIMESTAMP__ __DATE__ __TIME__ -#endif - -#ifdef WIN32_ENABLE_DIRECTMUSIC_SUPPORT -extern const HalMusicDriver _dmusic_midi_driver; -#endif - -static void MakePalette(void) -{ - LOGPALETTE *pal; - uint i; - - pal = alloca(sizeof(LOGPALETTE) + (256-1) * sizeof(PALETTEENTRY)); - - pal->palVersion = 0x300; - pal->palNumEntries = 256; - - for (i = 0; i != 256; i++) { - pal->palPalEntry[i].peRed = _cur_palette[i].r; - pal->palPalEntry[i].peGreen = _cur_palette[i].g; - pal->palPalEntry[i].peBlue = _cur_palette[i].b; - pal->palPalEntry[i].peFlags = 0; - - } - _wnd.gdi_palette = CreatePalette(pal); - if (_wnd.gdi_palette == NULL) - error("CreatePalette failed!\n"); -} - -static void UpdatePalette(HDC dc, uint start, uint count) -{ - RGBQUAD rgb[256]; - uint i; - - for (i = 0; i != count; i++) { - rgb[i].rgbRed = _cur_palette[start + i].r; - rgb[i].rgbGreen = _cur_palette[start + i].g; - rgb[i].rgbBlue = _cur_palette[start + i].b; - rgb[i].rgbReserved = 0; - } - - SetDIBColorTable(dc, start, count, rgb); -} - -static bool MyShowCursor(bool show) -{ - if (_wnd.cursor_visible == show) - return show; - - _wnd.cursor_visible = show; - ShowCursor(show); - - return !show; -} - -typedef struct { - byte vk_from; - byte vk_count; - byte map_to; -} VkMapping; - -#define AS(x, z) {x, 0, z} -#define AM(x, y, z, w) {x, y - x, z} - -#ifndef VK_OEM_3 -#define VK_OEM_3 0xC0 -#endif - -static const VkMapping _vk_mapping[] = { - // Pageup stuff + up/down - AM(VK_PRIOR,VK_DOWN, WKC_PAGEUP, WKC_DOWN), - // Map letters & digits - AM('A','Z','A','Z'), - AM('0','9','0','9'), - - AS(VK_ESCAPE, WKC_ESC), - AS(VK_PAUSE, WKC_PAUSE), - AS(VK_BACK, WKC_BACKSPACE), - AM(VK_INSERT,VK_DELETE,WKC_INSERT, WKC_DELETE), - - AS(VK_SPACE, WKC_SPACE), - AS(VK_RETURN, WKC_RETURN), - AS(VK_TAB, WKC_TAB), - - // Function keys - AM(VK_F1, VK_F12, WKC_F1, WKC_F12), - - // Numeric part. - // What is the virtual keycode for numeric enter?? - AM(VK_NUMPAD0,VK_NUMPAD9, WKC_NUM_0, WKC_NUM_9), - AS(VK_DIVIDE, WKC_NUM_DIV), - AS(VK_MULTIPLY, WKC_NUM_MUL), - AS(VK_SUBTRACT, WKC_NUM_MINUS), - AS(VK_ADD, WKC_NUM_PLUS), - AS(VK_DECIMAL, WKC_NUM_DECIMAL) -}; - -static uint MapWindowsKey(uint sym) -{ - const VkMapping *map; - uint key = 0; - - for (map = _vk_mapping; map != endof(_vk_mapping); ++map) { - if ((uint)(sym - map->vk_from) <= map->vk_count) { - key = sym - map->vk_from + map->map_to; - break; - } - } - - if (GetAsyncKeyState(VK_SHIFT) < 0) key |= WKC_SHIFT; - if (GetAsyncKeyState(VK_CONTROL) < 0) key |= WKC_CTRL; - if (GetAsyncKeyState(VK_MENU) < 0) key |= WKC_ALT; - return key; -} - -static void MakeWindow(bool full_screen); -static bool AllocateDibSection(int w, int h); - -static void ClientSizeChanged(int w, int h) -{ - if (_wnd.double_size) { - w /= 2; - h /= 2; - } - - // allocate new dib section of the new size - if (AllocateDibSection(w, h)) { - // mark all palette colors dirty - _pal_first_dirty = 0; - _pal_last_dirty = 255; - GameSizeChanged(); - - // redraw screen - if (_wnd.running) { - _screen.dst_ptr = _wnd.buffer_bits; - UpdateWindows(); - } - } -} - -extern void DoExitSave(void); - -#ifdef _DEBUG -// Keep this function here.. -// It allows you to redraw the screen from within the MSVC debugger -int RedrawScreenDebug() -{ - HDC dc,dc2; - static int _fooctr; - HBITMAP old_bmp; - HPALETTE old_palette; - - _screen.dst_ptr = _wnd.buffer_bits; - UpdateWindows(); - - dc = GetDC(_wnd.main_wnd); - dc2 = CreateCompatibleDC(dc); - - old_bmp = SelectObject(dc2, _wnd.dib_sect); - old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE); - BitBlt(dc, 0, 0, _wnd.width, _wnd.height, dc2, 0, 0, SRCCOPY); - SelectPalette(dc, old_palette, TRUE); - SelectObject(dc2, old_bmp); - DeleteDC(dc2); - ReleaseDC(_wnd.main_wnd, dc); - - return _fooctr++; -} -#endif - -static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) { - case WM_PAINT: { - PAINTSTRUCT ps; - HDC dc,dc2; - HBITMAP old_bmp; - HPALETTE old_palette; - BeginPaint(hwnd, &ps); - dc = ps.hdc; - dc2 = CreateCompatibleDC(dc); - old_bmp = SelectObject(dc2, _wnd.dib_sect); - old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE); - - if (_pal_last_dirty != -1) { - UpdatePalette(dc2, _pal_first_dirty, _pal_last_dirty - _pal_first_dirty + 1); - _pal_last_dirty = -1; - } - - BitBlt(dc, 0, 0, _wnd.width, _wnd.height, dc2, 0, 0, SRCCOPY); - SelectPalette(dc, old_palette, TRUE); - SelectObject(dc2, old_bmp); - DeleteDC(dc2); - EndPaint(hwnd, &ps); - } - return 0; - - case WM_PALETTECHANGED: - if ((HWND)wParam == hwnd) - return 0; - // FALL THROUGH - case WM_QUERYNEWPALETTE: { - HDC hDC = GetWindowDC(hwnd); - HPALETTE hOldPalette = SelectPalette(hDC, _wnd.gdi_palette, FALSE); - UINT nChanged = RealizePalette(hDC); - SelectPalette(hDC, hOldPalette, TRUE); - ReleaseDC(hwnd, hDC); - if (nChanged) - InvalidateRect(hwnd, NULL, FALSE); - return 0; - } - - case WM_CLOSE: - if (_game_mode == GM_MENU) { // do not ask to quit on the main screen - _exit_game = true; - } else if (_patches.autosave_on_exit) { - DoExitSave(); - _exit_game = true; - } else - AskExitGame(); - - return 0; - - case WM_LBUTTONDOWN: - SetCapture(hwnd); - _left_button_down = true; - return 0; - - case WM_LBUTTONUP: - ReleaseCapture(); - _left_button_down = false; - _left_button_clicked = false; - return 0; - - case WM_RBUTTONDOWN: - SetCapture(hwnd); - _right_button_down = true; - _right_button_clicked = true; - return 0; - - case WM_RBUTTONUP: - ReleaseCapture(); - _right_button_down = false; - return 0; - - case WM_MOUSEMOVE: { - int x = (int16)LOWORD(lParam); - int y = (int16)HIWORD(lParam); - POINT pt; - - if (_wnd.double_size) { - x /= 2; - y /= 2; - } - - if (_cursor.fix_at) { - int dx = x - _cursor.pos.x; - int dy = y - _cursor.pos.y; - if (dx != 0 || dy != 0) { - _cursor.delta.x += dx; - _cursor.delta.y += dy; - - pt.x = _cursor.pos.x; - pt.y = _cursor.pos.y; - - if (_wnd.double_size) { - pt.x *= 2; - pt.y *= 2; - } - ClientToScreen(hwnd, &pt); - SetCursorPos(pt.x, pt.y); - } - } else { - _cursor.delta.x += x - _cursor.pos.x; - _cursor.delta.y += y - _cursor.pos.y; - _cursor.pos.x = x; - _cursor.pos.y = y; - _cursor.dirty = true; - } - MyShowCursor(false); - return 0; - } - - case WM_KEYDOWN: { - // this is the rewritten ascii input function - // it disables windows deadkey handling --> more linux like :D - unsigned short w = 0; - int r = 0; - byte ks[256]; - unsigned int scan = 0; - uint16 scancode = (( lParam & 0xFF0000 ) >> 16 ); - - GetKeyboardState(ks); - r = ToAscii(wParam, scan, ks, &w, 0); - if (r == 0) w = 0; // no translation was possible - - _pressed_key = w | MapWindowsKey(wParam) << 16; - - if (scancode == 41) - _pressed_key = w | WKC_BACKQUOTE << 16; - - if ((_pressed_key >> 16) == ('D' | WKC_CTRL) && !_wnd.fullscreen) { - _double_size ^= 1; - _wnd.double_size = _double_size; - ClientSizeChanged(_wnd.width, _wnd.height); - MarkWholeScreenDirty(); - } - } break; - - case WM_SYSKEYDOWN: /* user presses F10 or Alt, both activating the title-menu */ - switch (wParam) { - case VK_RETURN: case 0x46: /* Full Screen on ALT + ENTER/F(VK_F) */ - ToggleFullScreen(!_wnd.fullscreen); - return 0; - case VK_MENU: /* Just ALT */ - return 0; // do nothing - case VK_F10: /* F10, ignore activation of menu */ - _pressed_key = MapWindowsKey(wParam) << 16; - return 0; - default: /* ALT in combination with something else */ - _pressed_key = MapWindowsKey(wParam) << 16; - break; - } - break; - case WM_NCMOUSEMOVE: - MyShowCursor(true); - return 0; - - case WM_SIZE: { - if (wParam != SIZE_MINIMIZED) { - ClientSizeChanged(LOWORD(lParam), HIWORD(lParam)); - } - return 0; - } - case WM_SIZING: { - RECT* r = (RECT*)lParam; - RECT r2; - int w, h; - - SetRect(&r2, 0, 0, 0, 0); - AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE); - - w = r->right - r->left - (r2.right - r2.left); - h = r->bottom - r->top - (r2.bottom - r2.top); - if (_wnd.double_size) { - w /= 2; - h /= 2; - } - w = clamp(w, 64, MAX_SCREEN_WIDTH); - h = clamp(h, 64, MAX_SCREEN_HEIGHT); - if (_wnd.double_size) { - w *= 2; - h *= 2; - } - SetRect(&r2, 0, 0, w, h); - - AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE); - w = r2.right - r2.left; - h = r2.bottom - r2.top; - - switch (wParam) { - case WMSZ_BOTTOM: - r->bottom = r->top + h; - break; - case WMSZ_BOTTOMLEFT: - r->bottom = r->top + h; - r->left = r->right - w; - break; - case WMSZ_BOTTOMRIGHT: - r->bottom = r->top + h; - r->right = r->left + w; - break; - case WMSZ_LEFT: - r->left = r->right - w; - break; - case WMSZ_RIGHT: - r->right = r->left + w; - break; - case WMSZ_TOP: - r->top = r->bottom - h; - break; - case WMSZ_TOPLEFT: - r->top = r->bottom - h; - r->left = r->right - w; - break; - case WMSZ_TOPRIGHT: - r->top = r->bottom - h; - r->right = r->left + w; - break; - } - return TRUE; - } +#include "driver.h" -// needed for wheel -#if !defined(WM_MOUSEWHEEL) -# define WM_MOUSEWHEEL 0x020A -#endif //WM_MOUSEWHEEL -#if !defined(GET_WHEEL_DELTA_WPARAM) -# define GET_WHEEL_DELTA_WPARAM(wparam) ((short)HIWORD(wparam)) -#endif //GET_WHEEL_DELTA_WPARAM - - case WM_MOUSEWHEEL: { - int delta = GET_WHEEL_DELTA_WPARAM(wParam); - - if (delta < 0) { - _cursor.wheel++; - } else if (delta > 0) { - _cursor.wheel--; - } - return 0; - } - - case WM_ACTIVATEAPP: - _wnd.has_focus = (bool)wParam; - break; - } - return DefWindowProc(hwnd, msg, wParam, lParam); -} +#include "music/dmusic.h" +#include "music/null.h" +#include "music/win32.h" -static void RegisterWndClass(void) -{ - static bool registered; - if (!registered) { - HINSTANCE hinst = GetModuleHandle(NULL); - WNDCLASS wnd = { - 0, - WndProcGdi, - 0, - 0, - hinst, - LoadIcon(hinst, MAKEINTRESOURCE(100)), - LoadCursor(NULL, IDC_ARROW), - 0, - 0, - "OTTD" - }; - registered = true; - if (!RegisterClass(&wnd)) - error("RegisterClass failed"); - } -} - -extern const char _openttd_revision[]; - -static void MakeWindow(bool full_screen) -{ - _fullscreen = full_screen; - - _wnd.double_size = _double_size && !full_screen; - - // recreate window? - if ((full_screen || _wnd.fullscreen) && _wnd.main_wnd) { - DestroyWindow(_wnd.main_wnd); - _wnd.main_wnd = 0; - } +#include "sound/null.h" +#include "sound/win32.h" - if (full_screen) { - DEVMODE settings; - memset(&settings, 0, sizeof(DEVMODE)); - settings.dmSize = sizeof(DEVMODE); - settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; +#include "video/null.h" +#include "video/win32.h" - if (_fullscreen_bpp) { - settings.dmBitsPerPel = _fullscreen_bpp; - settings.dmFields |= DM_BITSPERPEL; - } - settings.dmPelsWidth = _wnd.width_org; - settings.dmPelsHeight = _wnd.height_org; - settings.dmDisplayFrequency = _display_hz; - if (settings.dmDisplayFrequency != 0) - settings.dmFields |= DM_DISPLAYFREQUENCY; - if (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) { - MakeWindow(false); - return; - } - } else if (_wnd.fullscreen) { - // restore display? - ChangeDisplaySettings(NULL, 0); - } - - { - RECT r; - uint style; - int x, y, w, h; - - _wnd.fullscreen = full_screen; - if (_wnd.fullscreen) { - style = WS_POPUP | WS_VISIBLE; - SetRect(&r, 0, 0, _wnd.width_org, _wnd.height_org); - } else { - style = WS_OVERLAPPEDWINDOW | WS_VISIBLE; - SetRect(&r, 0, 0, _wnd.width, _wnd.height); - } - - AdjustWindowRect(&r, style, FALSE); - w = r.right - r.left; - h = r.bottom - r.top; - x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2; - y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2; - - if (_wnd.main_wnd) { - SetWindowPos(_wnd.main_wnd, 0, x, y, w, h, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER); - } else { - char Windowtitle[50]; - - snprintf(Windowtitle, lengthof(Windowtitle), "OpenTTD %s", _openttd_revision); - - _wnd.main_wnd = CreateWindow("OTTD", Windowtitle, style, x, y, w, h, 0, 0, _inst, 0); - if (_wnd.main_wnd == NULL) - error("CreateWindow failed"); - } - } - GameSizeChanged(); // invalidate all windows, force redraw -} - -static bool AllocateDibSection(int w, int h) -{ - BITMAPINFO *bi; - HDC dc; - - w = clamp(w, 64, MAX_SCREEN_WIDTH); - h = clamp(h, 64, MAX_SCREEN_HEIGHT); - - if (w == _screen.width && h == _screen.height) - return false; - - _screen.width = w; - _screen.pitch = (w + 3) & ~0x3; - _screen.height = h; - - if (_wnd.alloced_bits) { - free(_wnd.alloced_bits); - _wnd.alloced_bits = NULL; - } - - bi = alloca(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256); - memset(bi, 0, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256); - bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - - if (_wnd.double_size) { - w = (w + 3) & ~0x3; - _wnd.alloced_bits = _wnd.buffer_bits = malloc(w * h); - w *= 2; - h *= 2; - } - - bi->bmiHeader.biWidth = _wnd.width = w; - bi->bmiHeader.biHeight = -(_wnd.height = h); - - bi->bmiHeader.biPlanes = 1; - bi->bmiHeader.biBitCount = 8; - bi->bmiHeader.biCompression = BI_RGB; - - if (_wnd.dib_sect) - DeleteObject(_wnd.dib_sect); - - dc = GetDC(0); - _wnd.dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (void**)&_wnd.bitmap_bits, NULL, 0); - if (_wnd.dib_sect == NULL) - error("CreateDIBSection failed"); - ReleaseDC(0, dc); - - if (!_wnd.double_size) - _wnd.buffer_bits = _wnd.bitmap_bits; - - return true; -} - -static const uint16 default_resolutions[][2] = { - { 640, 480}, - { 800, 600}, - {1024, 768}, - {1152, 864}, - {1280, 800}, - {1280, 960}, - {1280, 1024}, - {1400, 1050}, - {1600, 1200}, - {1680, 1050}, - {1920, 1200} -}; - -static void FindResolutions(void) -{ - int i = 0, n = 0; - DEVMODE dm; - - while (EnumDisplaySettings(NULL, i++, &dm) != 0) { - if (dm.dmBitsPerPel == 8 && IS_INT_INSIDE(dm.dmPelsWidth, 640, MAX_SCREEN_WIDTH + 1) && - IS_INT_INSIDE(dm.dmPelsHeight, 480, MAX_SCREEN_HEIGHT + 1)){ - int j; - for (j = 0; j < n; j++) { - if (_resolutions[j][0] == dm.dmPelsWidth && _resolutions[j][1] == dm.dmPelsHeight) break; - } - - /* In the previous loop we have checked already existing/added resolutions if - * they are the same as the new ones. If this is not the case (j == n); we have - * looped all and found none, add the new one to the list. If we have reached the - * maximum amount of resolutions, then quit querying the display */ - if (j == n) { - _resolutions[j][0] = dm.dmPelsWidth; - _resolutions[j][1] = dm.dmPelsHeight; - if (++n == lengthof(_resolutions)) break; - } - } - } - - /* We have found no resolutions, show the default list */ - if (n == 0) { - memcpy(_resolutions, default_resolutions, sizeof(default_resolutions)); - n = lengthof(default_resolutions); - } - - _num_resolutions = n; - SortResolutions(_num_resolutions); -} - - -static const char *Win32GdiStart(const char * const *parm) -{ - memset(&_wnd, 0, sizeof(_wnd)); - _wnd.cursor_visible = true; - - RegisterWndClass(); - - MakePalette(); - - FindResolutions(); - - // fullscreen uses those - _wnd.width_org = _cur_resolution[0]; - _wnd.height_org = _cur_resolution[1]; - - AllocateDibSection(_cur_resolution[0], _cur_resolution[1]); - MarkWholeScreenDirty(); - - MakeWindow(_fullscreen); - - return NULL; -} - -static void Win32GdiStop(void) -{ - if (_wnd.fullscreen) ChangeDisplaySettings(NULL, 0); - MyShowCursor(true); - DeleteObject(_wnd.gdi_palette); - DeleteObject(_wnd.dib_sect); - DestroyWindow(_wnd.main_wnd); -} - -// simple upscaler by 2 -static void filter(int left, int top, int width, int height) -{ - uint p = _screen.pitch; - const Pixel *s = _wnd.buffer_bits + top * p + left; - Pixel *d = _wnd.bitmap_bits + top * p * 4 + left * 2; - - for (; height > 0; height--) { - int i; - - for (i = 0; i != width; i++) { - d[i * 2] = d[i * 2 + 1] = d[i * 2 + p * 2] = d[i * 2 + 1 + p * 2] = s[i]; - } - s += p; - d += p * 4; - } -} - -static void Win32GdiMakeDirty(int left, int top, int width, int height) -{ - RECT r = { left, top, left + width, top + height }; - - if (_wnd.double_size) { - filter(left, top, width, height); - r.left *= 2; - r.top *= 2; - r.right *= 2; - r.bottom *= 2; - } - InvalidateRect(_wnd.main_wnd, &r, FALSE); -} - -static void CheckPaletteAnim(void) -{ - if (_pal_last_dirty == -1) - return; - InvalidateRect(_wnd.main_wnd, NULL, FALSE); -} - -static int Win32GdiMainLoop(void) -{ - MSG mesg; - uint32 next_tick = GetTickCount() + 30, cur_ticks; - - _wnd.running = true; - - while(true) { - while (PeekMessage(&mesg, NULL, 0, 0, PM_REMOVE)) { - InteractiveRandom(); // randomness - TranslateMessage(&mesg); - DispatchMessage(&mesg); - } - if (_exit_game) return ML_QUIT; - if (_wnd.switch_driver) return ML_SWITCHDRIVER; +static bool _has_console; -#if defined(_DEBUG) - if (_wnd.has_focus && GetAsyncKeyState(VK_SHIFT) < 0) { - if ( -#else - if (_wnd.has_focus && GetAsyncKeyState(VK_TAB) < 0) { - /* Disable speeding up game with ALT+TAB (if syskey is pressed, the - * real key is in the upper 16 bits (see WM_SYSKEYDOWN in WndProcGdi()) */ - if ((_pressed_key >> 16) & WKC_TAB && +#if defined(__MINGW32__) || defined(__CYGWIN__) + #define __TIMESTAMP__ __DATE__ __TIME__ #endif - !_networking && _game_mode != GM_MENU) - _fast_forward |= 2; - } else if (_fast_forward & 2) - _fast_forward = 0; - - cur_ticks = GetTickCount(); - if ((_fast_forward && !_pause) || cur_ticks > next_tick) - next_tick = cur_ticks; - - if (cur_ticks == next_tick) { - next_tick += 30; - _ctrl_pressed = _wnd.has_focus && GetAsyncKeyState(VK_CONTROL)<0; - _shift_pressed = _wnd.has_focus && GetAsyncKeyState(VK_SHIFT)<0; - _dbg_screen_rect = _wnd.has_focus && GetAsyncKeyState(VK_CAPITAL)<0; - - // determine which directional keys are down - if (_wnd.has_focus) { - _dirkeys = - (GetAsyncKeyState(VK_LEFT) < 0 ? 1 : 0) + - (GetAsyncKeyState(VK_UP) < 0 ? 2 : 0) + - (GetAsyncKeyState(VK_RIGHT) < 0 ? 4 : 0) + - (GetAsyncKeyState(VK_DOWN) < 0 ? 8 : 0); - } else - _dirkeys = 0; - - GameLoop(); - _cursor.delta.x = _cursor.delta.y = 0; - - if (_force_full_redraw) - MarkWholeScreenDirty(); - - GdiFlush(); - _screen.dst_ptr = _wnd.buffer_bits; - UpdateWindows(); - CheckPaletteAnim(); - } else { - Sleep(1); - GdiFlush(); - _screen.dst_ptr = _wnd.buffer_bits; - DrawTextMessage(); - DrawMouseCursor(); - } - } -} - -static bool Win32GdiChangeRes(int w, int h) -{ - _wnd.width = _wnd.width_org = w; - _wnd.height = _wnd.height_org = h; - - MakeWindow(_fullscreen); // _wnd.fullscreen screws up ingame resolution switching - return true; -} - -static void Win32GdiFullScreen(bool full_screen) {MakeWindow(full_screen);} - -const HalVideoDriver _win32_video_driver = { - Win32GdiStart, - Win32GdiStop, - Win32GdiMakeDirty, - Win32GdiMainLoop, - Win32GdiChangeRes, - Win32GdiFullScreen, -}; - - -/********************** - * WIN32 MIDI PLAYER - **********************/ - -static struct { - bool stop_song; - bool terminate; - bool playing; - int new_vol; - HANDLE wait_obj; - char start_song[260]; -} _midi; - -static void Win32MidiPlaySong(const char *filename) -{ - strcpy(_midi.start_song, filename); - _midi.playing = true; - _midi.stop_song = false; - SetEvent(_midi.wait_obj); -} - -static void Win32MidiStopSong(void) -{ - if (_midi.playing) { - _midi.stop_song = true; - _midi.start_song[0] = '\0'; - SetEvent(_midi.wait_obj); - } -} - -static bool Win32MidiIsSongPlaying(void) -{ - return _midi.playing; -} - -static void Win32MidiSetVolume(byte vol) -{ - _midi.new_vol = vol; - SetEvent(_midi.wait_obj); -} - -static long CDECL MidiSendCommand(const char *cmd, ...) { - va_list va; - char buf[512]; - - va_start(va, cmd); - vsprintf(buf, cmd, va); - va_end(va); - return mciSendStringA(buf, NULL, 0, 0); -} - -static bool MidiIntPlaySong(const char *filename) -{ - MidiSendCommand("close all"); - if (MidiSendCommand("open \"%s\" type sequencer alias song", filename) != 0) - return false; - - if (MidiSendCommand("play song from 0") != 0) - return false; - return true; -} - -static void MidiIntStopSong(void) -{ - MidiSendCommand("close all"); -} - -static void MidiIntSetVolume(int vol) -{ - uint v = (vol * 65535 / 127); - midiOutSetVolume((HMIDIOUT)-1, v + (v << 16)); -} - -static bool MidiIntIsSongPlaying(void) -{ - char buf[16]; - mciSendStringA("status song mode", buf, sizeof(buf), 0); - return strcmp(buf, "playing") == 0 || strcmp(buf, "seeking") == 0; -} - -static DWORD WINAPI MidiThread(LPVOID arg) -{ - _midi.wait_obj = CreateEvent(NULL, FALSE, FALSE, NULL); - - do { - char *s; - int vol; - - vol = _midi.new_vol; - if (vol != -1) { - _midi.new_vol = -1; - MidiIntSetVolume(vol); - } - - s = _midi.start_song; - if (s[0] != '\0') { - _midi.playing = MidiIntPlaySong(s); - s[0] = '\0'; - - // Delay somewhat in case we don't manage to play. - if (!_midi.playing) { - Sleep(5000); - } - } - - if (_midi.stop_song && _midi.playing) { - _midi.stop_song = false; - _midi.playing = false; - MidiIntStopSong(); - } - - if (_midi.playing && !MidiIntIsSongPlaying()) - _midi.playing = false; - - WaitForMultipleObjects(1, &_midi.wait_obj, FALSE, 1000); - } while (!_midi.terminate); - - DeleteObject(_midi.wait_obj); - return 0; -} - -static const char *Win32MidiStart(const char * const *parm) -{ - DWORD threadId; - - memset(&_midi, 0, sizeof(_midi)); - _midi.new_vol = -1; - CreateThread(NULL, 8192, MidiThread, 0, 0, &threadId); - return 0; -} - -static void Win32MidiStop(void) -{ - _midi.terminate = true; - SetEvent(_midi.wait_obj); -} - -const HalMusicDriver _win32_music_driver = { - Win32MidiStart, - Win32MidiStop, - Win32MidiPlaySong, - Win32MidiStopSong, - Win32MidiIsSongPlaying, - Win32MidiSetVolume, -}; - -// WIN32 Sound code. - -static HWAVEOUT _waveout; -static WAVEHDR _wave_hdr[2]; -static int _bufsize; -static void PrepareHeader(WAVEHDR *hdr) -{ - hdr->dwBufferLength = _bufsize * 4; - hdr->dwFlags = 0; - hdr->lpData = malloc(_bufsize * 4); - if (hdr->lpData == NULL || - waveOutPrepareHeader(_waveout, hdr, sizeof(WAVEHDR)) != MMSYSERR_NOERROR) - error("waveOutPrepareHeader failed"); -} - -static void FillHeaders(void) -{ - WAVEHDR *hdr; - - for (hdr = _wave_hdr; hdr != endof(_wave_hdr); hdr++) { - if (!(hdr->dwFlags & WHDR_INQUEUE)) { - MxMixSamples(_mixer, hdr->lpData, hdr->dwBufferLength / 4); - if (waveOutWrite(_waveout, hdr, sizeof(WAVEHDR)) != MMSYSERR_NOERROR) - error("waveOutWrite failed"); - } - } -} - -static void CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, - DWORD dwParam1, DWORD dwParam2) -{ - switch (uMsg) { - case WOM_DONE: - if (_waveout) FillHeaders(); - break; - - default: - break; - } -} - -static const char *Win32SoundStart(const char * const *parm) -{ - WAVEFORMATEX wfex; - int hz; - - _bufsize = GetDriverParamInt(parm, "bufsize", 1024); - hz = GetDriverParamInt(parm, "hz", 11025); - wfex.wFormatTag = WAVE_FORMAT_PCM; - wfex.nChannels = 2; - wfex.nSamplesPerSec = hz; - wfex.nAvgBytesPerSec = hz*2*2; - wfex.nBlockAlign = 4; - wfex.wBitsPerSample = 16; - if (waveOutOpen(&_waveout, WAVE_MAPPER, &wfex, (DWORD)&waveOutProc, 0, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) - return "waveOutOpen failed"; - PrepareHeader(&_wave_hdr[0]); - PrepareHeader(&_wave_hdr[1]); - FillHeaders(); - return NULL; -} - -static void Win32SoundStop(void) -{ - HWAVEOUT waveout = _waveout; - - _waveout = NULL; - waveOutReset(waveout); - waveOutUnprepareHeader(waveout, &_wave_hdr[0], sizeof(WAVEHDR)); - waveOutUnprepareHeader(waveout, &_wave_hdr[1], sizeof(WAVEHDR)); - waveOutClose(waveout); -} - -const HalSoundDriver _win32_sound_driver = { - Win32SoundStart, - Win32SoundStop, -}; // Helper function needed by dynamically loading SDL bool LoadLibraryList(void **proc, const char *dll) @@ -2092,7 +1079,7 @@ void CreateConsole(void) SetConsoleScreenBufferSize(hand, coninfo.dwSize); // redirect unbuffered STDIN, STDOUT, STDERR to the console -#if !defined(__CYGWIN__) +#if !defined(__CYGWIN__) && 0 *stdout = *_fdopen( _open_osfhandle((long)hand, _O_TEXT), "w" ); *stdin = *_fdopen(_open_osfhandle((long)GetStdHandle(STD_INPUT_HANDLE), _O_TEXT), "r" ); *stderr = *_fdopen(_open_osfhandle((long)GetStdHandle(STD_ERROR_HANDLE), _O_TEXT), "w" ); @@ -2132,7 +1119,6 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, { int argc; char *argv[64]; // max 64 command line arguments - _inst = hInstance; #if defined(_DEBUG) CreateConsole(); |