Skip to content

Commit

Permalink
Save status counters as a nested properties file for 2.93.
Browse files Browse the repository at this point in the history
  • Loading branch information
AliceLR committed Nov 10, 2023
1 parent d8d1771 commit 26715f2
Show file tree
Hide file tree
Showing 5 changed files with 187 additions and 17 deletions.
1 change: 1 addition & 0 deletions docs/changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ DEVELOPERS
storage, like the NDS.
+ Board input strings, charset paths, and palette paths are now
heap allocated on-demand to save RAM for low-memory systems.
+ Status counters are now saved as a nested properties file.
+ Refactored the 3DS renderer to use templates. (asie)
+ intake2() now supports custom handling of intake events, i.e.
it can now be used without providing a fixed size buffer.
Expand Down
23 changes: 20 additions & 3 deletions docs/fileform.html
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@

td
{
padding: 1px 8px;
padding: 1px 6px;
border: 4px solid transparent;
}

Expand Down Expand Up @@ -359,6 +359,9 @@ <h2>Contents</h2>
<li><a href="#files290">Files List</a></li>
<li><a href="#properties">Properties Format</a></li>
<li><a href="#worldprop290">World Properties</a></li>
<ol type="a">
<li><a href="#statctrprop290">Status Counter Properties</a></li>
</ol>
<li><a href="#sfx290">Custom SFX Table</a></li>
<li><a href="#chars290">Character Sets</a></li>
<li><a href="#pal290">Palettes, Palette Indices, and Palette Intensities</a></li>
Expand Down Expand Up @@ -2398,7 +2401,8 @@ <h3>Properties Format</h3>
The file ends immediately when a property ID of <code>0x0000</code> is
encountered indicating the end of the file. This value is the same for
all different properties files. Unrecognized properties IDs are usually
skipped unless noted otherwise.
skipped unless noted otherwise. The EOF ID should always be present at
the end of the file and there should be no data after the EOF ID.
</p>
<p>
It is possible to nest properties files to create a file with a more
Expand Down Expand Up @@ -2444,7 +2448,7 @@ <h3>World Properties</h3>
| `0x0012` | ID Chars bullet colors | array(b * 3) |
| `0x0013` | ID Chars block 3 (damage) | array(b * 128) |

| `0x0018` | Status counters | array(s15 with \0 * 6) |
| `0x0018` | Status counters | Properties (2.93+)<br>array(s15 with \0 * 6) |

| `0x0020` | Edge color | int(b)
| `0x0021` | First board # | int(b)
Expand Down Expand Up @@ -2514,6 +2518,19 @@ <h3>World Properties</h3>
name if it is not.
</li>
</ol>
<h4 id="statctrprop290">Status Counter Properties</h4>
As of 2.93, the status counters are a nested properties file. Status
counters not present in the properties file are unused/blank.
<div class="markdown">
| ID | Property | Data Type | Notes |
|----------|--------------------------------------|-------------------------|-------|
| `0x0001` | Set current status counter ID | int(b) | Counters >=6 are ignored
| `0x0002` | Status counter name | string | Max. length 14
</div>
Prior to 2.93, the status counters were a fixed size array of 6 15-byte
ASCIIZ strings (total size 90 bytes). In 2.93+ worlds, if the status
counters are 90 bytes long <i>and</i> are not a valid properties file,
they will be loaded as the old format.
</section>

<section id="sfx290" class="inner">
Expand Down
40 changes: 38 additions & 2 deletions src/utils/downver.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,6 @@ struct downver_state

/* 2.93 conversion vars */
int screen_mode;
uint8_t *smzx_colors;
uint8_t *smzx_intensities;
};

