maug
Quick and dirty C mini-augmentation library.
Loading...
Searching...
No Matches
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
13
19typedef int16_t retroflat_tile_t;
20
22
42
163
277
278/* === Generic Includes and Defines === */
279
280#ifndef RETROFLAT_BITMAP_TRACE_LVL
281# define RETROFLAT_BITMAP_TRACE_LVL 0
282#endif /* !RETROFLAT_BITMAP_TRACE_LVL */
283
284#ifndef RETROINPUT_TRACE_LVL
285# define RETROINPUT_TRACE_LVL 0
286#endif /* !RETROINPUT_TRACE_LVL */
287
288#include <stdarg.h>
289
290#include <marge.h>
291
296
307#define RETROFLAT_COLOR_TABLE( f ) \
308 f( 0, black, BLACK, 0, 0, 0, BLACK, BLACK ) \
309 f( 1, darkblue, DARKBLUE, 0, 0, 170, CYAN, BLACK ) \
310 f( 2, darkgreen, DARKGREEN, 0, 170, 0, CYAN, BLACK ) \
311 f( 3, teal, TEAL, 0, 170, 170, CYAN, CYAN ) \
312 f( 4, darkred, DARKRED, 170, 0, 0, MAGENTA, BLACK ) \
313 f( 5, violet, VIOLET, 170, 0, 170, MAGENTA, BLACK ) \
314 f( 6, brown, BROWN, 170, 85, 0, CYAN, MAGENTA ) \
315 f( 7, gray, GRAY, 170, 170, 170, WHITE, BLACK ) \
316 f( 8, darkgray, DARKGRAY, 85, 85, 85, WHITE, BLACK ) \
317 f( 9, blue, BLUE, 85, 85, 255, CYAN, WHITE ) \
318 f( 10, green, GREEN, 85, 255, 85, CYAN, CYAN ) \
319 f( 11, cyan, CYAN, 85, 255, 255, CYAN, CYAN ) \
320 f( 12, red, RED, 255, 85, 85, MAGENTA, WHITE ) \
321 f( 13, magenta, MAGENTA, 255, 85, 255, MAGENTA, MAGENTA ) \
322 f( 14, yellow, YELLOW, 255, 255, 85, CYAN, MAGENTA ) \
323 f( 15, white, WHITE, 255, 255, 255, WHITE, WHITE )
324
326typedef int8_t RETROFLAT_COLOR;
327
328# define RETROFLAT_COLOR_NULL (-1)
329
330# define RETROFLAT_COLORS_CT 16
331
333
334/* TODO: Mouse is broken under DOS/Allegro. */
335#if defined( RETROFLAT_OS_UNIX ) || defined( RETROFLAT_OS_WIN )
336#define RETROFLAT_MOUSE
337#endif /* RETROFLAT_OS_WIN || RETROFLAT_OS_WIN */
338
344
346#define RETROFLAT_OK 0x00
347#define RETROFLAT_ERROR_ENGINE 0x01
348#define RETROFLAT_ERROR_GRAPHICS 0x02
349#define RETROFLAT_ERROR_MOUSE 0x04
350
355#define RETROFLAT_ERROR_BITMAP 0x08
356#define RETROFLAT_ERROR_TIMER 0x0f
357 /* maug_retroflt_retval */
359
369
374#define RETROFLAT_DRAW_FLAG_FILL 0x01
375
381#define RETROFLAT_DRAW_FLAG_IGNORE_VIEWPORT 0x02
382
389#define RETROFLAT_FONT_FLAG_ALL_CAPS 0x02
390 /* maug_retroflt_drawing */
392
399#define RETROFLAT_STATE_FLAG_RUNNING 0x01
400
406#define RETROFLAT_STATE_FLAG_UNLOCK_FPS 0x02
407
413#define RETROFLAT_STATE_FLAG_KEY_REPEAT 0x04
414
420#define RETROFLAT_STATE_FLAG_SCREENSAVER 0x08
421
425#define RETROFLAT_STATE_FLAG_HWSCROLLING 0x10
426
431#define RETROFLAT_STATE_FLAG_WAIT_FOR_FPS 0x20
432
437#define RETROFLAT_STATE_FLAG_USE_GXC 0x40
438
443#define RETROFLAT_STATE_FLAG_QUIT_REQUESTED 0x80
444
451
455#define RETROFLAT_MSG_FLAG_TYPE_MASK 0x07
456
461#define RETROFLAT_MSG_FLAG_ERROR 0x01
462
468#define RETROFLAT_MSG_FLAG_INFO 0x02
469
475#define RETROFLAT_MSG_FLAG_WARNING 0x04
476 /* maug_retroflt_msg_api */
478
479struct RETROFLAT_STATE;
480
492
500#define RETROFLAT_VDP_FLAG_PXLOCK 0x01
501
514
515#define retroflat_vdp_available() (NULL != g_retroflat_state->vdp_exe)
516 /* maug_retroflt_vdp */
518
523
524typedef MERROR_RETVAL (*retroflat_proc_resize_t)(
525 uint16_t new_w, uint16_t new_h, void* data );
526
527#define RETROFLAT_FOCUS_FLAG_ACTIVE 0x01
528
529#define RETROFLAT_FOCUS_FLAG_VISIBLE 0x02
530
531typedef MERROR_RETVAL (*retroflat_proc_focus_t)( uint8_t flags, void* data );
532
537typedef MERROR_RETVAL (*retroflat_proc_quit_t)( void* data );
538 /* maug_retroflt_platform */
540
545
546#define RETROSND_ARGS_FLAG_LIST_DEVS 0x01
547
549
575
580#define RETROFLAT_BITMAP_FLAG_OPAQUE 0x01
581
585#define RETROFLAT_BITMAP_FLAG_LITERAL_PATH 0x02
586
590#define RETROFLAT_BITMAP_FLAG_RO 0x04
591
598#define RETROFLAT_BITMAP_FLAG_SCREEN_BUFFER 0x08
599
603#define RETROFLAT_BITMAP_FLAG_IGNORE_VIEWPORT 0x10
604
608#define RETROFLAT_BITMAP_FLAG_SCREEN_LOCK 0x20
609
613#define RETROFLAT_BITMAP_FLAG_LOCK 0x40
614
620#define RETROFLAT_INSTANCE_NULL (0)
621
626#define retroflat_instance_tile( instance ) \
627 (instance * -1)
628
633#ifndef RETROFLAT_BITMAP_EXT
634# define RETROFLAT_BITMAP_EXT "bmp"
635#endif /* !RETROFLAT_BITMAP_EXT */
636
637#ifndef RETROFLAT_OPENGL_BPP
638# define RETROFLAT_OPENGL_BPP 32
639#endif /* !RETROFLAT_OPENGL_BPP */
640
641#ifndef RETROFLAT_TILE_W
642# define RETROFLAT_TILE_W 16
643#endif /* !RETROFLAT_TILE_W */
644
645#ifndef RETROFLAT_TILE_W_BITS
646# define RETROFLAT_TILE_W_BITS 4
647#endif /* !RETROFLAT_TILE_W_BITS */
648
649#ifndef RETROFLAT_TILE_H
650# define RETROFLAT_TILE_H 16
651#endif /* !RETROFLAT_TILE_H */
652
653#ifndef RETROFLAT_TILE_H_BITS
654# define RETROFLAT_TILE_H_BITS 4
655#endif /* !RETROFLAT_TILE_H_BITS */
656
657/* Transparency background color: black by default, to match Allegro. */
658#ifndef RETROFLAT_TXP_R
664# define RETROFLAT_TXP_R 0x00
665#endif /* !RETROFLAT_TXP_R */
666
667#ifndef RETROFLAT_TXP_G
673# define RETROFLAT_TXP_G 0x00
674#endif /* !RETROFLAT_TXP_G */
675
676#ifndef RETROFLAT_TXP_B
682# define RETROFLAT_TXP_B 0x00
683#endif /* !RETROFLAT_TXP_B */
684
685#ifndef RETROFLAT_TXP_PAL_IDX
686# define RETROFLAT_TXP_PAL_IDX 0
687#endif /* !RETROFLAT_TXP_PAL_IDX */
688 /* maug_retroflt_bitmap */
690
691#ifndef RETROFLAT_DEFAULT_SCREEN_W
692# define RETROFLAT_DEFAULT_SCREEN_W 320
693#endif /* !RETROFLAT_DEFAULT_SCREEN_W */
694
695#ifndef RETROFLAT_DEFAULT_SCREEN_H
696# define RETROFLAT_DEFAULT_SCREEN_H 200
697#endif /* !RETROFLAT_DEFAULT_SCREEN_H */
698
699#ifndef RETROFLAT_DEFAULT_SCREEN_SCALE
700# define RETROFLAT_DEFAULT_SCREEN_SCALE 1
701#endif /* !RETROFLAT_DEFAULT_SCREEN_SCALE */
702
703#define retroflat_on_resize( w, h ) \
704 g_retroflat_state->screen_w = (w); \
705 g_retroflat_state->screen_h = (h);
706
711
712#ifndef RETROFLAT_LINE_THICKNESS
717# define RETROFLAT_LINE_THICKNESS 1
718#endif /* !RETROFLAT_LINE_THICKNESS */
719
720#define RETROFLAT_PI 3.14159
721 /* maug_retroflt_drawing */
723
728
729#ifndef RETROFLAT_FPS
734# define RETROFLAT_FPS 30
735#endif /* !RETROFLAT_FPS */
736
737#define retroflat_fps_next() (1000 / RETROFLAT_FPS)
738
739#ifndef RETROFLAT_WINDOW_CLASS
744# define RETROFLAT_WINDOW_CLASS "RetroFlatWindowClass"
745#endif /* !RETROFLAT_WINDOW_CLASS */
746
747#ifndef RETROFLAT_WIN_FRAME_TIMER_ID
752# define RETROFLAT_WIN_FRAME_TIMER_ID 6001
753#endif /* !RETROFLAT_WIN_FRAME_TIMER_ID */
754
755#ifndef RETROFLAT_WIN_LOOP_TIMER_ID
760# define RETROFLAT_WIN_LOOP_TIMER_ID 6002
761#endif /* !RETROFLAT_WIN_LOOP_TIMER_ID */
762
763#ifndef RETROFLAT_MSG_MAX
768# define RETROFLAT_MSG_MAX 4096
769#endif /* !RETROFLAT_MSG_MAX */
770
771#ifndef RETROFLAT_TITLE_MAX
772# define RETROFLAT_TITLE_MAX 255
773#endif /* !RETROFLAT_TITLE_MAX */
774
775#ifndef RETROFLAT_VDP_ARGS_SZ_MAX
779# define RETROFLAT_VDP_ARGS_SZ_MAX 255
780#endif /* !RETROFLAT_VDP_ARGS_SZ_MAX */
781
782#if defined( RETROFLAT_API_SDL2 )
783# if !defined( NO_RETROFLAT_RESIZABLE )
784# define RETROFLAT_WIN_FLAGS SDL_WINDOW_RESIZABLE
785# else
786# define RETROFLAT_WIN_FLAGS 0
787# endif /* !NO_RETROFLAT_RESIZABLE */
788#endif /* RETROFLAT_API_SDL2 */
789
790#if defined( RETROFLAT_API_SDL1 )
791# define RETROFLAT_SDL_CC_FLAGS (SDL_RLEACCEL | SDL_SRCCOLORKEY)
792#elif defined( RETROFLAT_API_SDL2 )
793# define RETROFLAT_SDL_CC_FLAGS (SDL_TRUE)
794#endif /* RETROFLAT_API_SDL1 || RETROFLAT_API_SDL2 */
795
796#ifdef RETROFLAT_OS_DOS
797# define RETROFLAT_PATH_SEP '\\'
798#else
800# define RETROFLAT_PATH_SEP '/'
801#endif /* RETROFLAT_OS_DOS */
802
803#ifndef RETROFLAT_COLORS_CT_MAX
804# define RETROFLAT_COLORS_CT_MAX 256
805#endif /* !RETROFLAT_COLORS_CT_MAX */
806
807#ifndef RETROFLAT_TIMER_CT_MAX
808# define RETROFLAT_TIMER_CT_MAX 10
809#endif /* !RETROFLAT_TIMER_CT_MAX */
810 /* maug_retroflt_compiling */
812
813#define retroflat_wait_for_frame() \
814 (g_retroflat_state->retroflat_flags |= RETROFLAT_STATE_FLAG_WAIT_FOR_FPS)
815
816#define retroflat_is_waiting_for_frame() \
817 (RETROFLAT_STATE_FLAG_WAIT_FOR_FPS == \
818 (g_retroflat_state->retroflat_flags & RETROFLAT_STATE_FLAG_WAIT_FOR_FPS))
819
823typedef void (*retroflat_loop_iter)(void* data);
824
825uint32_t retroflat_get_rand();
826
832
836#define retroflat_buffer_bksp( buffer, buffer_cur, buffer_sz ) \
837 if( 0 < buffer_cur ) { \
838 if( buffer_cur < buffer_sz ) { \
839 memmove( \
840 &(buffer[(buffer_cur) - 1]), \
841 &(buffer[buffer_cur]), \
842 (buffer_sz) - (buffer_cur) ); \
843 } \
844 buffer_cur--; \
845 buffer_sz--; \
846 buffer[buffer_sz] = '\0'; \
847 }
848
852#define retroflat_buffer_insert( c, buffer, buffer_cur, buffer_sz, buffer_mx ) \
853 if( buffer_sz + 1 < buffer_mx ) { \
854 if( buffer_cur < buffer_sz ) { \
855 memmove( \
856 &(buffer[(buffer_cur) + 1]), \
857 &(buffer[buffer_cur]), \
858 (buffer_sz) - (buffer_cur) ); \
859 } \
860 buffer[buffer_cur] = c; \
861 buffer_cur++; \
862 buffer_sz++; \
863 buffer[buffer_sz] = '\0'; \
864 }
865
866#define RETROFLAT_INPUT_MOD_SHIFT 0x01
867
868#define RETROFLAT_INPUT_MOD_ALT 0x02
869
870#define RETROFLAT_INPUT_MOD_CTRL 0x04
871
872#define RETROFLAT_INPUT_FORCE_UPPER 0x08
873
886 uint8_t key_flags;
887};
888 /* maug_retroflt_input */
890
897
898typedef int8_t retroflat_dir4_t;
899
900typedef int8_t retroflat_dir8_t;
901
902#define RETROFLAT_DIR4_NONE (-1)
903#define RETROFLAT_DIR4_NORTH 0
904#define RETROFLAT_DIR4_EAST 1
905#define RETROFLAT_DIR4_SOUTH 2
906#define RETROFLAT_DIR4_WEST 3
907
908#define RETROFLAT_DIR8_NONE (-1)
909#define RETROFLAT_DIR8_NORTH 0
910#define RETROFLAT_DIR8_EAST 2
911#define RETROFLAT_DIR8_SOUTH 4
912#define RETROFLAT_DIR8_WEST 6
913
914#define retroflat_dir4_rotate_cw( dir ) \
915 ((dir + 1) % 4)
916
917#define retroflat_dir8_reverse( dir ) \
918 ((dir + 4) % 8)
919
920#define retroflat_dir8_bounce( dir ) \
921 ((dir + 2) % 8)
922 /* maug_retroflt_dir */
924
931typedef int16_t retroflat_pxxy_t;
932
933#define PXXY_FMT "%d"
934
935#define PXXY_MAX INT16_MAX
936
937struct RETROFLAT_ARGS;
938
939#ifndef RETRO2D_TRACE_LVL
940# define RETRO2D_TRACE_LVL 0
941#endif /* !RETRO2D_TRACE_LVL */
942
943#ifndef RETRO2D_DRAW_TRACE_LVL
944# define RETRO2D_DRAW_TRACE_LVL 0
945#endif /* !RETRO2D_DRAW_TRACE_LVL */
946
947#ifndef RETRO2D_LOCK_TRACE_LVL
948# define RETRO2D_LOCK_TRACE_LVL 0
949#endif /* !RETRO2D_LOCK_TRACE_LVL */
950
951typedef maug_ms_t retroflat_ms_t;
952
953retroflat_ms_t retroflat_get_ms();
954
955#ifndef RETROFLAT_NO_SOUND
956# include "retrosnd.h"
957#endif /* !RETROFLAT_NO_SOUND */
958
959/* === Platform-specific APIs === */
960
961/* The first call to these headers should just establish definitions (macros, defines, prototypes,
962 * typedefs, etc). The later call below should then define function bodies.
963 */
964#ifndef RETROFLAT_NO_SOUND
965# include <retapis.h>
966#endif /* !RETROFLAT_NO_SOUND */
967#include <retapii.h>
968
969/* === End platform-specific APIs === */
970
975
976# if defined( RETROFLAT_NO_KEYBOARD )
977# define retroflat_case_key( key, pad ) case pad:
978# define retroflat_or_key( input, key, pad ) ((input) == (pad))
979# elif defined( RETROFLAT_NO_PAD )
980# define retroflat_case_key( key, pad ) case key:
981# define retroflat_or_key( input, key, pad ) ((input) == (key))
982# else
990# define retroflat_case_key( key, pad ) case pad: case key:
991# define retroflat_or_key( input, key, pad ) \
992 (((input) == (pad)) || ((input) == (key)))
993# endif
994 /* maug_retroflt_input */
996
997/* === OS-Specific Includes and Defines === */
998
999#if defined( RETROFLAT_OS_WIN ) && !defined( MAUG_WINDOWS_H )
1000# include <windows.h>
1001# define MAUG_WINDOWS_H
1002#endif /* !MAUG_WINDOWS_H */
1003
1004#if defined( RETROFLAT_BMP_TEX ) || defined( DOCUMENTATION )
1005
1007 uint8_t flags;
1008 MAUG_MHANDLE bytes_h;
1009 uint8_t* bytes;
1010 uint32_t bpp;
1011 uint32_t sz;
1012 uint8_t* px;
1013 uint32_t id;
1014 size_t w;
1015 size_t h;
1016};
1017
1018#endif /* RETROFLAT_BMP_TEX */
1019
1020/* TODO: Migrate all platform-specific parts below to retapid.h. */
1021#include <retapid.h>
1022
1023#ifndef retroflat_system_task
1029# define retroflat_system_task()
1030#endif /* !retroflat_system_task */
1031
1032typedef void (*retroflat_timer_cb_t)( retroflat_ms_t time, void* data );
1033
1034#include "retrom2d.h"
1035
1036/* === Structures === */
1037
1038/* TODO: Break the args into API-specific headers. */
1039
1042 uint8_t flags;
1047 char* title;
1070 int screen_scale;
1078 int joystick_id;
1079 struct RETROFLAT_PLATFORM_ARGS platform;
1080# ifndef RETROFLAT_NO_SOUND
1081 struct RETROFLAT_SOUND_ARGS sound;
1082# endif /* !RETROFLAT_NO_SOUND */
1083};
1084
1089# define retroflat_screen_colors() (g_retroflat_state->screen_colors)
1090
1097#define retroflat_heartbeat_set( len, max ) \
1098 g_retroflat_state->heartbeat_max = max; \
1099 g_retroflat_state->heartbeat_len = len;
1100
1105#define retroflat_heartbeat() (g_retroflat_state->heartbeat_frame)
1106
1114#define retroflat_heartbeat_update() \
1115 /* Update the heartbeat animation frame. */ \
1116 if( g_retroflat_state->heartbeat_next <= retroflat_get_ms() ) { \
1117 g_retroflat_state->heartbeat_frame++; \
1118 if( \
1119 g_retroflat_state->heartbeat_frame >= \
1120 g_retroflat_state->heartbeat_max \
1121 ) { \
1122 g_retroflat_state->heartbeat_frame = 0; \
1123 } \
1124 g_retroflat_state->heartbeat_next = \
1125 retroflat_get_ms() + g_retroflat_state->heartbeat_len; \
1126 }
1127
1128#include <retroviw.h>
1129
1137 /* TODO: Set this up in the initialization function! */
1138 /* TODO: We probably need more of these. */
1139 size_t sz;
1140 size_t offset_pal;
1141 size_t offset_tex_pal;
1142
1143 void* loop_data;
1144 MERROR_RETVAL retval;
1147 maug_path config_path;
1148 maug_path assets_path;
1149 maug_path saves_path;
1150
1152 /* struct RETROFLAT_BITMAP buffer; */
1154
1155# if defined( RETROFLAT_VDP ) || defined( DOCUMENTATION ) || \
1156defined( RETROVDP_C )
1164 struct RETROFLAT_BITMAP* vdp_buffer_in;
1165 struct RETROFLAT_BITMAP* vdp_buffer_out;
1166# ifdef RETROFLAT_OS_WIN
1167 HMODULE vdp_exe;
1168# else
1170 void* vdp_exe;
1171# endif /* RETROFLAT_OS_WIN */
1180 uint8_t vdp_flags;
1181# endif /* RETROFLAT_VDP || DOCUMENTATION || RETROVDP_C */
1182
1183 /* These are used by VDP so should be standardized/not put in plat-spec! */
1184
1185 struct RETROFLAT_VIEWPORT viewport;
1186
1202 size_t screen_w;
1204 size_t screen_h;
1207
1208 /* WARNING: The VDP requires the state specifier to be the same size
1209 * as the one it was compiled for! Do not modify above here!
1210 */
1211
1212 /* TODO: Put these in a platform-specific struct of some kind to maintain
1213 * consistent state struct size for VDP?
1214 */
1215
1216 retroflat_ms_t heartbeat_next;
1234
1236 retroflat_proc_resize_t on_resize;
1237 void* on_resize_data;
1238
1240 retroflat_proc_focus_t on_focus;
1241 void* on_focus_data;
1244
1247 void* on_quit_data;
1248
1249#ifndef RETROFLAT_BMP_TEX
1251 RETROFLAT_COLOR_DEF palette[RETROFLAT_COLORS_CT_MAX];
1252#endif /* !RETROFLAT_BMP_TEX */
1253
1254 retroflat_loop_iter loop_iter;
1255 retroflat_loop_iter frame_iter;
1256
1257 struct RETROFLAT_PLATFORM platform;
1258
1259# if defined( RETROFLAT_BMP_TEX )
1260 /* This allows native colors to be used for things like glColor3fv while
1261 * these colors are used to manipulate textures passed through
1262 * retroflat_bitmap_*().
1263 */
1264 RETROFLAT_TEX_COLOR_DEF tex_palette[RETROFLAT_COLORS_CT_MAX];
1265# endif /* RETROFLAT_BMP_TEX */
1266
1267 struct RETROFLAT_INPUT_STATE input;
1268
1273 retroflat_timer_cb_t timers_cb[RETROFLAT_TIMER_CT_MAX];
1274 retroflat_ms_t timers_at[RETROFLAT_TIMER_CT_MAX];
1275 void* timers_data[RETROFLAT_TIMER_CT_MAX];
1276 size_t timers_ct;
1277
1278# ifndef RETROFLAT_NO_SOUND
1279 struct RETROFLAT_SOUND_STATE sound;
1280# endif /* !RETROFLAT_NO_SOUND */
1281};
1282
1283/* === Translation Module === */
1284
1285/* Declare the prototypes so that internal functions can call each other. */
1286
1287# ifdef retroflat_loop
1288MERROR_RETVAL retroflat_loop_generic(
1289 retroflat_loop_iter frame_iter, retroflat_loop_iter loop_iter, void* data );
1290# else
1297 retroflat_loop_iter frame_iter, retroflat_loop_iter loop_iter, void* data );
1298# endif /* retroflat_loop */
1299
1300#define retroflat_get_assets_path() (g_retroflat_state->assets_path)
1301
1302MERROR_RETVAL retroflat_build_filename_path(
1303 const maug_path filename_in, const char* filename_ext,
1304 char* buffer_out, size_t buffer_out_sz, uint8_t flags );
1305
1310
1318 uint8_t flags, const char* title, const char* format, ... );
1319 /* maug_retroflt_msg_api */
1321
1329MERROR_RETVAL retroflat_init( int argc, char* argv[], struct RETROFLAT_ARGS* args );
1330
1337void retroflat_shutdown( int retval );
1338
1339# if defined( RETROFLAT_VDP ) || defined( DOCUMENTATION )
1344
1348MERROR_RETVAL retroflat_vdp_call( const char* proc_name );
1349
1350uint8_t* retroflat_vdp_get_vdp_in();
1351
1352uint8_t* retroflat_vdp_get_vdp_out();
1353 /* maug_retroflt_vdp */
1355# endif /* RETROFLAT_VDP || DOCUMENTATION */
1356
1357RETROFLAT_IN_KEY retroflat_repeat_input(
1358 RETROFLAT_IN_KEY key_out, struct RETROFLAT_INPUT* input,
1359 RETROFLAT_IN_KEY* prev_input, int* prev_delay );
1360
1361void retroflat_set_title( const char* format, ... );
1362
1363# if !defined( RETROFLAT_NO_KEYBOARD )
1364char retroflat_vk_to_ascii( RETROFLAT_IN_KEY k, uint8_t flags );
1365# endif /* !RETROFLAT_NO_KEYBOARD */
1366
1371
1383 const char* filename, struct RETROFLAT_BITMAP* bmp_out, uint8_t flags );
1384
1385MERROR_RETVAL retroflat_create_bitmap(
1387 struct RETROFLAT_BITMAP* bmp_out, uint8_t flags );
1388
1394void retroflat_destroy_bitmap( struct RETROFLAT_BITMAP* bitmap );
1395
1412 struct RETROFLAT_BITMAP* target, struct RETROFLAT_BITMAP* src,
1416 int16_t instance );
1417 /* maug_retroflt_bitmap */
1419
1424
1434MERROR_RETVAL retroflat_draw_lock( struct RETROFLAT_BITMAP* bmp );
1435
1436MERROR_RETVAL retroflat_draw_release( struct RETROFLAT_BITMAP* bmp );
1437
1438void retroflat_px(
1439 struct RETROFLAT_BITMAP* target, const RETROFLAT_COLOR color,
1440 retroflat_pxxy_t x, retroflat_pxxy_t y, uint8_t flags );
1441
1442#ifdef RETROFLAT_SOFT_SHAPES
1443# ifdef RETROFLAT_OPENGL
1444/* Make sure we're not passing NULL to openGL texture drawers... they can't
1445 * handle that!
1446 */
1447# define retroflat_rect( t, c, x, y, w, h, f ) \
1448 assert( NULL != t ); \
1449 retrosoft_rect( t, c, x, y, w, h, f );
1450# define retroflat_ellipse( t, c, x, y, w, h, f ) \
1451 assert( NULL != t ); \
1452 retrosoft_ellipse( t, c, x, y, w, h, f )
1453# else
1454# define retroflat_rect( t, c, x, y, w, h, f ) \
1455 retrosoft_rect( t, c, x, y, w, h, f )
1456# define retroflat_ellipse( t, c, x, y, w, h, f ) \
1457 retrosoft_ellipse( t, c, x, y, w, h, f )
1458# endif /* RETROFLAT_3D */
1459#else
1460
1472 struct RETROFLAT_BITMAP* target, const RETROFLAT_COLOR color,
1474 retroflat_pxxy_t w, retroflat_pxxy_t h, uint8_t flags );
1475
1487 struct RETROFLAT_BITMAP* target, const RETROFLAT_COLOR color,
1489 retroflat_pxxy_t w, retroflat_pxxy_t h, uint8_t flags );
1490
1491#endif /* RETROFLAT_SOFT_SHAPES */
1492
1493#ifdef RETROFLAT_SOFT_LINES
1494# define retroflat_line( t, c, x1, y1, x2, y2, f ) \
1495 retrosoft_line( t, c, x1, y1, x2, y2, f )
1496#else
1497
1510 struct RETROFLAT_BITMAP* target, const RETROFLAT_COLOR color,
1512 retroflat_pxxy_t x2, retroflat_pxxy_t y2, uint8_t flags );
1513
1514#endif /* RETROFLAT_SOFT_LINES */
1515
1516void retroflat_cursor( struct RETROFLAT_BITMAP* target, uint8_t flags );
1517
1531 struct RETROFLAT_BITMAP* target, const char* str, size_t str_sz,
1532 const char* font_str,
1533 retroflat_pxxy_t* w_out, retroflat_pxxy_t* h_out, uint8_t flags );
1534
1553 struct RETROFLAT_BITMAP* target, const RETROFLAT_COLOR color,
1554 const char* str, int str_sz, const char* font_str,
1555 retroflat_pxxy_t x_orig, retroflat_pxxy_t y_orig,
1556 uint8_t flags );
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
1570
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
1620
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
1660
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
1682# ifdef RETROFLAT_STATE_ON_STACK
1683struct RETROFLAT_STATE SEG_MGLOBAL g_retroflat_state_stack;
1684# else
1685MAUG_MHANDLE SEG_MGLOBAL g_retroflat_state_h = (MAUG_MHANDLE)NULL;
1686# endif /* RETROFLAT_STATE_ON_STACK */
1687struct RETROFLAT_STATE* SEG_MGLOBAL g_retroflat_state = NULL;
1688
1689# define RETROFLAT_COLOR_TABLE_CONSTS( idx, name_l, name_u, r, g, b, cgac, cgad ) \
1690 MAUG_CONST RETROFLAT_COLOR SEG_MCONST RETROFLAT_COLOR_ ## name_u = idx;
1691
1692RETROFLAT_COLOR_TABLE( RETROFLAT_COLOR_TABLE_CONSTS )
1693
1694# define RETROFLAT_COLOR_TABLE_NAMES( idx, name_l, name_u, r, g, b, cgac, cgad ) \
1695 #name_u,
1696
1697MAUG_CONST char* SEG_MCONST gc_retroflat_color_names[] = {
1698 RETROFLAT_COLOR_TABLE( RETROFLAT_COLOR_TABLE_NAMES )
1699};
1700
1701/* Call a second time, to add function bodies. */
1702#include <retroviw.h>
1703
1704/* Callback table is down below, after the statically-defined callbacks. */
1705
1706/* === Function Definitions === */
1707
1708MERROR_RETVAL retroflat_build_filename_path(
1709 const maug_path filename_in, const char* filename_ext,
1710 char* buffer_out, size_t buffer_out_sz, uint8_t flags
1711) {
1712 MERROR_RETVAL retval = MERROR_OK;
1713
1714 assert( 1 < buffer_out_sz );
1715
1716 /* Build the path to the bitmap. */
1717 maug_mzero( buffer_out, buffer_out_sz );
1718 if(
1721 ) {
1722 /* TODO: Error checking. */
1723 maug_snprintf( buffer_out, buffer_out_sz - 1, "%s", filename_in );
1724 } else if( NULL != filename_ext ) {
1725 /* TODO: Error checking. */
1726 maug_snprintf( buffer_out, buffer_out_sz - 1, "%s%c%s.%s",
1727 g_retroflat_state->assets_path, RETROFLAT_PATH_SEP,
1728 filename_in, filename_ext );
1729 } else {
1730 maug_snprintf( buffer_out, buffer_out_sz - 1, "%s%c%s",
1731 g_retroflat_state->assets_path, RETROFLAT_PATH_SEP,
1732 filename_in );
1733 }
1734
1735 return retval;
1736}
1737
1738/* === */
1739
1740# if (defined( RETROFLAT_SOFT_SHAPES ) || defined( RETROFLAT_SOFT_LINES ) || \
1741 defined( RETROFLAT_3D ))
1742/* RETROSOFT_PRESENT is different from RETROFLAT_SOFT_SHAPES in that it only
1743 * indicates that the retrosoft library is loaded, not that it is the default
1744 * for drawing primatives!
1745 */
1746# define RETROSOFT_PRESENT
1747# endif
1748
1749# if defined( RETROFLAT_3D )
1750# if !defined( MAUG_NO_AUTO_C )
1751# define RETRO3D_C
1752# define RETRO3DP_C
1753# define RETROFP_C
1754# endif /* MAUG_NO_AUTO_C */
1755# include <retro3dp.h>
1756# include <retro3d.h>
1757# include <retro3du.h>
1758# include <retapi3.h>
1759# endif /* RETROFLAT_3D */
1760
1761# ifdef RETROSOFT_PRESENT
1762# if !defined( MAUG_NO_AUTO_C )
1763# define RETROSFT_C
1764# endif /* !MAUG_NO_AUTO_C */
1765# define RETROSOFT_PRESENT
1766# include <retrosft.h>
1767# endif /* RETROFLAT_SOFT_SHAPES */
1768
1769# ifndef RETROFLAT_NO_SOUND
1770# include <retapis.h>
1771# endif /* !RETROFLAT_NO_SOUND */
1772
1773# include <retapii.h>
1774
1775# if defined( RETROFLAT_VDP ) && defined( RETROFLAT_OS_UNIX )
1776# include <dlfcn.h>
1777# endif
1778
1779/* Still inside RETROFLT_C! */
1780
1781/* === */
1782
1783#ifndef RETROFLAT_NO_GENERIC_LOOP
1784
1785MERROR_RETVAL retroflat_loop_generic(
1786 retroflat_loop_iter frame_iter, retroflat_loop_iter loop_iter, void* data
1787) {
1788 MERROR_RETVAL retval = MERROR_OK;
1789 retroflat_ms_t next = 0,
1790 now = 0;
1791
1792 g_retroflat_state->loop_iter = (retroflat_loop_iter)loop_iter;
1793 g_retroflat_state->loop_data = (void*)data;
1794 g_retroflat_state->frame_iter = (retroflat_loop_iter)frame_iter;
1795
1796 if(
1798 (g_retroflat_state->retroflat_flags & RETROFLAT_STATE_FLAG_RUNNING)
1799 ) {
1800 /* Main loop is already running, so we're just changing the iter call
1801 * and leaving!
1802 */
1803 debug_printf( 1, "main loop already running!" );
1804 goto cleanup;
1805 }
1806
1807 g_retroflat_state->retroflat_flags |= RETROFLAT_STATE_FLAG_RUNNING;
1808 do {
1810
1811 if(
1812 /* Not waiting for the next frame? */
1814 (RETROFLAT_STATE_FLAG_WAIT_FOR_FPS & g_retroflat_state->retroflat_flags) &&
1815 /* Inter-frame loop present? */
1816 NULL != g_retroflat_state->loop_iter
1817 ) {
1818 /* Run the loop iter as many times as possible. */
1819 g_retroflat_state->loop_iter( g_retroflat_state->loop_data );
1820 }
1821 if(
1823 (RETROFLAT_STATE_FLAG_UNLOCK_FPS & g_retroflat_state->retroflat_flags) &&
1824 retroflat_get_ms() < next
1825 ) {
1826 /* Sleep/low power for a bit. */
1827 continue;
1828 }
1829
1831
1833
1834 if(
1835 NULL != g_retroflat_state->on_focus &&
1836 g_retroflat_state->last_focus_flags != retroflat_focus_platform()
1837 ) {
1838 g_retroflat_state->last_focus_flags = retroflat_focus_platform();
1839 retval = g_retroflat_state->on_focus(
1840 g_retroflat_state->last_focus_flags,
1841 g_retroflat_state->on_focus_data );
1842 maug_cleanup_if_not_ok();
1843 }
1844
1845 if( NULL != g_retroflat_state->frame_iter ) {
1846 /* Run the frame iterator once per FPS tick. */
1847 g_retroflat_state->frame_iter( g_retroflat_state->loop_data );
1848 }
1849 /* Reset wait-for-frame flag AFTER frame callback. */
1850 g_retroflat_state->retroflat_flags &= ~RETROFLAT_STATE_FLAG_WAIT_FOR_FPS;
1851 now = retroflat_get_ms();
1852 if( now + retroflat_fps_next() > now ) {
1853 next = now + retroflat_fps_next();
1854 } else {
1855 /* Rollover protection. */
1856 /* TODO: Add difference from now/next to 0 here. */
1857 next = 0;
1858 }
1859 } while(
1861 (RETROFLAT_STATE_FLAG_RUNNING & g_retroflat_state->retroflat_flags)
1862 );
1863 retval = g_retroflat_state->retval;
1864
1865cleanup:
1866
1867 /* This should be set by retroflat_quit(). */
1868 return retval;
1869}
1870
1871#endif /* !RETROFLAT_NO_GENERIC_LOOP */
1872
1873/* === */
1874
1875# if !defined( RETROFLAT_NO_KEYBOARD )
1876
1877char retroflat_vk_to_ascii( RETROFLAT_IN_KEY k, uint8_t flags ) {
1878 char c = 0;
1879 char offset_lower = 0;
1880
1881 if( RETROFLAT_INPUT_MOD_SHIFT != (RETROFLAT_INPUT_MOD_SHIFT & flags) ) {
1882 /* Shift is *not* being held down. */
1883
1884 if( RETROFLAT_KEY_A <= k && RETROFLAT_KEY_Z >= k ) {
1885 if(
1886 RETROFLAT_INPUT_FORCE_UPPER !=
1887 (RETROFLAT_INPUT_FORCE_UPPER & flags)
1888 ) {
1889 /* Key is alphabetical and we're not forcing uppercase. */
1890 offset_lower = 0x20;
1891 }
1892 } else {
1893 offset_lower = 1;
1894 }
1895 }
1896
1897 switch( k ) {
1898 case RETROFLAT_KEY_A: c = 0x41 + offset_lower; break;
1899 case RETROFLAT_KEY_B: c = 0x42 + offset_lower; break;
1900 case RETROFLAT_KEY_C: c = 0x43 + offset_lower; break;
1901 case RETROFLAT_KEY_D: c = 0x44 + offset_lower; break;
1902 case RETROFLAT_KEY_E: c = 0x45 + offset_lower; break;
1903 case RETROFLAT_KEY_F: c = 0x46 + offset_lower; break;
1904 case RETROFLAT_KEY_G: c = 0x47 + offset_lower; break;
1905 case RETROFLAT_KEY_H: c = 0x48 + offset_lower; break;
1906 case RETROFLAT_KEY_I: c = 0x49 + offset_lower; break;
1907 case RETROFLAT_KEY_J: c = 0x4a + offset_lower; break;
1908 case RETROFLAT_KEY_K: c = 0x4b + offset_lower; break;
1909 case RETROFLAT_KEY_L: c = 0x4c + offset_lower; break;
1910 case RETROFLAT_KEY_M: c = 0x4d + offset_lower; break;
1911 case RETROFLAT_KEY_N: c = 0x4e + offset_lower; break;
1912 case RETROFLAT_KEY_O: c = 0x4f + offset_lower; break;
1913 case RETROFLAT_KEY_P: c = 0x50 + offset_lower; break;
1914 case RETROFLAT_KEY_Q: c = 0x51 + offset_lower; break;
1915 case RETROFLAT_KEY_R: c = 0x52 + offset_lower; break;
1916 case RETROFLAT_KEY_S: c = 0x53 + offset_lower; break;
1917 case RETROFLAT_KEY_T: c = 0x54 + offset_lower; break;
1918 case RETROFLAT_KEY_U: c = 0x55 + offset_lower; break;
1919 case RETROFLAT_KEY_V: c = 0x56 + offset_lower; break;
1920 case RETROFLAT_KEY_W: c = 0x57 + offset_lower; break;
1921 case RETROFLAT_KEY_X: c = 0x58 + offset_lower; break;
1922 case RETROFLAT_KEY_Y: c = 0x59 + offset_lower; break;
1923 case RETROFLAT_KEY_Z: c = 0x60 + offset_lower; break;
1924 case RETROFLAT_KEY_0: c = offset_lower ? 0x30 : ')'; break;
1925 case RETROFLAT_KEY_1: c = offset_lower ? 0x31 : '!'; break;
1926 case RETROFLAT_KEY_2: c = offset_lower ? 0x32 : '@'; break;
1927 case RETROFLAT_KEY_3: c = offset_lower ? 0x33 : '#'; break;
1928 case RETROFLAT_KEY_4: c = offset_lower ? 0x34 : '$'; break;
1929 case RETROFLAT_KEY_5: c = offset_lower ? 0x35 : '%'; break;
1930 case RETROFLAT_KEY_6: c = offset_lower ? 0x36 : '^'; break;
1931 case RETROFLAT_KEY_7: c = offset_lower ? 0x37 : '&'; break;
1932 case RETROFLAT_KEY_8: c = offset_lower ? 0x38 : '*'; break;
1933 case RETROFLAT_KEY_9: c = offset_lower ? 0x39 : '('; break;
1934 case RETROFLAT_KEY_SPACE: c = ' '; break;
1935 case RETROFLAT_KEY_BKSP: c = 0x08; break;
1936 case RETROFLAT_KEY_ENTER: c = '\n'; break;
1937 case RETROFLAT_KEY_SEMICOLON: c = offset_lower ? ';' : ':'; break;
1938 case RETROFLAT_KEY_DASH: c = offset_lower ? '-' : '_'; break;
1939 case RETROFLAT_KEY_SLASH: c = offset_lower ? '/' : '?'; break;
1940 case RETROFLAT_KEY_PERIOD: c = offset_lower ? '.' : '>'; break;
1941 case RETROFLAT_KEY_COMMA: c = offset_lower ? ',' : '<'; break;
1942 case RETROFLAT_KEY_QUOTE: c = offset_lower ? '\'' : '"'; break;
1943 case RETROFLAT_KEY_EQUALS: c = offset_lower ? '=' : '+'; break;
1944 case RETROFLAT_KEY_BACKSLASH: c = offset_lower ? '\\' : '|'; break;
1945 case RETROFLAT_KEY_BRACKETL: c = offset_lower ? '[' : '{'; break;
1946 case RETROFLAT_KEY_BRACKETR: c = offset_lower ? ']' : '}'; break;
1947#ifndef RETROFLAT_API_PC_BIOS
1948 /* TODO: FIXME in DOS! */
1949 case RETROFLAT_KEY_GRAVE: c = offset_lower ? '`' : '~'; break;
1950#endif /* !RETROFLAT_API_PC_BIOS */
1951 }
1952
1953 debug_printf( RETROINPUT_TRACE_LVL, "0x%02x", c );
1954
1955 return c;
1956}
1957
1958#endif /* !RETROFLAT_NO_KEYBOARD */
1959
1960/* === */
1961
1962/* TODO: Migrate all platform-specific parts below to retapif.h. */
1963#include <retapif.h>
1964
1965/* === */
1966
1967# ifndef RETROFLAT_NO_CLI
1968
1969# if !defined( RETROFLAT_NO_SOUND ) && defined( RETROSND_ARGS )
1970
1971static MERROR_RETVAL retrosnd_cli_rsl(
1972 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
1973) {
1974 if(
1975 0 <= arg_c &&
1976 0 == maug_strncmp( MAUG_CLI_SIGIL "rsl", arg, MAUG_CLI_SIGIL_SZ + 4 )
1977 ) {
1978 args->sound.flags |= RETROSND_ARGS_FLAG_LIST_DEVS;
1979 }
1980 return MERROR_OK;
1981}
1982
1983# endif /* !RETROFLAT_NO_SOUND && RETROSND_ARGS */
1984
1985# if !defined( RETROFLAT_API_PC_BIOS ) && !defined( RETROFLAT_NO_CLI_SZ )
1986
1987static MERROR_RETVAL retroflat_cli_rfs(
1988 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
1989) {
1990 if( 1 < arg_c ) {
1991 args->screen_scale = atoi( arg );
1992 debug_printf( 3, "screen scale arg set to: %d", args->screen_scale );
1993 }
1994 return MERROR_OK;
1995}
1996
1997static MERROR_RETVAL retroflat_cli_rfx(
1998 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
1999) {
2000 if( 0 > arg_c ) {
2001 if( 0 == args->screen_w ) {
2002 args->screen_x = 0;
2003 }
2004 } else if(
2005 0 == maug_strncmp( MAUG_CLI_SIGIL "rfx", arg, MAUG_CLI_SIGIL_SZ + 4 )
2006 ) {
2007 /* The next arg must be the new var. */
2008 } else {
2009 args->screen_x = atoi( arg );
2010 }
2011 return MERROR_OK;
2012}
2013
2014static MERROR_RETVAL retroflat_cli_rfy(
2015 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2016) {
2017 if( 0 > arg_c ) {
2018 if( 0 == args->screen_h ) {
2019 args->screen_y = 0;
2020 }
2021 } else if(
2022 0 == maug_strncmp( MAUG_CLI_SIGIL "rfy", arg, MAUG_CLI_SIGIL_SZ + 4 )
2023 ) {
2024 /* The next arg must be the new var. */
2025 } else {
2026 args->screen_y = atoi( arg );
2027 }
2028 return MERROR_OK;
2029}
2030
2031static MERROR_RETVAL retroflat_cli_rfw(
2032 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2033) {
2034 if( 0 > arg_c ) {
2035 if( 0 == args->screen_w ) {
2036 args->screen_w = RETROFLAT_DEFAULT_SCREEN_W;
2037 debug_printf( 1, "setting arg screen_w to default %d:",
2038 args->screen_w );
2039 }
2040 } else if(
2041 0 == maug_strncmp( MAUG_CLI_SIGIL "rfw", arg, MAUG_CLI_SIGIL_SZ + 4 )
2042 ) {
2043 /* The next arg must be the new var. */
2044 } else {
2045 args->screen_w = atoi( arg );
2046 debug_printf( 1, "setting arg screen_w to: %d",
2047 args->screen_w );
2048 }
2049 return MERROR_OK;
2050}
2051
2052static MERROR_RETVAL retroflat_cli_rfh(
2053 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2054) {
2055 if( 0 > arg_c ) {
2056 if( 0 == args->screen_h ) {
2057 args->screen_h = RETROFLAT_DEFAULT_SCREEN_H;
2058 debug_printf( 1, "setting arg screen_h to default: %d",
2059 args->screen_h );
2060 }
2061 } else if(
2062 0 == maug_strncmp( MAUG_CLI_SIGIL "rfh", arg, MAUG_CLI_SIGIL_SZ + 4 )
2063 ) {
2064 /* The next arg must be the new var. */
2065 } else {
2066 args->screen_h = atoi( arg );
2067 debug_printf( 1, "setting arg screen_h to: %d",
2068 args->screen_h );
2069 }
2070 return MERROR_OK;
2071}
2072
2073# endif /* !RETROFLAT_API_PC_BIOS && !RETROFLAT_NO_CLI_SZ */
2074
2075# ifdef RETROFLAT_VDP
2076static MERROR_RETVAL retroflat_cli_vdp(
2077 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2078) {
2079 if( 0 == maug_strncmp( MAUG_CLI_SIGIL "vdp", arg, MAUG_CLI_SIGIL_SZ + 4 ) ) {
2080 /* Next arg is VDP args str. */
2081 } else {
2082 maug_mzero( g_retroflat_state->vdp_args, RETROFLAT_VDP_ARGS_SZ_MAX + 1 );
2083 maug_strncpy(
2084 g_retroflat_state->vdp_args, arg, RETROFLAT_VDP_ARGS_SZ_MAX );
2085 debug_printf( 1, "VDP args: %s", g_retroflat_state->vdp_args );
2086 }
2087 return MERROR_OK;
2088}
2089# endif /* RETROFLAT_VDP */
2090
2091static MERROR_RETVAL retroflat_cli_u(
2092 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2093) {
2094 if( 0 > arg_c ) {
2095 args->flags &= ~RETROFLAT_STATE_FLAG_UNLOCK_FPS;
2096 } else if(
2097 0 == maug_strncmp( MAUG_CLI_SIGIL "rfu", arg, MAUG_CLI_SIGIL_SZ + 4 )
2098 ) {
2099 debug_printf( 1, "unlocking FPS..." );
2100 args->flags |= RETROFLAT_STATE_FLAG_UNLOCK_FPS;
2101 }
2102 return MERROR_OK;
2103}
2104
2105# ifndef RETROFLAT_NO_PAD
2106
2107static MERROR_RETVAL retroflat_cli_rfj(
2108 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2109) {
2110 if( 0 > arg_c ) {
2111 args->joystick_id = -1;
2112 debug_printf( 1, "setting arg joystick_id to default: %d",
2113 args->joystick_id );
2114 } else if(
2115 0 == maug_strncmp( MAUG_CLI_SIGIL "rfj", arg, MAUG_CLI_SIGIL_SZ + 4 )
2116 ) {
2117 /* The next arg must be the new var. */
2118 } else {
2119 args->joystick_id = atoi( arg );
2120 debug_printf( 1, "setting arg joystick_id to: %d",
2121 args->joystick_id );
2122 }
2123 return MERROR_OK;
2124}
2125
2126# endif /* !RETROFLAT_NO_PAD */
2127
2128#endif /* !RETROFLAT_NO_CLI */
2129
2130/* === */
2131
2132/* Still inside RETROFLT_C! */
2133
2135 int argc, char* argv[], struct RETROFLAT_ARGS* args
2136) {
2137
2138 /* = Declare Init Vars = */
2139
2140 MERROR_RETVAL retval = 0;
2141
2142 /* = Begin Init Procedure = */
2143
2144# ifdef RETROFLAT_COMMIT_HASH
2145 debug_printf( 1, "retroflat commit: " RETROFLAT_COMMIT_HASH );
2146# endif /* RETROFLAT_COMMIT_HASH */
2147
2148 debug_printf( 1, "retroflat: initializing..." );
2149
2150 /* System sanity checks. */
2151 assert( 2 <= sizeof( MERROR_RETVAL ) );
2152 assert( 4 == sizeof( uint32_t ) );
2153 assert( 4 == sizeof( int32_t ) );
2154 assert( 2 == sizeof( uint16_t ) );
2155 assert( 2 == sizeof( int16_t ) );
2156 assert( 1 == sizeof( uint8_t ) );
2157 assert( 1 == sizeof( int8_t ) );
2158 assert( NULL != args );
2159 assert( 1 << RETROFLAT_TILE_W_BITS == RETROFLAT_TILE_W );
2160 assert( 1 << RETROFLAT_TILE_H_BITS == RETROFLAT_TILE_H );
2161
2162 debug_printf( 1, "initializing drawing routines..." );
2163
2164 /* Initialize 2D callbacks depending on if we're in 2D or 3D mode.
2165 * Please see retrom2d.h for more information.
2166 */
2167# if defined( RETROFLAT_BMP_TEX )
2168 retroflat_2d_px = (retroflat_px_cb)retro3d_texture_px;
2169 retroflat_2d_line = (retroflat_line_cb)retrosoft_line;
2170 retroflat_2d_rect = (retroflat_rect_cb)retrosoft_rect;
2171 retroflat_2d_ellipse = (retroflat_ellipse_cb)retrosoft_ellipse;
2172 retroflat_2d_blit_bitmap = (retroflat_blit_bitmap_cb)retro3d_texture_blit;
2173 retroflat_2d_load_bitmap =
2174 (retroflat_load_bitmap_cb)retro3d_texture_load_bitmap;
2175 retroflat_2d_create_bitmap =
2176 (retroflat_create_bitmap_cb)retro3d_texture_create;
2177# else
2178 retroflat_2d_px = (retroflat_px_cb)retroflat_px;
2179# ifdef RETROFLAT_SOFT_SHAPES
2180 /* TODO: Work retrosoft routines to use retroflat_blit_t */
2181 retroflat_2d_line = (retroflat_line_cb)retrosoft_line;
2182 retroflat_2d_rect = (retroflat_rect_cb)retrosoft_rect;
2183 retroflat_2d_ellipse = (retroflat_ellipse_cb)retrosoft_ellipse;
2184# else
2185 retroflat_2d_line = (retroflat_line_cb)retroflat_line;
2186 retroflat_2d_rect = (retroflat_rect_cb)retroflat_rect;
2187 retroflat_2d_ellipse = (retroflat_ellipse_cb)retroflat_ellipse;
2188# endif /* RETROFLAT_SOFT_SHAPES */
2189 retroflat_2d_blit_bitmap = (retroflat_blit_bitmap_cb)retroflat_blit_bitmap;
2190 retroflat_2d_load_bitmap = (retroflat_load_bitmap_cb)retroflat_load_bitmap;
2191 retroflat_2d_create_bitmap =
2192 (retroflat_create_bitmap_cb)retroflat_create_bitmap;
2193# endif /* RETROFLAT_BMP_TEX */
2194
2195 debug_printf( 1, "retroflat: MFIX_PRECISION: %f", MFIX_PRECISION );
2196
2197 debug_printf( 1, "retroflat: allocating state (" SIZE_T_FMT " bytes)...",
2198 sizeof( struct RETROFLAT_STATE ) );
2199
2200 debug_printf( 1, "retroflat: size_t is (" SIZE_T_FMT " bytes)...",
2201 sizeof( size_t ) );
2202
2203 debug_printf( 1, "retroflat: ssize_t is (" SIZE_T_FMT " bytes)...",
2204 sizeof( ssize_t ) );
2205
2206 debug_printf( 1, "retroflat: off_t is (" SIZE_T_FMT " bytes)...",
2207 sizeof( off_t ) );
2208
2209 debug_printf( 1, "initializing global state..." );
2210
2211# ifdef RETROFLAT_STATE_ON_STACK
2212 g_retroflat_state = &g_retroflat_state_stack;
2213# else
2214 maug_malloc_test( g_retroflat_state_h, 1, sizeof( struct RETROFLAT_STATE ) );
2215
2216 maug_mlock( g_retroflat_state_h, g_retroflat_state );
2217 if( NULL == g_retroflat_state ) {
2219 "Error", "Could not lock global state!" );
2220 retval = MERROR_ALLOC;
2221 goto cleanup;
2222 }
2223# endif /* RETROFLAT_STATE_ON_STACK */
2224
2225 maug_mzero( g_retroflat_state, sizeof( struct RETROFLAT_STATE ) );
2226
2227 retroflat_heartbeat_set( 1000, 2 );
2228
2229 debug_printf( 1, "initializing platform filesystem..." );
2230 retval = mfile_plt_init();
2231 maug_cleanup_if_not_ok();
2232
2233# ifndef RETROFLAT_NO_CLI
2234
2235 debug_printf( 1, "retroflat: parsing args..." );
2236
2237 /* All platforms: add command-line args based on compile definitons. */
2238
2239 retval = maug_add_arg(
2240 MAUG_CLI_SIGIL "h", MAUG_CLI_SIGIL_SZ + 2, "Display command-line help",
2241 26, maug_cli_h, NULL );
2242
2243# if !defined( RETROFLAT_NO_SOUND ) && defined( RETROSND_ARGS )
2244 retval = maug_add_arg( MAUG_CLI_SIGIL "rsd", MAUG_CLI_SIGIL_SZ + 4,
2245 "Select MIDI device", 0, (maug_cli_cb)retrosnd_cli_rsd, args );
2246 maug_cleanup_if_not_ok();
2247 retval = maug_add_arg( MAUG_CLI_SIGIL "rsl", MAUG_CLI_SIGIL_SZ + 4,
2248 "List MIDI devices", 0, (maug_cli_cb)retrosnd_cli_rsl, args );
2249 maug_cleanup_if_not_ok();
2250# endif /* !RETROFLAT_NO_SOUND && RETROSND_ARGS */
2251
2252# ifdef RETROFLAT_SCREENSAVER
2253 retval = maug_add_arg( MAUG_CLI_SIGIL "p", MAUG_CLI_SIGIL_SZ + 2,
2254 "Preview screensaver", 0, (maug_cli_cb)retroflat_cli_p, args );
2255 maug_cleanup_if_not_ok();
2256 retval = maug_add_arg( MAUG_CLI_SIGIL "s", MAUG_CLI_SIGIL_SZ + 2,
2257 "Launch screensaver", 0, (maug_cli_cb)retroflat_cli_s, args );
2258 maug_cleanup_if_not_ok();
2259# endif /* RETROFLAT_SCREENSAVER */
2260
2261# ifdef RETROFLAT_API_PC_BIOS
2262 retval = maug_add_arg( MAUG_CLI_SIGIL "rfm", MAUG_CLI_SIGIL_SZ + 4,
2263 "Set the screen mode.", 0,
2264 (maug_cli_cb)retroflat_cli_rfm, args );
2265 maug_cleanup_if_not_ok();
2266# elif !defined( RETROFLAT_NO_CLI_SZ )
2267 retval = maug_add_arg( MAUG_CLI_SIGIL "rfs", MAUG_CLI_SIGIL_SZ + 4,
2268 "Set screen scale factor.", 0,
2269 (maug_cli_cb)retroflat_cli_rfs, args );
2270 maug_cleanup_if_not_ok();
2271 retval = maug_add_arg( MAUG_CLI_SIGIL "rfx", MAUG_CLI_SIGIL_SZ + 4,
2272 "Set the screen X position.", 0,
2273 (maug_cli_cb)retroflat_cli_rfx, args );
2274 maug_cleanup_if_not_ok();
2275 retval = maug_add_arg( MAUG_CLI_SIGIL "rfy", MAUG_CLI_SIGIL_SZ + 4,
2276 "Set the screen Y position.", 0,
2277 (maug_cli_cb)retroflat_cli_rfy, args );
2278 maug_cleanup_if_not_ok();
2279 retval = maug_add_arg( MAUG_CLI_SIGIL "rfw", MAUG_CLI_SIGIL_SZ + 4,
2280 "Set the screen width.", 0,
2281 (maug_cli_cb)retroflat_cli_rfw, args );
2282 maug_cleanup_if_not_ok();
2283 retval = maug_add_arg( MAUG_CLI_SIGIL "rfh", MAUG_CLI_SIGIL_SZ + 4,
2284 "Set the screen height.", 0,
2285 (maug_cli_cb)retroflat_cli_rfh, args );
2286 maug_cleanup_if_not_ok();
2287# endif /* !RETROFLAT_NO_CLI_SZ */
2288
2289# ifdef RETROFLAT_VDP
2290 retval = maug_add_arg( MAUG_CLI_SIGIL "vdp", MAUG_CLI_SIGIL_SZ + 4,
2291 "Pass a string of args to the VDP.", 0,
2292 (maug_cli_cb)retroflat_cli_vdp, args );
2293 maug_cleanup_if_not_ok();
2294# endif /* RETROFLAT_VDP */
2295
2296 retval = maug_add_arg( MAUG_CLI_SIGIL "rfu", MAUG_CLI_SIGIL_SZ + 4,
2297 "Unlock FPS.", 0,
2298 (maug_cli_cb)retroflat_cli_u, args );
2299 maug_cleanup_if_not_ok();
2300
2301# ifndef RETROFLAT_NO_PAD
2302 retval = maug_add_arg( MAUG_CLI_SIGIL "rfj", MAUG_CLI_SIGIL_SZ + 4,
2303 "Specify joystick ID to use.", 0,
2304 (maug_cli_cb)retroflat_cli_rfj, args );
2305 maug_cleanup_if_not_ok();
2306# endif /* !RETROFLAT_NO_PAD */
2307
2308 /* Parse command line args. */
2309 retval = maug_parse_args( argc, argv );
2310 maug_cleanup_if_not_ok();
2311
2312# endif /* !RETROFLAT_NO_CLI */
2313
2314 if( 0 == args->screen_w ) {
2315 args->screen_w = RETROFLAT_DEFAULT_SCREEN_W;
2316 debug_printf( 1, "setting arg screen_w to default: %d",
2317 args->screen_w );
2318 }
2319 if( 0 == args->screen_h ) {
2320 args->screen_h = RETROFLAT_DEFAULT_SCREEN_H;
2321 debug_printf( 1, "setting arg screen_h to default: %d",
2322 args->screen_h );
2323 }
2324 if( 0 == args->screen_scale ) {
2325 args->screen_scale = RETROFLAT_DEFAULT_SCREEN_SCALE;
2326 debug_printf( 1, "setting arg screen_scale to default: %d",
2327 args->screen_scale );
2328 }
2329 if( 0 == args->screen_colors ) {
2330 args->screen_colors = 16;
2331 debug_printf( 1, "setting arg screen_colors to default: %d",
2332 args->screen_colors );
2333 }
2334 args->joystick_id = -1;
2335
2336 if(
2338 ) {
2339 g_retroflat_state->retroflat_flags |= RETROFLAT_STATE_FLAG_UNLOCK_FPS;
2340 }
2341
2342 debug_printf( 1, "retroflat: setting config..." );
2343
2344 /* Set the assets path. */
2345 if( NULL != args->assets_path ) {
2346 maug_mzero( g_retroflat_state->assets_path, MAUG_PATH_SZ_MAX );
2347 maug_strncpy( g_retroflat_state->assets_path,
2348 args->assets_path, MAUG_PATH_SZ_MAX - 1 );
2349 }
2350
2351# if defined( RETROFLAT_SCREENSAVER )
2352 if(
2354 (RETROFLAT_STATE_FLAG_SCREENSAVER & args->flags)
2355 ) {
2356 g_retroflat_state->retroflat_flags |= RETROFLAT_STATE_FLAG_SCREENSAVER;
2357 }
2358# endif /* RETROFLAT_SCREENSAVER */
2359
2360# if !defined( RETROFLAT_NO_CLI_SZ )
2361 /* Setup intended screen size. */
2362 g_retroflat_state->screen_scale = args->screen_scale;
2363 g_retroflat_state->screen_v_w = args->screen_w;
2364 g_retroflat_state->screen_v_h = args->screen_h;
2365 g_retroflat_state->screen_w = args->screen_w *
2366 g_retroflat_state->screen_scale;
2367 g_retroflat_state->screen_h = args->screen_h *
2368 g_retroflat_state->screen_scale;
2369 g_retroflat_state->screen_colors = args->screen_colors;
2370
2371 debug_printf( 3, "attempting to initialize platform with: "
2372 SIZE_T_FMT "x" SIZE_T_FMT " pixels (scaled to " SIZE_T_FMT "x" SIZE_T_FMT
2373 ") and " SIZE_T_FMT " colors",
2374 g_retroflat_state->screen_v_w, g_retroflat_state->screen_v_h,
2375 g_retroflat_state->screen_w, g_retroflat_state->screen_h,
2376 g_retroflat_state->screen_colors );
2377# endif /* !RETROFLAT_NO_CLI_SZ */
2378
2379 /* == Platform-Specific Init == */
2380
2381 retval = retroflat_init_platform( argc, argv, args );
2382 maug_cleanup_if_not_ok();
2383
2384# if defined( RETROFLAT_NO_CLI_SZ )
2385 g_retroflat_state->screen_scale = args->screen_scale;
2386 g_retroflat_state->screen_v_w = args->screen_w;
2387 g_retroflat_state->screen_v_h = args->screen_h;
2388 g_retroflat_state->screen_w = args->screen_w *
2389 g_retroflat_state->screen_scale;
2390 g_retroflat_state->screen_h = args->screen_h *
2391 g_retroflat_state->screen_scale;
2392 g_retroflat_state->screen_colors = args->screen_colors;
2393
2394 debug_printf( 3, "initialized platform with: "
2395 SIZE_T_FMT "x" SIZE_T_FMT " pixels (scaled to " SIZE_T_FMT "x" SIZE_T_FMT
2396 ") and " SIZE_T_FMT " colors",
2397 g_retroflat_state->screen_v_w, g_retroflat_state->screen_v_h,
2398 g_retroflat_state->screen_w, g_retroflat_state->screen_h,
2399 g_retroflat_state->screen_colors );
2400# endif /* RETROFLAT_NO_CLI_SZ */
2401
2402 retval = retroflat_init_input( args );
2403 maug_cleanup_if_not_ok();
2404
2405 debug_printf( 3, "screen initialized with: " SIZE_T_FMT "x" SIZE_T_FMT
2406 " pixels (scaled to " SIZE_T_FMT "x" SIZE_T_FMT
2407 ") with " SIZE_T_FMT " colors",
2408 g_retroflat_state->screen_v_w, g_retroflat_state->screen_v_h,
2409 g_retroflat_state->screen_w, g_retroflat_state->screen_h,
2411
2412 /* Setup the refresh grid, if requested, only after screen space has been
2413 * determined by the platform!
2414 */
2415 maug_cleanup_if_eq(
2416 (size_t)0, retroflat_screen_w(), SIZE_T_FMT, MERROR_GUI );
2417 maug_cleanup_if_eq(
2418 (size_t)0, retroflat_screen_h(), SIZE_T_FMT, MERROR_GUI );
2419 maug_cleanup_if_eq(
2420 (size_t)0, retroflat_screen_colors(), SIZE_T_FMT, MERROR_GUI );
2421
2422 debug_printf( 3, "setting up viewport for %d x %d screen...",
2423 retroflat_screen_w(), retroflat_screen_h() );
2424
2425 /* This is intended as a default and can be modified by calling this macro
2426 * again later.
2427 */
2428 retroflat_viewport_set_pos_size(
2429 0, 0, retroflat_screen_w(), retroflat_screen_h() );
2430
2431# ifdef RETROFLAT_VDP
2432# if defined( RETROFLAT_OS_UNIX )
2433 g_retroflat_state->vdp_exe = dlopen(
2434 "./" RETROFLAT_VDP_LIB_NAME ".so", RTLD_LAZY );
2435# elif defined( RETROFLAT_OS_WIN )
2436 g_retroflat_state->vdp_exe = LoadLibrary(
2437 "./" RETROFLAT_VDP_LIB_NAME ".dll" );
2438# else
2439# error "dlopen undefined!"
2440# endif /* RETROFLAT_OS_UNIX */
2441
2442 if( !(g_retroflat_state->vdp_exe) ) {
2443 error_printf( "not loading VDP" );
2444 /* Skip creating the buffer or trying to run the init proc. */
2445 goto skip_vdp;
2446 }
2447
2448 debug_printf( 1, "initializing VDP..." );
2449 retval = retroflat_vdp_call( "retroflat_vdp_init" );
2450 maug_cleanup_if_not_ok();
2451
2452skip_vdp:
2453
2454# endif /* RETROFLAT_VDP */
2455
2456# ifdef RETROFLAT_3D
2457 retro3d_platform_init();
2458# endif /* RETROFLAT_3D */
2459
2460# if !defined( RETROFLAT_NO_BLANK_INIT ) && !defined( RETROFLAT_3D )
2461 retroflat_draw_lock( NULL );
2463 NULL, RETROFLAT_COLOR_BLACK, 0, 0,
2464 retroflat_screen_w(), retroflat_screen_h(),
2466 retroflat_draw_release( NULL );
2467# endif /* !RETROFLAT_NO_BLANK_INIT */
2468
2469cleanup:
2470
2471 return retval;
2472}
2473
2474/* === */
2475
2476void retroflat_shutdown( int retval ) {
2477
2478 debug_printf( 1, "retroflat shutdown called..." );
2479
2480#ifndef RETROFLAT_NO_VIEWPORT_REFRESH
2481 if(
2482 NULL != g_retroflat_state &&
2483 (MAUG_MHANDLE)NULL != g_retroflat_state->viewport.refresh_grid_h
2484 ) {
2485 maug_mfree( g_retroflat_state->viewport.refresh_grid_h );
2486 }
2487#endif /* !RETROFLAT_NO_VIEWPORT_REFRESH */
2488
2489# if defined( RETROFLAT_VDP )
2490 if( NULL != g_retroflat_state->vdp_exe ) {
2491 retroflat_vdp_call( "retroflat_vdp_shutdown" );
2492# ifdef RETROFLAT_OS_UNIX
2493 dlclose( g_retroflat_state->vdp_exe );
2494# elif defined( RETROFLAT_OS_WIN )
2495 FreeLibrary( g_retroflat_state->vdp_exe );
2496# else
2497# error "dlclose undefined!"
2498# endif /* RETROFLAT_OS_UNIX || RETROFLAT_OS_WIN */
2499 }
2500# endif /* RETROFLAT_VDP */
2501
2502 /* === Platform-Specific Shutdown === */
2503
2504#ifdef RETROFLAT_3D
2505 retro3d_platform_shutdown();
2506#endif /* RETROFLAT_3D */
2507
2508 retroflat_shutdown_platform( retval );
2509
2510#ifndef RETROFLAT_STATE_ON_STACK
2511 maug_munlock( g_retroflat_state_h, g_retroflat_state );
2512 maug_mfree( g_retroflat_state_h );
2513#endif /* !RETROFLAT_STATE_ON_STACK */
2514
2515}
2516
2517/* === */
2518
2519RETROFLAT_IN_KEY retroflat_repeat_input(
2520 RETROFLAT_IN_KEY key_out, struct RETROFLAT_INPUT* input,
2521 RETROFLAT_IN_KEY* prev_input, int* prev_delay
2522) {
2523
2524 /* Add a slight debounce for gamepad button repeat. */
2525 if( 0 < (*prev_delay) ) {
2526 debug_printf(
2527 RETROINPUT_TRACE_LVL,
2528 "repeat delay: %d", (*prev_delay) );
2529 (*prev_delay)--;
2530 }
2531
2532 /* If nothing else happened and repeat is enabled and a joypad button is
2533 * down, then emulate repeat for it.
2534 */
2535 if(
2536 0 == key_out &&
2538 (RETROFLAT_STATE_FLAG_KEY_REPEAT & g_retroflat_state->retroflat_flags) &&
2539 /* There is an input to repeat. */
2540 0 != *prev_input &&
2541 /* Delay countdown reached. */
2542 0 == *prev_delay
2543 ) {
2544 key_out = *prev_input;
2545 *prev_delay = 1;
2546 debug_printf( RETROINPUT_TRACE_LVL, "repeat: %d", key_out );
2547 }
2548
2549 return key_out;
2550}
2551
2552/* === */
2553
2554ssize_t retroflat_timer_add(
2555 retroflat_ms_t at_time, retroflat_timer_cb_t cb, void* data
2556) {
2557 if( retroflat_get_ms() > at_time ) {
2558 error_printf( "timer time is in the past!" );
2559 return merror_retval_to_sz( MERROR_EXEC );
2560 }
2561
2562 if( g_retroflat_state->timers_ct + 1 < RETROFLAT_TIMER_CT_MAX ) {
2563 g_retroflat_state->timers_cb[g_retroflat_state->timers_ct] = cb;
2564 g_retroflat_state->timers_at[g_retroflat_state->timers_ct] = at_time;
2565 g_retroflat_state->timers_ct++;
2566 return g_retroflat_state->timers_ct - 1;
2567 }
2568
2569 error_printf( "too many timers!" );
2570 return merror_retval_to_sz( MERROR_OVERFLOW );
2571}
2572
2573/* === */
2574
2576 size_t i = 0;
2577 retroflat_ms_t time_now = 0;
2578
2579 time_now = retroflat_get_ms();
2580
2581 for( i = 0 ; g_retroflat_state->timers_ct > i ; i++ ) {
2582 if( g_retroflat_state->timers_at[i] <= time_now ) {
2583 g_retroflat_state->timers_cb[i](
2584 time_now, g_retroflat_state->timers_data[i] );
2585 memmove(
2586 &(g_retroflat_state->timers_cb[i]),
2587 &(g_retroflat_state->timers_cb[i + 1]),
2588 sizeof( retroflat_timer_cb_t ) *
2589 ((g_retroflat_state->timers_ct - i) - 1)
2590 );
2591 memmove(
2592 &(g_retroflat_state->timers_at[i]),
2593 &(g_retroflat_state->timers_at[i + 1]),
2594 sizeof( retroflat_ms_t ) * ((g_retroflat_state->timers_ct - i) - 1)
2595 );
2596 memmove(
2597 &(g_retroflat_state->timers_data[i]),
2598 &(g_retroflat_state->timers_data[i + 1]),
2599 sizeof( void* ) * ((g_retroflat_state->timers_ct - i) - 1)
2600 );
2601 g_retroflat_state->timers_ct--;
2602 i--;
2603 }
2604 }
2605}
2606
2607/* === */
2608
2609# ifdef RETROFLAT_VDP
2610
2611MERROR_RETVAL retroflat_vdp_call( const char* proc_name ) {
2612 MERROR_RETVAL retval = MERROR_OK;
2614# ifdef RETROFLAT_OS_WIN
2615 char proc_name_ex[256];
2616# endif /* RETROFLAT_OS_WIN */
2617
2618 if( NULL == g_retroflat_state->vdp_exe ) {
2619 goto cleanup;
2620 }
2621
2622# ifdef RETROFLAT_OS_UNIX
2623 vdp_proc = dlsym( g_retroflat_state->vdp_exe, proc_name );
2624# elif defined( RETROFLAT_OS_WIN )
2625 /* Append a _ to the proc_name because Watcom? Windows? */
2626 maug_snprintf( proc_name_ex, 255, "%s_", proc_name );
2627 vdp_proc = (retroflat_vdp_proc_t)GetProcAddress(
2628 g_retroflat_state->vdp_exe, proc_name_ex );
2629# else
2630# error "dlsym undefined!"
2631# endif
2632 if( (retroflat_vdp_proc_t)NULL == vdp_proc ) {
2633 goto cleanup;
2634 }
2635
2636# ifdef RETROFLAT_OS_WIN
2637 retroflat_draw_lock( g_retroflat_state->vdp_buffer_in );
2638# endif /* RETROFLAT_OS_WIN */
2639
2640 if(
2641 /* Don't pxlock before init can set the flag! */
2642 0 == strcmp( "retroflat_vdp_flip", proc_name ) &&
2644 (RETROFLAT_VDP_FLAG_PXLOCK & g_retroflat_state->vdp_flags)
2645 ) {
2646 retroflat_vdp_lock( g_retroflat_state->vdp_buffer_in );
2647 retroflat_vdp_lock( g_retroflat_state->vdp_buffer_out );
2648 }
2649
2650 retval = vdp_proc( g_retroflat_state );
2651
2652 if(
2653 0 == strcmp( "retroflat_vdp_flip", proc_name ) &&
2655 (RETROFLAT_VDP_FLAG_PXLOCK & g_retroflat_state->vdp_flags)
2656 ) {
2657 retroflat_vdp_release( g_retroflat_state->vdp_buffer_out );
2658 retroflat_vdp_release( g_retroflat_state->vdp_buffer_in );
2659 }
2660
2661# ifdef RETROFLAT_OS_WIN
2662 retroflat_draw_release( g_retroflat_state->vdp_buffer_in );
2663# endif /* RETROFLAT_OS_WIN */
2664
2665cleanup:
2666 return retval;
2667}
2668
2669# endif /* RETROFLAT_VDP */
2670
2671/* === */
2672
2673#if 0
2674
2675void retroflat_cursor( struct RETROFLAT_BITMAP* target, uint8_t flags ) {
2676#if 0
2677 char mouse_str[11] = "";
2678
2679 maug_snprintf(
2680 mouse_str, 10, "%02d, %02d", g_retroflat_state->last_mouse_x, g_retroflat_state->last_mouse_y );
2681
2683 target, RETROFLAT_COLOR_BLACK,
2684 mouse_str, 10, NULL, 0, 0, 0 );
2686 target, RETROFLAT_COLOR_BLACK,
2687 g_retroflat_state->last_mouse_x - 5, g_retroflat_state->last_mouse_y - 5, 10, 10, 0 );
2688#endif
2689}
2690
2691#endif
2692
2693/* === */
2694
2695void maug_critical_error( const char* msg ) {
2697}
2698
2699/* === */
2700
2702 retroflat_proc_resize_t on_resize_in, void* data_in
2703) {
2704 g_retroflat_state->on_resize = on_resize_in;
2705 g_retroflat_state->on_resize_data = data_in;
2706}
2707
2708/* === */
2709
2711 retroflat_proc_focus_t on_focus_in, void* data_in
2712) {
2713 g_retroflat_state->on_focus = on_focus_in;
2714 g_retroflat_state->on_focus_data = data_in;
2715}
2716
2717/* === */
2718
2720 retroflat_proc_quit_t on_quit_in, void* data_in
2721) {
2722 g_retroflat_state->on_quit = on_quit_in;
2723 g_retroflat_state->on_quit_data = data_in;
2724}
2725
2726/* === */
2727
2728#ifdef RETROFLAT_LOAD_BITMAP_GENERIC
2729
2730/* This is a generic function that uses the callback
2731 * retroflat_load_bitmap_px_cb(), which should be defined by the
2732 * platform-specific API to draw the loaded bitmap onto a native canvas.
2733 */
2734
2736 const char* filename, struct RETROFLAT_BITMAP* bmp_out, uint8_t flags
2737) {
2738 maug_path filename_path;
2739 MERROR_RETVAL retval = MERROR_OK;
2740 mfile_t bmp_file;
2741 struct MFMT_STRUCT_BMPFILE header_bmp;
2742 uint8_t bmp_flags = 0;
2743
2744 assert( NULL != bmp_out );
2745 maug_mzero( bmp_out, sizeof( struct RETROFLAT_BITMAP ) );
2746 retval = retroflat_build_filename_path(
2747 filename, RETROFLAT_BITMAP_EXT, filename_path,
2748 MAUG_PATH_SZ_MAX, flags );
2749 maug_cleanup_if_not_ok();
2750 debug_printf( 1, "retroflat: loading bitmap: %s", filename_path );
2751
2752 bmp_out->flags = flags;
2753
2754 /* Open the bitmap file. */
2755 retval = mfile_open_read( filename_path, &bmp_file );
2756 maug_cleanup_if_not_ok();
2757
2758 /* mfmt file detection system. */
2759 maug_mzero( &header_bmp, sizeof( struct MFMT_STRUCT_BMPFILE ) );
2760 header_bmp.magic[0] = 'B';
2761 header_bmp.magic[1] = 'M';
2762 header_bmp.info.sz = 40;
2763
2764 retval = mfmt_read_bmp_header(
2765 (struct MFMT_STRUCT*)&header_bmp,
2766 &bmp_file, 0, mfile_get_sz( &bmp_file ), &bmp_flags );
2767 maug_cleanup_if_not_ok();
2768
2769 retval = retroflat_create_bitmap(
2770 header_bmp.info.width, header_bmp.info.height, bmp_out, flags );
2771 maug_cleanup_if_not_ok();
2772
2773 retroflat_draw_lock( bmp_out );
2774
2775 retval = mfmt_read_bmp_px_cb(
2776 (struct MFMT_STRUCT*)&header_bmp,
2777 &bmp_file,
2778 header_bmp.px_offset,
2779 mfile_get_sz( &bmp_file ) - header_bmp.px_offset,
2780 bmp_flags,
2781 retroflat_load_bitmap_px_cb,
2782 bmp_out );
2783 maug_cleanup_if_not_ok();
2784
2785 retroflat_draw_release( bmp_out );
2786
2787cleanup:
2788
2789 mfile_close( &bmp_file );
2790
2791 return retval;
2792}
2793
2794#endif /* RETROFLAT_LOAD_BITMAP_GENERIC */
2795
2796#elif !defined( RETROVDP_C ) /* End of RETROFLT_C */
2797
2802
2803extern MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets8_x[8];
2804extern MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets8_y[8];
2805extern MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets4_x[4];
2806extern MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets4_y[4];
2807
2809
2810#define RETROFLAT_COLOR_TABLE_CONSTS( idx, name_l, name_u, r, g, b, cgac, cgad ) \
2811 extern MAUG_CONST RETROFLAT_COLOR SEG_MCONST RETROFLAT_COLOR_ ## name_u;
2812
2813RETROFLAT_COLOR_TABLE( RETROFLAT_COLOR_TABLE_CONSTS )
2814
2815extern MAUG_CONST char* SEG_MCONST gc_retroflat_color_names[];
2816
2817extern struct RETROFLAT_STATE* SEG_MGLOBAL g_retroflat_state;
2818
2819# if (defined( RETROFLAT_SOFT_SHAPES ) || defined( RETROFLAT_SOFT_LINES ) || \
2820 defined( RETROFLAT_3D ))
2821# define RETROSOFT_PRESENT
2822# endif
2823
2824# ifdef RETROFLAT_3D
2825# include <retro3dp.h>
2826# include <retro3d.h>
2827# include <retro3du.h>
2828# endif /* RETROFLAT_3D */
2829
2830# ifdef RETROSOFT_PRESENT
2831# include <retrosft.h>
2832# endif /* RETROFLAT_SOFT_SHAPES */
2833
2834/* Second retapis.h include for function bodies not needed. */
2835
2836/* Second retapii.h include for function bodies not needed. */
2837
2838#endif /* RETROFLT_C */
2839
2840#ifdef RETROFLAT_XPM
2841#include <retroxpm.h>
2842#endif /* RETROFLAT_XPM */
2843
2844#ifdef RETROVDP_C
2845
2846/* Declarations for VDP sources. */
2847
2848#endif /* RETROVDP_C */
2849 /* maug_retroflt */
2851
2852#endif /* RETROFLT_H */
2853
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:41
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:141
#define RETROFLAT_BITMAP_EXT
The filename suffix to be appended with a "." to filenames passed to retroflat_load_bitmap()....
Definition retroflt.h:634
#define RETROFLAT_BITMAP_FLAG_LITERAL_PATH
Flag for retroflat_load_bitmap() to not use assets path.
Definition retroflt.h:585
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 th...
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 th...
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:326
#define RETROFLAT_COLOR_TABLE(f)
This macro defines all colors supported by RetroFlat for primative operations, particularly using ret...
Definition retroflt.h:307
#define RETROFLAT_VDP_ARGS_SZ_MAX
Definition retroflt.h:779
#define RETROFLAT_PATH_SEP
The valid path separator on the target platform.
Definition retroflt.h:800
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:374
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_string(struct RETROFLAT_BITMAP *target, const RETROFLAT_COLOR color, const char *str, int str_sz, const char *font_str, retroflat_pxxy_t x_orig, retroflat_pxxy_t y_orig, uint8_t flags)
Draw a text string at the specified location in the specified font and color on the target RETROFLAT_...
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.
void retroflat_string_sz(struct RETROFLAT_BITMAP *target, const char *str, size_t str_sz, const char *font_str, retroflat_pxxy_t *w_out, retroflat_pxxy_t *h_out, uint8_t flags)
Get the size in pixels of a text string when drawn with a given font by retroflat_string().
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:461
void retroflat_timer_handle()
This should be called in the API HAL on every iteration of the main loop (this is done automatically ...
void retroflat_resize_v()
Platform-specific function to resize virtual screen to match physical window size.
uint8_t retroflat_focus_platform()
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:537
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:513
#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:500
#define retroflat_heartbeat_update()
Check and update RETROFLAT_STATE::heartbeat_frame.
Definition retroflt.h:1114
void retroflat_shutdown(int retval)
Deinitialize RetroFlat and its underlying layers. This should be called once at the end of the progra...
#define RETROFLAT_STATE_FLAG_KEY_REPEAT
Flag indicating keyboard repeat is enabled.
Definition retroflt.h:413
#define retroflat_screen_colors()
Get the number of available on-screen colors.
Definition retroflt.h:1089
#define RETROFLAT_STATE_FLAG_SCREENSAVER
Flag indicating the current application is running as a screensaver.
Definition retroflt.h:420
int16_t retroflat_pxxy_t
Type used for surface pixel coordinates.
Definition retroflt.h:931
#define RETROFLAT_STATE_FLAG_WAIT_FOR_FPS
Do not execute any more inter-frame loops until next frame.
Definition retroflt.h:431
#define RETROFLAT_STATE_FLAG_RUNNING
Flag indicating that retroflat_loop() should continue executing.
Definition retroflt.h:399
#define retroflat_heartbeat_set(len, max)
Set parameters for the RETROFLAT_STATE::heartbeat_frame.
Definition retroflt.h:1097
#define retroflat_system_task()
Platform-specific task that should be called on every iteration of the generic loop....
Definition retroflt.h:1029
void(* retroflat_loop_iter)(void *data)
Prototype for the main loop function passed to retroflat_loop().
Definition retroflt.h:823
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...
#define RETROFLAT_STATE_FLAG_UNLOCK_FPS
Flag indicating FPS should not be capped.
Definition retroflt.h:406
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 mfmt.h:124
Generic image description struct.
Definition mfmt.h:69
Definition retroflt.h:1006
Struct containing configuration values for a RetroFlat program.
Definition retroflt.h:1041
char * config_path
Relative path of local config file (if not using registry).
Definition retroflt.h:1051
char * assets_path
Relative path under which bitmap assets are stored.
Definition retroflt.h:1049
int screen_w
Desired screen or window width in pixels.
Definition retroflt.h:1058
int screen_h
Desired screen or window height in pixels.
Definition retroflt.h:1065
int screen_colors
Desired colors (2, 4, or 16, for now). \TODO Implement command-line argument for this....
Definition retroflt.h:1077
char * title
Title to set for the main program Window if applicable on the target platform.
Definition retroflt.h:1047
int screen_y
Desired window Y position in pixels.
Definition retroflt.h:1069
int screen_x
Desired window X position in pixels.
Definition retroflt.h:1067
Struct passed to retroflat_poll_input() to hold return data.
Definition retroflt.h:875
int mouse_y
Y-coordinate of the mouse pointer in pixels if the returned event is a mouse click.
Definition retroflt.h:885
int mouse_x
X-coordinate of the mouse pointer in pixels if the returned event is a mouse click.
Definition retroflt.h:880
Global singleton containing state for the current platform.
Definition retroflt.h:1136
size_t screen_h
The screen height as seen by the system, after scaling.
Definition retroflt.h:1204
uint8_t vdp_flags
Flags set by the RetroFlat VDP API.
Definition retroflt.h:1180
size_t screen_v_w
The screen width as seen by our program, before scaling.
Definition retroflt.h:1193
size_t screen_colors
The number of colors the screen is capable of displaying.
Definition retroflt.h:1206
RETROFLAT_COLOR_DEF palette[RETROFLAT_COLORS_CT_MAX]
Index of available colors, initialized on platform init.
Definition retroflt.h:1251
uint8_t retroflat_flags
maug_retroflt_flags indicating current system status.
Definition retroflt.h:1146
uint8_t heartbeat_max
When RETROFLAT_STATE::heartbeat_frame reaches this value, it will reset to 0.
Definition retroflt.h:1233
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:1273
uint8_t heartbeat_frame
Simple iteration loop that can be used to time e.g. perpetual sprite animations. Modify parameters wi...
Definition retroflt.h:1228
size_t screen_w
The screen width as seen by the system, after scaling.
Definition retroflt.h:1202
void * vdp_exe
A handle for the loaded RetroFlat VDP API module.
Definition retroflt.h:1170
uint8_t last_focus_flags
Used internally to track whether to call on_focus().
Definition retroflt.h:1243
uint16_t heartbeat_len
Number of ms to stay on current value of RETROFLAT_STATE::heartbeat_frame before incrementing....
Definition retroflt.h:1222
void * vdp_data
Pointer to data defined by the RetroFlat VDP API for its use.
Definition retroflt.h:1176
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:1164
size_t screen_v_h
The screen height as seen by our program, before scaling.
Definition retroflt.h:1200
int screen_scale
Off-screen buffer bitmap.
Definition retroflt.h:1153
retroflat_proc_quit_t on_quit
Should be set with retroflat_set_proc_focus().
Definition retroflt.h:1246
char vdp_args[RETROFLAT_VDP_ARGS_SZ_MAX+1]
CLI args passed with -vdp to the RetroFlat VDP API.
Definition retroflt.h:1178
retroflat_proc_focus_t on_focus
Should be set with retroflat_set_proc_focus().
Definition retroflt.h:1240
retroflat_proc_resize_t on_resize
Should be set with retroflat_set_proc_resize().
Definition retroflt.h:1236
The viewport data struct. There is generally only one of these, to which all helpers implicitly refer...
Definition retroviw.h:48