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_SZ 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_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
450#define RETROFLAT_FLAGS_USE_GXC 0x40
451
458
462#define RETROFLAT_MSG_FLAG_TYPE_MASK 0x07
463
468#define RETROFLAT_MSG_FLAG_ERROR 0x01
469
475#define RETROFLAT_MSG_FLAG_INFO 0x02
476
482#define RETROFLAT_MSG_FLAG_WARNING 0x04
483 /* maug_retroflt_msg_api */
485
486struct RETROFLAT_STATE;
487
499
507#define RETROFLAT_VDP_FLAG_PXLOCK 0x01
508
521 /* maug_retroflt_vdp */
523
524typedef MERROR_RETVAL (*retroflat_proc_resize_t)(
525 uint16_t new_w, uint16_t new_h, void* data );
526
531
532#define RETROSND_ARGS_FLAG_LIST_DEVS 0x01
533
535
561
565#define RETROFLAT_FLAGS_LOCK 0x08
566
567#define RETROFLAT_FLAGS_SCREEN_LOCK 0x02
568
569#define RETROFLAT_FLAGS_BITMAP_RO 0x04
570
576#define RETROFLAT_INSTANCE_NULL (0)
577
582#define retroflat_instance_tile( instance ) \
583 (instance * -1)
584
589#ifndef RETROFLAT_BITMAP_EXT
590# define RETROFLAT_BITMAP_EXT "bmp"
591#endif /* !RETROFLAT_BITMAP_EXT */
592
593#ifndef RETROFLAT_OPENGL_BPP
594# define RETROFLAT_OPENGL_BPP 32
595#endif /* !RETROFLAT_OPENGL_BPP */
596
597#ifndef RETROFLAT_TILE_W
598# define RETROFLAT_TILE_W 16
599#endif /* !RETROFLAT_TILE_W */
600
601#ifndef RETROFLAT_TILE_W_BITS
602# define RETROFLAT_TILE_W_BITS 4
603#endif /* !RETROFLAT_TILE_W_BITS */
604
605#ifndef RETROFLAT_TILE_H
606# define RETROFLAT_TILE_H 16
607#endif /* !RETROFLAT_TILE_H */
608
609#ifndef RETROFLAT_TILE_H_BITS
610# define RETROFLAT_TILE_H_BITS 4
611#endif /* !RETROFLAT_TILE_H_BITS */
612
613/* Transparency background color: black by default, to match Allegro. */
614#ifndef RETROFLAT_TXP_R
620# define RETROFLAT_TXP_R 0x00
621#endif /* !RETROFLAT_TXP_R */
622
623#ifndef RETROFLAT_TXP_G
629# define RETROFLAT_TXP_G 0x00
630#endif /* !RETROFLAT_TXP_G */
631
632#ifndef RETROFLAT_TXP_B
638# define RETROFLAT_TXP_B 0x00
639#endif /* !RETROFLAT_TXP_B */
640
641#ifndef RETROFLAT_TXP_PAL_IDX
642# define RETROFLAT_TXP_PAL_IDX 0
643#endif /* !RETROFLAT_TXP_PAL_IDX */
644 /* maug_retroflt_bitmap */
646
647#ifndef RETROFLAT_DEFAULT_SCREEN_W
648# define RETROFLAT_DEFAULT_SCREEN_W 320
649#endif /* !RETROFLAT_DEFAULT_SCREEN_W */
650
651#ifndef RETROFLAT_DEFAULT_SCREEN_H
652# define RETROFLAT_DEFAULT_SCREEN_H 200
653#endif /* !RETROFLAT_DEFAULT_SCREEN_H */
654
655#ifndef RETROFLAT_DEFAULT_SCREEN_SCALE
656# define RETROFLAT_DEFAULT_SCREEN_SCALE 1
657#endif /* !RETROFLAT_DEFAULT_SCREEN_SCALE */
658
659#define retroflat_on_resize( w, h ) \
660 g_retroflat_state->screen_w = w; \
661 g_retroflat_state->screen_h = h;
662
667
668#ifndef RETROFLAT_LINE_THICKNESS
673# define RETROFLAT_LINE_THICKNESS 1
674#endif /* !RETROFLAT_LINE_THICKNESS */
675
676#define RETROFLAT_PI 3.14159
677 /* maug_retroflt_drawing */
679
684
685#ifndef RETROFLAT_FPS
690# define RETROFLAT_FPS 30
691#endif /* !RETROFLAT_FPS */
692
693#define retroflat_fps_next() (1000 / RETROFLAT_FPS)
694
695#ifndef RETROFLAT_WINDOW_CLASS
700# define RETROFLAT_WINDOW_CLASS "RetroFlatWindowClass"
701#endif /* !RETROFLAT_WINDOW_CLASS */
702
703#ifndef RETROFLAT_WIN_FRAME_TIMER_ID
708# define RETROFLAT_WIN_FRAME_TIMER_ID 6001
709#endif /* !RETROFLAT_WIN_FRAME_TIMER_ID */
710
711#ifndef RETROFLAT_WIN_LOOP_TIMER_ID
716# define RETROFLAT_WIN_LOOP_TIMER_ID 6002
717#endif /* !RETROFLAT_WIN_LOOP_TIMER_ID */
718
719#ifndef RETROFLAT_MSG_MAX
724# define RETROFLAT_MSG_MAX 4096
725#endif /* !RETROFLAT_MSG_MAX */
726
727#ifndef RETROFLAT_TITLE_MAX
728# define RETROFLAT_TITLE_MAX 255
729#endif /* !RETROFLAT_TITLE_MAX */
730
731#ifndef RETROFLAT_VDP_ARGS_SZ_MAX
735# define RETROFLAT_VDP_ARGS_SZ_MAX 255
736#endif /* !RETROFLAT_VDP_ARGS_SZ_MAX */
737
738#if defined( RETROFLAT_API_SDL2 )
739# if !defined( NO_RETROFLAT_RESIZABLE )
740# define RETROFLAT_WIN_FLAGS SDL_WINDOW_RESIZABLE
741# else
742# define RETROFLAT_WIN_FLAGS 0
743# endif /* !NO_RETROFLAT_RESIZABLE */
744#endif /* RETROFLAT_API_SDL2 */
745
746#if defined( RETROFLAT_API_SDL1 )
747# define RETROFLAT_SDL_CC_FLAGS (SDL_RLEACCEL | SDL_SRCCOLORKEY)
748#elif defined( RETROFLAT_API_SDL2 )
749# define RETROFLAT_SDL_CC_FLAGS (SDL_TRUE)
750#endif /* RETROFLAT_API_SDL1 || RETROFLAT_API_SDL2 */
751
752#ifdef RETROFLAT_OS_DOS
753# define RETROFLAT_PATH_SEP '\\'
754#else
756# define RETROFLAT_PATH_SEP '/'
757#endif /* RETROFLAT_OS_DOS */
758
759#ifndef RETROFLAT_BMP_COLORS_SZ_MAX
760# define RETROFLAT_BMP_COLORS_SZ_MAX 256
761#endif /* !RETROFLAT_BMP_COLORS_SZ_MAX */
762
763#ifndef RETROFLAT_TIMER_CT_MAX
764# define RETROFLAT_TIMER_CT_MAX 10
765#endif /* !RETROFLAT_TIMER_CT_MAX */
766 /* maug_retroflt_compiling */
768
769#define retroflat_wait_for_frame() \
770 (g_retroflat_state->retroflat_flags |= RETROFLAT_FLAGS_WAIT_FOR_FPS)
771
772#define retroflat_is_waiting_for_frame() \
773 (RETROFLAT_FLAGS_WAIT_FOR_FPS == \
774 (g_retroflat_state->retroflat_flags & RETROFLAT_FLAGS_WAIT_FOR_FPS))
775
779typedef void (*retroflat_loop_iter)(void* data);
780
786
790#define retroflat_buffer_bksp( buffer, buffer_cur, buffer_sz ) \
791 if( 0 < buffer_cur ) { \
792 if( buffer_cur < buffer_sz ) { \
793 memmove( \
794 &(buffer[(buffer_cur) - 1]), \
795 &(buffer[buffer_cur]), \
796 (buffer_sz) - (buffer_cur) ); \
797 } \
798 buffer_cur--; \
799 buffer_sz--; \
800 buffer[buffer_sz] = '\0'; \
801 }
802
806#define retroflat_buffer_insert( c, buffer, buffer_cur, buffer_sz, buffer_mx ) \
807 if( buffer_sz + 1 < buffer_mx ) { \
808 if( buffer_cur < buffer_sz ) { \
809 memmove( \
810 &(buffer[(buffer_cur) + 1]), \
811 &(buffer[buffer_cur]), \
812 (buffer_sz) - (buffer_cur) ); \
813 } \
814 buffer[buffer_cur] = c; \
815 buffer_cur++; \
816 buffer_sz++; \
817 buffer[buffer_sz] = '\0'; \
818 }
819
820#define RETROFLAT_INPUT_MOD_SHIFT 0x01
821
822#define RETROFLAT_INPUT_MOD_ALT 0x02
823
824#define RETROFLAT_INPUT_MOD_CTRL 0x04
825
826#define RETROFLAT_INPUT_FORCE_UPPER 0x08
827
840 uint8_t key_flags;
841};
842 /* maug_retroflt_input */
844
851
852typedef int8_t retroflat_dir4_t;
853
854typedef int8_t retroflat_dir8_t;
855
856#define RETROFLAT_DIR4_NONE (-1)
857#define RETROFLAT_DIR4_NORTH 0
858#define RETROFLAT_DIR4_EAST 1
859#define RETROFLAT_DIR4_SOUTH 2
860#define RETROFLAT_DIR4_WEST 3
861
862#define RETROFLAT_DIR8_NONE (-1)
863#define RETROFLAT_DIR8_NORTH 0
864#define RETROFLAT_DIR8_EAST 2
865#define RETROFLAT_DIR8_SOUTH 4
866#define RETROFLAT_DIR8_WEST 6
867
868#define retroflat_dir4_rotate_cw( dir ) \
869 ((dir + 1) % 4)
870
871#define retroflat_dir8_reverse( dir ) \
872 ((dir + 4) % 8)
873
874#define retroflat_dir8_bounce( dir ) \
875 ((dir + 2) % 8)
876 /* maug_retroflt_dir */
878
885typedef int16_t retroflat_pxxy_t;
886
887#define PXXY_FMT "%d"
888
889#define PXXY_MAX INT16_MAX
890
891struct RETROFLAT_ARGS;
892
893#ifndef RETRO2D_TRACE_LVL
894# define RETRO2D_TRACE_LVL 0
895#endif /* !RETRO2D_TRACE_LVL */
896
897#ifndef RETRO2D_DRAW_TRACE_LVL
898# define RETRO2D_DRAW_TRACE_LVL 0
899#endif /* !RETRO2D_DRAW_TRACE_LVL */
900
901#ifndef RETRO2D_LOCK_TRACE_LVL
902# define RETRO2D_LOCK_TRACE_LVL 0
903#endif /* !RETRO2D_LOCK_TRACE_LVL */
904
905#ifndef RETROFLAT_NO_SOUND
906
934
935#ifndef RETROSND_TRACE_LVL
936# define RETROSND_TRACE_LVL 0
937#endif /* !RETROSND_TRACE_LVL */
938
939#ifndef RETROSND_REG_TRACE_LVL
940# define RETROSND_REG_TRACE_LVL 0
941#endif /* !RETROSND_REG_TRACE_LVL */
942
948
953#define RETROSND_FLAG_INIT 0x01
954 /* maug_retrosnd_flags */
956
957#define RETROSND_VOICE_BREATH 122
958
959#define RETROSND_VOICE_SEASHORE 123
960
961#define RETROSND_VOICE_BIRD_TWEET 124
962
963#define RETROSND_VOICE_PHONE_RING 125
964
965#define RETROSND_VOICE_HELICOPTER 126
966
967#define RETROSND_VOICE_APPLAUSE 127
968
973#define RETROSND_VOICE_GUNSHOT 128
974
975#define RETROSND_CHANNEL_CT 8
976
986
990void retrosnd_set_sf_bank( const char* filename_in );
991
992void retrosnd_midi_set_voice( uint8_t channel, uint8_t voice );
993
994void retrosnd_midi_set_control( uint8_t channel, uint8_t key, uint8_t val );
995
996void retrosnd_midi_note_on( uint8_t channel, uint8_t pitch, uint8_t vel );
997
998void retrosnd_midi_note_off( uint8_t channel, uint8_t pitch, uint8_t vel );
999
1000MERROR_RETVAL retrosnd_midi_play_smf( const char* filename );
1001
1002uint8_t retrosnd_midi_is_playing_smf();
1003
1004void retrosnd_shutdown();
1005 /* maug_retrosnd */
1007
1008#endif /* !RETROFLAT_NO_SOUND */
1009
1010/* === Platform-specific APIs === */
1011
1012/* The first call to these headers should just establish definitions (macros, defines, prototypes,
1013 * typedefs, etc). The later call below should then define function bodies.
1014 */
1015#ifndef RETROFLAT_NO_SOUND
1016# include <retapis.h>
1017#endif /* !RETROFLAT_NO_SOUND */
1018#include <retapii.h>
1019
1020/* === End platform-specific APIs === */
1021
1026
1027# if defined( RETROFLAT_NO_KEYBOARD )
1028# define retroflat_case_key( key, pad ) case pad:
1029# define retroflat_or_key( input, key, pad ) ((input) == (pad))
1030# elif defined( RETROFLAT_NO_PAD )
1031# define retroflat_case_key( key, pad ) case key:
1032# define retroflat_or_key( input, key, pad ) ((input) == (key))
1033# else
1041# define retroflat_case_key( key, pad ) case pad: case key:
1042# define retroflat_or_key( input, key, pad ) \
1043 (((input) == (pad)) || ((input) == (key)))
1044# endif
1045 /* maug_retroflt_input */
1047
1048/* === OS-Specific Includes and Defines === */
1049
1050#if defined( RETROFLAT_OS_WIN ) && !defined( MAUG_WINDOWS_H )
1051# include <windows.h>
1052# define MAUG_WINDOWS_H
1053#endif /* !MAUG_WINDOWS_H */
1054
1055#if defined( RETROFLAT_BMP_TEX ) || defined( DOCUMENTATION )
1056
1058 uint8_t flags;
1059 MAUG_MHANDLE bytes_h;
1060 uint8_t* bytes;
1061 uint32_t bpp;
1062 uint32_t sz;
1063 uint8_t* px;
1064 uint32_t id;
1065 size_t w;
1066 size_t h;
1067};
1068
1069#endif /* RETROFLAT_BMP_TEX */
1070
1071/* TODO: Migrate all platform-specific parts below to retapid.h. */
1072#include <retapid.h>
1073
1074#ifndef retroflat_system_task
1080# define retroflat_system_task()
1081#endif /* !retroflat_system_task */
1082
1083typedef maug_ms_t retroflat_ms_t;
1084
1085typedef void (*retroflat_timer_cb_t)( retroflat_ms_t time, void* data );
1086
1087#include "retrom2d.h"
1088
1089/* === Structures === */
1090
1091/* TODO: Break the args into API-specific headers. */
1092
1095 uint8_t flags;
1100 char* title;
1123 int screen_scale;
1131 int joystick_id;
1132 struct RETROFLAT_PLATFORM_ARGS platform;
1133# ifndef RETROFLAT_NO_SOUND
1134 struct RETROFLAT_SOUND_ARGS sound;
1135# endif /* !RETROFLAT_NO_SOUND */
1136};
1137
1148
1249
1250# define retroflat_screen_colors() (g_retroflat_state->screen_colors)
1251
1252#ifndef DOCUMENTATION
1253
1254# define retroflat_viewport_world_x_generic() \
1255 (g_retroflat_state->viewport.world_x)
1256
1257# define retroflat_viewport_world_y_generic() \
1258 (g_retroflat_state->viewport.world_y)
1259
1260# define retroflat_viewport_world_tile_x_generic() \
1261 (g_retroflat_state->viewport.world_tile_x)
1262
1263# define retroflat_viewport_world_tile_y_generic() \
1264 (g_retroflat_state->viewport.world_tile_y)
1265
1266# define retroflat_viewport_world_w_generic() \
1267 (g_retroflat_state->viewport.world_w)
1268
1269# define retroflat_viewport_world_h_generic() \
1270 (g_retroflat_state->viewport.world_h)
1271
1272# define retroflat_viewport_screen_tile_w_generic() \
1273 (g_retroflat_state->viewport.screen_tile_w)
1274
1275# define retroflat_viewport_screen_tile_h_generic() \
1276 (g_retroflat_state->viewport.screen_tile_h)
1277
1278# define retroflat_viewport_screen_w_generic() \
1279 (g_retroflat_state->viewport.screen_w)
1280
1281# define retroflat_viewport_screen_h_generic() \
1282 (g_retroflat_state->viewport.screen_h)
1283
1284# define retroflat_viewport_screen_w_remainder_generic() \
1285 (g_retroflat_state->viewport.screen_w_remainder)
1286
1287# define retroflat_viewport_screen_h_remainder_generic() \
1288 (g_retroflat_state->viewport.screen_h_remainder)
1289
1290# define retroflat_viewport_set_world_generic( w, h ) \
1291 debug_printf( 1, "setting viewport size to %d x %d...", \
1292 (int16_t)(w), (int16_t)(h) ); \
1293 (g_retroflat_state->viewport.world_w) = w; \
1294 (g_retroflat_state->viewport.world_h) = h;
1295
1296# define retroflat_viewport_set_world_pos_generic( x, y ) \
1297 debug_printf( 1, "setting viewport world pos to %d, %d...", x, y ); \
1298 (g_retroflat_state->viewport.world_x) = x; \
1299 (g_retroflat_state->viewport.world_y) = y; \
1300 (g_retroflat_state->viewport.world_tile_x) = (x) >> RETROFLAT_TILE_W_BITS; \
1301 (g_retroflat_state->viewport.world_tile_y) = (y) >> RETROFLAT_TILE_H_BITS;
1302
1303# define retroflat_viewport_set_pos_size_generic( x_px, y_px, w_px, h_px ) \
1304 g_retroflat_state->viewport.screen_x = (x_px); \
1305 g_retroflat_state->viewport.screen_y = (y_px); \
1306 g_retroflat_state->viewport.screen_tile_w = \
1307 ((w_px) / RETROFLAT_TILE_W); \
1308 g_retroflat_state->viewport.screen_tile_h = \
1309 ((h_px) / RETROFLAT_TILE_H); \
1310 /* We're not adding the extra room here since this won't be used for
1311 * indexing or allocation but rather pixel detection.
1312 */ \
1313 g_retroflat_state->viewport.screen_w = \
1314 ((w_px) / RETROFLAT_TILE_W) * RETROFLAT_TILE_W; \
1315 g_retroflat_state->viewport.screen_h = \
1316 ((h_px) / RETROFLAT_TILE_H) * RETROFLAT_TILE_H; \
1317 g_retroflat_state->viewport.screen_w_remainder = \
1318 (x_px) + (w_px) - g_retroflat_state->viewport.screen_w; \
1319 g_retroflat_state->viewport.screen_h_remainder = \
1320 (y_px) + (h_px) - g_retroflat_state->viewport.screen_h;
1321
1322#ifndef RETROFLAT_NO_VIEWPORT_REFRESH
1323
1324# define retroflat_viewport_lock_refresh_generic() \
1325 if( NULL == g_retroflat_state->viewport.refresh_grid ) { \
1326 maug_mlock( \
1327 g_retroflat_state->viewport.refresh_grid_h, \
1328 g_retroflat_state->viewport.refresh_grid ); \
1329 maug_cleanup_if_null_lock( retroflat_tile_t*, \
1330 g_retroflat_state->viewport.refresh_grid ); \
1331 }
1332
1333# define retroflat_viewport_unlock_refresh_generic() \
1334 if( NULL != g_retroflat_state->viewport.refresh_grid ) { \
1335 maug_munlock( \
1336 g_retroflat_state->viewport.refresh_grid_h, \
1337 g_retroflat_state->viewport.refresh_grid ); \
1338 }
1339
1340# define _retroflat_viewport_refresh_tile_x( x_px ) \
1341 (((x_px) + RETROFLAT_TILE_W) >> RETROFLAT_TILE_W_BITS)
1342
1343# define _retroflat_viewport_refresh_tile_y( y_px ) \
1344 (((y_px) + RETROFLAT_TILE_H) >> RETROFLAT_TILE_H_BITS)
1345
1346# define retroflat_viewport_set_refresh_generic( x_px, y_px, tid ) \
1347 assert( NULL != g_retroflat_state->viewport.refresh_grid ); \
1348 if( \
1349 /* Expand the range by -1 to account for just off-screen tile. */ \
1350 -(RETROFLAT_TILE_W) <= x_px && -(RETROFLAT_TILE_H) <= y_px && \
1351 retroflat_screen_w() > x_px && \
1352 retroflat_screen_h() > y_px \
1353 ) { \
1354 assert( 0 < g_retroflat_state->viewport.screen_tile_w ); \
1355 assert( 0 <= (((y_px) + RETROFLAT_TILE_H) >> RETROFLAT_TILE_H_BITS) ); \
1356 assert( 0 <= (((x_px) + RETROFLAT_TILE_W) >> RETROFLAT_TILE_W_BITS) ); \
1357 g_retroflat_state->viewport.refresh_grid[ \
1358 /* Add +1 tile to make off-screen "-1" tile positive. */ \
1359 ((_retroflat_viewport_refresh_tile_y( y_px ) + 1) * \
1360 (g_retroflat_state->viewport.screen_tile_w + 2)) + \
1361 (_retroflat_viewport_refresh_tile_x( x_px ) + 1)] = tid; \
1362 }
1363
1364# define retroflat_viewport_tile_is_stale( x_px, y_px, tile_id ) \
1365 ((tile_id) != \
1366 g_retroflat_state->viewport.refresh_grid[ \
1367 ((_retroflat_viewport_refresh_tile_y( y_px ) + 1) * \
1368 (g_retroflat_state->viewport.screen_tile_w + 2)) + \
1369 (_retroflat_viewport_refresh_tile_x( x_px ) + 1)])
1370
1371#endif /* !RETROFLAT_NO_VIEWPORT_REFRESH */
1372
1373uint8_t retroflat_viewport_move_x_generic( int16_t x );
1374
1375uint8_t retroflat_viewport_move_y_generic( int16_t y );
1376
1377uint8_t retroflat_viewport_focus_generic(
1379 retroflat_pxxy_t range, retroflat_pxxy_t speed );
1380
1381# define retroflat_viewport_screen_x_generic( world_x ) \
1382 (g_retroflat_state->viewport.screen_x + \
1383 ((world_x) - retroflat_viewport_world_x()))
1384
1385# define retroflat_viewport_screen_y_generic( world_y ) \
1386 (g_retroflat_state->viewport.screen_y + \
1387 ((world_y) - retroflat_viewport_world_y()))
1388
1389# define retroflat_viewport_screen_get_x_generic() \
1390 (g_retroflat_state->viewport.screen_x)
1391
1392# define retroflat_viewport_screen_get_y_generic() \
1393 (g_retroflat_state->viewport.screen_y)
1394
1395#endif /* !DOCUMENTATION */
1396
1397#if defined( RETROFLAT_SOFT_VIEWPORT ) || defined( DOCUMENTATION )
1398
1399# ifndef RETROFLAT_NO_VIEWPORT_REFRESH
1400 /* These clamp world coordinates to tile borders to allow refresh grid to
1401 * function properly (smooth-scrolling tiles will always be in motion).
1402 */
1403
1408# define retroflat_viewport_world_x() \
1409 ((retroflat_viewport_world_x_generic() \
1410 >> RETROFLAT_TILE_W_BITS) << RETROFLAT_TILE_W_BITS)
1411
1416# define retroflat_viewport_world_y() \
1417 ((retroflat_viewport_world_y_generic() \
1418 >> RETROFLAT_TILE_H_BITS) << RETROFLAT_TILE_H_BITS)
1419# else
1420# define retroflat_viewport_world_x() retroflat_viewport_world_x_generic()
1421# define retroflat_viewport_world_y() retroflat_viewport_world_y_generic()
1422#endif /* !RETROFLAT_NO_VIEWPORT_REFRESH */
1423
1424# define retroflat_viewport_world_tile_x() \
1425 retroflat_viewport_world_tile_x_generic()
1426# define retroflat_viewport_world_tile_y() \
1427 retroflat_viewport_world_tile_y_generic()
1428
1433# define retroflat_viewport_world_w() \
1434 retroflat_viewport_world_w_generic()
1435
1440# define retroflat_viewport_world_h() \
1441 retroflat_viewport_world_h_generic()
1442
1447# define retroflat_viewport_screen_tile_w() \
1448 retroflat_viewport_screen_tile_w_generic()
1449
1454# define retroflat_viewport_screen_tile_h() \
1455 retroflat_viewport_screen_tile_h_generic()
1456
1461# define retroflat_viewport_screen_w() \
1462 retroflat_viewport_screen_w_generic()
1463
1468# define retroflat_viewport_screen_h() \
1469 retroflat_viewport_screen_h_generic()
1470
1476# define retroflat_viewport_screen_w_remainder() \
1477 retroflat_viewport_screen_w_remainder_generic()
1478
1484# define retroflat_viewport_screen_h_remainder() \
1485 retroflat_viewport_screen_h_remainder_generic()
1486
1494# define retroflat_viewport_set_world( w, h ) \
1495 retroflat_viewport_set_world_generic( w, h )
1496
1501# define retroflat_viewport_set_world_pos( x, y ) \
1502 retroflat_viewport_set_world_pos_generic( x, y )
1503
1509# define retroflat_viewport_set_pos_size( x_px, y_px, w_px, h_px ) \
1510 retroflat_viewport_set_pos_size_generic( x_px, y_px, w_px, h_px )
1511
1512#ifndef RETROFLAT_NO_VIEWPORT_REFRESH
1513
1521# define retroflat_viewport_lock_refresh() \
1522 retroflat_viewport_lock_refresh_generic()
1523
1531# define retroflat_viewport_unlock_refresh() \
1532 retroflat_viewport_unlock_refresh_generic()
1533
1545# define retroflat_viewport_set_refresh( x, y, tid ) \
1546 retroflat_viewport_set_refresh_generic( x, y, tid )
1547
1548#endif /* !RETROFLAT_NO_VIEWPORT_REFRESH */
1549
1562# define retroflat_viewport_focus( x1, y1, range, speed ) \
1563 retroflat_viewport_focus_generic( x1, y1, range, speed )
1564
1569# define retroflat_viewport_screen_x( world_x ) \
1570 retroflat_viewport_screen_x_generic( world_x )
1571
1576# define retroflat_viewport_screen_y( world_y ) \
1577 retroflat_viewport_screen_y_generic( world_y )
1578
1579# define retroflat_viewport_screen_get_x() \
1580 retroflat_viewport_screen_get_x_generic()
1581
1582# define retroflat_viewport_screen_get_y() \
1583 retroflat_viewport_screen_get_y_generic()
1584
1585# ifndef RETROFLAT_VIEWPORT_OVERRIDE_MOVE
1586# define retroflat_viewport_move_x( x ) \
1587 retroflat_viewport_move_x_generic( x )
1588
1589# define retroflat_viewport_move_y( y ) \
1590 retroflat_viewport_move_y_generic( y )
1591# endif /* !RETROFLAT_VIEWPORT_OVERRIDE_MOVE */
1592
1593#endif /* RETROFLAT_SOFT_VIEWPORT || DOCUMENTATION */
1594
1596
1603#define retroflat_heartbeat_set( len, max ) \
1604 g_retroflat_state->heartbeat_max = max; \
1605 g_retroflat_state->heartbeat_len = len;
1606
1611#define retroflat_heartbeat() (g_retroflat_state->heartbeat_frame)
1612
1620#define retroflat_heartbeat_update() \
1621 /* Update the heartbeat animation frame. */ \
1622 if( g_retroflat_state->heartbeat_next <= retroflat_get_ms() ) { \
1623 g_retroflat_state->heartbeat_frame++; \
1624 if( \
1625 g_retroflat_state->heartbeat_frame >= \
1626 g_retroflat_state->heartbeat_max \
1627 ) { \
1628 g_retroflat_state->heartbeat_frame = 0; \
1629 } \
1630 g_retroflat_state->heartbeat_next = \
1631 retroflat_get_ms() + g_retroflat_state->heartbeat_len; \
1632 }
1633
1641 /* TODO: Set this up in the initialization function! */
1642 /* TODO: We probably need more of these. */
1643 size_t sz;
1644 size_t offset_pal;
1645 size_t offset_tex_pal;
1646
1647 void* loop_data;
1648 MERROR_RETVAL retval;
1651 maug_path config_path;
1652 maug_path assets_path;
1653 maug_path saves_path;
1654
1656 /* struct RETROFLAT_BITMAP buffer; */
1658
1659# if defined( RETROFLAT_VDP ) || defined( DOCUMENTATION ) || \
1660defined( RETROVDP_C )
1665 struct RETROFLAT_BITMAP* vdp_buffer;
1666# ifdef RETROFLAT_OS_WIN
1667 HMODULE vdp_exe;
1668# else
1670 void* vdp_exe;
1671# endif /* RETROFLAT_OS_WIN */
1680 uint8_t vdp_flags;
1681# endif /* RETROFLAT_VDP || DOCUMENTATION || RETROVDP_C */
1682
1683 /* These are used by VDP so should be standardized/not put in plat-spec! */
1684
1685 struct RETROFLAT_VIEWPORT viewport;
1686
1702 size_t screen_w;
1704 size_t screen_h;
1707
1708 /* WARNING: The VDP requires the state specifier to be the same size
1709 * as the one it was compiled for! Do not modify above here!
1710 */
1711
1712 /* TODO: Put these in a platform-specific struct of some kind to maintain
1713 * consistent state struct size for VDP?
1714 */
1715
1716 retroflat_ms_t heartbeat_next;
1734
1735 retroflat_proc_resize_t on_resize;
1736 void* on_resize_data;
1737
1738#ifndef RETROFLAT_BMP_TEX
1740 RETROFLAT_COLOR_DEF palette[RETROFLAT_COLORS_SZ];
1741#endif /* !RETROFLAT_BMP_TEX */
1742
1743 retroflat_loop_iter loop_iter;
1744 retroflat_loop_iter frame_iter;
1745
1746 struct RETROFLAT_PLATFORM platform;
1747
1748# if defined( RETROFLAT_BMP_TEX )
1749 /* This allows native colors to be used for things like glColor3fv while
1750 * these colors are used to manipulate textures passed through
1751 * retroflat_bitmap_*().
1752 */
1753 RETROFLAT_TEX_COLOR_DEF tex_palette[RETROFLAT_COLORS_SZ];
1754# endif /* RETROFLAT_BMP_TEX */
1755
1756 struct RETROFLAT_INPUT_STATE input;
1757
1762 retroflat_timer_cb_t timers_cb[RETROFLAT_TIMER_CT_MAX];
1763 retroflat_ms_t timers_at[RETROFLAT_TIMER_CT_MAX];
1764 void* timers_data[RETROFLAT_TIMER_CT_MAX];
1765 size_t timers_ct;
1766
1767# ifndef RETROFLAT_NO_SOUND
1768 struct RETROFLAT_SOUND_STATE sound;
1769# endif /* !RETROFLAT_NO_SOUND */
1770};
1771
1772/* === Translation Module === */
1773
1774/* Declare the prototypes so that internal functions can call each other. */
1775
1776# ifdef retroflat_loop
1777MERROR_RETVAL retroflat_loop_generic(
1778 retroflat_loop_iter frame_iter, retroflat_loop_iter loop_iter, void* data );
1779# else
1786 retroflat_loop_iter frame_iter, retroflat_loop_iter loop_iter, void* data );
1787# endif /* retroflat_loop */
1788
1789#define retroflat_get_assets_path() (g_retroflat_state->assets_path)
1790
1791MERROR_RETVAL retroflat_build_filename_path(
1792 const maug_path filename_in, const char* filename_ext,
1793 char* buffer_out, size_t buffer_out_sz, uint8_t flags );
1794
1799
1807 uint8_t flags, const char* title, const char* format, ... );
1808 /* maug_retroflt_msg_api */
1810
1818MERROR_RETVAL retroflat_init( int argc, char* argv[], struct RETROFLAT_ARGS* args );
1819
1826void retroflat_shutdown( int retval );
1827
1828# if defined( RETROFLAT_VDP ) || defined( DOCUMENTATION )
1833
1837MERROR_RETVAL retroflat_vdp_call( const char* proc_name );
1838 /* maug_retroflt_vdp */
1840# endif /* RETROFLAT_VDP || DOCUMENTATION */
1841
1842RETROFLAT_IN_KEY retroflat_repeat_input(
1843 RETROFLAT_IN_KEY key_out, struct RETROFLAT_INPUT* input,
1844 RETROFLAT_IN_KEY* prev_input, int* prev_delay );
1845
1846void retroflat_set_title( const char* format, ... );
1847
1848retroflat_ms_t retroflat_get_ms();
1849
1850uint32_t retroflat_get_rand();
1851
1852# if !defined( RETROFLAT_NO_KEYBOARD )
1853char retroflat_vk_to_ascii( RETROFLAT_IN_KEY k, uint8_t flags );
1854# endif /* !RETROFLAT_NO_KEYBOARD */
1855
1860
1872 const char* filename, struct RETROFLAT_BITMAP* bmp_out, uint8_t flags );
1873
1874MERROR_RETVAL retroflat_create_bitmap(
1876 struct RETROFLAT_BITMAP* bmp_out, uint8_t flags );
1877
1883void retroflat_destroy_bitmap( struct RETROFLAT_BITMAP* bitmap );
1884
1901 struct RETROFLAT_BITMAP* target, struct RETROFLAT_BITMAP* src,
1905 int16_t instance );
1906
1907#ifdef RETROFLAT_TRACE_CONSTRAIN
1908# define retroflat_constrain_px( x, y, bmp, retact ) \
1909 if( \
1910 x >= retroflat_bitmap_w( bmp ) || y >= retroflat_bitmap_h( bmp ) || \
1911 0 > x || 0 > y \
1912 ) { \
1913 error_printf( "attempted draw at %d, %d, out of bounds %d x %d", \
1914 x, y, retroflat_bitmap_w( bmp ), retroflat_bitmap_h( bmp ) ); \
1915 retact; \
1916 }
1917#else
1925# define retroflat_constrain_px( x, y, bmp, retact ) \
1926 if( \
1927 x >= retroflat_bitmap_w( bmp ) || y >= retroflat_bitmap_h( bmp ) || \
1928 0 > x || 0 > y \
1929 ) { \
1930 retact; \
1931 }
1932#endif /* RETROFLAT_TRACE_CONSTRAIN */
1933
1938 struct RETROFLAT_BITMAP* bitmap,
1939 int16_t instance,
1943 /* maug_retroflt_bitmap */
1945
1950
1960MERROR_RETVAL retroflat_draw_lock( struct RETROFLAT_BITMAP* bmp );
1961
1962MERROR_RETVAL retroflat_draw_release( struct RETROFLAT_BITMAP* bmp );
1963
1964void retroflat_px(
1965 struct RETROFLAT_BITMAP* target, const RETROFLAT_COLOR color,
1966 retroflat_pxxy_t x, retroflat_pxxy_t y, uint8_t flags );
1967
1968#ifdef RETROFLAT_SOFT_SHAPES
1969# ifdef RETROFLAT_OPENGL
1970/* Make sure we're not passing NULL to openGL texture drawers... they can't
1971 * handle that!
1972 */
1973# define retroflat_rect( t, c, x, y, w, h, f ) \
1974 assert( NULL != t ); \
1975 retrosoft_rect( t, c, x, y, w, h, f );
1976# define retroflat_ellipse( t, c, x, y, w, h, f ) \
1977 assert( NULL != t ); \
1978 retrosoft_ellipse( t, c, x, y, w, h, f )
1979# else
1980# define retroflat_rect( t, c, x, y, w, h, f ) \
1981 retrosoft_rect( t, c, x, y, w, h, f )
1982# define retroflat_ellipse( t, c, x, y, w, h, f ) \
1983 retrosoft_ellipse( t, c, x, y, w, h, f )
1984# endif /* RETROFLAT_3D */
1985#else
1986
1998 struct RETROFLAT_BITMAP* target, const RETROFLAT_COLOR color,
2000 retroflat_pxxy_t w, retroflat_pxxy_t h, uint8_t flags );
2001
2013 struct RETROFLAT_BITMAP* target, const RETROFLAT_COLOR color,
2015 retroflat_pxxy_t w, retroflat_pxxy_t h, uint8_t flags );
2016
2017#endif /* RETROFLAT_SOFT_SHAPES */
2018
2019#ifdef RETROFLAT_SOFT_LINES
2020# define retroflat_line( t, c, x1, y1, x2, y2, f ) \
2021 retrosoft_line( t, c, x1, y1, x2, y2, f )
2022#else
2023
2036 struct RETROFLAT_BITMAP* target, const RETROFLAT_COLOR color,
2038 retroflat_pxxy_t x2, retroflat_pxxy_t y2, uint8_t flags );
2039
2040#endif /* RETROFLAT_SOFT_LINES */
2041
2042void retroflat_cursor( struct RETROFLAT_BITMAP* target, uint8_t flags );
2043
2057 struct RETROFLAT_BITMAP* target, const char* str, size_t str_sz,
2058 const char* font_str,
2059 retroflat_pxxy_t* w_out, retroflat_pxxy_t* h_out, uint8_t flags );
2060
2079 struct RETROFLAT_BITMAP* target, const RETROFLAT_COLOR color,
2080 const char* str, int str_sz, const char* font_str,
2081 retroflat_pxxy_t x_orig, retroflat_pxxy_t y_orig,
2082 uint8_t flags );
2083
2084/* TODO: Documentation! */
2085void retroflat_get_palette( uint8_t idx, uint32_t* rgb );
2086
2087MERROR_RETVAL retroflat_set_palette( uint8_t idx, uint32_t rgb );
2088 /* maug_retroflt_bitmap */
2090
2101 retroflat_proc_resize_t on_resize_in, void* data_in );
2102
2108
2114 retroflat_ms_t time, retroflat_timer_cb_t cb, void* data );
2115
2121
2126
2132RETROFLAT_IN_KEY retroflat_poll_input( struct RETROFLAT_INPUT* input );
2133 /* maug_retroflt_input */
2135
2136#ifdef RETROFLT_C
2137
2138MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets8_x[8] =
2139 { 0, 1, 1, 1, 0, -1, -1, -1 };
2140MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets8_y[8] =
2141 { -1, -1, 0, 1, 1, 1, 0, -1 };
2142
2143MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets4_x[4] =
2144 { 0, 1, 0, -1 };
2145MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets4_y[4] =
2146 { -1, 0, 1, 0 };
2147
2148# ifdef RETROFLAT_STATE_ON_STACK
2149struct RETROFLAT_STATE SEG_MGLOBAL g_retroflat_state_stack;
2150# else
2151MAUG_MHANDLE SEG_MGLOBAL g_retroflat_state_h = (MAUG_MHANDLE)NULL;
2152# endif /* RETROFLAT_STATE_ON_STACK */
2153struct RETROFLAT_STATE* SEG_MGLOBAL g_retroflat_state = NULL;
2154
2155# define RETROFLAT_COLOR_TABLE_CONSTS( idx, name_l, name_u, r, g, b, cgac, cgad ) \
2156 MAUG_CONST RETROFLAT_COLOR SEG_MCONST RETROFLAT_COLOR_ ## name_u = idx;
2157
2158RETROFLAT_COLOR_TABLE( RETROFLAT_COLOR_TABLE_CONSTS )
2159
2160# define RETROFLAT_COLOR_TABLE_NAMES( idx, name_l, name_u, r, g, b, cgac, cgad ) \
2161 #name_u,
2162
2163MAUG_CONST char* SEG_MCONST gc_retroflat_color_names[] = {
2164 RETROFLAT_COLOR_TABLE( RETROFLAT_COLOR_TABLE_NAMES )
2165};
2166
2167/* Callback table is down below, after the statically-defined callbacks. */
2168
2169/* === Function Definitions === */
2170
2171MERROR_RETVAL retroflat_build_filename_path(
2172 const maug_path filename_in, const char* filename_ext,
2173 char* buffer_out, size_t buffer_out_sz, uint8_t flags
2174) {
2175 MERROR_RETVAL retval = MERROR_OK;
2176
2177 assert( 1 < buffer_out_sz );
2178
2179 /* Build the path to the bitmap. */
2180 maug_mzero( buffer_out, buffer_out_sz );
2181 if(
2184 ) {
2185 /* TODO: Error checking. */
2186 maug_snprintf( buffer_out, buffer_out_sz - 1, "%s", filename_in );
2187 } else if( NULL != filename_ext ) {
2188 /* TODO: Error checking. */
2189 maug_snprintf( buffer_out, buffer_out_sz - 1, "%s%c%s.%s",
2190 g_retroflat_state->assets_path, RETROFLAT_PATH_SEP,
2191 filename_in, filename_ext );
2192 } else {
2193 maug_snprintf( buffer_out, buffer_out_sz - 1, "%s%c%s",
2194 g_retroflat_state->assets_path, RETROFLAT_PATH_SEP,
2195 filename_in );
2196 }
2197
2198 return retval;
2199}
2200
2201/* === */
2202
2203# if (defined( RETROFLAT_SOFT_SHAPES ) || defined( RETROFLAT_SOFT_LINES ) || \
2204 defined( RETROFLAT_3D ))
2205/* RETROSOFT_PRESENT is different from RETROFLAT_SOFT_SHAPES in that it only
2206 * indicates that the retrosoft library is loaded, not that it is the default
2207 * for drawing primatives!
2208 */
2209# define RETROSOFT_PRESENT
2210# endif
2211
2212# if defined( RETROFLAT_3D )
2213# if !defined( MAUG_NO_AUTO_C )
2214# define RETRO3D_C
2215# define RETRO3DP_C
2216# define RETROFP_C
2217# endif /* MAUG_NO_AUTO_C */
2218# include <retro3dp.h>
2219# include <retro3d.h>
2220# include <retro3du.h>
2221# include <retapi3.h>
2222# endif /* RETROFLAT_3D */
2223
2224# ifdef RETROSOFT_PRESENT
2225# if !defined( MAUG_NO_AUTO_C )
2226# define RETROSFT_C
2227# endif /* !MAUG_NO_AUTO_C */
2228# define RETROSOFT_PRESENT
2229# include <retrosft.h>
2230# endif /* RETROFLAT_SOFT_SHAPES */
2231
2232# ifndef RETROFLAT_NO_SOUND
2233# include <retapis.h>
2234# endif /* !RETROFLAT_NO_SOUND */
2235
2236# include <retapii.h>
2237
2238# if defined( RETROFLAT_VDP ) && defined( RETROFLAT_OS_UNIX )
2239# include <dlfcn.h>
2240# endif
2241
2242/* Still inside RETROFLT_C! */
2243
2244/* === */
2245
2246#ifndef RETROFLAT_NO_GENERIC_LOOP
2247
2248MERROR_RETVAL retroflat_loop_generic(
2249 retroflat_loop_iter frame_iter, retroflat_loop_iter loop_iter, void* data
2250) {
2251 MERROR_RETVAL retval = MERROR_OK;
2252 retroflat_ms_t next = 0,
2253 now = 0;
2254
2255 g_retroflat_state->loop_iter = (retroflat_loop_iter)loop_iter;
2256 g_retroflat_state->loop_data = (void*)data;
2257 g_retroflat_state->frame_iter = (retroflat_loop_iter)frame_iter;
2258
2259 if(
2261 (g_retroflat_state->retroflat_flags & RETROFLAT_FLAGS_RUNNING)
2262 ) {
2263 /* Main loop is already running, so we're just changing the iter call
2264 * and leaving!
2265 */
2266 debug_printf( 1, "main loop already running!" );
2267 goto cleanup;
2268 }
2269
2270 g_retroflat_state->retroflat_flags |= RETROFLAT_FLAGS_RUNNING;
2271 do {
2273
2274 if(
2275 /* Not waiting for the next frame? */
2277 (RETROFLAT_FLAGS_WAIT_FOR_FPS & g_retroflat_state->retroflat_flags) &&
2278 /* Inter-frame loop present? */
2279 NULL != g_retroflat_state->loop_iter
2280 ) {
2281 /* Run the loop iter as many times as possible. */
2282 g_retroflat_state->loop_iter( g_retroflat_state->loop_data );
2283 }
2284 if(
2286 (RETROFLAT_FLAGS_UNLOCK_FPS & g_retroflat_state->retroflat_flags) &&
2287 retroflat_get_ms() < next
2288 ) {
2289 /* Sleep/low power for a bit. */
2290 continue;
2291 }
2292
2294
2296
2297 if( NULL != g_retroflat_state->frame_iter ) {
2298 /* Run the frame iterator once per FPS tick. */
2299 g_retroflat_state->frame_iter( g_retroflat_state->loop_data );
2300 }
2301 /* Reset wait-for-frame flag AFTER frame callback. */
2302 g_retroflat_state->retroflat_flags &= ~RETROFLAT_FLAGS_WAIT_FOR_FPS;
2303 now = retroflat_get_ms();
2304 if( now + retroflat_fps_next() > now ) {
2305 next = now + retroflat_fps_next();
2306 } else {
2307 /* Rollover protection. */
2308 /* TODO: Add difference from now/next to 0 here. */
2309 next = 0;
2310 }
2311 } while(
2313 (RETROFLAT_FLAGS_RUNNING & g_retroflat_state->retroflat_flags)
2314 );
2315 retval = g_retroflat_state->retval;
2316
2317cleanup:
2318
2319 /* This should be set by retroflat_quit(). */
2320 return retval;
2321}
2322
2323#endif /* !RETROFLAT_NO_GENERIC_LOOP */
2324
2325/* === */
2326
2327# if !defined( RETROFLAT_NO_KEYBOARD )
2328
2329char retroflat_vk_to_ascii( RETROFLAT_IN_KEY k, uint8_t flags ) {
2330 char c = 0;
2331 char offset_lower = 0;
2332
2333 if( RETROFLAT_INPUT_MOD_SHIFT != (RETROFLAT_INPUT_MOD_SHIFT & flags) ) {
2334 /* Shift is *not* being held down. */
2335
2336 if( RETROFLAT_KEY_A <= k && RETROFLAT_KEY_Z >= k ) {
2337 if(
2338 RETROFLAT_INPUT_FORCE_UPPER !=
2339 (RETROFLAT_INPUT_FORCE_UPPER & flags)
2340 ) {
2341 /* Key is alphabetical and we're not forcing uppercase. */
2342 offset_lower = 0x20;
2343 }
2344 } else {
2345 offset_lower = 1;
2346 }
2347 }
2348
2349 switch( k ) {
2350 case RETROFLAT_KEY_A: c = 0x41 + offset_lower; break;
2351 case RETROFLAT_KEY_B: c = 0x42 + offset_lower; break;
2352 case RETROFLAT_KEY_C: c = 0x43 + offset_lower; break;
2353 case RETROFLAT_KEY_D: c = 0x44 + offset_lower; break;
2354 case RETROFLAT_KEY_E: c = 0x45 + offset_lower; break;
2355 case RETROFLAT_KEY_F: c = 0x46 + offset_lower; break;
2356 case RETROFLAT_KEY_G: c = 0x47 + offset_lower; break;
2357 case RETROFLAT_KEY_H: c = 0x48 + offset_lower; break;
2358 case RETROFLAT_KEY_I: c = 0x49 + offset_lower; break;
2359 case RETROFLAT_KEY_J: c = 0x4a + offset_lower; break;
2360 case RETROFLAT_KEY_K: c = 0x4b + offset_lower; break;
2361 case RETROFLAT_KEY_L: c = 0x4c + offset_lower; break;
2362 case RETROFLAT_KEY_M: c = 0x4d + offset_lower; break;
2363 case RETROFLAT_KEY_N: c = 0x4e + offset_lower; break;
2364 case RETROFLAT_KEY_O: c = 0x4f + offset_lower; break;
2365 case RETROFLAT_KEY_P: c = 0x50 + offset_lower; break;
2366 case RETROFLAT_KEY_Q: c = 0x51 + offset_lower; break;
2367 case RETROFLAT_KEY_R: c = 0x52 + offset_lower; break;
2368 case RETROFLAT_KEY_S: c = 0x53 + offset_lower; break;
2369 case RETROFLAT_KEY_T: c = 0x54 + offset_lower; break;
2370 case RETROFLAT_KEY_U: c = 0x55 + offset_lower; break;
2371 case RETROFLAT_KEY_V: c = 0x56 + offset_lower; break;
2372 case RETROFLAT_KEY_W: c = 0x57 + offset_lower; break;
2373 case RETROFLAT_KEY_X: c = 0x58 + offset_lower; break;
2374 case RETROFLAT_KEY_Y: c = 0x59 + offset_lower; break;
2375 case RETROFLAT_KEY_Z: c = 0x60 + offset_lower; break;
2376 case RETROFLAT_KEY_0: c = offset_lower ? 0x30 : ')'; break;
2377 case RETROFLAT_KEY_1: c = offset_lower ? 0x31 : '!'; break;
2378 case RETROFLAT_KEY_2: c = offset_lower ? 0x32 : '@'; break;
2379 case RETROFLAT_KEY_3: c = offset_lower ? 0x33 : '#'; break;
2380 case RETROFLAT_KEY_4: c = offset_lower ? 0x34 : '$'; break;
2381 case RETROFLAT_KEY_5: c = offset_lower ? 0x35 : '%'; break;
2382 case RETROFLAT_KEY_6: c = offset_lower ? 0x36 : '^'; break;
2383 case RETROFLAT_KEY_7: c = offset_lower ? 0x37 : '&'; break;
2384 case RETROFLAT_KEY_8: c = offset_lower ? 0x38 : '*'; break;
2385 case RETROFLAT_KEY_9: c = offset_lower ? 0x39 : '('; break;
2386 case RETROFLAT_KEY_SPACE: c = ' '; break;
2387 case RETROFLAT_KEY_BKSP: c = 0x08; break;
2388 case RETROFLAT_KEY_ENTER: c = '\n'; break;
2389 case RETROFLAT_KEY_SEMICOLON: c = offset_lower ? ';' : ':'; break;
2390 case RETROFLAT_KEY_DASH: c = offset_lower ? '-' : '_'; break;
2391 case RETROFLAT_KEY_SLASH: c = offset_lower ? '/' : '?'; break;
2392 case RETROFLAT_KEY_PERIOD: c = offset_lower ? '.' : '>'; break;
2393 case RETROFLAT_KEY_COMMA: c = offset_lower ? ',' : '<'; break;
2394 case RETROFLAT_KEY_QUOTE: c = offset_lower ? '\'' : '"'; break;
2395 case RETROFLAT_KEY_EQUALS: c = offset_lower ? '=' : '+'; break;
2396 case RETROFLAT_KEY_BACKSLASH: c = offset_lower ? '\\' : '|'; break;
2397 case RETROFLAT_KEY_BRACKETL: c = offset_lower ? '[' : '{'; break;
2398 case RETROFLAT_KEY_BRACKETR: c = offset_lower ? ']' : '}'; break;
2399#ifndef RETROFLAT_API_PC_BIOS
2400 /* TODO: FIXME in DOS! */
2401 case RETROFLAT_KEY_GRAVE: c = offset_lower ? '`' : '~'; break;
2402#endif /* !RETROFLAT_API_PC_BIOS */
2403 }
2404
2405 debug_printf( RETROINPUT_TRACE_LVL, "0x%02x", c );
2406
2407 return c;
2408}
2409
2410#endif /* !RETROFLAT_NO_KEYBOARD */
2411
2412/* === */
2413
2414/* TODO: Migrate all platform-specific parts below to retapif.h. */
2415#include <retapif.h>
2416
2417/* === */
2418
2419# ifndef RETROFLAT_NO_CLI
2420
2421# if !defined( RETROFLAT_NO_SOUND ) && defined( RETROSND_ARGS )
2422
2423static MERROR_RETVAL retrosnd_cli_rsl(
2424 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2425) {
2426 if(
2427 0 <= arg_c &&
2428 0 == maug_strncmp( MAUG_CLI_SIGIL "rsl", arg, MAUG_CLI_SIGIL_SZ + 4 )
2429 ) {
2430 args->sound.flags |= RETROSND_ARGS_FLAG_LIST_DEVS;
2431 }
2432 return MERROR_OK;
2433}
2434
2435# endif /* !RETROFLAT_NO_SOUND && RETROSND_ARGS */
2436
2437# if !defined( RETROFLAT_API_PC_BIOS ) && !defined( RETROFLAT_NO_CLI_SZ )
2438
2439static MERROR_RETVAL retroflat_cli_rfs(
2440 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2441) {
2442 if( 1 < arg_c ) {
2443 args->screen_scale = atoi( arg );
2444 debug_printf( 3, "screen scale arg set to: %d", args->screen_scale );
2445 }
2446 return MERROR_OK;
2447}
2448
2449static MERROR_RETVAL retroflat_cli_rfx(
2450 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2451) {
2452 if( 0 > arg_c ) {
2453 if( 0 == args->screen_w ) {
2454 args->screen_x = 0;
2455 }
2456 } else if(
2457 0 == maug_strncmp( MAUG_CLI_SIGIL "rfx", arg, MAUG_CLI_SIGIL_SZ + 4 )
2458 ) {
2459 /* The next arg must be the new var. */
2460 } else {
2461 args->screen_x = atoi( arg );
2462 }
2463 return MERROR_OK;
2464}
2465
2466static MERROR_RETVAL retroflat_cli_rfy(
2467 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2468) {
2469 if( 0 > arg_c ) {
2470 if( 0 == args->screen_h ) {
2471 args->screen_y = 0;
2472 }
2473 } else if(
2474 0 == maug_strncmp( MAUG_CLI_SIGIL "rfy", arg, MAUG_CLI_SIGIL_SZ + 4 )
2475 ) {
2476 /* The next arg must be the new var. */
2477 } else {
2478 args->screen_y = atoi( arg );
2479 }
2480 return MERROR_OK;
2481}
2482
2483static MERROR_RETVAL retroflat_cli_rfw(
2484 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2485) {
2486 if( 0 > arg_c ) {
2487 if( 0 == args->screen_w ) {
2488 args->screen_w = RETROFLAT_DEFAULT_SCREEN_W;
2489 debug_printf( 1, "setting arg screen_w to default %d:",
2490 args->screen_w );
2491 }
2492 } else if(
2493 0 == maug_strncmp( MAUG_CLI_SIGIL "rfw", arg, MAUG_CLI_SIGIL_SZ + 4 )
2494 ) {
2495 /* The next arg must be the new var. */
2496 } else {
2497 args->screen_w = atoi( arg );
2498 debug_printf( 1, "setting arg screen_w to: %d",
2499 args->screen_w );
2500 }
2501 return MERROR_OK;
2502}
2503
2504static MERROR_RETVAL retroflat_cli_rfh(
2505 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2506) {
2507 if( 0 > arg_c ) {
2508 if( 0 == args->screen_h ) {
2509 args->screen_h = RETROFLAT_DEFAULT_SCREEN_H;
2510 debug_printf( 1, "setting arg screen_h to default: %d",
2511 args->screen_h );
2512 }
2513 } else if(
2514 0 == maug_strncmp( MAUG_CLI_SIGIL "rfh", arg, MAUG_CLI_SIGIL_SZ + 4 )
2515 ) {
2516 /* The next arg must be the new var. */
2517 } else {
2518 args->screen_h = atoi( arg );
2519 debug_printf( 1, "setting arg screen_h to: %d",
2520 args->screen_h );
2521 }
2522 return MERROR_OK;
2523}
2524
2525# endif /* !RETROFLAT_API_PC_BIOS && !RETROFLAT_NO_CLI_SZ */
2526
2527# ifdef RETROFLAT_VDP
2528static MERROR_RETVAL retroflat_cli_vdp(
2529 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2530) {
2531 if( 0 == maug_strncmp( MAUG_CLI_SIGIL "vdp", arg, MAUG_CLI_SIGIL_SZ + 4 ) ) {
2532 /* Next arg is VDP args str. */
2533 } else {
2534 maug_strncpy( g_retroflat_state->vdp_args, arg, RETROFLAT_VDP_ARGS_SZ_MAX );
2535 debug_printf( 1, "VDP args: %s", g_retroflat_state->vdp_args );
2536 }
2537 return MERROR_OK;
2538}
2539# endif /* RETROFLAT_VDP */
2540
2541static MERROR_RETVAL retroflat_cli_u(
2542 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2543) {
2544 if( 0 > arg_c ) {
2545 args->flags &= ~RETROFLAT_FLAGS_UNLOCK_FPS;
2546 } else if(
2547 0 == maug_strncmp( MAUG_CLI_SIGIL "rfu", arg, MAUG_CLI_SIGIL_SZ + 4 )
2548 ) {
2549 debug_printf( 1, "unlocking FPS..." );
2550 args->flags |= RETROFLAT_FLAGS_UNLOCK_FPS;
2551 }
2552 return MERROR_OK;
2553}
2554
2555# ifndef RETROFLAT_NO_PAD
2556
2557static MERROR_RETVAL retroflat_cli_rfj(
2558 const char* arg, ssize_t arg_c, struct RETROFLAT_ARGS* args
2559) {
2560 if( 0 > arg_c ) {
2561 args->joystick_id = -1;
2562 debug_printf( 1, "setting arg joystick_id to default: %d",
2563 args->joystick_id );
2564 } else if(
2565 0 == maug_strncmp( MAUG_CLI_SIGIL "rfj", arg, MAUG_CLI_SIGIL_SZ + 4 )
2566 ) {
2567 /* The next arg must be the new var. */
2568 } else {
2569 args->joystick_id = atoi( arg );
2570 debug_printf( 1, "setting arg joystick_id to: %d",
2571 args->joystick_id );
2572 }
2573 return MERROR_OK;
2574}
2575
2576# endif /* !RETROFLAT_NO_PAD */
2577
2578#endif /* !RETROFLAT_NO_CLI */
2579
2580/* === */
2581
2582/* Still inside RETROFLT_C! */
2583
2585 int argc, char* argv[], struct RETROFLAT_ARGS* args
2586) {
2587
2588 /* = Declare Init Vars = */
2589
2590 MERROR_RETVAL retval = 0;
2591
2592 /* = Begin Init Procedure = */
2593
2594# ifdef RETROFLAT_COMMIT_HASH
2595 debug_printf( 1, "retroflat commit: " RETROFLAT_COMMIT_HASH );
2596# endif /* RETROFLAT_COMMIT_HASH */
2597
2598 debug_printf( 1, "retroflat: initializing..." );
2599
2600 /* System sanity checks. */
2601 assert( 2 <= sizeof( MERROR_RETVAL ) );
2602 assert( 4 == sizeof( uint32_t ) );
2603 assert( 4 == sizeof( int32_t ) );
2604 assert( 2 == sizeof( uint16_t ) );
2605 assert( 2 == sizeof( int16_t ) );
2606 assert( 1 == sizeof( uint8_t ) );
2607 assert( 1 == sizeof( int8_t ) );
2608 assert( NULL != args );
2609 assert( 1 << RETROFLAT_TILE_W_BITS == RETROFLAT_TILE_W );
2610 assert( 1 << RETROFLAT_TILE_H_BITS == RETROFLAT_TILE_H );
2611
2612 debug_printf( 1, "initializing drawing routines..." );
2613
2614 /* Initialize 2D callbacks depending on if we're in 2D or 3D mode.
2615 * Please see retrom2d.h for more information.
2616 */
2617# if defined( RETROFLAT_BMP_TEX )
2618 retroflat_2d_px = (retroflat_px_cb)retro3d_texture_px;
2619 retroflat_2d_line = (retroflat_line_cb)retrosoft_line;
2620 retroflat_2d_rect = (retroflat_rect_cb)retrosoft_rect;
2621 retroflat_2d_ellipse = (retroflat_ellipse_cb)retrosoft_ellipse;
2622 retroflat_2d_blit_bitmap = (retroflat_blit_bitmap_cb)retro3d_texture_blit;
2623 retroflat_2d_load_bitmap =
2624 (retroflat_load_bitmap_cb)retro3d_texture_load_bitmap;
2625 retroflat_2d_create_bitmap =
2626 (retroflat_create_bitmap_cb)retro3d_texture_create;
2627# else
2628 retroflat_2d_px = (retroflat_px_cb)retroflat_px;
2629# ifdef RETROFLAT_SOFT_SHAPES
2630 /* TODO: Work retrosoft routines to use retroflat_blit_t */
2631 retroflat_2d_line = (retroflat_line_cb)retrosoft_line;
2632 retroflat_2d_rect = (retroflat_rect_cb)retrosoft_rect;
2633 retroflat_2d_ellipse = (retroflat_ellipse_cb)retrosoft_ellipse;
2634# else
2635 retroflat_2d_line = (retroflat_line_cb)retroflat_line;
2636 retroflat_2d_rect = (retroflat_rect_cb)retroflat_rect;
2637 retroflat_2d_ellipse = (retroflat_ellipse_cb)retroflat_ellipse;
2638# endif /* RETROFLAT_SOFT_SHAPES */
2639 retroflat_2d_blit_bitmap = (retroflat_blit_bitmap_cb)retroflat_blit_bitmap;
2640 retroflat_2d_load_bitmap = (retroflat_load_bitmap_cb)retroflat_load_bitmap;
2641 retroflat_2d_create_bitmap =
2642 (retroflat_create_bitmap_cb)retroflat_create_bitmap;
2643# endif /* RETROFLAT_BMP_TEX */
2644
2645 debug_printf( 1, "retroflat: MFIX_PRECISION: %f", MFIX_PRECISION );
2646
2647 debug_printf( 1, "retroflat: allocating state (" SIZE_T_FMT " bytes)...",
2648 sizeof( struct RETROFLAT_STATE ) );
2649
2650 debug_printf( 1, "retroflat: size_t is (" SIZE_T_FMT " bytes)...",
2651 sizeof( size_t ) );
2652
2653 debug_printf( 1, "retroflat: ssize_t is (" SIZE_T_FMT " bytes)...",
2654 sizeof( ssize_t ) );
2655
2656 debug_printf( 1, "retroflat: off_t is (" SIZE_T_FMT " bytes)...",
2657 sizeof( off_t ) );
2658
2659 debug_printf( 1, "initializing global state..." );
2660
2661# ifdef RETROFLAT_STATE_ON_STACK
2662 g_retroflat_state = &g_retroflat_state_stack;
2663# else
2664 maug_malloc_test( g_retroflat_state_h, 1, sizeof( struct RETROFLAT_STATE ) );
2665
2666 maug_mlock( g_retroflat_state_h, g_retroflat_state );
2667 if( NULL == g_retroflat_state ) {
2669 "Error", "Could not lock global state!" );
2670 retval = MERROR_ALLOC;
2671 goto cleanup;
2672 }
2673# endif /* RETROFLAT_STATE_ON_STACK */
2674
2675 maug_mzero( g_retroflat_state, sizeof( struct RETROFLAT_STATE ) );
2676
2677 retroflat_heartbeat_set( 1000, 2 );
2678
2679 debug_printf( 1, "initializing platform filesystem..." );
2680 retval = mfile_plt_init();
2681 maug_cleanup_if_not_ok();
2682
2683# ifndef RETROFLAT_NO_CLI
2684
2685 debug_printf( 1, "retroflat: parsing args..." );
2686
2687 /* All platforms: add command-line args based on compile definitons. */
2688
2689 retval = maug_add_arg(
2690 MAUG_CLI_SIGIL "h", MAUG_CLI_SIGIL_SZ + 2, "Display command-line help",
2691 26, maug_cli_h, NULL );
2692
2693# if !defined( RETROFLAT_NO_SOUND ) && defined( RETROSND_ARGS )
2694 retval = maug_add_arg( MAUG_CLI_SIGIL "rsd", MAUG_CLI_SIGIL_SZ + 4,
2695 "Select MIDI device", 0, (maug_cli_cb)retrosnd_cli_rsd, args );
2696 maug_cleanup_if_not_ok();
2697 retval = maug_add_arg( MAUG_CLI_SIGIL "rsl", MAUG_CLI_SIGIL_SZ + 4,
2698 "List MIDI devices", 0, (maug_cli_cb)retrosnd_cli_rsl, args );
2699 maug_cleanup_if_not_ok();
2700# endif /* !RETROFLAT_NO_SOUND && RETROSND_ARGS */
2701
2702# ifdef RETROFLAT_SCREENSAVER
2703 retval = maug_add_arg( MAUG_CLI_SIGIL "p", MAUG_CLI_SIGIL_SZ + 2,
2704 "Preview screensaver", 0, (maug_cli_cb)retroflat_cli_p, args );
2705 maug_cleanup_if_not_ok();
2706 retval = maug_add_arg( MAUG_CLI_SIGIL "s", MAUG_CLI_SIGIL_SZ + 2,
2707 "Launch screensaver", 0, (maug_cli_cb)retroflat_cli_s, args );
2708 maug_cleanup_if_not_ok();
2709# endif /* RETROFLAT_SCREENSAVER */
2710
2711# ifdef RETROFLAT_API_PC_BIOS
2712 retval = maug_add_arg( MAUG_CLI_SIGIL "rfm", MAUG_CLI_SIGIL_SZ + 4,
2713 "Set the screen mode.", 0,
2714 (maug_cli_cb)retroflat_cli_rfm, args );
2715 maug_cleanup_if_not_ok();
2716# elif !defined( RETROFLAT_NO_CLI_SZ )
2717 retval = maug_add_arg( MAUG_CLI_SIGIL "rfs", MAUG_CLI_SIGIL_SZ + 4,
2718 "Set screen scale factor.", 0,
2719 (maug_cli_cb)retroflat_cli_rfs, args );
2720 maug_cleanup_if_not_ok();
2721 retval = maug_add_arg( MAUG_CLI_SIGIL "rfx", MAUG_CLI_SIGIL_SZ + 4,
2722 "Set the screen X position.", 0,
2723 (maug_cli_cb)retroflat_cli_rfx, args );
2724 maug_cleanup_if_not_ok();
2725 retval = maug_add_arg( MAUG_CLI_SIGIL "rfy", MAUG_CLI_SIGIL_SZ + 4,
2726 "Set the screen Y position.", 0,
2727 (maug_cli_cb)retroflat_cli_rfy, args );
2728 maug_cleanup_if_not_ok();
2729 retval = maug_add_arg( MAUG_CLI_SIGIL "rfw", MAUG_CLI_SIGIL_SZ + 4,
2730 "Set the screen width.", 0,
2731 (maug_cli_cb)retroflat_cli_rfw, args );
2732 maug_cleanup_if_not_ok();
2733 retval = maug_add_arg( MAUG_CLI_SIGIL "rfh", MAUG_CLI_SIGIL_SZ + 4,
2734 "Set the screen height.", 0,
2735 (maug_cli_cb)retroflat_cli_rfh, args );
2736 maug_cleanup_if_not_ok();
2737# endif /* !RETROFLAT_NO_CLI_SZ */
2738
2739# ifdef RETROFLAT_VDP
2740 retval = maug_add_arg( MAUG_CLI_SIGIL "vdp", MAUG_CLI_SIGIL_SZ + 4,
2741 "Pass a string of args to the VDP.", 0,
2742 (maug_cli_cb)retroflat_cli_vdp, args );
2743 maug_cleanup_if_not_ok();
2744# endif /* RETROFLAT_VDP */
2745
2746 retval = maug_add_arg( MAUG_CLI_SIGIL "rfu", MAUG_CLI_SIGIL_SZ + 4,
2747 "Unlock FPS.", 0,
2748 (maug_cli_cb)retroflat_cli_u, args );
2749 maug_cleanup_if_not_ok();
2750
2751# ifndef RETROFLAT_NO_PAD
2752 retval = maug_add_arg( MAUG_CLI_SIGIL "rfj", MAUG_CLI_SIGIL_SZ + 4,
2753 "Specify joystick ID to use.", 0,
2754 (maug_cli_cb)retroflat_cli_rfj, args );
2755 maug_cleanup_if_not_ok();
2756# endif /* !RETROFLAT_NO_PAD */
2757
2758 /* Parse command line args. */
2759 retval = maug_parse_args( argc, argv );
2760 maug_cleanup_if_not_ok();
2761
2762# endif /* !RETROFLAT_NO_CLI */
2763
2764 if( 0 == args->screen_w ) {
2765 args->screen_w = RETROFLAT_DEFAULT_SCREEN_W;
2766 debug_printf( 1, "setting arg screen_w to default: %d",
2767 args->screen_w );
2768 }
2769 if( 0 == args->screen_h ) {
2770 args->screen_h = RETROFLAT_DEFAULT_SCREEN_H;
2771 debug_printf( 1, "setting arg screen_h to default: %d",
2772 args->screen_h );
2773 }
2774 if( 0 == args->screen_scale ) {
2775 args->screen_scale = RETROFLAT_DEFAULT_SCREEN_SCALE;
2776 debug_printf( 1, "setting arg screen_scale to default: %d",
2777 args->screen_scale );
2778 }
2779 if( 0 == args->screen_colors ) {
2780 args->screen_colors = 16;
2781 debug_printf( 1, "setting arg screen_colors to default: %d",
2782 args->screen_colors );
2783 }
2784 args->joystick_id = -1;
2785
2786 if(
2788 ) {
2789 g_retroflat_state->retroflat_flags |= RETROFLAT_FLAGS_UNLOCK_FPS;
2790 }
2791
2792 debug_printf( 1, "retroflat: setting config..." );
2793
2794 /* Set the assets path. */
2795 if( NULL != args->assets_path ) {
2796 maug_mzero( g_retroflat_state->assets_path, MAUG_PATH_SZ_MAX );
2797 maug_strncpy( g_retroflat_state->assets_path,
2798 args->assets_path, MAUG_PATH_SZ_MAX - 1 );
2799 }
2800
2801# if defined( RETROFLAT_SCREENSAVER )
2802 if(
2804 (RETROFLAT_FLAGS_SCREENSAVER & args->flags)
2805 ) {
2806 g_retroflat_state->retroflat_flags |= RETROFLAT_FLAGS_SCREENSAVER;
2807 }
2808# endif /* RETROFLAT_SCREENSAVER */
2809
2810# if !defined( RETROFLAT_NO_CLI_SZ )
2811 /* Setup intended screen size. */
2812 g_retroflat_state->screen_scale = args->screen_scale;
2813 g_retroflat_state->screen_v_w = args->screen_w;
2814 g_retroflat_state->screen_v_h = args->screen_h;
2815 g_retroflat_state->screen_w = args->screen_w *
2816 g_retroflat_state->screen_scale;
2817 g_retroflat_state->screen_h = args->screen_h *
2818 g_retroflat_state->screen_scale;
2819 g_retroflat_state->screen_colors = args->screen_colors;
2820
2821 debug_printf( 3, "attempting to initialize platform with: "
2822 SIZE_T_FMT "x" SIZE_T_FMT " pixels (scaled to " SIZE_T_FMT "x" SIZE_T_FMT
2823 ") and " SIZE_T_FMT " colors",
2824 g_retroflat_state->screen_v_w, g_retroflat_state->screen_v_h,
2825 g_retroflat_state->screen_w, g_retroflat_state->screen_h,
2826 g_retroflat_state->screen_colors );
2827# endif /* !RETROFLAT_NO_CLI_SZ */
2828
2829 /* == Platform-Specific Init == */
2830
2831 retval = retroflat_init_platform( argc, argv, args );
2832 maug_cleanup_if_not_ok();
2833
2834# if defined( RETROFLAT_NO_CLI_SZ )
2835 g_retroflat_state->screen_scale = args->screen_scale;
2836 g_retroflat_state->screen_v_w = args->screen_w;
2837 g_retroflat_state->screen_v_h = args->screen_h;
2838 g_retroflat_state->screen_w = args->screen_w *
2839 g_retroflat_state->screen_scale;
2840 g_retroflat_state->screen_h = args->screen_h *
2841 g_retroflat_state->screen_scale;
2842 g_retroflat_state->screen_colors = args->screen_colors;
2843
2844 debug_printf( 3, "initialized platform with: "
2845 SIZE_T_FMT "x" SIZE_T_FMT " pixels (scaled to " SIZE_T_FMT "x" SIZE_T_FMT
2846 ") and " SIZE_T_FMT " colors",
2847 g_retroflat_state->screen_v_w, g_retroflat_state->screen_v_h,
2848 g_retroflat_state->screen_w, g_retroflat_state->screen_h,
2849 g_retroflat_state->screen_colors );
2850# endif /* RETROFLAT_NO_CLI_SZ */
2851
2852 retval = retroflat_init_input( args );
2853 maug_cleanup_if_not_ok();
2854
2855 debug_printf( 3, "screen initialized with: " SIZE_T_FMT "x" SIZE_T_FMT
2856 " pixels (scaled to " SIZE_T_FMT "x" SIZE_T_FMT
2857 ") with " SIZE_T_FMT " colors",
2858 g_retroflat_state->screen_v_w, g_retroflat_state->screen_v_h,
2859 g_retroflat_state->screen_w, g_retroflat_state->screen_h,
2860 retroflat_screen_colors() );
2861
2862 /* Setup the refresh grid, if requested, only after screen space has been
2863 * determined by the platform!
2864 */
2865 maug_cleanup_if_eq(
2866 (size_t)0, retroflat_screen_w(), SIZE_T_FMT, MERROR_GUI );
2867 maug_cleanup_if_eq(
2868 (size_t)0, retroflat_screen_h(), SIZE_T_FMT, MERROR_GUI );
2869 maug_cleanup_if_eq(
2870 (size_t)0, retroflat_screen_colors(), SIZE_T_FMT, MERROR_GUI );
2871
2872 /* This is intended as a default and can be modified by calling this macro
2873 * again later.
2874 */
2875 retroflat_viewport_set_pos_size(
2876 0, 0, retroflat_screen_w(), retroflat_screen_h() );
2877
2878#ifndef RETROFLAT_NO_VIEWPORT_REFRESH
2879 debug_printf( 1, "allocating refresh grid (%d tiles...)",
2880 g_retroflat_state->viewport.screen_tile_w *
2881 g_retroflat_state->viewport.screen_tile_h );
2882 maug_malloc_test(
2883 g_retroflat_state->viewport.refresh_grid_h,
2884 (g_retroflat_state->viewport.screen_tile_w + 2) *
2885 (g_retroflat_state->viewport.screen_tile_h + 2),
2886 sizeof( retroflat_tile_t ) );
2887#endif /* !RETROFLAT_NO_VIEWPORT_REFRESH */
2888
2889# ifdef RETROFLAT_VDP
2890# if defined( RETROFLAT_OS_UNIX )
2891 g_retroflat_state->vdp_exe = dlopen(
2892 "./" RETROFLAT_VDP_LIB_NAME ".so", RTLD_LAZY );
2893# elif defined( RETROFLAT_OS_WIN )
2894 g_retroflat_state->vdp_exe = LoadLibrary(
2895 "./" RETROFLAT_VDP_LIB_NAME ".dll" );
2896# else
2897# error "dlopen undefined!"
2898# endif /* RETROFLAT_OS_UNIX */
2899
2900 if( !(g_retroflat_state->vdp_exe) ) {
2901 error_printf( "not loading VDP" );
2902 /* Skip creating the buffer or trying to run the init proc. */
2903 goto skip_vdp;
2904 }
2905
2906 /* Create intermediary screen buffer. */
2907 debug_printf( 1, "creating VDP buffer, " SIZE_T_FMT " x " SIZE_T_FMT,
2908 g_retroflat_state->screen_v_w, g_retroflat_state->screen_v_h );
2909 g_retroflat_state->vdp_buffer =
2910 calloc( 1, sizeof( struct RETROFLAT_BITMAP ) );
2911 maug_cleanup_if_null_alloc(
2912 struct RETROFLAT_BITMAP*, g_retroflat_state->vdp_buffer );
2913 retval = retroflat_create_bitmap(
2914 g_retroflat_state->screen_v_w, g_retroflat_state->screen_v_h,
2915 g_retroflat_state->vdp_buffer, RETROFLAT_FLAGS_OPAQUE );
2916 maug_cleanup_if_not_ok();
2917
2918 debug_printf( 1, "initializing VDP..." );
2919 retval = retroflat_vdp_call( "retroflat_vdp_init" );
2920
2921skip_vdp:
2922
2923# endif /* RETROFLAT_VDP */
2924
2925# ifdef RETROFLAT_3D
2926 retro3d_platform_init();
2927# endif /* RETROFLAT_3D */
2928
2929# if !defined( RETROFLAT_NO_BLANK_INIT ) && !defined( RETROFLAT_3D )
2930 retroflat_draw_lock( NULL );
2932 NULL, RETROFLAT_COLOR_BLACK, 0, 0,
2933 retroflat_screen_w(), retroflat_screen_h(),
2935 retroflat_draw_release( NULL );
2936# endif /* !RETROFLAT_NO_BLANK_INIT */
2937
2938cleanup:
2939
2940 return retval;
2941}
2942
2943/* === */
2944
2945void retroflat_shutdown( int retval ) {
2946
2947 debug_printf( 1, "retroflat shutdown called..." );
2948
2949#ifndef RETROFLAT_NO_VIEWPORT_REFRESH
2950 if(
2951 NULL != g_retroflat_state &&
2952 (MAUG_MHANDLE)NULL != g_retroflat_state->viewport.refresh_grid_h
2953 ) {
2954 maug_mfree( g_retroflat_state->viewport.refresh_grid_h );
2955 }
2956#endif /* !RETROFLAT_NO_VIEWPORT_REFRESH */
2957
2958# if defined( RETROFLAT_VDP )
2959 if( NULL != g_retroflat_state->vdp_exe ) {
2960 retroflat_vdp_call( "retroflat_vdp_shutdown" );
2961# ifdef RETROFLAT_OS_UNIX
2962 dlclose( g_retroflat_state->vdp_exe );
2963# elif defined( RETROFLAT_OS_WIN )
2964 FreeLibrary( g_retroflat_state->vdp_exe );
2965# else
2966# error "dlclose undefined!"
2967# endif /* RETROFLAT_OS_UNIX || RETROFLAT_OS_WIN */
2968 }
2969
2970 if( NULL != g_retroflat_state->vdp_buffer ) {
2971 debug_printf( 1, "destroying VPD buffer..." );
2972 retroflat_destroy_bitmap( g_retroflat_state->vdp_buffer );
2973 free( g_retroflat_state->vdp_buffer );
2974 }
2975# endif /* RETROFLAT_VDP */
2976
2977 /* === Platform-Specific Shutdown === */
2978
2979#ifdef RETROFLAT_3D
2980 retro3d_platform_shutdown();
2981#endif /* RETROFLAT_3D */
2982
2983 retroflat_shutdown_platform( retval );
2984
2985#ifndef RETROFLAT_STATE_ON_STACK
2986 maug_munlock( g_retroflat_state_h, g_retroflat_state );
2987 maug_mfree( g_retroflat_state_h );
2988#endif /* !RETROFLAT_STATE_ON_STACK */
2989
2990}
2991
2992/* === */
2993
2994RETROFLAT_IN_KEY retroflat_repeat_input(
2995 RETROFLAT_IN_KEY key_out, struct RETROFLAT_INPUT* input,
2996 RETROFLAT_IN_KEY* prev_input, int* prev_delay
2997) {
2998
2999 /* Add a slight debounce for gamepad button repeat. */
3000 if( 0 < (*prev_delay) ) {
3001 debug_printf(
3002 RETROINPUT_TRACE_LVL,
3003 "repeat delay: %d", (*prev_delay) );
3004 (*prev_delay)--;
3005 }
3006
3007 /* If nothing else happened and repeat is enabled and a joypad button is
3008 * down, then emulate repeat for it.
3009 */
3010 if(
3011 0 == key_out &&
3013 (RETROFLAT_FLAGS_KEY_REPEAT & g_retroflat_state->retroflat_flags) &&
3014 /* There is an input to repeat. */
3015 0 != *prev_input &&
3016 /* Delay countdown reached. */
3017 0 == *prev_delay
3018 ) {
3019 key_out = *prev_input;
3020 *prev_delay = 1;
3021 debug_printf( RETROINPUT_TRACE_LVL, "repeat: %d", key_out );
3022 }
3023
3024 return key_out;
3025}
3026
3027/* === */
3028
3029ssize_t retroflat_timer_add(
3030 retroflat_ms_t at_time, retroflat_timer_cb_t cb, void* data
3031) {
3032 if( retroflat_get_ms() > at_time ) {
3033 error_printf( "timer time is in the past!" );
3034 return merror_retval_to_sz( MERROR_EXEC );
3035 }
3036
3037 if( g_retroflat_state->timers_ct + 1 < RETROFLAT_TIMER_CT_MAX ) {
3038 g_retroflat_state->timers_cb[g_retroflat_state->timers_ct] = cb;
3039 g_retroflat_state->timers_at[g_retroflat_state->timers_ct] = at_time;
3040 g_retroflat_state->timers_ct++;
3041 return g_retroflat_state->timers_ct - 1;
3042 }
3043
3044 error_printf( "too many timers!" );
3045 return merror_retval_to_sz( MERROR_OVERFLOW );
3046}
3047
3048/* === */
3049
3051 size_t i = 0;
3052 retroflat_ms_t time_now = 0;
3053
3054 time_now = retroflat_get_ms();
3055
3056 for( i = 0 ; g_retroflat_state->timers_ct > i ; i++ ) {
3057 if( g_retroflat_state->timers_at[i] <= time_now ) {
3058 g_retroflat_state->timers_cb[i](
3059 time_now, g_retroflat_state->timers_data[i] );
3060 memmove(
3061 &(g_retroflat_state->timers_cb[i]),
3062 &(g_retroflat_state->timers_cb[i + 1]),
3063 sizeof( retroflat_timer_cb_t ) *
3064 ((g_retroflat_state->timers_ct - i) - 1)
3065 );
3066 memmove(
3067 &(g_retroflat_state->timers_at[i]),
3068 &(g_retroflat_state->timers_at[i + 1]),
3069 sizeof( retroflat_ms_t ) * ((g_retroflat_state->timers_ct - i) - 1)
3070 );
3071 memmove(
3072 &(g_retroflat_state->timers_data[i]),
3073 &(g_retroflat_state->timers_data[i + 1]),
3074 sizeof( void* ) * ((g_retroflat_state->timers_ct - i) - 1)
3075 );
3076 g_retroflat_state->timers_ct--;
3077 i--;
3078 }
3079 }
3080}
3081
3082/* === */
3083
3085 struct RETROFLAT_BITMAP* bitmap,
3086 int16_t instance,
3090) {
3091 retroflat_pxxy_t trim_bottom = *d_y + *h;
3092 retroflat_pxxy_t trim_right = *d_x + *w;
3093 retroflat_pxxy_t viewport_bottom = 0;
3094 retroflat_pxxy_t viewport_right = 0;
3095 retroflat_pxxy_t viewport_left = 0;
3096 retroflat_pxxy_t viewport_top = 0;
3097
3098 if(
3099 /* On the screen, constrain to the edges of the viewport. */
3100 retroflat_screen_buffer() == bitmap &&
3101 /* Probably blitting a window or other element that can go anywhere. */
3102 RETROFLAT_INSTANCE_NULL != instance
3103 ) {
3104 viewport_left = retroflat_viewport_screen_get_x();
3105 viewport_top = retroflat_viewport_screen_get_y();
3106 viewport_bottom =
3107 (retroflat_viewport_screen_get_y() + retroflat_viewport_screen_h());
3108 viewport_right =
3109 (retroflat_viewport_screen_get_x() + retroflat_viewport_screen_w());
3110
3111 } else {
3112 /* Constrain to the edges of the arbitrary bitmap. */
3113 viewport_bottom = retroflat_bitmap_h( bitmap );
3114 viewport_right = retroflat_bitmap_w( bitmap );
3115 }
3116
3117 if( viewport_bottom < *d_y || trim_bottom < viewport_top ) {
3118#ifdef RETROFLAT_TRACE_CONSTRAIN
3119 error_printf( "attempted to blit bitmap way out of bounds at %d, %d!",
3120 *d_x, *d_y );
3121#endif /* RETROFLAT_TRACE_CONSTRAIN */
3122 return MERROR_GUI;
3123
3124 } else if( viewport_bottom <= trim_bottom ) {
3125#ifdef RETROFLAT_TRACE_CONSTRAIN
3126 error_printf(
3127 "trimming " SIZE_T_FMT " pixels to get " SIZE_T_FMT " under "
3128 SIZE_T_FMT,
3129 trim_bottom - viewport_bottom, trim_bottom, viewport_bottom );
3130#endif /* RETROFLAT_TRACE_CONSTRAIN */
3131 *h -= (trim_bottom - viewport_bottom);
3132
3133 } else if( viewport_top > *d_y ) {
3134#ifdef RETROFLAT_TRACE_CONSTRAIN
3135 error_printf(
3136 "trimming " SIZE_T_FMT " pixels to get " SIZE_T_FMT " under "
3137 SIZE_T_FMT,
3138 trim_bottom - viewport_bottom, trim_bottom, viewport_bottom );
3139#endif /* RETROFLAT_TRACE_CONSTRAIN */
3140 *h -= (viewport_top - *d_y);
3141 if( NULL != s_y ) {
3142 *s_y += (viewport_top - *d_y);
3143 }
3144 *d_y += (viewport_top - *d_y);
3145 assert( viewport_top == *d_y );
3146 }
3147
3148 if( viewport_right < *d_x || trim_right < viewport_left ) {
3149#ifdef RETROFLAT_TRACE_CONSTRAIN
3150 error_printf( "attempted to blit bitmap way out of bounds at %d, %d!",
3151 *d_x, *d_y );
3152#endif /* RETROFLAT_TRACE_CONSTRAIN */
3153 return MERROR_GUI;
3154
3155 } else if( viewport_right <= trim_right ) {
3156#ifdef RETROFLAT_TRACE_CONSTRAIN
3157 error_printf(
3158 "trimming " SIZE_T_FMT " pixels to get " SIZE_T_FMT " under "
3159 SIZE_T_FMT,
3160 trim_right - viewport_right, trim_right, viewport_right );
3161#endif /* RETROFLAT_TRACE_CONSTRAIN */
3162 *w -= (trim_right - viewport_right);
3163
3164 } else if( viewport_left > *d_x ) {
3165#ifdef RETROFLAT_TRACE_CONSTRAIN
3166 error_printf(
3167 "trimming " SIZE_T_FMT " pixels to get " SIZE_T_FMT " under "
3168 SIZE_T_FMT,
3169 trim_bottom - viewport_bottom, trim_bottom, viewport_bottom );
3170#endif /* RETROFLAT_TRACE_CONSTRAIN */
3171 *w -= (viewport_left - *d_x);
3172 if( NULL != s_x ) {
3173 *s_x += (viewport_left - *d_x);
3174 }
3175 *d_x += (viewport_left - *d_x);
3176 assert( viewport_left == *d_x );
3177 }
3178
3179 if( 0 == w && 0 == h ) {
3180 return MERROR_GUI;
3181 }
3182
3183 return MERROR_OK;
3184}
3185
3186/* === */
3187
3188# ifdef RETROFLAT_VDP
3189
3190MERROR_RETVAL retroflat_vdp_call( const char* proc_name ) {
3191 MERROR_RETVAL retval = MERROR_OK;
3193# ifdef RETROFLAT_OS_WIN
3194 char proc_name_ex[256];
3195# endif /* RETROFLAT_OS_WIN */
3196
3197 if( NULL == g_retroflat_state->vdp_exe ) {
3198 goto cleanup;
3199 }
3200
3201# ifdef RETROFLAT_OS_UNIX
3202 vdp_proc = dlsym( g_retroflat_state->vdp_exe, proc_name );
3203# elif defined( RETROFLAT_OS_WIN )
3204 /* Append a _ to the proc_name because Watcom? Windows? */
3205 maug_snprintf( proc_name_ex, 255, "%s_", proc_name );
3206 vdp_proc = (retroflat_vdp_proc_t)GetProcAddress(
3207 g_retroflat_state->vdp_exe, proc_name_ex );
3208# else
3209# error "dlsym undefined!"
3210# endif
3211 if( (retroflat_vdp_proc_t)NULL == vdp_proc ) {
3212 goto cleanup;
3213 }
3214
3215# ifdef RETROFLAT_OS_WIN
3216 retroflat_draw_lock( g_retroflat_state->vdp_buffer );
3217# endif /* RETROFLAT_OS_WIN */
3218
3219 if(
3220 /* Don't pxlock before init can set the flag! */
3221 0 == strcmp( "retroflat_vdp_flip", proc_name ) &&
3223 (RETROFLAT_VDP_FLAG_PXLOCK & g_retroflat_state->vdp_flags)
3224 ) {
3225 retroflat_vdp_lock( &(g_retroflat_state->platform.buffer) );
3226 retroflat_vdp_lock( g_retroflat_state->vdp_buffer );
3227 }
3228
3229 retval = vdp_proc( g_retroflat_state );
3230
3231 if(
3232 0 == strcmp( "retroflat_vdp_flip", proc_name ) &&
3234 (RETROFLAT_VDP_FLAG_PXLOCK & g_retroflat_state->vdp_flags)
3235 ) {
3236 retroflat_vdp_release( &(g_retroflat_state->platform.buffer) );
3237 retroflat_vdp_release( g_retroflat_state->vdp_buffer );
3238 }
3239
3240# ifdef RETROFLAT_OS_WIN
3241 retroflat_draw_release( g_retroflat_state->vdp_buffer );
3242# endif /* RETROFLAT_OS_WIN */
3243
3244cleanup:
3245 return retval;
3246}
3247
3248# endif /* RETROFLAT_VDP */
3249
3250/* === */
3251
3252#if 0
3253
3254void retroflat_cursor( struct RETROFLAT_BITMAP* target, uint8_t flags ) {
3255#if 0
3256 char mouse_str[11] = "";
3257
3258 maug_snprintf(
3259 mouse_str, 10, "%02d, %02d", g_retroflat_state->last_mouse_x, g_retroflat_state->last_mouse_y );
3260
3262 target, RETROFLAT_COLOR_BLACK,
3263 mouse_str, 10, NULL, 0, 0, 0 );
3265 target, RETROFLAT_COLOR_BLACK,
3266 g_retroflat_state->last_mouse_x - 5, g_retroflat_state->last_mouse_y - 5, 10, 10, 0 );
3267#endif
3268}
3269
3270#endif
3271
3272/* === */
3273
3274void maug_critical_error( const char* msg ) {
3276}
3277
3278/* === */
3279
3281 retroflat_proc_resize_t on_resize_in, void* data_in
3282) {
3283 g_retroflat_state->on_resize = on_resize_in;
3284 g_retroflat_state->on_resize_data = data_in;
3285}
3286
3287/* === */
3288
3289uint8_t retroflat_viewport_move_x_generic( int16_t x ) {
3290 int16_t new_world_x = g_retroflat_state->viewport.world_x + x;
3291
3292 /* Keep the viewport in the world arena. */
3293 if(
3294 0 <= new_world_x &&
3295 g_retroflat_state->viewport.world_w >= new_world_x +
3296 g_retroflat_state->viewport.screen_w
3297 ) {
3298 g_retroflat_state->viewport.world_x += x;
3299 g_retroflat_state->viewport.world_tile_x += x >> RETROFLAT_TILE_W_BITS;
3300 return 1;
3301 }
3302
3303 return 0;
3304}
3305
3306/* === */
3307
3308uint8_t retroflat_viewport_move_y_generic( int16_t y ) {
3309 int16_t new_world_y = g_retroflat_state->viewport.world_y + y;
3310
3311 /* Keep the viewport in the world arena. */
3312 if(
3313 0 <= new_world_y &&
3314 g_retroflat_state->viewport.world_h >= new_world_y +
3315 g_retroflat_state->viewport.screen_h
3316 ) {
3317 g_retroflat_state->viewport.world_y += y;
3318 g_retroflat_state->viewport.world_tile_y += y >> RETROFLAT_TILE_H_BITS;
3319 return 1;
3320 }
3321
3322 return 0;
3323}
3324
3325/* === */
3326
3327uint8_t retroflat_viewport_focus_generic(
3330) {
3331 uint8_t moved = 0,
3332 new_moved = 0;
3333 int16_t new_pt = 0;
3334
3335# define _retroflat_viewport_focus_dir( n, xy, wh, gl, pm, dir, range, speed ) \
3336 new_pt = n - retroflat_viewport_world_ ## xy(); \
3337 if( new_pt gl (retroflat_screen_ ## wh() >> 1) pm range ) { \
3338 new_moved = retroflat_viewport_move_ ## xy( \
3339 gc_retroflat_offsets8_ ## xy[RETROFLAT_DIR8_ ## dir] * speed ); \
3340 if( !moved && new_moved ) { \
3341 moved = new_moved; \
3342 } \
3343 }
3344
3345 _retroflat_viewport_focus_dir( x1, x, w, <, -, WEST, range, speed );
3346 _retroflat_viewport_focus_dir( x1, x, w, >, +, EAST, range, speed );
3347 _retroflat_viewport_focus_dir( y1, y, h, <, -, NORTH, range, speed );
3348 _retroflat_viewport_focus_dir( y1, y, h, >, +, SOUTH, range, speed );
3349
3350 return moved;
3351}
3352
3353/* === */
3354
3355#ifdef RETROFLAT_LOAD_BITMAP_GENERIC
3356
3357/* This is a generic function that uses the callback
3358 * retroflat_load_bitmap_px_cb(), which should be defined by the
3359 * platform-specific API to draw the loaded bitmap onto a native canvas.
3360 */
3361
3363 const char* filename, struct RETROFLAT_BITMAP* bmp_out, uint8_t flags
3364) {
3365 maug_path filename_path;
3366 MERROR_RETVAL retval = MERROR_OK;
3367 mfile_t bmp_file;
3368 struct MFMT_STRUCT_BMPFILE header_bmp;
3369 uint8_t bmp_flags = 0;
3370
3371 assert( NULL != bmp_out );
3372 maug_mzero( bmp_out, sizeof( struct RETROFLAT_BITMAP ) );
3373 retval = retroflat_build_filename_path(
3374 filename, RETROFLAT_BITMAP_EXT, filename_path,
3375 MAUG_PATH_SZ_MAX, flags );
3376 maug_cleanup_if_not_ok();
3377 debug_printf( 1, "retroflat: loading bitmap: %s", filename_path );
3378
3379 bmp_out->flags = flags;
3380
3381 /* Open the bitmap file. */
3382 retval = mfile_open_read( filename_path, &bmp_file );
3383 maug_cleanup_if_not_ok();
3384
3385 /* mfmt file detection system. */
3386 maug_mzero( &header_bmp, sizeof( struct MFMT_STRUCT_BMPFILE ) );
3387 header_bmp.magic[0] = 'B';
3388 header_bmp.magic[1] = 'M';
3389 header_bmp.info.sz = 40;
3390
3391 retval = mfmt_read_bmp_header(
3392 (struct MFMT_STRUCT*)&header_bmp,
3393 &bmp_file, 0, mfile_get_sz( &bmp_file ), &bmp_flags );
3394 maug_cleanup_if_not_ok();
3395
3396 retval = retroflat_create_bitmap(
3397 header_bmp.info.width, header_bmp.info.height, bmp_out, flags );
3398 maug_cleanup_if_not_ok();
3399
3400 retroflat_draw_lock( bmp_out );
3401
3402 retval = mfmt_read_bmp_px_cb(
3403 (struct MFMT_STRUCT*)&header_bmp,
3404 &bmp_file,
3405 header_bmp.px_offset,
3406 mfile_get_sz( &bmp_file ) - header_bmp.px_offset,
3407 bmp_flags,
3408 retroflat_load_bitmap_px_cb,
3409 bmp_out );
3410 maug_cleanup_if_not_ok();
3411
3412 retroflat_draw_release( bmp_out );
3413
3414cleanup:
3415
3416 mfile_close( &bmp_file );
3417
3418 return retval;
3419}
3420
3421#endif /* RETROFLAT_LOAD_BITMAP_GENERIC */
3422
3423#elif !defined( RETROVDP_C ) /* End of RETROFLT_C */
3424
3429
3430extern MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets8_x[8];
3431extern MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets8_y[8];
3432extern MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets4_x[4];
3433extern MAUG_CONST int16_t SEG_MCONST gc_retroflat_offsets4_y[4];
3434
3436
3437#define RETROFLAT_COLOR_TABLE_CONSTS( idx, name_l, name_u, r, g, b, cgac, cgad ) \
3438 extern MAUG_CONST RETROFLAT_COLOR SEG_MCONST RETROFLAT_COLOR_ ## name_u;
3439
3440RETROFLAT_COLOR_TABLE( RETROFLAT_COLOR_TABLE_CONSTS )
3441
3442extern MAUG_CONST char* SEG_MCONST gc_retroflat_color_names[];
3443
3444extern struct RETROFLAT_STATE* SEG_MGLOBAL g_retroflat_state;
3445
3446# if (defined( RETROFLAT_SOFT_SHAPES ) || defined( RETROFLAT_SOFT_LINES ) || \
3447 defined( RETROFLAT_3D ))
3448# define RETROSOFT_PRESENT
3449# endif
3450
3451# ifdef RETROFLAT_3D
3452# include <retro3dp.h>
3453# include <retro3d.h>
3454# include <retro3du.h>
3455# endif /* RETROFLAT_3D */
3456
3457# ifdef RETROSOFT_PRESENT
3458# include <retrosft.h>
3459# endif /* RETROFLAT_SOFT_SHAPES */
3460
3461/* Second retapis.h include for function bodies not needed. */
3462
3463/* Second retapii.h include for function bodies not needed. */
3464
3465#endif /* RETROFLT_C */
3466
3467#ifdef RETROFLAT_XPM
3468#include <retroxpm.h>
3469#endif /* RETROFLAT_XPM */
3470
3471#ifdef RETROVDP_C
3472
3473/* Declarations for VDP sources. */
3474
3475#endif /* RETROVDP_C */
3476 /* maug_retroflt */
3478
3479#endif /* RETROFLT_H */
3480
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:590
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...
#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:576
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:735
#define RETROFLAT_PATH_SEP
The valid path separator on the target platform.
Definition retroflt.h:756
#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 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.
#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:468
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:520
#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:507
#define RETROFLAT_FLAGS_SCREENSAVER
Flag indicating the current application is running as a screensaver.
Definition retroflt.h:438
#define retroflat_heartbeat_update()
Check and update RETROFLAT_STATE::heartbeat_frame.
Definition retroflt.h:1620
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:885
#define RETROFLAT_FLAGS_UNLOCK_FPS
Flag indicating FPS should not be capped.
Definition retroflt.h:424
#define retroflat_heartbeat_set(len, max)
Set parameters for the RETROFLAT_STATE::heartbeat_frame.
Definition retroflt.h:1603
#define retroflat_system_task()
Platform-specific task that should be called on every iteration of the generic loop....
Definition retroflt.h:1080
void(* retroflat_loop_iter)(void *data)
Prototype for the main loop function passed to retroflat_loop().
Definition retroflt.h:779
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.
#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
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).
#define RETROFLAT_FLAGS_KEY_REPEAT
Flag indicating keyboard repeat is enabled.
Definition retroflt.h:431
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 mfmt.h:124
Generic image description struct.
Definition mfmt.h:69
Definition retroflt.h:1057
Struct containing configuration values for a RetroFlat program.
Definition retroflt.h:1094
char * config_path
Relative path of local config file (if not using registry).
Definition retroflt.h:1104
char * assets_path
Relative path under which bitmap assets are stored.
Definition retroflt.h:1102
int screen_w
Desired screen or window width in pixels.
Definition retroflt.h:1111
int screen_h
Desired screen or window height in pixels.
Definition retroflt.h:1118
int screen_colors
Desired colors (2, 4, or 16, for now). \TODO Implement command-line argument for this....
Definition retroflt.h:1130
char * title
Title to set for the main program Window if applicable on the target platform.
Definition retroflt.h:1100
int screen_y
Desired window Y position in pixels.
Definition retroflt.h:1122
int screen_x
Desired window X position in pixels.
Definition retroflt.h:1120
Struct passed to retroflat_poll_input() to hold return data.
Definition retroflt.h:829
int mouse_y
Y-coordinate of the mouse pointer in pixels if the returned event is a mouse click.
Definition retroflt.h:839
int mouse_x
X-coordinate of the mouse pointer in pixels if the returned event is a mouse click.
Definition retroflt.h:834
Global singleton containing state for the current platform.
Definition retroflt.h:1640
char vdp_args[RETROFLAT_VDP_ARGS_SZ_MAX]
CLI args passed with -vdp to the RetroFlat VDP API.
Definition retroflt.h:1678
size_t screen_h
The screen height as seen by the system, after scaling.
Definition retroflt.h:1704
uint8_t vdp_flags
Flags set by the RetroFlat VDP API.
Definition retroflt.h:1680
size_t screen_v_w
The screen width as seen by our program, before scaling.
Definition retroflt.h:1693
size_t screen_colors
The number of colors the screen is capable of displaying.
Definition retroflt.h:1706
uint8_t retroflat_flags
maug_retroflt_flags indicating current system status.
Definition retroflt.h:1650
uint8_t heartbeat_max
When RETROFLAT_STATE::heartbeat_frame reaches this value, it will reset to 0.
Definition retroflt.h:1733
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:1762
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:1665
uint8_t heartbeat_frame
Simple iteration loop that can be used to time e.g. perpetual sprite animations. Modify parameters wi...
Definition retroflt.h:1728
size_t screen_w
The screen width as seen by the system, after scaling.
Definition retroflt.h:1702
void * vdp_exe
A handle for the loaded RetroFlat VDP API module.
Definition retroflt.h:1670
RETROFLAT_COLOR_DEF palette[RETROFLAT_COLORS_SZ]
Index of available colors, initialized on platform init.
Definition retroflt.h:1740
uint16_t heartbeat_len
Number of ms to stay on current value of RETROFLAT_STATE::heartbeat_frame before incrementing....
Definition retroflt.h:1722
void * vdp_data
Pointer to data defined by the RetroFlat VDP API for its use.
Definition retroflt.h:1676
size_t screen_v_h
The screen height as seen by our program, before scaling.
Definition retroflt.h:1700
int screen_scale
Off-screen buffer bitmap.
Definition retroflt.h:1657
The viewport data struct.
Definition retroflt.h:1155
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:1173
retroflat_tile_t * refresh_grid
A grid of tile values representing the last-drawn values on-screen.
Definition retroflt.h:1246
retroflat_pxxy_t screen_h
Viewport height in pixels. Should only be retrieved through retroflat_viewport_screen_w() and set thr...
Definition retroflt.h:1203
retroflat_pxxy_t screen_h_remainder
Difference between viewport height and screen height in pixels. Should only be retrieved through retr...
Definition retroflt.h:1217
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:1167
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:1161
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:1224
retroflat_pxxy_t world_w
The width of the entire world tilemap in pixels. Should only be retrieved through retroflat_viewport_...
Definition retroflt.h:1185
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:1179
retroflat_pxxy_t screen_w_remainder
Difference between viewport width and screen width in pixels. Should only be retrieved through retrof...
Definition retroflt.h:1210
retroflat_pxxy_t screen_w
Viewport width in pixels. Should only be retrieved through retroflat_viewport_screen_w() and set thro...
Definition retroflt.h:1197
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:1231
retroflat_pxxy_t world_h
The height of the entire world tilemap in pixels. Should only be retrieved through retroflat_viewport...
Definition retroflt.h:1191