static inline void save_prop_p(int ident, struct memfile *prop,
Expand Down Expand Up @@ -171,6 +169,40 @@ static enum zip_error zip_duplicate_file(struct downver_state *dv,
return result;
}

static void convert_293_to_292_status_counters(struct downver_state *dv,
struct memfile *dest, struct memfile *src)
{
char counters[NUM_STATUS_COUNTERS * COUNTER_NAME_SIZE];
struct memfile prop;
int ident;
int len;
int num = 0;

memset(counters, 0, sizeof(counters));

while(next_prop(&prop, &ident, &len, src))
{
switch(ident)
{
case STATCTRPROP_SET_ID:
num = load_prop_int(&prop);
break;

case STATCTRPROP_NAME:
if(num < NUM_STATUS_COUNTERS)
{
char *pos = counters + num * COUNTER_NAME_SIZE;
len = MIN(len, COUNTER_NAME_SIZE - 1);
len = mfread(pos, 1, len, &prop);
pos[len] = '\0';
}
break;
}
}
save_prop_a(WPROP_STATUS_COUNTERS, counters,
COUNTER_NAME_SIZE, NUM_STATUS_COUNTERS, dest);
}

static void convert_293_to_292_world_info(struct downver_state *dv,
struct memfile *dest, struct memfile *src)
{
Expand All @@ -193,6 +225,10 @@ static void convert_293_to_292_world_info(struct downver_state *dv,
save_prop_s_to_asciiz(ident, BOARD_NAME_SIZE, &prop, dest);
break;

case WPROP_STATUS_COUNTERS:
convert_293_to_292_status_counters(dv, dest, &prop);
break;

case WPROP_SMZX_MODE:
/* Load for palette conversion. */
dv->screen_mode = load_prop_int(&prop);
Expand Down
86 changes: 77 additions & 9 deletions src/world.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,12 +298,30 @@ static inline int save_world_info(struct world *mzx_world,
save_prop_a(WPROP_ID_DMG, id_dmg, ID_DMG_SIZE, 1, mf);

// Status counters
save_prop_v(WPROP_STATUS_COUNTERS, COUNTER_NAME_SIZE * NUM_STATUS_COUNTERS,
prop, mf);
if(file_version >= V293)
{
char counters[STATCTR_PROP_SIZE];
mfopen_wr(counters, sizeof(counters), prop);

for(i = 0; i < NUM_STATUS_COUNTERS; i++)
for(i = 0; i < NUM_STATUS_COUNTERS; i++)
{
char *ctr = mzx_world->status_counters_shown[i];
if(ctr[0])
{
save_prop_c(STATCTRPROP_SET_ID, i, prop);
save_prop_s(STATCTRPROP_NAME, ctr, prop);
}
}
save_prop_eof(prop);
save_prop_a(WPROP_STATUS_COUNTERS, counters, mftell(prop), 1, mf);
}
else
{
mfwrite(mzx_world->status_counters_shown[i], COUNTER_NAME_SIZE, 1, prop);
save_prop_v(WPROP_STATUS_COUNTERS, COUNTER_NAME_SIZE * NUM_STATUS_COUNTERS,
prop, mf);

for(i = 0; i < NUM_STATUS_COUNTERS; i++)
mfwrite(mzx_world->status_counters_shown[i], COUNTER_NAME_SIZE, 1, prop);
}

// Global properties
Expand Down Expand Up @@ -580,6 +598,58 @@ static inline enum val_result validate_world_info(struct world *mzx_world,
return VAL_INVALID;
}

static inline void load_status_counter_info(struct world *mzx_world,
int *file_version, struct memfile *mf)
{
struct memfile prop;
int ident;
int len;
size_t num = 0;
boolean load_properties = false;
int i;

if(*file_version >= V293)
{
// Allow old format status counters in 2.93 worlds for convenience.
// The old format is 90 bytes long and should fail the properties file check.
if(mf->end - mf->start != NUM_STATUS_COUNTERS * COUNTER_NAME_SIZE ||
check_properties_file(mf, STATCTRPROP_NAME))
{
load_properties = true;
}
}

if(load_properties)
{
while(next_prop(&prop, &ident, &len, mf))
{
switch(ident)
{
case STATCTRPROP_SET_ID:
num = load_prop_int(&prop);
break;

case STATCTRPROP_NAME:
if(num < ARRAY_SIZE(mzx_world->status_counters_shown))
{
len = MIN((size_t)len, sizeof(mzx_world->status_counters_shown[num]) - 1);
len = mfread(mzx_world->status_counters_shown[num], 1, len, &prop);
mzx_world->status_counters_shown[num][len] = '\0';
}
break;
}
}
}
else
{
for(i = 0; i < NUM_STATUS_COUNTERS; i++)
{
mfread(mzx_world->status_counters_shown[i], COUNTER_NAME_SIZE, 1, mf);
mzx_world->status_counters_shown[i][COUNTER_NAME_SIZE - 1] = '\0';
}
}
}

#define if_savegame if(!savegame) { break; }
#define if_savegame_or_291 if(!savegame && *file_version < V291) { break; }

Expand Down Expand Up @@ -694,11 +764,7 @@ static inline void load_world_info(struct world *mzx_world,

// Status counters
case WPROP_STATUS_COUNTERS:
for(i = 0; i < NUM_STATUS_COUNTERS; i++)
{
mfread(mzx_world->status_counters_shown[i], COUNTER_NAME_SIZE, 1, prop);
mzx_world->status_counters_shown[i][COUNTER_NAME_SIZE - 1] = '\0';
}
load_status_counter_info(mzx_world, file_version, prop);
break;

// Global properties
Expand Down Expand Up @@ -3468,6 +3534,8 @@ void clear_world(struct world *mzx_world)
int num_boards = mzx_world->num_boards;
struct board **board_list = mzx_world->board_list;

memset(mzx_world->status_counters_shown, 0, NUM_STATUS_COUNTERS * COUNTER_NAME_SIZE);

for(i = 0; i < num_boards; i++)
{
if(mzx_world->current_board_id != i)
Expand Down
54 changes: 51 additions & 3 deletions src/world_format.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,26 @@ enum world_file_id
#define PROP_HEADER_SIZE 6
#define PROP_EOF_SIZE 2

#define STATS_SIZE NUM_STATUS_COUNTERS * COUNTER_NAME_SIZE
#define COUNT_STATCTR_PROPS (NUM_STATUS_COUNTERS * (2))
#define BOUND_STATCTR_PROPS (NUM_STATUS_COUNTERS * (1 + COUNTER_NAME_SIZE))

#define STATCTR_PROP_SIZE \
( \
BOUND_STATCTR_PROPS + \
COUNT_STATCTR_PROPS * PROP_HEADER_SIZE + \
PROP_EOF_SIZE \
)

enum status_counters_prop
{
STATCTRPROP_SET_ID = 0x0001, // 1
STATCTRPROP_NAME = 0x0002, // COUNTER_NAME_SIZE
};

// IF YOU ADD ANYTHING, MAKE SURE THIS GETS UPDATED!

#define COUNT_WORLD_PROPS ( 1 + 3 + 4 + 16 + 4 + 1)
#define BOUND_WORLD_PROPS (BOARD_NAME_SIZE + 5 + 455 + 24 + 9 + STATS_SIZE)
#define COUNT_WORLD_PROPS ( 1 + 3 + 4 + 16 + 4 + 1)
#define BOUND_WORLD_PROPS (BOARD_NAME_SIZE + 5 + 455 + 24 + 9 + STATCTR_PROP_SIZE)

#define COUNT_SAVE_PROPS ( 2 + 32 + 3 + 1)
#define BOUND_SAVE_PROPS ( 2 + 120 + 3*MAX_PATH + NUM_KEYS)
Expand Down Expand Up @@ -919,6 +933,40 @@ static inline boolean next_prop(struct memfile *prop, int *ident, int *length,
return true;
}

/**
* Returns true if the properties file in `mf` is valid.
* This can be used to distinguish whether or not an ambiguous file or field
* actually contains properties.
*/
static inline boolean check_properties_file(struct memfile *mf,
int maximum_ident)
{
int ident;
unsigned length;
while(mf->end - mf->current >= 6)
{
ident = mfgetw(mf);
length = mfgetud(mf);
if(ident == 0 || ident > maximum_ident)
goto err;

if((unsigned)(mf->end - mf->current) < length)
goto err;

mf->current += length;
}

if((mf->end - mf->current == 2) && mfgetw(mf) == 0x0000) // EOF
{
mf->current = mf->start;
return true;
}

err:
mf->current = mf->start;
return false;
}

__M_END_DECLS

#endif // __WORLD_FORMAT_H

0 comments on commit 26715f2

Please sign in to comment.