author | darkvater |
Thu, 23 Sep 2004 21:14:20 +0000 | |
changeset 306 | c44133836566 |
parent 298 | b3e83b94be19 |
child 318 | 65ebd0cab39b |
permissions | -rw-r--r-- |
0 | 1 |
#include "stdafx.h" |
2 |
#include "ttd.h" |
|
3 |
#include "gfx.h" |
|
4 |
#include "sound.h" |
|
5 |
#include "window.h" |
|
6 |
#include <windows.h> |
|
7 |
#include <mmsystem.h> |
|
8 |
#include "hal.h" |
|
9 |
#include <winnt.h> |
|
10 |
#include <wininet.h> |
|
11 |
#include <io.h> |
|
12 |
#include <fcntl.h> |
|
13 |
||
14 |
#define SMART_PALETTE_ANIM |
|
15 |
||
16 |
static struct { |
|
17 |
HWND main_wnd; |
|
18 |
HBITMAP dib_sect; |
|
19 |
void *bitmap_bits; |
|
20 |
void *buffer_bits; |
|
21 |
void *alloced_bits; |
|
22 |
HPALETTE gdi_palette; |
|
23 |
int width,height; |
|
24 |
int width_org, height_org; |
|
25 |
bool cursor_visible; |
|
26 |
bool switch_driver; |
|
27 |
bool fullscreen; |
|
28 |
bool double_size; |
|
29 |
bool has_focus; |
|
30 |
bool running; |
|
31 |
} _wnd; |
|
32 |
||
33 |
static HINSTANCE _inst; |
|
34 |
static bool _has_console; |
|
35 |
||
36 |
#if defined(MINGW32) || defined(__CYGWIN__) |
|
37 |
#define __TIMESTAMP__ __DATE__ __TIME__ |
|
38 |
#endif |
|
39 |
||
40 |
#ifdef WIN32_ENABLE_DIRECTMUSIC_SUPPORT |
|
41 |
extern const HalMusicDriver _dmusic_midi_driver; |
|
42 |
#endif |
|
43 |
||
44 |
static void MakePalette() |
|
45 |
{ |
|
46 |
LOGPALETTE *pal; |
|
47 |
int i; |
|
48 |
byte *b; |
|
49 |
||
50 |
pal = alloca(sizeof(LOGPALETTE) + (256-1) * sizeof(PALETTEENTRY)); |
|
51 |
||
52 |
pal->palVersion = 0x300; |
|
53 |
pal->palNumEntries = 256; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
54 |
|
0 | 55 |
for(i=0,b=_cur_palette; i!=256;i++,b+=3) { |
56 |
pal->palPalEntry[i].peRed = b[0]; |
|
57 |
pal->palPalEntry[i].peGreen = b[1]; |
|
58 |
pal->palPalEntry[i].peBlue = b[2]; |
|
59 |
pal->palPalEntry[i].peFlags = 0; |
|
60 |
||
61 |
} |
|
62 |
_wnd.gdi_palette = CreatePalette(pal); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
63 |
if (_wnd.gdi_palette == NULL) |
0 | 64 |
error("CreatePalette failed!\n"); |
65 |
} |
|
66 |
||
67 |
static void UpdatePalette(HDC dc, uint start, uint count) |
|
68 |
{ |
|
69 |
RGBQUAD rgb[256]; |
|
70 |
uint i; |
|
71 |
byte *b; |
|
72 |
||
73 |
for(i=0,b = _cur_palette + start*3; i!=count; i++,b+=3) { |
|
74 |
rgb[i].rgbRed = b[0]; |
|
75 |
rgb[i].rgbGreen = b[1]; |
|
76 |
rgb[i].rgbBlue = b[2]; |
|
77 |
rgb[i].rgbReserved = 0; |
|
78 |
} |
|
79 |
||
80 |
SetDIBColorTable(dc, start, count, rgb); |
|
81 |
} |
|
82 |
||
83 |
static bool MyShowCursor(bool show) |
|
84 |
{ |
|
85 |
if (_wnd.cursor_visible == show) |
|
86 |
return show; |
|
87 |
||
88 |
_wnd.cursor_visible = show; |
|
89 |
ShowCursor(show); |
|
90 |
||
91 |
return !show; |
|
92 |
} |
|
93 |
||
94 |
typedef struct { |
|
95 |
byte vk_from; |
|
96 |
byte vk_count; |
|
97 |
byte map_to; |
|
98 |
} VkMapping; |
|
99 |
||
100 |
#define AS(x,z) {x,0,z} |
|
101 |
#define AM(x,y,z,w) {x,y-x,z} |
|
102 |
||
153
3dbe2cfd7b3c
(svn r154) -Fix: some people while using MSVC don't have VK_OEM_3 defined? Or it could be Win2000/XP only
darkvater
parents:
151
diff
changeset
|
103 |
#ifndef VK_OEM_3 |
3dbe2cfd7b3c
(svn r154) -Fix: some people while using MSVC don't have VK_OEM_3 defined? Or it could be Win2000/XP only
darkvater
parents:
151
diff
changeset
|
104 |
#define VK_OEM_3 0xC0 |
3dbe2cfd7b3c
(svn r154) -Fix: some people while using MSVC don't have VK_OEM_3 defined? Or it could be Win2000/XP only
darkvater
parents:
151
diff
changeset
|
105 |
#endif |
3dbe2cfd7b3c
(svn r154) -Fix: some people while using MSVC don't have VK_OEM_3 defined? Or it could be Win2000/XP only
darkvater
parents:
151
diff
changeset
|
106 |
|
0 | 107 |
static const VkMapping _vk_mapping[] = { |
108 |
// Pageup stuff + up/down |
|
109 |
AM(VK_PRIOR,VK_DOWN, WKC_PAGEUP, WKC_DOWN), |
|
110 |
// Map letters & digits |
|
111 |
AM('A','Z','A','Z'), |
|
112 |
AM('0','9','0','9'), |
|
113 |
||
151
e90bf7f77216
(svn r152) -Fix: [1021061] windows WKC_BACKQUOTE [US] (sign_de)
darkvater
parents:
135
diff
changeset
|
114 |
AS(VK_OEM_3, WKC_BACKQUOTE), |
135
638fb31434eb
(svn r136) -Feature/Fix: Console Rev #2 and WKC_BACKQUOTE this patch adds new features to the ingame console and inserts a new keymanagement for windows pcs... (sign_de)
darkvater
parents:
49
diff
changeset
|
115 |
AS(220, WKC_BACKQUOTE), |
638fb31434eb
(svn r136) -Feature/Fix: Console Rev #2 and WKC_BACKQUOTE this patch adds new features to the ingame console and inserts a new keymanagement for windows pcs... (sign_de)
darkvater
parents:
49
diff
changeset
|
116 |
|
0 | 117 |
AS(VK_ESCAPE, WKC_ESC), |
118 |
AS(VK_BACK, WKC_BACKSPACE), |
|
119 |
AM(VK_INSERT,VK_DELETE,WKC_INSERT, WKC_DELETE), |
|
120 |
||
121 |
AS(VK_SPACE, WKC_SPACE), |
|
122 |
AS(VK_RETURN, WKC_RETURN), |
|
123 |
AS(VK_TAB, WKC_TAB), |
|
124 |
||
125 |
// Function keys |
|
126 |
AM(VK_F1, VK_F12, WKC_F1, WKC_F12), |
|
127 |
||
128 |
// Numeric part. |
|
129 |
// What is the virtual keycode for numeric enter?? |
|
130 |
AM(VK_NUMPAD0,VK_NUMPAD9, WKC_NUM_0, WKC_NUM_9), |
|
131 |
AS(VK_DIVIDE, WKC_NUM_DIV), |
|
132 |
AS(VK_MULTIPLY, WKC_NUM_MUL), |
|
133 |
AS(VK_SUBTRACT, WKC_NUM_MINUS), |
|
134 |
AS(VK_ADD, WKC_NUM_PLUS), |
|
135 |
AS(VK_DECIMAL, WKC_NUM_DECIMAL), |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
136 |
{0} |
0 | 137 |
}; |
138 |
||
139 |
static uint MapWindowsKey(uint key) |
|
140 |
{ |
|
141 |
const VkMapping *map = _vk_mapping - 1; |
|
142 |
uint from; |
|
143 |
do { |
|
144 |
map++; |
|
145 |
from = map->vk_from; |
|
135
638fb31434eb
(svn r136) -Feature/Fix: Console Rev #2 and WKC_BACKQUOTE this patch adds new features to the ingame console and inserts a new keymanagement for windows pcs... (sign_de)
darkvater
parents:
49
diff
changeset
|
146 |
if (from == 0) { |
638fb31434eb
(svn r136) -Feature/Fix: Console Rev #2 and WKC_BACKQUOTE this patch adds new features to the ingame console and inserts a new keymanagement for windows pcs... (sign_de)
darkvater
parents:
49
diff
changeset
|
147 |
return 0; // Unknown key pressed. |
638fb31434eb
(svn r136) -Feature/Fix: Console Rev #2 and WKC_BACKQUOTE this patch adds new features to the ingame console and inserts a new keymanagement for windows pcs... (sign_de)
darkvater
parents:
49
diff
changeset
|
148 |
} |
0 | 149 |
} while ((uint)(key - from) > map->vk_count); |
150 |
||
151 |
key = key - from + map->map_to; |
|
135
638fb31434eb
(svn r136) -Feature/Fix: Console Rev #2 and WKC_BACKQUOTE this patch adds new features to the ingame console and inserts a new keymanagement for windows pcs... (sign_de)
darkvater
parents:
49
diff
changeset
|
152 |
|
0 | 153 |
if (GetAsyncKeyState(VK_SHIFT)<0) key |= WKC_SHIFT; |
154 |
if (GetAsyncKeyState(VK_CONTROL)<0) key |= WKC_CTRL; |
|
155 |
if (GetAsyncKeyState(VK_MENU)<0) key |= WKC_ALT; |
|
156 |
return key; |
|
157 |
} |
|
158 |
||
159 |
static void MakeWindow(bool full_screen); |
|
160 |
static bool AllocateDibSection(int w, int h); |
|
161 |
||
162 |
static void ClientSizeChanged(int w, int h) |
|
163 |
{ |
|
164 |
if (_wnd.double_size) { w >>= 1; h >>= 1; } |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
165 |
|
0 | 166 |
// allocate new dib section of the new size |
167 |
if (AllocateDibSection(w, h)) { |
|
168 |
// mark all palette colors dirty |
|
169 |
_pal_first_dirty = 0; |
|
170 |
_pal_last_dirty = 255; |
|
171 |
GameSizeChanged(); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
172 |
|
0 | 173 |
// redraw screen |
174 |
if (_wnd.running) { |
|
175 |
_screen.dst_ptr = _wnd.buffer_bits; |
|
176 |
UpdateWindows(); |
|
177 |
} |
|
178 |
} |
|
179 |
} |
|
180 |
||
181 |
static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) |
|
182 |
{ |
|
183 |
switch(msg) { |
|
184 |
case WM_PAINT: { |
|
185 |
PAINTSTRUCT ps; |
|
186 |
HDC dc,dc2; |
|
187 |
HBITMAP old_bmp; |
|
188 |
HPALETTE old_palette; |
|
189 |
BeginPaint(hwnd, &ps); |
|
190 |
dc = ps.hdc; |
|
191 |
dc2 = CreateCompatibleDC(dc); |
|
192 |
old_bmp = SelectObject(dc2, _wnd.dib_sect); |
|
193 |
old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
194 |
|
0 | 195 |
if (_pal_last_dirty != -1) { |
196 |
UpdatePalette(dc2, _pal_first_dirty, _pal_last_dirty - _pal_first_dirty + 1); |
|
197 |
_pal_last_dirty = -1; |
|
198 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
199 |
|
0 | 200 |
BitBlt(dc, 0, 0, _wnd.width, _wnd.height, dc2, 0, 0, SRCCOPY); |
201 |
SelectPalette(dc, old_palette, TRUE); |
|
202 |
SelectObject(dc2, old_bmp); |
|
203 |
DeleteDC(dc2); |
|
204 |
EndPaint(hwnd, &ps); |
|
205 |
} |
|
206 |
return 0; |
|
207 |
||
208 |
case WM_PALETTECHANGED: |
|
209 |
if ((HWND)wParam == hwnd) |
|
210 |
return 0; |
|
211 |
// FALL THROUGH |
|
212 |
case WM_QUERYNEWPALETTE: { |
|
213 |
HDC hDC = GetWindowDC(hwnd); |
|
214 |
HPALETTE hOldPalette = SelectPalette(hDC, _wnd.gdi_palette, FALSE); |
|
215 |
UINT nChanged = RealizePalette(hDC); |
|
216 |
SelectPalette(hDC, hOldPalette, TRUE); |
|
217 |
ReleaseDC(hwnd, hDC); |
|
218 |
if (nChanged) |
|
219 |
InvalidateRect(hwnd, NULL, FALSE); |
|
220 |
return 0; |
|
221 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
222 |
|
0 | 223 |
case WM_CLOSE: |
224 |
AskExitGame(); |
|
225 |
return 0; |
|
226 |
||
227 |
case WM_LBUTTONDOWN: |
|
228 |
SetCapture(hwnd); |
|
229 |
_left_button_down = true; |
|
230 |
return 0; |
|
231 |
||
232 |
case WM_LBUTTONUP: |
|
233 |
ReleaseCapture(); |
|
234 |
_left_button_down = false; |
|
235 |
_left_button_clicked = false; |
|
236 |
return 0; |
|
237 |
||
238 |
case WM_RBUTTONDOWN: |
|
239 |
SetCapture(hwnd); |
|
240 |
_right_button_down = true; |
|
241 |
_right_button_clicked = true; |
|
242 |
return 0; |
|
243 |
||
244 |
case WM_RBUTTONUP: |
|
245 |
ReleaseCapture(); |
|
246 |
_right_button_down = false; |
|
247 |
return 0; |
|
248 |
||
249 |
case WM_MOUSEMOVE: { |
|
250 |
int x = (int16)LOWORD(lParam); |
|
251 |
int y = (int16)HIWORD(lParam); |
|
252 |
POINT pt; |
|
253 |
||
254 |
if (_wnd.double_size) { |
|
255 |
x >>= 1; |
|
256 |
y >>= 1; |
|
257 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
258 |
|
0 | 259 |
if (_cursor.fix_at) { |
260 |
int dx = x - _cursor.pos.x; |
|
261 |
int dy = y - _cursor.pos.y; |
|
262 |
if (dx != 0 || dy != 0) { |
|
263 |
_cursor.delta.x += dx; |
|
264 |
_cursor.delta.y += dy; |
|
265 |
||
266 |
pt.x = _cursor.pos.x; |
|
267 |
pt.y = _cursor.pos.y; |
|
268 |
||
269 |
if (_wnd.double_size) { |
|
270 |
pt.x *= 2; |
|
271 |
pt.y *= 2; |
|
272 |
} |
|
273 |
ClientToScreen(hwnd, &pt); |
|
274 |
SetCursorPos(pt.x, pt.y); |
|
275 |
} |
|
276 |
} else { |
|
277 |
_cursor.delta.x += x - _cursor.pos.x; |
|
278 |
_cursor.delta.y += y - _cursor.pos.y; |
|
279 |
_cursor.pos.x = x; |
|
280 |
_cursor.pos.y = y; |
|
281 |
_cursor.dirty = true; |
|
282 |
} |
|
283 |
MyShowCursor(false); |
|
284 |
return 0; |
|
285 |
} |
|
286 |
||
287 |
case WM_KEYDOWN: |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
288 |
{ |
135
638fb31434eb
(svn r136) -Feature/Fix: Console Rev #2 and WKC_BACKQUOTE this patch adds new features to the ingame console and inserts a new keymanagement for windows pcs... (sign_de)
darkvater
parents:
49
diff
changeset
|
289 |
// this is the rewritten ascii input function |
638fb31434eb
(svn r136) -Feature/Fix: Console Rev #2 and WKC_BACKQUOTE this patch adds new features to the ingame console and inserts a new keymanagement for windows pcs... (sign_de)
darkvater
parents:
49
diff
changeset
|
290 |
// it disables windows deadkey handling --> more linux like :D |
638fb31434eb
(svn r136) -Feature/Fix: Console Rev #2 and WKC_BACKQUOTE this patch adds new features to the ingame console and inserts a new keymanagement for windows pcs... (sign_de)
darkvater
parents:
49
diff
changeset
|
291 |
unsigned short w = 0; |
638fb31434eb
(svn r136) -Feature/Fix: Console Rev #2 and WKC_BACKQUOTE this patch adds new features to the ingame console and inserts a new keymanagement for windows pcs... (sign_de)
darkvater
parents:
49
diff
changeset
|
292 |
int r = 0; |
638fb31434eb
(svn r136) -Feature/Fix: Console Rev #2 and WKC_BACKQUOTE this patch adds new features to the ingame console and inserts a new keymanagement for windows pcs... (sign_de)
darkvater
parents:
49
diff
changeset
|
293 |
byte ks[256]; |
638fb31434eb
(svn r136) -Feature/Fix: Console Rev #2 and WKC_BACKQUOTE this patch adds new features to the ingame console and inserts a new keymanagement for windows pcs... (sign_de)
darkvater
parents:
49
diff
changeset
|
294 |
unsigned int scan=0; |
638fb31434eb
(svn r136) -Feature/Fix: Console Rev #2 and WKC_BACKQUOTE this patch adds new features to the ingame console and inserts a new keymanagement for windows pcs... (sign_de)
darkvater
parents:
49
diff
changeset
|
295 |
GetKeyboardState(ks); |
638fb31434eb
(svn r136) -Feature/Fix: Console Rev #2 and WKC_BACKQUOTE this patch adds new features to the ingame console and inserts a new keymanagement for windows pcs... (sign_de)
darkvater
parents:
49
diff
changeset
|
296 |
r=ToAscii(wParam,scan,ks,&w,0); |
638fb31434eb
(svn r136) -Feature/Fix: Console Rev #2 and WKC_BACKQUOTE this patch adds new features to the ingame console and inserts a new keymanagement for windows pcs... (sign_de)
darkvater
parents:
49
diff
changeset
|
297 |
if (r=0) w=0; |
638fb31434eb
(svn r136) -Feature/Fix: Console Rev #2 and WKC_BACKQUOTE this patch adds new features to the ingame console and inserts a new keymanagement for windows pcs... (sign_de)
darkvater
parents:
49
diff
changeset
|
298 |
|
638fb31434eb
(svn r136) -Feature/Fix: Console Rev #2 and WKC_BACKQUOTE this patch adds new features to the ingame console and inserts a new keymanagement for windows pcs... (sign_de)
darkvater
parents:
49
diff
changeset
|
299 |
_pressed_key = w | MapWindowsKey(wParam) << 16; |
638fb31434eb
(svn r136) -Feature/Fix: Console Rev #2 and WKC_BACKQUOTE this patch adds new features to the ingame console and inserts a new keymanagement for windows pcs... (sign_de)
darkvater
parents:
49
diff
changeset
|
300 |
} |
0 | 301 |
if ((_pressed_key>>16) == ('D' | WKC_CTRL) && !_wnd.fullscreen) { |
302 |
_double_size ^= 1; |
|
303 |
_wnd.double_size = _double_size; |
|
304 |
ClientSizeChanged(_wnd.width, _wnd.height); |
|
305 |
MarkWholeScreenDirty(); |
|
306 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
307 |
break; |
0 | 308 |
|
309 |
||
198
0f3481fa50e1
(svn r199) -Fix: [993374] Pressing alt locks the game - sort of a bug. I hope I didn't break anything :O
darkvater
parents:
196
diff
changeset
|
310 |
case WM_SYSKEYDOWN: /* user presses F10 or Alt, both activating the title-menu */ |
0 | 311 |
switch(wParam) { |
198
0f3481fa50e1
(svn r199) -Fix: [993374] Pressing alt locks the game - sort of a bug. I hope I didn't break anything :O
darkvater
parents:
196
diff
changeset
|
312 |
case VK_RETURN: /* Full Screen */ |
0 | 313 |
MakeWindow(!_wnd.fullscreen); |
314 |
return 0; |
|
199
10f6a586bfa6
(svn r200) -Fix: oops, ALT+F4 didn't work anymore. Fixed now.
darkvater
parents:
198
diff
changeset
|
315 |
case VK_MENU: /* Just ALT */ |
10f6a586bfa6
(svn r200) -Fix: oops, ALT+F4 didn't work anymore. Fixed now.
darkvater
parents:
198
diff
changeset
|
316 |
return 0; // do nothing |
10f6a586bfa6
(svn r200) -Fix: oops, ALT+F4 didn't work anymore. Fixed now.
darkvater
parents:
198
diff
changeset
|
317 |
default: /* ALT in combination with something else */ |
0 | 318 |
_pressed_key = MapWindowsKey(wParam) << 16; |
199
10f6a586bfa6
(svn r200) -Fix: oops, ALT+F4 didn't work anymore. Fixed now.
darkvater
parents:
198
diff
changeset
|
319 |
break; |
0 | 320 |
} |
321 |
break; |
|
322 |
case WM_NCMOUSEMOVE: |
|
323 |
MyShowCursor(true); |
|
324 |
return 0; |
|
325 |
||
326 |
case WM_SIZE: { |
|
327 |
if (wParam != SIZE_MINIMIZED) { |
|
328 |
ClientSizeChanged(LOWORD(lParam), HIWORD(lParam)); |
|
329 |
} |
|
330 |
return 0; |
|
331 |
} |
|
332 |
case WM_SIZING: { |
|
333 |
RECT* r = (RECT*)lParam; |
|
334 |
RECT r2; |
|
335 |
int w, h; |
|
336 |
||
337 |
SetRect(&r2, 0, 0, 0, 0); |
|
338 |
AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
339 |
|
0 | 340 |
w = r->right - r->left - (r2.right - r2.left); |
341 |
h = r->bottom - r->top - (r2.bottom - r2.top); |
|
342 |
if (_wnd.double_size) { w >>= 1; h >>= 1; } |
|
306
c44133836566
(svn r312) -Fix: [926105] ctrl + d bug. Longest outstanding bug has been fixed \o/ 2004-03-30 (Tron)
darkvater
parents:
298
diff
changeset
|
343 |
w = clamp(w, 64, MAX_SCREEN_WIDTH); |
c44133836566
(svn r312) -Fix: [926105] ctrl + d bug. Longest outstanding bug has been fixed \o/ 2004-03-30 (Tron)
darkvater
parents:
298
diff
changeset
|
344 |
h = clamp(h, 64, MAX_SCREEN_HEIGHT); |
0 | 345 |
if (_wnd.double_size) { w <<= 1; h <<= 1; } |
346 |
SetRect(&r2, 0, 0, w, h); |
|
347 |
||
348 |
AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE); |
|
349 |
w = r2.right - r2.left; |
|
350 |
h = r2.bottom - r2.top; |
|
351 |
||
352 |
switch (wParam) { |
|
353 |
case WMSZ_BOTTOM: |
|
354 |
r->bottom = r->top + h; |
|
355 |
break; |
|
356 |
case WMSZ_BOTTOMLEFT: |
|
357 |
r->bottom = r->top + h; |
|
358 |
r->left = r->right - w; |
|
359 |
break; |
|
360 |
case WMSZ_BOTTOMRIGHT: |
|
361 |
r->bottom = r->top + h; |
|
362 |
r->right = r->left + w; |
|
363 |
break; |
|
364 |
case WMSZ_LEFT: |
|
365 |
r->left = r->right - w; |
|
366 |
break; |
|
367 |
case WMSZ_RIGHT: |
|
368 |
r->right = r->left + w; |
|
369 |
break; |
|
370 |
case WMSZ_TOP: |
|
371 |
r->top = r->bottom - h; |
|
372 |
break; |
|
373 |
case WMSZ_TOPLEFT: |
|
374 |
r->top = r->bottom - h; |
|
375 |
r->left = r->right - w; |
|
376 |
break; |
|
377 |
case WMSZ_TOPRIGHT: |
|
378 |
r->top = r->bottom - h; |
|
379 |
r->right = r->left + w; |
|
380 |
break; |
|
381 |
} |
|
382 |
return TRUE; |
|
383 |
} |
|
384 |
||
385 |
// needed for wheel |
|
386 |
#if !defined(WM_MOUSEWHEEL) |
|
387 |
# define WM_MOUSEWHEEL 0x020A |
|
388 |
#endif //WM_MOUSEWHEEL |
|
389 |
#if !defined(GET_WHEEL_DELTA_WPARAM) |
|
390 |
# define GET_WHEEL_DELTA_WPARAM(wparam) ((short)HIWORD(wparam)) |
|
391 |
#endif //GET_WHEEL_DELTA_WPARAM |
|
392 |
||
393 |
case WM_MOUSEWHEEL: { |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
394 |
int delta = GET_WHEEL_DELTA_WPARAM(wParam); |
0 | 395 |
if (delta < 0) { |
396 |
_cursor.wheel++; |
|
397 |
} else if (delta > 0) { |
|
398 |
_cursor.wheel--; |
|
399 |
} |
|
400 |
return 0; |
|
401 |
} |
|
402 |
||
403 |
case WM_ACTIVATEAPP: |
|
404 |
_wnd.has_focus = (bool)wParam; |
|
405 |
break; |
|
406 |
} |
|
407 |
return DefWindowProc(hwnd, msg, wParam, lParam); |
|
408 |
} |
|
409 |
||
410 |
static void RegisterWndClass() |
|
411 |
{ |
|
412 |
static bool registered; |
|
413 |
if (!registered) { |
|
414 |
HINSTANCE hinst = GetModuleHandle(NULL); |
|
415 |
WNDCLASS wnd = { |
|
416 |
0, |
|
417 |
WndProcGdi, |
|
418 |
0, |
|
419 |
0, |
|
420 |
hinst, |
|
421 |
LoadIcon(hinst, MAKEINTRESOURCE(100)), |
|
422 |
LoadCursor(NULL, IDC_ARROW), |
|
423 |
0, |
|
424 |
0, |
|
425 |
"TTD" |
|
426 |
}; |
|
427 |
registered = true; |
|
428 |
if (!RegisterClass(&wnd)) |
|
429 |
error("RegisterClass failed"); |
|
430 |
} |
|
431 |
} |
|
432 |
||
433 |
static void MakeWindow(bool full_screen) |
|
434 |
{ |
|
435 |
_fullscreen = full_screen; |
|
436 |
||
437 |
_wnd.double_size = _double_size && !full_screen; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
438 |
|
0 | 439 |
// recreate window? |
440 |
if ((full_screen|_wnd.fullscreen) && _wnd.main_wnd) { |
|
441 |
DestroyWindow(_wnd.main_wnd); |
|
442 |
_wnd.main_wnd = 0; |
|
443 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
444 |
|
0 | 445 |
if (full_screen) { |
446 |
DEVMODE settings; |
|
447 |
memset(&settings, 0, sizeof(DEVMODE)); |
|
448 |
settings.dmSize = sizeof(DEVMODE); |
|
449 |
settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; |
|
450 |
||
451 |
if (_fullscreen_bpp) { |
|
452 |
settings.dmBitsPerPel = _fullscreen_bpp; |
|
453 |
settings.dmFields |= DM_BITSPERPEL; |
|
454 |
} |
|
455 |
settings.dmPelsWidth = _wnd.width_org; |
|
456 |
settings.dmPelsHeight = _wnd.height_org; |
|
457 |
if ((settings.dmDisplayFrequency = _display_hz) != 0) |
|
458 |
settings.dmFields |= DM_DISPLAYFREQUENCY; |
|
459 |
if ( !ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL ) { |
|
460 |
MakeWindow(false); |
|
461 |
return; |
|
462 |
} |
|
463 |
} else if (_wnd.fullscreen) { |
|
464 |
// restore display? |
|
465 |
ChangeDisplaySettings(NULL, 0); |
|
466 |
} |
|
467 |
||
468 |
{ |
|
469 |
RECT r; |
|
470 |
uint style; |
|
471 |
int x, y, w, h; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
472 |
|
0 | 473 |
if ((_wnd.fullscreen=full_screen) != false) { |
474 |
style = WS_POPUP | WS_VISIBLE; |
|
475 |
SetRect(&r, 0, 0, _wnd.width_org, _wnd.height_org); |
|
476 |
} else { |
|
477 |
style = WS_OVERLAPPEDWINDOW | WS_VISIBLE; |
|
478 |
SetRect(&r, 0, 0, _wnd.width, _wnd.height); |
|
479 |
} |
|
480 |
||
481 |
AdjustWindowRect(&r, style, FALSE); |
|
482 |
w = r.right - r.left; |
|
483 |
h = r.bottom - r.top; |
|
484 |
x = (GetSystemMetrics(SM_CXSCREEN)-w)>>1; |
|
485 |
y = (GetSystemMetrics(SM_CYSCREEN)-h)>>1; |
|
486 |
||
487 |
if (_wnd.main_wnd) { |
|
488 |
SetWindowPos(_wnd.main_wnd, 0, x, y, w, h, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER); |
|
489 |
} else { |
|
287
ca9584af45a0
(svn r293) -Feature: Windows now shows (available) revision, release information in title bar
darkvater
parents:
223
diff
changeset
|
490 |
char Windowtitle[50] = "OpenTTD "; |
ca9584af45a0
(svn r293) -Feature: Windows now shows (available) revision, release information in title bar
darkvater
parents:
223
diff
changeset
|
491 |
#ifdef WITH_REV_HACK |
ca9584af45a0
(svn r293) -Feature: Windows now shows (available) revision, release information in title bar
darkvater
parents:
223
diff
changeset
|
492 |
// also show revision number/release in window title |
ca9584af45a0
(svn r293) -Feature: Windows now shows (available) revision, release information in title bar
darkvater
parents:
223
diff
changeset
|
493 |
extern const char _openttd_revision[]; |
ca9584af45a0
(svn r293) -Feature: Windows now shows (available) revision, release information in title bar
darkvater
parents:
223
diff
changeset
|
494 |
strncat(Windowtitle, _openttd_revision, sizeof(Windowtitle)-(strlen(Windowtitle) + 1)); |
ca9584af45a0
(svn r293) -Feature: Windows now shows (available) revision, release information in title bar
darkvater
parents:
223
diff
changeset
|
495 |
#endif |
ca9584af45a0
(svn r293) -Feature: Windows now shows (available) revision, release information in title bar
darkvater
parents:
223
diff
changeset
|
496 |
_wnd.main_wnd = CreateWindow("TTD", Windowtitle, style, x, y, w, h, 0, 0, _inst, 0); |
0 | 497 |
if (_wnd.main_wnd == NULL) |
498 |
error("CreateWindow failed"); |
|
499 |
} |
|
500 |
} |
|
298
b3e83b94be19
(svn r304) -Fix: [967096] fullscreen. New button 'Fullscreen' in 'Game Options' menu which lets you set fullscreen ingame.
darkvater
parents:
287
diff
changeset
|
501 |
GameSizeChanged(); // invalidate all windows, force redraw |
0 | 502 |
} |
503 |
||
504 |
static bool AllocateDibSection(int w, int h) |
|
505 |
{ |
|
506 |
BITMAPINFO *bi; |
|
507 |
HDC dc; |
|
508 |
||
306
c44133836566
(svn r312) -Fix: [926105] ctrl + d bug. Longest outstanding bug has been fixed \o/ 2004-03-30 (Tron)
darkvater
parents:
298
diff
changeset
|
509 |
w = clamp(w, 64, MAX_SCREEN_WIDTH); |
c44133836566
(svn r312) -Fix: [926105] ctrl + d bug. Longest outstanding bug has been fixed \o/ 2004-03-30 (Tron)
darkvater
parents:
298
diff
changeset
|
510 |
h = clamp(h, 64, MAX_SCREEN_HEIGHT); |
0 | 511 |
|
512 |
if (w == _screen.width && h == _screen.height) |
|
513 |
return false; |
|
514 |
||
306
c44133836566
(svn r312) -Fix: [926105] ctrl + d bug. Longest outstanding bug has been fixed \o/ 2004-03-30 (Tron)
darkvater
parents:
298
diff
changeset
|
515 |
_screen.width = w; |
c44133836566
(svn r312) -Fix: [926105] ctrl + d bug. Longest outstanding bug has been fixed \o/ 2004-03-30 (Tron)
darkvater
parents:
298
diff
changeset
|
516 |
_screen.pitch = (w + 3) & ~0x3; |
0 | 517 |
_screen.height = h; |
518 |
||
519 |
if (_wnd.alloced_bits) { |
|
520 |
free(_wnd.alloced_bits); |
|
521 |
_wnd.alloced_bits = NULL; |
|
522 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
523 |
|
0 | 524 |
bi = alloca(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256); |
525 |
memset(bi, 0, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256); |
|
526 |
bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
527 |
|
306
c44133836566
(svn r312) -Fix: [926105] ctrl + d bug. Longest outstanding bug has been fixed \o/ 2004-03-30 (Tron)
darkvater
parents:
298
diff
changeset
|
528 |
if (_wnd.double_size) { |
c44133836566
(svn r312) -Fix: [926105] ctrl + d bug. Longest outstanding bug has been fixed \o/ 2004-03-30 (Tron)
darkvater
parents:
298
diff
changeset
|
529 |
w = (w + 3) & ~0x3; |
c44133836566
(svn r312) -Fix: [926105] ctrl + d bug. Longest outstanding bug has been fixed \o/ 2004-03-30 (Tron)
darkvater
parents:
298
diff
changeset
|
530 |
_wnd.alloced_bits = _wnd.buffer_bits = (byte*)malloc(w * h); |
c44133836566
(svn r312) -Fix: [926105] ctrl + d bug. Longest outstanding bug has been fixed \o/ 2004-03-30 (Tron)
darkvater
parents:
298
diff
changeset
|
531 |
w *= 2; |
c44133836566
(svn r312) -Fix: [926105] ctrl + d bug. Longest outstanding bug has been fixed \o/ 2004-03-30 (Tron)
darkvater
parents:
298
diff
changeset
|
532 |
h *= 2; |
c44133836566
(svn r312) -Fix: [926105] ctrl + d bug. Longest outstanding bug has been fixed \o/ 2004-03-30 (Tron)
darkvater
parents:
298
diff
changeset
|
533 |
} |
0 | 534 |
|
306
c44133836566
(svn r312) -Fix: [926105] ctrl + d bug. Longest outstanding bug has been fixed \o/ 2004-03-30 (Tron)
darkvater
parents:
298
diff
changeset
|
535 |
bi->bmiHeader.biWidth = _wnd.width = w; |
c44133836566
(svn r312) -Fix: [926105] ctrl + d bug. Longest outstanding bug has been fixed \o/ 2004-03-30 (Tron)
darkvater
parents:
298
diff
changeset
|
536 |
bi->bmiHeader.biHeight = -(_wnd.height = h); |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
537 |
|
0 | 538 |
bi->bmiHeader.biPlanes = 1; |
539 |
bi->bmiHeader.biBitCount = 8; |
|
540 |
bi->bmiHeader.biCompression = BI_RGB; |
|
541 |
||
542 |
if (_wnd.dib_sect) |
|
543 |
DeleteObject(_wnd.dib_sect); |
|
544 |
||
545 |
dc = GetDC(0); |
|
546 |
_wnd.dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, &_wnd.bitmap_bits, NULL, 0); |
|
547 |
if (_wnd.dib_sect == NULL) |
|
548 |
error("CreateDIBSection failed"); |
|
549 |
ReleaseDC(0, dc); |
|
550 |
||
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
551 |
if (!_wnd.double_size) |
0 | 552 |
_wnd.buffer_bits = _wnd.bitmap_bits; |
553 |
||
554 |
return true; |
|
555 |
} |
|
556 |
||
557 |
static const uint16 default_resolutions[][2] = { |
|
558 |
{640,480}, |
|
559 |
{800,600}, |
|
560 |
{1024,768}, |
|
561 |
{1152,864}, |
|
562 |
{1280,960}, |
|
563 |
{1280,1024}, |
|
564 |
{1400,1050}, |
|
565 |
{1600,1200}, |
|
566 |
}; |
|
567 |
||
568 |
static void FindResolutions() |
|
569 |
{ |
|
570 |
int i = 0, n = 0; |
|
571 |
DEVMODE dm; |
|
572 |
||
573 |
while (EnumDisplaySettings(NULL, i++, &dm)) { |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
574 |
if (dm.dmBitsPerPel == 8 && |
0 | 575 |
IS_INT_INSIDE(dm.dmPelsWidth, 640, MAX_SCREEN_WIDTH+1) && |
576 |
IS_INT_INSIDE(dm.dmPelsHeight, 480, MAX_SCREEN_HEIGHT+1) && |
|
577 |
(n == 0 || _resolutions[n-1][0] != dm.dmPelsWidth || _resolutions[n-1][1] != dm.dmPelsHeight)) { |
|
578 |
_resolutions[n][0] = dm.dmPelsWidth; |
|
579 |
_resolutions[n][1] = dm.dmPelsHeight; |
|
580 |
if (++n == sizeof(_resolutions) / (sizeof(uint16)*2)) break; |
|
581 |
} |
|
582 |
} |
|
583 |
||
584 |
if (n == 0) { |
|
585 |
memcpy(_resolutions, default_resolutions, sizeof(default_resolutions)); |
|
586 |
n = 6; |
|
587 |
} |
|
588 |
||
589 |
_num_resolutions = n; |
|
590 |
} |
|
591 |
||
592 |
||
8
9ab81ef450f2
(svn r9) Fixed a couple of warnings and minor coding issues
dominik
parents:
0
diff
changeset
|
593 |
static const char *Win32GdiStart(char **parm) |
0 | 594 |
{ |
595 |
memset(&_wnd, 0, sizeof(_wnd)); |
|
596 |
_wnd.cursor_visible = true; |
|
597 |
||
598 |
RegisterWndClass(); |
|
599 |
||
600 |
MakePalette(); |
|
601 |
||
602 |
FindResolutions(); |
|
603 |
||
604 |
// fullscreen uses those |
|
605 |
_wnd.width_org = _cur_resolution[0]; |
|
606 |
_wnd.height_org = _cur_resolution[1]; |
|
607 |
||
608 |
AllocateDibSection(_cur_resolution[0], _cur_resolution[1]); |
|
609 |
MarkWholeScreenDirty(); |
|
610 |
||
611 |
MakeWindow(_fullscreen); |
|
612 |
||
613 |
return NULL; |
|
614 |
} |
|
615 |
||
616 |
static void Win32GdiStop() |
|
617 |
{ |
|
618 |
if ( _wnd.fullscreen ) { |
|
619 |
ChangeDisplaySettings(NULL, 0); |
|
620 |
} |
|
621 |
MyShowCursor(true); |
|
622 |
DeleteObject(_wnd.gdi_palette); |
|
623 |
DeleteObject(_wnd.dib_sect); |
|
624 |
DestroyWindow(_wnd.main_wnd); |
|
625 |
} |
|
626 |
||
627 |
// simple upscaler by 2 |
|
628 |
static void filter(int left, int top, int width, int height) |
|
629 |
{ |
|
630 |
uint p = _screen.pitch; |
|
631 |
byte *s = (byte*)_wnd.buffer_bits + top * p + left; |
|
632 |
byte *d = (byte*)_wnd.bitmap_bits + top * p * 4 + left * 2; |
|
633 |
int i; |
|
634 |
||
635 |
while (height) { |
|
636 |
for(i=0; i!=width; i++) { |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
637 |
d[i*2] = d[i*2+1] = d[i*2+p*2] = d[i*2+1+p*2] = s[i]; |
0 | 638 |
} |
639 |
s += p; |
|
640 |
d += p * 4; |
|
641 |
height--; |
|
642 |
} |
|
643 |
} |
|
644 |
||
645 |
static void Win32GdiMakeDirty(int left, int top, int width, int height) |
|
646 |
{ |
|
647 |
RECT r = {left, top, left+width, top+height}; |
|
648 |
if (_wnd.double_size) { |
|
649 |
filter(left, top, width, height); |
|
650 |
//filter(0, 0, 640, 480); |
|
651 |
r.left *= 2;r.top *= 2;r.right *= 2;r.bottom *= 2; |
|
652 |
} |
|
653 |
InvalidateRect(_wnd.main_wnd, &r, FALSE); |
|
654 |
} |
|
655 |
||
656 |
static void CheckPaletteAnim() |
|
657 |
{ |
|
658 |
if (_pal_last_dirty == -1) |
|
659 |
return; |
|
660 |
InvalidateRect(_wnd.main_wnd, NULL, FALSE); |
|
661 |
} |
|
662 |
||
663 |
static int Win32GdiMainLoop() |
|
664 |
{ |
|
665 |
MSG mesg; |
|
666 |
uint32 next_tick = GetTickCount() + 30, cur_ticks; |
|
667 |
||
668 |
_wnd.running = true; |
|
669 |
||
670 |
while(true) { |
|
671 |
while (PeekMessage(&mesg, NULL, 0, 0, PM_REMOVE)) { |
|
672 |
InteractiveRandom(); // randomness |
|
673 |
TranslateMessage(&mesg); |
|
674 |
DispatchMessage(&mesg); |
|
675 |
} |
|
676 |
if (_exit_game) return ML_QUIT; |
|
677 |
if (_wnd.switch_driver) return ML_SWITCHDRIVER; |
|
678 |
||
679 |
#if defined(_DEBUG) |
|
680 |
if (_wnd.has_focus && GetAsyncKeyState(VK_SHIFT) < 0) { |
|
681 |
#else |
|
682 |
if (_wnd.has_focus && GetAsyncKeyState(VK_TAB) < 0) { |
|
683 |
#endif |
|
196
c4c33c0764a0
(svn r197) -Fix: Disable Fast Forward in network games visually (didn't work anyways, just showed graphical output)
darkvater
parents:
193
diff
changeset
|
684 |
if (!_networking) _fast_forward |= 2; |
0 | 685 |
} else if (_fast_forward&2) { |
686 |
_fast_forward = 0; |
|
687 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
688 |
|
0 | 689 |
|
690 |
cur_ticks=GetTickCount(); |
|
691 |
if ((_fast_forward && !_pause) || cur_ticks > next_tick) |
|
692 |
next_tick = cur_ticks; |
|
693 |
||
694 |
if (cur_ticks == next_tick) { |
|
695 |
next_tick += 30; |
|
696 |
_ctrl_pressed = _wnd.has_focus && GetAsyncKeyState(VK_CONTROL)<0; |
|
697 |
_shift_pressed = _wnd.has_focus && GetAsyncKeyState(VK_SHIFT)<0; |
|
698 |
_dbg_screen_rect = _wnd.has_focus && GetAsyncKeyState(VK_CAPITAL)<0; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
699 |
|
0 | 700 |
// determine which directional keys are down |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
701 |
_dirkeys = |
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
702 |
(GetAsyncKeyState(VK_LEFT) < 0 ? 1 : 0) + |
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
703 |
(GetAsyncKeyState(VK_UP) < 0 ? 2 : 0) + |
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
704 |
(GetAsyncKeyState(VK_RIGHT) < 0 ? 4 : 0) + |
0 | 705 |
(GetAsyncKeyState(VK_DOWN) < 0 ? 8 : 0); |
706 |
||
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
707 |
GameLoop(); |
0 | 708 |
_cursor.delta.x = _cursor.delta.y = 0; |
709 |
||
710 |
if (_force_full_redraw) |
|
711 |
MarkWholeScreenDirty(); |
|
712 |
||
713 |
GdiFlush(); |
|
714 |
_screen.dst_ptr = _wnd.buffer_bits; |
|
715 |
UpdateWindows(); |
|
716 |
CheckPaletteAnim(); |
|
717 |
} else { |
|
718 |
Sleep(1); |
|
719 |
GdiFlush(); |
|
720 |
_screen.dst_ptr = _wnd.buffer_bits; |
|
721 |
DrawMouseCursor(); |
|
722 |
} |
|
723 |
} |
|
724 |
} |
|
725 |
||
726 |
static bool Win32GdiChangeRes(int w, int h) |
|
727 |
{ |
|
728 |
_wnd.width = _wnd.width_org = w; |
|
729 |
_wnd.height = _wnd.height_org = h; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
730 |
|
298
b3e83b94be19
(svn r304) -Fix: [967096] fullscreen. New button 'Fullscreen' in 'Game Options' menu which lets you set fullscreen ingame.
darkvater
parents:
287
diff
changeset
|
731 |
MakeWindow(_fullscreen); // _wnd.fullscreen screws up ingame resolution switching |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
732 |
|
0 | 733 |
return true; |
734 |
} |
|
735 |
||
736 |
const HalVideoDriver _win32_video_driver = { |
|
737 |
Win32GdiStart, |
|
738 |
Win32GdiStop, |
|
739 |
Win32GdiMakeDirty, |
|
740 |
Win32GdiMainLoop, |
|
741 |
Win32GdiChangeRes, |
|
742 |
}; |
|
743 |
||
744 |
||
745 |
/********************** |
|
746 |
* WIN32 MIDI PLAYER |
|
747 |
**********************/ |
|
748 |
||
749 |
struct { |
|
750 |
bool stop_song; |
|
751 |
bool terminate; |
|
752 |
bool playing; |
|
753 |
int new_vol; |
|
754 |
HANDLE wait_obj; |
|
755 |
char start_song[260]; |
|
756 |
} _midi; |
|
757 |
||
758 |
static void Win32MidiPlaySong(const char *filename) |
|
759 |
{ |
|
760 |
strcpy(_midi.start_song, filename); |
|
761 |
_midi.playing = true; |
|
762 |
_midi.stop_song = false; |
|
763 |
SetEvent(_midi.wait_obj); |
|
764 |
} |
|
765 |
||
766 |
static void Win32MidiStopSong() |
|
767 |
{ |
|
768 |
if (_midi.playing) { |
|
769 |
_midi.stop_song = true; |
|
770 |
_midi.start_song[0] = 0; |
|
771 |
SetEvent(_midi.wait_obj); |
|
772 |
} |
|
773 |
} |
|
774 |
||
775 |
static bool Win32MidiIsSongPlaying() |
|
776 |
{ |
|
777 |
return _midi.playing; |
|
778 |
} |
|
779 |
||
780 |
static void Win32MidiSetVolume(byte vol) |
|
781 |
{ |
|
782 |
_midi.new_vol = vol; |
|
783 |
SetEvent(_midi.wait_obj); |
|
784 |
} |
|
785 |
||
786 |
static long CDECL MidiSendCommand(const char *cmd, ...) { |
|
787 |
va_list va; |
|
788 |
char buf[512]; |
|
789 |
va_start(va, cmd); |
|
790 |
vsprintf(buf, cmd, va); |
|
791 |
va_end(va); |
|
792 |
return mciSendStringA(buf, NULL, 0, 0); |
|
793 |
} |
|
794 |
||
795 |
static bool MidiIntPlaySong(const char *filename) |
|
796 |
{ |
|
797 |
MidiSendCommand("close all"); |
|
798 |
if (MidiSendCommand("open %s type sequencer alias song", filename) != 0) |
|
799 |
return false; |
|
800 |
||
801 |
if (MidiSendCommand("play song from 0") != 0) |
|
802 |
return false; |
|
803 |
return true; |
|
804 |
} |
|
805 |
||
806 |
static void MidiIntStopSong() |
|
807 |
{ |
|
808 |
MidiSendCommand("close all"); |
|
809 |
} |
|
810 |
||
811 |
static void MidiIntSetVolume(int vol) |
|
812 |
{ |
|
813 |
uint v = (vol * 65535 / 127); |
|
814 |
midiOutSetVolume((HMIDIOUT)-1, v + (v<<16)); |
|
815 |
} |
|
816 |
||
817 |
static bool MidiIntIsSongPlaying() |
|
818 |
{ |
|
819 |
char buf[16]; |
|
820 |
mciSendStringA("status song mode", buf, sizeof(buf), 0); |
|
821 |
return strcmp(buf, "playing") == 0 || strcmp(buf, "seeking") == 0; |
|
822 |
} |
|
823 |
||
824 |
static DWORD WINAPI MidiThread(LPVOID arg) |
|
825 |
{ |
|
826 |
char *s; |
|
827 |
int vol; |
|
828 |
||
829 |
_midi.wait_obj = CreateEvent(NULL, FALSE, FALSE, NULL); |
|
830 |
||
831 |
do { |
|
832 |
if ((vol=_midi.new_vol) != -1) { |
|
833 |
_midi.new_vol = -1; |
|
834 |
MidiIntSetVolume(vol); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
835 |
|
0 | 836 |
} |
837 |
if ((s=_midi.start_song)[0]) { |
|
838 |
_midi.playing = MidiIntPlaySong(s); |
|
839 |
s[0] = 0; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
840 |
|
0 | 841 |
// Delay somewhat in case we don't manage to play. |
842 |
if (!_midi.playing) { |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
843 |
Sleep(5000); |
0 | 844 |
} |
845 |
} |
|
846 |
if (_midi.stop_song != false && _midi.playing) { |
|
847 |
_midi.stop_song = false; |
|
848 |
_midi.playing = false; |
|
849 |
MidiIntStopSong(); |
|
850 |
} |
|
851 |
||
852 |
if (_midi.playing && !MidiIntIsSongPlaying()) |
|
853 |
_midi.playing = false; |
|
854 |
||
855 |
WaitForMultipleObjects(1, &_midi.wait_obj, FALSE, 1000); |
|
856 |
} while (!_midi.terminate); |
|
857 |
||
858 |
DeleteObject(_midi.wait_obj); |
|
859 |
return 0; |
|
860 |
} |
|
861 |
||
862 |
static char *Win32MidiStart(char **parm) |
|
863 |
{ |
|
864 |
DWORD threadId; |
|
865 |
memset(&_midi, 0, sizeof(_midi)); |
|
866 |
_midi.new_vol = -1; |
|
867 |
CreateThread(NULL, 8192, MidiThread, 0, 0, &threadId); |
|
868 |
return 0; |
|
869 |
} |
|
870 |
||
871 |
static void Win32MidiStop() |
|
872 |
{ |
|
873 |
_midi.terminate = true; |
|
874 |
SetEvent(_midi.wait_obj); |
|
875 |
} |
|
876 |
||
877 |
const HalMusicDriver _win32_music_driver = { |
|
878 |
Win32MidiStart, |
|
879 |
Win32MidiStop, |
|
880 |
Win32MidiPlaySong, |
|
881 |
Win32MidiStopSong, |
|
882 |
Win32MidiIsSongPlaying, |
|
883 |
Win32MidiSetVolume, |
|
884 |
}; |
|
885 |
||
886 |
// WIN32 Sound code. |
|
887 |
||
888 |
static HWAVEOUT _waveout; |
|
889 |
static WAVEHDR _wave_hdr[2]; |
|
890 |
static int _bufsize; |
|
891 |
static void PrepareHeader(WAVEHDR *hdr) |
|
892 |
{ |
|
893 |
hdr->dwBufferLength = _bufsize*4; |
|
894 |
hdr->dwFlags = 0; |
|
895 |
hdr->lpData = malloc(_bufsize*4); |
|
896 |
if (hdr->lpData == NULL || waveOutPrepareHeader(_waveout, hdr, sizeof(WAVEHDR)) != MMSYSERR_NOERROR) |
|
897 |
error("waveOutPrepareHeader failed"); |
|
898 |
} |
|
899 |
||
900 |
static void FillHeaders() |
|
901 |
{ |
|
902 |
WAVEHDR *hdr; |
|
903 |
for(hdr=_wave_hdr; hdr != endof(_wave_hdr); hdr++) { |
|
904 |
if (!(hdr->dwFlags & WHDR_INQUEUE)) { |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
905 |
MxMixSamples(_mixer, hdr->lpData, hdr->dwBufferLength >> 2); |
0 | 906 |
if (waveOutWrite(_waveout, hdr, sizeof(WAVEHDR)) != MMSYSERR_NOERROR) |
907 |
error("waveOutWrite failed"); |
|
908 |
} |
|
909 |
} |
|
910 |
} |
|
911 |
||
912 |
static void CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) |
|
913 |
{ |
|
914 |
switch(uMsg) { |
|
915 |
case WOM_DONE: |
|
916 |
if (_waveout) |
|
917 |
FillHeaders(); |
|
918 |
break; |
|
919 |
} |
|
920 |
} |
|
921 |
||
922 |
static char *Win32SoundStart(char **parm) |
|
923 |
{ |
|
924 |
WAVEFORMATEX wfex; |
|
925 |
int hz; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
926 |
|
0 | 927 |
_bufsize = GetDriverParamInt(parm, "bufsize", 1024); |
928 |
hz = GetDriverParamInt(parm, "hz", 11025); |
|
929 |
wfex.wFormatTag = WAVE_FORMAT_PCM; |
|
930 |
wfex.nChannels = 2; |
|
931 |
wfex.nSamplesPerSec = hz; |
|
932 |
wfex.nAvgBytesPerSec = hz*2*2; |
|
933 |
wfex.nBlockAlign = 4; |
|
934 |
wfex.wBitsPerSample = 16; |
|
935 |
if (waveOutOpen(&_waveout, WAVE_MAPPER, &wfex, (DWORD)&waveOutProc, 0, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) |
|
936 |
return "waveOutOpen failed"; |
|
937 |
PrepareHeader(&_wave_hdr[0]); |
|
938 |
PrepareHeader(&_wave_hdr[1]); |
|
939 |
FillHeaders(); |
|
940 |
return NULL; |
|
941 |
} |
|
942 |
||
943 |
static void Win32SoundStop() |
|
944 |
{ |
|
945 |
HWAVEOUT waveout = _waveout; |
|
946 |
_waveout = NULL; |
|
947 |
waveOutReset(waveout); |
|
948 |
waveOutUnprepareHeader(waveout, &_wave_hdr[0], sizeof(WAVEHDR)); |
|
949 |
waveOutUnprepareHeader(waveout, &_wave_hdr[1], sizeof(WAVEHDR)); |
|
950 |
waveOutClose(waveout); |
|
951 |
} |
|
952 |
||
953 |
const HalSoundDriver _win32_sound_driver = { |
|
954 |
Win32SoundStart, |
|
955 |
Win32SoundStop, |
|
956 |
}; |
|
957 |
||
958 |
// Helper function needed by dynamically loading SDL |
|
959 |
bool LoadLibraryList(void **proc, const char *dll) |
|
960 |
{ |
|
961 |
HMODULE lib; |
|
962 |
void *p; |
|
963 |
||
964 |
while (*dll) { |
|
965 |
lib = LoadLibrary(dll); |
|
966 |
if (lib == NULL) |
|
967 |
return false; |
|
968 |
while (true) { |
|
969 |
while(*dll++); |
|
970 |
if (!*dll) |
|
971 |
break; |
|
972 |
p = GetProcAddress(lib, dll); |
|
973 |
if (p == NULL) |
|
974 |
return false; |
|
975 |
*proc++ = p; |
|
976 |
} |
|
977 |
dll++; |
|
978 |
} |
|
979 |
return true; |
|
980 |
} |
|
981 |
||
982 |
static const char *_exception_string; |
|
983 |
static void *_safe_esp; |
|
984 |
static char *_crash_msg; |
|
985 |
static bool _expanded; |
|
986 |
static bool _did_emerg_save; |
|
987 |
static int _ident; |
|
988 |
||
989 |
void ShowOSErrorBox(const char *buf) |
|
990 |
{ |
|
991 |
MyShowCursor(true); |
|
992 |
MessageBoxA(GetActiveWindow(), buf, "Error!", MB_ICONSTOP); |
|
993 |
||
994 |
// if exception tracker is enabled, we crash here to let the exception handler handle it. |
|
995 |
#if defined(WIN32_EXCEPTION_TRACKER) && !defined(_DEBUG) |
|
996 |
if (*buf == '!') { |
|
997 |
_exception_string = buf; |
|
998 |
*(byte*)0 = 0; |
|
999 |
} |
|
1000 |
#endif |
|
1001 |
||
1002 |
} |
|
1003 |
||
1004 |
#ifdef _MSC_VER |
|
1005 |
||
1006 |
typedef struct DebugFileInfo { |
|
1007 |
uint32 size; |
|
1008 |
uint32 crc32; |
|
1009 |
SYSTEMTIME file_time; |
|
1010 |
} DebugFileInfo; |
|
1011 |
||
1012 |
||
1013 |
||
1014 |
static uint32 *_crc_table; |
|
1015 |
||
1016 |
static void MakeCRCTable(uint32 *table) { |
|
1017 |
uint32 crc, poly = 0xEDB88320L; |
|
1018 |
int i, j; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1019 |
|
0 | 1020 |
_crc_table = table; |
1021 |
||
1022 |
for (i=0; i!=256; i++) { |
|
1023 |
crc = i; |
|
1024 |
for (j=8; j!=0; j--) { |
|
1025 |
if (crc & 1) |
|
1026 |
crc = (crc >> 1) ^ poly; |
|
1027 |
else |
|
1028 |
crc>>=1; |
|
1029 |
} |
|
1030 |
table[i] = crc; |
|
1031 |
} |
|
1032 |
} |
|
1033 |
||
1034 |
static uint32 CalcCRC(byte *data, uint size, uint32 crc) { |
|
1035 |
do { |
|
1036 |
crc = ((crc>>8) & 0x00FFFFFF) ^ _crc_table[ (crc^(*data++)) & 0xFF ]; |
|
1037 |
} while (--size); |
|
1038 |
return crc; |
|
1039 |
} |
|
1040 |
||
1041 |
static void GetFileInfo(DebugFileInfo *dfi, const char *filename) |
|
1042 |
{ |
|
1043 |
memset(dfi, 0, sizeof(dfi)); |
|
1044 |
||
1045 |
{ |
|
1046 |
HANDLE file; |
|
1047 |
byte buffer[1024]; |
|
1048 |
DWORD numread; |
|
1049 |
uint32 filesize = 0; |
|
1050 |
FILETIME write_time; |
|
1051 |
uint32 crc = (uint32)-1; |
|
1052 |
||
1053 |
file = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); |
|
1054 |
if (file != INVALID_HANDLE_VALUE) { |
|
1055 |
while(true) { |
|
1056 |
if (ReadFile(file, buffer, sizeof(buffer), &numread, NULL) == 0 || numread==0) |
|
1057 |
break; |
|
1058 |
filesize += numread; |
|
1059 |
crc = CalcCRC(buffer, numread, crc); |
|
1060 |
} |
|
1061 |
dfi->size = filesize; |
|
1062 |
dfi->crc32 = crc ^ (uint32)-1; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1063 |
|
0 | 1064 |
if (GetFileTime(file, NULL, NULL, &write_time)) { |
1065 |
FileTimeToSystemTime(&write_time, &dfi->file_time); |
|
1066 |
} |
|
1067 |
CloseHandle(file); |
|
1068 |
} |
|
1069 |
} |
|
1070 |
} |
|
1071 |
||
1072 |
||
1073 |
static char *PrintModuleInfo(char *output, HMODULE mod) |
|
1074 |
{ |
|
1075 |
char *buffer = alloca(MAX_PATH); |
|
1076 |
DebugFileInfo dfi; |
|
1077 |
GetModuleFileName(mod, buffer, MAX_PATH); |
|
1078 |
GetFileInfo(&dfi, buffer); |
|
1079 |
output += sprintf(output, " %-20s handle: %.8X size: %d crc: %.8X date: %d-%.2d-%.2d %.2d:%.2d:%.2d\r\n", |
|
1080 |
buffer, |
|
1081 |
mod, |
|
1082 |
dfi.size, |
|
1083 |
dfi.crc32, |
|
1084 |
dfi.file_time.wYear, |
|
1085 |
dfi.file_time.wMonth, |
|
1086 |
dfi.file_time.wDay, |
|
1087 |
dfi.file_time.wHour, |
|
1088 |
dfi.file_time.wMinute, |
|
1089 |
dfi.file_time.wSecond |
|
1090 |
); |
|
1091 |
return output; |
|
1092 |
} |
|
1093 |
||
1094 |
static char *PrintModuleList(char *output) |
|
1095 |
{ |
|
1096 |
BOOL (WINAPI *EnumProcessModules)(HANDLE,HMODULE*,DWORD,LPDWORD); |
|
1097 |
HANDLE proc; |
|
1098 |
HMODULE modules[100]; |
|
1099 |
DWORD needed; |
|
1100 |
BOOL res; |
|
1101 |
int count,i; |
|
1102 |
||
1103 |
if (LoadLibraryList((void*)&EnumProcessModules, "psapi.dll\0EnumProcessModules\0")) { |
|
1104 |
proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId()); |
|
1105 |
if (proc) { |
|
1106 |
res = EnumProcessModules(proc, modules, sizeof(modules), &needed); |
|
1107 |
CloseHandle(proc); |
|
1108 |
if (res) { |
|
1109 |
count = min(needed/sizeof(HMODULE*), sizeof(modules)/sizeof(HMODULE*)); |
|
1110 |
for(i=0; i!=count; i++) |
|
1111 |
output = PrintModuleInfo(output, modules[i]); |
|
1112 |
return output; |
|
1113 |
} |
|
1114 |
} |
|
1115 |
} |
|
1116 |
output = PrintModuleInfo(output, NULL); |
|
1117 |
return output; |
|
1118 |
} |
|
1119 |
||
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1120 |
static const char _crash_desc[] = |
0 | 1121 |
"A serious fault condition occured in the game. The game will shut down.\n" |
1122 |
"Press \"Submit report\" to send crash information to the developers. " |
|
1123 |
"This will greatly help debugging. The information contained in the report is " |
|
1124 |
"displayed below.\n" |
|
1125 |
"Press \"Emergency save\" to attempt saving the game."; |
|
1126 |
||
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1127 |
static const char _save_succeeded[] = |
0 | 1128 |
"Emergency save succeeded.\nBe aware that critical parts of the internal game state " |
1129 |
"may have become corrupted. The saved game is not guaranteed to work."; |
|
1130 |
||
1131 |
bool EmergencySave(); |
|
1132 |
||
1133 |
||
1134 |
typedef struct { |
|
1135 |
HINTERNET (WINAPI *InternetOpenA)(LPCSTR,DWORD, LPCSTR, LPCSTR, DWORD); |
|
1136 |
HINTERNET (WINAPI *InternetConnectA)(HINTERNET, LPCSTR, INTERNET_PORT, LPCSTR, LPCSTR, DWORD, DWORD, DWORD); |
|
1137 |
HINTERNET (WINAPI *HttpOpenRequestA)(HINTERNET, LPCSTR, LPCSTR, LPCSTR, LPCSTR, LPCSTR *, DWORD, DWORD); |
|
1138 |
BOOL (WINAPI *HttpSendRequestA)(HINTERNET, LPCSTR, DWORD, LPVOID, DWORD); |
|
1139 |
BOOL (WINAPI *InternetCloseHandle)(HINTERNET); |
|
1140 |
BOOL (WINAPI *HttpQueryInfo)(HINTERNET, DWORD, LPVOID, LPDWORD, LPDWORD); |
|
1141 |
} WinInetProcs; |
|
1142 |
||
1143 |
#define M(x) x "\0" |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1144 |
static const char wininet_files[] = |
0 | 1145 |
M("wininet.dll") |
1146 |
M("InternetOpenA") |
|
1147 |
M("InternetConnectA") |
|
1148 |
M("HttpOpenRequestA") |
|
1149 |
M("HttpSendRequestA") |
|
1150 |
M("InternetCloseHandle") |
|
1151 |
M("HttpQueryInfoA") |
|
1152 |
M(""); |
|
1153 |
#undef M |
|
1154 |
||
1155 |
static WinInetProcs _wininet; |
|
1156 |
||
1157 |
||
1158 |
static char *SubmitCrashReport(HWND wnd, void *msg, size_t msglen, const char *arg) |
|
1159 |
{ |
|
1160 |
HINTERNET inet, conn, http; |
|
1161 |
char *err = NULL; |
|
1162 |
DWORD code, len; |
|
1163 |
static char buf[100]; |
|
1164 |
char buff[100]; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1165 |
|
0 | 1166 |
if (_wininet.InternetOpen == NULL && !LoadLibraryList((void**)&_wininet, wininet_files)) return "can't load wininet.dll"; |
1167 |
||
1168 |
inet = _wininet.InternetOpen("TTD", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 ); |
|
1169 |
if (inet == NULL) { err = "internetopen failed"; goto error1; } |
|
1170 |
||
1171 |
conn = _wininet.InternetConnect(inet, "openttd.com", INTERNET_DEFAULT_HTTP_PORT, "", "", INTERNET_SERVICE_HTTP, 0, 0); |
|
1172 |
if (conn == NULL) { err = "internetconnect failed"; goto error2; } |
|
1173 |
||
1174 |
sprintf(buff, "/crash.php?file=%s&ident=%d", arg, _ident); |
|
1175 |
||
1176 |
http = _wininet.HttpOpenRequest(conn, "POST", buff, NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE , 0); |
|
1177 |
if (http == NULL) { err = "httpopenrequest failed"; goto error3; } |
|
1178 |
||
1179 |
if (!_wininet.HttpSendRequest(http, "Content-type: application/binary", -1, msg, msglen)) { err = "httpsendrequest failed"; goto error4; } |
|
1180 |
||
1181 |
len = sizeof(code); |
|
1182 |
if (!_wininet.HttpQueryInfo(http, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &code, &len, 0)) { err = "httpqueryinfo failed"; goto error4; } |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1183 |
|
0 | 1184 |
if (code != 200) { |
1185 |
int l = sprintf(buf, "Server said: %d ", code); |
|
1186 |
len = sizeof(buf) - l; |
|
1187 |
_wininet.HttpQueryInfo(http, HTTP_QUERY_STATUS_TEXT, buf + l, &len, 0); |
|
1188 |
err = buf; |
|
1189 |
} |
|
1190 |
||
1191 |
error4: |
|
1192 |
_wininet.InternetCloseHandle(http); |
|
1193 |
error3: |
|
1194 |
_wininet.InternetCloseHandle(conn); |
|
1195 |
error2: |
|
1196 |
_wininet.InternetCloseHandle(inet); |
|
1197 |
error1: |
|
1198 |
return err; |
|
1199 |
} |
|
1200 |
||
1201 |
static void SubmitFile(HWND wnd, const char *file) |
|
1202 |
{ |
|
1203 |
HANDLE h; |
|
1204 |
unsigned long size; |
|
1205 |
unsigned long read; |
|
1206 |
void *mem; |
|
1207 |
||
1208 |
h = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); |
|
1209 |
if (h == NULL) return; |
|
1210 |
||
1211 |
size = GetFileSize(h, NULL); |
|
1212 |
if (size > 500000) goto error1; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1213 |
|
0 | 1214 |
mem = malloc(size); |
1215 |
if (mem == NULL) goto error1; |
|
1216 |
||
1217 |
if (!ReadFile(h, mem, size, &read, NULL) || read != size) goto error2; |
|
1218 |
||
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1219 |
SubmitCrashReport(wnd, mem, size, file); |
0 | 1220 |
|
1221 |
error2: |
|
1222 |
free(mem); |
|
1223 |
error1: |
|
1224 |
CloseHandle(h); |
|
1225 |
} |
|
1226 |
||
1227 |
static const char * const _expand_texts[] = {"S&how report >>", "&Hide report <<" }; |
|
1228 |
||
1229 |
static void SetWndSize(HWND wnd, int mode) |
|
1230 |
{ |
|
1231 |
RECT r,r2; |
|
1232 |
int offs; |
|
1233 |
||
1234 |
GetWindowRect(wnd, &r); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1235 |
|
0 | 1236 |
SetDlgItemText(wnd, 15, _expand_texts[mode == 1]); |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1237 |
|
0 | 1238 |
if (mode >= 0) { |
1239 |
GetWindowRect(GetDlgItem(wnd, 11), &r2); |
|
1240 |
offs = r2.bottom - r2.top + 10; |
|
1241 |
if (!mode) offs=-offs; |
|
1242 |
SetWindowPos(wnd, HWND_TOPMOST, 0, 0, r.right - r.left, r.bottom - r.top + offs, SWP_NOMOVE | SWP_NOZORDER); |
|
1243 |
} else { |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1244 |
SetWindowPos(wnd, HWND_TOPMOST, |
0 | 1245 |
(GetSystemMetrics(SM_CXSCREEN) - (r.right - r.left)) >> 1, |
1246 |
(GetSystemMetrics(SM_CYSCREEN) - (r.bottom - r.top)) >> 1, |
|
1247 |
0, 0, SWP_NOSIZE); |
|
1248 |
} |
|
1249 |
} |
|
1250 |
||
1251 |
static bool DoEmergencySave(HWND wnd) |
|
1252 |
{ |
|
1253 |
bool b = false; |
|
1254 |
||
1255 |
EnableWindow(GetDlgItem(wnd, 13), FALSE); |
|
1256 |
_did_emerg_save = true; |
|
1257 |
__try { |
|
1258 |
b = EmergencySave(); |
|
1259 |
} __except (1) {} |
|
1260 |
return b; |
|
1261 |
} |
|
1262 |
||
1263 |
static BOOL CALLBACK CrashDialogFunc(HWND wnd,UINT msg,WPARAM wParam,LPARAM lParam) |
|
1264 |
{ |
|
1265 |
switch(msg) { |
|
1266 |
case WM_INITDIALOG: |
|
1267 |
SetDlgItemText(wnd, 10, _crash_desc); |
|
1268 |
SetDlgItemText(wnd, 11, _crash_msg); |
|
1269 |
SendDlgItemMessage(wnd, 11, WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), FALSE); |
|
1270 |
SetWndSize(wnd, -1); |
|
1271 |
return TRUE; |
|
1272 |
case WM_COMMAND: |
|
1273 |
switch(wParam) { |
|
1274 |
case 12: // Close |
|
1275 |
ExitProcess(0); |
|
1276 |
case 13: { // Emergency save |
|
1277 |
if (DoEmergencySave(wnd)) |
|
1278 |
MessageBoxA(wnd, _save_succeeded, "Save successful", MB_ICONINFORMATION); |
|
1279 |
else |
|
1280 |
MessageBoxA(wnd, "Save failed", "Save failed", MB_ICONINFORMATION); |
|
1281 |
break; |
|
1282 |
} |
|
1283 |
case 14: { // Submit crash report |
|
1284 |
char *s; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1285 |
|
0 | 1286 |
SetCursor(LoadCursor(NULL, IDC_WAIT)); |
1287 |
||
1288 |
s = SubmitCrashReport(wnd, _crash_msg, strlen(_crash_msg), ""); |
|
1289 |
if (s) { |
|
1290 |
MessageBoxA(wnd, s, "Error", MB_ICONSTOP); |
|
1291 |
break; |
|
1292 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1293 |
|
0 | 1294 |
// try to submit emergency savegame |
1295 |
if (_did_emerg_save || DoEmergencySave(wnd)) { |
|
1296 |
SubmitFile(wnd, "crash.sav"); |
|
1297 |
} |
|
1298 |
// try to submit the autosaved game |
|
1299 |
if (_opt.autosave) { |
|
1300 |
char buf[40]; |
|
1301 |
sprintf(buf, "autosave%d.sav", (_autosave_ctr - 1) & 3); |
|
1302 |
SubmitFile(wnd, buf); |
|
1303 |
} |
|
1304 |
EnableWindow(GetDlgItem(wnd, 14), FALSE); |
|
1305 |
SetCursor(LoadCursor(NULL, IDC_ARROW)); |
|
1306 |
MessageBoxA(wnd, "Crash report submitted. Thank you.", "Crash Report", MB_ICONINFORMATION); |
|
1307 |
break; |
|
1308 |
} |
|
1309 |
case 15: // Expand |
|
1310 |
_expanded ^= 1; |
|
1311 |
SetWndSize(wnd, _expanded); |
|
1312 |
break; |
|
1313 |
} |
|
1314 |
return TRUE; |
|
1315 |
case WM_CLOSE: |
|
1316 |
ExitProcess(0); |
|
1317 |
} |
|
1318 |
||
1319 |
return FALSE; |
|
1320 |
} |
|
1321 |
||
1322 |
static void Handler2() |
|
1323 |
{ |
|
1324 |
ShowCursor(TRUE); |
|
1325 |
ShowWindow(GetActiveWindow(), FALSE); |
|
1326 |
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(100), NULL, CrashDialogFunc); |
|
1327 |
} |
|
1328 |
||
1329 |
static LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *ep) |
|
1330 |
{ |
|
1331 |
char *output; |
|
1332 |
static bool had_exception; |
|
1333 |
||
1334 |
if (had_exception) { ExitProcess(0); } |
|
1335 |
had_exception = true; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1336 |
|
0 | 1337 |
_ident = GetTickCount(); // something pretty unique |
1338 |
||
1339 |
MakeCRCTable(alloca(256 * sizeof(uint32))); |
|
1340 |
_crash_msg = output = LocalAlloc(LMEM_FIXED, 8192); |
|
1341 |
||
1342 |
{ |
|
1343 |
SYSTEMTIME time; |
|
1344 |
GetLocalTime(&time); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1345 |
output += sprintf(output, |
0 | 1346 |
"*** OpenTTD Crash Report ***\r\n" |
1347 |
"Date: %d-%.2d-%.2d %.2d:%.2d:%.2d\r\n" |
|
1348 |
"Build: %s built on " __TIMESTAMP__ "\r\n", |
|
1349 |
time.wYear, |
|
1350 |
time.wMonth, |
|
1351 |
time.wDay, |
|
1352 |
time.wHour, |
|
1353 |
time.wMinute, |
|
1354 |
time.wSecond, |
|
1355 |
"???" |
|
1356 |
); |
|
1357 |
} |
|
1358 |
||
1359 |
if (_exception_string) output += sprintf(output, "Reason: %s\r\n", _exception_string); |
|
1360 |
||
1361 |
output += sprintf(output, "Exception %.8X at %.8X\r\n" |
|
1362 |
"Registers:\r\n" |
|
1363 |
" EAX: %.8X EBX: %.8X ECX: %.8X EDX: %.8X\r\n" |
|
1364 |
" ESI: %.8X EDI: %.8X EBP: %.8X ESP: %.8X\r\n" |
|
1365 |
" EIP: %.8X EFLAGS: %.8X\r\n" |
|
1366 |
"\r\nBytes at CS:EIP:\r\n", |
|
1367 |
ep->ExceptionRecord->ExceptionCode, |
|
1368 |
ep->ExceptionRecord->ExceptionAddress, |
|
1369 |
ep->ContextRecord->Eax, |
|
1370 |
ep->ContextRecord->Ebx, |
|
1371 |
ep->ContextRecord->Ecx, |
|
1372 |
ep->ContextRecord->Edx, |
|
1373 |
ep->ContextRecord->Esi, |
|
1374 |
ep->ContextRecord->Edi, |
|
1375 |
ep->ContextRecord->Ebp, |
|
1376 |
ep->ContextRecord->Esp, |
|
1377 |
ep->ContextRecord->Eip, |
|
1378 |
ep->ContextRecord->EFlags |
|
1379 |
); |
|
1380 |
||
1381 |
{ |
|
1382 |
byte *b = (byte*)ep->ContextRecord->Eip; |
|
1383 |
int i; |
|
1384 |
for(i=0; i!=24; i++) { |
|
1385 |
if (IsBadReadPtr(b, 1)) { |
|
1386 |
output += sprintf(output, " ??"); // OCR: WAS: , 0); |
|
1387 |
} else { |
|
1388 |
output += sprintf(output, " %.2X", *b); |
|
1389 |
} |
|
1390 |
b++; |
|
1391 |
} |
|
1392 |
output += sprintf(output, |
|
1393 |
"\r\n" |
|
1394 |
"\r\nStack trace: \r\n" |
|
1395 |
); |
|
1396 |
} |
|
1397 |
||
1398 |
{ |
|
1399 |
int i,j; |
|
1400 |
uint32 *b = (uint32*)ep->ContextRecord->Esp; |
|
1401 |
for(j=0; j!=24; j++) { |
|
1402 |
for(i=0; i!=8; i++) { |
|
1403 |
if (IsBadReadPtr(b,sizeof(uint32))) { |
|
1404 |
output += sprintf(output, " ????????"); //OCR: WAS - , 0); |
|
1405 |
} else { |
|
1406 |
output += sprintf(output, " %.8X", *b); |
|
1407 |
} |
|
1408 |
b++; |
|
1409 |
} |
|
1410 |
output += sprintf(output, "\r\n"); |
|
1411 |
} |
|
1412 |
} |
|
1413 |
||
1414 |
output += sprintf(output, "\r\nModule information:\r\n"); |
|
1415 |
output = PrintModuleList(output); |
|
1416 |
||
1417 |
{ |
|
1418 |
OSVERSIONINFO os; |
|
1419 |
os.dwOSVersionInfoSize = sizeof(os); |
|
1420 |
GetVersionEx(&os); |
|
1421 |
output += sprintf(output, "\r\nSystem information:\r\n" |
|
1422 |
" Windows version %d.%d %d %s\r\n", os.dwMajorVersion, os.dwMinorVersion, os.dwBuildNumber, os.szCSDVersion); |
|
1423 |
} |
|
1424 |
||
1425 |
{ |
|
1426 |
HANDLE file = CreateFile("crash.log", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); |
|
1427 |
DWORD num_written; |
|
1428 |
if (file != INVALID_HANDLE_VALUE) { |
|
1429 |
WriteFile(file, _crash_msg, output - _crash_msg, &num_written, NULL); |
|
1430 |
CloseHandle(file); |
|
1431 |
} |
|
1432 |
} |
|
1433 |
||
1434 |
if (_safe_esp) { |
|
1435 |
ep->ContextRecord->Eip = (DWORD)Handler2; |
|
1436 |
ep->ContextRecord->Esp = (DWORD)_safe_esp; |
|
1437 |
return EXCEPTION_CONTINUE_EXECUTION; |
|
1438 |
} else { |
|
1439 |
return EXCEPTION_EXECUTE_HANDLER; |
|
1440 |
} |
|
1441 |
} |
|
1442 |
||
1443 |
static void Win32InitializeExceptions() |
|
1444 |
{ |
|
1445 |
_asm { |
|
1446 |
mov _safe_esp,esp |
|
1447 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1448 |
|
0 | 1449 |
SetUnhandledExceptionFilter(ExceptionHandler); |
1450 |
} |
|
1451 |
#endif |
|
1452 |
||
1453 |
static char *_fios_path; |
|
1454 |
static char *_fios_save_path; |
|
1455 |
static char *_fios_scn_path; |
|
1456 |
static FiosItem *_fios_items; |
|
1457 |
static int _fios_count, _fios_alloc; |
|
1458 |
||
1459 |
static FiosItem *FiosAlloc() |
|
1460 |
{ |
|
1461 |
if (_fios_count == _fios_alloc) { |
|
1462 |
_fios_alloc += 256; |
|
1463 |
_fios_items = realloc(_fios_items, _fios_alloc * sizeof(FiosItem)); |
|
1464 |
} |
|
1465 |
return &_fios_items[_fios_count++]; |
|
1466 |
} |
|
1467 |
||
1468 |
static HANDLE MyFindFirstFile(char *path, char *file, WIN32_FIND_DATA *fd) |
|
1469 |
{ |
|
1470 |
char paths[MAX_PATH]; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1471 |
|
0 | 1472 |
sprintf(paths, "%s\\%s", path, file); |
1473 |
return FindFirstFile(paths, fd); |
|
1474 |
} |
|
1475 |
||
1476 |
int CDECL compare_FiosItems (const void *a, const void *b) { |
|
1477 |
const FiosItem *da = (const FiosItem *) a; |
|
1478 |
const FiosItem *db = (const FiosItem *) b; |
|
1479 |
int r; |
|
1480 |
||
1481 |
if (_savegame_sort_order < 2) // sort by date |
|
164
0cbdf3c9bde1
(svn r165) -Feature: Option to sort vehicles in vehicle-list window by different criteria. Total independent sort for all types and players. Periodic resort of list every 10 TTD days. Thank you for your graphical inspiration follow and buxo (since none of you provided any code).
darkvater
parents:
153
diff
changeset
|
1482 |
r = da->mtime < db->mtime ? -1 : 1; |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1483 |
else |
0 | 1484 |
r = stricmp(da->title[0] ? da->title : da->name, db->title[0] ? db->title : db->name); |
1485 |
||
1486 |
if (_savegame_sort_order & 1) r = -r; |
|
1487 |
return r; |
|
1488 |
} |
|
1489 |
||
1490 |
// Get a list of savegames |
|
1491 |
FiosItem *FiosGetSavegameList(int *num, int mode) |
|
1492 |
{ |
|
1493 |
WIN32_FIND_DATA fd; |
|
1494 |
HANDLE h; |
|
1495 |
FiosItem *fios; |
|
1496 |
int sort_start; |
|
1497 |
char buf[MAX_PATH]; |
|
1498 |
||
1499 |
if (_fios_save_path == NULL) { |
|
1500 |
_fios_save_path = malloc(MAX_PATH); |
|
1501 |
strcpy(_fios_save_path, _path.save_dir); |
|
1502 |
} |
|
1503 |
||
1504 |
if (_game_mode == GM_EDITOR) |
|
1505 |
_fios_path = _fios_scn_path; |
|
1506 |
else |
|
1507 |
_fios_path = _fios_save_path; |
|
1508 |
||
1509 |
// Parent directory, only if not of the type C:\. |
|
1510 |
if (_fios_path[3] != 0) { |
|
1511 |
fios = FiosAlloc(); |
|
1512 |
fios->type = FIOS_TYPE_PARENT; |
|
1513 |
strcpy(fios->title, ".. (Parent directory)"); |
|
1514 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1515 |
|
0 | 1516 |
|
1517 |
// Show subdirectories first |
|
1518 |
h = MyFindFirstFile(_fios_path, "*.*", &fd); |
|
1519 |
if (h != INVALID_HANDLE_VALUE) { |
|
1520 |
do { |
|
1521 |
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && |
|
1522 |
!(fd.cFileName[0]=='.' && (fd.cFileName[1]==0 || fd.cFileName[1]=='.' && fd.cFileName[2]==0))) { |
|
1523 |
fios = FiosAlloc(); |
|
1524 |
fios->type = FIOS_TYPE_DIR; |
|
1525 |
strcpy(fios->name, fd.cFileName); |
|
1526 |
sprintf(fios->title, "\\%s (Directory)", fd.cFileName); |
|
1527 |
} |
|
1528 |
} while (FindNextFile(h, &fd)); |
|
1529 |
FindClose(h); |
|
1530 |
} |
|
1531 |
||
1532 |
// this is where to start sorting |
|
1533 |
sort_start = _fios_count; |
|
1534 |
||
1535 |
/* Show savegame files |
|
1536 |
* .SAV OpenTTD saved game |
|
1537 |
* .SS1 Transport Tycoon Deluxe preset game |
|
1538 |
* .SV1 Transport Tycoon Deluxe (Patch) saved game |
|
1539 |
* .SV2 Transport Tycoon Deluxe (Patch) saved 2-player game |
|
1540 |
*/ |
|
1541 |
h = MyFindFirstFile(_fios_path, "*.*", &fd); |
|
1542 |
if (h != INVALID_HANDLE_VALUE) { |
|
1543 |
do { |
|
1544 |
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { |
|
1545 |
char *t = strrchr(fd.cFileName, '.'); |
|
1546 |
if (t && !stricmp(t, ".SAV")) { // OpenTTD |
|
1547 |
fios = FiosAlloc(); |
|
1548 |
fios->mtime = *(uint64*)&fd.ftLastWriteTime; |
|
1549 |
sprintf(buf, "%s\\%s", _fios_path, fd.cFileName); |
|
1550 |
fios->type = FIOS_TYPE_FILE; |
|
1551 |
fios->title[0] = 0; |
|
1552 |
ttd_strlcpy(fios->name, fd.cFileName, strlen(fd.cFileName)-3); |
|
1553 |
} else if (mode == SLD_LOAD_GAME || mode == SLD_LOAD_SCENARIO) { |
|
1554 |
int ext = 0; // start of savegame extensions in _old_extensions[] |
|
1555 |
if (t && ((ext++, !stricmp(t, ".SS1")) || (ext++, !stricmp(t, ".SV1")) || (ext++, !stricmp(t, ".SV2"))) ) { // TTDLX(Patch) |
|
1556 |
fios = FiosAlloc(); |
|
1557 |
fios->old_extension = ext-1; |
|
1558 |
fios->mtime = *(uint64*)&fd.ftLastWriteTime; |
|
1559 |
sprintf(buf, "%s\\%s", _fios_path, fd.cFileName); |
|
1560 |
fios->type = FIOS_TYPE_OLDFILE; |
|
1561 |
GetOldSaveGameName(fios->title, buf); |
|
1562 |
ttd_strlcpy(fios->name, fd.cFileName, strlen(fd.cFileName)-3); |
|
1563 |
} |
|
1564 |
} |
|
1565 |
} |
|
1566 |
} while (FindNextFile(h, &fd)); |
|
1567 |
FindClose(h); |
|
1568 |
} |
|
1569 |
||
1570 |
qsort(_fios_items + sort_start, _fios_count - sort_start, sizeof(FiosItem), compare_FiosItems); |
|
1571 |
||
1572 |
// Drives |
|
1573 |
{ |
|
1574 |
char drives[256]; |
|
1575 |
char *s; |
|
1576 |
GetLogicalDriveStrings(sizeof(drives), drives); |
|
1577 |
s=drives; |
|
1578 |
while (*s) { |
|
1579 |
fios = FiosAlloc(); |
|
1580 |
fios->type = FIOS_TYPE_DRIVE; |
|
1581 |
fios->title[0] = s[0]; |
|
1582 |
fios->title[1] = ':'; |
|
1583 |
fios->title[2] = 0; |
|
1584 |
while (*s++) {} |
|
1585 |
} |
|
1586 |
} |
|
1587 |
*num = _fios_count; |
|
1588 |
return _fios_items; |
|
1589 |
} |
|
1590 |
||
1591 |
// Get a list of scenarios |
|
1592 |
FiosItem *FiosGetScenarioList(int *num, int mode) |
|
1593 |
{ |
|
1594 |
FiosItem *fios; |
|
1595 |
WIN32_FIND_DATA fd; |
|
1596 |
HANDLE h; |
|
1597 |
int sort_start; |
|
1598 |
char buf[MAX_PATH]; |
|
1599 |
||
1600 |
if (mode == SLD_NEW_GAME || _fios_scn_path == NULL) { |
|
1601 |
if (_fios_scn_path == NULL) |
|
1602 |
_fios_scn_path = malloc(MAX_PATH); |
|
1603 |
strcpy(_fios_scn_path, _path.scenario_dir); |
|
1604 |
} |
|
1605 |
||
1606 |
_fios_path = _fios_scn_path; |
|
1607 |
||
1608 |
// Parent directory, only if not of the type C:\. |
|
1609 |
if (_fios_path[3] != 0 && mode != SLD_NEW_GAME) { |
|
1610 |
fios = FiosAlloc(); |
|
1611 |
fios->type = FIOS_TYPE_PARENT; |
|
1612 |
strcpy(fios->title, ".. (Parent directory)"); |
|
1613 |
} |
|
1614 |
||
1615 |
// Show subdirectories first |
|
1616 |
h = MyFindFirstFile(_fios_scn_path, "*.*", &fd); |
|
1617 |
if (h != INVALID_HANDLE_VALUE && mode != SLD_NEW_GAME) { |
|
1618 |
do { |
|
1619 |
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && |
|
1620 |
!(fd.cFileName[0]=='.' && (fd.cFileName[1]==0 || fd.cFileName[1]=='.' && fd.cFileName[2]==0))) { |
|
1621 |
fios = FiosAlloc(); |
|
1622 |
fios->type = FIOS_TYPE_DIR; |
|
1623 |
strcpy(fios->name, fd.cFileName); |
|
1624 |
sprintf(fios->title, "\\%s (Directory)", fd.cFileName); |
|
1625 |
} |
|
1626 |
} while (FindNextFile(h, &fd)); |
|
1627 |
FindClose(h); |
|
1628 |
} |
|
1629 |
||
1630 |
// this is where to start sorting |
|
1631 |
sort_start = _fios_count; |
|
1632 |
||
1633 |
/* Show scenario files |
|
1634 |
* .SCN OpenTTD style scenario file |
|
1635 |
* .SV0 Transport Tycoon Deluxe (Patch) scenario |
|
1636 |
* .SS0 Transport Tycoon Deluxe preset scenario |
|
1637 |
*/ |
|
1638 |
h = MyFindFirstFile(_fios_scn_path, "*.*", &fd); |
|
1639 |
if (h != INVALID_HANDLE_VALUE) { |
|
1640 |
do { |
|
1641 |
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { |
|
1642 |
char *t = strrchr(fd.cFileName, '.'); |
|
1643 |
if (t && !stricmp(t, ".SCN")) { // OpenTTD |
|
1644 |
fios = FiosAlloc(); |
|
1645 |
fios->mtime = *(uint64*)&fd.ftLastWriteTime; |
|
1646 |
sprintf(buf, "%s\\%s", _fios_path, fd.cFileName); |
|
1647 |
fios->type = FIOS_TYPE_SCENARIO; |
|
1648 |
fios->title[0] = 0; |
|
1649 |
ttd_strlcpy(fios->name, fd.cFileName, strlen(fd.cFileName)-3); |
|
1650 |
} else if (mode == SLD_LOAD_GAME || mode == SLD_LOAD_SCENARIO || mode == SLD_NEW_GAME) { |
|
1651 |
int ext = 3; // start of scenario extensions in _old_extensions[] |
|
1652 |
if (t && ((ext++, !stricmp(t, ".SV0")) || (ext++, !stricmp(t, ".SS0"))) ) { // TTDLX(Patch) |
|
1653 |
fios = FiosAlloc(); |
|
1654 |
fios->old_extension = ext-1; |
|
1655 |
fios->mtime = *(uint64*)&fd.ftLastWriteTime; |
|
1656 |
sprintf(buf, "%s\\%s", _fios_path, fd.cFileName); |
|
1657 |
fios->type = FIOS_TYPE_OLD_SCENARIO; |
|
1658 |
GetOldScenarioGameName(fios->title, buf); |
|
1659 |
ttd_strlcpy(fios->name, fd.cFileName, strlen(fd.cFileName)-3); |
|
1660 |
} |
|
1661 |
} |
|
1662 |
} |
|
1663 |
} while (FindNextFile(h, &fd)); |
|
1664 |
FindClose(h); |
|
1665 |
} |
|
1666 |
||
1667 |
qsort(_fios_items + sort_start, _fios_count - sort_start, sizeof(FiosItem), compare_FiosItems); |
|
1668 |
||
1669 |
// Drives |
|
1670 |
if (mode != SLD_NEW_GAME) { |
|
1671 |
char drives[256]; |
|
1672 |
char *s; |
|
1673 |
GetLogicalDriveStrings(sizeof(drives), drives); |
|
1674 |
s=drives; |
|
1675 |
while (*s) { |
|
1676 |
fios = FiosAlloc(); |
|
1677 |
fios->type = FIOS_TYPE_DRIVE; |
|
1678 |
fios->title[0] = s[0]; |
|
1679 |
fios->title[1] = ':'; |
|
1680 |
fios->title[2] = 0; |
|
1681 |
while (*s++) {} |
|
1682 |
} |
|
1683 |
} |
|
1684 |
||
1685 |
*num = _fios_count; |
|
1686 |
return _fios_items; |
|
1687 |
} |
|
1688 |
||
1689 |
// Free the list of savegames |
|
1690 |
void FiosFreeSavegameList() |
|
1691 |
{ |
|
1692 |
free(_fios_items); |
|
1693 |
_fios_items = NULL; |
|
1694 |
_fios_alloc = _fios_count = 0; |
|
1695 |
} |
|
1696 |
||
1697 |
// Browse to |
|
1698 |
char *FiosBrowseTo(const FiosItem *item) |
|
1699 |
{ |
|
1700 |
char *path = _fios_path; |
|
1701 |
char *s; |
|
1702 |
||
1703 |
switch(item->type) { |
|
1704 |
case FIOS_TYPE_DRIVE: |
|
1705 |
sprintf(path, "%c:\\", item->title[0]); |
|
1706 |
break; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1707 |
|
0 | 1708 |
case FIOS_TYPE_PARENT: |
1709 |
// Skip drive part |
|
1710 |
path += 3; |
|
1711 |
s = path; |
|
1712 |
while (*path) { |
|
1713 |
if (*path== '\\') |
|
1714 |
s = path; |
|
1715 |
path++; |
|
1716 |
} |
|
1717 |
*s = 0; |
|
1718 |
break; |
|
1719 |
||
1720 |
case FIOS_TYPE_DIR: |
|
1721 |
// Scan to end |
|
1722 |
while (*++path); |
|
1723 |
// Add backslash? |
|
1724 |
if (path[-1] != '\\') *path++ = '\\'; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1725 |
|
0 | 1726 |
strcpy(path, item->name); |
1727 |
break; |
|
1728 |
||
1729 |
case FIOS_TYPE_FILE: |
|
1730 |
FiosMakeSavegameName(str_buffr, item->name); |
|
1731 |
return str_buffr; |
|
1732 |
||
1733 |
case FIOS_TYPE_OLDFILE: |
|
1734 |
sprintf(str_buffr, "%s\\%s.%s", _fios_path, item->name, _old_extensions[item->old_extension]); |
|
1735 |
return str_buffr; |
|
1736 |
||
1737 |
case FIOS_TYPE_SCENARIO: |
|
1738 |
sprintf(str_buffr, "%s\\%s.scn", path, item->name); |
|
1739 |
return str_buffr; |
|
1740 |
case FIOS_TYPE_OLD_SCENARIO: |
|
1741 |
sprintf(str_buffr, "%s\\%s.%s", path, item->name, _old_extensions[item->old_extension]); |
|
1742 |
return str_buffr; |
|
1743 |
} |
|
1744 |
||
1745 |
return NULL; |
|
1746 |
} |
|
1747 |
||
1748 |
// Get descriptive texts. |
|
1749 |
// Returns a path as well as a |
|
1750 |
// string describing the path. |
|
222
b88456001397
(svn r223) -Fix: Const correctness and miscellaneous fixes. Thank you Tron for your diligent fixing of warnings (and some possibly bugs) (Tron)
darkvater
parents:
206
diff
changeset
|
1751 |
StringID FiosGetDescText(const char **path) |
0 | 1752 |
{ |
1753 |
char root[4]; |
|
1754 |
DWORD spc, bps, nfc, tnc; |
|
1755 |
*path = _fios_path; |
|
1756 |
||
1757 |
root[0] = _fios_path[0]; |
|
1758 |
root[1] = ':'; |
|
1759 |
root[2] = '\\'; |
|
1760 |
root[3] = 0; |
|
1761 |
if (GetDiskFreeSpace(root, &spc, &bps, &nfc, &tnc)) { |
|
1762 |
uint32 tot = ((spc*bps)*(uint64)nfc) >> 20; |
|
1763 |
SET_DPARAM32(0, tot); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1764 |
return STR_4005_BYTES_FREE; |
0 | 1765 |
} else { |
1766 |
return STR_4006_UNABLE_TO_READ_DRIVE; |
|
1767 |
} |
|
1768 |
} |
|
1769 |
||
1770 |
void FiosMakeSavegameName(char *buf, const char *name) |
|
1771 |
{ |
|
1772 |
if(_game_mode == GM_EDITOR) |
|
1773 |
sprintf(buf, "%s\\%s.scn", _fios_path, name); |
|
1774 |
else |
|
1775 |
sprintf(buf, "%s\\%s.sav", _fios_path, name); |
|
1776 |
} |
|
1777 |
||
1778 |
void FiosDelete(const char *name) |
|
1779 |
{ |
|
1780 |
char *path = str_buffr; |
|
1781 |
FiosMakeSavegameName(path, name); |
|
1782 |
DeleteFile(path); |
|
1783 |
} |
|
1784 |
||
223
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1785 |
#define Windows_2000 5 |
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1786 |
#define Windows_NT3_51 4 |
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1787 |
|
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1788 |
/* flags show the minimum required OS to use a given feature. Currently |
287
ca9584af45a0
(svn r293) -Feature: Windows now shows (available) revision, release information in title bar
darkvater
parents:
223
diff
changeset
|
1789 |
only dwMajorVersion and dwMinorVersion (WindowsME) are used |
223
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1790 |
MajorVersion MinorVersion |
287
ca9584af45a0
(svn r293) -Feature: Windows now shows (available) revision, release information in title bar
darkvater
parents:
223
diff
changeset
|
1791 |
Windows Server 2003 5 2 dmusic |
ca9584af45a0
(svn r293) -Feature: Windows now shows (available) revision, release information in title bar
darkvater
parents:
223
diff
changeset
|
1792 |
Windows XP 5 1 dmusic |
ca9584af45a0
(svn r293) -Feature: Windows now shows (available) revision, release information in title bar
darkvater
parents:
223
diff
changeset
|
1793 |
Windows 2000 5 0 dmusic |
ca9584af45a0
(svn r293) -Feature: Windows now shows (available) revision, release information in title bar
darkvater
parents:
223
diff
changeset
|
1794 |
Windows NT 4.0 4 0 win32 |
ca9584af45a0
(svn r293) -Feature: Windows now shows (available) revision, release information in title bar
darkvater
parents:
223
diff
changeset
|
1795 |
Windows Me 4 90 dmusic |
ca9584af45a0
(svn r293) -Feature: Windows now shows (available) revision, release information in title bar
darkvater
parents:
223
diff
changeset
|
1796 |
Windows 98 4 10 win32 |
ca9584af45a0
(svn r293) -Feature: Windows now shows (available) revision, release information in title bar
darkvater
parents:
223
diff
changeset
|
1797 |
Windows 95 4 0 win32 |
ca9584af45a0
(svn r293) -Feature: Windows now shows (available) revision, release information in title bar
darkvater
parents:
223
diff
changeset
|
1798 |
Windows NT 3.51 3 51 ????? |
223
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1799 |
*/ |
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1800 |
|
0 | 1801 |
const DriverDesc _video_driver_descs[] = { |
223
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1802 |
{"null", "Null Video Driver", &_null_video_driver, 0}, |
0 | 1803 |
#if defined(WITH_SDL) |
223
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1804 |
{"sdl", "SDL Video Driver", &_sdl_video_driver, 1}, |
0 | 1805 |
#endif |
223
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1806 |
{"win32", "Win32 GDI Video Driver", &_win32_video_driver, Windows_NT3_51}, |
0 | 1807 |
{NULL} |
1808 |
}; |
|
1809 |
||
1810 |
const DriverDesc _sound_driver_descs[] = { |
|
1811 |
{"null", "Null Sound Driver", &_null_sound_driver, 0}, |
|
1812 |
#if defined(WITH_SDL) |
|
223
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1813 |
{"sdl", "SDL Sound Driver", &_sdl_sound_driver, 1}, |
0 | 1814 |
#endif |
223
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1815 |
{"win32", "Win32 WaveOut Driver", &_win32_sound_driver, Windows_NT3_51}, |
0 | 1816 |
{NULL} |
1817 |
}; |
|
1818 |
||
1819 |
const DriverDesc _music_driver_descs[] = { |
|
223
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1820 |
{"null", "Null Music Driver", &_null_music_driver, 0}, |
0 | 1821 |
#ifdef WIN32_ENABLE_DIRECTMUSIC_SUPPORT |
223
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1822 |
{"dmusic", "DirectMusic MIDI Driver", &_dmusic_midi_driver, Windows_2000}, |
0 | 1823 |
#endif |
223
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1824 |
// Win32 MIDI driver has higher priority then DMusic, so this one is chosen |
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1825 |
{"win32", "Win32 MIDI Driver", &_win32_music_driver, Windows_NT3_51}, |
0 | 1826 |
{NULL} |
1827 |
}; |
|
1828 |
||
223
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1829 |
byte GetOSVersion() |
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1830 |
{ |
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1831 |
OSVERSIONINFO osvi; |
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1832 |
|
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1833 |
ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); |
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1834 |
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); |
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1835 |
|
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1836 |
if (GetVersionEx(&osvi)) { |
287
ca9584af45a0
(svn r293) -Feature: Windows now shows (available) revision, release information in title bar
darkvater
parents:
223
diff
changeset
|
1837 |
DEBUG(misc, 2) ("Windows Version is %d.%d", osvi.dwMajorVersion, osvi.dwMinorVersion); |
ca9584af45a0
(svn r293) -Feature: Windows now shows (available) revision, release information in title bar
darkvater
parents:
223
diff
changeset
|
1838 |
// WinME needs directmusic too (dmusic, Windows_2000 mode), all others default to OK |
ca9584af45a0
(svn r293) -Feature: Windows now shows (available) revision, release information in title bar
darkvater
parents:
223
diff
changeset
|
1839 |
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) { return Windows_2000;} // WinME |
ca9584af45a0
(svn r293) -Feature: Windows now shows (available) revision, release information in title bar
darkvater
parents:
223
diff
changeset
|
1840 |
|
ca9584af45a0
(svn r293) -Feature: Windows now shows (available) revision, release information in title bar
darkvater
parents:
223
diff
changeset
|
1841 |
return osvi.dwMajorVersion; |
223
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1842 |
} |
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1843 |
|
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1844 |
// GetVersionEx failed, but we can safely assume at least Win95/WinNT3.51 is used |
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1845 |
DEBUG(misc, 0) ("Windows version retrieval failed, defaulting to level 4"); |
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1846 |
return Windows_NT3_51; |
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1847 |
} |
0e5cc5a65df6
(svn r224) -Fix: Music now finally works on WinXP. DirectMusic is now default for an OS >= WinNT4 (WinNT4, Win2k, WinXP), and MIDI driver for lower OS's (Win95, Win98, WinME, etc).
darkvater
parents:
222
diff
changeset
|
1848 |
|
0 | 1849 |
bool FileExists(const char *filename) |
1850 |
{ |
|
1851 |
HANDLE hand = CreateFile(filename, 0, 0, NULL, OPEN_EXISTING, 0, NULL); |
|
1852 |
if (hand == INVALID_HANDLE_VALUE) return false; |
|
1853 |
CloseHandle(hand); |
|
1854 |
return true; |
|
1855 |
} |
|
1856 |
||
1857 |
static int CDECL LanguageCompareFunc(const void *a, const void *b) |
|
1858 |
{ |
|
222
b88456001397
(svn r223) -Fix: Const correctness and miscellaneous fixes. Thank you Tron for your diligent fixing of warnings (and some possibly bugs) (Tron)
darkvater
parents:
206
diff
changeset
|
1859 |
return strcmp(*(const char* const *)a, *(const char* const *)b); |
0 | 1860 |
} |
1861 |
||
1862 |
int GetLanguageList(char **languages, int max) |
|
1863 |
{ |
|
1864 |
HANDLE hand; |
|
1865 |
int num = 0; |
|
1866 |
char filedir[MAX_PATH]; |
|
1867 |
WIN32_FIND_DATA fd; |
|
1868 |
sprintf(filedir, "%s*.lng", _path.lang_dir); |
|
1869 |
||
1870 |
hand = FindFirstFile(filedir, &fd); |
|
1871 |
if (hand != INVALID_HANDLE_VALUE) { |
|
1872 |
do { |
|
1873 |
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { |
|
1874 |
languages[num++] = strdup(fd.cFileName); |
|
1875 |
if (num == max) break; |
|
1876 |
} |
|
1877 |
} while (FindNextFile(hand, &fd)); |
|
1878 |
FindClose(hand); |
|
1879 |
} |
|
1880 |
||
1881 |
qsort(languages, num, sizeof(char*), LanguageCompareFunc); |
|
1882 |
return num; |
|
1883 |
} |
|
1884 |
||
1885 |
static int ParseCommandLine(char *line, char **argv, int max_argc) |
|
1886 |
{ |
|
1887 |
int n = 0; |
|
1888 |
||
1889 |
do { |
|
1890 |
// skip whitespace |
|
1891 |
while (*line == ' ' || *line == '\t') |
|
1892 |
line++; |
|
1893 |
||
1894 |
// end? |
|
1895 |
if (*line == 0) |
|
1896 |
break; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1897 |
|
0 | 1898 |
// special handling when quoted |
1899 |
if (*line == '"') { |
|
1900 |
argv[n++] = ++line; |
|
1901 |
while (*line != '"') { |
|
1902 |
if (*line == 0) return n; |
|
1903 |
line++; |
|
1904 |
} |
|
1905 |
} else { |
|
1906 |
argv[n++] = line; |
|
1907 |
while (*line != ' ' && *line != '\t') { |
|
1908 |
if (*line == 0) return n; |
|
1909 |
line++; |
|
1910 |
} |
|
1911 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1912 |
*line++ = 0; |
0 | 1913 |
} while (n != max_argc); |
1914 |
||
1915 |
return n; |
|
1916 |
} |
|
1917 |
||
1918 |
||
1919 |
#if defined(_MSC_VER) |
|
1920 |
__int64 _declspec(naked) rdtsc() |
|
1921 |
{ |
|
1922 |
_asm { |
|
1923 |
rdtsc |
|
1924 |
ret |
|
1925 |
} |
|
1926 |
} |
|
1927 |
#endif |
|
1928 |
||
1929 |
void CreateConsole() |
|
1930 |
{ |
|
1931 |
HANDLE hand; |
|
1932 |
CONSOLE_SCREEN_BUFFER_INFO coninfo; |
|
1933 |
||
1934 |
if (_has_console) return; |
|
1935 |
||
1936 |
_has_console = true; |
|
1937 |
||
1938 |
AllocConsole(); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1939 |
|
0 | 1940 |
hand = GetStdHandle(STD_OUTPUT_HANDLE); |
1941 |
GetConsoleScreenBufferInfo(hand, &coninfo); |
|
1942 |
coninfo.dwSize.Y = 500; |
|
1943 |
SetConsoleScreenBufferSize(hand, coninfo.dwSize); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1944 |
|
0 | 1945 |
// redirect unbuffered STDIN, STDOUT, STDERR to the console |
1946 |
#if !defined(__CYGWIN__) |
|
1947 |
*stdout = *_fdopen( _open_osfhandle((long)hand, _O_TEXT), "w" ); |
|
1948 |
*stdin = *_fdopen(_open_osfhandle((long)GetStdHandle(STD_INPUT_HANDLE), _O_TEXT), "w" ); |
|
1949 |
*stderr = *_fdopen(_open_osfhandle((long)GetStdHandle(STD_ERROR_HANDLE), _O_TEXT), "w" ); |
|
1950 |
#else |
|
1951 |
// open_osfhandle is not in cygwin |
|
1952 |
*stdout = *fdopen(1, "w" ); |
|
1953 |
*stdin = *fdopen(0, "w" ); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1954 |
*stderr = *fdopen(2, "w" ); |
0 | 1955 |
#endif |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1956 |
|
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1957 |
setvbuf( stdin, NULL, _IONBF, 0 ); |
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1958 |
setvbuf( stdout, NULL, _IONBF, 0 ); |
0 | 1959 |
setvbuf( stderr, NULL, _IONBF, 0 ); |
1960 |
} |
|
1961 |
||
1962 |
void ShowInfo(const char *str) |
|
1963 |
{ |
|
1964 |
if (_has_console) |
|
1965 |
puts(str); |
|
1966 |
else { |
|
1967 |
bool old; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1968 |
|
0 | 1969 |
ReleaseCapture(); |
1970 |
_left_button_clicked =_left_button_down = false; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
1971 |
|
0 | 1972 |
old = MyShowCursor(true); |
1973 |
if (MessageBoxA(GetActiveWindow(), str, "OpenTTD", MB_ICONINFORMATION | MB_OKCANCEL) == IDCANCEL) { |
|
1974 |
CreateConsole(); |
|
1975 |
} |
|
1976 |
MyShowCursor(old); |
|
1977 |
} |
|
1978 |
} |
|
1979 |
||
1980 |
||
1981 |
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow) |
|
1982 |
{ |
|
1983 |
int argc; |
|
1984 |
char *argv[64]; // max 64 command line arguments |
|
1985 |
_inst = hInstance; |
|
1986 |
||
1987 |
#if defined(_DEBUG) |
|
1988 |
CreateConsole(); |
|
1989 |
#endif |
|
1990 |
||
1991 |
// make sure we have an autosave folder - Done in DeterminePaths |
|
1992 |
// CreateDirectory("autosave", NULL); |
|
1993 |
||
1994 |
// setup random seed to something quite random |
|
1995 |
#if defined(_MSC_VER) |
|
1996 |
{ |
|
1997 |
uint64 seed = rdtsc(); |
|
206 | 1998 |
_random_seeds[0][0] = ((uint32*)&seed)[0]; |
1999 |
_random_seeds[0][1] = ((uint32*)&seed)[1]; |
|
0 | 2000 |
} |
2001 |
#else |
|
206 | 2002 |
_random_seeds[0][0] = GetTickCount(); |
2003 |
_random_seeds[0][1] = _random_seeds[0][0] * 0x1234567; |
|
0 | 2004 |
#endif |
2005 |
||
2006 |
argc = ParseCommandLine(GetCommandLine(), argv, lengthof(argv)); |
|
2007 |
||
2008 |
#if defined(WIN32_EXCEPTION_TRACKER) |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
2009 |
{ |
0 | 2010 |
Win32InitializeExceptions(); |
2011 |
} |
|
2012 |
#endif |
|
2013 |
||
2014 |
#if defined(WIN32_EXCEPTION_TRACKER_DEBUG) |
|
2015 |
_try { |
|
2016 |
uint32 _stdcall ExceptionHandler(void *ep); |
|
2017 |
#endif |
|
2018 |
ttd_main(argc, argv); |
|
2019 |
||
2020 |
#if defined(WIN32_EXCEPTION_TRACKER_DEBUG) |
|
2021 |
} _except (ExceptionHandler(_exception_info())) {} |
|
2022 |
#endif |
|
2023 |
||
2024 |
return 0; |
|
2025 |
} |
|
2026 |
||
2027 |
void DeterminePaths() |
|
2028 |
{ |
|
2029 |
char *s; |
|
2030 |
char *cfg; |
|
2031 |
||
2032 |
_path.personal_dir = _path.game_data_dir = cfg = malloc(MAX_PATH); |
|
2033 |
GetCurrentDirectory(MAX_PATH - 1, cfg); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
2034 |
|
0 | 2035 |
|
2036 |
s = strchr(cfg, 0); |
|
2037 |
if (s[-1] != '\\') { s[0] = '\\'; s[1] = 0; } |
|
2038 |
||
2039 |
_path.save_dir = str_fmt("%ssave", cfg); |
|
2040 |
_path.autosave_dir = str_fmt("%s\\autosave", _path.save_dir); |
|
2041 |
_path.scenario_dir = str_fmt("%sscenario", cfg); |
|
2042 |
_path.gm_dir = str_fmt("%sgm\\", cfg); |
|
2043 |
_path.data_dir = str_fmt("%sdata\\", cfg); |
|
2044 |
_path.lang_dir = str_fmt("%slang\\", cfg); |
|
2045 |
||
2046 |
_config_file = str_fmt("%sopenttd.cfg", _path.personal_dir); |
|
2047 |
||
2048 |
// make (auto)save and scenario folder |
|
2049 |
CreateDirectory(_path.save_dir, NULL); |
|
2050 |
CreateDirectory(_path.autosave_dir, NULL); |
|
2051 |
CreateDirectory(_path.scenario_dir, NULL); |
|
2052 |
} |
|
2053 |