17#ifndef RETROTILE_NAME_SZ_MAX
19# define RETROTILE_NAME_SZ_MAX 10
22#ifndef RETROTILE_TILESET_IMAGE_STR_SZ_MAX
24# define RETROTILE_TILESET_IMAGE_STR_SZ_MAX 48
27#ifndef RETROTILE_TILE_SCALE_DEFAULT
29# define RETROTILE_TILE_SCALE_DEFAULT 1.0f
32#ifndef RETROTILE_TRACE_LVL
34# define RETROTILE_TRACE_LVL 0
37#ifndef RETROTILE_VORONOI_DEFAULT_SPB
38# define RETROTILE_VORONOI_DEFAULT_SPB 8
41#ifndef RETROTILE_VORONOI_DEFAULT_DRIFT
42# define RETROTILE_VORONOI_DEFAULT_DRIFT 4
45#ifdef MPARSER_TRACE_NAMES
46# define retrotile_mstate_name( state ) gc_retrotile_mstate_names[state]
48# define retrotile_mstate_name( state ) state
61#define RETROTILE_PARSER_MODE_MAP 0
62#define RETROTILE_PARSER_MODE_DEFS 1
64#define RETROTILE_TILE_FLAG_BLOCK 0x01
65#define RETROTILE_TILE_FLAG_ROT_X 0x02
66#define RETROTILE_TILE_FLAG_ROT_Z 0x04
67#define RETROTILE_TILE_FLAG_PRTCL_FIRE 0x08
81#define RETROTILE_DS_FLAG_INIT_DATA 0x02
83#define RETROTILE_IDX_FMT "%u"
98 uint32_t layers_count;
99 uint32_t layers_offset;
124 retroflat_tile_t highest_generated;
125 retroflat_tile_t lowest_generated;
129 int16_t tiles_changed;
130 retroflat_tile_t center;
131 retroflat_tile_t outside;
136#define retrotile_get_tile( tilemap, layer, x, y ) \
137 (retrotile_get_tiles_p( layer )[((y) * (tilemap)->tiles_w) + (x)])
139#define retrotile_set_tile( tilemap, layer, x, y, new_val ) \
140 (retrotile_get_tiles_p( layer )[((y) * (tilemap)->tiles_w) + (x)])
142#define retrotile_get_tiles_p( layer ) \
143 ((retroflat_tile_t*)(((uint8_t*)(layer)) + \
144 sizeof( struct RETROTILE_LAYER )))
146#define retrotile_clear_tiles( t, layer ) \
147 memset( retrotile_get_tiles_p( layer ), -1, \
148 t->tiles_w * t->tiles_h * sizeof( retroflat_tile_t ) )
156 const char* filename, MAUG_MHANDLE* p_tm_h,
157 MAUG_MHANDLE* p_td_h,
size_t* p_td_c,
158 mparser_wait_cb_t wait_cb,
void* wait_data );
165 mparser_wait_cb_t wait_cb;
167 retroflat_ms_t wait_last;
168 size_t layer_tile_iter;
169 size_t pass_layer_iter;
178 retrotile_tj_parse_cb tj_parse_cb;
179 struct MJSON_PARSER jparser;
180 MAUG_MHANDLE* p_tile_defs_h;
181 size_t* p_tile_defs_count;
184#define RETROTILE_PARSER_MSTATE_TABLE( f ) \
185 f( MTILESTATE_NONE, 0, "", 0, 0 ) \
186 f( MTILESTATE_HEIGHT, 1, "height", 0 , 0 ) \
187 f( MTILESTATE_WIDTH, 2, "width", 0 , 0 ) \
188 f( MTILESTATE_LAYERS, 3, "layers", 0 , 0 ) \
189 f( MTILESTATE_LAYER_DATA, 4, "data", 15 , 0 ) \
190 f( MTILESTATE_LAYER_NAME, 5, "name", 15 , 0 ) \
191 f( MTILESTATE_TILES, 6, "tiles", 0 , 1 ) \
192 f( MTILESTATE_TILES_ID, 7, "id", 6 , 1 ) \
193 f( MTILESTATE_TILES_IMAGE, 8, "image", 6 , 1 ) \
194 f( MTILESTATE_TILESETS, 9, "tilesets", 0 , 0 ) \
195 f( MTILESTATE_TILESETS_SRC, 10, "source", 9 , 0 ) \
196 f( MTILESTATE_TILESETS_FGID, 11, "firstgid",9 , 0 ) \
197 f( MTILESTATE_TILESETS_PROP, 12, "firstgid",9 , 0 ) \
198 f( MTILESTATE_GRID, 13, "grid", 0 , 1 ) \
199 f( MTILESTATE_TILES_PROP, 14, "properties",6 , 1 ) \
200 f( MTILESTATE_LAYER, 15, "layers", 3 , 0 ) \
201 f( MTILESTATE_TILES_PROP_NAME, 16, "name", 14 , 1 ) \
202 f( MTILESTATE_TILES_PROP_VAL, 17, "value", 14 , 1 )
208 const char* filename, MAUG_MHANDLE* p_tilemap_h,
209 MAUG_MHANDLE* p_tile_defs_h,
size_t* p_tile_defs_count,
210 mparser_wait_cb_t wait_cb,
void* wait_data );
221 void* animation_cb_data, int16_t iter );
224 struct RETROTILE* t, retroflat_tile_t min_z, retroflat_tile_t max_z,
225 uint32_t tuning,
size_t layer_idx, uint8_t flags,
void* data,
226 retrotile_ani_cb animation_cb,
void* animation_cb_data );
238 struct RETROTILE* t, retroflat_tile_t min_z, retroflat_tile_t max_z,
239 uint32_t tuning,
size_t layer_idx, uint8_t flags,
void* data,
240 retrotile_ani_cb animation_cb,
void* animation_cb_data );
253 struct RETROTILE* t, retroflat_tile_t min_z, retroflat_tile_t max_z,
254 uint32_t tuning,
size_t layer_idx, uint8_t flags,
void* data,
255 retrotile_ani_cb animation_cb,
void* animation_cb_data );
265 struct RETROTILE* t, retroflat_tile_t min_z, retroflat_tile_t max_z,
266 uint32_t tuning,
size_t layer_idx, uint8_t flags,
void* data,
267 retrotile_ani_cb animation_cb,
void* animation_cb_data );
276 struct RETROTILE* t, retroflat_tile_t min_z, retroflat_tile_t max_z,
277 uint32_t tuning,
size_t layer_idx, uint8_t flags,
void* data,
278 retrotile_ani_cb animation_cb,
void* animation_cb_data );
281 struct RETROTILE* tilemap, uint32_t layer_idx );
284 MAUG_MHANDLE* p_tile_defs_h,
size_t* p_tile_defs_count,
size_t ndefs );
287 MAUG_MHANDLE* p_tilemap_h,
size_t w,
size_t h,
size_t layers_count );
297#define retrotile_parser_mstate( parser, new_mstate ) \
298 parser->mstate = new_mstate;
303 retrotile_mstate_name( parser->mstate ) );
306# define RETROTILE_PARSER_MSTATE_TABLE_CONST( name, idx, tokn, parent, m ) \
307 static MAUG_CONST uint8_t SEG_MCONST name = idx;
309RETROTILE_PARSER_MSTATE_TABLE( RETROTILE_PARSER_MSTATE_TABLE_CONST )
311#ifdef MPARSER_TRACE_NAMES
312# define RETROTILE_PARSER_MSTATE_TABLE_NAME( name, idx, tokn, parent, m ) \
315static MAUG_CONST
char* SEG_MCONST gc_retrotile_mstate_names[] = {
316 RETROTILE_PARSER_MSTATE_TABLE( RETROTILE_PARSER_MSTATE_TABLE_NAME )
321# define RETROTILE_PARSER_MSTATE_TABLE_TOKEN( name, idx, tokn, parent, m ) \
324static MAUG_CONST
char* SEG_MCONST gc_retrotile_mstate_tokens[] = {
325 RETROTILE_PARSER_MSTATE_TABLE( RETROTILE_PARSER_MSTATE_TABLE_TOKEN )
329# define RETROTILE_PARSER_MSTATE_TABLE_PARNT( name, idx, tokn, parent, m ) \
332static MAUG_CONST uint8_t SEG_MCONST gc_retrotile_mstate_parents[] = {
333 RETROTILE_PARSER_MSTATE_TABLE( RETROTILE_PARSER_MSTATE_TABLE_PARNT )
337# define RETROTILE_PARSER_MSTATE_TABLE_MODE( name, idx, tokn, parent, m ) \
340static MAUG_CONST uint8_t SEG_MCONST gc_retrotile_mstate_modes[] = {
341 RETROTILE_PARSER_MSTATE_TABLE( RETROTILE_PARSER_MSTATE_TABLE_MODE )
347static void retrotile_parser_match_token(
353 while(
'\0' != gc_retrotile_mstate_tokens[j][0] ) {
356 maug_strlen( gc_retrotile_mstate_tokens[j] ) != token_sz ||
358 token, gc_retrotile_mstate_tokens[j], token_sz
369 parser->mstate != gc_retrotile_mstate_parents[j]
373 "found token \"%s\" "
374#ifdef MPARSER_TRACE_NAMES
375 "but incorrect parent %s (%d) (needs %s (%d))!",
377 "but incorrect parent %d (needs %d)!",
380#ifdef MPARSER_TRACE_NAMES
381 retrotile_mstate_name( parser->mstate ),
383 retrotile_mstate_name( gc_retrotile_mstate_parents[j] ),
384 gc_retrotile_mstate_parents[j]
387 gc_retrotile_mstate_parents[j]
396 parser->mode != gc_retrotile_mstate_modes[j]
401 gc_retrotile_mstate_modes[j] );
407 retrotile_parser_mstate( parser, j );
416 const char* token,
size_t token_sz,
void* parser_arg
421 size_t tileset_id_parsed = 0;
423 if( 0 < *(parser->p_tile_defs_count) ) {
424 maug_mlock( *(parser->p_tile_defs_h), tile_defs );
429 MJSON_PSTATE_OBJECT_VAL ==
430 mjson_parser_pstate( &(parser->jparser) )
432 if( MTILESTATE_TILES_ID == parser->mstate ) {
433 retrotile_parser_mstate( parser, MTILESTATE_TILES );
434 if( 0 == parser->pass ) {
436 tileset_id_parsed = atoi( token );
441 "new highest tile ID: " SIZE_T_FMT,
449 "next tile ID: " SIZE_T_FMT,
453 }
else if( MTILESTATE_TILES_IMAGE == parser->mstate ) {
454 if( 1 == parser->pass ) {
470 retrotile_parser_mstate( parser, MTILESTATE_TILES );
472 }
else if( MTILESTATE_TILES_PROP_NAME == parser->mstate ) {
474 if( 1 == parser->pass ) {
476 parser->jparser.base.token,
478 parser->jparser.base.token_sz
484 "tileset ID " SIZE_T_FMT
485 " outside of tile defs count " SIZE_T_FMT
"!",
487 retval = MERROR_OVERFLOW;
491 RETROTILE_TILE_FLAG_ROT_X;
497 retrotile_parser_mstate( parser, MTILESTATE_TILES_PROP );
499 }
else if( MTILESTATE_TILES_PROP_VAL == parser->mstate ) {
501 retrotile_parser_mstate( parser, MTILESTATE_TILES_PROP );
506 retrotile_parser_match_token( token, token_sz, parser );
510 if( NULL != tile_defs ) {
511 maug_munlock( *(parser->p_tile_defs_h), tile_defs );
518 const char* token,
size_t token_sz,
void* parser_arg
524 retroflat_tile_t* tiles = NULL;
526 if( 0 < *(parser->p_tile_defs_count) ) {
527 maug_mlock( *(parser->p_tile_defs_h), tile_defs );
531 if( MJSON_PSTATE_LIST == mjson_parser_pstate( &(parser->jparser) ) ) {
534 MTILESTATE_LAYER_DATA == parser->mstate
543 "selecting layer " SIZE_T_FMT
"...",
544 parser->pass_layer_iter );
545 assert( NULL != parser->t );
546 tiles_layer = retrotile_get_layer_p(
547 parser->t, parser->pass_layer_iter );
548 assert( NULL != tiles_layer );
550 tiles = retrotile_get_tiles_p( tiles_layer );
554 "layer " SIZE_T_FMT
" tile: " SIZE_T_FMT
" (tiles: %p)",
555 parser->pass_layer_iter, parser->layer_tile_iter,
557 assert( NULL != token );
558 assert( NULL != parser );
559 assert( NULL != tiles );
562 parser->layer_tile_iter >=
563 parser->t->tiles_w * parser->t->tiles_h
566 "tile " SIZE_T_FMT
" outside of layer tile buffer size "
568 parser->layer_tile_iter,
569 parser->t->tiles_w * parser->t->tiles_h );
570 retval = MERROR_OVERFLOW;
574 assert( 0 == tiles[parser->layer_tile_iter] );
576 tiles[parser->layer_tile_iter] = atoi( token );
578 parser->layer_tile_iter++;
582 MJSON_PSTATE_OBJECT_VAL ==
583 mjson_parser_pstate( &(parser->jparser) )
585 if( MTILESTATE_TILESETS_FGID == parser->mstate ) {
586 if( 1 == parser->pass ) {
587 parser->t->tileset_fgid = atoi( token );
590 parser->t->tileset_fgid );
592 retrotile_parser_mstate( parser, MTILESTATE_TILESETS );
594 }
else if( MTILESTATE_TILESETS_SRC == parser->mstate ) {
595 if( 1 == parser->pass ) {
598 token, NULL, parser->p_tile_defs_h,
599 parser->p_tile_defs_count,
600 parser->wait_cb, parser->wait_data );
602 retrotile_parser_mstate( parser, MTILESTATE_TILESETS );
604 }
else if( MTILESTATE_HEIGHT == parser->mstate ) {
605 if( 0 == parser->pass ) {
606 parser->tiles_h = atoi( token );
611 retrotile_parser_mstate( parser, MTILESTATE_NONE );
613 }
else if( MTILESTATE_WIDTH == parser->mstate ) {
614 if( 0 == parser->pass ) {
615 parser->tiles_w = atoi( token );
620 retrotile_parser_mstate( parser, MTILESTATE_NONE );
622 }
else if( MTILESTATE_LAYER_NAME == parser->mstate ) {
624 retrotile_parser_mstate( parser, MTILESTATE_LAYER );
630 retrotile_parser_match_token( token, token_sz, parser );
634 if( NULL != tile_defs ) {
635 maug_munlock( *(parser->p_tile_defs_h), tile_defs );
646 if( MTILESTATE_LAYER_DATA == parser->mstate ) {
647 assert( RETROTILE_PARSER_MODE_MAP == parser->mode );
648 assert( parser->layer_tile_iter == 1600 );
649 retrotile_parser_mstate( parser, MTILESTATE_LAYER );
651 }
else if( MTILESTATE_LAYERS == parser->mstate ) {
652 assert( RETROTILE_PARSER_MODE_MAP == parser->mode );
653 retrotile_parser_mstate( parser, MTILESTATE_NONE );
655 }
else if( MTILESTATE_TILESETS == parser->mstate ) {
656 assert( RETROTILE_PARSER_MODE_MAP == parser->mode );
657 retrotile_parser_mstate( parser, MTILESTATE_NONE );
659 }
else if( MTILESTATE_TILES_PROP == parser->mstate ) {
660 assert( RETROTILE_PARSER_MODE_DEFS == parser->mode );
661 retrotile_parser_mstate( parser, MTILESTATE_TILES );
672 if( MTILESTATE_LAYERS == parser->mstate ) {
673 assert( RETROTILE_PARSER_MODE_MAP == parser->mode );
676 parser->layer_tile_iter = 0;
677 retrotile_parser_mstate( parser, MTILESTATE_LAYER );
688 if( MTILESTATE_LAYER == parser->mstate ) {
689 assert( RETROTILE_PARSER_MODE_MAP == parser->mode );
690 assert( parser->layer_tile_iter == 1600 );
692 "incrementing pass layer to " SIZE_T_FMT
" after " SIZE_T_FMT
694 parser->pass_layer_iter + 1, parser->layer_tile_iter );
695 parser->pass_layer_iter++;
696 retrotile_parser_mstate( parser, MTILESTATE_LAYERS );
698 }
else if( MTILESTATE_GRID == parser->mstate ) {
699 retrotile_parser_mstate( parser, MTILESTATE_NONE );
708 const char* filename, MAUG_MHANDLE* p_tilemap_h,
709 MAUG_MHANDLE* p_tile_defs_h,
size_t* p_tile_defs_count,
710 mparser_wait_cb_t wait_cb,
void* wait_data
713 MAUG_MHANDLE parser_h = (MAUG_MHANDLE)NULL;
715 char filename_path[RETROFLAT_PATH_MAX];
718 char* filename_ext = NULL;
722 maug_cleanup_if_null_alloc( MAUG_MHANDLE, parser_h );
724 maug_mlock( parser_h, parser );
728 parser->tj_parse_cb = retrotile_parse_json_file;
731 memset( filename_path,
'\0', RETROFLAT_PATH_MAX );
734 filename_path, RETROFLAT_PATH_MAX,
"mapsrc/%s", filename );
739 maug_cleanup_if_not_ok();
741 assert( NULL != p_tile_defs_count );
744 for( parser->pass = 0 ; 2 > parser->pass ; parser->pass++ ) {
752 maug_mzero( &(parser->jparser.base),
sizeof(
struct MJSON_PARSER ) );
754 parser->wait_cb = wait_cb;
755 parser->wait_data = wait_data;
756 parser->jparser.base.wait_cb = wait_cb;
757 parser->jparser.base.wait_data = wait_data;
760 filename_ext = maug_strrchr( filename,
'.' );
761 if( NULL == filename_ext ) {
762 error_printf(
"could not parse filename extension!" );
763 retval = MERROR_FILE;
766 if(
's' == filename_ext[2] ) {
768 parser->mode = RETROTILE_PARSER_MODE_DEFS;
769 parser->jparser.token_parser = retrotile_parser_parse_tiledef_token;
770 parser->jparser.token_parser_arg = parser;
771 parser->jparser.close_list = retrotile_json_close_list;
772 parser->jparser.close_list_arg = parser;
773 parser->jparser.close_obj = retrotile_json_close_obj;
774 parser->jparser.close_obj_arg = parser;
779 parser->p_tile_defs_h = p_tile_defs_h;
780 parser->p_tile_defs_count = p_tile_defs_count;
782 assert( NULL != p_tile_defs_h );
783 if( 1 == parser->pass ) {
787 retval = retrotile_alloc_tile_defs(
788 p_tile_defs_h, p_tile_defs_count,
790 maug_cleanup_if_not_ok();
794 parser->mode = RETROTILE_PARSER_MODE_MAP;
796 parser->jparser.close_list = retrotile_json_close_list;
797 parser->jparser.close_list_arg = parser;
798 parser->jparser.open_obj = retrotile_json_open_obj;
799 parser->jparser.open_obj_arg = parser;
800 parser->jparser.close_obj = retrotile_json_close_obj;
801 parser->jparser.close_obj_arg = parser;
802 parser->jparser.token_parser = retrotile_parser_parse_token;
803 parser->jparser.token_parser_arg = parser;
804 parser->p_tile_defs_h = p_tile_defs_h;
805 parser->p_tile_defs_count = p_tile_defs_count;
807 assert( NULL != p_tilemap_h );
808 if( 1 == parser->pass ) {
810 retval = retrotile_alloc(
811 p_tilemap_h, parser->tiles_w, parser->tiles_h,
812 parser->pass_layer_iter );
813 maug_cleanup_if_not_ok();
815 maug_mlock( *p_tilemap_h, parser->t );
817 parser->pass_layer_iter = 0;
820 while( mfile_has_bytes( &buffer ) ) {
821 buffer.read_int( &buffer, (uint8_t*)&c, 1, 0 );
822 retval = mjson_parse_c( &(parser->jparser), c );
823 if( MERROR_OK != retval ) {
824 error_printf(
"error parsing JSON!" );
829 buffer.seek( &buffer, 0 );
831 filename_ext = maug_strrchr( filename,
'.' );
832 if( NULL == filename_ext ) {
833 error_printf(
"could not parse filename extension!" );
834 retval = MERROR_FILE;
837 if(
's' != filename_ext[2] ) {
839 "pass %u found " SIZE_T_FMT
" layers",
840 parser->pass, parser->pass_layer_iter );
849 if( NULL != parser ) {
850 if( NULL != parser->t ) {
851 maug_munlock( *p_tilemap_h, parser->t );
853 maug_munlock( parser_h, parser );
856 if( NULL != parser_h ) {
857 maug_mfree( parser_h );
865static retroflat_tile_t retrotile_gen_diamond_square_rand(
866 retroflat_tile_t min_z, retroflat_tile_t max_z, uint32_t tuning,
867 retroflat_tile_t top_left_z
869 retroflat_tile_t avg = top_left_z;
871 if( 8 > rand() % 10 ) {
873 avg -= (min_z / tuning) + (rand() % (max_z / tuning));
893static void retrotile_gen_diamond_square_corners(
894 int16_t corners_x[2][2], int16_t corners_y[2][2],
895 retroflat_tile_t min_z, retroflat_tile_t max_z,
901 retroflat_tile_t* tile_iter = NULL;
902 retroflat_tile_t top_left_z = 0;
907 for( iter_y = 0 ; iter_y < 2 ; iter_y++ ) {
908 for( iter_x = 0 ; iter_x < 2 ; iter_x++ ) {
911 corners_x[iter_x][iter_y] =
913 if( 0 > corners_x[iter_x][iter_y] ) {
914 corners_x[iter_x][iter_y] += 1;
918 corners_y[iter_x][iter_y] =
920 if( 0 > corners_y[iter_x][iter_y] ) {
921 corners_y[iter_x][iter_y] += 1;
927 assert( 0 <= corners_x[0][0] );
928 assert( 0 <= corners_y[0][0] );
929 assert( t->tiles_w > corners_x[0][0] );
930 assert( t->tiles_h > corners_y[0][0] );
933 top_left_z = retrotile_get_tile(
938 if( 0 > top_left_z ) {
941 corners_x[0][0] >= 0 ? corners_x[0][0] : 0,
942 corners_y[0][0] >= 0 ? corners_y[0][0] : 0 ) = max_z;
947 for( iter_y = 0 ; iter_y < 2 ; iter_y++ ) {
948 for( iter_x = 0 ; iter_x < 2 ; iter_x++ ) {
950 tile_iter = &(retrotile_get_tile(
952 corners_x[iter_x][iter_y],
953 corners_y[iter_x][iter_y] ));
956 if( -1 != *tile_iter ) {
959 corners_x[iter_x][iter_y], corners_y[iter_x][iter_y],
962 corners_x[iter_x][iter_y],
963 corners_y[iter_x][iter_y] ) );
968 *tile_iter = retrotile_gen_diamond_square_rand(
969 min_z, max_z, tuning, top_left_z );
972 "missing corner coord %d x %d: %d",
973 corners_x[iter_x][iter_y], corners_y[iter_x][iter_y],
981static retroflat_tile_t retrotile_gen_diamond_square_avg(
982 int16_t corners_x[2][2], int16_t corners_y[2][2],
985 retroflat_tile_t* tile_iter = NULL;
988 retroflat_tile_t avg = 0;
991 for( iter_y = 0 ; 2 > iter_y ; iter_y++ ) {
992 for( iter_x = 0 ; 2 > iter_x ; iter_x++ ) {
993 tile_iter = &(retrotile_get_tile(
995 corners_x[iter_x][iter_y],
996 corners_y[iter_x][iter_y] ));
997 assert( -1 != *tile_iter );
1017 struct RETROTILE* t, retroflat_tile_t min_z, retroflat_tile_t max_z,
1018 uint32_t tuning,
size_t layer_idx, uint8_t flags,
void* data,
1019 retrotile_ani_cb animation_cb,
void* animation_cb_data
1024 int16_t corners_x[2][2];
1025 int16_t corners_y[2][2];
1029 MAUG_MHANDLE data_ds_h = NULL;
1034 retroflat_tile_t* tile_iter = NULL;
1035 uint8_t free_ds_data = 0;
1042 #define _retrotile_ds_update_statistics( data, tile ) \
1044 if( (data)->highest_generated < (tile) && 32767 > (tile) ) { \
1045 (data)->highest_generated = (tile); \
1047 if( (data)->lowest_generated > (tile) && 0 < (tile) ) { \
1048 (data)->lowest_generated = (tile); \
1051 layer = retrotile_get_layer_p( t, layer_idx );
1059 if( NULL == data ) {
1062 maug_cleanup_if_null_alloc( MAUG_MHANDLE, data_ds_h );
1064 maug_mlock( data_ds_h, data_ds );
1071 memset( retrotile_get_tiles_p( layer ), -1,
1072 t->tiles_w * t->tiles_h *
sizeof( retroflat_tile_t ) );
1076 data_ds->
sect_w = t->tiles_w;
1077 data_ds->
sect_h = t->tiles_h;
1080 data_ds->lowest_generated = 32767;
1083 flags &= ~RETROTILE_DS_FLAG_INIT_DATA;
1087 assert( NULL != data_ds );
1090 if( 0 == data_ds->
sect_w ) {
1105 iter_depth = t->tiles_w / data_ds->
sect_w;
1108 retrotile_gen_diamond_square_corners(
1109 corners_x, corners_y, min_z, max_z, tuning, data_ds, layer, t );
1115 "%d return: reached innermost point", iter_depth );
1120 retrotile_gen_diamond_square_avg( corners_x, corners_y, t, layer );
1122 debug_printf( 1,
"avg :%d", avg );
1124 tile_iter = &(retrotile_get_tile(
1128 if( -1 != *tile_iter ) {
1135 _retrotile_ds_update_statistics( data_ds, avg );
1144 iter_y = data_ds->
sect_y ;
1149 iter_x = data_ds->
sect_x ;
1153 data_ds_sub.sect_x = data_ds->
sect_x + iter_x;
1155 data_ds_sub.sect_y = data_ds->
sect_y + iter_y;
1159 data_ds_sub.sect_w_half = data_ds_sub.sect_w >> 1;
1160 data_ds_sub.sect_h_half = data_ds_sub.sect_h >> 1;
1161 data_ds_sub.lowest_generated = 32767;
1162 data_ds_sub.highest_generated = 0;
1167 data_ds_sub.sect_x, data_ds_sub.sect_y, data_ds_sub.sect_w );
1170 t, min_z, max_z, tuning, layer_idx, flags, &data_ds_sub,
1171 animation_cb, animation_cb_data );
1172 maug_cleanup_if_not_ok();
1174 _retrotile_ds_update_statistics(
1175 data_ds, data_ds_sub.highest_generated );
1176 _retrotile_ds_update_statistics(
1177 data_ds, data_ds_sub.lowest_generated );
1182 data_ds->
sect_w == t->tiles_w >> 1 &&
1183 NULL != animation_cb
1185 retval = animation_cb( animation_cb_data, iter_y );
1186 maug_cleanup_if_not_ok();
1194 if( free_ds_data && NULL != data_ds ) {
1195 maug_munlock( data_ds_h, data_ds );
1198 if( free_ds_data && NULL != data_ds_h ) {
1199 maug_mfree( data_ds_h );
1208 struct RETROTILE* t, retroflat_tile_t min_z, retroflat_tile_t max_z,
1209 uint32_t tuning,
size_t layer_idx, uint8_t flags,
void* data,
1210 retrotile_ani_cb animation_cb,
void* animation_cb_data
1214 int16_t offset_x = 0,
1219 int16_t spb = RETROTILE_VORONOI_DEFAULT_SPB;
1220 int16_t drift = RETROTILE_VORONOI_DEFAULT_DRIFT;
1221 MAUG_MHANDLE temp_grid_h = (MAUG_MHANDLE)NULL;
1222 retroflat_tile_t* temp_grid = NULL;
1223 retroflat_tile_t* tiles = NULL;
1225 int8_t side_iter = 0;
1227 layer = retrotile_get_layer_p( t, 0 );
1229 tiles = retrotile_get_tiles_p( layer );
1233 t->tiles_w * t->tiles_h *
sizeof( retroflat_tile_t ) );
1236 for( y = 0 ; t->tiles_w > y ; y += spb ) {
1237 for( x = 0 ; t->tiles_w > x ; x += spb ) {
1238 offset_x = x + ((drift * -1) + (rand() % drift));
1239 offset_y = y + ((drift * -1) + (rand() % drift));
1242 if( 0 > offset_x ) {
1245 if( offset_x >= t->tiles_w ) {
1246 offset_x = t->tiles_w - 1;
1248 if( 0 > offset_y ) {
1251 if( offset_y >= t->tiles_h ) {
1252 offset_y = t->tiles_h - 1;
1255 retrotile_get_tile( t, layer, offset_x, offset_y ) =
1256 min_z + (rand() % max_z);
1260 temp_grid_h = maug_malloc(
1261 sizeof( retroflat_tile_t ), t->tiles_w * t->tiles_h );
1262 maug_cleanup_if_null_alloc( MAUG_MHANDLE, temp_grid_h );
1264 maug_mlock( temp_grid_h, temp_grid );
1265 maug_cleanup_if_null_alloc( retroflat_tile_t*, temp_grid );
1268 while( !finished ) {
1269 if( NULL != animation_cb ) {
1270 retval = animation_cb( animation_cb_data, -1 );
1271 maug_cleanup_if_not_ok();
1279 sizeof( retroflat_tile_t ) * t->tiles_w * t->tiles_h );
1283 for( y = 0 ; t->tiles_h > y ; y++ ) {
1284 for( x = 0 ; t->tiles_w > x ; x++ ) {
1285 if( -1 == retrotile_get_tile( t, layer, x, y ) ) {
1296 for( side_iter = 0 ; 4 > side_iter ; side_iter++ ) {
1298 SIZE_T_FMT
" (%d), " SIZE_T_FMT
" (%d) ("
1299 SIZE_T_FMT
", " SIZE_T_FMT
")",
1301 gc_retroflat_offsets4_x[side_iter],
1303 gc_retroflat_offsets4_y[side_iter],
1304 t->tiles_w, t->tiles_h );
1309 t->tiles_w > x + gc_retroflat_offsets4_x[side_iter] &&
1310 t->tiles_h > y + gc_retroflat_offsets4_y[side_iter] &&
1312 ((y + gc_retroflat_offsets4_y[side_iter]) *
1314 (x + gc_retroflat_offsets4_x[side_iter])]
1317 retrotile_get_tile( t, layer,
1318 x + gc_retroflat_offsets4_x[side_iter],
1319 y + gc_retroflat_offsets4_y[side_iter] ) =
1320 retrotile_get_tile( t, layer, x, y );
1330 if( NULL != temp_grid ) {
1331 maug_munlock( temp_grid_h, temp_grid );
1334 if( NULL != temp_grid_h ) {
1335 maug_mfree( temp_grid_h );
1344 struct RETROTILE* t, retroflat_tile_t min_z, retroflat_tile_t max_z,
1345 uint32_t tuning,
size_t layer_idx, uint8_t flags,
void* data,
1346 retrotile_ani_cb animation_cb,
void* animation_cb_data
1351 int16_t side_iter = 0,
1357 assert( NULL != t );
1358 layer = retrotile_get_layer_p( t, layer_idx );
1359 assert( NULL != layer );
1361 for( y = 0 ; t->tiles_h > y ; y++ ) {
1362 if( NULL != animation_cb ) {
1363 retval = animation_cb( animation_cb_data, y );
1364 maug_cleanup_if_not_ok();
1366 for( x = 0 ; t->tiles_w > x ; x++ ) {
1372 for( side_iter = 0 ; 8 > side_iter ; side_iter++ ) {
1374 t->tiles_w <= x + gc_retroflat_offsets8_x[side_iter] ||
1375 t->tiles_h <= y + gc_retroflat_offsets8_y[side_iter]
1383 "si %d: x, y: " SIZE_T_FMT
" (+%d), " SIZE_T_FMT
1384 " (+%d) idx: " SIZE_T_FMT,
1386 x + gc_retroflat_offsets8_x[side_iter],
1387 gc_retroflat_offsets8_x[side_iter],
1388 y + gc_retroflat_offsets8_y[side_iter],
1389 gc_retroflat_offsets8_y[side_iter],
1390 ((y + gc_retroflat_offsets8_y[side_iter]) * t->tiles_w) +
1391 x + gc_retroflat_offsets8_x[side_iter] );
1392 sides_sum += retrotile_get_tile(
1394 x + gc_retroflat_offsets8_x[side_iter],
1395 y + gc_retroflat_offsets8_y[side_iter] );
1398 retrotile_get_tile( t, layer, x, y ) = sides_sum / sides_avail;
1410 struct RETROTILE* t, retroflat_tile_t min_z, retroflat_tile_t max_z,
1411 uint32_t tuning,
size_t layer_idx, uint8_t flags,
void* data,
1412 retrotile_ani_cb animation_cb,
void* animation_cb_data
1423 int16_t ctr_iter = 0,
1427 assert( NULL != t );
1428 layer = retrotile_get_layer_p( t, layer_idx );
1429 assert( NULL != layer );
1432 for( i = 0 ; 0 <= borders[i].center ; i++ ) {
1433 borders[i].tiles_changed = 0;
1436 debug_printf( 1,
"adding borders..." );
1438 for( y = 0 ; t->tiles_h > y ; y++ ) {
1439 for( x = 0 ; t->tiles_w > x ; x++ ) {
1441 while( 0 <= borders[i].center ) {
1443 ctr_iter = retrotile_get_tile( t, layer, x, y );
1445 "x: " SIZE_T_FMT
", y: " SIZE_T_FMT
", 0x%04x vs 0x%04x",
1446 x, y, ctr_iter, borders[i].center );
1447 if( ctr_iter != borders[i].center ) {
1455 for( side = 0 ; 8 > side ; side += 2 ) {
1457 x + gc_retroflat_offsets8_x[side] > t->tiles_w ||
1458 y + gc_retroflat_offsets8_y[side] > t->tiles_h
1464 outside_iter = retrotile_get_tile( t, layer,
1465 x + gc_retroflat_offsets8_x[side],
1466 y + gc_retroflat_offsets8_y[side] );
1470 if( side + 4 < 8 ) {
1471 x_plus_1 = x + gc_retroflat_offsets8_x[side + 4];
1472 y_plus_1 = y + gc_retroflat_offsets8_y[side + 4];
1474 x_plus_1 = x + gc_retroflat_offsets8_x[side - 4];
1475 y_plus_1 = y + gc_retroflat_offsets8_y[side - 4];
1479 x_plus_1 < t->tiles_w && y_plus_1 < t->tiles_h &&
1480 outside_iter == borders[i].outside &&
1481 outside_iter == retrotile_get_tile( t, layer,
1482 x_plus_1, y_plus_1 )
1486 retrotile_get_tile( t, layer, x, y ) =
1488 borders[i].tiles_changed++;
1495 for( side = 0 ; 8 > side ; side += 2 ) {
1497 x + gc_retroflat_offsets8_x[side] > t->tiles_w ||
1498 y + gc_retroflat_offsets8_y[side] > t->tiles_h
1504 outside_iter = retrotile_get_tile( t, layer,
1505 x + gc_retroflat_offsets8_x[side],
1506 y + gc_retroflat_offsets8_y[side] );
1510 if( side + 2 < 8 ) {
1511 x_plus_1 = x + gc_retroflat_offsets8_x[side + 2];
1512 y_plus_1 = y + gc_retroflat_offsets8_y[side + 2];
1514 x_plus_1 = x + gc_retroflat_offsets8_x[0];
1515 y_plus_1 = y + gc_retroflat_offsets8_y[0];
1519 x_plus_1 < t->tiles_w && y_plus_1 < t->tiles_h &&
1520 outside_iter == borders[i].outside &&
1521 outside_iter == retrotile_get_tile( t, layer,
1522 x_plus_1, y_plus_1 )
1525 retrotile_get_tile( t, layer, x, y ) =
1526 borders[i].
mod_to[side + 1 < 8 ? side + 1 : 0];
1527 borders[i].tiles_changed++;
1533 for( side = 0 ; 8 > side ; side += 2 ) {
1535 x + gc_retroflat_offsets8_x[side] > t->tiles_w ||
1536 y + gc_retroflat_offsets8_y[side] > t->tiles_h
1542 outside_iter = retrotile_get_tile( t, layer,
1543 x + gc_retroflat_offsets8_x[side],
1544 y + gc_retroflat_offsets8_y[side] );
1546 if( outside_iter == borders[i].outside ) {
1549 retrotile_get_tile( t, layer, x, y ) =
1551 borders[i].tiles_changed++;
1569 struct RETROTILE* tilemap, uint32_t layer_idx
1572 uint8_t* tilemap_buf = (uint8_t*)tilemap;
1574 if( 0 == tilemap->layers_count || layer_idx >= tilemap->layers_count ) {
1575 error_printf(
"invalid layer " UPRINTF_U32_FMT
1576 " requested (of " UPRINTF_U32_FMT
")!",
1577 layer_idx, tilemap->layers_count );
1582 tilemap_buf +=
sizeof(
struct RETROTILE );
1584 while( layer_idx > 0 ) {
1585 tilemap_buf += layer_iter->sz;
1597 MAUG_MHANDLE* p_tile_defs_h,
size_t* p_tile_defs_count,
size_t ndefs
1602 assert( 0 == *p_tile_defs_count );
1603 assert( NULL == *p_tile_defs_h );
1604 debug_printf( 1,
"allocating " SIZE_T_FMT
" tile definitions ("
1605 SIZE_T_FMT
" bytes)...",
1609 maug_cleanup_if_null_alloc( MAUG_MHANDLE, *p_tile_defs_h );
1610 *p_tile_defs_count = ndefs;
1613 maug_mlock( *p_tile_defs_h, tile_defs );
1619 if( NULL != tile_defs ) {
1620 maug_munlock( *p_tile_defs_h, tile_defs );
1629 MAUG_MHANDLE* p_tilemap_h,
size_t w,
size_t h,
size_t layers_count
1633 size_t tilemap_sz = 0;
1637 tilemap_sz =
sizeof(
struct RETROTILE ) +
1639 (layers_count * (w * h *
sizeof( retroflat_tile_t ) ));
1641 debug_printf( 1,
"allocating new tilemap " SIZE_T_FMT
"x" SIZE_T_FMT
1642 " tiles, " SIZE_T_FMT
" layers (" SIZE_T_FMT
" bytes)...",
1643 w, h, layers_count, tilemap_sz );
1645 *p_tilemap_h = maug_malloc( 1, tilemap_sz );
1646 maug_cleanup_if_null_alloc( MAUG_MHANDLE, *p_tilemap_h );
1648 maug_mlock( *p_tilemap_h, tilemap );
1649 maug_cleanup_if_null_alloc(
struct RETROTILE*, tilemap );
1652 tilemap->sz = tilemap_sz;
1653 tilemap->layers_count = layers_count;
1654 tilemap->tiles_w = w;
1655 tilemap->tiles_h = h;
1658 for( i = 0 ; layers_count > i ; i++ ) {
1659 layer_iter = retrotile_get_layer_p( tilemap, i );
1660 assert( NULL != layer_iter );
1662 (w * h *
sizeof( retroflat_tile_t ));
1663 maug_cleanup_if_not_ok();
1668 if( NULL != tilemap ) {
1669 maug_munlock( *p_tilemap_h, tilemap );
int MERROR_RETVAL
Return type indicating function returns a value from this list.
Definition merror.h:19
#define maug_mzero(ptr, sz)
Zero the block of memory pointed to by ptr.
Definition mmem.h:62
MERROR_RETVAL mfile_open_read(const char *filename, mfile_t *p_file)
Open a file and read it into memory or memory-map it.
#define RETROTILE_DS_FLAG_INIT_DATA
Flag for retrotile_gen_diamond_square_iter() indicating that passed RETROTILE_DATA_DS object should b...
Definition retrotil.h:81
MERROR_RETVAL retrotile_gen_smooth_iter(struct RETROTILE *t, retroflat_tile_t min_z, retroflat_tile_t max_z, uint32_t tuning, size_t layer_idx, uint8_t flags, void *data, retrotile_ani_cb animation_cb, void *animation_cb_data)
Average the values in adjacent tiles over an already-generated tilemap.
MERROR_RETVAL retrotile_gen_borders_iter(struct RETROTILE *t, retroflat_tile_t min_z, retroflat_tile_t max_z, uint32_t tuning, size_t layer_idx, uint8_t flags, void *data, retrotile_ani_cb animation_cb, void *animation_cb_data)
Given a list of RETROTILE_DATA_BORDER structs, this will search for occurrences of RETROTILE_DATA_BOR...
MERROR_RETVAL retrotile_gen_diamond_square_iter(struct RETROTILE *t, retroflat_tile_t min_z, retroflat_tile_t max_z, uint32_t tuning, size_t layer_idx, uint8_t flags, void *data, retrotile_ani_cb animation_cb, void *animation_cb_data)
Generate tilemap terrain using diamond square algorithm.
MERROR_RETVAL retrotile_gen_voronoi_iter(struct RETROTILE *t, retroflat_tile_t min_z, retroflat_tile_t max_z, uint32_t tuning, size_t layer_idx, uint8_t flags, void *data, retrotile_ani_cb animation_cb, void *animation_cb_data)
Generate tilemap terrain using voronoi graph.
#define RETROTILE_TILESET_IMAGE_STR_SZ_MAX
Maximum number of chars in a RETROTILE_TILE_DEF::image_path.
Definition retrotil.h:24
#define RETROTILE_TILE_SCALE_DEFAULT
Default value for RETROTILE::tile_scale.
Definition retrotil.h:29
#define RETROTILE_TRACE_LVL
If defined, bring debug printf statements up to this level.
Definition retrotil.h:34
#define RETROTILE_NAME_SZ_MAX
Maximum number of chars in a RETROTILE::name.
Definition retrotil.h:19
Definition retrotil.h:128
retroflat_tile_t mod_to[8]
If the center and outside match, use this mod-to.
Definition retrotil.h:133
Internal data structure used by retrotile_gen_diamond_square_iter().
Definition retrotil.h:111
int16_t sect_y
Starting Y of subsector in a given iteration.
Definition retrotil.h:115
int16_t sect_w
Width of subsector in a given iteration.
Definition retrotil.h:117
int16_t sect_w_half
Half of the width of subsector in a given iteration.
Definition retrotil.h:121
int16_t sect_x
Starting X of subsector in a given iteration.
Definition retrotil.h:113
int16_t sect_h
Height of subsector in a given iteration.
Definition retrotil.h:119
int16_t sect_h_half
Half of the height of subsector in a given iteration.
Definition retrotil.h:123
Definition retrotil.h:160
size_t tileset_id_cur
Highest tileset ID on first pass and next ID to be assigned on second.
Definition retrotil.h:174