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