1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * Assorted globals and setup/cleanup routines.
12 *
13 * By Shawn Hargreaves.
14 *
15 * See readme.txt for copyright information.
16 */
17
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include "allegro.h"
24 #include "allegro/internal/aintern.h"
25
26
27
28 #define PREFIX_I "al-main INFO: "
29 #define PREFIX_W "al-main WARNING: "
30 #define PREFIX_E "al-main ERROR: "
31
32 #ifdef ALLEGRO_AMIGA
33 #define LOGFILE "RAM:allegro.log"
34 #else
35 #define LOGFILE "allegro.log"
36 #endif
37
38
39 /* in case you want to report version numbers */
40 char allegro_id[] = "Allegro " ALLEGRO_VERSION_STR ", " ALLEGRO_PLATFORM_STR;
41
42
43 /* error message for sound and gfx init routines */
44 char allegro_error[ALLEGRO_ERROR_SIZE] = EMPTY_STRING;
45
46
47 /* current system driver */
48 SYSTEM_DRIVER *system_driver = NULL;
49
50
51 /* error value, which will work even with DLL linkage */
52 int *allegro_errno = NULL;
53
54
55 /* flag for how many times we have been initialised */
56 int _allegro_count = 0;
57
58
59 /* flag to know whether we are being called by the exit mechanism */
60 int _allegro_in_exit = FALSE;
61
62
63 /* flag to decide whether to disable the screensaver */
64 int _screensaver_policy = FULLSCREEN_DISABLED;
65
66
67 /* the graphics driver currently in use */
68 GFX_DRIVER *gfx_driver = NULL;
69
70
71 /* abilities of the current graphics driver */
72 int gfx_capabilities = 0;
73
74
75 /* a bitmap structure for accessing the physical screen */
76 BITMAP *screen = NULL;
77
78
79 /* info about the current graphics drawing mode */
80 int _drawing_mode = DRAW_MODE_SOLID;
81
82 BITMAP *_drawing_pattern = NULL;
83
84 int _drawing_x_anchor = 0;
85 int _drawing_y_anchor = 0;
86
87 unsigned int _drawing_x_mask = 0;
88 unsigned int _drawing_y_mask = 0;
89
90
91 /* default palette structures */
92 PALETTE black_palette;
93 PALETTE _current_palette;
94
95 int _current_palette_changed = 0xFFFFFFFF;
96
97
98 PALETTE desktop_palette =
99 {
100 { 63, 63, 63, 0 }, { 63, 0, 0, 0 }, { 0, 63, 0, 0 }, { 63, 63, 0, 0 },
101 { 0, 0, 63, 0 }, { 63, 0, 63, 0 }, { 0, 63, 63, 0 }, { 16, 16, 16, 0 },
102 { 31, 31, 31, 0 }, { 63, 31, 31, 0 }, { 31, 63, 31, 0 }, { 63, 63, 31, 0 },
103 { 31, 31, 63, 0 }, { 63, 31, 63, 0 }, { 31, 63, 63, 0 }, { 0, 0, 0, 0 }
104 };
105
106
107 PALETTE default_palette =
108 {
109 { 0, 0, 0, 0 }, { 0, 0, 42, 0 }, { 0, 42, 0, 0 }, { 0, 42, 42, 0 },
110 { 42, 0, 0, 0 }, { 42, 0, 42, 0 }, { 42, 21, 0, 0 }, { 42, 42, 42, 0 },
111 { 21, 21, 21, 0 }, { 21, 21, 63, 0 }, { 21, 63, 21, 0 }, { 21, 63, 63, 0 },
112 { 63, 21, 21, 0 }, { 63, 21, 63, 0 }, { 63, 63, 21, 0 }, { 63, 63, 63, 0 },
113 { 0, 0, 0, 0 }, { 5, 5, 5, 0 }, { 8, 8, 8, 0 }, { 11, 11, 11, 0 },
114 { 14, 14, 14, 0 }, { 17, 17, 17, 0 }, { 20, 20, 20, 0 }, { 24, 24, 24, 0 },
115 { 28, 28, 28, 0 }, { 32, 32, 32, 0 }, { 36, 36, 36, 0 }, { 40, 40, 40, 0 },
116 { 45, 45, 45, 0 }, { 50, 50, 50, 0 }, { 56, 56, 56, 0 }, { 63, 63, 63, 0 },
117 { 0, 0, 63, 0 }, { 16, 0, 63, 0 }, { 31, 0, 63, 0 }, { 47, 0, 63, 0 },
118 { 63, 0, 63, 0 }, { 63, 0, 47, 0 }, { 63, 0, 31, 0 }, { 63, 0, 16, 0 },
119 { 63, 0, 0, 0 }, { 63, 16, 0, 0 }, { 63, 31, 0, 0 }, { 63, 47, 0, 0 },
120 { 63, 63, 0, 0 }, { 47, 63, 0, 0 }, { 31, 63, 0, 0 }, { 16, 63, 0, 0 },
121 { 0, 63, 0, 0 }, { 0, 63, 16, 0 }, { 0, 63, 31, 0 }, { 0, 63, 47, 0 },
122 { 0, 63, 63, 0 }, { 0, 47, 63, 0 }, { 0, 31, 63, 0 }, { 0, 16, 63, 0 },
123 { 31, 31, 63, 0 }, { 39, 31, 63, 0 }, { 47, 31, 63, 0 }, { 55, 31, 63, 0 },
124 { 63, 31, 63, 0 }, { 63, 31, 55, 0 }, { 63, 31, 47, 0 }, { 63, 31, 39, 0 },
125 { 63, 31, 31, 0 }, { 63, 39, 31, 0 }, { 63, 47, 31, 0 }, { 63, 55, 31, 0 },
126 { 63, 63, 31, 0 }, { 55, 63, 31, 0 }, { 47, 63, 31, 0 }, { 39, 63, 31, 0 },
127 { 31, 63, 31, 0 }, { 31, 63, 39, 0 }, { 31, 63, 47, 0 }, { 31, 63, 55, 0 },
128 { 31, 63, 63, 0 }, { 31, 55, 63, 0 }, { 31, 47, 63, 0 }, { 31, 39, 63, 0 },
129 { 45, 45, 63, 0 }, { 49, 45, 63, 0 }, { 54, 45, 63, 0 }, { 58, 45, 63, 0 },
130 { 63, 45, 63, 0 }, { 63, 45, 58, 0 }, { 63, 45, 54, 0 }, { 63, 45, 49, 0 },
131 { 63, 45, 45, 0 }, { 63, 49, 45, 0 }, { 63, 54, 45, 0 }, { 63, 58, 45, 0 },
132 { 63, 63, 45, 0 }, { 58, 63, 45, 0 }, { 54, 63, 45, 0 }, { 49, 63, 45, 0 },
133 { 45, 63, 45, 0 }, { 45, 63, 49, 0 }, { 45, 63, 54, 0 }, { 45, 63, 58, 0 },
134 { 45, 63, 63, 0 }, { 45, 58, 63, 0 }, { 45, 54, 63, 0 }, { 45, 49, 63, 0 },
135 { 0, 0, 28, 0 }, { 7, 0, 28, 0 }, { 14, 0, 28, 0 }, { 21, 0, 28, 0 },
136 { 28, 0, 28, 0 }, { 28, 0, 21, 0 }, { 28, 0, 14, 0 }, { 28, 0, 7, 0 },
137 { 28, 0, 0, 0 }, { 28, 7, 0, 0 }, { 28, 14, 0, 0 }, { 28, 21, 0, 0 },
138 { 28, 28, 0, 0 }, { 21, 28, 0, 0 }, { 14, 28, 0, 0 }, { 7, 28, 0, 0 },
139 { 0, 28, 0, 0 }, { 0, 28, 7, 0 }, { 0, 28, 14, 0 }, { 0, 28, 21, 0 },
140 { 0, 28, 28, 0 }, { 0, 21, 28, 0 }, { 0, 14, 28, 0 }, { 0, 7, 28, 0 },
141 { 14, 14, 28, 0 }, { 17, 14, 28, 0 }, { 21, 14, 28, 0 }, { 24, 14, 28, 0 },
142 { 28, 14, 28, 0 }, { 28, 14, 24, 0 }, { 28, 14, 21, 0 }, { 28, 14, 17, 0 },
143 { 28, 14, 14, 0 }, { 28, 17, 14, 0 }, { 28, 21, 14, 0 }, { 28, 24, 14, 0 },
144 { 28, 28, 14, 0 }, { 24, 28, 14, 0 }, { 21, 28, 14, 0 }, { 17, 28, 14, 0 },
145 { 14, 28, 14, 0 }, { 14, 28, 17, 0 }, { 14, 28, 21, 0 }, { 14, 28, 24, 0 },
146 { 14, 28, 28, 0 }, { 14, 24, 28, 0 }, { 14, 21, 28, 0 }, { 14, 17, 28, 0 },
147 { 20, 20, 28, 0 }, { 22, 20, 28, 0 }, { 24, 20, 28, 0 }, { 26, 20, 28, 0 },
148 { 28, 20, 28, 0 }, { 28, 20, 26, 0 }, { 28, 20, 24, 0 }, { 28, 20, 22, 0 },
149 { 28, 20, 20, 0 }, { 28, 22, 20, 0 }, { 28, 24, 20, 0 }, { 28, 26, 20, 0 },
150 { 28, 28, 20, 0 }, { 26, 28, 20, 0 }, { 24, 28, 20, 0 }, { 22, 28, 20, 0 },
151 { 20, 28, 20, 0 }, { 20, 28, 22, 0 }, { 20, 28, 24, 0 }, { 20, 28, 26, 0 },
152 { 20, 28, 28, 0 }, { 20, 26, 28, 0 }, { 20, 24, 28, 0 }, { 20, 22, 28, 0 },
153 { 0, 0, 16, 0 }, { 4, 0, 16, 0 }, { 8, 0, 16, 0 }, { 12, 0, 16, 0 },
154 { 16, 0, 16, 0 }, { 16, 0, 12, 0 }, { 16, 0, 8, 0 }, { 16, 0, 4, 0 },
155 { 16, 0, 0, 0 }, { 16, 4, 0, 0 }, { 16, 8, 0, 0 }, { 16, 12, 0, 0 },
156 { 16, 16, 0, 0 }, { 12, 16, 0, 0 }, { 8, 16, 0, 0 }, { 4, 16, 0, 0 },
157 { 0, 16, 0, 0 }, { 0, 16, 4, 0 }, { 0, 16, 8, 0 }, { 0, 16, 12, 0 },
158 { 0, 16, 16, 0 }, { 0, 12, 16, 0 }, { 0, 8, 16, 0 }, { 0, 4, 16, 0 },
159 { 8, 8, 16, 0 }, { 10, 8, 16, 0 }, { 12, 8, 16, 0 }, { 14, 8, 16, 0 },
160 { 16, 8, 16, 0 }, { 16, 8, 14, 0 }, { 16, 8, 12, 0 }, { 16, 8, 10, 0 },
161 { 16, 8, 8, 0 }, { 16, 10, 8, 0 }, { 16, 12, 8, 0 }, { 16, 14, 8, 0 },
162 { 16, 16, 8, 0 }, { 14, 16, 8, 0 }, { 12, 16, 8, 0 }, { 10, 16, 8, 0 },
163 { 8, 16, 8, 0 }, { 8, 16, 10, 0 }, { 8, 16, 12, 0 }, { 8, 16, 14, 0 },
164 { 8, 16, 16, 0 }, { 8, 14, 16, 0 }, { 8, 12, 16, 0 }, { 8, 10, 16, 0 },
165 { 11, 11, 16, 0 }, { 12, 11, 16, 0 }, { 13, 11, 16, 0 }, { 15, 11, 16, 0 },
166 { 16, 11, 16, 0 }, { 16, 11, 15, 0 }, { 16, 11, 13, 0 }, { 16, 11, 12, 0 },
167 { 16, 11, 11, 0 }, { 16, 12, 11, 0 }, { 16, 13, 11, 0 }, { 16, 15, 11, 0 },
168 { 16, 16, 11, 0 }, { 15, 16, 11, 0 }, { 13, 16, 11, 0 }, { 12, 16, 11, 0 },
169 { 11, 16, 11, 0 }, { 11, 16, 12, 0 }, { 11, 16, 13, 0 }, { 11, 16, 15, 0 },
170 { 11, 16, 16, 0 }, { 11, 15, 16, 0 }, { 11, 13, 16, 0 }, { 11, 12, 16, 0 },
171 { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
172 { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 63, 63, 63, 0 }
173 };
174
175
176 /* colors for the standard GUI dialogs (alerts, file selector, etc) */
177 int gui_fg_color = 255;
178 int gui_mg_color = 8;
179 int gui_bg_color = 0;
180
181
182 /* a block of temporary working memory */
183 void *_scratch_mem = NULL;
184 int _scratch_mem_size = 0;
185
186
187 /* SVGA bank switching tables */
188 int _last_bank_1 = -1;
189 int _last_bank_2 = -1;
190 int *_gfx_bank = NULL;
191
192
193 /* what OS are we running under? */
194 int os_type = OSTYPE_UNKNOWN;
195 int os_version = -1;
196 int os_revision = -1;
197 int os_multitasking = FALSE;
198
199
200 /* processor information */
201 char cpu_vendor[_AL_CPU_VENDOR_SIZE] = EMPTY_STRING;
202 int cpu_family = 0;
203 int cpu_model = 0;
204 int cpu_capabilities = 0;
205
206
207 /* debugging stuff */
208 static int debug_assert_virgin = TRUE;
209 static int debug_trace_virgin = TRUE;
210
211 static FILE *assert_file = NULL;
212 static FILE *trace_file = NULL;
213
214 static int (*assert_handler)(AL_CONST char *msg) = NULL;
215 int (*_al_trace_handler)(AL_CONST char *msg) = NULL;
216
217
218 /* Module linking system stuff: if an object file is linked in, then its
219 * constructor function is executed; this function should fill in the
220 * data structures below (declared in aintern.h). If the module is not
221 * linked in, then the structure pointers will be null, so we don't need
222 * to bother with that bit of code elsewhere.
223 */
224 struct _AL_LINKER_MIDI *_al_linker_midi = NULL;
225 struct _AL_LINKER_MOUSE *_al_linker_mouse = NULL;
226
227
228 /* dynamic registration system for cleanup code */
229 struct al_exit_func {
230 void (*funcptr)(void);
231 AL_CONST char *desc;
232 struct al_exit_func *next;
233 };
234
235 static struct al_exit_func *exit_func_list = NULL;
236
237
238
239 /* _add_exit_func:
240 * Adds a function to the list that need to be called by allegro_exit().
241 * `desc' should point to a statically allocated string to help with
242 * debugging.
243 */
_add_exit_func(void (* func)(void),AL_CONST char * desc)244 void _add_exit_func(void (*func)(void), AL_CONST char *desc)
245 {
246 struct al_exit_func *n;
247
248 for (n = exit_func_list; n; n = n->next)
249 if (n->funcptr == func)
250 return;
251
252 n = _AL_MALLOC(sizeof(struct al_exit_func));
253 if (!n)
254 return;
255
256 n->next = exit_func_list;
257 n->funcptr = func;
258 n->desc = desc;
259 exit_func_list = n;
260 }
261
262
263
264 /* _remove_exit_func:
265 * Removes a function from the list that need to be called by allegro_exit().
266 */
_remove_exit_func(void (* func)(void))267 void _remove_exit_func(void (*func)(void))
268 {
269 struct al_exit_func *iter = exit_func_list, *prev = NULL;
270
271 while (iter) {
272 if (iter->funcptr == func) {
273 if (prev)
274 prev->next = iter->next;
275 else
276 exit_func_list = iter->next;
277 _AL_FREE(iter);
278 return;
279 }
280 prev = iter;
281 iter = iter->next;
282 }
283 }
284
285
286
287 /* allegro_exit_stub:
288 * Stub function registered by the library via atexit.
289 */
allegro_exit_stub(void)290 static void allegro_exit_stub(void)
291 {
292 _allegro_in_exit = TRUE;
293
294 allegro_exit();
295 }
296
297
298
299 /* _install_allegro:
300 * Initialises the Allegro library, activating the system driver.
301 */
_install_allegro(int system_id,int * errno_ptr,int (* atexit_ptr)(void (* func)(void)))302 static int _install_allegro(int system_id, int *errno_ptr, int (*atexit_ptr)(void (*func)(void)))
303 {
304 RGB black_rgb = {0, 0, 0, 0};
305 char tmp1[64], tmp2[64];
306 int i;
307
308 #ifndef ALLEGRO_USE_CONSTRUCTOR
309 /* call constructor functions manually */
310 extern void _initialize_datafile_types();
311 extern void _midi_constructor();
312 extern void _mouse_constructor();
313
314 _initialize_datafile_types();
315 _midi_constructor();
316 _mouse_constructor();
317 _register_bitmap_file_type_init();
318 _register_sample_file_type_init();
319 _register_font_file_type_init();
320 #endif
321
322 if (errno_ptr)
323 allegro_errno = errno_ptr;
324 else
325 allegro_errno = &errno;
326
327 /* set up default palette structures */
328 for (i=0; i<256; i++)
329 black_palette[i] = black_rgb;
330
331 for (i=16; i<256; i++)
332 desktop_palette[i] = desktop_palette[i & 15];
333
334 /* lock some important variables */
335 LOCK_VARIABLE(screen);
336 LOCK_VARIABLE(gfx_driver);
337 LOCK_VARIABLE(gfx_capabilities);
338 LOCK_VARIABLE(_last_bank_1);
339 LOCK_VARIABLE(_last_bank_2);
340 LOCK_VARIABLE(_gfx_bank);
341 LOCK_VARIABLE(_drawing_mode);
342 LOCK_VARIABLE(_drawing_pattern);
343 LOCK_VARIABLE(_drawing_x_anchor);
344 LOCK_VARIABLE(_drawing_y_anchor);
345 LOCK_VARIABLE(_drawing_x_mask);
346 LOCK_VARIABLE(_drawing_y_mask);
347 LOCK_VARIABLE(_current_palette);
348 LOCK_VARIABLE(os_type);
349
350 /* nasty stuff to set up the config system before the system driver */
351 system_driver = _system_driver_list[0].driver;
352
353 /* needed in case set_config_file was called before allegro_init */
354 _reload_config();
355
356 reload_config_texts(NULL);
357
358 if (system_id == SYSTEM_AUTODETECT)
359 system_id = get_config_id(uconvert_ascii("system", tmp1), uconvert_ascii("system", tmp2), SYSTEM_AUTODETECT);
360
361 system_driver = NULL;
362
363 /* initialise the system driver */
364 usetc(allegro_error, 0);
365
366 for (i=0; _system_driver_list[i].driver; i++) {
367 if ((_system_driver_list[i].id == system_id) ||
368 ((_system_driver_list[i].autodetect) && (system_id == SYSTEM_AUTODETECT))) {
369 system_driver = _system_driver_list[i].driver;
370 system_driver->name = system_driver->desc = get_config_text(system_driver->ascii_name);
371 if (system_driver->init() != 0) {
372 system_driver = NULL;
373 if (system_id != SYSTEM_AUTODETECT)
374 break;
375 }
376 else
377 break;
378 }
379 }
380
381 if (!system_driver)
382 return -1;
383
384 /* disable close button */
385 set_close_button_callback(NULL);
386
387 /* detect CPU type */
388 check_cpu();
389
390 #if defined(ALLEGRO_UNIX) || defined(ALLEGRO_WINDOWS)
391 /* detect filename encoding used by libc */
392 /* XXX This should be done for all platforms but I'm not set up to check
393 * that all platforms have been covered before making the 4.2.3 release.
394 * --pw
395 */
396 _al_detect_filename_encoding();
397 #endif
398
399 /* set up screensaver policy */
400 _screensaver_policy = get_config_int(uconvert_ascii("system", tmp1),
401 uconvert_ascii("disable_screensaver", tmp2),
402 FULLSCREEN_DISABLED);
403
404 /* install shutdown handler */
405 if (_allegro_count == 0) {
406 if (atexit_ptr)
407 atexit_ptr(allegro_exit_stub);
408 }
409
410 _allegro_count++;
411
412 TRACE(PREFIX_I "Allegro initialised (instance %d)\n", _allegro_count);
413 return 0;
414 }
415
416
417
418 /* _install_allegro_version_check:
419 * Initialises the Allegro library, but return with an error if an
420 * incompatible version is found.
421 */
_install_allegro_version_check(int system_id,int * errno_ptr,int (* atexit_ptr)(void (* func)(void)),int version)422 int _install_allegro_version_check(int system_id, int *errno_ptr,
423 int (*atexit_ptr)(void (*func)(void)), int version)
424 {
425 int r = _install_allegro(system_id, errno_ptr, atexit_ptr);
426
427 int build_wip = version & 255;
428 int build_ver = version & ~255;
429
430 int version_ok;
431
432 if (r != 0) {
433 /* failed */
434 return r;
435 }
436
437 #if ALLEGRO_SUB_VERSION & 1
438 /* This is a WIP runtime, so enforce strict compatibility. */
439 version_ok = version == MAKE_VERSION(ALLEGRO_VERSION, ALLEGRO_SUB_VERSION, ALLEGRO_WIP_VERSION);
440 #else
441 /* This is a stable runtime, so the runtime should be at least as new
442 * as the build headers (otherwise we may get a crash, since some
443 * functions may have been used which aren't available in this runtime).
444 */
445 version_ok = (MAKE_VERSION(ALLEGRO_VERSION, ALLEGRO_SUB_VERSION, 0) == build_ver) &&
446 (ALLEGRO_WIP_VERSION >= build_wip);
447 #endif
448
449 if (!version_ok) {
450 uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text(
451 "The detected dynamic Allegro library (%d.%d.%d) is "
452 "not compatible with this program (%d.%d.%d)."),
453 ALLEGRO_VERSION, ALLEGRO_SUB_VERSION, ALLEGRO_WIP_VERSION,
454 build_ver >> 16, (build_ver >> 8) & 255, build_wip);
455 return -1;
456 }
457 return 0;
458 }
459
460
461
462 /* allegro_exit:
463 * Closes down the Allegro system.
464 */
allegro_exit(void)465 void allegro_exit(void)
466 {
467 while (exit_func_list) {
468 void (*func)(void) = exit_func_list->funcptr;
469 _remove_exit_func(func);
470 (*func)();
471 }
472
473 if (system_driver) {
474 system_driver->exit();
475 system_driver = NULL;
476 }
477
478 if (_scratch_mem) {
479 _AL_FREE(_scratch_mem);
480 _scratch_mem = NULL;
481 _scratch_mem_size = 0;
482 }
483 }
484
485
486
487 /* allegro_message:
488 * Displays a message in whatever form the current platform requires.
489 */
allegro_message(AL_CONST char * msg,...)490 void allegro_message(AL_CONST char *msg, ...)
491 {
492 char *buf = _AL_MALLOC_ATOMIC(ALLEGRO_MESSAGE_SIZE);
493 char *tmp = _AL_MALLOC_ATOMIC(ALLEGRO_MESSAGE_SIZE);
494 va_list ap;
495 ASSERT(msg);
496 va_start(ap, msg);
497 uvszprintf(buf, ALLEGRO_MESSAGE_SIZE, msg, ap);
498 va_end(ap);
499
500 if ((system_driver) && (system_driver->message))
501 system_driver->message(buf);
502 else
503 fputs(uconvert(buf, U_CURRENT, tmp, U_ASCII_CP, ALLEGRO_MESSAGE_SIZE), stdout);
504
505 _AL_FREE(buf);
506 _AL_FREE(tmp);
507 }
508
509
510
511 /* get_executable_name:
512 * Finds out the name of the current executable.
513 */
get_executable_name(char * output,int size)514 void get_executable_name(char *output, int size)
515 {
516 ASSERT(system_driver);
517 ASSERT(output);
518
519 if (system_driver->get_executable_name) {
520 system_driver->get_executable_name(output, size);
521 }
522 else {
523 output += usetc(output, '.');
524 output += usetc(output, '/');
525 usetc(output, 0);
526 }
527 }
528
529
530
531 /* set_close_button_callback:
532 * Installs a callback function to be called when the close button
533 * of the window or any equivalent device is activated. Returns 0 on
534 * success and -1 on failure (e.g. feature not supported).
535 */
set_close_button_callback(void (* proc)(void))536 int set_close_button_callback(void (*proc)(void))
537 {
538 ASSERT(system_driver);
539
540 if (system_driver->set_close_button_callback)
541 return system_driver->set_close_button_callback(proc);
542
543 return -1;
544 }
545
546
547
548 /* debug_exit:
549 * Closes the debugging output files.
550 */
debug_exit(void)551 static void debug_exit(void)
552 {
553 if (assert_file) {
554 fclose(assert_file);
555 assert_file = NULL;
556 }
557
558 if (trace_file) {
559 fclose(trace_file);
560 trace_file = NULL;
561 }
562
563 debug_assert_virgin = TRUE;
564 debug_trace_virgin = TRUE;
565
566 _remove_exit_func(debug_exit);
567 }
568
569
570
571 /* al_assert:
572 * Raises an assert (uses ASCII strings).
573 */
al_assert(AL_CONST char * file,int line)574 void al_assert(AL_CONST char *file, int line)
575 {
576 static int asserted = FALSE;
577 int olderr = errno;
578 char buf[128];
579 char *s;
580
581 if (asserted)
582 return;
583
584 /* todo, some day: use snprintf (C99) */
585 sprintf(buf, "Assert failed at line %d of %s", line, file);
586
587 if (assert_handler) {
588 if (assert_handler(buf))
589 return;
590 }
591
592 if (debug_assert_virgin) {
593 s = getenv("ALLEGRO_ASSERT");
594
595 if (s)
596 assert_file = fopen(s, "w");
597 else
598 assert_file = NULL;
599
600 if (debug_trace_virgin)
601 _add_exit_func(debug_exit, "debug_exit");
602
603 debug_assert_virgin = FALSE;
604 }
605
606 if (assert_file) {
607 fprintf(assert_file, "%s\n", buf);
608 fflush(assert_file);
609 }
610 else {
611 asserted = TRUE;
612
613 if ((system_driver) && (system_driver->assert)) {
614 system_driver->assert(buf);
615 }
616 else {
617 allegro_exit();
618 fprintf(stderr, "%s\n", buf);
619 abort();
620 }
621 }
622
623 errno = olderr;
624 }
625
626
627
628 /* al_trace:
629 * Outputs a trace message (uses ASCII strings).
630 */
al_trace(AL_CONST char * msg,...)631 void al_trace(AL_CONST char *msg, ...)
632 {
633 int olderr = errno;
634 char buf[512];
635 char *s;
636
637 /* todo, some day: use vsnprintf (C99) */
638 va_list ap;
639 va_start(ap, msg);
640 vsprintf(buf, msg, ap);
641 va_end(ap);
642
643 if (_al_trace_handler) {
644 if (_al_trace_handler(buf))
645 return;
646 }
647
648 if (debug_trace_virgin) {
649 s = getenv("ALLEGRO_TRACE");
650
651 if (s)
652 trace_file = fopen(s, "w");
653 else
654 trace_file = fopen(LOGFILE, "w");
655
656 if (debug_assert_virgin)
657 _add_exit_func(debug_exit, "debug_exit");
658
659 debug_trace_virgin = FALSE;
660 }
661
662 if (trace_file) {
663 fwrite(buf, sizeof(char), strlen(buf), trace_file);
664 fflush(trace_file);
665 }
666
667 errno = olderr;
668 }
669
670
671
672 /* register_assert_handler:
673 * Installs a user handler for assert failures.
674 */
register_assert_handler(int (* handler)(AL_CONST char * msg))675 void register_assert_handler(int (*handler)(AL_CONST char *msg))
676 {
677 assert_handler = handler;
678 }
679
680
681
682 /* register_trace_handler:
683 * Installs a user handler for trace output.
684 */
register_trace_handler(int (* handler)(AL_CONST char * msg))685 void register_trace_handler(int (*handler)(AL_CONST char *msg))
686 {
687 _al_trace_handler = handler;
688 }
689
690
691
692 /* _al_malloc:
693 * Wrapper for when a program needs to manipulate memory that has been
694 * allocated by the Allegro DLL.
695 */
_al_malloc(size_t size)696 void *_al_malloc(size_t size)
697 {
698 return malloc(size);
699 }
700
701
702
703 /* _al_free:
704 * Wrapper for when a program needs to manipulate memory that has been
705 * allocated by the Allegro DLL.
706 */
_al_free(void * mem)707 void _al_free(void *mem)
708 {
709 free(mem);
710 }
711
712
713
714 /* _al_realloc:
715 * Wrapper for when a program needs to manipulate memory that has been
716 * allocated by the Allegro DLL.
717 */
_al_realloc(void * mem,size_t size)718 void *_al_realloc(void *mem, size_t size)
719 {
720 return realloc(mem, size);
721 }
722
723
724
725 /* _al_strdup:
726 * Wrapper for when a program needs to duplicate a string in a way that
727 * uses any user overloaded memory allocation system in use.
728 * The result of this function _must_ be freed with _AL_FREE().
729 */
_al_strdup(AL_CONST char * string)730 char *_al_strdup(AL_CONST char *string)
731 {
732 char *newstring = _AL_MALLOC(strlen(string) + 1);
733
734 if (newstring)
735 strcpy(newstring, string);
736
737 return newstring;
738 }
739
740
741
742 /* a simple system driver for platform-independent code */
sys_none_init(void)743 static int sys_none_init(void) { return 0; }
sys_none_exit(void)744 static void sys_none_exit(void) { }
745
746 static _DRIVER_INFO no_drivers[] = {{ 0, NULL, 0 }};
sys_no_driver(void)747 static _DRIVER_INFO *sys_no_driver(void) { return no_drivers; }
748
749
750 SYSTEM_DRIVER system_none =
751 {
752 SYSTEM_NONE,
753 empty_string,
754 empty_string,
755 "Agnostic",
756 sys_none_init,
757 sys_none_exit,
758 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
759 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
760 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
761 sys_no_driver, sys_no_driver, sys_no_driver, sys_no_driver,
762 sys_no_driver, sys_no_driver, sys_no_driver
763 };
764
765