author | rubidium |
Sat, 29 Nov 2008 01:28:13 +0000 | |
changeset 10390 | 0c2cc4c7b91f |
parent 10385 | 4f9838649c7f |
permissions | -rw-r--r-- |
10379 | 1 |
/* $Id$ */ |
2 |
||
3 |
/** @file allegro_v.cpp Implementation of the Allegro video driver. */ |
|
4 |
||
5 |
#ifdef WITH_ALLEGRO |
|
6 |
||
7 |
#include "../stdafx.h" |
|
8 |
#include "../openttd.h" |
|
9 |
#include "../debug.h" |
|
10 |
#include "../gfx_func.h" |
|
11 |
#include "../sdl.h" |
|
12 |
#include "../variables.h" |
|
13 |
#include "../rev.h" |
|
14 |
#include "../blitter/factory.hpp" |
|
15 |
#include "../network/network.h" |
|
16 |
#include "../core/math_func.hpp" |
|
17 |
#include "../core/random_func.hpp" |
|
18 |
#include "../functions.h" |
|
19 |
#include "../texteff.hpp" |
|
20 |
#include "allegro_v.h" |
|
21 |
#include <allegro.h> |
|
22 |
||
10390
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
23 |
#ifdef _DEBUG |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
24 |
/* Allegro replaces SEGV/ABRT signals meaning that the debugger will never |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
25 |
* be triggered, so rereplace the signals and make the debugger userful. */ |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
26 |
#include <signal.h> |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
27 |
#endif |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
28 |
|
10379 | 29 |
static FVideoDriver_Allegro iFVideoDriver_Allegro; |
30 |
||
31 |
static BITMAP *_allegro_screen; |
|
32 |
||
33 |
#define MAX_DIRTY_RECTS 100 |
|
34 |
static PointDimension _dirty_rects[MAX_DIRTY_RECTS]; |
|
35 |
static int _num_dirty_rects; |
|
36 |
||
37 |
void VideoDriver_Allegro::MakeDirty(int left, int top, int width, int height) |
|
38 |
{ |
|
39 |
if (_num_dirty_rects < MAX_DIRTY_RECTS) { |
|
40 |
_dirty_rects[_num_dirty_rects].x = left; |
|
41 |
_dirty_rects[_num_dirty_rects].y = top; |
|
42 |
_dirty_rects[_num_dirty_rects].width = width; |
|
43 |
_dirty_rects[_num_dirty_rects].height = height; |
|
44 |
} |
|
45 |
_num_dirty_rects++; |
|
46 |
} |
|
47 |
||
48 |
static void DrawSurfaceToScreen() |
|
49 |
{ |
|
50 |
int n = _num_dirty_rects; |
|
51 |
if (n == 0) return; |
|
52 |
||
53 |
_num_dirty_rects = 0; |
|
54 |
if (n > MAX_DIRTY_RECTS) { |
|
55 |
blit(_allegro_screen, screen, 0, 0, 0, 0, _allegro_screen->w, _allegro_screen->h); |
|
56 |
return; |
|
57 |
} |
|
58 |
||
59 |
for (int i = 0; i < n; i++) { |
|
60 |
blit(_allegro_screen, screen, _dirty_rects[i].x, _dirty_rects[i].y, _dirty_rects[i].x, _dirty_rects[i].y, _dirty_rects[i].width, _dirty_rects[i].height); |
|
61 |
} |
|
62 |
} |
|
63 |
||
64 |
||
65 |
static void UpdatePalette(uint start, uint count) |
|
66 |
{ |
|
67 |
static PALETTE pal; |
|
68 |
||
69 |
uint end = start + count; |
|
70 |
for (uint i = start; i != end; i++) { |
|
71 |
pal[i].r = _cur_palette[i].r / 4; |
|
72 |
pal[i].g = _cur_palette[i].g / 4; |
|
73 |
pal[i].b = _cur_palette[i].b / 4; |
|
74 |
pal[i].filler = 0; |
|
75 |
} |
|
76 |
||
77 |
set_palette_range(pal, start, end - 1, 1); |
|
78 |
} |
|
79 |
||
80 |
static void InitPalette() |
|
81 |
{ |
|
82 |
UpdatePalette(0, 256); |
|
83 |
} |
|
84 |
||
85 |
static void CheckPaletteAnim() |
|
86 |
{ |
|
87 |
if (_pal_count_dirty != 0) { |
|
88 |
Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter(); |
|
89 |
||
90 |
switch (blitter->UsePaletteAnimation()) { |
|
91 |
case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND: |
|
92 |
UpdatePalette(_pal_first_dirty, _pal_count_dirty); |
|
93 |
break; |
|
94 |
||
95 |
case Blitter::PALETTE_ANIMATION_BLITTER: |
|
96 |
blitter->PaletteAnimate(_pal_first_dirty, _pal_count_dirty); |
|
97 |
break; |
|
98 |
||
99 |
case Blitter::PALETTE_ANIMATION_NONE: |
|
100 |
break; |
|
101 |
||
102 |
default: |
|
103 |
NOT_REACHED(); |
|
104 |
} |
|
105 |
_pal_count_dirty = 0; |
|
106 |
} |
|
107 |
} |
|
108 |
||
109 |
static const Dimension default_resolutions[] = { |
|
110 |
{ 640, 480}, |
|
111 |
{ 800, 600}, |
|
112 |
{1024, 768}, |
|
113 |
{1152, 864}, |
|
114 |
{1280, 800}, |
|
115 |
{1280, 960}, |
|
116 |
{1280, 1024}, |
|
117 |
{1400, 1050}, |
|
118 |
{1600, 1200}, |
|
119 |
{1680, 1050}, |
|
120 |
{1920, 1200} |
|
121 |
}; |
|
122 |
||
123 |
static void GetVideoModes() |
|
124 |
{ |
|
125 |
/* Need to set a gfx_mode as there is NO other way to autodetect for |
|
126 |
* cards ourselves... and we need a card to get the modes. */ |
|
127 |
set_gfx_mode(_fullscreen ? GFX_AUTODETECT_FULLSCREEN : GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0); |
|
128 |
||
129 |
GFX_MODE_LIST *mode_list = get_gfx_mode_list(gfx_driver->id); |
|
130 |
if (mode_list == NULL) { |
|
131 |
memcpy(_resolutions, default_resolutions, sizeof(default_resolutions)); |
|
132 |
_num_resolutions = lengthof(default_resolutions); |
|
133 |
return; |
|
134 |
} |
|
135 |
||
136 |
GFX_MODE *modes = mode_list->mode; |
|
137 |
||
138 |
int n = 0; |
|
139 |
for (int i = 0; modes[i].bpp != 0; i++) { |
|
140 |
int w = modes[i].width; |
|
141 |
int h = modes[i].height; |
|
142 |
if (w >= 640 && h >= 480) { |
|
143 |
int j; |
|
144 |
for (j = 0; j < n; j++) { |
|
145 |
if (_resolutions[j].width == w && _resolutions[j].height == h) break; |
|
146 |
} |
|
147 |
||
148 |
if (j == n) { |
|
149 |
_resolutions[j].width = w; |
|
150 |
_resolutions[j].height = h; |
|
151 |
if (++n == lengthof(_resolutions)) break; |
|
152 |
} |
|
153 |
} |
|
154 |
} |
|
155 |
_num_resolutions = n; |
|
156 |
SortResolutions(_num_resolutions); |
|
157 |
||
158 |
destroy_gfx_mode_list(mode_list); |
|
159 |
} |
|
160 |
||
161 |
static void GetAvailableVideoMode(int *w, int *h) |
|
162 |
{ |
|
10390
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
163 |
/* No video modes, so just try it and see where it ends */ |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
164 |
if (_num_resolutions == 0) return; |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
165 |
|
10379 | 166 |
/* is the wanted mode among the available modes? */ |
167 |
for (int i = 0; i != _num_resolutions; i++) { |
|
168 |
if (*w == _resolutions[i].width && *h == _resolutions[i].height) return; |
|
169 |
} |
|
170 |
||
171 |
/* use the closest possible resolution */ |
|
172 |
int best = 0; |
|
173 |
uint delta = abs((_resolutions[0].width - *w) * (_resolutions[0].height - *h)); |
|
174 |
for (int i = 1; i != _num_resolutions; ++i) { |
|
175 |
uint newdelta = abs((_resolutions[i].width - *w) * (_resolutions[i].height - *h)); |
|
176 |
if (newdelta < delta) { |
|
177 |
best = i; |
|
178 |
delta = newdelta; |
|
179 |
} |
|
180 |
} |
|
181 |
*w = _resolutions[best].width; |
|
182 |
*h = _resolutions[best].height; |
|
183 |
} |
|
184 |
||
185 |
static bool CreateMainSurface(int w, int h) |
|
186 |
{ |
|
187 |
int bpp = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth(); |
|
188 |
if (bpp == 0) usererror("Can't use a blitter that blits 0 bpp for normal visuals"); |
|
189 |
set_color_depth(bpp); |
|
190 |
||
10390
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
191 |
GetAvailableVideoMode(&w, &h); |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
192 |
if (set_gfx_mode(_fullscreen ? GFX_AUTODETECT_FULLSCREEN : GFX_AUTODETECT_WINDOWED, w, h, 0, 0) != 0) { |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
193 |
DEBUG(driver, 0, "Allegro: Couldn't allocate a window to draw on"); |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
194 |
return false; |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
195 |
} |
10385
4f9838649c7f
(svn r14636) -Add: DOS port of OpenTTD, without network support though.
rubidium
parents:
10381
diff
changeset
|
196 |
|
10390
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
197 |
/* The size of the screen might be bigger than the part we can actually draw on! |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
198 |
* So calculate the size based on the top, bottom, left and right */ |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
199 |
_allegro_screen = create_bitmap_ex(bpp, screen->cr - screen->cl, screen->cb - screen->ct); |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
200 |
_screen.width = _allegro_screen->w; |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
201 |
_screen.height = _allegro_screen->h; |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
202 |
_screen.pitch = ((byte*)screen->line[1] - (byte*)screen->line[0]) / (bpp / 8); |
10379 | 203 |
|
10390
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
204 |
/* Initialise the screen so we don't blit garbage to the screen */ |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
205 |
memset(_allegro_screen->line[0], 0, _screen.height * _screen.pitch); |
10379 | 206 |
|
10390
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
207 |
/* Set the mouse at the place where we expect it */ |
10379 | 208 |
poll_mouse(); |
209 |
_cursor.pos.x = mouse_x; |
|
210 |
_cursor.pos.y = mouse_y; |
|
211 |
||
212 |
InitPalette(); |
|
213 |
||
214 |
char caption[32]; |
|
215 |
snprintf(caption, sizeof(caption), "OpenTTD %s", _openttd_revision); |
|
216 |
set_window_title(caption); |
|
217 |
||
218 |
GameSizeChanged(); |
|
219 |
||
220 |
return true; |
|
221 |
} |
|
222 |
||
223 |
struct VkMapping { |
|
224 |
uint16 vk_from; |
|
225 |
byte vk_count; |
|
226 |
byte map_to; |
|
227 |
}; |
|
228 |
||
229 |
#define AS(x, z) {x, 0, z} |
|
230 |
#define AM(x, y, z, w) {x, y - x, z} |
|
231 |
||
232 |
static const VkMapping _vk_mapping[] = { |
|
233 |
/* Pageup stuff + up/down */ |
|
234 |
AM(KEY_PGUP, KEY_PGDN, WKC_PAGEUP, WKC_PAGEDOWN), |
|
235 |
AS(KEY_UP, WKC_UP), |
|
236 |
AS(KEY_DOWN, WKC_DOWN), |
|
237 |
AS(KEY_LEFT, WKC_LEFT), |
|
238 |
AS(KEY_RIGHT, WKC_RIGHT), |
|
239 |
||
240 |
AS(KEY_HOME, WKC_HOME), |
|
241 |
AS(KEY_END, WKC_END), |
|
242 |
||
243 |
AS(KEY_INSERT, WKC_INSERT), |
|
244 |
AS(KEY_DEL, WKC_DELETE), |
|
245 |
||
246 |
/* Map letters & digits */ |
|
247 |
AM(KEY_A, KEY_Z, 'A', 'Z'), |
|
248 |
AM(KEY_0, KEY_9, '0', '9'), |
|
249 |
||
250 |
AS(KEY_ESC, WKC_ESC), |
|
251 |
AS(KEY_PAUSE, WKC_PAUSE), |
|
252 |
AS(KEY_BACKSPACE, WKC_BACKSPACE), |
|
253 |
||
254 |
AS(KEY_SPACE, WKC_SPACE), |
|
255 |
AS(KEY_ENTER, WKC_RETURN), |
|
256 |
AS(KEY_TAB, WKC_TAB), |
|
257 |
||
258 |
/* Function keys */ |
|
259 |
AM(KEY_F1, KEY_F12, WKC_F1, WKC_F12), |
|
260 |
||
261 |
/* Numeric part. */ |
|
262 |
AM(KEY_0_PAD, KEY_9_PAD, '0', '9'), |
|
263 |
AS(KEY_SLASH_PAD, WKC_NUM_DIV), |
|
264 |
AS(KEY_ASTERISK, WKC_NUM_MUL), |
|
265 |
AS(KEY_MINUS_PAD, WKC_NUM_MINUS), |
|
266 |
AS(KEY_PLUS_PAD, WKC_NUM_PLUS), |
|
267 |
AS(KEY_ENTER_PAD, WKC_NUM_ENTER), |
|
268 |
AS(KEY_DEL_PAD, WKC_DELETE), |
|
269 |
||
270 |
/* Other non-letter keys */ |
|
271 |
AS(KEY_SLASH, WKC_SLASH), |
|
272 |
AS(KEY_SEMICOLON, WKC_SEMICOLON), |
|
273 |
AS(KEY_EQUALS, WKC_EQUALS), |
|
274 |
AS(KEY_OPENBRACE, WKC_L_BRACKET), |
|
275 |
AS(KEY_BACKSLASH, WKC_BACKSLASH), |
|
276 |
AS(KEY_CLOSEBRACE, WKC_R_BRACKET), |
|
277 |
||
278 |
AS(KEY_QUOTE, WKC_SINGLEQUOTE), |
|
279 |
AS(KEY_COMMA, WKC_COMMA), |
|
280 |
AS(KEY_MINUS, WKC_MINUS), |
|
281 |
AS(KEY_STOP, WKC_PERIOD), |
|
282 |
AS(KEY_TILDE, WKC_BACKQUOTE), |
|
283 |
}; |
|
284 |
||
285 |
static uint32 ConvertAllegroKeyIntoMy() |
|
286 |
{ |
|
287 |
int scancode; |
|
288 |
int unicode = ureadkey(&scancode); |
|
289 |
||
290 |
const VkMapping *map; |
|
291 |
uint key = 0; |
|
292 |
||
293 |
for (map = _vk_mapping; map != endof(_vk_mapping); ++map) { |
|
294 |
if ((uint)(scancode - map->vk_from) <= map->vk_count) { |
|
295 |
key = scancode - map->vk_from + map->map_to; |
|
296 |
break; |
|
297 |
} |
|
298 |
} |
|
299 |
||
300 |
if (key_shifts & KB_SHIFT_FLAG) key |= WKC_SHIFT; |
|
301 |
if (key_shifts & KB_CTRL_FLAG) key |= WKC_CTRL; |
|
302 |
if (key_shifts & KB_ALT_FLAG) key |= WKC_ALT; |
|
303 |
#if 0 |
|
304 |
DEBUG(driver, 0, "Scancode character pressed %u", scancode); |
|
305 |
DEBUG(driver, 0, "Unicode character pressed %u", unicode); |
|
306 |
#endif |
|
307 |
return (key << 16) + unicode; |
|
308 |
} |
|
309 |
||
310 |
enum { |
|
311 |
LEFT_BUTTON, |
|
312 |
RIGHT_BUTTON, |
|
313 |
}; |
|
314 |
||
315 |
static void PollEvent() |
|
316 |
{ |
|
317 |
poll_mouse(); |
|
318 |
||
319 |
bool mouse_action = false; |
|
320 |
||
321 |
/* Mouse buttons */ |
|
322 |
static int prev_button_state; |
|
323 |
if (prev_button_state != mouse_b) { |
|
324 |
uint diff = prev_button_state ^ mouse_b; |
|
325 |
while (diff != 0) { |
|
326 |
int button = FindFirstBit(diff); |
|
327 |
ClrBit(diff, button); |
|
328 |
if (HasBit(mouse_b, button)) { |
|
329 |
/* Pressed mouse button */ |
|
330 |
if (_rightclick_emulate && key_shifts & KB_CTRL_FLAG) { |
|
331 |
button = RIGHT_BUTTON; |
|
332 |
ClrBit(diff, RIGHT_BUTTON); |
|
333 |
} |
|
334 |
switch (button) { |
|
335 |
case LEFT_BUTTON: |
|
336 |
_left_button_down = true; |
|
337 |
break; |
|
338 |
||
339 |
case RIGHT_BUTTON: |
|
340 |
_right_button_down = true; |
|
341 |
_right_button_clicked = true; |
|
342 |
break; |
|
343 |
||
344 |
default: |
|
345 |
/* ignore rest */ |
|
346 |
break; |
|
347 |
} |
|
348 |
} else { |
|
349 |
/* Released mouse button */ |
|
350 |
if (_rightclick_emulate) { |
|
351 |
_right_button_down = false; |
|
352 |
_left_button_down = false; |
|
353 |
_left_button_clicked = false; |
|
354 |
} else if (button == LEFT_BUTTON) { |
|
355 |
_left_button_down = false; |
|
356 |
_left_button_clicked = false; |
|
357 |
} else if (button == RIGHT_BUTTON) { |
|
358 |
_right_button_down = false; |
|
359 |
} |
|
360 |
} |
|
361 |
} |
|
362 |
prev_button_state = mouse_b; |
|
363 |
mouse_action = true; |
|
364 |
} |
|
365 |
||
366 |
/* Mouse movement */ |
|
367 |
int dx = mouse_x - _cursor.pos.x; |
|
368 |
int dy = mouse_y - _cursor.pos.y; |
|
369 |
if (dx != 0 || dy != 0) { |
|
370 |
if (_cursor.fix_at) { |
|
371 |
_cursor.delta.x += dx; |
|
372 |
_cursor.delta.y += dy; |
|
373 |
position_mouse(_cursor.pos.x, _cursor.pos.y); |
|
374 |
} else { |
|
375 |
_cursor.delta.x = dx; |
|
376 |
_cursor.delta.y = dy; |
|
377 |
_cursor.pos.x = mouse_x; |
|
378 |
_cursor.pos.y = mouse_y; |
|
379 |
_cursor.dirty = true; |
|
380 |
} |
|
381 |
mouse_action = true; |
|
382 |
} |
|
383 |
||
384 |
if (mouse_action) HandleMouseEvents(); |
|
385 |
||
386 |
poll_keyboard(); |
|
387 |
if (key_shifts & KB_ALT_FLAG && (key[KEY_ENTER] || key[KEY_F])) { |
|
388 |
ToggleFullScreen(!_fullscreen); |
|
389 |
} else if (keypressed()) { |
|
390 |
HandleKeypress(ConvertAllegroKeyIntoMy()); |
|
391 |
} |
|
392 |
} |
|
393 |
||
10380
f4adb9648a93
(svn r14631) -Add: support for Allegro as sound backend.
rubidium
parents:
10379
diff
changeset
|
394 |
/** There are multiple modules that might be using Allegro and |
f4adb9648a93
(svn r14631) -Add: support for Allegro as sound backend.
rubidium
parents:
10379
diff
changeset
|
395 |
* Allegro can only be initiated once. */ |
10381
c043aa0c1695
(svn r14632) -Add: support Allegro as midi backend.
rubidium
parents:
10380
diff
changeset
|
396 |
int _allegro_instance_count = 0; |
10380
f4adb9648a93
(svn r14631) -Add: support for Allegro as sound backend.
rubidium
parents:
10379
diff
changeset
|
397 |
|
10379 | 398 |
const char *VideoDriver_Allegro::Start(const char * const *parm) |
399 |
{ |
|
10381
c043aa0c1695
(svn r14632) -Add: support Allegro as midi backend.
rubidium
parents:
10380
diff
changeset
|
400 |
if (_allegro_instance_count == 0 && install_allegro(SYSTEM_AUTODETECT, &errno, NULL)) return NULL; |
c043aa0c1695
(svn r14632) -Add: support Allegro as midi backend.
rubidium
parents:
10380
diff
changeset
|
401 |
_allegro_instance_count++; |
10379 | 402 |
|
403 |
install_timer(); |
|
404 |
install_mouse(); |
|
405 |
install_keyboard(); |
|
406 |
||
10390
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
407 |
#if defined _DEBUG |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
408 |
/* Allegro replaces SEGV/ABRT signals meaning that the debugger will never |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
409 |
* be triggered, so rereplace the signals and make the debugger userful. */ |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
410 |
signal(SIGABRT, NULL); |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
411 |
signal(SIGSEGV, NULL); |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
412 |
#endif |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
413 |
|
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
414 |
#if defined(DOS) |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
415 |
/* Force DOS builds to ALWAYS use full screen as |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
416 |
* it can't do windowed. */ |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
417 |
_fullscreen = true; |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
418 |
#endif |
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
419 |
|
0c2cc4c7b91f
(svn r14641) -Change [Allegro]: when making a debug build revert Allegro's hooks on SIGSEGV/SIGABRT so one can actually use gdb.
rubidium
parents:
10385
diff
changeset
|
420 |
GetVideoModes(); |
10379 | 421 |
CreateMainSurface(_cur_resolution.width, _cur_resolution.height); |
422 |
MarkWholeScreenDirty(); |
|
423 |
set_close_button_callback(HandleExitGameRequest); |
|
424 |
||
425 |
return NULL; |
|
426 |
} |
|
427 |
||
428 |
void VideoDriver_Allegro::Stop() |
|
429 |
{ |
|
10381
c043aa0c1695
(svn r14632) -Add: support Allegro as midi backend.
rubidium
parents:
10380
diff
changeset
|
430 |
if (--_allegro_instance_count == 0) allegro_exit(); |
10379 | 431 |
} |
432 |
||
10385
4f9838649c7f
(svn r14636) -Add: DOS port of OpenTTD, without network support though.
rubidium
parents:
10381
diff
changeset
|
433 |
#if defined(UNIX) || defined(__OS2__) || defined(PSP) || defined(DOS) |
10379 | 434 |
# include <sys/time.h> /* gettimeofday */ |
435 |
||
436 |
static uint32 GetTime() |
|
437 |
{ |
|
438 |
struct timeval tim; |
|
439 |
||
440 |
gettimeofday(&tim, NULL); |
|
441 |
return tim.tv_usec / 1000 + tim.tv_sec * 1000; |
|
442 |
} |
|
443 |
#else |
|
444 |
static uint32 GetTime() |
|
445 |
{ |
|
446 |
return GetTickCount(); |
|
447 |
} |
|
448 |
#endif |
|
449 |
||
450 |
||
451 |
void VideoDriver_Allegro::MainLoop() |
|
452 |
{ |
|
453 |
uint32 cur_ticks = GetTime(); |
|
454 |
uint32 last_cur_ticks = cur_ticks; |
|
455 |
uint32 next_tick = cur_ticks + 30; |
|
456 |
uint32 pal_tick = 0; |
|
457 |
||
458 |
for (;;) { |
|
459 |
uint32 prev_cur_ticks = cur_ticks; // to check for wrapping |
|
460 |
InteractiveRandom(); // randomness |
|
461 |
||
462 |
PollEvent(); |
|
463 |
if (_exit_game) return; |
|
464 |
||
465 |
#if defined(_DEBUG) |
|
466 |
if (_shift_pressed) |
|
467 |
#else |
|
468 |
/* Speedup when pressing tab, except when using ALT+TAB |
|
469 |
* to switch to another application */ |
|
10380
f4adb9648a93
(svn r14631) -Add: support for Allegro as sound backend.
rubidium
parents:
10379
diff
changeset
|
470 |
if (key[KEY_TAB] && (key_shifts & KB_ALT_FLAG) == 0) |
10379 | 471 |
#endif |
472 |
{ |
|
473 |
if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2; |
|
474 |
} else if (_fast_forward & 2) { |
|
475 |
_fast_forward = 0; |
|
476 |
} |
|
477 |
||
478 |
cur_ticks = GetTime(); |
|
479 |
if (cur_ticks >= next_tick || (_fast_forward && !_pause_game) || cur_ticks < prev_cur_ticks) { |
|
480 |
_realtime_tick += cur_ticks - last_cur_ticks; |
|
481 |
last_cur_ticks = cur_ticks; |
|
482 |
next_tick = cur_ticks + 30; |
|
483 |
||
484 |
bool old_ctrl_pressed = _ctrl_pressed; |
|
485 |
||
486 |
_ctrl_pressed = !!(key_shifts & KB_CTRL_FLAG); |
|
487 |
_shift_pressed = !!(key_shifts & KB_SHIFT_FLAG); |
|
488 |
||
489 |
/* determine which directional keys are down */ |
|
490 |
_dirkeys = |
|
491 |
(key[KEY_LEFT] ? 1 : 0) | |
|
492 |
(key[KEY_UP] ? 2 : 0) | |
|
493 |
(key[KEY_RIGHT] ? 4 : 0) | |
|
494 |
(key[KEY_DOWN] ? 8 : 0); |
|
495 |
||
496 |
if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged(); |
|
497 |
||
498 |
GameLoop(); |
|
499 |
||
500 |
_screen.dst_ptr = _allegro_screen->line[0]; |
|
501 |
UpdateWindows(); |
|
502 |
if (++pal_tick > 4) { |
|
503 |
CheckPaletteAnim(); |
|
504 |
pal_tick = 1; |
|
505 |
} |
|
506 |
DrawSurfaceToScreen(); |
|
507 |
} else { |
|
508 |
CSleep(1); |
|
509 |
_screen.dst_ptr = _allegro_screen->line[0]; |
|
510 |
NetworkDrawChatMessage(); |
|
511 |
DrawMouseCursor(); |
|
512 |
DrawSurfaceToScreen(); |
|
513 |
} |
|
514 |
} |
|
515 |
} |
|
516 |
||
517 |
bool VideoDriver_Allegro::ChangeResolution(int w, int h) |
|
518 |
{ |
|
519 |
return CreateMainSurface(w, h); |
|
520 |
} |
|
521 |
||
522 |
bool VideoDriver_Allegro::ToggleFullscreen(bool fullscreen) |
|
523 |
{ |
|
10385
4f9838649c7f
(svn r14636) -Add: DOS port of OpenTTD, without network support though.
rubidium
parents:
10381
diff
changeset
|
524 |
#ifdef DOS |
4f9838649c7f
(svn r14636) -Add: DOS port of OpenTTD, without network support though.
rubidium
parents:
10381
diff
changeset
|
525 |
return false; |
4f9838649c7f
(svn r14636) -Add: DOS port of OpenTTD, without network support though.
rubidium
parents:
10381
diff
changeset
|
526 |
#else |
10379 | 527 |
_fullscreen = fullscreen; |
528 |
GetVideoModes(); // get the list of available video modes |
|
529 |
if (_num_resolutions == 0 || !this->ChangeResolution(_cur_resolution.width, _cur_resolution.height)) { |
|
530 |
/* switching resolution failed, put back full_screen to original status */ |
|
531 |
_fullscreen ^= true; |
|
532 |
return false; |
|
533 |
} |
|
534 |
return true; |
|
10385
4f9838649c7f
(svn r14636) -Add: DOS port of OpenTTD, without network support though.
rubidium
parents:
10381
diff
changeset
|
535 |
#endif |
10379 | 536 |
} |
537 |
||
538 |
#endif /* WITH_ALLEGRO */ |