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
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
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_SZ 16
331
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
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
374#define RETROFLAT_FLAGS_FILL 0x01
375
380#define RETROFLAT_FLAGS_OPAQUE 0x01
381
385#define RETROFLAT_FLAGS_LITERAL_PATH 0x02
386
391#define RETROFLAT_FLAGS_BITMAP_SILENT 0x04
392
399#define RETROFLAT_FLAGS_ALL_CAPS 0x02
400
407#define RETROFLAT_FLAGS_SCREEN_BUFFER 0x80
408 /* maug_retroflt_drawing */
410
417#define RETROFLAT_FLAGS_RUNNING 0x01
418
424#define RETROFLAT_FLAGS_UNLOCK_FPS 0x02
425
431#define RETROFLAT_FLAGS_KEY_REPEAT 0x04
432
438#define RETROFLAT_FLAGS_SCREENSAVER 0x08
439
444#define RETROFLAT_FLAGS_WAIT_FOR_FPS 0x20
445
456#define RETROFLAT_MSG_FLAG_TYPE_MASK 0x07
457
462#define RETROFLAT_MSG_FLAG_ERROR 0x01
463
469#define RETROFLAT_MSG_FLAG_INFO 0x02
470
476#define RETROFLAT_MSG_FLAG_WARNING 0x04
477 /* maug_retroflt_msg_api */
479
480struct RETROFLAT_STATE;
481
501#define RETROFLAT_VDP_FLAG_PXLOCK 0x01
502
515 /* maug_retroflt_vdp */
517
518typedef MERROR_RETVAL (*retroflat_proc_resize_t)(
519 uint16_t new_w, uint16_t new_h, void* data );
520
526#define RETROSND_ARGS_FLAG_LIST_DEVS 0x01
527
559#define RETROFLAT_FLAGS_LOCK 0x08
560
561#define RETROFLAT_FLAGS_SCREEN_LOCK 0x02
562
563#define RETROFLAT_FLAGS_BITMAP_RO 0x04
564
570#define RETROFLAT_INSTANCE_NULL (0)
571
576#define retroflat_instance_tile( instance ) \
577 (instance * -1)
578
583#ifndef RETROFLAT_BITMAP_EXT
584# define RETROFLAT_BITMAP_EXT "bmp"
585#endif /* !RETROFLAT_BITMAP_EXT */
586
587#ifndef RETROFLAT_OPENGL_BPP
588# define RETROFLAT_OPENGL_BPP 32
589#endif /* !RETROFLAT_OPENGL_BPP */
590
591#ifndef RETROFLAT_TILE_W
592# define RETROFLAT_TILE_W 16
593#endif /* !RETROFLAT_TILE_W */
594
595#ifndef RETROFLAT_TILE_W_BITS
596# define RETROFLAT_TILE_W_BITS 4
597#endif /* !RETROFLAT_TILE_W_BITS */
598
599#ifndef RETROFLAT_TILE_H
600# define RETROFLAT_TILE_H 16
601#endif /* !RETROFLAT_TILE_H */
602
603#ifndef RETROFLAT_TILE_H_BITS
604# define RETROFLAT_TILE_H_BITS 4
605#endif /* !RETROFLAT_TILE_H_BITS */
606
607/* Transparency background color: black by default, to match Allegro. */
608#ifndef RETROFLAT_TXP_R
614# define RETROFLAT_TXP_R 0x00
615#endif /* !RETROFLAT_TXP_R */
616
617#ifndef RETROFLAT_TXP_G
623# define RETROFLAT_TXP_G 0x00
624#endif /* !RETROFLAT_TXP_G */
625
626#ifndef RETROFLAT_TXP_B
632# define RETROFLAT_TXP_B 0x00
633#endif /* !RETROFLAT_TXP_B */
634
635#ifndef RETROFLAT_TXP_PAL_IDX
636# define RETROFLAT_TXP_PAL_IDX 0
637#endif /* !RETROFLAT_TXP_PAL_IDX */
638 /* maug_retroflt_bitmap */
640
641#ifndef RETROFLAT_DEFAULT_SCREEN_W
642# define RETROFLAT_DEFAULT_SCREEN_W 320
643#endif /* !RETROFLAT_DEFAULT_SCREEN_W */
644
645#ifndef RETROFLAT_DEFAULT_SCREEN_H
646# define RETROFLAT_DEFAULT_SCREEN_H 200
647#endif /* !RETROFLAT_DEFAULT_SCREEN_H */
648
649#ifndef RETROFLAT_DEFAULT_SCREEN_SCALE
650# define RETROFLAT_DEFAULT_SCREEN_SCALE 1
651#endif /* !RETROFLAT_DEFAULT_SCREEN_SCALE */
652
653#define retroflat_on_resize( w, h ) \
654 g_retroflat_state->screen_w = w; \
655 g_retroflat_state->screen_h = h;
656
662#ifndef RETROFLAT_LINE_THICKNESS
667# define RETROFLAT_LINE_THICKNESS 1
668#endif /* !RETROFLAT_LINE_THICKNESS */
669
670#define RETROFLAT_PI 3.14159
671 /* maug_retroflt_drawing */
673
679#ifndef RETROFLAT_FPS
684# define RETROFLAT_FPS 30
685#endif /* !RETROFLAT_FPS */
686
687#define retroflat_fps_next() (1000 / RETROFLAT_FPS)
688
689#ifndef RETROFLAT_WINDOW_CLASS
694# define RETROFLAT_WINDOW_CLASS "RetroFlatWindowClass"
695#endif /* !RETROFLAT_WINDOW_CLASS */
696
697#ifndef RETROFLAT_WIN_FRAME_TIMER_ID
702# define RETROFLAT_WIN_FRAME_TIMER_ID 6001
703#endif /* !RETROFLAT_WIN_FRAME_TIMER_ID */
704
705#ifndef RETROFLAT_WIN_LOOP_TIMER_ID
710# define RETROFLAT_WIN_LOOP_TIMER_ID 6002
711#endif /* !RETROFLAT_WIN_LOOP_TIMER_ID */
712
713#ifndef RETROFLAT_MSG_MAX
718# define RETROFLAT_MSG_MAX 4096
719#endif /* !RETROFLAT_MSG_MAX */
720
721#ifndef RETROFLAT_TITLE_MAX
722# define RETROFLAT_TITLE_MAX 255
723#endif /* !RETROFLAT_TITLE_MAX */
724
725#ifndef RETROFLAT_VDP_ARGS_SZ_MAX
729# define RETROFLAT_VDP_ARGS_SZ_MAX 255
730#endif /* !RETROFLAT_VDP_ARGS_SZ_MAX */
731
732#if defined( RETROFLAT_API_SDL2 )
733# if !defined( NO_RETROFLAT_RESIZABLE )
734# define RETROFLAT_WIN_FLAGS SDL_WINDOW_RESIZABLE
735# else
736# define RETROFLAT_WIN_FLAGS 0
737# endif /* !NO_RETROFLAT_RESIZABLE */
738#endif /* RETROFLAT_API_SDL2 */
739
740#if defined( RETROFLAT_API_SDL1 )
741# define RETROFLAT_SDL_CC_FLAGS (SDL_RLEACCEL | SDL_SRCCOLORKEY)
742#elif defined( RETROFLAT_API_SDL2 )
743# define RETROFLAT_SDL_CC_FLAGS (SDL_TRUE)
744#endif /* RETROFLAT_API_SDL1 || RETROFLAT_API_SDL2 */
745
746#ifdef RETROFLAT_OS_DOS
747# define RETROFLAT_PATH_SEP '\\'
748#else
750# define RETROFLAT_PATH_SEP '/'
751#endif /* RETROFLAT_OS_DOS */
752
753#ifndef RETROFLAT_BMP_COLORS_SZ_MAX
754# define RETROFLAT_BMP_COLORS_SZ_MAX 256
755#endif /* !RETROFLAT_BMP_COLORS_SZ_MAX */
756
757#ifndef RETROFLAT_TIMER_CT_MAX
758# define RETROFLAT_TIMER_CT_MAX 10
759#endif /* !RETROFLAT_TIMER_CT_MAX */
760 /* maug_retroflt_compiling */
762
763#define retroflat_wait_for_frame() \
764 (g_retroflat_state->retroflat_flags |= RETROFLAT_FLAGS_WAIT_FOR_FPS)
765
766#define retroflat_is_waiting_for_frame() \
767 (RETROFLAT_FLAGS_WAIT_FOR_FPS == \
768 (g_retroflat_state->retroflat_flags & RETROFLAT_FLAGS_WAIT_FOR_FPS))
769
773typedef void (*retroflat_loop_iter)(void* data);
774
784#define retroflat_buffer_bksp( buffer, buffer_cur, buffer_sz ) \
785 if( 0 < buffer_cur ) { \
786 if( buffer_cur < buffer_sz ) { \
787 memmove( \
788 &(buffer[(buffer_cur) - 1]), \
789 &(buffer[buffer_cur]), \
790 (buffer_sz) - (buffer_cur) ); \
791 } \
792 buffer_cur--; \
793 buffer_sz--; \
794 buffer[buffer_sz] = '\0'; \
795 }
796
800#define retroflat_buffer_insert( c, buffer, buffer_cur, buffer_sz, buffer_mx ) \
801 if( buffer_sz + 1 < buffer_mx ) { \
802 if( buffer_cur < buffer_sz ) { \
803 memmove( \
804 &(buffer[(buffer_cur) + 1]), \
805 &(buffer[buffer_cur]), \
806 (buffer_sz) - (buffer_cur) ); \
807 } \
808 buffer[buffer_cur] = c; \
809 buffer_cur++; \
810 buffer_sz++; \
811 buffer[buffer_sz] = '\0'; \
812 }
813
814#define RETROFLAT_INPUT_MOD_SHIFT 0x01
815
816#define RETROFLAT_INPUT_MOD_ALT 0x02
817
818#define RETROFLAT_INPUT_MOD_CTRL 0x04
819
820#define RETROFLAT_INPUT_FORCE_UPPER 0x08
821
834 uint8_t key_flags;
835};
836 /* maug_retroflt_input */
838
846typedef int8_t retroflat_dir4_t;
847
848typedef int8_t retroflat_dir8_t;
849
850#define RETROFLAT_DIR4_NONE (-1)
851#define RETROFLAT_DIR4_NORTH 0
852#define RETROFLAT_DIR4_EAST 1
853#define RETROFLAT_DIR4_SOUTH 2
854#define RETROFLAT_DIR4_WEST 3
855
856#define RETROFLAT_DIR8_NONE (-1)
857#define RETROFLAT_DIR8_NORTH 0
858#define RETROFLAT_DIR8_EAST 2
859#define RETROFLAT_DIR8_SOUTH 4
860#define RETROFLAT_DIR8_WEST 6
861
862#define retroflat_dir4_rotate_cw( dir ) \
863 ((dir + 1) % 4)
864
865#define retroflat_dir8_reverse( dir ) \
866 ((dir + 4) % 8)
867
868#define retroflat_dir8_bounce( dir ) \
869 ((dir + 2) % 8)
870 /* maug_retroflt_dir */
872
879typedef int16_t retroflat_pxxy_t;
880
881#define PXXY_FMT "%d"
882
883#define PXXY_MAX INT16_MAX
884
885struct RETROFLAT_ARGS;
886
887#ifndef RETRO2D_TRACE_LVL
888# define RETRO2D_TRACE_LVL 0
889#endif /* !RETRO2D_TRACE_LVL */
890
891#ifndef RETRO2D_DRAW_TRACE_LVL
892# define RETRO2D_DRAW_TRACE_LVL 0
893#endif /* !RETRO2D_DRAW_TRACE_LVL */
894
895#ifndef RETRO2D_LOCK_TRACE_LVL
896# define RETRO2D_LOCK_TRACE_LVL 0
897#endif /* !RETRO2D_LOCK_TRACE_LVL */
898
899#ifndef RETROFLAT_NO_SOUND
900
929#ifndef RETROSND_TRACE_LVL
930# define RETROSND_TRACE_LVL 0
931#endif /* !RETROSND_TRACE_LVL */
932
933#ifndef RETROSND_REG_TRACE_LVL
934# define RETROSND_REG_TRACE_LVL 0
935#endif /* !RETROSND_REG_TRACE_LVL */
936
947#define RETROSND_FLAG_INIT 0x01
948 /* maug_retrosnd_flags */
950
951#define RETROSND_VOICE_BREATH 122
952
953#define RETROSND_VOICE_SEASHORE 123
954
955#define RETROSND_VOICE_BIRD_TWEET 124
956
957#define RETROSND_VOICE_PHONE_RING 125
958
959#define RETROSND_VOICE_HELICOPTER 126
960
961#define RETROSND_VOICE_APPLAUSE 127
962
967#define RETROSND_VOICE_GUNSHOT 128
968
969#define RETROSND_CHANNEL_CT 8
970
980
984void retrosnd_set_sf_bank( const char* filename_in );
985
986void retrosnd_midi_set_voice( uint8_t channel, uint8_t voice );
987
988void retrosnd_midi_set_control( uint8_t channel, uint8_t key, uint8_t val );
989
990void retrosnd_midi_note_on( uint8_t channel, uint8_t pitch, uint8_t vel );
991
992void retrosnd_midi_note_off( uint8_t channel, uint8_t pitch, uint8_t vel );
993
994MERROR_RETVAL retrosnd_midi_play_smf( const char* filename );
995
996uint8_t retrosnd_midi_is_playing_smf();
997
998void retrosnd_shutdown();
999 /* maug_retrosnd */
1001
1002#endif /* !RETROFLAT_NO_SOUND */
1003
1004/* === Platform-specific APIs === */
1005
1006/* The first call to these headers should just establish definitions (macros, defines, prototypes,
1007 * typedefs, etc). The later call below should then define function bodies.
1008 */
1009#ifndef RETROFLAT_NO_SOUND
1010# include <retapis.h>
1011#endif /* !RETROFLAT_NO_SOUND */
1012#include <retapii.h>
1013
1014/* === End platform-specific APIs === */
1015
1021# if defined( RETROFLAT_NO_KEYBOARD )
1022# define retroflat_case_key( key, pad ) case pad:
1023# define retroflat_or_key( input, key, pad ) ((input) == (pad))
1024# elif defined( RETROFLAT_NO_PAD )
1025# define retroflat_case_key( key, pad ) case key:
1026# define retroflat_or_key( input, key, pad ) ((input) == (key))
1027# else
1035# define retroflat_case_key( key, pad ) case pad: case key:
1036# define retroflat_or_key( input, key, pad ) \
1037 (((input) == (pad)) || ((input) == (key)))
1038# endif
1039 /* maug_retroflt_input */
1041
1042/* === OS-Specific Includes and Defines === */
1043
1044#if defined( RETROFLAT_OS_WIN ) && !defined( MAUG_WINDOWS_H )
1045# include <windows.h>
1046# define MAUG_WINDOWS_H
1047#endif /* !MAUG_WINDOWS_H */
1048
1049#if defined( RETROFLAT_BMP_TEX ) || defined( DOCUMENTATION )
1050
1052 uint8_t flags;
1053 MAUG_MHANDLE bytes_h;
1054 uint8_t* bytes;
1055 uint32_t bpp;
1056 uint32_t sz;
1057 uint8_t* px;
1058 uint32_t id;
1059 size_t w;
1060 size_t h;
1061};
1062
1063#endif /* RETROFLAT_BMP_TEX */
1064
1065/* TODO: Migrate all platform-specific parts below to retapid.h. */
1066#include <retapid.h>
1067
1068#ifndef retroflat_system_task
1074# define retroflat_system_task()
1075#endif /* !retroflat_system_task */
1076
1077typedef maug_ms_t retroflat_ms_t;
1078
1079typedef void (*retroflat_timer_cb_t)( retroflat_ms_t time, void* data );
1080
1081#include "retrom2d.h"
1082
1083/* === Structures === */
1084
1085/* TODO: Break the args into API-specific headers. */
1086
1089 uint8_t flags;
1094 char* title;
1117 int screen_scale;
1125 int joystick_id;
1126 struct RETROFLAT_PLATFORM_ARGS platform;
1127# ifndef RETROFLAT_NO_SOUND
1128 struct RETROFLAT_SOUND_ARGS sound;
1129# endif /* !RETROFLAT_NO_SOUND */
1130};
1131
1226 int16_t world_tile_x;
1227 int16_t world_tile_y;
1228#ifndef RETROFLAT_NO_VIEWPORT_REFRESH
1229 MAUG_MHANDLE refresh_grid_h;
1241#endif /* !RETROFLAT_NO_VIEWPORT_REFRESH */
1242};
1243
1244# define retroflat_screen_colors() (g_retroflat_state->screen_colors)
1245
1246#ifndef DOCUMENTATION
1247
1248# define retroflat_viewport_world_x_generic() \
1249 (g_retroflat_state->viewport.world_x)
1250
1251# define retroflat_viewport_world_y_generic() \
1252 (g_retroflat_state->viewport.world_y)
1253
1254# define retroflat_viewport_world_tile_x_generic() \
1255 (g_retroflat_state->viewport.world_tile_x)
1256
1257# define retroflat_viewport_world_tile_y_generic() \
1258 (g_retroflat_state->viewport.world_tile_y)
1259
1260# define retroflat_viewport_world_w_generic() \
1261 (g_retroflat_state->viewport.world_w)
1262
1263# define retroflat_viewport_world_h_generic() \
1264 (g_retroflat_state->viewport.world_h)
1265
1266# define retroflat_viewport_screen_tile_w_generic() \
1267 (g_retroflat_state->viewport.screen_tile_w)
1268
1269# define retroflat_viewport_screen_tile_h_generic() \
1270 (g_retroflat_state->viewport.screen_tile_h)
1271
1272# define retroflat_viewport_screen_w_generic() \
1273 (g_retroflat_state->viewport.screen_w)
1274
1275# define retroflat_viewport_screen_h_generic() \
1276 (g_retroflat_state->viewport.screen_h)
1277
1278# define retroflat_viewport_screen_w_remainder_generic() \
1279 (g_retroflat_state->viewport.screen_w_remainder)
1280
1281# define retroflat_viewport_screen_h_remainder_generic() \
1282 (g_retroflat_state->viewport.screen_h_remainder)
1283
1284# define retroflat_viewport_set_world_generic( w, h ) \
1285 debug_printf( 1, "setting viewport size to %d x %d...", \
1286 (int16_t)(w), (int16_t)(h) ); \
1287 (g_retroflat_state->viewport.world_w) = w; \
1288 (g_retroflat_state->viewport.world_h) = h;
1289
1290# define retroflat_viewport_set_world_pos_generic( x, y ) \
1291 debug_printf( 1, "setting viewport world pos to %d, %d...", x, y ); \
1292 (g_retroflat_state->viewport.world_x) = x; \
1293 (g_retroflat_state->viewport.world_y) = y; \
1294 (g_retroflat_state->viewport.world_tile_x) = (x) >> RETROFLAT_TILE_W_BITS; \
1295 (g_retroflat_state->viewport.world_tile_y) = (y) >> RETROFLAT_TILE_H_BITS;
1296
1297# define retroflat_viewport_set_pos_size_generic( x_px, y_px, w_px, h_px ) \
1298 g_retroflat_state->viewport.screen_x = (x_px); \
1299 g_retroflat_state->viewport.screen_y = (y_px); \
1300 g_retroflat_state->viewport.screen_tile_w = \
1301 ((w_px) / RETROFLAT_TILE_W); \
1302 g_retroflat_state->viewport.screen_tile_h = \
1303 ((h_px) / RETROFLAT_TILE_H); \
1304 /* We're not adding the extra room here since this won't be used for
1305 * indexing or allocation but rather pixel detection.
1306 */ \
1307 g_retroflat_state->viewport.screen_w = \
1308 ((w_px) / RETROFLAT_TILE_W) * RETROFLAT_TILE_W; \
1309 g_retroflat_state->viewport.screen_h = \
1310 ((h_px) / RETROFLAT_TILE_H) * RETROFLAT_TILE_H; \
1311 g_retroflat_state->viewport.screen_w_remainder = \
1312 (x_px) + (w_px) - g_retroflat_state->viewport.screen_w; \
1313 g_retroflat_state->viewport.screen_h_remainder = \
1314 (y_px) + (h_px) - g_retroflat_state->viewport.screen_h;
1315
1316#ifndef RETROFLAT_NO_VIEWPORT_REFRESH
1317
1318# define retroflat_viewport_lock_refresh_generic() \
1319 if( NULL == g_retroflat_state->viewport.refresh_grid ) { \
1320 maug_mlock( \
1321 g_retroflat_state->viewport.refresh_grid_h, \
1322 g_retroflat_state->viewport.refresh_grid ); \
1323 maug_cleanup_if_null_lock( retroflat_tile_t*, \
1324 g_retroflat_state->viewport.refresh_grid ); \
1325 }
1326
1327# define retroflat_viewport_unlock_refresh_generic() \
1328 if( NULL != g_retroflat_state->viewport.refresh_grid ) { \
1329 maug_munlock( \
1330 g_retroflat_state->viewport.refresh_grid_h, \
1331 g_retroflat_state->viewport.refresh_grid ); \
1332 }
1333
1334# define _retroflat_viewport_refresh_tile_x( x_px ) \
1335 (((x_px) + RETROFLAT_TILE_W) >> RETROFLAT_TILE_W_BITS)
1336
1337# define _retroflat_viewport_refresh_tile_y( y_px ) \
1338 (((y_px) + RETROFLAT_TILE_H) >> RETROFLAT_TILE_H_BITS)
1339
1340# define retroflat_viewport_set_refresh_generic( x_px, y_px, tid ) \
1341 assert( NULL != g_retroflat_state->viewport.refresh_grid ); \
1342 if( \
1343 /* Expand the range by -1 to account for just off-screen tile. */ \
1344 -(RETROFLAT_TILE_W) <= x_px && -(RETROFLAT_TILE_H) <= y_px && \
1345 retroflat_screen_w() > x_px && \
1346 retroflat_screen_h() > y_px \
1347 ) { \
1348 assert( 0 < g_retroflat_state->viewport.screen_tile_w ); \
1349 assert( 0 <= (((y_px) + RETROFLAT_TILE_H) >> RETROFLAT_TILE_H_BITS) ); \
1350 assert( 0 <= (((x_px) + RETROFLAT_TILE_W) >> RETROFLAT_TILE_W_BITS) ); \
1351 g_retroflat_state->viewport.refresh_grid[ \
1352 /* Add +1 tile to make off-screen "-1" tile positive. */ \
1353 ((_retroflat_viewport_refresh_tile_y( y_px ) + 1) * \
1354 (g_retroflat_state->viewport.screen_tile_w + 2)) + \
1355 (_retroflat_viewport_refresh_tile_x( x_px ) + 1)] = tid; \
1356 }
1357
1358# define retroflat_viewport_tile_is_stale( x_px, y_px, tile_id ) \
1359 ((tile_id) != \
1360 g_retroflat_state->viewport.refresh_grid[ \
1361 ((_retroflat_viewport_refresh_tile_y( y_px ) + 1) * \
1362 (g_retroflat_state->viewport.screen_tile_w + 2)) + \
1363 (_retroflat_viewport_refresh_tile_x( x_px ) + 1)])
1364
1365#endif /* !RETROFLAT_NO_VIEWPORT_REFRESH */
1366
1367uint8_t retroflat_viewport_move_x_generic( int16_t x );
1368
1369uint8_t retroflat_viewport_move_y_generic( int16_t y );
1370
1371uint8_t retroflat_viewport_focus_generic(
1373 retroflat_pxxy_t range, retroflat_pxxy_t speed );
1374
1375# define retroflat_viewport_screen_x_generic( world_x ) \
1376 (g_retroflat_state->viewport.screen_x + \
1377 ((world_x) - retroflat_viewport_world_x()))
1378
1379# define retroflat_viewport_screen_y_generic( world_y ) \
1380 (g_retroflat_state->viewport.screen_y + \
1381 ((world_y) - retroflat_viewport_world_y()))
1382
1383# define retroflat_viewport_screen_get_x_generic() \
1384 (g_retroflat_state->viewport.screen_x)
1385
1386# define retroflat_viewport_screen_get_y_generic() \
1387 (g_retroflat_state->viewport.screen_y)
1388
1389#endif /* !DOCUMENTATION */
1390
1391#if defined( RETROFLAT_SOFT_VIEWPORT ) || defined( DOCUMENTATION )
1392
1393# ifndef RETROFLAT_NO_VIEWPORT_REFRESH
1394 /* These clamp world coordinates to tile borders to allow refresh grid to
1395 * function properly (smooth-scrolling tiles will always be in motion).
1396 */
1397
1402# define retroflat_viewport_world_x() \
1403 ((retroflat_viewport_world_x_generic() \
1404 >> RETROFLAT_TILE_W_BITS) << RETROFLAT_TILE_W_BITS)
1405
1410# define retroflat_viewport_world_y() \
1411 ((retroflat_viewport_world_y_generic() \
1412 >> RETROFLAT_TILE_H_BITS) << RETROFLAT_TILE_H_BITS)
1413# else
1414# define retroflat_viewport_world_x() retroflat_viewport_world_x_generic()
1415# define retroflat_viewport_world_y() retroflat_viewport_world_y_generic()
1416#endif /* !RETROFLAT_NO_VIEWPORT_REFRESH */
1417
1418# define retroflat_viewport_world_tile_x() \
1419 retroflat_viewport_world_tile_x_generic()
1420# define retroflat_viewport_world_tile_y() \
1421 retroflat_viewport_world_tile_y_generic()
1422
1427# define retroflat_viewport_world_w() \
1428 retroflat_viewport_world_w_generic()
1429
1434# define retroflat_viewport_world_h() \
1435 retroflat_viewport_world_h_generic()
1436
1441# define retroflat_viewport_screen_tile_w() \
1442 retroflat_viewport_screen_tile_w_generic()
1443
1448# define retroflat_viewport_screen_tile_h() \
1449 retroflat_viewport_screen_tile_h_generic()
1450
1455# define retroflat_viewport_screen_w() \
1456 retroflat_viewport_screen_w_generic()
1457
1462# define retroflat_viewport_screen_h() \
1463 retroflat_viewport_screen_h_generic()
1464
1470# define retroflat_viewport_screen_w_remainder() \
1471 retroflat_viewport_screen_w_remainder_generic()
1472
1478# define retroflat_viewport_screen_h_remainder() \
1479 retroflat_viewport_screen_h_remainder_generic()
1480
1488# define retroflat_viewport_set_world( w, h ) \
1489 retroflat_viewport_set_world_generic( w, h )
1490
1495# define retroflat_viewport_set_world_pos( x, y ) \
1496 retroflat_viewport_set_world_pos_generic( x, y )
1497
1503# define retroflat_viewport_set_pos_size( x_px, y_px, w_px, h_px ) \
1504 retroflat_viewport_set_pos_size_generic( x_px, y_px, w_px, h_px )
1505
1506#ifndef RETROFLAT_NO_VIEWPORT_REFRESH
1507
1515# define retroflat_viewport_lock_refresh() \
1516 retroflat_viewport_lock_refresh_generic()
1517
1525# define retroflat_viewport_unlock_refresh() \
1526 retroflat_viewport_unlock_refresh_generic()
1527
1539# define retroflat_viewport_set_refresh( x, y, tid ) \
1540 retroflat_viewport_set_refresh_generic( x, y, tid )
1541
1542#endif /* !RETROFLAT_NO_VIEWPORT_REFRESH */
1543
1556# define retroflat_viewport_focus( x1, y1, range, speed ) \
1557 retroflat_viewport_focus_generic( x1, y1, range, speed )
1558
1563# define retroflat_viewport_screen_x( world_x ) \
1564 retroflat_viewport_screen_x_generic( world_x )
1565
1570# define retroflat_viewport_screen_y( world_y ) \
1571 retroflat_viewport_screen_y_generic( world_y )
1572
1573# define retroflat_viewport_screen_get_x() \
1574 retroflat_viewport_screen_get_x_generic()
1575
1576# define retroflat_viewport_screen_get_y() \
1577 retroflat_viewport_screen_get_y_generic()
1578
1579# ifndef RETROFLAT_VIEWPORT_OVERRIDE_MOVE
1580# define retroflat_viewport_move_x( x ) \
1581 retroflat_viewport_move_x_generic( x )
1582
1583# define retroflat_viewport_move_y( y ) \
1584 retroflat_viewport_move_y_generic( y )
1585# endif /* !RETROFLAT_VIEWPORT_OVERRIDE_MOVE */
1586
1587#endif /* RETROFLAT_SOFT_VIEWPORT || DOCUMENTATION */
1588
1597#define retroflat_heartbeat_set( len, max ) \
1598 g_retroflat_state->heartbeat_max = max; \
1599 g_retroflat_state->heartbeat_len = len;
1600
1605#define retroflat_heartbeat() (g_retroflat_state->heartbeat_frame)
1606
1614#define retroflat_heartbeat_update() \
1615 /* Update the heartbeat animation frame. */ \
1616 if( g_retroflat_state->heartbeat_next <= retroflat_get_ms() ) { \
1617 g_retroflat_state->heartbeat_frame++; \
1618 if( \
1619 g_retroflat_state->heartbeat_frame >= \
1620 g_retroflat_state->heartbeat_max \
1621 ) { \
1622 g_retroflat_state->heartbeat_frame = 0; \
1623 } \
1624 g_retroflat_state->heartbeat_next = \
1625 retroflat_get_ms() + g_retroflat_state->heartbeat_len; \
1626 }
1627
1635 /* TODO: Set this up in the initialization function! */
1636 /* TODO: We probably need more of these. */
1637 size_t sz;
1638 size_t offset_pal;
1639 size_t offset_tex_pal;
1640
1641 void* loop_data;
1642 MERROR_RETVAL retval;
1645 maug_path config_path;
1646 maug_path assets_path;
1647 maug_path saves_path;
1648
1650 /* struct RETROFLAT_BITMAP buffer; */
1652
1653# if defined( RETROFLAT_VDP ) || defined( DOCUMENTATION ) || \
1654defined( RETROVDP_C )
1659 struct RETROFLAT_BITMAP* vdp_buffer;
1660# ifdef RETROFLAT_OS_WIN
1661 HMODULE vdp_exe;
1662# else
1664 void* vdp_exe;
1665# endif /* RETROFLAT_OS_WIN */
1674 uint8_t vdp_flags;
1675# endif /* RETROFLAT_VDP || DOCUMENTATION || RETROVDP_C */
1676
1677 /* These are used by VDP so should be standardized/not put in plat-spec! */
1678
1679 struct RETROFLAT_VIEWPORT viewport;
1680
1696 size_t screen_w;
1698 size_t screen_h;
1701
1702 /* WARNING: The VDP requires the state specifier to be the same size
1703 * as the one it was compiled for! Do not modify above here!
1704 */
1705
1706 /* TODO: Put these in a platform-specific struct of some kind to maintain
1707 * consistent state struct size for VDP?
1708 */
1709
1710 retroflat_ms_t heartbeat_next;
1728
1729 retroflat_proc_resize_t on_resize;
1730 void* on_resize_data;
1731
1732#ifndef RETROFLAT_BMP_TEX
1734 RETROFLAT_COLOR_DEF palette[RETROFLAT_COLORS_SZ];
1735#endif /* !RETROFLAT_BMP_TEX */
1736
1737 retroflat_loop_iter loop_iter;
1738 retroflat_loop_iter frame_iter;
1739
1740 struct RETROFLAT_PLATFORM platform;
1741
1742# if defined( RETROFLAT_BMP_TEX )
1743 /* This allows native colors to be used for things like glColor3fv while
1744 * these colors are used to manipulate textures passed through
1745 * retroflat_bitmap_*().
1746 */
1747 RETROFLAT_TEX_COLOR_DEF tex_palette[RETROFLAT_COLORS_SZ];
1748# endif /* RETROFLAT_BMP_TEX */
1749
1750 struct RETROFLAT_INPUT_STATE input;
1751
1756 retroflat_timer_cb_t timers_cb[RETROFLAT_TIMER_CT_MAX];
1757 retroflat_ms_t timers_at[RETROFLAT_TIMER_CT_MAX];
1758 void* timers_data[RETROFLAT_TIMER_CT_MAX];
1759 size_t timers_ct;
1760
1761# ifndef RETROFLAT_NO_SOUND
1762 struct RETROFLAT_SOUND_STATE sound;
1763# endif /* !RETROFLAT_NO_SOUND */
1764};
1765
1766/* === Translation Module === */
1767
1768/* Declare the prototypes so that internal functions can call each other. */
1769
1770# ifdef retroflat_loop
1771MERROR_RETVAL retroflat_loop_generic(
1772 retroflat_loop_iter frame_iter, retroflat_loop_iter loop_iter, void* data );
1773# else
1780 retroflat_loop_iter frame_iter, retroflat_loop_iter loop_iter, void* data );
1781# endif /* retroflat_loop */
1782
1783#define retroflat_get_assets_path() (g_retroflat_state->assets_path)
1784
1785MERROR_RETVAL retroflat_build_filename_path(
1786 const maug_path filename_in, const char* filename_ext,
1787 char* buffer_out, size_t buffer_out_sz, uint8_t flags );
1788
1801 uint8_t flags, const char* title, const char* format, ... );
1802 /* maug_retroflt_msg_api */
1804
1812MERROR_RETVAL retroflat_init( int argc, char* argv[], struct RETROFLAT_ARGS* args );
1813
1820void retroflat_shutdown( int retval );
1821
1822# if defined( RETROFLAT_VDP ) || defined( DOCUMENTATION )
1831MERROR_RETVAL retroflat_vdp_call( const char* proc_name );
1832 /* maug_retroflt_vdp */
1834# endif /* RETROFLAT_VDP || DOCUMENTATION */
1835
1836RETROFLAT_IN_KEY retroflat_repeat_input(
1837 RETROFLAT_IN_KEY key_out, struct RETROFLAT_INPUT* input,
1838 RETROFLAT_IN_KEY* prev_input, int* prev_delay );
1839
1840void retroflat_set_title( const char* format, ... );
1841
1842retroflat_ms_t retroflat_get_ms();
1843
1844uint32_t retroflat_get_rand();
1845
1846# if !defined( RETROFLAT_NO_KEYBOARD )
1847char retroflat_vk_to_ascii( RETROFLAT_IN_KEY k, uint8_t flags );
1848# endif /* !RETROFLAT_NO_KEYBOARD */
1849
1866 const char* filename, struct RETROFLAT_BITMAP* bmp_out, uint8_t flags );
1867
1868MERROR_RETVAL retroflat_create_bitmap(
1870 struct RETROFLAT_BITMAP* bmp_out, uint8_t flags );
1871
1877void retroflat_destroy_bitmap( struct RETROFLAT_BITMAP* bitmap );
1878
1895 struct RETROFLAT_BITMAP* target, struct RETROFLAT_BITMAP* src,
1899 int16_t instance );
1900
1901#ifdef RETROFLAT_TRACE_CONSTRAIN
1902# define retroflat_constrain_px( x, y, bmp, retact ) \
1903 if( \
1904 x >= retroflat_bitmap_w( bmp ) || y >= retroflat_bitmap_h( bmp ) || \
1905 0 > x || 0 > y \
1906 ) { \
1907 error_printf( "attempted draw at %d, %d, out of bounds %d x %d", \
1908 x, y, retroflat_bitmap_w( bmp ), retroflat_bitmap_h( bmp ) ); \
1909 retact; \
1910 }
1911#else
1919# define retroflat_constrain_px( x, y, bmp, retact ) \
1920 if( \
1921 x >= retroflat_bitmap_w( bmp ) || y >= retroflat_bitmap_h( bmp ) || \
1922 0 > x || 0 > y \
1923 ) { \
1924 retact; \
1925 }
1926#endif /* RETROFLAT_TRACE_CONSTRAIN */
1927
1932 struct RETROFLAT_BITMAP* bitmap,
1933 int16_t instance,
1937 /* maug_retroflt_bitmap */
1939
1954MERROR_RETVAL retroflat_draw_lock( struct RETROFLAT_BITMAP* bmp );
1955
1956MERROR_RETVAL retroflat_draw_release( struct RETROFLAT_BITMAP* bmp );
1957
1958void retroflat_px(
1959 struct RETROFLAT_BITMAP* target, const RETROFLAT_COLOR color,
1960 retroflat_pxxy_t x, retroflat_pxxy_t y, uint8_t flags );
1961
1962#ifdef RETROFLAT_SOFT_SHAPES
1963# ifdef RETROFLAT_OPENGL
1964/* Make sure we're not passing NULL to openGL texture drawers... they can't
1965 * handle that!
1966 */
1967# define retroflat_rect( t, c, x, y, w, h, f ) \
1968 assert( NULL != t ); \
1969 retrosoft_rect( t, c, x, y, w, h, f );
1970# define retroflat_ellipse( t, c, x, y, w, h, f ) \
1971 assert( NULL != t ); \
1972 retrosoft_ellipse( t, c, x, y, w, h, f )
1973# else
1974# define retroflat_rect( t, c, x, y, w, h, f ) \
1975 retrosoft_rect( t, c, x, y, w, h, f )
1976# define retroflat_ellipse( t, c, x, y, w, h, f ) \
1977 retrosoft_ellipse( t, c, x, y, w, h, f )
1978# endif /* RETROFLAT_3D */
1979#else
1980
1992 struct RETROFLAT_BITMAP* target, const RETROFLAT_COLOR color,
1994 retroflat_pxxy_t w, retroflat_pxxy_t h, uint8_t flags );
1995
2007 struct RETROFLAT_BITMAP* target, const RETROFLAT_COLOR color,
2009 retroflat_pxxy_t w, retroflat_pxxy_t h, uint8_t flags );
2010
2011#endif /* RETROFLAT_SOFT_SHAPES */
2012
2013#ifdef RETROFLAT_SOFT_LINES
2014# define retroflat_line( t, c, x1, y1, x2, y2, f ) \
2015 retrosoft_line( t, c, x1, y1, x2, y2, f )
2016#else
2017
2030 struct RETROFLAT_BITMAP* target, const RETROFLAT_COLOR color,
2032 retroflat_pxxy_t x2, retroflat_pxxy_t y2, uint8_t flags );
2033
2034#endif /* RETROFLAT_SOFT_LINES */
2035
2036void retroflat_cursor( struct RETROFLAT_BITMAP* target, uint8_t flags );
2037
2051 struct RETROFLAT_BITMAP* target, const char* str, size_t str_sz,
2052 const char* font_str,
2053 retroflat_pxxy_t* w_out, retroflat_pxxy_t* h_out, uint8_t flags );
2054
2073 struct RETROFLAT_BITMAP* target, const RETROFLAT_COLOR color,
2074 const char* str, int str_sz, const char* font_str,
2075 retroflat_pxxy_t x_orig, retroflat_pxxy_t y_orig,
2076 uint8_t flags );
2077
2078/* TODO: Documentation! */
2079void retroflat_get_palette( uint8_t idx, uint32_t* rgb );
2080
2081MERROR_RETVAL retroflat_set_palette( uint8_t idx, uint32_t rgb );
2082 /* maug_retroflt_bitmap */
2084
2095 retroflat_proc_resize_t on_resize_in, void* data_in );
2096
2102
2108 retroflat_ms_t time, retroflat_timer_cb_t cb, void* data );
2109
2115
2126RETROFLAT_IN_KEY retroflat_poll_input( struct RETROFLAT_INPUT* input );
2127 /* maug_retroflt_input */
2129
2130#ifdef RETROFLT_C
2131
2132MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets8_x[8] =
2133 { 0, 1, 1, 1, 0, -1, -1, -1 };
2134MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets8_y[8] =
2135 { -1, -1, 0, 1, 1, 1, 0, -1 };
2136
2137MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets4_x[4] =
2138 { 0, 1, 0, -1 };
2139MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets4_y[4] =
2140 { -1, 0, 1, 0 };
2141
2142# ifdef RETROFLAT_STATE_ON_STACK
2143struct RETROFLAT_STATE SEG_MGLOBAL g_retroflat_state_stack;
2144# else
2145MAUG_MHANDLE SEG_MGLOBAL g_retroflat_state_h = (MAUG_MHANDLE)NULL;
2146# endif /* RETROFLAT_STATE_ON_STACK */
2147struct RETROFLAT_STATE* SEG_MGLOBAL g_retroflat_state = NULL;
2148
2149# define RETROFLAT_COLOR_TABLE_CONSTS( idx, name_l, name_u, r, g, b, cgac, cgad ) \
2150 MAUG_CONST RETROFLAT_COLOR SEG_MCONST RETROFLAT_COLOR_ ## name_u = idx;
2151
2152RETROFLAT_COLOR_TABLE( RETROFLAT_COLOR_TABLE_CONSTS )
2153
2154# define RETROFLAT_COLOR_TABLE_NAMES( idx, name_l, name_u, r, g, b, cgac, cgad ) \
2155 #name_u,
2156
2157MAUG_CONST char* SEG_MCONST gc_retroflat_color_names[] = {
2158 RETROFLAT_COLOR_TABLE( RETROFLAT_COLOR_TABLE_NAMES )
2159};
2160
2161/* Callback table is down below, after the statically-defined callbacks. */
2162
2163/* === Function Definitions === */
2164
2165MERROR_RETVAL retroflat_build_filename_path(
2166 const maug_path filename_in, const char* filename_ext,
2167 char* buffer_out, size_t buffer_out_sz, uint8_t flags
2168) {
2169 MERROR_RETVAL retval = MERROR_OK;
2170
2171 assert( 1 < buffer_out_sz );
2172
2173 /* Build the path to the bitmap. */
2174 maug_mzero( buffer_out, buffer_out_sz );
2175 if(
2178 ) {
2179 /* TODO: Error checking. */
2180 maug_snprintf( buffer_out, buffer_out_sz - 1, "%s", filename_in );
2181 } else if( NULL != filename_ext ) {
2182 /* TODO: Error checking. */
2183 maug_snprintf( buffer_out, buffer_out_sz - 1, "%s%c%s.%s",
2184 g_retroflat_state->assets_path, RETROFLAT_PATH_SEP,
2185 filename_in, filename_ext );
2186 } else {
2187 maug_snprintf( buffer_out, buffer_out_sz - 1, "%s%c%s",
2188 g_retroflat_state->assets_path, RETROFLAT_PATH_SEP,
2189 filename_in );
2190 }
2191
2192 return retval;
2193}
2194
2195/* === */
2196
2197# if (defined( RETROFLAT_SOFT_SHAPES ) || defined( RETROFLAT_SOFT_LINES ) || \
2198 defined( RETROFLAT_3D ))
2199/* RETROSOFT_PRESENT is different from RETROFLAT_SOFT_SHAPES in that it only
2200 * indicates that the retrosoft library is loaded, not that it is the default
2201 * for drawing primatives!
2202 */
2203# define RETROSOFT_PRESENT
2204# endif
2205
2206# if defined( RETROFLAT_3D )
2207# if !defined( MAUG_NO_AUTO_C )
2208# define RETRO3D_C
2209# define RETRO3DP_C
2210# define RETROFP_C
2211# endif /* MAUG_NO_AUTO_C */
2212# include <retro3dp.h>
2213# include <retro3d.h>
2214# include <retro3du.h>
2215# include <retapi3.h>
2216# endif /* RETROFLAT_3D */
2217
2218# ifdef RETROSOFT_PRESENT
2219# if !defined( MAUG_NO_AUTO_C )
2220# define RETROSFT_C
2221# endif /* !MAUG_NO_AUTO_C */
2222# define RETROSOFT_PRESENT
2223# include <retrosft.h>
2224# endif /* RETROFLAT_SOFT_SHAPES */
2225
2226# ifndef RETROFLAT_NO_SOUND
2227# include <retapis.h>
2228# endif /* !RETROFLAT_NO_SOUND */
2229
2230# include <retapii.h>
2231
2232# if defined( RETROFLAT_VDP ) && defined( RETROFLAT_OS_UNIX )
2233# include <dlfcn.h>
2234# endif
2235
2236/* Still inside RETROFLT_C! */
2237
2238/* === */
2239
2240#ifndef RETROFLAT_NO_GENERIC_LOOP
2241
2242MERROR_RETVAL retroflat_loop_generic(
2243 retroflat_loop_iter frame_iter, retroflat_loop_iter loop_iter, void* data
2244) {
2245 MERROR_RETVAL retval = MERROR_OK;
2246 retroflat_ms_t next = 0,
2247 now = 0;
2248
2249 g_retroflat_state->loop_iter = (retroflat_loop_iter)loop_iter;
2250 g_retroflat_state->loop_data = (void*)data;
2251 g_retroflat_state->frame_iter = (retroflat_loop_iter)frame_iter;
2252
2253 if(
2255 (g_retroflat_state->retroflat_flags & RETROFLAT_FLAGS_RUNNING)
2256 ) {
2257 /* Main loop is already running, so we're just changing the iter call
2258 * and leaving!
2259 */
2260 debug_printf( 1, "main loop already running!" );
2261 goto cleanup;
2262 }
2263
2264 g_retroflat_state->retroflat_flags |= RETROFLAT_FLAGS_RUNNING;
2265 do {
2267
2268 if(
2269 /* Not waiting for the next frame? */
2271 (RETROFLAT_FLAGS_WAIT_FOR_FPS & g_retroflat_state->retroflat_flags) &&
2272 /* Inter-frame loop present? */
2273 NULL != g_retroflat_state->loop_iter
2274 ) {
2275 /* Run the loop iter as many times as possible. */
2276 g_retroflat_state->loop_iter( g_retroflat_state->loop_data );
2277 }
2278 if(
2280 (RETROFLAT_FLAGS_UNLOCK_FPS & g_retroflat_state->retroflat_flags) &&
2281 retroflat_get_ms() < next
2282 ) {
2283 /* Sleep/low power for a bit. */
2284 continue;
2285 }
2286
2288
2290
2291 if( NULL != g_retroflat_state->frame_iter ) {
2292 /* Run the frame iterator once per FPS tick. */
2293 g_retroflat_state->frame_iter( g_retroflat_state->loop_data );
2294 }
2295 /* Reset wait-for-frame flag AFTER frame callback. */
2296 g_retroflat_state->retroflat_flags &= ~RETROFLAT_FLAGS_WAIT_FOR_FPS;
2297 now = retroflat_get_ms();
2298 if( now + retroflat_fps_next() > now ) {
2299 next = now + retroflat_fps_next();
2300 } else {
2301 /* Rollover protection. */
2302 /* TODO: Add difference from now/next to 0 here. */
2303 next = 0;
2304 }
2305 } while(
2307 (RETROFLAT_FLAGS_RUNNING & g_retroflat_state->retroflat_flags)
2308 );
2309 retval = g_retroflat_state->retval;
2310
2311cleanup:
2312
2313 /* This should be set by retroflat_quit(). */
2314 return retval;
2315}
2316
2317#endif /* !RETROFLAT_NO_GENERIC_LOOP */
2318
2319/* === */
2320
2321# if !defined( RETROFLAT_NO_KEYBOARD )
2322
2323char retroflat_vk_to_ascii( RETROFLAT_IN_KEY k, uint8_t flags ) {
2324 char c = 0;
2325 char offset_lower = 0;
2326
2327 if( RETROFLAT_INPUT_MOD_SHIFT != (RETROFLAT_INPUT_MOD_SHIFT & flags) ) {
2328 /* Shift is *not* being held down. */
2329
2330 if( RETROFLAT_KEY_A <= k && RETROFLAT_KEY_Z >= k ) {
2331 if(
2332 RETROFLAT_INPUT_FORCE_UPPER !=
2333 (RETROFLAT_INPUT_FORCE_UPPER & flags)
2334 ) {
2335 /* Key is alphabetical and we're not forcing uppercase. */
2336 offset_lower = 0x20;
2337 }
2338 } else {
2339 offset_lower = 1;
2340 }
2341 }
2342
2343 switch( k ) {
2344 case RETROFLAT_KEY_A: c = 0x41 + offset_lower; break;
2345 case RETROFLAT_KEY_B: c = 0x42 + offset_lower; break;
2346 case RETROFLAT_KEY_C: c = 0x43 + offset_lower; break;
2347 case RETROFLAT_KEY_D: c = 0x44 + offset_lower; break;
2348 case RETROFLAT_KEY_E: c = 0x45 + offset_lower; break;
2349 case RETROFLAT_KEY_F: c = 0x46 + offset_lower; break;
2350 case RETROFLAT_KEY_G: c = 0x47 + offset_lower; break;
2351 case RETROFLAT_KEY_H: c = 0x48 + offset_lower; break;
2352 case RETROFLAT_KEY_I: c = 0x49 + offset_lower; break;
2353 case RETROFLAT_KEY_J: c = 0x4a + offset_lower; break;
2354 case RETROFLAT_KEY_K: c = 0x4b + offset_lower; break;
2355 case RETROFLAT_KEY_L: c = 0x4c + offset_lower; break;
2356 case RETROFLAT_KEY_M: c = 0x4d + offset_lower; break;
2357 case RETROFLAT_KEY_N: c = 0x4e + offset_lower; break;
2358 case RETROFLAT_KEY_O: c = 0x4f + offset_lower; break;
2359 case RETROFLAT_KEY_P: c = 0x50 + offset_lower; break;
2360 case RETROFLAT_KEY_Q: c = 0x51 + offset_lower; break;
2361 case RETROFLAT_KEY_R: c = 0x52 + offset_lower; break;
2362 case RETROFLAT_KEY_S: c = 0x53 + offset_lower; break;
2363 case RETROFLAT_KEY_T: c = 0x54 + offset_lower; break;
2364 case RETROFLAT_KEY_U: c = 0x55 + offset_lower; break;
2365 case RETROFLAT_KEY_V: c = 0x56 + offset_lower; break;
2366 case RETROFLAT_KEY_W: c = 0x57 + offset_lower; break;
2367 case RETROFLAT_KEY_X: c = 0x58 + offset_lower; break;
2368 case RETROFLAT_KEY_Y: c = 0x59 + offset_lower; break;
2369 case RETROFLAT_KEY_Z: c = 0x60 + offset_lower; break;
2370 case RETROFLAT_KEY_0: c = offset_lower ? 0x30 : ')'; break;
2371 case RETROFLAT_KEY_1: c = offset_lower ? 0x31 : '!'; break;
2372 case RETROFLAT_KEY_2: c = offset_lower ? 0x32 : '@'; break;
2373 case RETROFLAT_KEY_3: c = offset_lower ? 0x33 : '#'; break;
2374 case RETROFLAT_KEY_4: c = offset_lower ? 0x34 : '$'; break;
2375 case RETROFLAT_KEY_5: c = offset_lower ? 0x35 : '%'; break;
2376 case RETROFLAT_KEY_6: c = offset_lower ? 0x36 : '^'; break;
2377 case RETROFLAT_KEY_7: c = offset_lower ? 0x37 : '&'; break;
2378 case RETROFLAT_KEY_8: c = offset_lower ? 0x38 : '*'; break;
2379 case RETROFLAT_KEY_9: c = offset_lower ? 0x39 : '('; break;
2380 case RETROFLAT_KEY_SPACE: c = ' '; break;
2381 case RETROFLAT_KEY_BKSP: c = 0x08; break;
2382 case RETROFLAT_KEY_ENTER: c = '\n'; break;
2383 case RETROFLAT_KEY_SEMICOLON: c = offset_lower ? ';' : ':'; break;
2384 case RETROFLAT_KEY_DASH: c = offset_lower ? '-' : '_'; break;
2385 case RETROFLAT_KEY_SLASH: c = offset_lower ? '/' : '?'; break;
2386 case RETROFLAT_KEY_PERIOD: c = offset_lower ? '.' : '>'; break;
2387 case RETROFLAT_KEY_COMMA: c = offset_lower ? ',' : '<'; break;
2388 case RETROFLAT_KEY_QUOTE: c = offset_lower ? '\'' : '"'; break;
2389 case RETROFLAT_KEY_EQUALS: c = offset_lower ? '=' : '+'; break;
2390 case RETROFLAT_KEY_BACKSLASH: c = offset_lower ? '\\' : '|'; break;
2391 case RETROFLAT_KEY_BRACKETL: c = offset_lower ? '[' : '{'; break;
2392 case RETROFLAT_KEY_BRACKETR: c = offset_lower ? ']' : '}'; break;
2393#ifndef RETROFLAT_API_PC_BIOS
2394 /* TODO: FIXME in DOS! */
2395 case RETROFLAT_KEY_GRAVE: c = offset_lower ? '`' : '~'; break;
2396#endif /* !RETROFLAT_API_PC_BIOS */
2397 }
2398
2399 debug_printf( RETROINPUT_TRACE_LVL, "0x%02x", c );
2400
2401 return c;
2402}
2403
2404#endif /* !RETROFLAT_NO_KEYBOARD */
2405
2406/* === */
2407
2408/* TODO: Migrate all platform-specific parts below to retapif.h. */
2409#include <retapif.h>
2410
2411/* === */
2412
2413# ifndef RETROFLAT_NO_CLI
2414
2415# if !defined( RETROFLAT_NO_SOUND ) && defined( RETROSND_ARGS )
2416
2417static MERROR_RETVAL retrosnd_cli_rsl(
2418 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2419) {
2420 if(
2421 0 <= arg_c &&
2422 0 == maug_strncmp( MAUG_CLI_SIGIL "rsl", arg, MAUG_CLI_SIGIL_SZ + 4 )
2423 ) {
2424 args->sound.flags |= RETROSND_ARGS_FLAG_LIST_DEVS;
2425 }
2426 return MERROR_OK;
2427}
2428
2429# endif /* !RETROFLAT_NO_SOUND && RETROSND_ARGS */
2430
2431# if !defined( RETROFLAT_API_PC_BIOS ) && !defined( RETROFLAT_NO_CLI_SZ )
2432
2433static MERROR_RETVAL retroflat_cli_rfs(
2434 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2435) {
2436 if( 1 < arg_c ) {
2437 args->screen_scale = atoi( arg );
2438 debug_printf( 3, "screen scale arg set to: %d", args->screen_scale );
2439 }
2440 return MERROR_OK;
2441}
2442
2443static MERROR_RETVAL retroflat_cli_rfx(
2444 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2445) {
2446 if( 0 > arg_c ) {
2447 if( 0 == args->screen_w ) {
2448 args->screen_x = 0;
2449 }
2450 } else if(
2451 0 == maug_strncmp( MAUG_CLI_SIGIL "rfx", arg, MAUG_CLI_SIGIL_SZ + 4 )
2452 ) {
2453 /* The next arg must be the new var. */
2454 } else {
2455 args->screen_x = atoi( arg );
2456 }
2457 return MERROR_OK;
2458}
2459
2460static MERROR_RETVAL retroflat_cli_rfy(
2461 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2462) {
2463 if( 0 > arg_c ) {
2464 if( 0 == args->screen_h ) {
2465 args->screen_y = 0;
2466 }
2467 } else if(
2468 0 == maug_strncmp( MAUG_CLI_SIGIL "rfy", arg, MAUG_CLI_SIGIL_SZ + 4 )
2469 ) {
2470 /* The next arg must be the new var. */
2471 } else {
2472 args->screen_y = atoi( arg );
2473 }
2474 return MERROR_OK;
2475}
2476
2477static MERROR_RETVAL retroflat_cli_rfw(
2478 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2479) {
2480 if( 0 > arg_c ) {
2481 if( 0 == args->screen_w ) {
2482 args->screen_w = RETROFLAT_DEFAULT_SCREEN_W;
2483 debug_printf( 1, "setting arg screen_w to default %d:",
2484 args->screen_w );
2485 }
2486 } else if(
2487 0 == maug_strncmp( MAUG_CLI_SIGIL "rfw", arg, MAUG_CLI_SIGIL_SZ + 4 )
2488 ) {
2489 /* The next arg must be the new var. */
2490 } else {
2491 args->screen_w = atoi( arg );
2492 debug_printf( 1, "setting arg screen_w to: %d",
2493 args->screen_w );
2494 }
2495 return MERROR_OK;
2496}
2497
2498static MERROR_RETVAL retroflat_cli_rfh(
2499 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2500) {
2501 if( 0 > arg_c ) {
2502 if( 0 == args->screen_h ) {
2503 args->screen_h = RETROFLAT_DEFAULT_SCREEN_H;
2504 debug_printf( 1, "setting arg screen_h to default: %d",
2505 args->screen_h );
2506 }
2507 } else if(
2508 0 == maug_strncmp( MAUG_CLI_SIGIL "rfh", arg, MAUG_CLI_SIGIL_SZ + 4 )
2509 ) {
2510 /* The next arg must be the new var. */
2511 } else {
2512 args->screen_h = atoi( arg );
2513 debug_printf( 1, "setting arg screen_h to: %d",
2514 args->screen_h );
2515 }
2516 return MERROR_OK;
2517}
2518
2519# endif /* !RETROFLAT_API_PC_BIOS && !RETROFLAT_NO_CLI_SZ */
2520
2521# ifdef RETROFLAT_VDP
2522static MERROR_RETVAL retroflat_cli_vdp(
2523 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2524) {
2525 if( 0 == maug_strncmp( MAUG_CLI_SIGIL "vdp", arg, MAUG_CLI_SIGIL_SZ + 4 ) ) {
2526 /* Next arg is VDP args str. */
2527 } else {
2528 maug_strncpy( g_retroflat_state->vdp_args, arg, RETROFLAT_VDP_ARGS_SZ_MAX );
2529 debug_printf( 1, "VDP args: %s", g_retroflat_state->vdp_args );
2530 }
2531 return MERROR_OK;
2532}
2533# endif /* RETROFLAT_VDP */
2534
2535static MERROR_RETVAL retroflat_cli_u(
2536 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2537) {
2538 if( 0 > arg_c ) {
2539 args->flags &= ~RETROFLAT_FLAGS_UNLOCK_FPS;
2540 } else if(
2541 0 == maug_strncmp( MAUG_CLI_SIGIL "rfu", arg, MAUG_CLI_SIGIL_SZ + 4 )
2542 ) {
2543 debug_printf( 1, "unlocking FPS..." );
2544 args->flags |= RETROFLAT_FLAGS_UNLOCK_FPS;
2545 }
2546 return MERROR_OK;
2547}
2548
2549# ifndef RETROFLAT_NO_PAD
2550
2551static MERROR_RETVAL retroflat_cli_rfj(
2552 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2553) {
2554 if( 0 > arg_c ) {
2555 args->joystick_id = -1;
2556 debug_printf( 1, "setting arg joystick_id to default: %d",
2557 args->joystick_id );
2558 } else if(
2559 0 == maug_strncmp( MAUG_CLI_SIGIL "rfj", arg, MAUG_CLI_SIGIL_SZ + 4 )
2560 ) {
2561 /* The next arg must be the new var. */
2562 } else {
2563 args->joystick_id = atoi( arg );
2564 debug_printf( 1, "setting arg joystick_id to: %d",
2565 args->joystick_id );
2566 }
2567 return MERROR_OK;
2568}
2569
2570# endif /* !RETROFLAT_NO_PAD */
2571
2572#endif /* !RETROFLAT_NO_CLI */
2573
2574/* === */
2575
2576/* Still inside RETROFLT_C! */
2577
2579 int argc, char* argv[], struct RETROFLAT_ARGS* args
2580) {
2581
2582 /* = Declare Init Vars = */
2583
2584 MERROR_RETVAL retval = 0;
2585
2586 /* = Begin Init Procedure = */
2587
2588# ifdef RETROFLAT_COMMIT_HASH
2589 debug_printf( 1, "retroflat commit: " RETROFLAT_COMMIT_HASH );
2590# endif /* RETROFLAT_COMMIT_HASH */
2591
2592 debug_printf( 1, "retroflat: initializing..." );
2593
2594 /* System sanity checks. */
2595 assert( 2 <= sizeof( MERROR_RETVAL ) );
2596 assert( 4 == sizeof( uint32_t ) );
2597 assert( 4 == sizeof( int32_t ) );
2598 assert( 2 == sizeof( uint16_t ) );
2599 assert( 2 == sizeof( int16_t ) );
2600 assert( 1 == sizeof( uint8_t ) );
2601 assert( 1 == sizeof( int8_t ) );
2602 assert( NULL != args );
2603 assert( 1 << RETROFLAT_TILE_W_BITS == RETROFLAT_TILE_W );
2604 assert( 1 << RETROFLAT_TILE_H_BITS == RETROFLAT_TILE_H );
2605
2606 debug_printf( 1, "initializing drawing routines..." );
2607
2608 /* Initialize 2D callbacks depending on if we're in 2D or 3D mode.
2609 * Please see retrom2d.h for more information.
2610 */
2611# if defined( RETROFLAT_BMP_TEX )
2612 retroflat_2d_px = (retroflat_px_cb)retro3d_texture_px;
2613 retroflat_2d_line = (retroflat_line_cb)retrosoft_line;
2614 retroflat_2d_rect = (retroflat_rect_cb)retrosoft_rect;
2615 retroflat_2d_ellipse = (retroflat_ellipse_cb)retrosoft_ellipse;
2616 retroflat_2d_blit_bitmap = (retroflat_blit_bitmap_cb)retro3d_texture_blit;
2617 retroflat_2d_load_bitmap =
2618 (retroflat_load_bitmap_cb)retro3d_texture_load_bitmap;
2619 retroflat_2d_create_bitmap =
2620 (retroflat_create_bitmap_cb)retro3d_texture_create;
2621# else
2622 retroflat_2d_px = (retroflat_px_cb)retroflat_px;
2623# ifdef RETROFLAT_SOFT_SHAPES
2624 /* TODO: Work retrosoft routines to use retroflat_blit_t */
2625 retroflat_2d_line = (retroflat_line_cb)retrosoft_line;
2626 retroflat_2d_rect = (retroflat_rect_cb)retrosoft_rect;
2627 retroflat_2d_ellipse = (retroflat_ellipse_cb)retrosoft_ellipse;
2628# else
2629 retroflat_2d_line = (retroflat_line_cb)retroflat_line;
2630 retroflat_2d_rect = (retroflat_rect_cb)retroflat_rect;
2631 retroflat_2d_ellipse = (retroflat_ellipse_cb)retroflat_ellipse;
2632# endif /* RETROFLAT_SOFT_SHAPES */
2633 retroflat_2d_blit_bitmap = (retroflat_blit_bitmap_cb)retroflat_blit_bitmap;
2634 retroflat_2d_load_bitmap = (retroflat_load_bitmap_cb)retroflat_load_bitmap;
2635 retroflat_2d_create_bitmap =
2636 (retroflat_create_bitmap_cb)retroflat_create_bitmap;
2637# endif /* RETROFLAT_BMP_TEX */
2638
2639 debug_printf( 1, "retroflat: MFIX_PRECISION: %f", MFIX_PRECISION );
2640
2641 debug_printf( 1, "retroflat: allocating state (" SIZE_T_FMT " bytes)...",
2642 sizeof( struct RETROFLAT_STATE ) );
2643
2644 debug_printf( 1, "retroflat: size_t is (" SIZE_T_FMT " bytes)...",
2645 sizeof( size_t ) );
2646
2647 debug_printf( 1, "retroflat: ssize_t is (" SIZE_T_FMT " bytes)...",
2648 sizeof( ssize_t ) );
2649
2650 debug_printf( 1, "retroflat: off_t is (" SIZE_T_FMT " bytes)...",
2651 sizeof( off_t ) );
2652
2653 debug_printf( 1, "initializing global state..." );
2654
2655# ifdef RETROFLAT_STATE_ON_STACK
2656 g_retroflat_state = &g_retroflat_state_stack;
2657# else
2658 maug_malloc_test( g_retroflat_state_h, 1, sizeof( struct RETROFLAT_STATE ) );
2659
2660 maug_mlock( g_retroflat_state_h, g_retroflat_state );
2661 if( NULL == g_retroflat_state ) {
2663 "Error", "Could not lock global state!" );
2664 retval = MERROR_ALLOC;
2665 goto cleanup;
2666 }
2667# endif /* RETROFLAT_STATE_ON_STACK */
2668
2669 maug_mzero( g_retroflat_state, sizeof( struct RETROFLAT_STATE ) );
2670
2671 retroflat_heartbeat_set( 1000, 2 );
2672
2673 debug_printf( 1, "initializing platform filesystem..." );
2674 retval = mfile_plt_init();
2675 maug_cleanup_if_not_ok();
2676
2677# ifndef RETROFLAT_NO_CLI
2678
2679 debug_printf( 1, "retroflat: parsing args..." );
2680
2681 /* All platforms: add command-line args based on compile definitons. */
2682
2683 retval = maug_add_arg(
2684 MAUG_CLI_SIGIL "h", MAUG_CLI_SIGIL_SZ + 2, "Display command-line help",
2685 26, maug_cli_h, NULL );
2686
2687# if !defined( RETROFLAT_NO_SOUND ) && defined( RETROSND_ARGS )
2688 retval = maug_add_arg( MAUG_CLI_SIGIL "rsd", MAUG_CLI_SIGIL_SZ + 4,
2689 "Select MIDI device", 0, (maug_cli_cb)retrosnd_cli_rsd, args );
2690 maug_cleanup_if_not_ok();
2691 retval = maug_add_arg( MAUG_CLI_SIGIL "rsl", MAUG_CLI_SIGIL_SZ + 4,
2692 "List MIDI devices", 0, (maug_cli_cb)retrosnd_cli_rsl, args );
2693 maug_cleanup_if_not_ok();
2694# endif /* !RETROFLAT_NO_SOUND && RETROSND_ARGS */
2695
2696# ifdef RETROFLAT_SCREENSAVER
2697 retval = maug_add_arg( MAUG_CLI_SIGIL "p", MAUG_CLI_SIGIL_SZ + 2,
2698 "Preview screensaver", 0, (maug_cli_cb)retroflat_cli_p, args );
2699 maug_cleanup_if_not_ok();
2700 retval = maug_add_arg( MAUG_CLI_SIGIL "s", MAUG_CLI_SIGIL_SZ + 2,
2701 "Launch screensaver", 0, (maug_cli_cb)retroflat_cli_s, args );
2702 maug_cleanup_if_not_ok();
2703# endif /* RETROFLAT_SCREENSAVER */
2704
2705# ifdef RETROFLAT_API_PC_BIOS
2706 retval = maug_add_arg( MAUG_CLI_SIGIL "rfm", MAUG_CLI_SIGIL_SZ + 4,
2707 "Set the screen mode.", 0,
2708 (maug_cli_cb)retroflat_cli_rfm, args );
2709 maug_cleanup_if_not_ok();
2710# elif !defined( RETROFLAT_NO_CLI_SZ )
2711 retval = maug_add_arg( MAUG_CLI_SIGIL "rfs", MAUG_CLI_SIGIL_SZ + 4,
2712 "Set screen scale factor.", 0,
2713 (maug_cli_cb)retroflat_cli_rfs, args );
2714 maug_cleanup_if_not_ok();
2715 retval = maug_add_arg( MAUG_CLI_SIGIL "rfx", MAUG_CLI_SIGIL_SZ + 4,
2716 "Set the screen X position.", 0,
2717 (maug_cli_cb)retroflat_cli_rfx, args );
2718 maug_cleanup_if_not_ok();
2719 retval = maug_add_arg( MAUG_CLI_SIGIL "rfy", MAUG_CLI_SIGIL_SZ + 4,
2720 "Set the screen Y position.", 0,
2721 (maug_cli_cb)retroflat_cli_rfy, args );
2722 maug_cleanup_if_not_ok();
2723 retval = maug_add_arg( MAUG_CLI_SIGIL "rfw", MAUG_CLI_SIGIL_SZ + 4,
2724 "Set the screen width.", 0,
2725 (maug_cli_cb)retroflat_cli_rfw, args );
2726 maug_cleanup_if_not_ok();
2727 retval = maug_add_arg( MAUG_CLI_SIGIL "rfh", MAUG_CLI_SIGIL_SZ + 4,
2728 "Set the screen height.", 0,
2729 (maug_cli_cb)retroflat_cli_rfh, args );
2730 maug_cleanup_if_not_ok();
2731# endif /* !RETROFLAT_NO_CLI_SZ */
2732
2733# ifdef RETROFLAT_VDP
2734 retval = maug_add_arg( MAUG_CLI_SIGIL "vdp", MAUG_CLI_SIGIL_SZ + 4,
2735 "Pass a string of args to the VDP.", 0,
2736 (maug_cli_cb)retroflat_cli_vdp, args );
2737 maug_cleanup_if_not_ok();
2738# endif /* RETROFLAT_VDP */
2739
2740 retval = maug_add_arg( MAUG_CLI_SIGIL "rfu", MAUG_CLI_SIGIL_SZ + 4,
2741 "Unlock FPS.", 0,
2742 (maug_cli_cb)retroflat_cli_u, args );
2743 maug_cleanup_if_not_ok();
2744
2745# ifndef RETROFLAT_NO_PAD
2746 retval = maug_add_arg( MAUG_CLI_SIGIL "rfj", MAUG_CLI_SIGIL_SZ + 4,
2747 "Specify joystick ID to use.", 0,
2748 (maug_cli_cb)retroflat_cli_rfj, args );
2749 maug_cleanup_if_not_ok();
2750# endif /* !RETROFLAT_NO_PAD */
2751
2752 /* Parse command line args. */
2753 retval = maug_parse_args( argc, argv );
2754 maug_cleanup_if_not_ok();
2755
2756# endif /* !RETROFLAT_NO_CLI */
2757
2758 if( 0 == args->screen_w ) {
2759 args->screen_w = RETROFLAT_DEFAULT_SCREEN_W;
2760 debug_printf( 1, "setting arg screen_w to default: %d",
2761 args->screen_w );
2762 }
2763 if( 0 == args->screen_h ) {
2764 args->screen_h = RETROFLAT_DEFAULT_SCREEN_H;
2765 debug_printf( 1, "setting arg screen_h to default: %d",
2766 args->screen_h );
2767 }
2768 if( 0 == args->screen_scale ) {
2769 args->screen_scale = RETROFLAT_DEFAULT_SCREEN_SCALE;
2770 debug_printf( 1, "setting arg screen_scale to default: %d",
2771 args->screen_scale );
2772 }
2773 if( 0 == args->screen_colors ) {
2774 args->screen_colors = 16;
2775 debug_printf( 1, "setting arg screen_colors to default: %d",
2776 args->screen_colors );
2777 }
2778 args->joystick_id = -1;
2779
2780 if(
2782 ) {
2783 g_retroflat_state->retroflat_flags |= RETROFLAT_FLAGS_UNLOCK_FPS;
2784 }
2785
2786 debug_printf( 1, "retroflat: setting config..." );
2787
2788 /* Set the assets path. */
2789 if( NULL != args->assets_path ) {
2790 maug_mzero( g_retroflat_state->assets_path, MAUG_PATH_SZ_MAX );
2791 maug_strncpy( g_retroflat_state->assets_path,
2792 args->assets_path, MAUG_PATH_SZ_MAX - 1 );
2793 }
2794
2795# if defined( RETROFLAT_SCREENSAVER )
2796 if(
2798 (RETROFLAT_FLAGS_SCREENSAVER & args->flags)
2799 ) {
2800 g_retroflat_state->retroflat_flags |= RETROFLAT_FLAGS_SCREENSAVER;
2801 }
2802# endif /* RETROFLAT_SCREENSAVER */
2803
2804# if !defined( RETROFLAT_NO_CLI_SZ )
2805 /* Setup intended screen size. */
2806 g_retroflat_state->screen_scale = args->screen_scale;
2807 g_retroflat_state->screen_v_w = args->screen_w;
2808 g_retroflat_state->screen_v_h = args->screen_h;
2809 g_retroflat_state->screen_w = args->screen_w *
2810 g_retroflat_state->screen_scale;
2811 g_retroflat_state->screen_h = args->screen_h *
2812 g_retroflat_state->screen_scale;
2813 g_retroflat_state->screen_colors = args->screen_colors;
2814
2815 debug_printf( 3, "attempting to initialize platform with: "
2816 SIZE_T_FMT "x" SIZE_T_FMT " pixels (scaled to " SIZE_T_FMT "x" SIZE_T_FMT
2817 ") and " SIZE_T_FMT " colors",
2818 g_retroflat_state->screen_v_w, g_retroflat_state->screen_v_h,
2819 g_retroflat_state->screen_w, g_retroflat_state->screen_h,
2820 g_retroflat_state->screen_colors );
2821# endif /* !RETROFLAT_NO_CLI_SZ */
2822
2823 /* == Platform-Specific Init == */
2824
2825 retval = retroflat_init_platform( argc, argv, args );
2826 maug_cleanup_if_not_ok();
2827
2828# if defined( RETROFLAT_NO_CLI_SZ )
2829 g_retroflat_state->screen_scale = args->screen_scale;
2830 g_retroflat_state->screen_v_w = args->screen_w;
2831 g_retroflat_state->screen_v_h = args->screen_h;
2832 g_retroflat_state->screen_w = args->screen_w *
2833 g_retroflat_state->screen_scale;
2834 g_retroflat_state->screen_h = args->screen_h *
2835 g_retroflat_state->screen_scale;
2836 g_retroflat_state->screen_colors = args->screen_colors;
2837
2838 debug_printf( 3, "initialized platform with: "
2839 SIZE_T_FMT "x" SIZE_T_FMT " pixels (scaled to " SIZE_T_FMT "x" SIZE_T_FMT
2840 ") and " SIZE_T_FMT " colors",
2841 g_retroflat_state->screen_v_w, g_retroflat_state->screen_v_h,
2842 g_retroflat_state->screen_w, g_retroflat_state->screen_h,
2843 g_retroflat_state->screen_colors );
2844# endif /* RETROFLAT_NO_CLI_SZ */
2845
2846 retval = retroflat_init_input( args );
2847 maug_cleanup_if_not_ok();
2848
2849 debug_printf( 3, "screen initialized with: " SIZE_T_FMT "x" SIZE_T_FMT
2850 " pixels (scaled to " SIZE_T_FMT "x" SIZE_T_FMT
2851 ") with " SIZE_T_FMT " colors",
2852 g_retroflat_state->screen_v_w, g_retroflat_state->screen_v_h,
2853 g_retroflat_state->screen_w, g_retroflat_state->screen_h,
2854 retroflat_screen_colors() );
2855
2856 /* Setup the refresh grid, if requested, only after screen space has been
2857 * determined by the platform!
2858 */
2859 maug_cleanup_if_eq(
2860 (size_t)0, retroflat_screen_w(), SIZE_T_FMT, MERROR_GUI );
2861 maug_cleanup_if_eq(
2862 (size_t)0, retroflat_screen_h(), SIZE_T_FMT, MERROR_GUI );
2863 maug_cleanup_if_eq(
2864 (size_t)0, retroflat_screen_colors(), SIZE_T_FMT, MERROR_GUI );
2865
2866 /* This is intended as a default and can be modified by calling this macro
2867 * again later.
2868 */
2870 0, 0, retroflat_screen_w(), retroflat_screen_h() );
2871
2872#ifndef RETROFLAT_NO_VIEWPORT_REFRESH
2873 debug_printf( 1, "allocating refresh grid (%d tiles...)",
2874 g_retroflat_state->viewport.screen_tile_w *
2875 g_retroflat_state->viewport.screen_tile_h );
2876 maug_malloc_test(
2877 g_retroflat_state->viewport.refresh_grid_h,
2878 (g_retroflat_state->viewport.screen_tile_w + 2) *
2879 (g_retroflat_state->viewport.screen_tile_h + 2),
2880 sizeof( retroflat_tile_t ) );
2881#endif /* !RETROFLAT_NO_VIEWPORT_REFRESH */
2882
2883# ifdef RETROFLAT_VDP
2884# if defined( RETROFLAT_OS_UNIX )
2885 g_retroflat_state->vdp_exe = dlopen(
2886 "./" RETROFLAT_VDP_LIB_NAME ".so", RTLD_LAZY );
2887# elif defined( RETROFLAT_OS_WIN )
2888 g_retroflat_state->vdp_exe = LoadLibrary(
2889 "./" RETROFLAT_VDP_LIB_NAME ".dll" );
2890# else
2891# error "dlopen undefined!"
2892# endif /* RETROFLAT_OS_UNIX */
2893
2894 if( !(g_retroflat_state->vdp_exe) ) {
2895 error_printf( "not loading VDP" );
2896 /* Skip creating the buffer or trying to run the init proc. */
2897 goto skip_vdp;
2898 }
2899
2900 /* Create intermediary screen buffer. */
2901 debug_printf( 1, "creating VDP buffer, " SIZE_T_FMT " x " SIZE_T_FMT,
2902 g_retroflat_state->screen_v_w, g_retroflat_state->screen_v_h );
2903 g_retroflat_state->vdp_buffer =
2904 calloc( 1, sizeof( struct RETROFLAT_BITMAP ) );
2905 maug_cleanup_if_null_alloc(
2906 struct RETROFLAT_BITMAP*, g_retroflat_state->vdp_buffer );
2907 retval = retroflat_create_bitmap(
2908 g_retroflat_state->screen_v_w, g_retroflat_state->screen_v_h,
2909 g_retroflat_state->vdp_buffer, RETROFLAT_FLAGS_OPAQUE );
2910 maug_cleanup_if_not_ok();
2911
2912 debug_printf( 1, "initializing VDP..." );
2913 retval = retroflat_vdp_call( "retroflat_vdp_init" );
2914
2915skip_vdp:
2916
2917# endif /* RETROFLAT_VDP */
2918
2919# ifdef RETROFLAT_3D
2920 retro3d_platform_init();
2921# endif /* RETROFLAT_3D */
2922
2923# if !defined( RETROFLAT_NO_BLANK_INIT ) && !defined( RETROFLAT_3D )
2924 retroflat_draw_lock( NULL );
2926 NULL, RETROFLAT_COLOR_BLACK, 0, 0,
2927 retroflat_screen_w(), retroflat_screen_h(),
2929 retroflat_draw_release( NULL );
2930# endif /* !RETROFLAT_NO_BLANK_INIT */
2931
2932cleanup:
2933
2934 return retval;
2935}
2936
2937/* === */
2938
2939void retroflat_shutdown( int retval ) {
2940
2941 debug_printf( 1, "retroflat shutdown called..." );
2942
2943#ifndef RETROFLAT_NO_VIEWPORT_REFRESH
2944 if(
2945 NULL != g_retroflat_state &&
2946 (MAUG_MHANDLE)NULL != g_retroflat_state->viewport.refresh_grid_h
2947 ) {
2948 maug_mfree( g_retroflat_state->viewport.refresh_grid_h );
2949 }
2950#endif /* !RETROFLAT_NO_VIEWPORT_REFRESH */
2951
2952# if defined( RETROFLAT_VDP )
2953 if( NULL != g_retroflat_state->vdp_exe ) {
2954 retroflat_vdp_call( "retroflat_vdp_shutdown" );
2955# ifdef RETROFLAT_OS_UNIX
2956 dlclose( g_retroflat_state->vdp_exe );
2957# elif defined( RETROFLAT_OS_WIN )
2958 FreeLibrary( g_retroflat_state->vdp_exe );
2959# else
2960# error "dlclose undefined!"
2961# endif /* RETROFLAT_OS_UNIX || RETROFLAT_OS_WIN */
2962 }
2963
2964 if( NULL != g_retroflat_state->vdp_buffer ) {
2965 debug_printf( 1, "destroying VPD buffer..." );
2966 retroflat_destroy_bitmap( g_retroflat_state->vdp_buffer );
2967 free( g_retroflat_state->vdp_buffer );
2968 }
2969# endif /* RETROFLAT_VDP */
2970
2971 /* === Platform-Specific Shutdown === */
2972
2973#ifdef RETROFLAT_3D
2974 retro3d_platform_shutdown();
2975#endif /* RETROFLAT_3D */
2976
2977 retroflat_shutdown_platform( retval );
2978
2979#ifndef RETROFLAT_STATE_ON_STACK
2980 maug_munlock( g_retroflat_state_h, g_retroflat_state );
2981 maug_mfree( g_retroflat_state_h );
2982#endif /* !RETROFLAT_STATE_ON_STACK */
2983
2984}
2985
2986/* === */
2987
2988RETROFLAT_IN_KEY retroflat_repeat_input(
2989 RETROFLAT_IN_KEY key_out, struct RETROFLAT_INPUT* input,
2990 RETROFLAT_IN_KEY* prev_input, int* prev_delay
2991) {
2992
2993 /* Add a slight debounce for gamepad button repeat. */
2994 if( 0 < (*prev_delay) ) {
2995 debug_printf(
2996 RETROINPUT_TRACE_LVL,
2997 "repeat delay: %d", (*prev_delay) );
2998 (*prev_delay)--;
2999 }
3000
3001 /* If nothing else happened and repeat is enabled and a joypad button is
3002 * down, then emulate repeat for it.
3003 */
3004 if(
3005 0 == key_out &&
3007 (RETROFLAT_FLAGS_KEY_REPEAT & g_retroflat_state->retroflat_flags) &&
3008 /* There is an input to repeat. */
3009 0 != *prev_input &&
3010 /* Delay countdown reached. */
3011 0 == *prev_delay
3012 ) {
3013 key_out = *prev_input;
3014 *prev_delay = 1;
3015 debug_printf( RETROINPUT_TRACE_LVL, "repeat: %d", key_out );
3016 }
3017
3018 return key_out;
3019}
3020
3021/* === */
3022
3023ssize_t retroflat_timer_add(
3024 retroflat_ms_t at_time, retroflat_timer_cb_t cb, void* data
3025) {
3026 if( retroflat_get_ms() > at_time ) {
3027 error_printf( "timer time is in the past!" );
3028 return merror_retval_to_sz( MERROR_EXEC );
3029 }
3030
3031 if( g_retroflat_state->timers_ct + 1 < RETROFLAT_TIMER_CT_MAX ) {
3032 g_retroflat_state->timers_cb[g_retroflat_state->timers_ct] = cb;
3033 g_retroflat_state->timers_at[g_retroflat_state->timers_ct] = at_time;
3034 g_retroflat_state->timers_ct++;
3035 return g_retroflat_state->timers_ct - 1;
3036 }
3037
3038 error_printf( "too many timers!" );
3039 return merror_retval_to_sz( MERROR_OVERFLOW );
3040}
3041
3042/* === */
3043
3045 size_t i = 0;
3046 retroflat_ms_t time_now = 0;
3047
3048 time_now = retroflat_get_ms();
3049
3050 for( i = 0 ; g_retroflat_state->timers_ct > i ; i++ ) {
3051 if( g_retroflat_state->timers_at[i] <= time_now ) {
3052 g_retroflat_state->timers_cb[i](
3053 time_now, g_retroflat_state->timers_data[i] );
3054 memmove(
3055 &(g_retroflat_state->timers_cb[i]),
3056 &(g_retroflat_state->timers_cb[i + 1]),
3057 sizeof( retroflat_timer_cb_t ) *
3058 ((g_retroflat_state->timers_ct - i) - 1)
3059 );
3060 memmove(
3061 &(g_retroflat_state->timers_at[i]),
3062 &(g_retroflat_state->timers_at[i + 1]),
3063 sizeof( retroflat_ms_t ) * ((g_retroflat_state->timers_ct - i) - 1)
3064 );
3065 memmove(
3066 &(g_retroflat_state->timers_data[i]),
3067 &(g_retroflat_state->timers_data[i + 1]),
3068 sizeof( void* ) * ((g_retroflat_state->timers_ct - i) - 1)
3069 );
3070 g_retroflat_state->timers_ct--;
3071 i--;
3072 }
3073 }
3074}
3075
3076/* === */
3077
3079 struct RETROFLAT_BITMAP* bitmap,
3080 int16_t instance,
3084) {
3085 retroflat_pxxy_t trim_bottom = *d_y + *h;
3086 retroflat_pxxy_t trim_right = *d_x + *w;
3087 retroflat_pxxy_t viewport_bottom = 0;
3088 retroflat_pxxy_t viewport_right = 0;
3089 retroflat_pxxy_t viewport_left = 0;
3090 retroflat_pxxy_t viewport_top = 0;
3091
3092 if(
3093 /* On the screen, constrain to the edges of the viewport. */
3094 retroflat_screen_buffer() == bitmap &&
3095 /* Probably blitting a window or other element that can go anywhere. */
3096 RETROFLAT_INSTANCE_NULL != instance
3097 ) {
3098 viewport_left = retroflat_viewport_screen_get_x();
3099 viewport_top = retroflat_viewport_screen_get_y();
3100 viewport_bottom =
3101 (retroflat_viewport_screen_get_y() + retroflat_viewport_screen_h());
3102 viewport_right =
3103 (retroflat_viewport_screen_get_x() + retroflat_viewport_screen_w());
3104
3105 } else {
3106 /* Constrain to the edges of the arbitrary bitmap. */
3107 viewport_bottom = retroflat_bitmap_h( bitmap );
3108 viewport_right = retroflat_bitmap_w( bitmap );
3109 }
3110
3111 if( viewport_bottom < *d_y || trim_bottom < viewport_top ) {
3112#ifdef RETROFLAT_TRACE_CONSTRAIN
3113 error_printf( "attempted to blit bitmap way out of bounds at %d, %d!",
3114 *d_x, *d_y );
3115#endif /* RETROFLAT_TRACE_CONSTRAIN */
3116 return MERROR_GUI;
3117
3118 } else if( viewport_bottom <= trim_bottom ) {
3119#ifdef RETROFLAT_TRACE_CONSTRAIN
3120 error_printf(
3121 "trimming " SIZE_T_FMT " pixels to get " SIZE_T_FMT " under "
3122 SIZE_T_FMT,
3123 trim_bottom - viewport_bottom, trim_bottom, viewport_bottom );
3124#endif /* RETROFLAT_TRACE_CONSTRAIN */
3125 *h -= (trim_bottom - viewport_bottom);
3126
3127 } else if( viewport_top > *d_y ) {
3128#ifdef RETROFLAT_TRACE_CONSTRAIN
3129 error_printf(
3130 "trimming " SIZE_T_FMT " pixels to get " SIZE_T_FMT " under "
3131 SIZE_T_FMT,
3132 trim_bottom - viewport_bottom, trim_bottom, viewport_bottom );
3133#endif /* RETROFLAT_TRACE_CONSTRAIN */
3134 *h -= (viewport_top - *d_y);
3135 if( NULL != s_y ) {
3136 *s_y += (viewport_top - *d_y);
3137 }
3138 *d_y += (viewport_top - *d_y);
3139 assert( viewport_top == *d_y );
3140 }
3141
3142 if( viewport_right < *d_x || trim_right < viewport_left ) {
3143#ifdef RETROFLAT_TRACE_CONSTRAIN
3144 error_printf( "attempted to blit bitmap way out of bounds at %d, %d!",
3145 *d_x, *d_y );
3146#endif /* RETROFLAT_TRACE_CONSTRAIN */
3147 return MERROR_GUI;
3148
3149 } else if( viewport_right <= trim_right ) {
3150#ifdef RETROFLAT_TRACE_CONSTRAIN
3151 error_printf(
3152 "trimming " SIZE_T_FMT " pixels to get " SIZE_T_FMT " under "
3153 SIZE_T_FMT,
3154 trim_right - viewport_right, trim_right, viewport_right );
3155#endif /* RETROFLAT_TRACE_CONSTRAIN */
3156 *w -= (trim_right - viewport_right);
3157
3158 } else if( viewport_left > *d_x ) {
3159#ifdef RETROFLAT_TRACE_CONSTRAIN
3160 error_printf(
3161 "trimming " SIZE_T_FMT " pixels to get " SIZE_T_FMT " under "
3162 SIZE_T_FMT,
3163 trim_bottom - viewport_bottom, trim_bottom, viewport_bottom );
3164#endif /* RETROFLAT_TRACE_CONSTRAIN */
3165 *w -= (viewport_left - *d_x);
3166 if( NULL != s_x ) {
3167 *s_x += (viewport_left - *d_x);
3168 }
3169 *d_x += (viewport_left - *d_x);
3170 assert( viewport_left == *d_x );
3171 }
3172
3173 if( 0 == w && 0 == h ) {
3174 return MERROR_GUI;
3175 }
3176
3177 return MERROR_OK;
3178}
3179
3180/* === */
3181
3182# ifdef RETROFLAT_VDP
3183
3184MERROR_RETVAL retroflat_vdp_call( const char* proc_name ) {
3185 MERROR_RETVAL retval = MERROR_OK;
3187# ifdef RETROFLAT_OS_WIN
3188 char proc_name_ex[256];
3189# endif /* RETROFLAT_OS_WIN */
3190
3191 if( NULL == g_retroflat_state->vdp_exe ) {
3192 goto cleanup;
3193 }
3194
3195# ifdef RETROFLAT_OS_UNIX
3196 vdp_proc = dlsym( g_retroflat_state->vdp_exe, proc_name );
3197# elif defined( RETROFLAT_OS_WIN )
3198 /* Append a _ to the proc_name because Watcom? Windows? */
3199 maug_snprintf( proc_name_ex, 255, "%s_", proc_name );
3200 vdp_proc = (retroflat_vdp_proc_t)GetProcAddress(
3201 g_retroflat_state->vdp_exe, proc_name_ex );
3202# else
3203# error "dlsym undefined!"
3204# endif
3205 if( (retroflat_vdp_proc_t)NULL == vdp_proc ) {
3206 goto cleanup;
3207 }
3208
3209# ifdef RETROFLAT_OS_WIN
3210 retroflat_draw_lock( g_retroflat_state->vdp_buffer );
3211# endif /* RETROFLAT_OS_WIN */
3212
3213 if(
3214 /* Don't pxlock before init can set the flag! */
3215 0 == strcmp( "retroflat_vdp_flip", proc_name ) &&
3217 (RETROFLAT_VDP_FLAG_PXLOCK & g_retroflat_state->vdp_flags)
3218 ) {
3219 retroflat_vdp_lock( &(g_retroflat_state->platform.buffer) );
3220 retroflat_vdp_lock( g_retroflat_state->vdp_buffer );
3221 }
3222
3223 retval = vdp_proc( g_retroflat_state );
3224
3225 if(
3226 0 == strcmp( "retroflat_vdp_flip", proc_name ) &&
3228 (RETROFLAT_VDP_FLAG_PXLOCK & g_retroflat_state->vdp_flags)
3229 ) {
3230 retroflat_vdp_release( &(g_retroflat_state->platform.buffer) );
3231 retroflat_vdp_release( g_retroflat_state->vdp_buffer );
3232 }
3233
3234# ifdef RETROFLAT_OS_WIN
3235 retroflat_draw_release( g_retroflat_state->vdp_buffer );
3236# endif /* RETROFLAT_OS_WIN */
3237
3238cleanup:
3239 return retval;
3240}
3241
3242# endif /* RETROFLAT_VDP */
3243
3244/* === */
3245
3246#if 0
3247
3248void retroflat_cursor( struct RETROFLAT_BITMAP* target, uint8_t flags ) {
3249#if 0
3250 char mouse_str[11] = "";
3251
3252 maug_snprintf(
3253 mouse_str, 10, "%02d, %02d", g_retroflat_state->last_mouse_x, g_retroflat_state->last_mouse_y );
3254
3256 target, RETROFLAT_COLOR_BLACK,
3257 mouse_str, 10, NULL, 0, 0, 0 );
3259 target, RETROFLAT_COLOR_BLACK,
3260 g_retroflat_state->last_mouse_x - 5, g_retroflat_state->last_mouse_y - 5, 10, 10, 0 );
3261#endif
3262}
3263
3264#endif
3265
3266/* === */
3267
3268void maug_critical_error( const char* msg ) {
3270}
3271
3272/* === */
3273
3275 retroflat_proc_resize_t on_resize_in, void* data_in
3276) {
3277 g_retroflat_state->on_resize = on_resize_in;
3278 g_retroflat_state->on_resize_data = data_in;
3279}
3280
3281/* === */
3282
3283uint8_t retroflat_viewport_move_x_generic( int16_t x ) {
3284 int16_t new_world_x = g_retroflat_state->viewport.world_x + x;
3285
3286 /* Keep the viewport in the world arena. */
3287 if(
3288 0 <= new_world_x &&
3289 g_retroflat_state->viewport.world_w >= new_world_x +
3290 g_retroflat_state->viewport.screen_w
3291 ) {
3292 g_retroflat_state->viewport.world_x += x;
3293 g_retroflat_state->viewport.world_tile_x += x >> RETROFLAT_TILE_W_BITS;
3294 return 1;
3295 }
3296
3297 return 0;
3298}
3299
3300/* === */
3301
3302uint8_t retroflat_viewport_move_y_generic( int16_t y ) {
3303 int16_t new_world_y = g_retroflat_state->viewport.world_y + y;
3304
3305 /* Keep the viewport in the world arena. */
3306 if(
3307 0 <= new_world_y &&
3308 g_retroflat_state->viewport.world_h >= new_world_y +
3309 g_retroflat_state->viewport.screen_h
3310 ) {
3311 g_retroflat_state->viewport.world_y += y;
3312 g_retroflat_state->viewport.world_tile_y += y >> RETROFLAT_TILE_H_BITS;
3313 return 1;
3314 }
3315
3316 return 0;
3317}
3318
3319/* === */
3320
3321uint8_t retroflat_viewport_focus_generic(
3324) {
3325 uint8_t moved = 0,
3326 new_moved = 0;
3327 int16_t new_pt = 0;
3328
3329# define _retroflat_viewport_focus_dir( n, xy, wh, gl, pm, dir, range, speed ) \
3330 new_pt = n - retroflat_viewport_world_ ## xy(); \
3331 if( new_pt gl (retroflat_screen_ ## wh() >> 1) pm range ) { \
3332 new_moved = retroflat_viewport_move_ ## xy( \
3333 gc_retroflat_offsets8_ ## xy[RETROFLAT_DIR8_ ## dir] * speed ); \
3334 if( !moved && new_moved ) { \
3335 moved = new_moved; \
3336 } \
3337 }
3338
3339 _retroflat_viewport_focus_dir( x1, x, w, <, -, WEST, range, speed );
3340 _retroflat_viewport_focus_dir( x1, x, w, >, +, EAST, range, speed );
3341 _retroflat_viewport_focus_dir( y1, y, h, <, -, NORTH, range, speed );
3342 _retroflat_viewport_focus_dir( y1, y, h, >, +, SOUTH, range, speed );
3343
3344 return moved;
3345}
3346
3347/* === */
3348
3349#ifdef RETROFLAT_LOAD_BITMAP_GENERIC
3350
3351/* This is a generic function that uses the callback
3352 * retroflat_load_bitmap_px_cb(), which should be defined by the
3353 * platform-specific API to draw the loaded bitmap onto a native canvas.
3354 */
3355
3357 const char* filename, struct RETROFLAT_BITMAP* bmp_out, uint8_t flags
3358) {
3359 maug_path filename_path;
3360 MERROR_RETVAL retval = MERROR_OK;
3361 mfile_t bmp_file;
3362 struct MFMT_STRUCT_BMPFILE header_bmp;
3363 uint8_t bmp_flags = 0;
3364
3365 assert( NULL != bmp_out );
3366 maug_mzero( bmp_out, sizeof( struct RETROFLAT_BITMAP ) );
3367 retval = retroflat_build_filename_path(
3368 filename, RETROFLAT_BITMAP_EXT, filename_path,
3369 MAUG_PATH_SZ_MAX, flags );
3370 maug_cleanup_if_not_ok();
3371 debug_printf( 1, "retroflat: loading bitmap: %s", filename_path );
3372
3373 bmp_out->flags = flags;
3374
3375 /* Open the bitmap file. */
3376 retval = mfile_open_read( filename_path, &bmp_file );
3377 maug_cleanup_if_not_ok();
3378
3379 /* mfmt file detection system. */
3380 maug_mzero( &header_bmp, sizeof( struct MFMT_STRUCT_BMPFILE ) );
3381 header_bmp.magic[0] = 'B';
3382 header_bmp.magic[1] = 'M';
3383 header_bmp.info.sz = 40;
3384
3385 retval = mfmt_read_bmp_header(
3386 (struct MFMT_STRUCT*)&header_bmp,
3387 &bmp_file, 0, mfile_get_sz( &bmp_file ), &bmp_flags );
3388 maug_cleanup_if_not_ok();
3389
3390 retval = retroflat_create_bitmap(
3391 header_bmp.info.width, header_bmp.info.height, bmp_out, flags );
3392 maug_cleanup_if_not_ok();
3393
3394 retroflat_draw_lock( bmp_out );
3395
3396 retval = mfmt_read_bmp_px_cb(
3397 (struct MFMT_STRUCT*)&header_bmp,
3398 &bmp_file,
3399 header_bmp.px_offset,
3400 mfile_get_sz( &bmp_file ) - header_bmp.px_offset,
3401 bmp_flags,
3402 retroflat_load_bitmap_px_cb,
3403 bmp_out );
3404 maug_cleanup_if_not_ok();
3405
3406 retroflat_draw_release( bmp_out );
3407
3408cleanup:
3409
3410 mfile_close( &bmp_file );
3411
3412 return retval;
3413}
3414
3415#endif /* RETROFLAT_LOAD_BITMAP_GENERIC */
3416
3417#elif !defined( RETROVDP_C ) /* End of RETROFLT_C */
3418
3424extern MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets8_x[8];
3425extern MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets8_y[8];
3426extern MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets4_x[4];
3427extern MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets4_y[4];
3428
3431#define RETROFLAT_COLOR_TABLE_CONSTS( idx, name_l, name_u, r, g, b, cgac, cgad ) \
3432 extern MAUG_CONST RETROFLAT_COLOR SEG_MCONST RETROFLAT_COLOR_ ## name_u;
3433
3434RETROFLAT_COLOR_TABLE( RETROFLAT_COLOR_TABLE_CONSTS )
3435
3436extern MAUG_CONST char* SEG_MCONST gc_retroflat_color_names[];
3437
3438extern struct RETROFLAT_STATE* SEG_MGLOBAL g_retroflat_state;
3439
3440# if (defined( RETROFLAT_SOFT_SHAPES ) || defined( RETROFLAT_SOFT_LINES ) || \
3441 defined( RETROFLAT_3D ))
3442# define RETROSOFT_PRESENT
3443# endif
3444
3445# ifdef RETROFLAT_3D
3446# include <retro3dp.h>
3447# include <retro3d.h>
3448# include <retro3du.h>
3449# endif /* RETROFLAT_3D */
3450
3451# ifdef RETROSOFT_PRESENT
3452# include <retrosft.h>
3453# endif /* RETROFLAT_SOFT_SHAPES */
3454
3455/* Second retapis.h include for function bodies not needed. */
3456
3457/* Second retapii.h include for function bodies not needed. */
3458
3459#endif /* RETROFLT_C */
3460
3461#ifdef RETROFLAT_XPM
3462#include <retroxpm.h>
3463#endif /* RETROFLAT_XPM */
3464
3465#ifdef RETROVDP_C
3466
3467/* Declarations for VDP sources. */
3468
3469#endif /* RETROVDP_C */
3470 /* maug_retroflt */
3472
3473#endif /* RETROFLT_H */
3474
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:584
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 ...
#define RETROFLAT_INSTANCE_NULL
Pass to retroflat_blit_bitmap() instance arg if this is not a sprite (i.e. if it is a background tile...
Definition: retroflt.h:570
MERROR_RETVAL retroflat_trim_px(struct RETROFLAT_BITMAP *bitmap, int16_t instance, 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)
Chop w/h down to fit inside viewport or just fail if it's impossible.
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:729
#define RETROFLAT_PATH_SEP
The valid path separator on the target platform.
Definition: retroflt.h:750
#define RETROFLAT_FLAGS_LITERAL_PATH
Flag for retroflat_load_bitmap() to not use assets path.
Definition: retroflt.h:385
#define RETROFLAT_FLAGS_OPAQUE
Flag for retroflat_create_bitmap() or retroflat_load_bitmap() to create or load a bitmap without tran...
Definition: retroflt.h:380
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,...
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 ::RETROFLA...
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.
#define RETROFLAT_FLAGS_FILL
Flag for retroflat_rect() or retroflat_ellipse(), indicating drawn shape should be filled.
Definition: retroflt.h:374
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:462
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:514
#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:501
void retroflat_shutdown(int retval)
Deinitialize RetroFlat and its underlying layers. This should be called once at the end of the progra...
void retroflat_timer_handle()
int16_t retroflat_pxxy_t
Type used for surface pixel coordinates.
Definition: retroflt.h:879
#define retroflat_system_task()
Platform-specific task that should be called on every iteration of the generic loop....
Definition: retroflt.h:1074
void(* retroflat_loop_iter)(void *data)
Prototype for the main loop function passed to retroflat_loop().
Definition: retroflt.h:773
void retroflat_resize_v()
Platform-specific function to resize virtual screen to match physical window size.
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...
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_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).
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.
void retrosnd_set_sf_bank(const char *filename_in)
Set the name of the voice bank filename to use.
MERROR_RETVAL retrosnd_init(struct RETROFLAT_ARGS *args)
Initialize retrosnd engine.
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.
Definition: mfile.h:206
Definition: mfmt.h:124
Generic image description struct.
Definition: mfmt.h:69
Definition: retroflt.h:1051
Struct containing configuration values for a RetroFlat program.
Definition: retroflt.h:1088
char * config_path
Relative path of local config file (if not using registry).
Definition: retroflt.h:1098
char * assets_path
Relative path under which bitmap assets are stored.
Definition: retroflt.h:1096
int screen_w
Desired screen or window width in pixels.
Definition: retroflt.h:1105
int screen_h
Desired screen or window height in pixels.
Definition: retroflt.h:1112
int screen_colors
Desired colors (2, 4, or 16, for now). \TODO Implement command-line argument for this....
Definition: retroflt.h:1124
char * title
Title to set for the main program Window if applicable on the target platform.
Definition: retroflt.h:1094
int screen_y
Desired window Y position in pixels.
Definition: retroflt.h:1116
int screen_x
Desired window X position in pixels.
Definition: retroflt.h:1114
Struct passed to retroflat_poll_input() to hold return data.
Definition: retroflt.h:823
int mouse_y
Y-coordinate of the mouse pointer in pixels if the returned event is a mouse click.
Definition: retroflt.h:833
int mouse_x
X-coordinate of the mouse pointer in pixels if the returned event is a mouse click.
Definition: retroflt.h:828
Global singleton containing state for the current platform.
Definition: retroflt.h:1634
#define RETROFLAT_FLAGS_SCREENSAVER
Flag indicating the current application is running as a screensaver.
Definition: retroflt.h:438
char vdp_args[RETROFLAT_VDP_ARGS_SZ_MAX]
CLI args passed with -vdp to the RetroFlat VDP API.
Definition: retroflt.h:1672
size_t screen_h
The screen height as seen by the system, after scaling.
Definition: retroflt.h:1698
uint8_t vdp_flags
Flags set by the RetroFlat VDP API.
Definition: retroflt.h:1674
#define retroflat_heartbeat_update()
Check and update RETROFLAT_STATE::heartbeat_frame.
Definition: retroflt.h:1614
size_t screen_v_w
The screen width as seen by our program, before scaling.
Definition: retroflt.h:1687
size_t screen_colors
The number of colors the screen is capable of displaying.
Definition: retroflt.h:1700
uint8_t retroflat_flags
maug_retroflt_flags indicating current system status.
Definition: retroflt.h:1644
#define RETROFLAT_FLAGS_UNLOCK_FPS
Flag indicating FPS should not be capped.
Definition: retroflt.h:424
uint8_t heartbeat_max
When RETROFLAT_STATE::heartbeat_frame reaches this value, it will reset to 0.
Definition: retroflt.h:1727
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:1756
struct RETROFLAT_BITMAP * vdp_buffer
A buffer assembled and passed to the RetroFlat VDP API for it to modify, or NULL if no VDP is loaded.
Definition: retroflt.h:1659
uint8_t heartbeat_frame
Simple iteration loop that can be used to time e.g. perpetual sprite animations. Modify parameters wi...
Definition: retroflt.h:1722
size_t screen_w
The screen width as seen by the system, after scaling.
Definition: retroflt.h:1696
#define retroflat_heartbeat_set(len, max)
Set parameters for the RETROFLAT_STATE::heartbeat_frame.
Definition: retroflt.h:1597
void * vdp_exe
A handle for the loaded RetroFlat VDP API module.
Definition: retroflt.h:1664
RETROFLAT_COLOR_DEF palette[RETROFLAT_COLORS_SZ]
Index of available colors, initialized on platform init.
Definition: retroflt.h:1734
uint16_t heartbeat_len
Number of ms to stay on current value of RETROFLAT_STATE::heartbeat_frame before incrementing....
Definition: retroflt.h:1716
void * vdp_data
Pointer to data defined by the RetroFlat VDP API for its use.
Definition: retroflt.h:1670
size_t screen_v_h
The screen height as seen by our program, before scaling.
Definition: retroflt.h:1694
int screen_scale
Off-screen buffer bitmap.
Definition: retroflt.h:1651
#define RETROFLAT_FLAGS_RUNNING
Flag indicating that retroflat_loop() should continue executing.
Definition: retroflt.h:417
#define RETROFLAT_FLAGS_WAIT_FOR_FPS
Do not execute any more inter-frame loops until next frame.
Definition: retroflt.h:444
#define RETROFLAT_FLAGS_KEY_REPEAT
Flag indicating keyboard repeat is enabled.
Definition: retroflt.h:431
The viewport data struct.
Definition: retroflt.h:1149
retroflat_pxxy_t world_x
The X offset, in pixels, of the viewport on the world tilemap. Should only be retrieved through retro...
Definition: retroflt.h:1167
#define retroflat_viewport_screen_h()
Return the height of the viewport in pixels.
Definition: retroflt.h:1462
retroflat_tile_t * refresh_grid
A grid of tile values representing the last-drawn values on-screen.
Definition: retroflt.h:1240
retroflat_pxxy_t screen_h
Viewport height in pixels. Should only be retrieved through retroflat_viewport_screen_w() and set thr...
Definition: retroflt.h:1197
#define retroflat_viewport_screen_w()
Return the width of the viewport in pixels.
Definition: retroflt.h:1455
retroflat_pxxy_t screen_h_remainder
Difference between viewport height and screen height in pixels. Should only be retrieved through retr...
Definition: retroflt.h:1211
retroflat_pxxy_t screen_y
Y position of the viewport in real screen memory in pixels. Should only be retrieved through retrofla...
Definition: retroflt.h:1161
retroflat_pxxy_t screen_x
X position of the viewport in real screen memory in pixels. Should only be retrieved through retrofla...
Definition: retroflt.h:1155
int16_t screen_tile_w
The number of tiles across that fit in the viewport. Should only be retrieved through retroflat_viewp...
Definition: retroflt.h:1218
retroflat_pxxy_t world_w
The width of the entire world tilemap in pixels. Should only be retrieved through retroflat_viewport_...
Definition: retroflt.h:1179
#define retroflat_viewport_set_pos_size(x_px, y_px, w_px, h_px)
Set the pixel width and height of the viewport, as well as some other dependent values frequently use...
Definition: retroflt.h:1503
retroflat_pxxy_t world_y
The Y offset, in pixels, of the viewport on the world tilemap. Should only be retrieved through retro...
Definition: retroflt.h:1173
retroflat_pxxy_t screen_w_remainder
Difference between viewport width and screen width in pixels. Should only be retrieved through retrof...
Definition: retroflt.h:1204
retroflat_pxxy_t screen_w
Viewport width in pixels. Should only be retrieved through retroflat_viewport_screen_w() and set thro...
Definition: retroflt.h:1191
int16_t screen_tile_h
The number of tiles high that fit in the viewport. Should only be retrieved through retroflat_viewpor...
Definition: retroflt.h:1225
retroflat_pxxy_t world_h
The height of the entire world tilemap in pixels. Should only be retrieved through retroflat_viewport...
Definition: retroflt.h:1185