maug
Quick and dirty C mini-augmentation library.
retroflt.h
Go to the documentation of this file.
1
2#ifndef RETROFLT_H
3#define RETROFLT_H
4
5#ifdef RETROFLAT_OPENGL
6# define RETROFLAT_BMP_TEX
7#endif /* RETROFLAT_OPENGL */
8
19typedef int16_t retroflat_tile_t;
20
21typedef int16_t retrotile_coord_t;
22
280/* === Generic Includes and Defines === */
281
282#ifndef RETROFLAT_BITMAP_TRACE_LVL
283# define RETROFLAT_BITMAP_TRACE_LVL 0
284#endif /* !RETROFLAT_BITMAP_TRACE_LVL */
285
286#ifndef RETROINPUT_TRACE_LVL
287# define RETROINPUT_TRACE_LVL 0
288#endif /* !RETROINPUT_TRACE_LVL */
289
290#include <stdarg.h>
291
292#include <marge.h>
293
309#define RETROFLAT_COLOR_TABLE( f ) \
310 f( 0, black, BLACK, 0, 0, 0, BLACK, BLACK ) \
311 f( 1, darkblue, DARKBLUE, 0, 0, 170, CYAN, BLACK ) \
312 f( 2, darkgreen, DARKGREEN, 0, 170, 0, CYAN, BLACK ) \
313 f( 3, teal, TEAL, 0, 170, 170, CYAN, CYAN ) \
314 f( 4, darkred, DARKRED, 170, 0, 0, MAGENTA, BLACK ) \
315 f( 5, violet, VIOLET, 170, 0, 170, MAGENTA, BLACK ) \
316 f( 6, brown, BROWN, 170, 85, 0, CYAN, MAGENTA ) \
317 f( 7, gray, GRAY, 170, 170, 170, WHITE, BLACK ) \
318 f( 8, darkgray, DARKGRAY, 85, 85, 85, WHITE, BLACK ) \
319 f( 9, blue, BLUE, 85, 85, 255, CYAN, WHITE ) \
320 f( 10, green, GREEN, 85, 255, 85, CYAN, CYAN ) \
321 f( 11, cyan, CYAN, 85, 255, 255, CYAN, CYAN ) \
322 f( 12, red, RED, 255, 85, 85, MAGENTA, WHITE ) \
323 f( 13, magenta, MAGENTA, 255, 85, 255, MAGENTA, MAGENTA ) \
324 f( 14, yellow, YELLOW, 255, 255, 85, CYAN, MAGENTA ) \
325 f( 15, white, WHITE, 255, 255, 255, WHITE, WHITE )
326
328typedef int8_t RETROFLAT_COLOR;
329
330# define RETROFLAT_COLOR_NULL (-1)
331
332# define RETROFLAT_COLORS_CT 16
333
336/* TODO: Mouse is broken under DOS/Allegro. */
337#if defined( RETROFLAT_OS_UNIX ) || defined( RETROFLAT_OS_WIN )
338#define RETROFLAT_MOUSE
339#endif /* RETROFLAT_OS_WIN || RETROFLAT_OS_WIN */
340
348#define RETROFLAT_OK 0x00
349#define RETROFLAT_ERROR_ENGINE 0x01
350#define RETROFLAT_ERROR_GRAPHICS 0x02
351#define RETROFLAT_ERROR_MOUSE 0x04
352
357#define RETROFLAT_ERROR_BITMAP 0x08
358#define RETROFLAT_ERROR_TIMER 0x0f
359 /* maug_retroflt_retval */
361
376#define RETROFLAT_DRAW_FLAG_FILL 0x01
377
384#define RETROFLAT_FONT_FLAG_ALL_CAPS 0x02
385 /* maug_retroflt_drawing */
387
394#define RETROFLAT_STATE_FLAG_RUNNING 0x01
395
401#define RETROFLAT_STATE_FLAG_UNLOCK_FPS 0x02
402
408#define RETROFLAT_STATE_FLAG_KEY_REPEAT 0x04
409
415#define RETROFLAT_STATE_FLAG_SCREENSAVER 0x08
416
420#define RETROFLAT_STATE_FLAG_HWSCROLLING 0x10
421
426#define RETROFLAT_STATE_FLAG_WAIT_FOR_FPS 0x20
427
432#define RETROFLAT_STATE_FLAG_USE_GXC 0x40
433
438#define RETROFLAT_STATE_FLAG_QUIT_REQUESTED 0x80
439
450#define RETROFLAT_MSG_FLAG_TYPE_MASK 0x07
451
456#define RETROFLAT_MSG_FLAG_ERROR 0x01
457
463#define RETROFLAT_MSG_FLAG_INFO 0x02
464
470#define RETROFLAT_MSG_FLAG_WARNING 0x04
471 /* maug_retroflt_msg_api */
473
474struct RETROFLAT_STATE;
475
495#define RETROFLAT_VDP_FLAG_PXLOCK 0x01
496
509
510#define retroflat_vdp_available() (NULL != g_retroflat_state->vdp_exe)
511 /* maug_retroflt_vdp */
513
519typedef MERROR_RETVAL (*retroflat_proc_resize_t)(
520 uint16_t new_w, uint16_t new_h, void* data );
521
522#define RETROFLAT_FOCUS_FLAG_ACTIVE 0x01
523
524#define RETROFLAT_FOCUS_FLAG_VISIBLE 0x02
525
526typedef MERROR_RETVAL (*retroflat_proc_focus_t)( uint8_t flags, void* data );
527
532typedef MERROR_RETVAL (*retroflat_proc_quit_t)( void* data );
533 /* maug_retroflt_platform */
535
541#define RETROSND_ARGS_FLAG_LIST_DEVS 0x01
542
575#define RETROFLAT_BITMAP_FLAG_OPAQUE 0x01
576
580#define RETROFLAT_BITMAP_FLAG_LITERAL_PATH 0x02
581
585#define RETROFLAT_BITMAP_FLAG_RO 0x04
586
593#define RETROFLAT_BITMAP_FLAG_SCREEN_BUFFER 0x08
594
598#define RETROFLAT_BITMAP_FLAG_SCREEN_LOCK 0x20
599
603#define RETROFLAT_BITMAP_FLAG_LOCK 0x40
604
610#define RETROFLAT_INSTANCE_NULL (0)
611
616#define retroflat_instance_tile( instance ) \
617 (0 - (instance))
618
623#ifndef RETROFLAT_BITMAP_EXT
624# define RETROFLAT_BITMAP_EXT "bmp"
625#endif /* !RETROFLAT_BITMAP_EXT */
626
627#ifndef RETROFLAT_OPENGL_BPP
628# define RETROFLAT_OPENGL_BPP 32
629#endif /* !RETROFLAT_OPENGL_BPP */
630
631#ifndef RETROFLAT_TILE_W
632# define RETROFLAT_TILE_W 16
633#endif /* !RETROFLAT_TILE_W */
634
635#ifndef RETROFLAT_TILE_W_BITS
636# define RETROFLAT_TILE_W_BITS 4
637#endif /* !RETROFLAT_TILE_W_BITS */
638
639#ifndef RETROFLAT_TILE_H
640# define RETROFLAT_TILE_H 16
641#endif /* !RETROFLAT_TILE_H */
642
643#ifndef RETROFLAT_TILE_H_BITS
644# define RETROFLAT_TILE_H_BITS 4
645#endif /* !RETROFLAT_TILE_H_BITS */
646
647/* Transparency background color: black by default, to match Allegro. */
648#ifndef RETROFLAT_TXP_R
654# define RETROFLAT_TXP_R 0x00
655#endif /* !RETROFLAT_TXP_R */
656
657#ifndef RETROFLAT_TXP_G
663# define RETROFLAT_TXP_G 0x00
664#endif /* !RETROFLAT_TXP_G */
665
666#ifndef RETROFLAT_TXP_B
672# define RETROFLAT_TXP_B 0x00
673#endif /* !RETROFLAT_TXP_B */
674
675#ifndef RETROFLAT_TXP_PAL_IDX
676# define RETROFLAT_TXP_PAL_IDX 0
677#endif /* !RETROFLAT_TXP_PAL_IDX */
678 /* maug_retroflt_bitmap */
680
681#ifndef RETROFLAT_DEFAULT_SCREEN_W
682# define RETROFLAT_DEFAULT_SCREEN_W 320
683#endif /* !RETROFLAT_DEFAULT_SCREEN_W */
684
685#ifndef RETROFLAT_DEFAULT_SCREEN_H
686# define RETROFLAT_DEFAULT_SCREEN_H 200
687#endif /* !RETROFLAT_DEFAULT_SCREEN_H */
688
689#ifndef RETROFLAT_DEFAULT_SCREEN_SCALE
690# define RETROFLAT_DEFAULT_SCREEN_SCALE 1
691#endif /* !RETROFLAT_DEFAULT_SCREEN_SCALE */
692
693#define retroflat_on_resize( w, h ) \
694 g_retroflat_state->screen_w = (w); \
695 g_retroflat_state->screen_h = (h);
696
702#ifndef RETROFLAT_LINE_THICKNESS
707# define RETROFLAT_LINE_THICKNESS 1
708#endif /* !RETROFLAT_LINE_THICKNESS */
709
710#define RETROFLAT_PI 3.14159
711 /* maug_retroflt_drawing */
713
719#ifndef RETROFLAT_FPS
724# define RETROFLAT_FPS 30
725#endif /* !RETROFLAT_FPS */
726
727#define retroflat_fps_next() (1000 / RETROFLAT_FPS)
728
729#ifndef RETROFLAT_WINDOW_CLASS
734# define RETROFLAT_WINDOW_CLASS "RetroFlatWindowClass"
735#endif /* !RETROFLAT_WINDOW_CLASS */
736
737#ifndef RETROFLAT_WIN_FRAME_TIMER_ID
742# define RETROFLAT_WIN_FRAME_TIMER_ID 6001
743#endif /* !RETROFLAT_WIN_FRAME_TIMER_ID */
744
745#ifndef RETROFLAT_WIN_LOOP_TIMER_ID
750# define RETROFLAT_WIN_LOOP_TIMER_ID 6002
751#endif /* !RETROFLAT_WIN_LOOP_TIMER_ID */
752
753#ifndef RETROFLAT_MSG_MAX
758# define RETROFLAT_MSG_MAX 4096
759#endif /* !RETROFLAT_MSG_MAX */
760
761#ifndef RETROFLAT_TITLE_MAX
762# define RETROFLAT_TITLE_MAX 255
763#endif /* !RETROFLAT_TITLE_MAX */
764
765#ifndef RETROFLAT_VDP_ARGS_SZ_MAX
769# define RETROFLAT_VDP_ARGS_SZ_MAX 255
770#endif /* !RETROFLAT_VDP_ARGS_SZ_MAX */
771
772#if defined( RETROFLAT_API_SDL2 )
773# if !defined( NO_RETROFLAT_RESIZABLE )
774# define RETROFLAT_WIN_FLAGS SDL_WINDOW_RESIZABLE
775# else
776# define RETROFLAT_WIN_FLAGS 0
777# endif /* !NO_RETROFLAT_RESIZABLE */
778#endif /* RETROFLAT_API_SDL2 */
779
780#if defined( RETROFLAT_API_SDL1 )
781# define RETROFLAT_SDL_CC_FLAGS (SDL_RLEACCEL | SDL_SRCCOLORKEY)
782#elif defined( RETROFLAT_API_SDL2 )
783# define RETROFLAT_SDL_CC_FLAGS (SDL_TRUE)
784#endif /* RETROFLAT_API_SDL1 || RETROFLAT_API_SDL2 */
785
786#ifdef RETROFLAT_OS_DOS
787# define RETROFLAT_PATH_SEP '\\'
788#else
790# define RETROFLAT_PATH_SEP '/'
791#endif /* RETROFLAT_OS_DOS */
792
793#ifndef RETROFLAT_COLORS_CT_MAX
794# define RETROFLAT_COLORS_CT_MAX 256
795#endif /* !RETROFLAT_COLORS_CT_MAX */
796
797#ifndef RETROFLAT_TIMER_CT_MAX
798# define RETROFLAT_TIMER_CT_MAX 10
799#endif /* !RETROFLAT_TIMER_CT_MAX */
800 /* maug_retroflt_compiling */
802
803#define retroflat_wait_for_frame() \
804 (g_retroflat_state->retroflat_flags |= RETROFLAT_STATE_FLAG_WAIT_FOR_FPS)
805
806#define retroflat_is_waiting_for_frame() \
807 (RETROFLAT_STATE_FLAG_WAIT_FOR_FPS == \
808 (g_retroflat_state->retroflat_flags & RETROFLAT_STATE_FLAG_WAIT_FOR_FPS))
809
813typedef void (*retroflat_loop_iter)(void* data);
814
815uint32_t retroflat_get_rand( void );
816
826#define retroflat_buffer_bksp( buffer, buffer_cur, buffer_sz ) \
827 if( 0 < buffer_cur ) { \
828 if( buffer_cur < buffer_sz ) { \
829 memmove( \
830 &(buffer[(buffer_cur) - 1]), \
831 &(buffer[buffer_cur]), \
832 (buffer_sz) - (buffer_cur) ); \
833 } \
834 buffer_cur--; \
835 buffer_sz--; \
836 buffer[buffer_sz] = '\0'; \
837 }
838
842#define retroflat_buffer_insert( c, buffer, buffer_cur, buffer_sz, buffer_mx ) \
843 if( buffer_sz + 1 < buffer_mx ) { \
844 if( buffer_cur < buffer_sz ) { \
845 memmove( \
846 &(buffer[(buffer_cur) + 1]), \
847 &(buffer[buffer_cur]), \
848 (buffer_sz) - (buffer_cur) ); \
849 } \
850 buffer[buffer_cur] = c; \
851 buffer_cur++; \
852 buffer_sz++; \
853 buffer[buffer_sz] = '\0'; \
854 }
855
856#define RETROFLAT_INPUT_MOD_SHIFT 0x01
857
858#define RETROFLAT_INPUT_MOD_ALT 0x02
859
860#define RETROFLAT_INPUT_MOD_CTRL 0x04
861
862#define RETROFLAT_INPUT_FORCE_UPPER 0x08
863
876 uint8_t key_flags;
877};
878 /* maug_retroflt_input */
880
888typedef int8_t retroflat_dir4_t;
889
890typedef int8_t retroflat_dir8_t;
891
892#define RETROFLAT_DIR4_NONE (-1)
893#define RETROFLAT_DIR4_NORTH 0
894#define RETROFLAT_DIR4_EAST 1
895#define RETROFLAT_DIR4_SOUTH 2
896#define RETROFLAT_DIR4_WEST 3
897
898#define RETROFLAT_DIR8_NONE (-1)
899#define RETROFLAT_DIR8_NORTH 0
900#define RETROFLAT_DIR8_EAST 2
901#define RETROFLAT_DIR8_SOUTH 4
902#define RETROFLAT_DIR8_WEST 6
903
904#define retroflat_dir4_rotate_cw( dir ) \
905 ((dir + 1) % 4)
906
907#define retroflat_dir8_reverse( dir ) \
908 ((dir + 4) % 8)
909
910#define retroflat_dir8_bounce( dir ) \
911 ((dir + 2) % 8)
912 /* maug_retroflt_dir */
914
915#define retroflat_outside_rect( x, y, rx, ry, rw, rh ) \
916 ((unsigned int)(x - rx) >= (unsigned int)rw || \
917 (unsigned int)(y - ry) >= (unsigned int)rh)
918
925typedef int16_t retroflat_pxxy_t;
926
927#define PXXY_FMT "%d"
928
929#define PXXY_MAX INT16_MAX
930
931struct RETROFLAT_ARGS;
932
933#ifndef RETRO2D_TRACE_LVL
934# define RETRO2D_TRACE_LVL 0
935#endif /* !RETRO2D_TRACE_LVL */
936
937#ifndef RETRO2D_DRAW_TRACE_LVL
938# define RETRO2D_DRAW_TRACE_LVL 0
939#endif /* !RETRO2D_DRAW_TRACE_LVL */
940
941#ifndef RETRO2D_LOCK_TRACE_LVL
942# define RETRO2D_LOCK_TRACE_LVL 0
943#endif /* !RETRO2D_LOCK_TRACE_LVL */
944
945typedef maug_ms_t retroflat_ms_t;
946
947retroflat_ms_t retroflat_get_ms( void );
948
949#ifndef RETROFLAT_NO_SOUND
950# include "retrosnd.h"
951#endif /* !RETROFLAT_NO_SOUND */
952
953/* === Platform-specific APIs === */
954
955/* The first call to these headers should just establish definitions (macros, defines, prototypes,
956 * typedefs, etc). The later call below should then define function bodies.
957 */
958#ifndef RETROFLAT_NO_SOUND
959# include <retapis.h>
960#endif /* !RETROFLAT_NO_SOUND */
961#include <retapii.h>
962
963/* === End platform-specific APIs === */
964
970# if defined( RETROFLAT_NO_KEYBOARD )
971# define retroflat_case_key( key, pad ) case pad:
972# define retroflat_or_key( input, key, pad ) ((input) == (pad))
973# elif defined( RETROFLAT_NO_PAD )
974# define retroflat_case_key( key, pad ) case key:
975# define retroflat_or_key( input, key, pad ) ((input) == (key))
976# else
984# define retroflat_case_key( key, pad ) case pad: case key:
985# define retroflat_or_key( input, key, pad ) \
986 (((input) == (pad)) || ((input) == (key)))
987# endif
988 /* maug_retroflt_input */
990
991/* === OS-Specific Includes and Defines === */
992
993#if defined( RETROFLAT_OS_WIN ) && !defined( MAUG_WINDOWS_H )
994# include <windows.h>
995# define MAUG_WINDOWS_H
996#endif /* !MAUG_WINDOWS_H */
997
998#if defined( RETROFLAT_BMP_TEX ) || defined( DOCUMENTATION )
999
1001 uint8_t flags;
1002 MAUG_MHANDLE bytes_h;
1003 uint8_t* bytes;
1004 uint32_t bpp;
1005 uint32_t sz;
1006 uint8_t* px;
1007 uint32_t id;
1008 size_t w;
1009 size_t h;
1010};
1011
1012#endif /* RETROFLAT_BMP_TEX */
1013
1014/* TODO: Migrate all platform-specific parts below to retapid.h. */
1015#include <retapid.h>
1016
1017#ifndef retroflat_system_task
1023# define retroflat_system_task()
1024#endif /* !retroflat_system_task */
1025
1026typedef void (*retroflat_timer_cb_t)( retroflat_ms_t time, void* data );
1027
1028#include "retrom2d.h"
1029
1030/* === Structures === */
1031
1032/* TODO: Break the args into API-specific headers. */
1033
1036 uint8_t flags;
1041 char* title;
1064 int screen_scale;
1072 int joystick_id;
1073 struct RETROFLAT_PLATFORM_ARGS platform;
1074# ifndef RETROFLAT_NO_SOUND
1075 struct RETROFLAT_SOUND_ARGS sound;
1076# endif /* !RETROFLAT_NO_SOUND */
1077};
1078
1083# define retroflat_screen_colors() (g_retroflat_state->screen_colors)
1084
1091#define retroflat_heartbeat_set( len, max ) \
1092 g_retroflat_state->heartbeat_max = max; \
1093 g_retroflat_state->heartbeat_len = len;
1094
1099#define retroflat_heartbeat() (g_retroflat_state->heartbeat_frame)
1100
1108#define retroflat_heartbeat_update() \
1109 /* Update the heartbeat animation frame. */ \
1110 if( g_retroflat_state->heartbeat_next <= retroflat_get_ms() ) { \
1111 g_retroflat_state->heartbeat_frame++; \
1112 if( \
1113 g_retroflat_state->heartbeat_frame >= \
1114 g_retroflat_state->heartbeat_max \
1115 ) { \
1116 g_retroflat_state->heartbeat_frame = 0; \
1117 } \
1118 g_retroflat_state->heartbeat_next = \
1119 retroflat_get_ms() + g_retroflat_state->heartbeat_len; \
1120 }
1121
1122#include <retrovi2.h>
1123
1131 /* TODO: Set this up in the initialization function! */
1132 /* TODO: We probably need more of these. */
1133 size_t sz;
1134 size_t offset_pal;
1135 size_t offset_tex_pal;
1136
1137 void* loop_data;
1138 MERROR_RETVAL retval;
1141 maug_path config_path;
1142 maug_path assets_path;
1143 maug_path saves_path;
1144
1146 /* struct RETROFLAT_BITMAP buffer; */
1148
1149# if defined( RETROFLAT_VDP ) || defined( DOCUMENTATION ) || \
1150defined( RETROVDP_C )
1158 struct RETROFLAT_BITMAP* vdp_buffer_in;
1159 struct RETROFLAT_BITMAP* vdp_buffer_out;
1160# ifdef RETROFLAT_OS_WIN
1161 HMODULE vdp_exe;
1162# else
1164 void* vdp_exe;
1165# endif /* RETROFLAT_OS_WIN */
1174 uint8_t vdp_flags;
1175# endif /* RETROFLAT_VDP || DOCUMENTATION || RETROVDP_C */
1176
1177 /* These are used by VDP so should be standardized/not put in plat-spec! */
1178
1179 struct RETROFLAT_VIEWPORT viewport;
1180
1196 size_t screen_w;
1198 size_t screen_h;
1201
1202 /* WARNING: The VDP requires the state specifier to be the same size
1203 * as the one it was compiled for! Do not modify above here!
1204 */
1205
1206 /* TODO: Put these in a platform-specific struct of some kind to maintain
1207 * consistent state struct size for VDP?
1208 */
1209
1210 retroflat_ms_t heartbeat_next;
1228
1230 retroflat_proc_resize_t on_resize;
1231 void* on_resize_data;
1232
1234 retroflat_proc_focus_t on_focus;
1235 void* on_focus_data;
1238
1241 void* on_quit_data;
1242
1243#ifndef RETROFLAT_BMP_TEX
1245 RETROFLAT_COLOR_DEF palette[RETROFLAT_COLORS_CT_MAX];
1246#endif /* !RETROFLAT_BMP_TEX */
1247
1248 retroflat_loop_iter loop_iter;
1249 retroflat_loop_iter frame_iter;
1250
1251 struct RETROFLAT_PLATFORM platform;
1252
1253# if defined( RETROFLAT_BMP_TEX )
1254 /* This allows native colors to be used for things like glColor3fv while
1255 * these colors are used to manipulate textures passed through
1256 * retroflat_bitmap_*().
1257 */
1258 RETROFLAT_TEX_COLOR_DEF tex_palette[RETROFLAT_COLORS_CT_MAX];
1259# endif /* RETROFLAT_BMP_TEX */
1260
1261 struct RETROFLAT_INPUT_STATE input;
1262
1267 retroflat_timer_cb_t timers_cb[RETROFLAT_TIMER_CT_MAX];
1268 retroflat_ms_t timers_at[RETROFLAT_TIMER_CT_MAX];
1269 void* timers_data[RETROFLAT_TIMER_CT_MAX];
1270 size_t timers_ct;
1271
1272# ifndef RETROFLAT_NO_SOUND
1273 struct RETROFLAT_SOUND_STATE sound;
1274# endif /* !RETROFLAT_NO_SOUND */
1275};
1276
1277/* === Translation Module === */
1278
1279/* Declare the prototypes so that internal functions can call each other. */
1280
1281# ifdef retroflat_loop
1282MERROR_RETVAL retroflat_loop_generic(
1283 retroflat_loop_iter frame_iter, retroflat_loop_iter loop_iter, void* data );
1284# else
1291 retroflat_loop_iter frame_iter, retroflat_loop_iter loop_iter, void* data );
1292# endif /* retroflat_loop */
1293
1294#define retroflat_get_assets_path() (g_retroflat_state->assets_path)
1295
1296MERROR_RETVAL retroflat_build_filename_path(
1297 const maug_path filename_in, const char* filename_ext,
1298 char* buffer_out, size_t buffer_out_sz, uint8_t flags );
1299
1312 uint8_t flags, const char* title, const char* format, ... );
1313 /* maug_retroflt_msg_api */
1315
1323MERROR_RETVAL retroflat_init( int argc, char* argv[], struct RETROFLAT_ARGS* args );
1324
1331void retroflat_shutdown( int retval );
1332
1333# if defined( RETROFLAT_VDP ) || defined( DOCUMENTATION )
1342MERROR_RETVAL retroflat_vdp_call( const char* proc_name );
1343
1344uint8_t* retroflat_vdp_get_vdp_in( void );
1345
1346uint8_t* retroflat_vdp_get_vdp_out( void );
1347 /* maug_retroflt_vdp */
1349# endif /* RETROFLAT_VDP || DOCUMENTATION */
1350
1351RETROFLAT_IN_KEY retroflat_repeat_input(
1352 RETROFLAT_IN_KEY key_out, struct RETROFLAT_INPUT* input,
1353 RETROFLAT_IN_KEY* prev_input, int* prev_delay );
1354
1355void retroflat_set_title( const char* format, ... );
1356
1357# if !defined( RETROFLAT_NO_KEYBOARD )
1358char retroflat_vk_to_ascii( RETROFLAT_IN_KEY k, uint8_t flags );
1359# endif /* !RETROFLAT_NO_KEYBOARD */
1360
1377 const char* filename, struct RETROFLAT_BITMAP* bmp_out, uint8_t flags );
1378
1379MERROR_RETVAL retroflat_create_bitmap(
1381 struct RETROFLAT_BITMAP* bmp_out, uint8_t flags );
1382
1388void retroflat_destroy_bitmap( struct RETROFLAT_BITMAP* bitmap );
1389
1406 struct RETROFLAT_BITMAP* target, struct RETROFLAT_BITMAP* src,
1410 int16_t instance );
1411 /* maug_retroflt_bitmap */
1413
1428MERROR_RETVAL retroflat_draw_lock( struct RETROFLAT_BITMAP* bmp );
1429
1430MERROR_RETVAL retroflat_draw_release( struct RETROFLAT_BITMAP* bmp );
1431
1432void retroflat_px(
1433 struct RETROFLAT_BITMAP* target, const RETROFLAT_COLOR color,
1434 retroflat_pxxy_t x, retroflat_pxxy_t y, uint8_t flags );
1435
1436#ifdef RETROFLAT_SOFT_SHAPES
1437# ifdef RETROFLAT_OPENGL
1438/* Make sure we're not passing NULL to openGL texture drawers... they can't
1439 * handle that!
1440 */
1441# define retroflat_rect( t, c, x, y, w, h, f ) \
1442 assert( NULL != t ); \
1443 retrosoft_rect( t, c, x, y, w, h, f );
1444# define retroflat_ellipse( t, c, x, y, w, h, f ) \
1445 assert( NULL != t ); \
1446 retrosoft_ellipse( t, c, x, y, w, h, f )
1447# else
1448# define retroflat_rect( t, c, x, y, w, h, f ) \
1449 retrosoft_rect( t, c, x, y, w, h, f )
1450# define retroflat_ellipse( t, c, x, y, w, h, f ) \
1451 retrosoft_ellipse( t, c, x, y, w, h, f )
1452# endif /* RETROFLAT_3D */
1453#else
1454
1466 struct RETROFLAT_BITMAP* target, const RETROFLAT_COLOR color,
1468 retroflat_pxxy_t w, retroflat_pxxy_t h, uint8_t flags );
1469
1481 struct RETROFLAT_BITMAP* target, const RETROFLAT_COLOR color,
1483 retroflat_pxxy_t w, retroflat_pxxy_t h, uint8_t flags );
1484
1485#endif /* RETROFLAT_SOFT_SHAPES */
1486
1487#ifdef RETROFLAT_SOFT_LINES
1488# define retroflat_line( t, c, x1, y1, x2, y2, f ) \
1489 retrosoft_line( t, c, x1, y1, x2, y2, f )
1490#else
1491
1504 struct RETROFLAT_BITMAP* target, const RETROFLAT_COLOR color,
1506 retroflat_pxxy_t x2, retroflat_pxxy_t y2, uint8_t flags );
1507
1508#endif /* RETROFLAT_SOFT_LINES */
1509
1510#ifndef RETROFLAT_CLIP_TRACE_LVL
1511# define RETROFLAT_CLIP_TRACE_LVL 0
1512#endif /* !RETROFLAT_CLIP_TRACE_LVL */
1513
1514#ifdef RETROFLAT_CLIP_GENERIC
1515
1516#if RETROFLAT_CLIP_TRACE_LVL > 0
1517# define retroflat_clip_px( x, y, bmp, retact ) \
1518 if( \
1519 x < bmp->clip_l || \
1520 y < bmp->clip_t || \
1521 x >= bmp->clip_r || \
1522 y >= bmp->clip_b \
1523 ) { \
1524 debug_printf( RETROFLAT_CLIP_TRACE_LVL, \
1525 "attempted draw at %d, %d, out of bounds %d, %d, %d, %d", \
1526 x, y, bmp->clip_l, bmp->clip_t, bmp->clip_r, bmp->clip_b ); \
1527 retact; \
1528 }
1529#else
1530# define retroflat_clip_px( x, y, bmp, retact ) \
1531 if( \
1532 x < bmp->clip_l || \
1533 y < bmp->clip_t || \
1534 x >= bmp->clip_r || \
1535 y >= bmp->clip_b \
1536 ) { \
1537 retact; \
1538 }
1539#endif /* RETROFLAT_CLIP_TRACE_LVL */
1540
1541#endif /* RETROFLAT_CLIP_GENERIC */
1542
1543void retroflat_set_clip(
1544 struct RETROFLAT_BITMAP* target,
1547
1548void retroflat_cursor( struct RETROFLAT_BITMAP* target, uint8_t flags );
1549
1550#define retroflat_blank( target, color ) \
1551 retroflat_rect( \
1552 target, color, 0, 0, \
1553 retroflat_bitmap_w( NULL == target ? retroflat_screen_buffer() : target )\
1554 , \
1555 retroflat_bitmap_h( NULL == target ? retroflat_screen_buffer() : target )\
1556 , RETROFLAT_DRAW_FLAG_FILL );
1557
1558/* TODO: Documentation! */
1559void retroflat_get_palette( uint8_t idx, uint32_t* rgb );
1560
1561MERROR_RETVAL retroflat_set_palette( uint8_t idx, uint32_t rgb );
1562 /* maug_retroflt_bitmap */
1564
1581 retroflat_proc_resize_t on_resize_in, void* data_in );
1582
1588 retroflat_ms_t time, retroflat_timer_cb_t cb, void* data );
1589
1599 retroflat_proc_focus_t on_focus_in, void* data_in );
1600
1610 retroflat_proc_quit_t on_quit_in, void* data_in );
1611
1625#define retroflat_soft_quit( retval ) \
1626 if( \
1627 NULL == g_retroflat_state->on_quit || \
1628 MERROR_PREEMPT != g_retroflat_state->on_quit( \
1629 g_retroflat_state->on_quit_data \
1630 ) ) { \
1631 retroflat_quit( retval ); \
1632 }
1633
1639
1645
1651 /* maug_retroflt_platform_handler */
1653 /* maug_retroflt_platform */
1655
1666RETROFLAT_IN_KEY retroflat_poll_input( struct RETROFLAT_INPUT* input );
1667 /* maug_retroflt_input */
1669
1670#ifdef RETROFLT_C
1671
1672MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets8_x[8] =
1673 { 0, 1, 1, 1, 0, -1, -1, -1 };
1674MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets8_y[8] =
1675 { -1, -1, 0, 1, 1, 1, 0, -1 };
1676
1677MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets4_x[4] =
1678 { 0, 1, 0, -1 };
1679MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets4_y[4] =
1680 { -1, 0, 1, 0 };
1681
1682MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets4_x_tile[4] =
1683 { 0, RETROFLAT_TILE_W, 0, -RETROFLAT_TILE_W };
1684MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets4_y_tile[4] =
1685 { -RETROFLAT_TILE_H, 0, RETROFLAT_TILE_H, 0 };
1686
1687# ifdef RETROFLAT_STATE_ON_STACK
1688struct RETROFLAT_STATE SEG_MGLOBAL g_retroflat_state_stack;
1689# else
1690MAUG_MHANDLE SEG_MGLOBAL g_retroflat_state_h = (MAUG_MHANDLE)NULL;
1691# endif /* RETROFLAT_STATE_ON_STACK */
1692struct RETROFLAT_STATE* SEG_MGLOBAL g_retroflat_state = NULL;
1693
1694# define RETROFLAT_COLOR_TABLE_CONSTS( idx, name_l, name_u, r, g, b, cgac, cgad ) \
1695 MAUG_CONST RETROFLAT_COLOR SEG_MCONST RETROFLAT_COLOR_ ## name_u = idx;
1696
1697RETROFLAT_COLOR_TABLE( RETROFLAT_COLOR_TABLE_CONSTS )
1698
1699# define RETROFLAT_COLOR_TABLE_NAMES( idx, name_l, name_u, r, g, b, cgac, cgad ) \
1700 #name_u,
1701
1702MAUG_CONST char* SEG_MCONST gc_retroflat_color_names[] = {
1703 RETROFLAT_COLOR_TABLE( RETROFLAT_COLOR_TABLE_NAMES )
1704};
1705
1706/* Call a second time, to add function bodies. */
1707#include <retrovi2.h>
1708
1709/* Callback table is down below, after the statically-defined callbacks. */
1710
1711/* === Function Definitions === */
1712
1713MERROR_RETVAL retroflat_build_filename_path(
1714 const maug_path filename_in, const char* filename_ext,
1715 char* buffer_out, size_t buffer_out_sz, uint8_t flags
1716) {
1717 MERROR_RETVAL retval = MERROR_OK;
1718
1719 assert( 1 < buffer_out_sz );
1720
1721 /* Build the path to the bitmap. */
1722 maug_mzero( buffer_out, buffer_out_sz );
1723 if(
1726 ) {
1727 /* TODO: Error checking. */
1728 maug_snprintf( buffer_out, buffer_out_sz - 1, "%s", filename_in );
1729 } else if( NULL != filename_ext ) {
1730 /* TODO: Error checking. */
1731 maug_snprintf( buffer_out, buffer_out_sz - 1, "%s%c%s.%s",
1732 g_retroflat_state->assets_path, RETROFLAT_PATH_SEP,
1733 filename_in, filename_ext );
1734 } else {
1735 maug_snprintf( buffer_out, buffer_out_sz - 1, "%s%c%s",
1736 g_retroflat_state->assets_path, RETROFLAT_PATH_SEP,
1737 filename_in );
1738 }
1739
1740 return retval;
1741}
1742
1743/* === */
1744
1745# if (defined( RETROFLAT_SOFT_SHAPES ) || defined( RETROFLAT_SOFT_LINES ) || \
1746 defined( RETROFLAT_3D ))
1747/* RETROSOFT_PRESENT is different from RETROFLAT_SOFT_SHAPES in that it only
1748 * indicates that the retrosoft library is loaded, not that it is the default
1749 * for drawing primatives!
1750 */
1751# define RETROSOFT_PRESENT
1752# endif
1753
1754# if defined( RETROFLAT_3D )
1755# if !defined( MAUG_NO_AUTO_C )
1756# define RETRO3D_C
1757# define RETRO3DP_C
1758# define RETROFP_C
1759# endif /* MAUG_NO_AUTO_C */
1760# include <retro3dp.h>
1761# include <retro3d.h>
1762# include <retro3du.h>
1763# include <retapi3.h>
1764# endif /* RETROFLAT_3D */
1765
1766# ifdef RETROSOFT_PRESENT
1767# if !defined( MAUG_NO_AUTO_C )
1768# define RETROSFT_C
1769# endif /* !MAUG_NO_AUTO_C */
1770# define RETROSOFT_PRESENT
1771# include <retrosft.h>
1772# endif /* RETROFLAT_SOFT_SHAPES */
1773
1774# ifndef RETROFLAT_NO_SOUND
1775# include <retapis.h>
1776# endif /* !RETROFLAT_NO_SOUND */
1777
1778# include <retapii.h>
1779
1780# if defined( RETROFLAT_VDP ) && defined( RETROFLAT_OS_UNIX )
1781# include <dlfcn.h>
1782# endif
1783
1784/* Still inside RETROFLT_C! */
1785
1786/* === */
1787
1788#ifndef RETROFLAT_NO_GENERIC_LOOP
1789
1790MERROR_RETVAL retroflat_loop_generic(
1791 retroflat_loop_iter frame_iter, retroflat_loop_iter loop_iter, void* data
1792) {
1793 MERROR_RETVAL retval = MERROR_OK;
1794 retroflat_ms_t next = 0,
1795 now = 0;
1796
1797 g_retroflat_state->loop_iter = (retroflat_loop_iter)loop_iter;
1798 g_retroflat_state->loop_data = (void*)data;
1799 g_retroflat_state->frame_iter = (retroflat_loop_iter)frame_iter;
1800
1801 if(
1803 (g_retroflat_state->retroflat_flags & RETROFLAT_STATE_FLAG_RUNNING)
1804 ) {
1805 /* Main loop is already running, so we're just changing the iter call
1806 * and leaving!
1807 */
1808 debug_printf( 1, "main loop already running!" );
1809 goto cleanup;
1810 }
1811
1812 g_retroflat_state->retroflat_flags |= RETROFLAT_STATE_FLAG_RUNNING;
1813 do {
1815
1816 if(
1817 /* Not waiting for the next frame? */
1819 (RETROFLAT_STATE_FLAG_WAIT_FOR_FPS & g_retroflat_state->retroflat_flags) &&
1820 /* Inter-frame loop present? */
1821 NULL != g_retroflat_state->loop_iter
1822 ) {
1823 /* Run the loop iter as many times as possible. */
1824 g_retroflat_state->loop_iter( g_retroflat_state->loop_data );
1825 }
1826 if(
1828 (RETROFLAT_STATE_FLAG_UNLOCK_FPS & g_retroflat_state->retroflat_flags) &&
1829 retroflat_get_ms() < next
1830 ) {
1831 /* Sleep/low power for a bit. */
1832 continue;
1833 }
1834
1836
1838
1839 if(
1840 NULL != g_retroflat_state->on_focus &&
1841 g_retroflat_state->last_focus_flags != retroflat_focus_platform()
1842 ) {
1843 g_retroflat_state->last_focus_flags = retroflat_focus_platform();
1844 retval = g_retroflat_state->on_focus(
1845 g_retroflat_state->last_focus_flags,
1846 g_retroflat_state->on_focus_data );
1847 maug_cleanup_if_not_ok();
1848 }
1849
1850 if( NULL != g_retroflat_state->frame_iter ) {
1851 /* Run the frame iterator once per FPS tick. */
1852 g_retroflat_state->frame_iter( g_retroflat_state->loop_data );
1853 }
1854 /* Reset wait-for-frame flag AFTER frame callback. */
1855 g_retroflat_state->retroflat_flags &= ~RETROFLAT_STATE_FLAG_WAIT_FOR_FPS;
1856 now = retroflat_get_ms();
1857 if( now + retroflat_fps_next() > now ) {
1858 next = now + retroflat_fps_next();
1859 } else {
1860 /* Rollover protection. */
1861 /* TODO: Add difference from now/next to 0 here. */
1862 next = 0;
1863 }
1864 } while(
1866 (RETROFLAT_STATE_FLAG_RUNNING & g_retroflat_state->retroflat_flags)
1867 );
1868 retval = g_retroflat_state->retval;
1869
1870cleanup:
1871
1872 /* This should be set by retroflat_quit(). */
1873 return retval;
1874}
1875
1876#endif /* !RETROFLAT_NO_GENERIC_LOOP */
1877
1878/* === */
1879
1880# if !defined( RETROFLAT_NO_KEYBOARD )
1881
1882char retroflat_vk_to_ascii( RETROFLAT_IN_KEY k, uint8_t flags ) {
1883 char c = 0;
1884 char offset_lower = 0;
1885
1886 if( RETROFLAT_INPUT_MOD_SHIFT != (RETROFLAT_INPUT_MOD_SHIFT & flags) ) {
1887 /* Shift is *not* being held down. */
1888
1889 if( RETROFLAT_KEY_A <= k && RETROFLAT_KEY_Z >= k ) {
1890 if(
1891 RETROFLAT_INPUT_FORCE_UPPER !=
1892 (RETROFLAT_INPUT_FORCE_UPPER & flags)
1893 ) {
1894 /* Key is alphabetical and we're not forcing uppercase. */
1895 offset_lower = 0x20;
1896 }
1897 } else {
1898 offset_lower = 1;
1899 }
1900 }
1901
1902 switch( k ) {
1903 case RETROFLAT_KEY_A: c = 0x41 + offset_lower; break;
1904 case RETROFLAT_KEY_B: c = 0x42 + offset_lower; break;
1905 case RETROFLAT_KEY_C: c = 0x43 + offset_lower; break;
1906 case RETROFLAT_KEY_D: c = 0x44 + offset_lower; break;
1907 case RETROFLAT_KEY_E: c = 0x45 + offset_lower; break;
1908 case RETROFLAT_KEY_F: c = 0x46 + offset_lower; break;
1909 case RETROFLAT_KEY_G: c = 0x47 + offset_lower; break;
1910 case RETROFLAT_KEY_H: c = 0x48 + offset_lower; break;
1911 case RETROFLAT_KEY_I: c = 0x49 + offset_lower; break;
1912 case RETROFLAT_KEY_J: c = 0x4a + offset_lower; break;
1913 case RETROFLAT_KEY_K: c = 0x4b + offset_lower; break;
1914 case RETROFLAT_KEY_L: c = 0x4c + offset_lower; break;
1915 case RETROFLAT_KEY_M: c = 0x4d + offset_lower; break;
1916 case RETROFLAT_KEY_N: c = 0x4e + offset_lower; break;
1917 case RETROFLAT_KEY_O: c = 0x4f + offset_lower; break;
1918 case RETROFLAT_KEY_P: c = 0x50 + offset_lower; break;
1919 case RETROFLAT_KEY_Q: c = 0x51 + offset_lower; break;
1920 case RETROFLAT_KEY_R: c = 0x52 + offset_lower; break;
1921 case RETROFLAT_KEY_S: c = 0x53 + offset_lower; break;
1922 case RETROFLAT_KEY_T: c = 0x54 + offset_lower; break;
1923 case RETROFLAT_KEY_U: c = 0x55 + offset_lower; break;
1924 case RETROFLAT_KEY_V: c = 0x56 + offset_lower; break;
1925 case RETROFLAT_KEY_W: c = 0x57 + offset_lower; break;
1926 case RETROFLAT_KEY_X: c = 0x58 + offset_lower; break;
1927 case RETROFLAT_KEY_Y: c = 0x59 + offset_lower; break;
1928 case RETROFLAT_KEY_Z: c = 0x60 + offset_lower; break;
1929 case RETROFLAT_KEY_0: c = offset_lower ? 0x30 : ')'; break;
1930 case RETROFLAT_KEY_1: c = offset_lower ? 0x31 : '!'; break;
1931 case RETROFLAT_KEY_2: c = offset_lower ? 0x32 : '@'; break;
1932 case RETROFLAT_KEY_3: c = offset_lower ? 0x33 : '#'; break;
1933 case RETROFLAT_KEY_4: c = offset_lower ? 0x34 : '$'; break;
1934 case RETROFLAT_KEY_5: c = offset_lower ? 0x35 : '%'; break;
1935 case RETROFLAT_KEY_6: c = offset_lower ? 0x36 : '^'; break;
1936 case RETROFLAT_KEY_7: c = offset_lower ? 0x37 : '&'; break;
1937 case RETROFLAT_KEY_8: c = offset_lower ? 0x38 : '*'; break;
1938 case RETROFLAT_KEY_9: c = offset_lower ? 0x39 : '('; break;
1939 case RETROFLAT_KEY_SPACE: c = ' '; break;
1940 case RETROFLAT_KEY_BKSP: c = 0x08; break;
1941 case RETROFLAT_KEY_ENTER: c = '\n'; break;
1942 case RETROFLAT_KEY_SEMICOLON: c = offset_lower ? ';' : ':'; break;
1943 case RETROFLAT_KEY_DASH: c = offset_lower ? '-' : '_'; break;
1944 case RETROFLAT_KEY_SLASH: c = offset_lower ? '/' : '?'; break;
1945 case RETROFLAT_KEY_PERIOD: c = offset_lower ? '.' : '>'; break;
1946 case RETROFLAT_KEY_COMMA: c = offset_lower ? ',' : '<'; break;
1947 case RETROFLAT_KEY_QUOTE: c = offset_lower ? '\'' : '"'; break;
1948 case RETROFLAT_KEY_EQUALS: c = offset_lower ? '=' : '+'; break;
1949 case RETROFLAT_KEY_BACKSLASH: c = offset_lower ? '\\' : '|'; break;
1950 case RETROFLAT_KEY_BRACKETL: c = offset_lower ? '[' : '{'; break;
1951 case RETROFLAT_KEY_BRACKETR: c = offset_lower ? ']' : '}'; break;
1952#ifndef RETROFLAT_API_PC_BIOS
1953 /* TODO: FIXME in DOS! */
1954 case RETROFLAT_KEY_GRAVE: c = offset_lower ? '`' : '~'; break;
1955#endif /* !RETROFLAT_API_PC_BIOS */
1956 }
1957
1958 debug_printf( RETROINPUT_TRACE_LVL, "0x%02x", c );
1959
1960 return c;
1961}
1962
1963#endif /* !RETROFLAT_NO_KEYBOARD */
1964
1965/* === */
1966
1967/* TODO: Migrate all platform-specific parts below to retapif.h. */
1968#include <retapif.h>
1969
1970/* === */
1971
1972# ifndef RETROFLAT_NO_CLI
1973
1974# if !defined( RETROFLAT_NO_SOUND ) && defined( RETROSND_ARGS )
1975
1976static MERROR_RETVAL retrosnd_cli_rsl(
1977 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
1978) {
1979 if(
1980 0 <= arg_c &&
1981 0 == maug_strncmp( MAUG_CLI_SIGIL "rsl", arg, MAUG_CLI_SIGIL_SZ + 4 )
1982 ) {
1983 args->sound.flags |= RETROSND_ARGS_FLAG_LIST_DEVS;
1984 }
1985 return MERROR_OK;
1986}
1987
1988# endif /* !RETROFLAT_NO_SOUND && RETROSND_ARGS */
1989
1990# if !defined( RETROFLAT_API_PC_BIOS ) && !defined( RETROFLAT_NO_CLI_SZ )
1991
1992static MERROR_RETVAL retroflat_cli_rfs(
1993 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
1994) {
1995 if( 1 < arg_c ) {
1996 args->screen_scale = atoi( arg );
1997 debug_printf( 3, "screen scale arg set to: %d", args->screen_scale );
1998 }
1999 return MERROR_OK;
2000}
2001
2002static MERROR_RETVAL retroflat_cli_rfx(
2003 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2004) {
2005 if( 0 > arg_c ) {
2006 if( 0 == args->screen_w ) {
2007 args->screen_x = 0;
2008 }
2009 } else if(
2010 0 == maug_strncmp( MAUG_CLI_SIGIL "rfx", arg, MAUG_CLI_SIGIL_SZ + 4 )
2011 ) {
2012 /* The next arg must be the new var. */
2013 } else {
2014 args->screen_x = atoi( arg );
2015 }
2016 return MERROR_OK;
2017}
2018
2019static MERROR_RETVAL retroflat_cli_rfy(
2020 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2021) {
2022 if( 0 > arg_c ) {
2023 if( 0 == args->screen_h ) {
2024 args->screen_y = 0;
2025 }
2026 } else if(
2027 0 == maug_strncmp( MAUG_CLI_SIGIL "rfy", arg, MAUG_CLI_SIGIL_SZ + 4 )
2028 ) {
2029 /* The next arg must be the new var. */
2030 } else {
2031 args->screen_y = atoi( arg );
2032 }
2033 return MERROR_OK;
2034}
2035
2036static MERROR_RETVAL retroflat_cli_rfw(
2037 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2038) {
2039 if( 0 > arg_c ) {
2040 if( 0 == args->screen_w ) {
2041 args->screen_w = RETROFLAT_DEFAULT_SCREEN_W;
2042 debug_printf( 1, "setting arg screen_w to default %d:",
2043 args->screen_w );
2044 }
2045 } else if(
2046 0 == maug_strncmp( MAUG_CLI_SIGIL "rfw", arg, MAUG_CLI_SIGIL_SZ + 4 )
2047 ) {
2048 /* The next arg must be the new var. */
2049 } else {
2050 args->screen_w = atoi( arg );
2051 debug_printf( 1, "setting arg screen_w to: %d",
2052 args->screen_w );
2053 }
2054 return MERROR_OK;
2055}
2056
2057static MERROR_RETVAL retroflat_cli_rfh(
2058 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2059) {
2060 if( 0 > arg_c ) {
2061 if( 0 == args->screen_h ) {
2062 args->screen_h = RETROFLAT_DEFAULT_SCREEN_H;
2063 debug_printf( 1, "setting arg screen_h to default: %d",
2064 args->screen_h );
2065 }
2066 } else if(
2067 0 == maug_strncmp( MAUG_CLI_SIGIL "rfh", arg, MAUG_CLI_SIGIL_SZ + 4 )
2068 ) {
2069 /* The next arg must be the new var. */
2070 } else {
2071 args->screen_h = atoi( arg );
2072 debug_printf( 1, "setting arg screen_h to: %d",
2073 args->screen_h );
2074 }
2075 return MERROR_OK;
2076}
2077
2078# endif /* !RETROFLAT_API_PC_BIOS && !RETROFLAT_NO_CLI_SZ */
2079
2080# ifdef RETROFLAT_VDP
2081static MERROR_RETVAL retroflat_cli_vdp(
2082 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2083) {
2084 if( 0 == maug_strncmp( MAUG_CLI_SIGIL "vdp", arg, MAUG_CLI_SIGIL_SZ + 4 ) ) {
2085 /* Next arg is VDP args str. */
2086 } else {
2087 maug_mzero( g_retroflat_state->vdp_args, RETROFLAT_VDP_ARGS_SZ_MAX + 1 );
2088 maug_strncpy(
2089 g_retroflat_state->vdp_args, arg, RETROFLAT_VDP_ARGS_SZ_MAX );
2090 debug_printf( 1, "VDP args: %s", g_retroflat_state->vdp_args );
2091 }
2092 return MERROR_OK;
2093}
2094# endif /* RETROFLAT_VDP */
2095
2096static MERROR_RETVAL retroflat_cli_u(
2097 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2098) {
2099 if( 0 > arg_c ) {
2100 args->flags &= ~RETROFLAT_STATE_FLAG_UNLOCK_FPS;
2101 } else if(
2102 0 == maug_strncmp( MAUG_CLI_SIGIL "rfu", arg, MAUG_CLI_SIGIL_SZ + 4 )
2103 ) {
2104 debug_printf( 1, "unlocking FPS..." );
2105 args->flags |= RETROFLAT_STATE_FLAG_UNLOCK_FPS;
2106 }
2107 return MERROR_OK;
2108}
2109
2110# ifndef RETROFLAT_NO_PAD
2111
2112static MERROR_RETVAL retroflat_cli_rfj(
2113 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2114) {
2115 if( 0 > arg_c ) {
2116 args->joystick_id = -1;
2117 debug_printf( 1, "setting arg joystick_id to default: %d",
2118 args->joystick_id );
2119 } else if(
2120 0 == maug_strncmp( MAUG_CLI_SIGIL "rfj", arg, MAUG_CLI_SIGIL_SZ + 4 )
2121 ) {
2122 /* The next arg must be the new var. */
2123 } else {
2124 args->joystick_id = atoi( arg );
2125 debug_printf( 1, "setting arg joystick_id to: %d",
2126 args->joystick_id );
2127 }
2128 return MERROR_OK;
2129}
2130
2131# endif /* !RETROFLAT_NO_PAD */
2132
2133#endif /* !RETROFLAT_NO_CLI */
2134
2135/* === */
2136
2137/* Still inside RETROFLT_C! */
2138
2140 int argc, char* argv[], struct RETROFLAT_ARGS* args
2141) {
2142
2143 /* = Declare Init Vars = */
2144
2145 MERROR_RETVAL retval = 0;
2146
2147 /* = Begin Init Procedure = */
2148
2149# ifdef RETROFLAT_COMMIT_HASH
2150 debug_printf( 1, "retroflat commit: " RETROFLAT_COMMIT_HASH );
2151# endif /* RETROFLAT_COMMIT_HASH */
2152
2153 debug_printf( 1, "retroflat: initializing..." );
2154
2155 /* System sanity checks. */
2156 assert( 2 <= sizeof( MERROR_RETVAL ) );
2157 assert( 4 == sizeof( uint32_t ) );
2158 assert( 4 == sizeof( int32_t ) );
2159 assert( 2 == sizeof( uint16_t ) );
2160 assert( 2 == sizeof( int16_t ) );
2161 assert( 1 == sizeof( uint8_t ) );
2162 assert( 1 == sizeof( int8_t ) );
2163 assert( NULL != args );
2164 assert( 1 << RETROFLAT_TILE_W_BITS == RETROFLAT_TILE_W );
2165 assert( 1 << RETROFLAT_TILE_H_BITS == RETROFLAT_TILE_H );
2166
2167 debug_printf( 1, "initializing drawing routines..." );
2168
2169 /* Initialize 2D callbacks depending on if we're in 2D or 3D mode.
2170 * Please see retrom2d.h for more information.
2171 */
2172# if defined( RETROFLAT_BMP_TEX )
2173 retroflat_2d_px = (retroflat_px_cb)retro3d_texture_px;
2174 retroflat_2d_line = (retroflat_line_cb)retrosoft_line;
2175 retroflat_2d_rect = (retroflat_rect_cb)retrosoft_rect;
2176 retroflat_2d_ellipse = (retroflat_ellipse_cb)retrosoft_ellipse;
2177 retroflat_2d_blit_bitmap = (retroflat_blit_bitmap_cb)retro3d_texture_blit;
2178 retroflat_2d_load_bitmap =
2179 (retroflat_load_bitmap_cb)retro3d_texture_load_bitmap;
2180 retroflat_2d_create_bitmap =
2181 (retroflat_create_bitmap_cb)retro3d_texture_create;
2182# else
2183 retroflat_2d_px = (retroflat_px_cb)retroflat_px;
2184# ifdef RETROFLAT_SOFT_SHAPES
2185 /* TODO: Work retrosoft routines to use retroflat_blit_t */
2186 retroflat_2d_line = (retroflat_line_cb)retrosoft_line;
2187 retroflat_2d_rect = (retroflat_rect_cb)retrosoft_rect;
2188 retroflat_2d_ellipse = (retroflat_ellipse_cb)retrosoft_ellipse;
2189# else
2190 retroflat_2d_line = (retroflat_line_cb)retroflat_line;
2191 retroflat_2d_rect = (retroflat_rect_cb)retroflat_rect;
2192 retroflat_2d_ellipse = (retroflat_ellipse_cb)retroflat_ellipse;
2193# endif /* RETROFLAT_SOFT_SHAPES */
2194 retroflat_2d_blit_bitmap = (retroflat_blit_bitmap_cb)retroflat_blit_bitmap;
2195 retroflat_2d_load_bitmap = (retroflat_load_bitmap_cb)retroflat_load_bitmap;
2196 retroflat_2d_create_bitmap =
2197 (retroflat_create_bitmap_cb)retroflat_create_bitmap;
2198# endif /* RETROFLAT_BMP_TEX */
2199
2200 debug_printf( 1, "retroflat: MFIX_PRECISION: %f", MFIX_PRECISION );
2201
2202 debug_printf( 1, "retroflat: allocating state (" SIZE_T_FMT " bytes)...",
2203 sizeof( struct RETROFLAT_STATE ) );
2204
2205 debug_printf( 1, "retroflat: size_t is (" SIZE_T_FMT " bytes)...",
2206 sizeof( size_t ) );
2207
2208 debug_printf( 1, "retroflat: ssize_t is (" SIZE_T_FMT " bytes)...",
2209 sizeof( ssize_t ) );
2210
2211 debug_printf( 1, "retroflat: off_t is (" SIZE_T_FMT " bytes)...",
2212 sizeof( off_t ) );
2213
2214 debug_printf( 1, "initializing global state..." );
2215
2216# ifdef RETROFLAT_STATE_ON_STACK
2217 g_retroflat_state = &g_retroflat_state_stack;
2218# else
2219 maug_malloc_test( g_retroflat_state_h, 1, sizeof( struct RETROFLAT_STATE ) );
2220
2221 maug_mlock( g_retroflat_state_h, g_retroflat_state );
2222 if( NULL == g_retroflat_state ) {
2224 "Error", "Could not lock global state!" );
2225 retval = MERROR_ALLOC;
2226 goto cleanup;
2227 }
2228# endif /* RETROFLAT_STATE_ON_STACK */
2229
2230 maug_mzero( g_retroflat_state, sizeof( struct RETROFLAT_STATE ) );
2231
2232 retroflat_heartbeat_set( 1000, 2 );
2233
2234 debug_printf( 1, "initializing platform filesystem..." );
2235 retval = mfile_plt_init();
2236 maug_cleanup_if_not_ok();
2237
2238# ifndef RETROFLAT_NO_CLI
2239
2240 debug_printf( 1, "retroflat: parsing args..." );
2241
2242 /* All platforms: add command-line args based on compile definitons. */
2243
2244 retval = maug_add_arg(
2245 MAUG_CLI_SIGIL "h", MAUG_CLI_SIGIL_SZ + 2, "Display command-line help",
2246 26, maug_cli_h, NULL );
2247
2248# if !defined( RETROFLAT_NO_SOUND ) && defined( RETROSND_ARGS )
2249 retval = maug_add_arg( MAUG_CLI_SIGIL "rsd", MAUG_CLI_SIGIL_SZ + 4,
2250 "Select MIDI device", 0, (maug_cli_cb)retrosnd_cli_rsd, args );
2251 maug_cleanup_if_not_ok();
2252 retval = maug_add_arg( MAUG_CLI_SIGIL "rsl", MAUG_CLI_SIGIL_SZ + 4,
2253 "List MIDI devices", 0, (maug_cli_cb)retrosnd_cli_rsl, args );
2254 maug_cleanup_if_not_ok();
2255# endif /* !RETROFLAT_NO_SOUND && RETROSND_ARGS */
2256
2257# ifdef RETROFLAT_SCREENSAVER
2258 retval = maug_add_arg( MAUG_CLI_SIGIL "p", MAUG_CLI_SIGIL_SZ + 2,
2259 "Preview screensaver", 0, (maug_cli_cb)retroflat_cli_p, args );
2260 maug_cleanup_if_not_ok();
2261 retval = maug_add_arg( MAUG_CLI_SIGIL "s", MAUG_CLI_SIGIL_SZ + 2,
2262 "Launch screensaver", 0, (maug_cli_cb)retroflat_cli_s, args );
2263 maug_cleanup_if_not_ok();
2264# endif /* RETROFLAT_SCREENSAVER */
2265
2266# ifdef RETROFLAT_API_PC_BIOS
2267 retval = maug_add_arg( MAUG_CLI_SIGIL "rfm", MAUG_CLI_SIGIL_SZ + 4,
2268 "Set the screen mode.", 0,
2269 (maug_cli_cb)retroflat_cli_rfm, args );
2270 maug_cleanup_if_not_ok();
2271# elif !defined( RETROFLAT_NO_CLI_SZ )
2272 retval = maug_add_arg( MAUG_CLI_SIGIL "rfs", MAUG_CLI_SIGIL_SZ + 4,
2273 "Set screen scale factor.", 0,
2274 (maug_cli_cb)retroflat_cli_rfs, args );
2275 maug_cleanup_if_not_ok();
2276 retval = maug_add_arg( MAUG_CLI_SIGIL "rfx", MAUG_CLI_SIGIL_SZ + 4,
2277 "Set the screen X position.", 0,
2278 (maug_cli_cb)retroflat_cli_rfx, args );
2279 maug_cleanup_if_not_ok();
2280 retval = maug_add_arg( MAUG_CLI_SIGIL "rfy", MAUG_CLI_SIGIL_SZ + 4,
2281 "Set the screen Y position.", 0,
2282 (maug_cli_cb)retroflat_cli_rfy, args );
2283 maug_cleanup_if_not_ok();
2284 retval = maug_add_arg( MAUG_CLI_SIGIL "rfw", MAUG_CLI_SIGIL_SZ + 4,
2285 "Set the screen width.", 0,
2286 (maug_cli_cb)retroflat_cli_rfw, args );
2287 maug_cleanup_if_not_ok();
2288 retval = maug_add_arg( MAUG_CLI_SIGIL "rfh", MAUG_CLI_SIGIL_SZ + 4,
2289 "Set the screen height.", 0,
2290 (maug_cli_cb)retroflat_cli_rfh, args );
2291 maug_cleanup_if_not_ok();
2292# endif /* !RETROFLAT_NO_CLI_SZ */
2293
2294# ifdef RETROFLAT_VDP
2295 retval = maug_add_arg( MAUG_CLI_SIGIL "vdp", MAUG_CLI_SIGIL_SZ + 4,
2296 "Pass a string of args to the VDP.", 0,
2297 (maug_cli_cb)retroflat_cli_vdp, args );
2298 maug_cleanup_if_not_ok();
2299# endif /* RETROFLAT_VDP */
2300
2301 retval = maug_add_arg( MAUG_CLI_SIGIL "rfu", MAUG_CLI_SIGIL_SZ + 4,
2302 "Unlock FPS.", 0,
2303 (maug_cli_cb)retroflat_cli_u, args );
2304 maug_cleanup_if_not_ok();
2305
2306# ifndef RETROFLAT_NO_PAD
2307 retval = maug_add_arg( MAUG_CLI_SIGIL "rfj", MAUG_CLI_SIGIL_SZ + 4,
2308 "Specify joystick ID to use.", 0,
2309 (maug_cli_cb)retroflat_cli_rfj, args );
2310 maug_cleanup_if_not_ok();
2311# endif /* !RETROFLAT_NO_PAD */
2312
2313 /* Parse command line args. */
2314 retval = maug_parse_args( argc, argv );
2315 maug_cleanup_if_not_ok();
2316
2317# endif /* !RETROFLAT_NO_CLI */
2318
2319 if( 0 == args->screen_w ) {
2320 args->screen_w = RETROFLAT_DEFAULT_SCREEN_W;
2321 debug_printf( 1, "setting arg screen_w to default: %d",
2322 args->screen_w );
2323 }
2324 if( 0 == args->screen_h ) {
2325 args->screen_h = RETROFLAT_DEFAULT_SCREEN_H;
2326 debug_printf( 1, "setting arg screen_h to default: %d",
2327 args->screen_h );
2328 }
2329 if( 0 == args->screen_scale ) {
2330 args->screen_scale = RETROFLAT_DEFAULT_SCREEN_SCALE;
2331 debug_printf( 1, "setting arg screen_scale to default: %d",
2332 args->screen_scale );
2333 }
2334 if( 0 == args->screen_colors ) {
2335 args->screen_colors = 16;
2336 debug_printf( 1, "setting arg screen_colors to default: %d",
2337 args->screen_colors );
2338 }
2339 args->joystick_id = -1;
2340
2341 if(
2343 ) {
2345 }
2346
2347 debug_printf( 1, "retroflat: setting config..." );
2348
2349 /* Set the assets path. */
2350 if( NULL != args->assets_path ) {
2351 maug_mzero( g_retroflat_state->assets_path, MAUG_PATH_SZ_MAX );
2352 maug_strncpy( g_retroflat_state->assets_path,
2353 args->assets_path, MAUG_PATH_SZ_MAX - 1 );
2354 }
2355
2356# if defined( RETROFLAT_SCREENSAVER )
2357 if(
2359 (RETROFLAT_STATE_FLAG_SCREENSAVER & args->flags)
2360 ) {
2362 }
2363# endif /* RETROFLAT_SCREENSAVER */
2364
2365# if !defined( RETROFLAT_NO_CLI_SZ )
2366 /* Setup intended screen size. */
2367 g_retroflat_state->screen_scale = args->screen_scale;
2368 g_retroflat_state->screen_v_w = args->screen_w;
2369 g_retroflat_state->screen_v_h = args->screen_h;
2370 g_retroflat_state->screen_w = args->screen_w *
2371 g_retroflat_state->screen_scale;
2372 g_retroflat_state->screen_h = args->screen_h *
2373 g_retroflat_state->screen_scale;
2374 g_retroflat_state->screen_colors = args->screen_colors;
2375
2376 debug_printf( 3, "attempting to initialize platform with: "
2377 SIZE_T_FMT "x" SIZE_T_FMT " pixels (scaled to " SIZE_T_FMT "x" SIZE_T_FMT
2378 ") and " SIZE_T_FMT " colors",
2379 g_retroflat_state->screen_v_w, g_retroflat_state->screen_v_h,
2380 g_retroflat_state->screen_w, g_retroflat_state->screen_h,
2381 g_retroflat_state->screen_colors );
2382# endif /* !RETROFLAT_NO_CLI_SZ */
2383
2384 /* == Platform-Specific Init == */
2385
2386 retval = retroflat_init_platform( argc, argv, args );
2387 maug_cleanup_if_not_ok();
2388
2389# if defined( RETROFLAT_NO_CLI_SZ )
2390 g_retroflat_state->screen_scale = args->screen_scale;
2391 g_retroflat_state->screen_v_w = args->screen_w;
2392 g_retroflat_state->screen_v_h = args->screen_h;
2393 g_retroflat_state->screen_w = args->screen_w *
2394 g_retroflat_state->screen_scale;
2395 g_retroflat_state->screen_h = args->screen_h *
2396 g_retroflat_state->screen_scale;
2397 g_retroflat_state->screen_colors = args->screen_colors;
2398
2399 debug_printf( 3, "initialized platform with: "
2400 SIZE_T_FMT "x" SIZE_T_FMT " pixels (scaled to " SIZE_T_FMT "x" SIZE_T_FMT
2401 ") and " SIZE_T_FMT " colors",
2402 g_retroflat_state->screen_v_w, g_retroflat_state->screen_v_h,
2403 g_retroflat_state->screen_w, g_retroflat_state->screen_h,
2404 g_retroflat_state->screen_colors );
2405# endif /* RETROFLAT_NO_CLI_SZ */
2406
2407 retval = retroflat_init_input( args );
2408 maug_cleanup_if_not_ok();
2409
2410 debug_printf( 3, "screen initialized with: " SIZE_T_FMT "x" SIZE_T_FMT
2411 " pixels (scaled to " SIZE_T_FMT "x" SIZE_T_FMT
2412 ") with " SIZE_T_FMT " colors",
2413 g_retroflat_state->screen_v_w, g_retroflat_state->screen_v_h,
2414 g_retroflat_state->screen_w, g_retroflat_state->screen_h,
2416
2417 /* Setup the refresh grid, if requested, only after screen space has been
2418 * determined by the platform!
2419 */
2420 maug_cleanup_if_eq(
2421 (size_t)0, retroflat_screen_w(), SIZE_T_FMT, MERROR_GUI );
2422 maug_cleanup_if_eq(
2423 (size_t)0, retroflat_screen_h(), SIZE_T_FMT, MERROR_GUI );
2424 maug_cleanup_if_eq(
2425 (size_t)0, retroflat_screen_colors(), SIZE_T_FMT, MERROR_GUI );
2426
2427 /* Init the viewport with no world size, just to get the refresh grid
2428 * allocated.
2429 */
2430 retval = retroview_init( 0, 0 );
2431 maug_cleanup_if_not_ok();
2432
2433# ifdef RETROFLAT_VDP
2434# if defined( RETROFLAT_OS_UNIX )
2435 g_retroflat_state->vdp_exe = dlopen(
2436 "./" RETROFLAT_VDP_LIB_NAME ".so", RTLD_LAZY );
2437# elif defined( RETROFLAT_OS_WIN )
2438 g_retroflat_state->vdp_exe = LoadLibrary(
2439 "./" RETROFLAT_VDP_LIB_NAME ".dll" );
2440# else
2441# error "dlopen undefined!"
2442# endif /* RETROFLAT_OS_UNIX */
2443
2444 if( !(g_retroflat_state->vdp_exe) ) {
2445 error_printf( "not loading VDP" );
2446 /* Skip creating the buffer or trying to run the init proc. */
2447 goto skip_vdp;
2448 }
2449
2450 debug_printf( 1, "initializing VDP..." );
2451 retval = retroflat_vdp_call( "retroflat_vdp_init" );
2452 maug_cleanup_if_not_ok();
2453
2454skip_vdp:
2455
2456# endif /* RETROFLAT_VDP */
2457
2458# ifdef RETROFLAT_3D
2459 retro3d_platform_init();
2460# endif /* RETROFLAT_3D */
2461
2462# if !defined( RETROFLAT_NO_BLANK_INIT ) && !defined( RETROFLAT_3D )
2463 retroflat_draw_lock( NULL );
2465 NULL, RETROFLAT_COLOR_BLACK, 0, 0,
2466 retroflat_screen_w(), retroflat_screen_h(),
2468 retroflat_draw_release( NULL );
2469# endif /* !RETROFLAT_NO_BLANK_INIT */
2470
2471cleanup:
2472
2473 return retval;
2474}
2475
2476/* === */
2477
2478void retroflat_shutdown( int retval ) {
2479
2480 debug_printf( 1, "retroflat shutdown called..." );
2481
2482 retroview_shutdown();
2483
2484# if defined( RETROFLAT_VDP )
2485 if( NULL != g_retroflat_state->vdp_exe ) {
2486 retroflat_vdp_call( "retroflat_vdp_shutdown" );
2487# ifdef RETROFLAT_OS_UNIX
2488 dlclose( g_retroflat_state->vdp_exe );
2489# elif defined( RETROFLAT_OS_WIN )
2490 FreeLibrary( g_retroflat_state->vdp_exe );
2491# else
2492# error "dlclose undefined!"
2493# endif /* RETROFLAT_OS_UNIX || RETROFLAT_OS_WIN */
2494 }
2495# endif /* RETROFLAT_VDP */
2496
2497 /* === Platform-Specific Shutdown === */
2498
2499#ifdef RETROFLAT_3D
2500 retro3d_platform_shutdown();
2501#endif /* RETROFLAT_3D */
2502
2503 retroflat_shutdown_platform( retval );
2504
2505#ifndef RETROFLAT_STATE_ON_STACK
2506 maug_munlock( g_retroflat_state_h, g_retroflat_state );
2507 maug_mfree( g_retroflat_state_h );
2508#endif /* !RETROFLAT_STATE_ON_STACK */
2509
2510}
2511
2512/* === */
2513
2514RETROFLAT_IN_KEY retroflat_repeat_input(
2515 RETROFLAT_IN_KEY key_out, struct RETROFLAT_INPUT* input,
2516 RETROFLAT_IN_KEY* prev_input, int* prev_delay
2517) {
2518
2519 /* Add a slight debounce for gamepad button repeat. */
2520 if( 0 < (*prev_delay) ) {
2521 debug_printf(
2522 RETROINPUT_TRACE_LVL,
2523 "repeat delay: %d", (*prev_delay) );
2524 (*prev_delay)--;
2525 }
2526
2527 /* If nothing else happened and repeat is enabled and a joypad button is
2528 * down, then emulate repeat for it.
2529 */
2530 if(
2531 0 == key_out &&
2533 (RETROFLAT_STATE_FLAG_KEY_REPEAT & g_retroflat_state->retroflat_flags) &&
2534 /* There is an input to repeat. */
2535 0 != *prev_input &&
2536 /* Delay countdown reached. */
2537 0 == *prev_delay
2538 ) {
2539 key_out = *prev_input;
2540 *prev_delay = 1;
2541 debug_printf( RETROINPUT_TRACE_LVL, "repeat: %d", key_out );
2542 }
2543
2544 return key_out;
2545}
2546
2547/* === */
2548
2549ssize_t retroflat_timer_add(
2550 retroflat_ms_t at_time, retroflat_timer_cb_t cb, void* data
2551) {
2552 if( retroflat_get_ms() > at_time ) {
2553 error_printf( "timer time is in the past!" );
2554 return merror_retval_to_sz( MERROR_EXEC );
2555 }
2556
2557 if( g_retroflat_state->timers_ct + 1 < RETROFLAT_TIMER_CT_MAX ) {
2558 g_retroflat_state->timers_cb[g_retroflat_state->timers_ct] = cb;
2559 g_retroflat_state->timers_at[g_retroflat_state->timers_ct] = at_time;
2560 g_retroflat_state->timers_ct++;
2561 return g_retroflat_state->timers_ct - 1;
2562 }
2563
2564 error_printf( "too many timers!" );
2565 return merror_retval_to_sz( MERROR_OVERFLOW );
2566}
2567
2568/* === */
2569
2570void retroflat_timer_handle( void ) {
2571 size_t i = 0;
2572 retroflat_ms_t time_now = 0;
2573
2574 time_now = retroflat_get_ms();
2575
2576 for( i = 0 ; g_retroflat_state->timers_ct > i ; i++ ) {
2577 if( g_retroflat_state->timers_at[i] <= time_now ) {
2578 g_retroflat_state->timers_cb[i](
2579 time_now, g_retroflat_state->timers_data[i] );
2580 memmove(
2581 &(g_retroflat_state->timers_cb[i]),
2582 &(g_retroflat_state->timers_cb[i + 1]),
2583 sizeof( retroflat_timer_cb_t ) *
2584 ((g_retroflat_state->timers_ct - i) - 1)
2585 );
2586 memmove(
2587 &(g_retroflat_state->timers_at[i]),
2588 &(g_retroflat_state->timers_at[i + 1]),
2589 sizeof( retroflat_ms_t ) * ((g_retroflat_state->timers_ct - i) - 1)
2590 );
2591 memmove(
2592 &(g_retroflat_state->timers_data[i]),
2593 &(g_retroflat_state->timers_data[i + 1]),
2594 sizeof( void* ) * ((g_retroflat_state->timers_ct - i) - 1)
2595 );
2596 g_retroflat_state->timers_ct--;
2597 i--;
2598 }
2599 }
2600}
2601
2602/* === */
2603
2604# ifdef RETROFLAT_VDP
2605
2606MERROR_RETVAL retroflat_vdp_call( const char* proc_name ) {
2607 MERROR_RETVAL retval = MERROR_OK;
2609# ifdef RETROFLAT_OS_WIN
2610 char proc_name_ex[256];
2611# endif /* RETROFLAT_OS_WIN */
2612
2613 if( NULL == g_retroflat_state->vdp_exe ) {
2614 goto cleanup;
2615 }
2616
2617# ifdef RETROFLAT_OS_UNIX
2618 vdp_proc = dlsym( g_retroflat_state->vdp_exe, proc_name );
2619# elif defined( RETROFLAT_OS_WIN )
2620 /* Append a _ to the proc_name because Watcom? Windows? */
2621 maug_snprintf( proc_name_ex, 255, "%s_", proc_name );
2622 vdp_proc = (retroflat_vdp_proc_t)GetProcAddress(
2623 g_retroflat_state->vdp_exe, proc_name_ex );
2624# else
2625# error "dlsym undefined!"
2626# endif
2627 if( (retroflat_vdp_proc_t)NULL == vdp_proc ) {
2628 goto cleanup;
2629 }
2630
2631# ifdef RETROFLAT_OS_WIN
2632 retroflat_draw_lock( g_retroflat_state->vdp_buffer_in );
2633# endif /* RETROFLAT_OS_WIN */
2634
2635 if(
2636 /* Don't pxlock before init can set the flag! */
2637 0 == strcmp( "retroflat_vdp_flip", proc_name ) &&
2639 (RETROFLAT_VDP_FLAG_PXLOCK & g_retroflat_state->vdp_flags)
2640 ) {
2641 retroflat_vdp_lock( g_retroflat_state->vdp_buffer_in );
2642 retroflat_vdp_lock( g_retroflat_state->vdp_buffer_out );
2643 }
2644
2645 retval = vdp_proc( g_retroflat_state );
2646
2647 if(
2648 0 == strcmp( "retroflat_vdp_flip", proc_name ) &&
2650 (RETROFLAT_VDP_FLAG_PXLOCK & g_retroflat_state->vdp_flags)
2651 ) {
2652 retroflat_vdp_release( g_retroflat_state->vdp_buffer_out );
2653 retroflat_vdp_release( g_retroflat_state->vdp_buffer_in );
2654 }
2655
2656# ifdef RETROFLAT_OS_WIN
2657 retroflat_draw_release( g_retroflat_state->vdp_buffer_in );
2658# endif /* RETROFLAT_OS_WIN */
2659
2660cleanup:
2661 return retval;
2662}
2663
2664# endif /* RETROFLAT_VDP */
2665
2666# ifdef RETROFLAT_CLIP_GENERIC
2667
2668/* === */
2669
2670void retroflat_set_clip(
2671 struct RETROFLAT_BITMAP* target,
2674) {
2675 if( NULL == target ) {
2676 target = retroflat_screen_buffer();
2677 }
2678
2679 target->clip_l = x;
2680 target->clip_t = y;
2681 target->clip_r = x + w;
2682 target->clip_b = y + h;
2683}
2684
2685# endif /* RETROFLAT_CLIP_GENERIC */
2686
2687/* === */
2688
2689#if 0
2690
2691void retroflat_cursor( struct RETROFLAT_BITMAP* target, uint8_t flags ) {
2692#if 0
2693 char mouse_str[11] = "";
2694
2695 maug_snprintf(
2696 mouse_str, 10, "%02d, %02d", g_retroflat_state->last_mouse_x, g_retroflat_state->last_mouse_y );
2697
2698 retroflat_string(
2699 target, RETROFLAT_COLOR_BLACK,
2700 mouse_str, 10, NULL, 0, 0, 0 );
2702 target, RETROFLAT_COLOR_BLACK,
2703 g_retroflat_state->last_mouse_x - 5, g_retroflat_state->last_mouse_y - 5, 10, 10, 0 );
2704#endif
2705}
2706
2707#endif
2708
2709/* === */
2710
2711void maug_critical_error( const char* msg ) {
2713}
2714
2715/* === */
2716
2718 retroflat_proc_resize_t on_resize_in, void* data_in
2719) {
2720 g_retroflat_state->on_resize = on_resize_in;
2721 g_retroflat_state->on_resize_data = data_in;
2722}
2723
2724/* === */
2725
2727 retroflat_proc_focus_t on_focus_in, void* data_in
2728) {
2729 g_retroflat_state->on_focus = on_focus_in;
2730 g_retroflat_state->on_focus_data = data_in;
2731}
2732
2733/* === */
2734
2736 retroflat_proc_quit_t on_quit_in, void* data_in
2737) {
2738 g_retroflat_state->on_quit = on_quit_in;
2739 g_retroflat_state->on_quit_data = data_in;
2740}
2741
2742/* === */
2743
2744#ifdef RETROFLAT_LOAD_BITMAP_GENERIC
2745
2746/* This is a generic function that uses the callback
2747 * retroflat_load_bitmap_px_cb(), which should be defined by the
2748 * platform-specific API to draw the loaded bitmap onto a native canvas.
2749 */
2750
2752 const char* filename, struct RETROFLAT_BITMAP* bmp_out, uint8_t flags
2753) {
2754 maug_path filename_path;
2755 MERROR_RETVAL retval = MERROR_OK;
2756 mfile_t bmp_file;
2757 struct MFMT_STRUCT_BMPFILE header_bmp;
2758 uint8_t bmp_flags = 0;
2759
2760 assert( NULL != bmp_out );
2761 maug_mzero( bmp_out, sizeof( struct RETROFLAT_BITMAP ) );
2762 retval = retroflat_build_filename_path(
2763 filename, RETROFLAT_BITMAP_EXT, filename_path,
2764 MAUG_PATH_SZ_MAX, flags );
2765 maug_cleanup_if_not_ok();
2766 debug_printf( 1, "retroflat: loading bitmap: %s", filename_path );
2767
2768 bmp_out->flags = flags;
2769
2770 /* Open the bitmap file. */
2771 retval = mfile_open_read( filename_path, &bmp_file );
2772 maug_cleanup_if_not_ok();
2773
2774 /* mfmt file detection system. */
2775 maug_mzero( &header_bmp, sizeof( struct MFMT_STRUCT_BMPFILE ) );
2776 header_bmp.magic[0] = 'B';
2777 header_bmp.magic[1] = 'M';
2778 header_bmp.info.sz = 40;
2779
2780 retval = mfmt_read_bmp_header(
2781 (struct MFMT_STRUCT*)&header_bmp,
2782 &bmp_file, 0, mfile_get_sz( &bmp_file ), &bmp_flags );
2783 maug_cleanup_if_not_ok();
2784
2785 retval = retroflat_create_bitmap(
2786 header_bmp.info.width, header_bmp.info.height, bmp_out, flags );
2787 maug_cleanup_if_not_ok();
2788
2789 retroflat_draw_lock( bmp_out );
2790
2791 retval = mfmt_read_bmp_px_cb(
2792 (struct MFMT_STRUCT*)&header_bmp,
2793 &bmp_file,
2794 header_bmp.px_offset,
2795 mfile_get_sz( &bmp_file ) - header_bmp.px_offset,
2796 bmp_flags,
2797 retroflat_load_bitmap_px_cb,
2798 bmp_out );
2799 maug_cleanup_if_not_ok();
2800
2801 retroflat_draw_release( bmp_out );
2802
2803cleanup:
2804
2805 mfile_close( &bmp_file );
2806
2807 return retval;
2808}
2809
2810#endif /* RETROFLAT_LOAD_BITMAP_GENERIC */
2811
2812#elif !defined( RETROVDP_C ) /* End of RETROFLT_C */
2813
2819extern MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets8_x[8];
2820extern MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets8_y[8];
2821extern MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets4_x[4];
2822extern MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets4_y[4];
2823extern MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets4_x_tile[4];
2824extern MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets4_y_tile[4];
2825
2828#define RETROFLAT_COLOR_TABLE_CONSTS( idx, name_l, name_u, r, g, b, cgac, cgad ) \
2829 extern MAUG_CONST RETROFLAT_COLOR SEG_MCONST RETROFLAT_COLOR_ ## name_u;
2830
2831RETROFLAT_COLOR_TABLE( RETROFLAT_COLOR_TABLE_CONSTS )
2832
2833extern MAUG_CONST char* SEG_MCONST gc_retroflat_color_names[];
2834
2835extern struct RETROFLAT_STATE* SEG_MGLOBAL g_retroflat_state;
2836
2837# if (defined( RETROFLAT_SOFT_SHAPES ) || defined( RETROFLAT_SOFT_LINES ) || \
2838 defined( RETROFLAT_3D ))
2839# define RETROSOFT_PRESENT
2840# endif
2841
2842# ifdef RETROFLAT_3D
2843# include <retro3dp.h>
2844# include <retro3d.h>
2845# include <retro3du.h>
2846# endif /* RETROFLAT_3D */
2847
2848# ifdef RETROSOFT_PRESENT
2849# include <retrosft.h>
2850# endif /* RETROFLAT_SOFT_SHAPES */
2851
2852/* Second retapis.h include for function bodies not needed. */
2853
2854/* Second retapii.h include for function bodies not needed. */
2855
2856#endif /* RETROFLT_C */
2857
2858#ifdef RETROFLAT_XPM
2859#include <retroxpm.h>
2860#endif /* RETROFLAT_XPM */
2861
2862#ifdef RETROVDP_C
2863
2864/* Declarations for VDP sources. */
2865
2866#endif /* RETROVDP_C */
2867 /* maug_retroflt */
2869
2870#endif /* RETROFLT_H */
2871
MERROR_RETVAL maug_add_arg(const char *arg, int arg_sz, const char *help, int help_sz, maug_cli_cb arg_cb, void *data)
Add a command-line argument to the built-in parser.
#define MAUG_CLI_SIGIL
Default flag to prepend to CLI arguments. Is "/" on Windows/DOS and "-" on other platforms....
Definition: marge.h:39
uint16_t MERROR_RETVAL
Return type indicating function returns a value from this list.
Definition: merror.h:28
void maug_critical_error(const char *msg)
Display an error dialog. This is a minimal function that can be called early on (e....
MERROR_RETVAL mfmt_read_bmp_px_cb(struct MFMT_STRUCT *header, mfile_t *p_file_in, uint32_t px_offset, off_t file_sz, uint8_t flags, mfmt_read_1px_cb px_cb, void *px_cb_data)
Read mfmt_bitmap pixels and process them using a callback.
MERROR_RETVAL mfile_open_read(const maug_path filename, mfile_t *p_file)
Open a file and read it into memory or memory-map it.
#define MAUG_PATH_SZ_MAX
Maximum size allocated for asset paths.
Definition: mfile.h:38
void mfile_close(mfile_t *p_file)
Close a file opened with mfile_open_read().
char maug_path[MAUG_PATH_SZ_MAX]
Path/name used to load an asset from disk or access other files.
Definition: mfile.h:138
#define RETROFLAT_BITMAP_EXT
The filename suffix to be appended with a "." to filenames passed to retroflat_load_bitmap()....
Definition: retroflt.h:624
#define RETROFLAT_BITMAP_FLAG_LITERAL_PATH
Flag for retroflat_load_bitmap() to not use assets path.
Definition: retroflt.h:580
void retroflat_destroy_bitmap(struct RETROFLAT_BITMAP *bitmap)
Unload a bitmap from a ::RETROFLAT_BITMAP struct. The struct, itself, is not freed (in case it is on ...
MERROR_RETVAL retroflat_load_bitmap(const char *filename, struct RETROFLAT_BITMAP *bmp_out, uint8_t flags)
Load a bitmap into the given ::RETROFLAT_BITMAP structure if it is available. Bitmaps are subject to ...
MERROR_RETVAL retroflat_blit_bitmap(struct RETROFLAT_BITMAP *target, struct RETROFLAT_BITMAP *src, retroflat_pxxy_t s_x, retroflat_pxxy_t s_y, retroflat_pxxy_t d_x, retroflat_pxxy_t d_y, retroflat_pxxy_t w, retroflat_pxxy_t h, int16_t instance)
Blit the contents of a ::RETROFLAT_BITMAP onto another ::RETROFLAT_BITMAP.
int8_t RETROFLAT_COLOR
Defines an index in the platform-specific color-table.
Definition: retroflt.h:328
#define RETROFLAT_COLOR_TABLE(f)
This macro defines all colors supported by RetroFlat for primative operations, particularly using ret...
Definition: retroflt.h:309
#define RETROFLAT_VDP_ARGS_SZ_MAX
Definition: retroflt.h:769
#define RETROFLAT_PATH_SEP
The valid path separator on the target platform.
Definition: retroflt.h:790
void retroflat_ellipse(struct RETROFLAT_BITMAP *target, const RETROFLAT_COLOR color, retroflat_pxxy_t x, retroflat_pxxy_t y, retroflat_pxxy_t w, retroflat_pxxy_t h, uint8_t flags)
Draw an ellipse onto the target ::RETROFLAT_BITMAP.
MERROR_RETVAL retroflat_draw_lock(struct RETROFLAT_BITMAP *bmp)
Lock a bitmap for drawing. This will be done automatically if necessary and not called explicitly,...
#define RETROFLAT_DRAW_FLAG_FILL
Flag for retroflat_rect() or retroflat_ellipse(), indicating drawn shape should be filled.
Definition: retroflt.h:376
void retroflat_line(struct RETROFLAT_BITMAP *target, const RETROFLAT_COLOR color, retroflat_pxxy_t x1, retroflat_pxxy_t y1, retroflat_pxxy_t x2, retroflat_pxxy_t y2, uint8_t flags)
Draw a straight line onto the target ::RETROFLAT_BITMAP.
void retroflat_rect(struct RETROFLAT_BITMAP *target, const RETROFLAT_COLOR color, retroflat_pxxy_t x, retroflat_pxxy_t y, retroflat_pxxy_t w, retroflat_pxxy_t h, uint8_t flags)
Draw a rectangle onto the target ::RETROFLAT_BITMAP.
RETROFLAT_IN_KEY retroflat_poll_input(struct RETROFLAT_INPUT *input)
Poll input devices (keyboard/mouse) and return the latest event.
void retroflat_message(uint8_t flags, const char *title, const char *format,...)
Display a message in a dialog box and/or on stderr.
#define RETROFLAT_MSG_FLAG_ERROR
This icon/type flag indicates an error. It will try to display messages in an urgent way with a red i...
Definition: retroflt.h:456
void retroflat_timer_handle(void)
This should be called in the API HAL on every iteration of the main loop (this is done automatically ...
void retroflat_resize_v(void)
Platform-specific function to resize virtual screen to match physical window size.
uint8_t retroflat_focus_platform(void)
Platform-specific function to get current focus flags for the generic loop.
void retroflat_set_proc_quit(retroflat_proc_quit_t on_quit_in, void *data_in)
Set the procedure to call when the window is attempted to be closed (on platforms that support window...
MERROR_RETVAL(* retroflat_proc_quit_t)(void *data)
Callback to call when window closing is attempted. Should return MERROR_PREEMPT to defer or MERROR_OK...
Definition: retroflt.h:532
ssize_t retroflat_timer_add(retroflat_ms_t time, retroflat_timer_cb_t cb, void *data)
Add a timer callback to be executed at the given time.
void retroflat_set_proc_focus(retroflat_proc_focus_t on_focus_in, void *data_in)
Set the procedure to call when the window gains or loses focus (on platforms that support multitaskin...
void retroflat_set_proc_resize(retroflat_proc_resize_t on_resize_in, void *data_in)
Set the procedure to call when the window is resized (on platforms that support resizing).
MERROR_RETVAL retroflat_vdp_call(const char *proc_name)
Call a function from the retroflat VDP.
MERROR_RETVAL(* retroflat_vdp_proc_t)(struct RETROFLAT_STATE *)
VDP function called from the VDP library.
Definition: retroflt.h:508
#define RETROFLAT_VDP_FLAG_PXLOCK
Flag for RETROFLAT_STATE::vdp_flags indicating the VDP requires RetroFlat to pixel-lock the frame bef...
Definition: retroflt.h:495
void retroflat_shutdown(int retval)
Deinitialize RetroFlat and its underlying layers. This should be called once at the end of the progra...
int16_t retroflat_pxxy_t
Type used for surface pixel coordinates.
Definition: retroflt.h:925
#define retroflat_system_task()
Platform-specific task that should be called on every iteration of the generic loop....
Definition: retroflt.h:1023
void(* retroflat_loop_iter)(void *data)
Prototype for the main loop function passed to retroflat_loop().
Definition: retroflt.h:813
MERROR_RETVAL retroflat_loop(retroflat_loop_iter frame_iter, retroflat_loop_iter loop_iter, void *data)
This should be called once in the main body of the program in order to enter the main loop....
MERROR_RETVAL retroflat_init(int argc, char *argv[], struct RETROFLAT_ARGS *args)
Initialize RetroFlat and its underlying layers. This should be called once at the beginning of the pr...
void retrosoft_rect(retroflat_blit_t *target, const RETROFLAT_COLOR color_idx, int x, int y, int w, int h, uint8_t flags)
Draw a rectangle at the given coordinates, with the given dimensions.
void retrosoft_ellipse(retroflat_blit_t *target, RETROFLAT_COLOR color, int x, int y, int w, int h, uint8_t flags)
Draw an ellipsoid at the given coordinates, with the given dimensions.
void retrosoft_line(retroflat_blit_t *target, RETROFLAT_COLOR color, int x1, int y1, int x2, int y2, uint8_t flags)
Draw a line from x1, y1 to x2, y2.
int16_t retroflat_tile_t
Value for an individual tile in a RETROTILE_LAYER.
Definition: retroflt.h:19
Lower-level retargetable 3D engine wrapper.
Tools for drawing shape primatives.
Abstraction layer header for sound on retro systems.
Definition: mfile.h:184
Definition: mfmt.h:124
Generic image description struct.
Definition: mfmt.h:69
Definition: retroflt.h:1000
Struct containing configuration values for a RetroFlat program.
Definition: retroflt.h:1035
char * config_path
Relative path of local config file (if not using registry).
Definition: retroflt.h:1045
char * assets_path
Relative path under which bitmap assets are stored.
Definition: retroflt.h:1043
int screen_w
Desired screen or window width in pixels.
Definition: retroflt.h:1052
int screen_h
Desired screen or window height in pixels.
Definition: retroflt.h:1059
int screen_colors
Desired colors (2, 4, or 16, for now). \TODO Implement command-line argument for this....
Definition: retroflt.h:1071
char * title
Title to set for the main program Window if applicable on the target platform.
Definition: retroflt.h:1041
int screen_y
Desired window Y position in pixels.
Definition: retroflt.h:1063
int screen_x
Desired window X position in pixels.
Definition: retroflt.h:1061
Struct passed to retroflat_poll_input() to hold return data.
Definition: retroflt.h:865
int mouse_y
Y-coordinate of the mouse pointer in pixels if the returned event is a mouse click.
Definition: retroflt.h:875
int mouse_x
X-coordinate of the mouse pointer in pixels if the returned event is a mouse click.
Definition: retroflt.h:870
Global singleton containing state for the current platform.
Definition: retroflt.h:1130
size_t screen_h
The screen height as seen by the system, after scaling.
Definition: retroflt.h:1198
uint8_t vdp_flags
Flags set by the RetroFlat VDP API.
Definition: retroflt.h:1174
#define retroflat_heartbeat_update()
Check and update RETROFLAT_STATE::heartbeat_frame.
Definition: retroflt.h:1108
#define RETROFLAT_STATE_FLAG_KEY_REPEAT
Flag indicating keyboard repeat is enabled.
Definition: retroflt.h:408
#define retroflat_screen_colors()
Get the number of available on-screen colors.
Definition: retroflt.h:1083
size_t screen_v_w
The screen width as seen by our program, before scaling.
Definition: retroflt.h:1187
size_t screen_colors
The number of colors the screen is capable of displaying.
Definition: retroflt.h:1200
#define RETROFLAT_STATE_FLAG_SCREENSAVER
Flag indicating the current application is running as a screensaver.
Definition: retroflt.h:415
RETROFLAT_COLOR_DEF palette[RETROFLAT_COLORS_CT_MAX]
Index of available colors, initialized on platform init.
Definition: retroflt.h:1245
uint8_t retroflat_flags
maug_retroflt_flags indicating current system status.
Definition: retroflt.h:1140
uint8_t heartbeat_max
When RETROFLAT_STATE::heartbeat_frame reaches this value, it will reset to 0.
Definition: retroflt.h:1227
#define RETROFLAT_STATE_FLAG_WAIT_FOR_FPS
Do not execute any more inter-frame loops until next frame.
Definition: retroflt.h:426
retroflat_timer_cb_t timers_cb[RETROFLAT_TIMER_CT_MAX]
List of installable timers that should be tended every frame with retroflat_handle_timers().
Definition: retroflt.h:1267
#define RETROFLAT_STATE_FLAG_RUNNING
Flag indicating that retroflat_loop() should continue executing.
Definition: retroflt.h:394
uint8_t heartbeat_frame
Simple iteration loop that can be used to time e.g. perpetual sprite animations. Modify parameters wi...
Definition: retroflt.h:1222
size_t screen_w
The screen width as seen by the system, after scaling.
Definition: retroflt.h:1196
#define retroflat_heartbeat_set(len, max)
Set parameters for the RETROFLAT_STATE::heartbeat_frame.
Definition: retroflt.h:1091
void * vdp_exe
A handle for the loaded RetroFlat VDP API module.
Definition: retroflt.h:1164
uint8_t last_focus_flags
Used internally to track whether to call on_focus().
Definition: retroflt.h:1237
uint16_t heartbeat_len
Number of ms to stay on current value of RETROFLAT_STATE::heartbeat_frame before incrementing....
Definition: retroflt.h:1216
void * vdp_data
Pointer to data defined by the RetroFlat VDP API for its use.
Definition: retroflt.h:1170
struct RETROFLAT_BITMAP * vdp_buffer_in
A buffer assembled and passed to the RetroFlat VDP API for it to modify, or NULL if no VDP is loaded.
Definition: retroflt.h:1158
size_t screen_v_h
The screen height as seen by our program, before scaling.
Definition: retroflt.h:1194
int screen_scale
Off-screen buffer bitmap.
Definition: retroflt.h:1147
retroflat_proc_quit_t on_quit
Should be set with retroflat_set_proc_focus().
Definition: retroflt.h:1240
char vdp_args[RETROFLAT_VDP_ARGS_SZ_MAX+1]
CLI args passed with -vdp to the RetroFlat VDP API.
Definition: retroflt.h:1172
retroflat_proc_focus_t on_focus
Should be set with retroflat_set_proc_focus().
Definition: retroflt.h:1234
retroflat_proc_resize_t on_resize
Should be set with retroflat_set_proc_resize().
Definition: retroflt.h:1230
#define RETROFLAT_STATE_FLAG_UNLOCK_FPS
Flag indicating FPS should not be capped.
Definition: retroflt.h:401