3 Quick and Dirty Game Development Framework (QDGDF)
5 Copyright (C) 2001/2011 Angel Ortega <angel@triptico.com>
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 http://www.triptico.com
32 #include "qdgdf_video.h"
38 * _qdgdfv_fopen_path - Search path for qdgdfv_fopen().
40 * This string can contain a semicolon-separated list of paths
41 * where files to be open with qdgdfv_fopen() will be tried
45 char _qdgdfv_fopen_path
[250] = "";
48 * _qdgdfv_virtual_screen - The virtual screen.
50 * This variable points to a buffer of (_qdgdfv_screen_x_size *
51 * _qdgdfv_screen_y_size) unsigned chars. All video operations are
52 * done over this space. To dump it to the real screen, use
53 * qdgdfv_dump_virtual_screen().
56 unsigned char *_qdgdfv_virtual_screen
= NULL
;
59 * _qdgdfv_clear_color - The clear color.
61 * This color will be used to clear the screen when using
62 * qdgdfv_clear_virtual_screen().
65 unsigned char _qdgdfv_clear_color
= 0;
68 * _qdgdfv_screen_x_size - Horizontal screen size.
70 * This variable holds the horizontal screen size in pixels. It can be
71 * set to whatever wanted before the startup. The real horizontal
72 * screen size will be stored here after the startup (it can be a
76 unsigned int _qdgdfv_screen_x_size
= 320;
79 * _qdgdfv_screen_y_size - Vertical screen size.
81 * This variable holds the vertical screen size in pixels. It can be
82 * set to whatever wanted before the startup. The real vertical
83 * screen size will be stored here after the startup (it can be a
87 unsigned int _qdgdfv_screen_y_size
= 200;
90 * _qdgdfv_window_x - Initial x position of the window.
92 * This variable must be set before startup and holds the desired
93 * initial position of the window. Not all supported systems let
94 * this be set (some of them even have no window at all, just
95 * fullscreen graphics), so it's purely orientative there.
98 int _qdgdfv_window_x
= 60;
101 * _qdgdfv_window_y - Initial y position of the window.
103 * This variable must be set before startup and holds the desired
104 * initial position of the window. Not all supported systems let
105 * this be set (some of them even have no window at all, just
106 * fullscreen graphics), so it's purely orientative there.
109 int _qdgdfv_window_y
= 60;
113 * _qdgdfv_scale - Sets the scale.
115 * Sets the scale. If not set, a 1 scale (no scale) will be tried;
116 * if it's impossible to set due to hardware limitations (for example,
117 * a 320x200 resolution has been requested and current hardware don't
118 * support it, but can do 640x400), a 2 scale (double) will be tried.
119 * Some drivers allow even bigger scales.
121 * This variable obsoletes the old _qdgdfv_double_mode.
124 int _qdgdfv_scale
= 0;
127 * _qdgdfv_double_mode - Sets the double mode.
129 * The use of this variable is deprecated. Use _qdgdfv_scale instead.
132 int _qdgdfv_double_mode
= 0;
135 * _qdgdfv_double_antialias - Antialias flag for double modes.
137 * If you set this variable, double modes will be dumped using
138 * a basic antialiasing mechanism, if the video driver implements one.
141 int _qdgdfv_double_antialias
= 0;
144 * _qdgdfv_scale2x - Scale2x algorithm flag.
146 * When set, double screen dumping is done by using the scale2x
147 * algorithm (read about it at http://scale2x.sourceforge.net).
148 * It's set by default.
151 int _qdgdfv_scale2x
= 1;
154 * _qdgdfv_window_title - Title for the window.
156 * This string holds the title for the window. Take note
157 * that some systems are fullscreen and has no window titles.
160 char _qdgdfv_window_title
[150] = "qdgdf Window";
163 * _qdgdfv_additional_info - Additional string info for the driver.
165 * This string can be filled with some information for the driver.
166 * Its content is purposely driver dependent and can contain,
167 * for example, the remote X Window display.
170 char _qdgdfv_additional_info
[150] = "";
173 * _qdgdfv_additional_int_info - Additional integer info for the driver.
175 * This integer can be filled with some information for the driver.
176 * Its content is purposely driver dependent and can contain,
177 * for example, the Windows instance handler.
180 int _qdgdfv_additional_int_info
= 0;
183 * _qdgdfv_gamma_correct - Gamma correction.
185 * This variable containts the amount of gamma correction to
186 * be applied when colors are created. It ranges from 0 (colors as
187 * defined in the palette) to 255 (absolutely saturate).
189 int _qdgdfv_gamma_correct
= 0;
194 * _qdgdfv_key_ - The key flags.
196 * This variables are set by qdgdfv_input_poll() accordingly to
197 * the current keyboard status. These variables are:
198 * _qdgdfv_key_up, _qdgdfv_key_down, _qdgdfv_key_left,
199 * _qdgdfv_key_right, _qdgdfv_key_escape, _qdgdfv_key_space,
200 * _qdgdfv_key_enter, _qdgdfv_key_control_l, _qdgdfv_key_control_r,
201 * _qdgdfv_key_control, _qdgdfv_key_shift_l, _qdgdfv_key_shift_r,
202 * _qdgdfv_key_pgup, _qdgdfv_key_pgdn, _qdgdfv_key_home, _qdgdfv_key_end
203 * and _qdgdfv_key_f1 to f10.
204 * [Keyboard Variables]
206 int _qdgdfv_key_up
= 0;
207 int _qdgdfv_key_down
= 0;
208 int _qdgdfv_key_left
= 0;
209 int _qdgdfv_key_right
= 0;
210 int _qdgdfv_key_escape
= 0;
211 int _qdgdfv_key_space
= 0;
212 int _qdgdfv_key_enter
= 0;
213 int _qdgdfv_key_control_l
= 0;
214 int _qdgdfv_key_control_r
= 0;
215 int _qdgdfv_key_pgup
= 0;
216 int _qdgdfv_key_pgdn
= 0;
217 int _qdgdfv_key_home
= 0;
218 int _qdgdfv_key_end
= 0;
219 int _qdgdfv_key_f1
= 0;
220 int _qdgdfv_key_f2
= 0;
221 int _qdgdfv_key_f3
= 0;
222 int _qdgdfv_key_f4
= 0;
223 int _qdgdfv_key_f5
= 0;
224 int _qdgdfv_key_f6
= 0;
225 int _qdgdfv_key_f7
= 0;
226 int _qdgdfv_key_f8
= 0;
227 int _qdgdfv_key_f9
= 0;
228 int _qdgdfv_key_f10
= 0;
230 /* Dan Compton added these changes */
231 int _qdgdfv_key_control
= 0;
232 int _qdgdfv_key_shift_l
= 0;
233 int _qdgdfv_key_shift_r
= 0;
234 int _qdgdfv_key_alnum
= 0;
235 char _qdgdfv_alnum
= 0;
238 /* extended key information */
239 static struct __qdgdfv_extended_key_status
{
240 int *key_var
; /* pointer to key variable */
241 int last_val
; /* last seen value */
242 } _qdgdfv_extended_key_status
[] = {
243 { &_qdgdfv_key_up
, 0},
244 { &_qdgdfv_key_down
, 0},
245 { &_qdgdfv_key_left
, 0},
246 { &_qdgdfv_key_right
, 0},
247 { &_qdgdfv_key_escape
, 0},
248 { &_qdgdfv_key_space
, 0},
249 { &_qdgdfv_key_enter
, 0},
250 { &_qdgdfv_key_control_l
, 0},
251 { &_qdgdfv_key_control_r
, 0},
252 { &_qdgdfv_key_pgup
, 0},
253 { &_qdgdfv_key_pgdn
, 0},
254 { &_qdgdfv_key_home
, 0},
255 { &_qdgdfv_key_end
, 0},
256 { &_qdgdfv_key_f1
, 0},
257 { &_qdgdfv_key_f2
, 0},
258 { &_qdgdfv_key_f3
, 0},
259 { &_qdgdfv_key_f4
, 0},
260 { &_qdgdfv_key_f5
, 0},
261 { &_qdgdfv_key_f6
, 0},
262 { &_qdgdfv_key_f7
, 0},
263 { &_qdgdfv_key_f8
, 0},
264 { &_qdgdfv_key_f9
, 0},
265 { &_qdgdfv_key_f10
, 0},
266 { &_qdgdfv_key_control
, 0},
267 { &_qdgdfv_key_shift_l
, 0},
268 { &_qdgdfv_key_shift_r
, 0},
275 /* the palette. Includes by default the original palette from
276 the never-finished game Freak Wars (256*rgb) */
278 unsigned int _qdgdfv_palette
[256 * 3] = {
279 0, 0, 0, 28, 24, 12, 20, 16, 8, 68, 68, 68, 255, 224, 0, 24, 24, 24,
280 16, 20, 20, 8, 12, 12, 4, 8, 8, 40, 52, 28, 32, 40, 16, 20, 28, 8,
281 12, 24, 0, 68, 56, 40, 64, 48, 32, 56, 40, 24, 255, 69, 0, 220, 152, 152,
282 216, 148, 148, 208, 136, 136, 204, 128, 128, 196, 120, 120, 196, 112, 112,
283 188, 104, 104, 180, 96, 96, 176, 88, 88, 168, 84, 84, 164, 80, 80,
284 160, 72, 72, 156, 64, 64, 148, 56, 56, 144, 56, 56, 136, 48, 48,
285 132, 44, 44, 128, 40, 40, 124, 32, 32, 116, 28, 28, 112, 24, 24,
286 104, 24, 24, 100, 20, 20, 96, 16, 16, 92, 12, 12, 84, 8, 8, 80, 8, 8,
287 72, 8, 8, 68, 0, 0, 64, 0, 0, 255, 191, 0, 228, 212, 200, 228, 204, 188,
288 228, 196, 180, 228, 188, 168, 228, 184, 160, 228, 180, 152, 228, 172, 140,
289 228, 168, 132, 228, 160, 120, 220, 152, 112, 212, 148, 104, 204, 140, 96,
290 196, 132, 88, 192, 124, 84, 184, 120, 76, 180, 116, 72, 168, 112, 68,
291 160, 104, 64, 152, 100, 60, 144, 96, 56, 136, 88, 56, 128, 88, 52,
292 120, 80, 48, 112, 76, 44, 104, 72, 40, 96, 64, 36, 84, 60, 32, 72, 56, 28,
293 68, 52, 24, 56, 44, 24, 44, 40, 20, 36, 32, 16, 212, 216, 216,
294 204, 208, 208, 196, 200, 200, 196, 196, 196, 188, 188, 188, 180, 184, 184,
295 176, 180, 180, 168, 172, 172, 164, 164, 164, 160, 160, 160, 152, 152, 152,
296 148, 152, 152, 140, 144, 144, 132, 136, 136, 132, 132, 132, 124, 124, 124,
297 116, 120, 120, 112, 116, 116, 104, 108, 108, 100, 100, 100, 96, 96, 96,
298 88, 88, 88, 80, 84, 84, 76, 80, 80, 68, 72, 72, 64, 64, 64, 60, 60, 60,
299 52, 56, 56, 48, 52, 52, 40, 44, 44, 36, 36, 36, 32, 32, 32, 255, 89, 0,
300 100, 216, 92, 92, 200, 88, 84, 184, 80, 80, 172, 72, 72, 156, 64,
301 68, 144, 56, 60, 132, 52, 56, 120, 44, 48, 104, 40, 40, 88, 32,
302 36, 76, 24, 28, 60, 24, 20, 48, 16, 16, 32, 12, 255, 29, 0, 168, 152, 128,
303 164, 144, 120, 156, 136, 116, 148, 128, 108, 140, 120, 100, 136, 116, 96,
304 132, 112, 88, 124, 104, 84, 116, 96, 80, 108, 88, 72, 104, 88, 68,
305 100, 80, 60, 92, 76, 56, 84, 68, 52, 76, 60, 48, 72, 56, 44, 140, 120, 88,
306 128, 108, 76, 116, 96, 68, 104, 88, 56, 92, 76, 48, 80, 64, 40,
307 68, 56, 32, 60, 48, 24, 108, 116, 88, 100, 104, 80, 92, 96, 72,
308 80, 88, 64, 72, 80, 56, 64, 72, 48, 56, 64, 40, 48, 56, 36, 228, 228, 104,
309 208, 196, 80, 192, 168, 60, 172, 140, 44, 156, 112, 28, 136, 84, 20,
310 120, 60, 8, 100, 40, 0, 228, 228, 228, 228, 196, 196, 228, 168, 168,
311 228, 140, 140, 228, 112, 112, 228, 88, 88, 228, 56, 56, 228, 28, 28,
312 228, 0, 0, 212, 0, 0, 200, 0, 0, 192, 0, 0, 180, 0, 0, 168, 0, 0,
313 160, 0, 0, 148, 0, 0, 136, 0, 0, 124, 0, 0, 112, 0, 0, 100, 0, 0,
314 92, 0, 0, 80, 0, 0, 68, 0, 0, 60, 0, 0, 204, 208, 228, 176, 180, 228,
315 152, 152, 228, 128, 128, 228, 100, 104, 228, 72, 76, 228, 48, 52, 228,
316 24, 24, 228, 0, 0, 228, 0, 0, 204, 0, 0, 184, 0, 0, 160, 0, 0, 140,
317 0, 0, 120, 0, 0, 96, 0, 0, 76, 228, 228, 228, 228, 212, 196, 228, 192, 168,
318 228, 180, 140, 228, 160, 112, 228, 148, 84, 228, 128, 56, 228, 116, 24,
319 216, 104, 24, 208, 100, 16, 196, 92, 16, 192, 88, 12, 180, 80, 8,
320 172, 72, 0, 164, 64, 0, 156, 60, 0, 228, 228, 228, 228, 228, 192,
321 228, 228, 160, 228, 228, 128, 228, 228, 96, 228, 228, 64, 228, 228, 32,
322 228, 228, 0, 148, 56, 0, 140, 52, 0, 132, 44, 0, 120, 32, 0, 68, 56, 36,
323 60, 44, 24, 48, 32, 20, 40, 24, 12, 255, 204, 0, 0, 0, 64, 0, 0, 56,
324 0, 0, 44, 0, 0, 32, 0, 0, 24, 0, 0, 12, 148, 96, 96, 228, 144, 60,
325 228, 208, 68, 255, 181, 0, 255, 159, 0, 255, 139, 0, 255, 119, 0,
326 255, 109, 0, 255, 0, 255
330 * _qdgdfv_use_logger - Logger use flag.
332 * If this variable is set, the logger will be active.
333 * [Support Variables]
335 int _qdgdfv_use_logger
= 1;
338 * _qdgdfv_logger_file - Logger file.
340 * This string holds the path of the logger file.
341 * [Support Variables]
343 char _qdgdfv_logger_file
[150] = "";
345 char *_qdgdfv_version
= VERSION
;
349 * _qdgdfv_accum_buffer - Accumulation buffer.
351 * This buffer holds the last dumped virtual screen if
352 * the accumulation buffer is used, or a NULL pointer
353 * otherwise. It's rarely used directly, as the accumulation
354 * buffer is treated transparently.
357 unsigned char *_qdgdfv_accum_buffer
= NULL
;
359 unsigned char _qdgdfv_accum_table
[256][256];
361 /* the extended palette (for 15, 16, 24 and 32 bpp) */
362 unsigned int _qdgdfv_extended_palette
[256];
364 /* pixel size (1, 2 or 4) */
365 int _qdgdfv_pixel_size
;
368 static struct _qdgdfv_driver
*drv
= NULL
;
370 /* masks and shifts for pixel sizes > 1 */
371 unsigned int _qdgdfv_red_mask
;
372 unsigned int _qdgdfv_green_mask
;
373 unsigned int _qdgdfv_blue_mask
;
374 int _qdgdfv_red_shift
;
375 int _qdgdfv_green_shift
;
376 int _qdgdfv_blue_shift
;
379 * _qdgdfv_full_screen - Full screen flag.
381 * When set before initialization, it expresses the preference
382 * of running full screen or not (a value of -1 means it doesn't matter).
383 * After initialization, contains what really happened.
385 int _qdgdfv_full_screen
= -1;
390 #include "qdgdf_path.c"
395 * qdgdfv_sprintf - Static sprintf.
396 * @fmt: the format string
398 * Formats a string, using sprintf.
399 * A static buffer is returned.
400 * [Support Functions]
402 char *qdgdfv_sprintf(char *fmt
, ...)
404 static char sp_buf
[4096];
407 va_start(argptr
, fmt
);
408 vsprintf(sp_buf
, fmt
, argptr
);
416 * qdgdfv_logger - Logs a message.
417 * @where: caller function name
420 * Logs the @message to the logger file, usually an error.
421 * [Support Functions]
423 void qdgdfv_logger(char *where
, char *msg
)
427 if (_qdgdfv_use_logger
&& _qdgdfv_logger_file
[0] != '\0') {
428 if ((f
= fopen(_qdgdfv_logger_file
, "a")) != NULL
) {
429 fprintf(f
, "%s: %s\n", where
, msg
);
438 * qdgdfv_bang - Bangs on unrecoverable problems.
439 * @where: caller function name
442 * Logs the @message to the logger and returns to the system.
443 * [Support Functions]
445 void qdgdfv_bang(char *where
, char *msg
)
447 qdgdfv_logger(where
, msg
);
449 printf("\nBANG! %s: %s\n", where
, msg
);
457 * qdgdfv_malloc - 'Secure' malloc.
458 * @size: the size of the block to malloc
460 * Tries to alloc the desired memory @size and, if not succesful,
461 * bangs out to the system. This make unnecesary to test if
462 * the block could be allocated.
463 * Returns the allocated block.
464 * [Support Functions]
466 void *qdgdfv_malloc(int size
)
473 qdgdfv_bang("a_malloc", "Out of memory");
479 FILE *_qdgdfv_fopen(char *file
, char *mode
)
481 return _path_fopen(_qdgdfv_fopen_path
, file
, mode
);
486 * qdgdfv_path_find - Finds a file in _qdgdfv_fopen_path.
487 * @file: the file to be found
489 * Searches for @file in the path stored in _qdgdfv_fopen_path.
490 * If it's found in some of the directories there, a string is
491 * allocated contaning the full path, that should be freed
492 * when no longer needed. Otherwise, returns NULL.
494 char *qdgdfv_path_find(const char *file
)
496 return _path_find(_qdgdfv_fopen_path
, file
);
501 * qdgdfv_fopen - 'Secure' open.
502 * @file: file to be opened
503 * @mode: mode for the file
505 * Opens a file, banging if could not be opened. Optional search paths
506 * can be defined in _qdgdfv_fopen_path.
507 * Returns the opened file.
508 * [Support Functions]
510 FILE *qdgdfv_fopen(char *file
, char *mode
)
514 if ((f
= _qdgdfv_fopen(file
, mode
)) == NULL
)
515 qdgdfv_bang("qdgdfv_fopen: can't open", file
);
521 static void load_pcx(unsigned char *pcx
, char *pcxfile
, int size
, int usepal
)
526 unsigned char _pcx_palette
[256][3];
528 f
= qdgdfv_fopen(pcxfile
, "rb");
531 fseek(f
, 128, SEEK_SET
);
553 fseek(f
, -((long) sizeof(_pcx_palette
)), SEEK_END
);
554 fread(_pcx_palette
, 3, 256, f
);
558 /* if the palette is not to be used, it's over */
563 /* fixes the pcx to use current palette */
564 for (n
= 0; n
< size
; n
++) {
566 pcx
[n
] = qdgdfv_seek_color(_pcx_palette
[c
][0],
567 _pcx_palette
[c
][1], _pcx_palette
[c
][2]
571 else if (usepal
== 2) {
572 /* transfers this pcx's palette to system one */
573 for (n
= 0; n
< 256; n
++) {
574 _qdgdfv_palette
[n
* 3] = _pcx_palette
[n
][0];
575 _qdgdfv_palette
[(n
* 3) + 1] = _pcx_palette
[n
][1];
576 _qdgdfv_palette
[(n
* 3) + 2] = _pcx_palette
[n
][2];
580 qdgdfv_set_palette();
586 * qdgdfv_load_pcx - Loads a graphic in PCX format.
587 * @pcx: the buffer where the graphic will be stored
588 * @pcxfile: the file containing the graphic
589 * @size: the size in bytes of the graphic data
591 * Loads a graphic into the supplied @pcx buffer. The file must be
592 * in 256 color PCX format. The palette included inside the file
596 void qdgdfv_load_pcx(unsigned char *pcx
, char *pcxfile
, int size
)
598 load_pcx(pcx
, pcxfile
, size
, 0);
603 * qdgdfv_load_pcx_pal - Loads a graphic in PCX format using its palette.
604 * @pcx: the buffer where the graphic will be stored
605 * @pcxfile: the file containing the graphic
606 * @size: the size in bytes of the graphic data
608 * This function does the same as qdgdfv_load_pcx(), but taking into
609 * account the palette information stored inside the file to match
610 * the current palette.
613 void qdgdfv_load_pcx_pal(unsigned char *pcx
, char *pcxfile
, int size
)
615 load_pcx(pcx
, pcxfile
, size
, 1);
620 * qdgdfv_load_pcx_pal_set - Loads a graphic in PCX format setting its palette.
621 * @pcx: the buffer where the graphic will be stored
622 * @pcxfile: the file containing the graphic
623 * @size: the size in bytes of the graphic data
625 * This function does the same as qdgdfv_load_pcx(), but setting the palette
626 * store inside the file as the default.
629 void qdgdfv_load_pcx_pal_set(unsigned char *pcx
, char *pcxfile
, int size
)
631 load_pcx(pcx
, pcxfile
, size
, 2);
636 * qdgdfv_load_palette - Loads an external palette.
637 * @palette_file: the file containing the palette
639 * Loads an external palette. The file is a text one having
640 * lines with three decimal values from 0 to 255 for the red,
641 * green and blue parts of each color, respectively. To be used,
642 * qdgdfv_set_palette() must be called afterwards.
645 void qdgdfv_load_palette(char *palette_file
)
650 unsigned int r
, g
, b
;
652 if (*palette_file
== '\0')
655 f
= qdgdfv_fopen(palette_file
, "r");
657 /* ignores first three lines */
658 fgets(lin
, sizeof(lin
) - 1, f
);
659 fgets(lin
, sizeof(lin
) - 1, f
);
660 fgets(lin
, sizeof(lin
) - 1, f
);
662 for (n
= 0; n
< 256; n
++) {
663 if (fscanf(f
, "%u %u %u\n", &r
, &g
, &b
) != 3)
666 _qdgdfv_palette
[n
* 3] = r
;
667 _qdgdfv_palette
[(n
* 3) + 1] = g
;
668 _qdgdfv_palette
[(n
* 3) + 2] = b
;
671 /* fills to the end with zeroes */
672 for (; n
< 256; n
++) {
673 _qdgdfv_palette
[n
* 3] = 0;
674 _qdgdfv_palette
[(n
* 3) + 1] = 0;
675 _qdgdfv_palette
[(n
* 3) + 2] = 0;
682 static void fill_extended_palette(void)
685 unsigned int r
, g
, b
;
688 pal
= (int *) _qdgdfv_palette
;
690 for (n
= 0; n
< 256; n
++) {
692 if ((r
= (unsigned int) pal
[n
* 3] + _qdgdfv_gamma_correct
) > 255)
695 if ((g
= (unsigned int) pal
[(n
* 3) + 1] + _qdgdfv_gamma_correct
) > 255)
698 if ((b
= (unsigned int) pal
[(n
* 3) + 2] + _qdgdfv_gamma_correct
) > 255)
701 r
= ((r
<< 24) & _qdgdfv_red_mask
) >> _qdgdfv_red_shift
;
702 g
= ((g
<< 24) & _qdgdfv_green_mask
) >> _qdgdfv_green_shift
;
703 b
= ((b
<< 24) & _qdgdfv_blue_mask
) >> _qdgdfv_blue_shift
;
705 _qdgdfv_extended_palette
[n
] = r
| g
| b
;
711 * qdgdfv_set_palette - Sets the palette.
713 * Sets the stored palette as the current one, probably
714 * loading it into video hardware.
717 void qdgdfv_set_palette(void)
719 /* call the driver setting */
722 if (_qdgdfv_pixel_size
> 1)
723 fill_extended_palette();
728 * qdgdfv_clear_virtual_screen - Clears the virtual screen.
730 * Clears the virtual screen, using _qdgdfv_clear_color.
733 void qdgdfv_clear_virtual_screen(void)
735 memset(_qdgdfv_virtual_screen
, _qdgdfv_clear_color
,
736 _qdgdfv_screen_x_size
* _qdgdfv_screen_y_size
);
742 #define DUMP_PLAIN(NAME,TYPE) \
743 void NAME(unsigned char * screen, TYPE * dscreen) { \
745 for(n = _qdgdfv_screen_x_size * _qdgdfv_screen_y_size;n > 0;n--) { \
746 a = (TYPE) _qdgdfv_extended_palette[(int)*screen++]; \
751 DUMP_PLAIN(_qdgdfv_dump2_screen
, short)
752 DUMP_PLAIN(_qdgdfv_dump4_screen
, int)
754 #define DOUBLE_DUMP_PLAIN(NAME,TYPE) \
755 void NAME(unsigned char * screen, TYPE * dscreen) { \
756 int n, m, l; TYPE a; \
757 l = _qdgdfv_screen_x_size * 2; \
758 for(n = 0;n < _qdgdfv_screen_y_size;n++) { \
759 for(m = 0;m < _qdgdfv_screen_x_size;m++) { \
760 a = (TYPE) _qdgdfv_extended_palette[(int)*screen++]; \
761 *dscreen = a; *(dscreen + l) = a; dscreen++; \
762 *dscreen = a; *(dscreen + l) = a; dscreen++; \
767 DOUBLE_DUMP_PLAIN(_qdgdfv_double_dump1_screen
, char)
768 DOUBLE_DUMP_PLAIN(_qdgdfv_double_dump2_screen
, short)
769 DOUBLE_DUMP_PLAIN(_qdgdfv_double_dump4_screen
, int)
771 #define TRIPLE_DUMP_PLAIN(NAME,TYPE) \
772 void NAME(unsigned char * screen, TYPE * dscreen) { \
773 int n, m, l, l2; TYPE a; \
774 l = _qdgdfv_screen_x_size * 3; \
775 l2 = _qdgdfv_screen_x_size * 3 * 2; \
776 for(n = 0;n < _qdgdfv_screen_y_size;n++) { \
777 for(m = 0;m < _qdgdfv_screen_x_size;m++) { \
778 a = (TYPE) _qdgdfv_extended_palette[(int)*screen++]; \
779 *dscreen = a; *(dscreen + l) = a; *(dscreen + l2) = a; dscreen++; \
780 *dscreen = a; *(dscreen + l) = a; *(dscreen + l2) = a; dscreen++; \
781 *dscreen = a; *(dscreen + l) = a; *(dscreen + l2) = a; dscreen++; \
786 TRIPLE_DUMP_PLAIN(_qdgdfv_triple_dump1_screen
, char)
787 TRIPLE_DUMP_PLAIN(_qdgdfv_triple_dump2_screen
, short)
788 TRIPLE_DUMP_PLAIN(_qdgdfv_triple_dump4_screen
, int)
791 /** scale2x: algorithm taken from http://scale2x.sourceforge.net **/
793 static void scale2x_peek(unsigned char *p
, int tx
, unsigned char o
[9])
795 o
[0] = *(p
- tx
- 1); o
[1] = *(p
- tx
); o
[2] = *(p
- tx
+ 1);
796 o
[3] = *(p
- 1); o
[4] = *p
; o
[5] = *(p
+ 1);
797 o
[6] = *(p
+ tx
- 1); o
[7] = *(p
+ tx
); o
[8] = *(p
+ tx
+ 1);
801 void qdgdfv_scale2x_p(unsigned char *p
, int tx
, int o
[4])
805 scale2x_peek(p
, tx
, i
);
807 o
[0] = (i
[3] == i
[1] && i
[1] != i
[5] && i
[3] != i
[7]) ? i
[3] : i
[4];
808 o
[1] = (i
[1] == i
[5] && i
[1] != i
[3] && i
[5] != i
[7]) ? i
[5] : i
[4];
809 o
[2] = (i
[3] == i
[7] && i
[3] != i
[1] && i
[7] != i
[5]) ? i
[3] : i
[4];
810 o
[3] = (i
[7] == i
[5] && i
[3] != i
[7] && i
[1] != i
[5]) ? i
[5] : i
[4];
814 void qdgdfv_scale3x_p(unsigned char *p
, int tx
, int o
[9])
818 scale2x_peek(p
, tx
, i
);
820 if (i
[1] != i
[7] && i
[3] != i
[5]) {
821 o
[0] = i
[3] == i
[1] ? i
[3] : i
[4];
822 o
[1] = (i
[3] == i
[1] && i
[4] != i
[2]) ||
823 (i
[1] == i
[5] && i
[4] != i
[0]) ? i
[1] : i
[4];
824 o
[2] = i
[1] == i
[5] ? i
[5] : i
[4];
825 o
[3] = (i
[3] == i
[1] && i
[4] != i
[6]) ||
826 (i
[3] == i
[1] && i
[4] != i
[0]) ? i
[3] : i
[4];
828 o
[5] = (i
[1] == i
[5] && i
[4] != i
[8]) ||
829 (i
[7] == i
[5] && i
[4] != i
[2]) ? i
[5] : i
[4];
830 o
[6] = i
[3] == i
[7] ? i
[3] : i
[4];
831 o
[7] = (i
[3] == i
[7] && i
[4] != i
[8]) ||
832 (i
[7] == i
[5] && i
[4] != i
[6]) ? i
[7] : i
[4];
833 o
[8] = i
[7] == i
[5] ? i
[5] : i
[4];
838 for (n
= 0; n
< 9; n
++)
843 #define DOUBLE_DUMP_S2X(NAME,TYPE) \
844 void NAME(unsigned char * screen, TYPE * dscreen) { \
846 l = _qdgdfv_screen_x_size * 2; \
847 screen += _qdgdfv_screen_x_size + 1; \
848 for(n = 0; n < _qdgdfv_screen_y_size - 2; n++) { \
849 for(m = 0; m < _qdgdfv_screen_x_size; m++) { \
851 qdgdfv_scale2x_p(screen, _qdgdfv_screen_x_size, o); \
853 *dscreen = (TYPE)_qdgdfv_extended_palette[o[0]]; \
854 *(dscreen + l) = (TYPE)_qdgdfv_extended_palette[o[2]]; \
856 *dscreen = (TYPE)_qdgdfv_extended_palette[o[1]]; \
857 *(dscreen + l) = (TYPE)_qdgdfv_extended_palette[o[3]]; \
863 DOUBLE_DUMP_S2X(_qdgdfv_s2x_dump1_screen
, char)
864 DOUBLE_DUMP_S2X(_qdgdfv_s2x_dump2_screen
, short)
865 DOUBLE_DUMP_S2X(_qdgdfv_s2x_dump4_screen
, int)
867 #define TRIPLE_DUMP_S3X(NAME,TYPE) \
868 void NAME(unsigned char * screen, TYPE * dscreen) { \
870 l = _qdgdfv_screen_x_size * 3; \
871 l2 = _qdgdfv_screen_x_size * 3 * 2; \
872 screen += _qdgdfv_screen_x_size + 1; \
873 for(n = 0;n < _qdgdfv_screen_y_size - 2;n++) { \
874 for(m = 0;m < _qdgdfv_screen_x_size;m++) { \
876 qdgdfv_scale3x_p(screen, _qdgdfv_screen_x_size, o); \
878 *dscreen = (TYPE)_qdgdfv_extended_palette[o[0]]; \
879 *(dscreen + l) = (TYPE)_qdgdfv_extended_palette[o[3]]; \
880 *(dscreen + l2) = (TYPE)_qdgdfv_extended_palette[o[6]]; \
882 *dscreen = (TYPE)_qdgdfv_extended_palette[o[1]]; \
883 *(dscreen + l) = (TYPE)_qdgdfv_extended_palette[o[4]]; \
884 *(dscreen + l2) = (TYPE)_qdgdfv_extended_palette[o[7]]; \
886 *dscreen = (TYPE)_qdgdfv_extended_palette[o[2]]; \
887 *(dscreen + l) = (TYPE)_qdgdfv_extended_palette[o[5]]; \
888 *(dscreen + l2) = (TYPE)_qdgdfv_extended_palette[o[8]]; \
894 TRIPLE_DUMP_S3X(_qdgdfv_s3x_dump1_screen
, char)
895 TRIPLE_DUMP_S3X(_qdgdfv_s3x_dump2_screen
, short)
896 TRIPLE_DUMP_S3X(_qdgdfv_s3x_dump4_screen
, int)
900 * qdgdfv_dump_virtual_screen - Dumps the virtual screen.
902 * Dumps the virtual screen into the real one.
905 void qdgdfv_dump_virtual_screen(void)
907 if (_qdgdfv_accum_buffer
) {
910 for (n
= 0; n
< _qdgdfv_screen_x_size
* _qdgdfv_screen_y_size
; n
++)
911 _qdgdfv_virtual_screen
[n
] =
912 _qdgdfv_accum_table
[_qdgdfv_virtual_screen
[n
]]
913 [_qdgdfv_accum_buffer
[n
]];
916 drv
->dump_virtual_screen();
918 if (_qdgdfv_accum_buffer
)
919 memcpy(_qdgdfv_accum_buffer
, _qdgdfv_virtual_screen
,
920 _qdgdfv_screen_x_size
* _qdgdfv_screen_y_size
);
925 * qdgdfv_assert_in_virtual_screen - Asserts that a pointer is inside the virtual screen.
926 * @func: function where the test is happening
929 * Asserts that a pointer falls inside the virtual screen.
930 * If it's outside (less than _qdgdfv_virtual_screen or further the
931 * end of the virtual screen), aborts.
933 void qdgdfv_assert_in_virtual_screen(char *func
, unsigned char *ptr
)
937 diff
= (int) (ptr
- _qdgdfv_virtual_screen
);
939 if (diff
< 0 || diff
>= (_qdgdfv_screen_x_size
* _qdgdfv_screen_y_size
))
940 qdgdfv_bang(func
, qdgdfv_sprintf("virtual screen diff: %d", diff
));
945 * qdgdfv_input_poll - Polls the input system.
947 * Polls the input system, setting the individual key variables
949 * [Keyboard Functions]
951 void qdgdfv_input_poll(void)
958 * qdgdfv_timer - Returns the elapsed time in microseconds.
961 * Returns the elapsed time between calls, in milliseconds. If @reset
962 * is set to 1, the timer is reset any time the function is called,
963 * or accumulative otherwise. It's mainly used for calculating the
964 * elapsed time per frame. It's wise to reset the timer just before
965 * entering the main loop.
966 * [Support Functions]
968 int qdgdfv_timer(int reset
)
970 return (drv
->timer(reset
));
974 #define qdgdfv_max(a,b) ((a) > (b)) ? (a) : (b)
977 * qdgdfv_seek_color - Searches for the nearest matching color.
978 * @r: the red part of the color
979 * @g: the green part of the color
980 * @b: the blue part of the color
982 * Searches the internal palette for the nearest color matching
983 * the r, g and b values. This values must range from 0 to 255.
984 * Returns the selected color.
987 unsigned char qdgdfv_seek_color(int r
, int g
, int b
)
1003 mindif
= 0x7fffffff;
1004 pal
= _qdgdfv_palette
;
1006 for (n
= 0; n
< 256; n
++, pal
+= 3) {
1008 gg
= abs(g
- *(pal
+ 1));
1009 bb
= abs(b
- *(pal
+ 2));
1011 i
= qdgdfv_max(rr
, qdgdfv_max(gg
, bb
));
1019 return (unsigned char) best
;
1024 * qdgdfv_build_light_table - Builds a light table.
1025 * @lut: the buffer where to store the light table
1026 * @levels: number of light levels
1027 * @mid: the level where color is 100%
1029 * Builds a light table. The @lut argument must have enough size to
1030 * store (256 * levels) bytes, and be easily accessed (so it can wisely
1031 * be defined as unsigned char lut[levels][256]). The @mid value
1032 * is the level where color is 100% (i.e. equal to the color itself).
1033 * Below, colors fade to black and above colors saturate to white.
1036 void qdgdfv_build_light_table(unsigned char *lut
, int levels
, int mid
)
1038 qdgdfv_build_light_table_ext(lut
, levels
, mid
, 0, 0, 0);
1043 * qdgdfv_build_light_table_ext - Builds a light table (extended).
1044 * @lut: the buffer where to store the light table
1045 * @levels: number of light levels
1046 * @mid: the level where color is 100%
1047 * @fr: red component of fade color
1048 * @fg: green component of fade color
1049 * @fb: blue component of fade color
1051 * This function is an extended version of qdgdfv_build_light_table().
1052 * Instead of fading to black, this function allows to specify what
1053 * color the dark light levels fade to.
1056 void qdgdfv_build_light_table_ext(unsigned char *lut
, int levels
,
1057 int mid
, int fr
, int fg
, int fb
)
1065 for (n
= 0; n
< levels
; n
++) {
1066 for (m
= 0; m
< 255; m
++) {
1067 r
= _qdgdfv_palette
[m
* 3];
1068 g
= _qdgdfv_palette
[(m
* 3) + 1];
1069 b
= _qdgdfv_palette
[(m
* 3) + 2];
1071 /* old algorithm was r=(r*(n+mid))/levels; */
1073 r
+= ((fr
- r
) / levels
) * (levels
- (n
+ mid
));
1074 g
+= ((fg
- g
) / levels
) * (levels
- (n
+ mid
));
1075 b
+= ((fb
- b
) / levels
) * (levels
- (n
+ mid
));
1077 lut
[(n
* 256) + m
] = qdgdfv_seek_color(r
, g
, b
);
1080 lut
[(n
* 256) + 255] = 255;
1086 * qdgdfv_blend_color - Blends two colors into one.
1089 * @percent: percentage of blending
1091 * Blends two colors into the nearest matching one. If @percent is 100,
1092 * the returned color will be @c1, if it's 0, @c2, or a blending between
1096 unsigned char qdgdfv_blend_color(unsigned char c1
, unsigned char c2
, int percent
)
1106 p
= (int *) &_qdgdfv_palette
[(int) c1
* 3];
1108 r
= (*(p
++) * percent
) / 100;
1109 g
= (*(p
++) * percent
) / 100;
1110 b
= (*p
* percent
) / 100;
1112 percent
= 100 - percent
;
1114 p
= (int *) &_qdgdfv_palette
[(int) c2
* 3];
1116 r
+= (*(p
++) * percent
) / 100;
1117 g
+= (*(p
++) * percent
) / 100;
1118 b
+= (*p
* percent
) / 100;
1120 return qdgdfv_seek_color(r
, g
, b
);
1125 * qdgdfv_set_accum_buffer - Sets or resets the accumulation buffer.
1126 * @percent: percentage of buffer lasting
1128 * If @percent is set to a non zero value (the default), the contents
1129 * of the previous frame is blended with the actual one with the
1130 * specified percent.
1133 void qdgdfv_set_accum_buffer(int percent
)
1137 if (_qdgdfv_accum_buffer
)
1138 free(_qdgdfv_accum_buffer
);
1141 _qdgdfv_accum_buffer
= NULL
;
1143 /* alloc a buffer */
1144 _qdgdfv_accum_buffer
= qdgdfv_malloc(_qdgdfv_screen_x_size
*
1145 _qdgdfv_screen_y_size
);
1148 /* build the table */
1149 for (y
= 0; y
< 256; y
++)
1150 for (x
= 0; x
< 256; x
++)
1151 _qdgdfv_accum_table
[x
][y
] = qdgdfv_blend_color(y
, x
, percent
);
1157 * qdgdfv_extended_key_status - Returns more status about a key.
1158 * @key_var: pointer to the wanted key variable (_qdgdfv_key_up, etc.)
1160 * Returns extended status for the variable pointed by @key_var.
1161 * Returned values are: 0, key not pressed; 1, key just pressed;
1162 * 2, key pressed; 3, key just released; -1, no information about
1164 * [Keyboard Functions]
1166 int qdgdfv_extended_key_status(int *key_var
)
1170 struct __qdgdfv_extended_key_status
*xk
;
1172 for (n
= 0; ret
== -1; n
++) {
1173 xk
= &_qdgdfv_extended_key_status
[n
];
1176 if (xk
->key_var
== NULL
)
1179 /* is this the wanted key? */
1180 if (xk
->key_var
== key_var
) {
1182 ret
= xk
->last_val
== 1 ? 3 : 0;
1184 ret
= xk
->last_val
== 1 ? 2 : 1;
1186 xk
->last_val
= *key_var
;
1195 * qdgdfv_home_dir - Returns the home user directory.
1197 * Returns a system-dependent directory where the user can write
1198 * documents and create subdirectories.
1201 char *qdgdfv_home_dir(void)
1208 * qdgdfv_app_dir - Returns the applications directory.
1210 * Returns a system-dependent directory where the applications store
1211 * their private data, as components or resources.
1214 char *qdgdfv_app_dir(void)
1221 * qdgdfv_opengl - Enables or disables the use of OpenGL.
1222 * @onoff: boolean value
1224 * Enables or disables the use of OpenGL using the @onoff argument.
1225 * Returns 1 if the operation succeeded or 0 if not. When the OpenGL
1226 * mode is active, OpenGL code can be used before dumping the virtual
1230 int qdgdfv_opengl(int onoff
)
1234 if (drv
->opengl
!= NULL
)
1235 ret
= drv
->opengl(onoff
);
1242 * qdgdfv_startup - Inits the video system.
1244 * Starts up the video system.
1247 void qdgdfv_startup(void)
1252 if ((logger
= getenv("QDGDF_LOG")) != NULL
) {
1253 _qdgdfv_use_logger
= 1;
1254 strncpy(_qdgdfv_logger_file
, logger
, sizeof(_qdgdfv_logger_file
) - 1);
1255 _qdgdfv_logger_file
[sizeof(_qdgdfv_logger_file
)] = '\0';
1259 if (_qdgdfv_scale
== 0)
1260 _qdgdfv_scale
= _qdgdfv_double_mode
? 2 : 1;
1262 if (!TRY_VIDEO_DRIVERS())
1263 qdgdfv_bang("qdgdfv_startup", "No usable video driver found");
1265 qdgdfv_set_palette();
1267 atexit(qdgdfv_shutdown
);
1272 * qdgdfv_shutdown - Shuts down the video system.
1274 * Shuts down the video system.
1277 void qdgdfv_shutdown(void)