win32.c
changeset 193 0a7025304867
parent 164 0cbdf3c9bde1
child 196 c4c33c0764a0
equal deleted inserted replaced
192:614bba52258d 193:0a7025304867
    49 
    49 
    50 	pal = alloca(sizeof(LOGPALETTE) + (256-1) * sizeof(PALETTEENTRY));
    50 	pal = alloca(sizeof(LOGPALETTE) + (256-1) * sizeof(PALETTEENTRY));
    51 
    51 
    52 	pal->palVersion = 0x300;
    52 	pal->palVersion = 0x300;
    53 	pal->palNumEntries = 256;
    53 	pal->palNumEntries = 256;
    54 	
    54 
    55 	for(i=0,b=_cur_palette; i!=256;i++,b+=3) {
    55 	for(i=0,b=_cur_palette; i!=256;i++,b+=3) {
    56 		pal->palPalEntry[i].peRed = b[0];
    56 		pal->palPalEntry[i].peRed = b[0];
    57 		pal->palPalEntry[i].peGreen = b[1];
    57 		pal->palPalEntry[i].peGreen = b[1];
    58 		pal->palPalEntry[i].peBlue = b[2];
    58 		pal->palPalEntry[i].peBlue = b[2];
    59 		pal->palPalEntry[i].peFlags = 0;
    59 		pal->palPalEntry[i].peFlags = 0;
    60 
    60 
    61 	}
    61 	}
    62 	_wnd.gdi_palette = CreatePalette(pal);
    62 	_wnd.gdi_palette = CreatePalette(pal);
    63 	if (_wnd.gdi_palette == NULL)	
    63 	if (_wnd.gdi_palette == NULL)
    64 		error("CreatePalette failed!\n");
    64 		error("CreatePalette failed!\n");
    65 }
    65 }
    66 
    66 
    67 static void UpdatePalette(HDC dc, uint start, uint count)
    67 static void UpdatePalette(HDC dc, uint start, uint count)
    68 {
    68 {
   131 	AS(VK_DIVIDE,			WKC_NUM_DIV),
   131 	AS(VK_DIVIDE,			WKC_NUM_DIV),
   132 	AS(VK_MULTIPLY,		WKC_NUM_MUL),
   132 	AS(VK_MULTIPLY,		WKC_NUM_MUL),
   133 	AS(VK_SUBTRACT,		WKC_NUM_MINUS),
   133 	AS(VK_SUBTRACT,		WKC_NUM_MINUS),
   134 	AS(VK_ADD,				WKC_NUM_PLUS),
   134 	AS(VK_ADD,				WKC_NUM_PLUS),
   135 	AS(VK_DECIMAL,		WKC_NUM_DECIMAL),
   135 	AS(VK_DECIMAL,		WKC_NUM_DECIMAL),
   136 	{0}	
   136 	{0}
   137 };
   137 };
   138 
   138 
   139 static uint MapWindowsKey(uint key)
   139 static uint MapWindowsKey(uint key)
   140 {
   140 {
   141 	const VkMapping	*map = _vk_mapping - 1;
   141 	const VkMapping	*map = _vk_mapping - 1;
   160 static bool AllocateDibSection(int w, int h);
   160 static bool AllocateDibSection(int w, int h);
   161 
   161 
   162 static void ClientSizeChanged(int w, int h)
   162 static void ClientSizeChanged(int w, int h)
   163 {
   163 {
   164 	if (_wnd.double_size) { w >>= 1; h >>= 1; }
   164 	if (_wnd.double_size) { w >>= 1; h >>= 1; }
   165 	
   165 
   166 	// allocate new dib section of the new size
   166 	// allocate new dib section of the new size
   167 	if (AllocateDibSection(w, h)) {
   167 	if (AllocateDibSection(w, h)) {
   168 		// mark all palette colors dirty
   168 		// mark all palette colors dirty
   169 		_pal_first_dirty = 0;
   169 		_pal_first_dirty = 0;
   170 		_pal_last_dirty = 255;
   170 		_pal_last_dirty = 255;
   171 		GameSizeChanged();
   171 		GameSizeChanged();
   172 		
   172 
   173 		// redraw screen
   173 		// redraw screen
   174 		if (_wnd.running) {
   174 		if (_wnd.running) {
   175 			_screen.dst_ptr = _wnd.buffer_bits;
   175 			_screen.dst_ptr = _wnd.buffer_bits;
   176 			UpdateWindows();
   176 			UpdateWindows();
   177 		}
   177 		}
   189 		BeginPaint(hwnd, &ps);
   189 		BeginPaint(hwnd, &ps);
   190 		dc = ps.hdc;
   190 		dc = ps.hdc;
   191 		dc2 = CreateCompatibleDC(dc);
   191 		dc2 = CreateCompatibleDC(dc);
   192 		old_bmp = SelectObject(dc2, _wnd.dib_sect);
   192 		old_bmp = SelectObject(dc2, _wnd.dib_sect);
   193 		old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE);
   193 		old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE);
   194 		
   194 
   195 		if (_pal_last_dirty != -1) {
   195 		if (_pal_last_dirty != -1) {
   196 			UpdatePalette(dc2, _pal_first_dirty, _pal_last_dirty - _pal_first_dirty + 1);
   196 			UpdatePalette(dc2, _pal_first_dirty, _pal_last_dirty - _pal_first_dirty + 1);
   197 			_pal_last_dirty = -1;
   197 			_pal_last_dirty = -1;
   198 		}
   198 		}
   199 				
   199 
   200 		BitBlt(dc, 0, 0, _wnd.width, _wnd.height, dc2, 0, 0, SRCCOPY);
   200 		BitBlt(dc, 0, 0, _wnd.width, _wnd.height, dc2, 0, 0, SRCCOPY);
   201 		SelectPalette(dc, old_palette, TRUE);
   201 		SelectPalette(dc, old_palette, TRUE);
   202 		SelectObject(dc2, old_bmp);
   202 		SelectObject(dc2, old_bmp);
   203 		DeleteDC(dc2);
   203 		DeleteDC(dc2);
   204 		EndPaint(hwnd, &ps);
   204 		EndPaint(hwnd, &ps);
   217 		ReleaseDC(hwnd, hDC);
   217 		ReleaseDC(hwnd, hDC);
   218 		if (nChanged)
   218 		if (nChanged)
   219 			InvalidateRect(hwnd, NULL, FALSE);
   219 			InvalidateRect(hwnd, NULL, FALSE);
   220 		return 0;
   220 		return 0;
   221 	}
   221 	}
   222 		
   222 
   223 	case WM_CLOSE:
   223 	case WM_CLOSE:
   224 		AskExitGame();
   224 		AskExitGame();
   225 		return 0;
   225 		return 0;
   226 
   226 
   227 	case WM_LBUTTONDOWN:
   227 	case WM_LBUTTONDOWN:
   253 
   253 
   254 		if (_wnd.double_size) {
   254 		if (_wnd.double_size) {
   255 			x >>= 1;
   255 			x >>= 1;
   256 			y >>= 1;
   256 			y >>= 1;
   257 		}
   257 		}
   258 		
   258 
   259 		if (_cursor.fix_at) {
   259 		if (_cursor.fix_at) {
   260 			int dx = x - _cursor.pos.x;
   260 			int dx = x - _cursor.pos.x;
   261 			int dy = y - _cursor.pos.y;
   261 			int dy = y - _cursor.pos.y;
   262 			if (dx != 0 || dy != 0) {
   262 			if (dx != 0 || dy != 0) {
   263 				_cursor.delta.x += dx;
   263 				_cursor.delta.x += dx;
   283 		MyShowCursor(false);
   283 		MyShowCursor(false);
   284 		return 0;
   284 		return 0;
   285 	}
   285 	}
   286 
   286 
   287 	case WM_KEYDOWN:
   287 	case WM_KEYDOWN:
   288 		{         
   288 		{
   289 		// this is the rewritten ascii input function
   289 		// this is the rewritten ascii input function
   290 		// it disables windows deadkey handling --> more linux like :D
   290 		// it disables windows deadkey handling --> more linux like :D
   291         unsigned short w = 0;
   291         unsigned short w = 0;
   292 		int r = 0;
   292 		int r = 0;
   293 		byte ks[256];
   293 		byte ks[256];
   302 			_double_size ^= 1;
   302 			_double_size ^= 1;
   303 			_wnd.double_size = _double_size;
   303 			_wnd.double_size = _double_size;
   304 			ClientSizeChanged(_wnd.width, _wnd.height);
   304 			ClientSizeChanged(_wnd.width, _wnd.height);
   305 			MarkWholeScreenDirty();
   305 			MarkWholeScreenDirty();
   306 		}
   306 		}
   307 		break;	
   307 		break;
   308 
   308 
   309 
   309 
   310 	case WM_SYSKEYDOWN:
   310 	case WM_SYSKEYDOWN:
   311 		switch(wParam) {
   311 		switch(wParam) {
   312 		case VK_RETURN:
   312 		case VK_RETURN:
   332 		RECT r2;
   332 		RECT r2;
   333 		int w, h;
   333 		int w, h;
   334 
   334 
   335 		SetRect(&r2, 0, 0, 0, 0);
   335 		SetRect(&r2, 0, 0, 0, 0);
   336 		AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE);
   336 		AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE);
   337 		
   337 
   338 		w = r->right - r->left - (r2.right - r2.left);
   338 		w = r->right - r->left - (r2.right - r2.left);
   339 		h = r->bottom - r->top - (r2.bottom - r2.top);
   339 		h = r->bottom - r->top - (r2.bottom - r2.top);
   340 		if (_wnd.double_size) { w >>= 1; h >>= 1; }
   340 		if (_wnd.double_size) { w >>= 1; h >>= 1; }
   341 		w = clamp(w & ~0x7, 64, MAX_SCREEN_WIDTH);
   341 		w = clamp(w & ~0x7, 64, MAX_SCREEN_WIDTH);
   342 		h = clamp(h & ~0x7, 64, MAX_SCREEN_HEIGHT);
   342 		h = clamp(h & ~0x7, 64, MAX_SCREEN_HEIGHT);
   387 #if !defined(GET_WHEEL_DELTA_WPARAM)
   387 #if !defined(GET_WHEEL_DELTA_WPARAM)
   388 # define GET_WHEEL_DELTA_WPARAM(wparam) ((short)HIWORD(wparam))
   388 # define GET_WHEEL_DELTA_WPARAM(wparam) ((short)HIWORD(wparam))
   389 #endif  //GET_WHEEL_DELTA_WPARAM
   389 #endif  //GET_WHEEL_DELTA_WPARAM
   390 
   390 
   391 	case WM_MOUSEWHEEL: {
   391 	case WM_MOUSEWHEEL: {
   392 		int delta = GET_WHEEL_DELTA_WPARAM(wParam);	
   392 		int delta = GET_WHEEL_DELTA_WPARAM(wParam);
   393 		if (delta < 0) {
   393 		if (delta < 0) {
   394 			_cursor.wheel++;
   394 			_cursor.wheel++;
   395 		} else if (delta > 0) {
   395 		} else if (delta > 0) {
   396 			_cursor.wheel--;
   396 			_cursor.wheel--;
   397 		}
   397 		}
   431 static void MakeWindow(bool full_screen)
   431 static void MakeWindow(bool full_screen)
   432 {
   432 {
   433 	_fullscreen = full_screen;
   433 	_fullscreen = full_screen;
   434 
   434 
   435 	_wnd.double_size = _double_size && !full_screen;
   435 	_wnd.double_size = _double_size && !full_screen;
   436 	
   436 
   437 	// recreate window?
   437 	// recreate window?
   438 	if ((full_screen|_wnd.fullscreen) && _wnd.main_wnd) {
   438 	if ((full_screen|_wnd.fullscreen) && _wnd.main_wnd) {
   439 		DestroyWindow(_wnd.main_wnd);
   439 		DestroyWindow(_wnd.main_wnd);
   440 		_wnd.main_wnd = 0;
   440 		_wnd.main_wnd = 0;
   441 	}
   441 	}
   442 	
   442 
   443 	if (full_screen) {
   443 	if (full_screen) {
   444 		DEVMODE settings;
   444 		DEVMODE settings;
   445 		memset(&settings, 0, sizeof(DEVMODE));
   445 		memset(&settings, 0, sizeof(DEVMODE));
   446 		settings.dmSize = sizeof(DEVMODE);
   446 		settings.dmSize = sizeof(DEVMODE);
   447 		settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
   447 		settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
   465 
   465 
   466 	{
   466 	{
   467 		RECT r;
   467 		RECT r;
   468 		uint style;
   468 		uint style;
   469 		int x, y, w, h;
   469 		int x, y, w, h;
   470 	
   470 
   471 		if ((_wnd.fullscreen=full_screen) != false) {
   471 		if ((_wnd.fullscreen=full_screen) != false) {
   472 			style = WS_POPUP | WS_VISIBLE;
   472 			style = WS_POPUP | WS_VISIBLE;
   473 			SetRect(&r, 0, 0, _wnd.width_org, _wnd.height_org);
   473 			SetRect(&r, 0, 0, _wnd.width_org, _wnd.height_org);
   474 		} else {
   474 		} else {
   475 			style = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
   475 			style = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
   508 
   508 
   509 	if (_wnd.alloced_bits) {
   509 	if (_wnd.alloced_bits) {
   510 		free(_wnd.alloced_bits);
   510 		free(_wnd.alloced_bits);
   511 		_wnd.alloced_bits = NULL;
   511 		_wnd.alloced_bits = NULL;
   512 	}
   512 	}
   513 	
   513 
   514 	bi = alloca(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256);
   514 	bi = alloca(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256);
   515 	memset(bi, 0, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256);
   515 	memset(bi, 0, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256);
   516 	bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
   516 	bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
   517 	
   517 
   518 	{
   518 	{
   519 		if (_wnd.double_size) {
   519 		if (_wnd.double_size) {
   520 			_wnd.alloced_bits = _wnd.buffer_bits = (byte*)malloc(w * h);
   520 			_wnd.alloced_bits = _wnd.buffer_bits = (byte*)malloc(w * h);
   521 			w *= 2;
   521 			w *= 2;
   522 			h *= 2;
   522 			h *= 2;
   523 		}
   523 		}
   524 
   524 
   525 		bi->bmiHeader.biWidth = _wnd.width = w;
   525 		bi->bmiHeader.biWidth = _wnd.width = w;
   526 		bi->bmiHeader.biHeight = -(_wnd.height = h);
   526 		bi->bmiHeader.biHeight = -(_wnd.height = h);
   527 	}
   527 	}
   528 	
   528 
   529 	bi->bmiHeader.biPlanes = 1;
   529 	bi->bmiHeader.biPlanes = 1;
   530 	bi->bmiHeader.biBitCount = 8;
   530 	bi->bmiHeader.biBitCount = 8;
   531 	bi->bmiHeader.biCompression = BI_RGB;
   531 	bi->bmiHeader.biCompression = BI_RGB;
   532 
   532 
   533 	if (_wnd.dib_sect)
   533 	if (_wnd.dib_sect)
   537 	_wnd.dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, &_wnd.bitmap_bits, NULL, 0);
   537 	_wnd.dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, &_wnd.bitmap_bits, NULL, 0);
   538 	if (_wnd.dib_sect == NULL)
   538 	if (_wnd.dib_sect == NULL)
   539 		error("CreateDIBSection failed");
   539 		error("CreateDIBSection failed");
   540 	ReleaseDC(0, dc);
   540 	ReleaseDC(0, dc);
   541 
   541 
   542 	if (!_wnd.double_size) 
   542 	if (!_wnd.double_size)
   543 		_wnd.buffer_bits = _wnd.bitmap_bits;
   543 		_wnd.buffer_bits = _wnd.bitmap_bits;
   544 
   544 
   545 	return true;
   545 	return true;
   546 }
   546 }
   547 
   547 
   560 {
   560 {
   561 	int i = 0, n = 0;
   561 	int i = 0, n = 0;
   562 	DEVMODE dm;
   562 	DEVMODE dm;
   563 
   563 
   564 	while (EnumDisplaySettings(NULL, i++, &dm)) {
   564 	while (EnumDisplaySettings(NULL, i++, &dm)) {
   565 		if (dm.dmBitsPerPel == 8 && 
   565 		if (dm.dmBitsPerPel == 8 &&
   566 				IS_INT_INSIDE(dm.dmPelsWidth, 640, MAX_SCREEN_WIDTH+1) &&
   566 				IS_INT_INSIDE(dm.dmPelsWidth, 640, MAX_SCREEN_WIDTH+1) &&
   567 				IS_INT_INSIDE(dm.dmPelsHeight, 480, MAX_SCREEN_HEIGHT+1) &&
   567 				IS_INT_INSIDE(dm.dmPelsHeight, 480, MAX_SCREEN_HEIGHT+1) &&
   568 				(n == 0 || _resolutions[n-1][0] != dm.dmPelsWidth || _resolutions[n-1][1] != dm.dmPelsHeight)) {
   568 				(n == 0 || _resolutions[n-1][0] != dm.dmPelsWidth || _resolutions[n-1][1] != dm.dmPelsHeight)) {
   569 			_resolutions[n][0] = dm.dmPelsWidth;
   569 			_resolutions[n][0] = dm.dmPelsWidth;
   570 			_resolutions[n][1] = dm.dmPelsHeight;
   570 			_resolutions[n][1] = dm.dmPelsHeight;
   623 	byte *d = (byte*)_wnd.bitmap_bits + top * p * 4 + left * 2;
   623 	byte *d = (byte*)_wnd.bitmap_bits + top * p * 4 + left * 2;
   624 	int i;
   624 	int i;
   625 
   625 
   626 	while (height) {
   626 	while (height) {
   627 		for(i=0; i!=width; i++) {
   627 		for(i=0; i!=width; i++) {
   628 			d[i*2] = d[i*2+1] = d[i*2+p*2] = d[i*2+1+p*2] = s[i];  
   628 			d[i*2] = d[i*2+1] = d[i*2+p*2] = d[i*2+1+p*2] = s[i];
   629 		}
   629 		}
   630 		s += p;
   630 		s += p;
   631 		d += p * 4;
   631 		d += p * 4;
   632 		height--;
   632 		height--;
   633 	}
   633 	}
   674 #endif
   674 #endif
   675 			_fast_forward |= 2;
   675 			_fast_forward |= 2;
   676 		} else if (_fast_forward&2) {
   676 		} else if (_fast_forward&2) {
   677 			_fast_forward = 0;
   677 			_fast_forward = 0;
   678 		}
   678 		}
   679 		
   679 
   680 
   680 
   681 		cur_ticks=GetTickCount();
   681 		cur_ticks=GetTickCount();
   682 		if ((_fast_forward && !_pause) || cur_ticks > next_tick)
   682 		if ((_fast_forward && !_pause) || cur_ticks > next_tick)
   683 			next_tick = cur_ticks;
   683 			next_tick = cur_ticks;
   684 
   684 
   685 		if (cur_ticks == next_tick) {
   685 		if (cur_ticks == next_tick) {
   686 			next_tick += 30;
   686 			next_tick += 30;
   687 			_ctrl_pressed = _wnd.has_focus && GetAsyncKeyState(VK_CONTROL)<0;
   687 			_ctrl_pressed = _wnd.has_focus && GetAsyncKeyState(VK_CONTROL)<0;
   688 			_shift_pressed = _wnd.has_focus && GetAsyncKeyState(VK_SHIFT)<0;
   688 			_shift_pressed = _wnd.has_focus && GetAsyncKeyState(VK_SHIFT)<0;
   689 			_dbg_screen_rect = _wnd.has_focus && GetAsyncKeyState(VK_CAPITAL)<0;
   689 			_dbg_screen_rect = _wnd.has_focus && GetAsyncKeyState(VK_CAPITAL)<0;
   690 			
   690 
   691 			// determine which directional keys are down
   691 			// determine which directional keys are down
   692 			_dirkeys = 
   692 			_dirkeys =
   693 				(GetAsyncKeyState(VK_LEFT) < 0 ? 1 : 0) + 
   693 				(GetAsyncKeyState(VK_LEFT) < 0 ? 1 : 0) +
   694 				(GetAsyncKeyState(VK_UP) < 0 ? 2 : 0) + 
   694 				(GetAsyncKeyState(VK_UP) < 0 ? 2 : 0) +
   695 				(GetAsyncKeyState(VK_RIGHT) < 0 ? 4 : 0) + 
   695 				(GetAsyncKeyState(VK_RIGHT) < 0 ? 4 : 0) +
   696 				(GetAsyncKeyState(VK_DOWN) < 0 ? 8 : 0);
   696 				(GetAsyncKeyState(VK_DOWN) < 0 ? 8 : 0);
   697 
   697 
   698 			GameLoop();	
   698 			GameLoop();
   699 			_cursor.delta.x = _cursor.delta.y = 0;
   699 			_cursor.delta.x = _cursor.delta.y = 0;
   700 
   700 
   701 			if (_force_full_redraw)
   701 			if (_force_full_redraw)
   702 				MarkWholeScreenDirty();
   702 				MarkWholeScreenDirty();
   703 
   703 
   716 
   716 
   717 static bool Win32GdiChangeRes(int w, int h)
   717 static bool Win32GdiChangeRes(int w, int h)
   718 {
   718 {
   719 	_wnd.width = _wnd.width_org = w;
   719 	_wnd.width = _wnd.width_org = w;
   720 	_wnd.height = _wnd.height_org = h;
   720 	_wnd.height = _wnd.height_org = h;
   721 		
   721 
   722 	MakeWindow(_wnd.fullscreen);
   722 	MakeWindow(_wnd.fullscreen);
   723 		
   723 
   724 	return true;
   724 	return true;
   725 }
   725 }
   726 
   726 
   727 const HalVideoDriver _win32_video_driver = {
   727 const HalVideoDriver _win32_video_driver = {
   728 	Win32GdiStart,
   728 	Win32GdiStart,
   821 
   821 
   822 	do {
   822 	do {
   823 		if ((vol=_midi.new_vol) != -1) {
   823 		if ((vol=_midi.new_vol) != -1) {
   824 			_midi.new_vol = -1;
   824 			_midi.new_vol = -1;
   825 			MidiIntSetVolume(vol);
   825 			MidiIntSetVolume(vol);
   826 			
   826 
   827 		}
   827 		}
   828 		if ((s=_midi.start_song)[0]) {
   828 		if ((s=_midi.start_song)[0]) {
   829 			_midi.playing = MidiIntPlaySong(s);
   829 			_midi.playing = MidiIntPlaySong(s);
   830 			s[0] = 0;
   830 			s[0] = 0;
   831 			
   831 
   832 			// Delay somewhat in case we don't manage to play.
   832 			// Delay somewhat in case we don't manage to play.
   833 			if (!_midi.playing) {
   833 			if (!_midi.playing) {
   834 				Sleep(5000);	
   834 				Sleep(5000);
   835 			}
   835 			}
   836 		}
   836 		}
   837 		if (_midi.stop_song != false && _midi.playing) {
   837 		if (_midi.stop_song != false && _midi.playing) {
   838 			_midi.stop_song = false;
   838 			_midi.stop_song = false;
   839 			_midi.playing = false;
   839 			_midi.playing = false;
   891 static void FillHeaders()
   891 static void FillHeaders()
   892 {
   892 {
   893 	WAVEHDR *hdr;
   893 	WAVEHDR *hdr;
   894 	for(hdr=_wave_hdr; hdr != endof(_wave_hdr); hdr++) {
   894 	for(hdr=_wave_hdr; hdr != endof(_wave_hdr); hdr++) {
   895 		if (!(hdr->dwFlags & WHDR_INQUEUE)) {
   895 		if (!(hdr->dwFlags & WHDR_INQUEUE)) {
   896 			MxMixSamples(_mixer, hdr->lpData, hdr->dwBufferLength >> 2);		
   896 			MxMixSamples(_mixer, hdr->lpData, hdr->dwBufferLength >> 2);
   897 			if (waveOutWrite(_waveout, hdr, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
   897 			if (waveOutWrite(_waveout, hdr, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
   898 				error("waveOutWrite failed");
   898 				error("waveOutWrite failed");
   899 		}
   899 		}
   900 	}
   900 	}
   901 }
   901 }
   912 
   912 
   913 static char *Win32SoundStart(char **parm)
   913 static char *Win32SoundStart(char **parm)
   914 {
   914 {
   915 	WAVEFORMATEX wfex;
   915 	WAVEFORMATEX wfex;
   916 	int hz;
   916 	int hz;
   917 	
   917 
   918 	_bufsize = GetDriverParamInt(parm, "bufsize", 1024);
   918 	_bufsize = GetDriverParamInt(parm, "bufsize", 1024);
   919 	hz = GetDriverParamInt(parm, "hz", 11025);
   919 	hz = GetDriverParamInt(parm, "hz", 11025);
   920 	wfex.wFormatTag = WAVE_FORMAT_PCM;
   920 	wfex.wFormatTag = WAVE_FORMAT_PCM;
   921 	wfex.nChannels = 2;
   921 	wfex.nChannels = 2;
   922 	wfex.nSamplesPerSec = hz;
   922 	wfex.nSamplesPerSec = hz;
  1005 static uint32 *_crc_table;
  1005 static uint32 *_crc_table;
  1006 
  1006 
  1007 static void MakeCRCTable(uint32 *table) {
  1007 static void MakeCRCTable(uint32 *table) {
  1008 	uint32 crc, poly = 0xEDB88320L;
  1008 	uint32 crc, poly = 0xEDB88320L;
  1009 	int	i, j;
  1009 	int	i, j;
  1010 	
  1010 
  1011 	_crc_table = table;
  1011 	_crc_table = table;
  1012 
  1012 
  1013 	for (i=0; i!=256; i++) {
  1013 	for (i=0; i!=256; i++) {
  1014 		crc = i;
  1014 		crc = i;
  1015 		for (j=8; j!=0; j--) {
  1015 		for (j=8; j!=0; j--) {
  1049 				filesize += numread;
  1049 				filesize += numread;
  1050 				crc = CalcCRC(buffer, numread, crc);
  1050 				crc = CalcCRC(buffer, numread, crc);
  1051 			}
  1051 			}
  1052 			dfi->size = filesize;
  1052 			dfi->size = filesize;
  1053 			dfi->crc32 = crc ^ (uint32)-1;
  1053 			dfi->crc32 = crc ^ (uint32)-1;
  1054 			
  1054 
  1055 			if (GetFileTime(file, NULL, NULL, &write_time)) {
  1055 			if (GetFileTime(file, NULL, NULL, &write_time)) {
  1056 				FileTimeToSystemTime(&write_time, &dfi->file_time);
  1056 				FileTimeToSystemTime(&write_time, &dfi->file_time);
  1057 			}
  1057 			}
  1058 			CloseHandle(file);
  1058 			CloseHandle(file);
  1059 		}
  1059 		}
  1106 	}
  1106 	}
  1107 	output = PrintModuleInfo(output, NULL);
  1107 	output = PrintModuleInfo(output, NULL);
  1108 	return output;
  1108 	return output;
  1109 }
  1109 }
  1110 
  1110 
  1111 static const char _crash_desc[] = 
  1111 static const char _crash_desc[] =
  1112 	"A serious fault condition occured in the game. The game will shut down.\n"
  1112 	"A serious fault condition occured in the game. The game will shut down.\n"
  1113 	"Press \"Submit report\" to send crash information to the developers. "
  1113 	"Press \"Submit report\" to send crash information to the developers. "
  1114 	"This will greatly help debugging. The information contained in the report is "
  1114 	"This will greatly help debugging. The information contained in the report is "
  1115 	"displayed below.\n"
  1115 	"displayed below.\n"
  1116 	"Press \"Emergency save\" to attempt saving the game.";
  1116 	"Press \"Emergency save\" to attempt saving the game.";
  1117 
  1117 
  1118 static const char _save_succeeded[] = 
  1118 static const char _save_succeeded[] =
  1119 	"Emergency save succeeded.\nBe aware that critical parts of the internal game state "
  1119 	"Emergency save succeeded.\nBe aware that critical parts of the internal game state "
  1120 	"may have become corrupted. The saved game is not guaranteed to work.";
  1120 	"may have become corrupted. The saved game is not guaranteed to work.";
  1121 
  1121 
  1122 bool EmergencySave();
  1122 bool EmergencySave();
  1123 
  1123 
  1130 	BOOL (WINAPI *InternetCloseHandle)(HINTERNET);
  1130 	BOOL (WINAPI *InternetCloseHandle)(HINTERNET);
  1131 	BOOL (WINAPI *HttpQueryInfo)(HINTERNET, DWORD, LPVOID, LPDWORD, LPDWORD);
  1131 	BOOL (WINAPI *HttpQueryInfo)(HINTERNET, DWORD, LPVOID, LPDWORD, LPDWORD);
  1132 } WinInetProcs;
  1132 } WinInetProcs;
  1133 
  1133 
  1134 #define M(x) x "\0"
  1134 #define M(x) x "\0"
  1135 static const char wininet_files[] = 
  1135 static const char wininet_files[] =
  1136 	M("wininet.dll")
  1136 	M("wininet.dll")
  1137 	M("InternetOpenA")
  1137 	M("InternetOpenA")
  1138 	M("InternetConnectA")
  1138 	M("InternetConnectA")
  1139 	M("HttpOpenRequestA")
  1139 	M("HttpOpenRequestA")
  1140 	M("HttpSendRequestA")
  1140 	M("HttpSendRequestA")
  1151 	HINTERNET inet, conn, http;
  1151 	HINTERNET inet, conn, http;
  1152 	char *err = NULL;
  1152 	char *err = NULL;
  1153 	DWORD code, len;
  1153 	DWORD code, len;
  1154 	static char buf[100];
  1154 	static char buf[100];
  1155 	char buff[100];
  1155 	char buff[100];
  1156 	
  1156 
  1157 	if (_wininet.InternetOpen == NULL && !LoadLibraryList((void**)&_wininet, wininet_files)) return "can't load wininet.dll";
  1157 	if (_wininet.InternetOpen == NULL && !LoadLibraryList((void**)&_wininet, wininet_files)) return "can't load wininet.dll";
  1158 
  1158 
  1159 	inet = _wininet.InternetOpen("TTD", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 );
  1159 	inet = _wininet.InternetOpen("TTD", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 );
  1160 	if (inet == NULL) { err = "internetopen failed"; goto error1; }
  1160 	if (inet == NULL) { err = "internetopen failed"; goto error1; }
  1161 
  1161 
  1169 
  1169 
  1170 	if (!_wininet.HttpSendRequest(http, "Content-type: application/binary", -1, msg, msglen)) { err = "httpsendrequest failed"; goto error4; }
  1170 	if (!_wininet.HttpSendRequest(http, "Content-type: application/binary", -1, msg, msglen)) { err = "httpsendrequest failed"; goto error4; }
  1171 
  1171 
  1172 	len = sizeof(code);
  1172 	len = sizeof(code);
  1173 	if (!_wininet.HttpQueryInfo(http, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &code, &len, 0)) { err = "httpqueryinfo failed"; goto error4; }
  1173 	if (!_wininet.HttpQueryInfo(http, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &code, &len, 0)) { err = "httpqueryinfo failed"; goto error4; }
  1174 	
  1174 
  1175 	if (code != 200) {
  1175 	if (code != 200) {
  1176 		int l = sprintf(buf, "Server said: %d ", code);
  1176 		int l = sprintf(buf, "Server said: %d ", code);
  1177 		len = sizeof(buf) - l;
  1177 		len = sizeof(buf) - l;
  1178 		_wininet.HttpQueryInfo(http, HTTP_QUERY_STATUS_TEXT, buf + l, &len, 0);
  1178 		_wininet.HttpQueryInfo(http, HTTP_QUERY_STATUS_TEXT, buf + l, &len, 0);
  1179 		err = buf;
  1179 		err = buf;
  1199 	h = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  1199 	h = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  1200 	if (h == NULL) return;
  1200 	if (h == NULL) return;
  1201 
  1201 
  1202 	size = GetFileSize(h, NULL);
  1202 	size = GetFileSize(h, NULL);
  1203 	if (size > 500000) goto error1;
  1203 	if (size > 500000) goto error1;
  1204 	
  1204 
  1205 	mem = malloc(size);
  1205 	mem = malloc(size);
  1206 	if (mem == NULL) goto error1;
  1206 	if (mem == NULL) goto error1;
  1207 
  1207 
  1208 	if (!ReadFile(h, mem, size, &read, NULL) || read != size) goto error2;
  1208 	if (!ReadFile(h, mem, size, &read, NULL) || read != size) goto error2;
  1209 
  1209 
  1210 	SubmitCrashReport(wnd, mem, size, file);		
  1210 	SubmitCrashReport(wnd, mem, size, file);
  1211 
  1211 
  1212 error2:
  1212 error2:
  1213 	free(mem);
  1213 	free(mem);
  1214 error1:
  1214 error1:
  1215 	CloseHandle(h);
  1215 	CloseHandle(h);
  1221 {
  1221 {
  1222 	RECT r,r2;
  1222 	RECT r,r2;
  1223 	int offs;
  1223 	int offs;
  1224 
  1224 
  1225 	GetWindowRect(wnd, &r);
  1225 	GetWindowRect(wnd, &r);
  1226 	
  1226 
  1227 	SetDlgItemText(wnd, 15, _expand_texts[mode == 1]);
  1227 	SetDlgItemText(wnd, 15, _expand_texts[mode == 1]);
  1228 	
  1228 
  1229 	if (mode >= 0) {
  1229 	if (mode >= 0) {
  1230 		GetWindowRect(GetDlgItem(wnd, 11), &r2);
  1230 		GetWindowRect(GetDlgItem(wnd, 11), &r2);
  1231 		offs = r2.bottom - r2.top + 10;
  1231 		offs = r2.bottom - r2.top + 10;
  1232 		if (!mode) offs=-offs;
  1232 		if (!mode) offs=-offs;
  1233 		SetWindowPos(wnd, HWND_TOPMOST, 0, 0, r.right - r.left, r.bottom - r.top + offs, SWP_NOMOVE | SWP_NOZORDER);
  1233 		SetWindowPos(wnd, HWND_TOPMOST, 0, 0, r.right - r.left, r.bottom - r.top + offs, SWP_NOMOVE | SWP_NOZORDER);
  1234 	} else {
  1234 	} else {
  1235 		SetWindowPos(wnd, HWND_TOPMOST, 
  1235 		SetWindowPos(wnd, HWND_TOPMOST,
  1236 			(GetSystemMetrics(SM_CXSCREEN) - (r.right - r.left)) >> 1,
  1236 			(GetSystemMetrics(SM_CXSCREEN) - (r.right - r.left)) >> 1,
  1237 			(GetSystemMetrics(SM_CYSCREEN) - (r.bottom - r.top)) >> 1,
  1237 			(GetSystemMetrics(SM_CYSCREEN) - (r.bottom - r.top)) >> 1,
  1238 			0, 0, SWP_NOSIZE);
  1238 			0, 0, SWP_NOSIZE);
  1239 	}
  1239 	}
  1240 }
  1240 }
  1271 				MessageBoxA(wnd, "Save failed", "Save failed", MB_ICONINFORMATION);
  1271 				MessageBoxA(wnd, "Save failed", "Save failed", MB_ICONINFORMATION);
  1272 			break;
  1272 			break;
  1273 		}
  1273 		}
  1274 		case 14: { // Submit crash report
  1274 		case 14: { // Submit crash report
  1275 			char *s;
  1275 			char *s;
  1276 			
  1276 
  1277 			SetCursor(LoadCursor(NULL, IDC_WAIT));
  1277 			SetCursor(LoadCursor(NULL, IDC_WAIT));
  1278 
  1278 
  1279 			s = SubmitCrashReport(wnd, _crash_msg, strlen(_crash_msg), "");
  1279 			s = SubmitCrashReport(wnd, _crash_msg, strlen(_crash_msg), "");
  1280 			if (s) {
  1280 			if (s) {
  1281 				MessageBoxA(wnd, s, "Error", MB_ICONSTOP);
  1281 				MessageBoxA(wnd, s, "Error", MB_ICONSTOP);
  1282 				break;
  1282 				break;
  1283 			}
  1283 			}
  1284 			
  1284 
  1285 			// try to submit emergency savegame
  1285 			// try to submit emergency savegame
  1286 			if (_did_emerg_save || DoEmergencySave(wnd)) {
  1286 			if (_did_emerg_save || DoEmergencySave(wnd)) {
  1287 				SubmitFile(wnd, "crash.sav");
  1287 				SubmitFile(wnd, "crash.sav");
  1288 			}
  1288 			}
  1289 			// try to submit the autosaved game
  1289 			// try to submit the autosaved game
  1322 	char *output;
  1322 	char *output;
  1323 	static bool had_exception;
  1323 	static bool had_exception;
  1324 
  1324 
  1325 	if (had_exception) { ExitProcess(0); }
  1325 	if (had_exception) { ExitProcess(0); }
  1326 	had_exception = true;
  1326 	had_exception = true;
  1327 	
  1327 
  1328 	_ident = GetTickCount(); // something pretty unique
  1328 	_ident = GetTickCount(); // something pretty unique
  1329 
  1329 
  1330 	MakeCRCTable(alloca(256 * sizeof(uint32)));
  1330 	MakeCRCTable(alloca(256 * sizeof(uint32)));
  1331 	_crash_msg = output = LocalAlloc(LMEM_FIXED, 8192);
  1331 	_crash_msg = output = LocalAlloc(LMEM_FIXED, 8192);
  1332 
  1332 
  1333 	{
  1333 	{
  1334 		SYSTEMTIME time;
  1334 		SYSTEMTIME time;
  1335 		GetLocalTime(&time);
  1335 		GetLocalTime(&time);
  1336 		output += sprintf(output, 
  1336 		output += sprintf(output,
  1337 			"*** OpenTTD Crash Report ***\r\n"
  1337 			"*** OpenTTD Crash Report ***\r\n"
  1338 			"Date: %d-%.2d-%.2d %.2d:%.2d:%.2d\r\n"
  1338 			"Date: %d-%.2d-%.2d %.2d:%.2d:%.2d\r\n"
  1339 			"Build: %s built on " __TIMESTAMP__ "\r\n",
  1339 			"Build: %s built on " __TIMESTAMP__ "\r\n",
  1340 			time.wYear,
  1340 			time.wYear,
  1341 			time.wMonth,
  1341 			time.wMonth,
  1434 static void Win32InitializeExceptions()
  1434 static void Win32InitializeExceptions()
  1435 {
  1435 {
  1436 	_asm {
  1436 	_asm {
  1437 		mov _safe_esp,esp
  1437 		mov _safe_esp,esp
  1438 	}
  1438 	}
  1439 	
  1439 
  1440 	SetUnhandledExceptionFilter(ExceptionHandler);
  1440 	SetUnhandledExceptionFilter(ExceptionHandler);
  1441 }
  1441 }
  1442 #endif
  1442 #endif
  1443 
  1443 
  1444 static char *_fios_path;
  1444 static char *_fios_path;
  1457 }
  1457 }
  1458 
  1458 
  1459 static HANDLE MyFindFirstFile(char *path, char *file, WIN32_FIND_DATA *fd)
  1459 static HANDLE MyFindFirstFile(char *path, char *file, WIN32_FIND_DATA *fd)
  1460 {
  1460 {
  1461 	char paths[MAX_PATH];
  1461 	char paths[MAX_PATH];
  1462 	
  1462 
  1463 	sprintf(paths, "%s\\%s", path, file);
  1463 	sprintf(paths, "%s\\%s", path, file);
  1464 	return FindFirstFile(paths, fd);
  1464 	return FindFirstFile(paths, fd);
  1465 }
  1465 }
  1466 
  1466 
  1467 int CDECL compare_FiosItems (const void *a, const void *b) {
  1467 int CDECL compare_FiosItems (const void *a, const void *b) {
  1469 	const FiosItem *db = (const FiosItem *) b;
  1469 	const FiosItem *db = (const FiosItem *) b;
  1470 	int r;
  1470 	int r;
  1471 
  1471 
  1472 	if (_savegame_sort_order < 2) // sort by date
  1472 	if (_savegame_sort_order < 2) // sort by date
  1473     r = da->mtime < db->mtime ? -1 : 1;
  1473     r = da->mtime < db->mtime ? -1 : 1;
  1474 	else	
  1474 	else
  1475 		r = stricmp(da->title[0] ? da->title : da->name, db->title[0] ? db->title : db->name);
  1475 		r = stricmp(da->title[0] ? da->title : da->name, db->title[0] ? db->title : db->name);
  1476 
  1476 
  1477 	if (_savegame_sort_order & 1) r = -r;
  1477 	if (_savegame_sort_order & 1) r = -r;
  1478 	return r;
  1478 	return r;
  1479 }
  1479 }
  1501 	if (_fios_path[3] != 0) {
  1501 	if (_fios_path[3] != 0) {
  1502 		fios = FiosAlloc();
  1502 		fios = FiosAlloc();
  1503 		fios->type = FIOS_TYPE_PARENT;
  1503 		fios->type = FIOS_TYPE_PARENT;
  1504 		strcpy(fios->title, ".. (Parent directory)");
  1504 		strcpy(fios->title, ".. (Parent directory)");
  1505 	}
  1505 	}
  1506 	
  1506 
  1507 
  1507 
  1508 	// Show subdirectories first
  1508 	// Show subdirectories first
  1509 	h = MyFindFirstFile(_fios_path, "*.*", &fd);
  1509 	h = MyFindFirstFile(_fios_path, "*.*", &fd);
  1510 	if (h != INVALID_HANDLE_VALUE) {
  1510 	if (h != INVALID_HANDLE_VALUE) {
  1511 		do {
  1511 		do {
  1693 
  1693 
  1694 	switch(item->type) {
  1694 	switch(item->type) {
  1695 	case FIOS_TYPE_DRIVE:
  1695 	case FIOS_TYPE_DRIVE:
  1696 		sprintf(path, "%c:\\", item->title[0]);
  1696 		sprintf(path, "%c:\\", item->title[0]);
  1697 		break;
  1697 		break;
  1698 	
  1698 
  1699 	case FIOS_TYPE_PARENT:
  1699 	case FIOS_TYPE_PARENT:
  1700 		// Skip drive part
  1700 		// Skip drive part
  1701 		path += 3;
  1701 		path += 3;
  1702 		s = path;
  1702 		s = path;
  1703 		while (*path) {
  1703 		while (*path) {
  1711 	case FIOS_TYPE_DIR:
  1711 	case FIOS_TYPE_DIR:
  1712 		// Scan to end
  1712 		// Scan to end
  1713 		while (*++path);
  1713 		while (*++path);
  1714 		// Add backslash?
  1714 		// Add backslash?
  1715 		if (path[-1] != '\\') *path++ = '\\';
  1715 		if (path[-1] != '\\') *path++ = '\\';
  1716 		
  1716 
  1717 		strcpy(path, item->name);
  1717 		strcpy(path, item->name);
  1718 		break;
  1718 		break;
  1719 
  1719 
  1720 	case FIOS_TYPE_FILE:
  1720 	case FIOS_TYPE_FILE:
  1721 		FiosMakeSavegameName(str_buffr, item->name);
  1721 		FiosMakeSavegameName(str_buffr, item->name);
  1750 	root[2] = '\\';
  1750 	root[2] = '\\';
  1751 	root[3] = 0;
  1751 	root[3] = 0;
  1752 	if (GetDiskFreeSpace(root, &spc, &bps, &nfc, &tnc)) {
  1752 	if (GetDiskFreeSpace(root, &spc, &bps, &nfc, &tnc)) {
  1753 		uint32 tot = ((spc*bps)*(uint64)nfc) >> 20;
  1753 		uint32 tot = ((spc*bps)*(uint64)nfc) >> 20;
  1754 		SET_DPARAM32(0, tot);
  1754 		SET_DPARAM32(0, tot);
  1755 		return STR_4005_BYTES_FREE; 
  1755 		return STR_4005_BYTES_FREE;
  1756 	} else {
  1756 	} else {
  1757 		return STR_4006_UNABLE_TO_READ_DRIVE;
  1757 		return STR_4006_UNABLE_TO_READ_DRIVE;
  1758 	}
  1758 	}
  1759 }
  1759 }
  1760 
  1760 
  1846 			line++;
  1846 			line++;
  1847 
  1847 
  1848 		// end?
  1848 		// end?
  1849 		if (*line == 0)
  1849 		if (*line == 0)
  1850 			break;
  1850 			break;
  1851 		
  1851 
  1852 		// special handling when quoted
  1852 		// special handling when quoted
  1853 		if (*line == '"') {
  1853 		if (*line == '"') {
  1854 			argv[n++] = ++line;
  1854 			argv[n++] = ++line;
  1855 			while (*line != '"') {
  1855 			while (*line != '"') {
  1856 				if (*line == 0) return n;
  1856 				if (*line == 0) return n;
  1861 			while (*line != ' ' && *line != '\t') {
  1861 			while (*line != ' ' && *line != '\t') {
  1862 				if (*line == 0) return n;
  1862 				if (*line == 0) return n;
  1863 				line++;
  1863 				line++;
  1864 			}
  1864 			}
  1865 		}
  1865 		}
  1866 		*line++ = 0;	
  1866 		*line++ = 0;
  1867 	} while (n != max_argc);
  1867 	} while (n != max_argc);
  1868 
  1868 
  1869 	return n;
  1869 	return n;
  1870 }
  1870 }
  1871 
  1871 
  1888 	if (_has_console) return;
  1888 	if (_has_console) return;
  1889 
  1889 
  1890 	_has_console = true;
  1890 	_has_console = true;
  1891 
  1891 
  1892 	AllocConsole();
  1892 	AllocConsole();
  1893 	
  1893 
  1894 	hand = GetStdHandle(STD_OUTPUT_HANDLE);
  1894 	hand = GetStdHandle(STD_OUTPUT_HANDLE);
  1895 	GetConsoleScreenBufferInfo(hand, &coninfo);
  1895 	GetConsoleScreenBufferInfo(hand, &coninfo);
  1896 	coninfo.dwSize.Y = 500;
  1896 	coninfo.dwSize.Y = 500;
  1897 	SetConsoleScreenBufferSize(hand, coninfo.dwSize);
  1897 	SetConsoleScreenBufferSize(hand, coninfo.dwSize);
  1898     
  1898 
  1899 	// redirect unbuffered STDIN, STDOUT, STDERR to the console
  1899 	// redirect unbuffered STDIN, STDOUT, STDERR to the console
  1900 #if !defined(__CYGWIN__)
  1900 #if !defined(__CYGWIN__)
  1901 	*stdout = *_fdopen( _open_osfhandle((long)hand, _O_TEXT), "w" );
  1901 	*stdout = *_fdopen( _open_osfhandle((long)hand, _O_TEXT), "w" );
  1902 	*stdin = *_fdopen(_open_osfhandle((long)GetStdHandle(STD_INPUT_HANDLE), _O_TEXT), "w" );
  1902 	*stdin = *_fdopen(_open_osfhandle((long)GetStdHandle(STD_INPUT_HANDLE), _O_TEXT), "w" );
  1903 	*stderr = *_fdopen(_open_osfhandle((long)GetStdHandle(STD_ERROR_HANDLE), _O_TEXT), "w" );
  1903 	*stderr = *_fdopen(_open_osfhandle((long)GetStdHandle(STD_ERROR_HANDLE), _O_TEXT), "w" );
  1904 #else
  1904 #else
  1905 	// open_osfhandle is not in cygwin
  1905 	// open_osfhandle is not in cygwin
  1906 	*stdout = *fdopen(1, "w" );
  1906 	*stdout = *fdopen(1, "w" );
  1907 	*stdin = *fdopen(0, "w" );
  1907 	*stdin = *fdopen(0, "w" );
  1908 	*stderr = *fdopen(2, "w" );    
  1908 	*stderr = *fdopen(2, "w" );
  1909 #endif
  1909 #endif
  1910     
  1910 
  1911 	setvbuf( stdin, NULL, _IONBF, 0 );    
  1911 	setvbuf( stdin, NULL, _IONBF, 0 );
  1912 	setvbuf( stdout, NULL, _IONBF, 0 );    
  1912 	setvbuf( stdout, NULL, _IONBF, 0 );
  1913 	setvbuf( stderr, NULL, _IONBF, 0 );
  1913 	setvbuf( stderr, NULL, _IONBF, 0 );
  1914 }
  1914 }
  1915 
  1915 
  1916 void ShowInfo(const char *str)
  1916 void ShowInfo(const char *str)
  1917 {
  1917 {
  1918 	if (_has_console)
  1918 	if (_has_console)
  1919 		puts(str);
  1919 		puts(str);
  1920 	else {
  1920 	else {
  1921 		bool old;
  1921 		bool old;
  1922 		
  1922 
  1923 		ReleaseCapture();
  1923 		ReleaseCapture();
  1924 		_left_button_clicked =_left_button_down = false;
  1924 		_left_button_clicked =_left_button_down = false;
  1925 		
  1925 
  1926 		old = MyShowCursor(true);
  1926 		old = MyShowCursor(true);
  1927 		if (MessageBoxA(GetActiveWindow(), str, "OpenTTD", MB_ICONINFORMATION | MB_OKCANCEL) == IDCANCEL) {
  1927 		if (MessageBoxA(GetActiveWindow(), str, "OpenTTD", MB_ICONINFORMATION | MB_OKCANCEL) == IDCANCEL) {
  1928 			CreateConsole();
  1928 			CreateConsole();
  1929 		}
  1929 		}
  1930 		MyShowCursor(old);
  1930 		MyShowCursor(old);
  1958 #endif
  1958 #endif
  1959 
  1959 
  1960 	argc = ParseCommandLine(GetCommandLine(), argv, lengthof(argv));
  1960 	argc = ParseCommandLine(GetCommandLine(), argv, lengthof(argv));
  1961 
  1961 
  1962 #if defined(WIN32_EXCEPTION_TRACKER)
  1962 #if defined(WIN32_EXCEPTION_TRACKER)
  1963 	{	
  1963 	{
  1964 		Win32InitializeExceptions();
  1964 		Win32InitializeExceptions();
  1965 	}
  1965 	}
  1966 #endif
  1966 #endif
  1967 
  1967 
  1968 #if defined(WIN32_EXCEPTION_TRACKER_DEBUG)
  1968 #if defined(WIN32_EXCEPTION_TRACKER_DEBUG)
  1983 	char *s;
  1983 	char *s;
  1984 	char *cfg;
  1984 	char *cfg;
  1985 
  1985 
  1986 	_path.personal_dir = _path.game_data_dir = cfg = malloc(MAX_PATH);
  1986 	_path.personal_dir = _path.game_data_dir = cfg = malloc(MAX_PATH);
  1987 	GetCurrentDirectory(MAX_PATH - 1, cfg);
  1987 	GetCurrentDirectory(MAX_PATH - 1, cfg);
  1988 	
  1988 
  1989 
  1989 
  1990 	s = strchr(cfg, 0);
  1990 	s = strchr(cfg, 0);
  1991 	if (s[-1] != '\\') { s[0] = '\\'; s[1] = 0; }
  1991 	if (s[-1] != '\\') { s[0] = '\\'; s[1] = 0; }
  1992 
  1992 
  1993 	_path.save_dir = str_fmt("%ssave", cfg);
  1993 	_path.save_dir = str_fmt("%ssave", cfg);