aboutsummaryrefslogtreecommitdiff
path: root/project/src/lib-lecode.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--project/src/lib-lecode.c922
1 files changed, 692 insertions, 230 deletions
diff --git a/project/src/lib-lecode.c b/project/src/lib-lecode.c
index 45f4277..59b1024 100644
--- a/project/src/lib-lecode.c
+++ b/project/src/lib-lecode.c
@@ -74,6 +74,20 @@ bool opt_complete = false;
/////////////// helpers ///////////////
///////////////////////////////////////////////////////////////////////////////
+ccp GetLecodeSupportWarning ( const le_analyze_t *ana )
+{
+ DASSERT(ana);
+ return !( ana->valid & LE_HEAD_VALID )
+ ? "LE-CODE file header is invalid"
+ : GetEncodedVersion() < ana->szs_version
+ ? PrintCircBuf("SZS Tools v%s or younger required",DecodeVersion(ana->szs_version))
+ : IsLecodeSupported(ana->valid)
+ ? 0
+ : PrintCircBuf("LE-CODE v%u is not supported",ana->header_vers);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
uint GetNextRacingTrackLE ( uint tid )
{
if ( ++tid == 0xff )
@@ -438,13 +452,13 @@ int ScanOptEngine ( ccp arg )
const VarMap_t * SetupVarsLECODE()
{
- static VarMap_t vm = {0};
+ static VarMap_t vm = { .force_case = LOUP_UPPER };
if (!vm.used)
{
DefineMkwVars(&vm);
- //DefineParserFuncTab(lex_func_tab,FF_LPAR);
DefineParserVars(&vm);
+
//--- setup integer variables
struct inttab_t { ccp name; int val; };
@@ -473,11 +487,6 @@ const VarMap_t * SetupVarsLECODE()
{ "VS", LTTY_TRACK },
{ "FILL", -1 },
- { "RALL", MKW_LE_RANDOM_BEG+0 },
- { "RORIG", MKW_LE_RANDOM_BEG+1 },
- { "RCUST", MKW_LE_RANDOM_BEG+2 },
- { "RNEW", MKW_LE_RANDOM_BEG+3 },
-
{ "LE$STRING_LIST_ENABLED", LE_STRING_LIST_ENABLED },
{ "LE$STRING_SET_ENABLED", LE_STRING_SET_ENABLED },
{ "LE$TYPE_MARKERS_ENABLED",LE_TYPE_MARKERS_ENABLED },
@@ -565,7 +574,9 @@ bool GetNextDebugMode ( lecode_debug_info_t *ldi )
{ LEDEB_ITEM_POINT, 0, "ITEM-POINT" },
{ LEDEB_KCL_TYPE, 0, "KCL-TYPE" },
{ LEDEB_LAP_POS, 0, "LAP-POS" },
+ { LEDEB_TRACK_ID, 0, "TRACK-ID" },
{ LEDEB_XPF, LEDEB_S_XPF, "XPF" },
+ // [[new-debug]]
};
while ( ldi->index >= 0 && ldi->index < sizeof(tab)/sizeof(*tab) )
@@ -610,7 +621,9 @@ lecode_debug_t DecodeLecodeDebug ( lecode_debug_ex_t *lde, lecode_debug_t mode )
lde->item_point = ( mode & LEDEB_ITEM_POINT ) > 0;
lde->kcl_type = ( mode & LEDEB_KCL_TYPE ) > 0;
lde->lap_pos = ( mode & LEDEB_LAP_POS ) > 0;
+ lde->track_id = ( mode & LEDEB_TRACK_ID ) > 0;
lde->xpf = mode >> LEDEB_S_XPF & LEDEB_M_XPF;
+ // [[new-debug]]
lde->have_output = isDebugModeOutput(mode);
lde->is_active = isDebugModeActive(mode);
@@ -635,6 +648,8 @@ lecode_debug_t EncodeLecodeDebug ( lecode_debug_ex_t *lde )
if ( lde->item_point ) mode |= LEDEB_ITEM_POINT;
if ( lde->kcl_type ) mode |= LEDEB_KCL_TYPE;
if ( lde->lap_pos ) mode |= LEDEB_LAP_POS;
+ if ( lde->track_id ) mode |= LEDEB_TRACK_ID;
+ // [[new-debug]]
return DecodeLecodeDebug(lde,mode); // normalize all settings
}
@@ -694,7 +709,9 @@ bool SetupLecodeDebugLPAR
{ PREDEBUG_VERTICAL, 4, LEDEB_KCL_TYPE },
{ PREDEBUG_VERTICAL, 5, LEDEB_LAP_POS },
{ PREDEBUG_VERTICAL, 6, LEDEB_POSITION },
- { PREDEBUG_VERTICAL, 7, LEDEB_LONG_XPF },
+ { PREDEBUG_VERTICAL, 7, LEDEB_TRACK_ID },
+ { PREDEBUG_VERTICAL, 8, LEDEB_LONG_XPF },
+ // [[new-debug]]
{0,0,0}
};
@@ -718,7 +735,6 @@ bool SetupLecodeDebugLPAR
else
debug_list[ptr->line] = ptr->mode | LEDEB_ENABLED;
}
-
if (hide_speedo)
*hide_speedo = my_hide_speedo;
@@ -889,13 +905,13 @@ ccp GetInfoLECODE ( mem_t lecode )
region, debug,
ntohl(head->version),
ntohl(head->build_number),
- ntohl(head->size) )
+ ntohl(head->file_size) )
: PrintCircBuf("%s%s v%u, build %u (%s UTC), %u bytes",
region, debug,
ntohl(head->version),
ntohl(head->build_number),
head->timestamp,
- ntohl(head->size) );
+ ntohl(head->file_size) );
}
//
@@ -1150,6 +1166,9 @@ void InitializeLPAR ( le_lpar_t *lpar, bool load_lpar )
lpar->enable_xpflags = 1;
lpar->drag_blue_shell = 1;
lpar->thcloud_frames = 300;
+ lpar->block_textures = 1;
+
+ // [[new-lpar]]
if ( load_lpar && opt_lpar )
LoadLPAR(lpar,false,0,false);
@@ -1191,6 +1210,13 @@ static void NormalizeLPAR ( le_lpar_t * lp )
lp->block_track = lp->block_track < LE_MAX_BLOCK_TRACK
? lp->block_track : LE_MAX_BLOCK_TRACK;
lp->drag_blue_shell = lp->drag_blue_shell > 0;
+ lp->bt_worldwide = lp->bt_worldwide > 0;
+ lp->vs_worldwide = lp->vs_worldwide > 0;
+ lp->bt_textures = lp->bt_textures & LE_M_TEXTURE;
+ lp->vs_textures = lp->vs_textures & LE_M_TEXTURE;
+ lp->block_textures = lp->block_textures > 0;
+
+ // [[new-lpar]]
#if 0
for ( int c = 0; c < LEDEB__N_CONFIG; c++ )
@@ -1198,15 +1224,22 @@ static void NormalizeLPAR ( le_lpar_t * lp )
lp->debug[c][l] &= LEDEB__ALL;
#endif
- // [[new-lpar]]
}
+
///////////////////////////////////////////////////////////////////////////////
-static void CopyLPAR2Data ( le_analyse_t * ana )
+static void CopyLPAR2Data ( le_analyze_t * ana )
{
DASSERT(ana);
+ ccp warn = GetLecodeSupportWarning(ana);
+ if (warn)
+ {
+ ERROR0(ERR_INVALID_DATA,"Can't patch LE-CODE because %s.",warn);
+ return;
+ }
+
NormalizeLPAR(&ana->lpar);
const le_lpar_t *lp = &ana->lpar;
le_binpar_v1_t *h = ana->param_v1;
@@ -1262,6 +1295,18 @@ static void CopyLPAR2Data ( le_analyse_t * ana )
if ( offsetof(le_binpar_v1_t,thcloud_frames) < ana->param_size )
h->thcloud_frames = htons(lp->thcloud_frames);
+ if ( offsetof(le_binpar_v1_t,bt_worldwide) < ana->param_size )
+ h->bt_worldwide = lp->bt_worldwide;
+ if ( offsetof(le_binpar_v1_t,vs_worldwide) < ana->param_size )
+ h->vs_worldwide = lp->vs_worldwide;
+
+ if ( offsetof(le_binpar_v1_t,bt_textures) < ana->param_size )
+ h->bt_textures = lp->bt_textures;
+ if ( offsetof(le_binpar_v1_t,vs_textures) < ana->param_size )
+ h->vs_textures = lp->vs_textures;
+ if ( offsetof(le_binpar_v1_t,block_textures) < ana->param_size )
+ h->block_textures = lp->block_textures;
+
// [[new-lpar]]
}
@@ -1357,6 +1402,17 @@ static ccp PrintChatMode ( u16 msg, u16 mode1, u16 mode2, int numeric )
///////////////////////////////////////////////////////////////////////////////
+static ccp lpar_std_flags ( uint flags )
+{
+ return PrintCircBuf("LE$%sABLE%s%s%s",
+ flags & LE_ENABLED ? "EN" : "DIS",
+ flags & LE_ALTERABLE ? " | LE$ALTERABLE" : "",
+ flags & LE_EXCLUDED ? " | LE$EXCLUDE" : "",
+ flags & LE_INCLUDED ? " | LE$INCLUDE" : "" );
+}
+
+//-----------------------------------------------------------------------------
+
enumError WriteSectionLPAR
(
FILE *f, // output files
@@ -1391,6 +1447,10 @@ enumError WriteSectionLPAR
,lpar->item_cheat
,lpar->drag_blue_shell
,lpar->thcloud_frames,lpar->thcloud_frames/60.0
+ // [[worldwide]] should be included here, see below for a temporary solution
+ ,lpar_std_flags( lpar->bt_textures & LE_M_TEXTURE )
+ ,lpar_std_flags( lpar->vs_textures & LE_M_TEXTURE )
+ ,lpar->block_textures
);
}
else
@@ -1411,6 +1471,10 @@ enumError WriteSectionLPAR
"ITEM-CHEAT = %u\r\n"
"DRAG-BLUE-SHELL = %u\r\n"
"THCLOUD-TIME = %u # %.2fs\r\n"
+ "BT-TEXTURES = %s\r\n"
+ "VS-TEXTURES = %s\r\n"
+ "BLOCK-TEXTURES = %u\r\n"
+ // [[worldwide]] should be included here, see below for a temporary solution
,GetLparModeName(CalcCurrentLparMode(lpar,true),export_count>0)
,lpar->cheat_mode
,lpar->engine[0],lpar->engine[1],lpar->engine[2]
@@ -1424,9 +1488,22 @@ enumError WriteSectionLPAR
,lpar->item_cheat
,lpar->drag_blue_shell
,lpar->thcloud_frames,lpar->thcloud_frames/60.0
+ ,lpar_std_flags( lpar->bt_textures & LE_M_TEXTURE )
+ ,lpar_std_flags( lpar->vs_textures & LE_M_TEXTURE )
+ ,lpar->block_textures
);
+
}
+ // [[worldwide]]
+ if ( lpar->bt_worldwide || lpar->vs_worldwide )
+ fprintf(f,
+ "BT-WORLDWIDE = %u\r\n"
+ "VS-WORLDWIDE = %u\r\n"
+ ,lpar->bt_worldwide,
+ lpar->vs_worldwide
+ );
+
//--- chat modes
@@ -1457,7 +1534,7 @@ enumError WriteSectionLPAR
fputs("\r\n",f);
}
- fprintf(f,"%s\n",PrintChatMode(i,mode1,mode2,export_count));
+ fprintf(f,"%s\r\n",PrintChatMode(i,mode1,mode2,export_count));
}
}
@@ -1472,11 +1549,11 @@ enumError WriteSectionLPAR
{
fprintf(f,"\r\n#\f\r\n%.79s\r\n\r\n[DEBUG-%u]\r\n",Hash200,conf+1);
if (verbose)
- fputs("# See section [DEBUG-DOCU] for details.\n",f);
+ fputs("# See section [DEBUG-DOCU] for details.\r\n",f);
fprintf(f,"\r\n"
- "SETUP\t\t= DEBUG$%s\n"
- "HIDE-SPEEDO\t= %u\n",
+ "SETUP\t\t= DEBUG$%s\r\n"
+ "HIDE-SPEEDO\t= %u\r\n",
GetPredefDebugName(lpar->debug_predef[conf]),
( 1<<conf & lpar->no_speedo_if_debug ) != 0 );
@@ -1508,7 +1585,7 @@ enumError WriteSectionLPAR
{
if (!line_printed)
{
- fprintf(f,"\nLINE\t\t= %u\r\n",idx);
+ fprintf(f,"\r\nLINE\t\t= %u\r\n",idx);
line_printed = true;
}
fprintf(f,"%s%.*s= %u\r\n",
@@ -1527,11 +1604,12 @@ enumError WriteSectionLPAR
/////////////// analyse ///////////////
///////////////////////////////////////////////////////////////////////////////
-void ResetLEAnalyse ( le_analyse_t *ana )
+void ResetLEAnalyze ( le_analyze_t *ana )
{
if (ana)
{
- ResetLEAnalyseUsage(ana);
+ ResetLEAnalyzeUsage(ana);
+ FREE(ana->flags);
memset(ana,0,sizeof(*ana));
InitializeLPAR(&ana->lpar,false);
}
@@ -1539,7 +1617,7 @@ void ResetLEAnalyse ( le_analyse_t *ana )
///////////////////////////////////////////////////////////////////////////////
-void ResetLEAnalyseUsage ( le_analyse_t *ana )
+void ResetLEAnalyzeUsage ( le_analyze_t *ana )
{
if (ana)
{
@@ -1554,34 +1632,56 @@ void ResetLEAnalyseUsage ( le_analyse_t *ana )
///////////////////////////////////////////////////////////////////////////////
-static void ApplyArena ( le_analyse_t * ana, const ctcode_arena_t * ca )
+static void ApplyArena ( le_analyze_t * ana, const ctcode_arena_t * ca )
{
DASSERT(ana);
DASSERT(ca);
if (!ana->arena_setup)
- SetupArenasLEAnalyse(ana,false);
+ SetupArenasLEAnalyze(ana,false);
- if (ana->property)
+ if ( ana->property && ana->music && ana->flags)
+ {
for ( int a = 0; a < MKW_N_ARENAS; a++ )
+ {
+ const int slot = MKW_ARENA_BEG + a;
if (ca->prop[a])
{
- ana->property[a+MKW_ARENA_BEG] = ca->prop[a];
- ana->arena_applied = true;
+ const le_property_t prop = ca->prop[a];
+ if (IsLecodeRandom(prop))
+ {
+ for ( int idx = 0; idx < 10; idx++ )
+ if ( ntohl(ana->cup_arena[idx]) == slot )
+ {
+ ana->cup_arena[idx] = htonl(prop);
+ break;
+ }
+ }
+ else
+ {
+ ana->property[slot] = prop;
+ ana->arena_applied = true;
+ }
}
- if (ana->music)
- for ( int a = 0; a < MKW_N_ARENAS; a++ )
if (ca->music[a])
{
- ana->music[a+MKW_ARENA_BEG] = ca->music[a];
+ ana->music[slot] = ca->music[a];
ana->arena_applied = true;
}
+
+ if ( ca->flags[a] & CT_ARENA_FLAGS_VALID )
+ {
+ ana->flags[slot] = ca->flags[a] & LEFL__ALL;
+ ana->arena_applied = true;
+ }
+ }
+ }
}
///////////////////////////////////////////////////////////////////////////////
-void SetupArenasLEAnalyse ( le_analyse_t *ana, bool force )
+void SetupArenasLEAnalyze ( le_analyze_t *ana, bool force )
{
DASSERT(ana);
if ( ana->property && ana->music )
@@ -1614,19 +1714,19 @@ void SetupArenasLEAnalyse ( le_analyse_t *ana, bool force )
///////////////////////////////////////////////////////////////////////////////
-enumError AnalyseLEBinary
+enumError AnalyzeLEBinary
(
- le_analyse_t *ana, // NULL or destination of analysis
+ le_analyze_t *ana, // NULL or destination of analysis
const void *data, // data pointer
uint data_size // data size
)
{
//--- setup analyse
- le_analyse_t ana0 = {0};
+ le_analyze_t ana0 = {0};
if (!ana)
{
- ResetLEAnalyse(&ana0);
+ ResetLEAnalyze(&ana0);
ana = &ana0;
}
memset(ana,0,sizeof(*ana));
@@ -1639,41 +1739,67 @@ enumError AnalyseLEBinary
}
le_binary_head_t *head = (le_binary_head_t*)data;
- const uint head_size = ntohl(head->size);
- if ( head_size > data_size )
+ const uint file_size = ntohl(head->file_size);
+ if ( file_size > data_size )
return ERR_INVALID_DATA;
ana->valid = LE_HEAD_FOUND;
ana->version = head->phase;
ana->region = GetLEREG(head->region);
ana->data = data;
- ana->size = data_size;
+ ana->data_size = data_size;
ana->head = head;
- ana->head_vers = ntohl(head->version);
- ana->head_size = head_size;
- ana->end_of_data = (u8*)data + head_size;
+ ana->header_vers = ntohl(head->version);
+ ana->end_of_data = (u8*)data + file_size;
+ ana->flags_bits = ntohl(head->build_number) < 35 ? 8 : 16;
+ ana->le_random_beg = MKW_LE_RANDOM_BEG;
+ ana->le_random_end = MKW_LE_RANDOM_END;
uint off_param = 0;
- switch(ana->head_vers)
+ switch(ana->header_vers)
{
case 4:
- if ( ana->size > sizeof(le_binary_head_v4_t) )
+ if ( ana->data_size > sizeof(le_binary_head_v4_t) )
+ {
+ off_param = ntohl(ana->head_v4->off_param);
+ ana->header_size = sizeof(le_binary_head_v4_t);
+ ana->le_random_beg = MKW_LE_RANDOM_BY_CUP;
+ ana->valid |= LE_HEAD_VALID | LE_HEAD_KNOWN;
+
+ time_t tim;
+ ScanDateTime(&tim,0,ana->head_v4->timestamp,false,0);
+ ana->creation_time = tim;
+ }
+ break;
+
+ case 5:
+ if ( ana->data_size > sizeof(le_binary_head_v5_t) )
{
- ana->valid |= LE_HEAD_VALID | LE_HEAD_KNOWN;
- off_param = ntohl(ana->head_v4->off_param);
+ off_param = ntohl(ana->head_v5->off_param);
+ ana->szs_version = ntohl(ana->head_v5->szs_version);
+ ana->edit_version = ntohl(ana->head_v5->edit_version);
+ ana->header_size = ntohl(ana->head_v5->head_size);
+ ana->creation_time = ntohl(ana->head_v5->creation_time);
+ ana->edit_time = ntohl(ana->head_v5->edit_time);
+
+ if ( ana->edit_version != 0x32303232 ) // first 4 bytes of "2022-10-23" => invalid
+ ana->valid |= LE_HEAD_VALID | LE_HEAD_KNOWN;
}
break;
default:
- // at least v4
- if ( ana->head_vers > 4 && ana->size > sizeof(le_binary_head_t) )
+ if ( ana->header_vers > 5 && ana->data_size > sizeof(le_binary_head_t) )
{
- ana->valid |= LE_HEAD_VALID;
- off_param = ntohl(head->off_param);
+ off_param = ntohl(head->off_param);
+ ana->header_size = ntohl(ana->head_v5->head_size);
+ ana->valid |= LE_HEAD_VALID;
}
break;
}
+ if ( GetEncodedVersion() >= ana->szs_version )
+ ana->valid |= LE_HEAD_VERSION;
+
//--- analyse parameters (prepare)
@@ -1685,7 +1811,7 @@ enumError AnalyseLEBinary
ptr_ana_t;
#undef DEF_TAB
- #define DEF_TAB(s,o,p) { offsetof(s,o), offsetof(le_analyse_t,p) },
+ #define DEF_TAB(s,o,p) { offsetof(s,o), offsetof(le_analyze_t,p) },
const u8 *ptr_list[8]; // for section-size analysis
uint n_ptr = 0; // number of used pointers
@@ -1695,13 +1821,13 @@ enumError AnalyseLEBinary
if ( off_param
&& !(off_param&3)
- && ana->size >= off_param + sizeof(le_binary_param_t)
+ && ana->data_size >= off_param + sizeof(le_binary_param_t)
&& !memcmp(data+off_param,LE_PARAM_MAGIC,4) )
{
le_binary_param_t *param = (le_binary_param_t*)(data+off_param);
const uint param_size = ntohl(param->size);
if ( off_param + param_size <= data_size
- && off_param + param_size <= ana->head_size )
+ && off_param + param_size <= ana->data_size )
{
ana->valid |= LE_PARAM_FOUND;
ana->param = param;
@@ -1709,7 +1835,7 @@ enumError AnalyseLEBinary
ana->param_vers = ntohl(param->version);
ana->param_size = param_size;
- const uint max_off = ana->head_size - off_param;
+ const uint max_off = ana->data_size - off_param;
switch(ana->param_vers)
{
@@ -1725,7 +1851,7 @@ enumError AnalyseLEBinary
DEF_TAB( le_binpar_v1_35_t, off_course_par, course_par )
DEF_TAB( le_binpar_v1_35_t, off_property, property )
DEF_TAB( le_binpar_v1_35_t, off_music, music )
- DEF_TAB( le_binpar_v1_35_t, off_flags, flags )
+ DEF_TAB( le_binpar_v1_35_t, off_flags, flags_bin )
{-1,-1}
};
@@ -1807,7 +1933,19 @@ enumError AnalyseLEBinary
// ana->lpar.thcloud_frames = 300;
// }
- break; // [[new-lpar]]
+ if ( param_size >= sizeof(le_binpar_v1_26c_t) )
+ {
+ le_binpar_v1_26c_t *p = (le_binpar_v1_26c_t*)(data+off_param);
+ ana->lpar.bt_worldwide = p->bt_worldwide;
+ ana->lpar.vs_worldwide = p->vs_worldwide;
+ ana->lpar.bt_textures = p->bt_textures;
+ ana->lpar.vs_textures = p->vs_textures;
+ ana->lpar.block_textures = p->block_textures;
+ }
+
+ // [[new-lpar]]
+
+ break;
default:
// at least v1
@@ -1827,7 +1965,7 @@ enumError AnalyseLEBinary
if (ana->end_of_data)
{
- const int size = ana->data + ana->size - ana->end_of_data;
+ const int size = ana->data + ana->data_size - ana->end_of_data;
if ( size >= 0 )
{
ana->bin_data = ana->end_of_data;
@@ -1848,9 +1986,9 @@ enumError AnalyseLEBinary
ana_n_max_t;
#undef DEF_TAB
- #define DEF_TAB(p,n,m,s) { offsetof(le_analyse_t,p), \
- offsetof(le_analyse_t,n), \
- offsetof(le_analyse_t,m), \
+ #define DEF_TAB(p,n,m,s) { offsetof(le_analyze_t,p), \
+ offsetof(le_analyze_t,n), \
+ offsetof(le_analyze_t,m), \
sizeof(*ana->p)*s },
static const ana_n_max_t n_max_tab[] =
@@ -1859,7 +1997,7 @@ enumError AnalyseLEBinary
DEF_TAB( cup_arena, n_cup_arena, max_cup_arena, 5 )
DEF_TAB( property, n_slot, max_property, 1 )
DEF_TAB( music, n_slot, max_music, 1 )
- DEF_TAB( flags, n_slot, max_flags, 1 )
+ DEF_TAB( flags_bin, n_slot, max_flags, 1 )
{-1,-1,-1}
};
@@ -1875,7 +2013,7 @@ enumError AnalyseLEBinary
for ( pnm = n_max_tab; pnm->off_ptr >= 0; pnm++ )
{
const u8 *ptr = *(u8**)((u8*)ana+pnm->off_ptr);
- const u8 *end = data + ana->head_size;
+ const u8 *end = data + ana->data_size;
uint i;
for ( i = 0; i < n_ptr; i++ )
if ( ptr_list[i] > ptr && ptr_list[i] < end )
@@ -1886,9 +2024,31 @@ enumError AnalyseLEBinary
*(uint*)((u8*)ana+pnm->off_max) = max;
}
- SetupArenasLEAnalyse(ana,false);
+
+ //--- setup flags
+
+ if ( ana->flags_bits == 16 )
+ {
+ ana->max_flags /= 2;
+ ana->flags = MALLOC(ana->max_flags*sizeof(*ana->flags));
+ const le_flags_t *src = (le_flags_t*)ana->flags_bin;
+ if (src)
+ for ( int i = 0; i < ana->max_flags; i++ )
+ ana->flags[i] = be16(src++);
+ }
+ else
+ {
+ ana->flags = MALLOC(ana->max_flags*sizeof(*ana->flags));
+ const le_flags8_t *src = (le_flags8_t*)ana->flags_bin;
+ if (src)
+ for ( int i = 0; i < ana->max_flags; i++ )
+ ana->flags[i] = *src++;
+ }
+
+ SetupArenasLEAnalyze(ana,false);
CalculateStatsLE(ana);
+
//--- return
return ana->valid & LE_PARAM_VALID ? ERR_OK :
@@ -1898,7 +2058,7 @@ enumError AnalyseLEBinary
///////////////////////////////////////////////////////////////////////////////
-le_region_t GetLERegion ( const le_analyse_t *ana )
+le_region_t GetLERegion ( const le_analyze_t *ana )
{
if (ana->valid)
{
@@ -1916,9 +2076,9 @@ le_region_t GetLERegion ( const le_analyse_t *ana )
///////////////////////////////////////////////////////////////////////////////
-void CalculateStatsLE ( le_analyse_t *ana )
+void CalculateStatsLE ( le_analyze_t *ana )
{
- ResetLEAnalyseUsage(ana);
+ ResetLEAnalyzeUsage(ana);
ana->used_rslots = 0;
ana->max_rslots = 0;
@@ -1968,11 +2128,11 @@ void CalculateStatsLE ( le_analyse_t *ana )
///////////////////////////////////////////////////////////////////////////////
-const le_usage_t * GetLEUsage ( const le_analyse_t *ana0, bool force_recalc )
+const le_usage_t * GetLEUsage ( const le_analyze_t *ana0, bool force_recalc )
{
- le_analyse_t *ana = (le_analyse_t*)ana0;
+ le_analyze_t *ana = (le_analyze_t*)ana0;
if ( force_recalc && ana->usage )
- ResetLEAnalyseUsage(ana);
+ ResetLEAnalyzeUsage(ana);
if ( ana->usage || ana->max_slot < LE_FIRST_CT_SLOT )
return ana->usage;
@@ -1983,18 +2143,18 @@ const le_usage_t * GetLEUsage ( const le_analyse_t *ana0, bool force_recalc )
memset(usage,LEU_S_UNUSED,ana->usage_size);
- //-- special slots
+ //-- random slots, can be overwritten by special slots
- memset(usage+0x36,LEU_S_SPECIAL,5);
- usage[0x42] = LEU_S_SPECIAL;
- usage[0x43] = LEU_S_NETWORK|LEU_F_ONLINE;
+ memset( usage + ana->le_random_beg,
+ LEU_S_LE_RANDOM|LEU_F_ONLINE,
+ ana->le_random_end - ana->le_random_beg );
- //-- random slots
+ //-- special slots, may overwrite random slots
- memset( usage + LE_FIRST_RANDOM_SLOT,
- LEU_S_WIIMM|LEU_F_ONLINE,
- LE_LAST_RANDOM_SLOT - LE_FIRST_RANDOM_SLOT+1 );
+ memset(usage+0x36,LEU_S_SPECIAL,5);
+ usage[0x42] = LEU_S_SPECIAL;
+ usage[0x43] = LEU_S_NETWORK|LEU_F_ONLINE;
//-- check racing slots
@@ -2008,16 +2168,27 @@ const le_usage_t * GetLEUsage ( const le_analyse_t *ana0, bool force_recalc )
{
if (IsLESlotUsed(ana,slot))
{
- const le_flags_t flags = ana->flags ? ana->flags[slot] : 0;
- usage[slot] = flags & LETF_ALIAS ? LEU_S_ALIAS
- : flags & LETF_RND_HEAD ? LEU_S_TRACK_RND
- : flags & LETF_RND_GROUP ? LEU_S_TRACK_HIDE
- : LEU_S_TRACK;
+ const le_flags_t flags = ana->flags[slot];
+
+ if ( flags & LEFL_ALIAS )
+ usage[slot] = LEU_S_ALIAS;
+ else if ( IsLEBattleSlot(ana,slot) )
+ usage[slot]
+ = flags & LEFL_RND_HEAD ? LEU_S_ARENA_RND
+ : flags & (LEFL_RND_GROUP|LEFL_HIDDEN) ? LEU_S_ARENA_HIDE
+ : LEU_S_ARENA;
+ else
+ usage[slot]
+ = flags & LEFL_RND_HEAD ? LEU_S_TRACK_RND
+ : flags & (LEFL_RND_GROUP|LEFL_HIDDEN) ? LEU_S_TRACK_HIDE
+ : LEU_S_TRACK;
}
if ( ana->version > 1 || slot < 0xff
|| slot >= LE_FIRST_UPPER_CT_SLOT && slot <= LE_LAST_UPPER_CT_SLOT )
+ {
usage[slot] |= LEU_F_ONLINE;
+ }
}
@@ -2027,10 +2198,10 @@ const le_usage_t * GetLEUsage ( const le_analyse_t *ana0, bool force_recalc )
{
if (IsLESlotUsed(ana,slot))
{
- const le_flags_t flags = ana->flags ? ana->flags[slot] : 0;
- usage[slot] = flags & LETF_ALIAS ? LEU_S_ALIAS
- : flags & LETF_RND_HEAD ? LEU_S_ARENA_RND
- : flags & LETF_RND_GROUP ? LEU_S_ARENA_HIDE
+ const le_flags_t flags = ana->flags[slot];
+ usage[slot] = flags & LEFL_ALIAS ? LEU_S_ALIAS
+ : flags & LEFL_RND_HEAD ? LEU_S_ARENA_RND
+ : flags & LEFL_RND_GROUP ? LEU_S_ARENA_HIDE
: LEU_S_ARENA;
}
}
@@ -2046,11 +2217,11 @@ const le_usage_t * GetLEUsage ( const le_analyse_t *ana0, bool force_recalc )
///////////////////////////////////////////////////////////////////////////////
-static const char usage_ch[] = "-AraTRtsn*W>----";
+static const char usage_ch[] = "-AarTtRLsn>-----";
char GetLEUsageChar ( le_usage_t usage )
{
- return usage_ch[usage & LEU_S_MASK];
+ return usage_ch[ usage & LEU_S_MASK ];
}
///////////////////////////////////////////////////////////////////////////////
@@ -2064,20 +2235,20 @@ ccp GetLEUsageCharCol ( le_usage_t usage, const ColorSet_t *colset, ccp * prev_c
ccp col;
switch ( usage & LEU_S_MASK )
{
+ case LEU_S_SPECIAL:
+ case LEU_S_NETWORK:
case LEU_S_UNUSED: col = colset->reset; break;
case LEU_S_ARENA: col = colset->b_cyan; break;
- case LEU_S_ARENA_RND: col = colset->b_yellow; break;
- case LEU_S_ARENA_HIDE: col = colset->b_green; break;
- case LEU_S_TRACK: col = colset->b_cyan_blue; break;
- case LEU_S_TRACK_RND: col = colset->b_yellow; break;
- case LEU_S_TRACK_HIDE: col = colset->green_cyan; break;
+ case LEU_S_ARENA_HIDE: col = colset->b_blue; break;
+ case LEU_S_TRACK: col = colset->b_yellow; break;
+ case LEU_S_TRACK_HIDE: col = colset->b_green; break;
- case LEU_S_SPECIAL: col = colset->reset; break;
- case LEU_S_NETWORK: col = colset->b_orange; break;
- case LEU_S_RANDOM: col = colset->b_yellow; break;
- case LEU_S_WIIMM: col = colset->b_orange; break;
- case LEU_S_ALIAS: col = colset->b_red; break;
+ case LEU_S_ARENA_RND: col = colset->orange; break;
+ case LEU_S_TRACK_RND: col = colset->b_orange; break;
+ case LEU_S_LE_RANDOM: col = colset->red; break;
+
+ case LEU_S_ALIAS:
default: col = colset->b_magenta; break;
}
@@ -2106,7 +2277,8 @@ typedef enum
{
CHECK_OFF, // don't check
CHECK_TRACK, // check for racing tracks
- CHECK_ARENA // check for battle arenas
+ CHECK_ARENA, // check for battle arenas
+ HIGHLIGHT_ARENA, // highlight arenas
}
slot_check_t;
@@ -2114,16 +2286,18 @@ slot_check_t;
ccp GetLEValid ( le_valid_t valid )
{
- char *buf = GetCircBuf(7);
+ char *buf = GetCircBuf(8);
DASSERT(buf);
+ char *d = buf;
- buf[0] = valid & LE_HEAD_FOUND ? 'F' : '-';
- buf[1] = valid & LE_HEAD_VALID ? 'V' : '-';
- buf[2] = valid & LE_HEAD_KNOWN ? 'K' : '-';
- buf[3] = valid & LE_PARAM_FOUND ? 'f' : '-';
- buf[4] = valid & LE_PARAM_VALID ? 'v' : '-';
- buf[5] = valid & LE_PARAM_KNOWN ? 'k' : '-';
- buf[6] = 0;
+ *d++ = valid & LE_HEAD_FOUND ? 'F' : '-';
+ *d++ = valid & LE_HEAD_VALID ? 'V' : '-';
+ *d++ = valid & LE_HEAD_KNOWN ? 'K' : '-';
+ *d++ = valid & LE_HEAD_VERSION ? 'L' : '-';
+ *d++ = valid & LE_PARAM_FOUND ? 'f' : '-';
+ *d++ = valid & LE_PARAM_VALID ? 'v' : '-';
+ *d++ = valid & LE_PARAM_KNOWN ? 'k' : '-';
+ *d = 0;
return buf;
}
@@ -2131,17 +2305,23 @@ ccp GetLEValid ( le_valid_t valid )
static ccp GetSlotInfo
(
- const le_analyse_t *ana, // valid structure
+ const le_analyze_t *ana, // valid structure
int tid, // track id
ColorSet_t *col, // NULL or color set for warnings
slot_check_t check, // check modus
uint *warnings // not NULL: increment on warnings
)
{
+ if (IsLecodeRandom(tid))
+ return PrintCircBuf("[%s%-7.7s%s,%s] ",
+ col->info, GetLecodeRandomName(tid,"random"), col->reset,
+ PrintLEFL(ana->flags_bits,ana->flags[tid],true));
+
if ( tid < ana->n_slot || IsMkwArena(tid) )
{
uint warn = 0;
+
//-- property slot
ccp prop1 = "", prop0 = "";
@@ -2160,10 +2340,17 @@ static ccp GetSlotInfo
}
else if ( IsMkwOriginal(tid) && tid != prop )
{
- warn |= 1;
if (col)
{
- prop1 = col->hint;
+ prop1 = col->info;
+ prop0 = col->reset;
+ }
+ }
+ else if ( check == HIGHLIGHT_ARENA && IsMkwArena(prop) )
+ {
+ if (col)
+ {
+ prop1 = col->info;
prop0 = col->reset;
}
}
@@ -2185,7 +2372,7 @@ static ccp GetSlotInfo
music0 = col->reset;
}
}
- else if ( !(music&1) || IsMkwArena(tid) && MusicID2TrackId(music,0,0) != tid )
+ else if ( !(music&1) )
{
warn |= 1;
if (col)
@@ -2194,51 +2381,36 @@ static ccp GetSlotInfo
music0 = col->reset;
}
}
- }
-
-
- //-- flags slot
-
- ccp flags;
- char flags_buf[8];
- bool is_alias = false;
- if (ana->flags)
- {
- const le_flags_t fl = ana->flags[tid];
- if ( fl & ~LETF__ALL )
- snprintf(flags_buf,sizeof(flags_buf),"?%03x",fl);
- else
+ else if ( IsMkwTrack(prop) != IsMkwTrack(MusicID2TrackId(music,0,0)) )
{
- if ( fl & LETF_ALIAS )
- is_alias = true;
-
- snprintf(flags_buf,sizeof(flags_buf),"%c%c%c%c",
- fl & LETF_NEW ? 'N' : '-',
- fl & LETF_RND_HEAD ? 'H' : '-',
- fl & LETF_RND_GROUP ? 'G' : '-',
- fl & LETF_ALIAS ? 'A' : '-' );
+ if (col)
+ {
+ music1 = col->info;
+ music0 = col->reset;
+ }
}
- flags = flags_buf;
}
- else
- flags = "-?-";
+
+
+ //-- flags
static const char warn_list[] = " <!!";
- return is_alias
+ const le_flags_t flags = ana->flags[tid];
+ return flags & LEFL_ALIAS
? PrintCircBuf("[%s->%4x %s,%s] ",
col->differ, TrackByAliasLE(prop,music),
- col->reset, flags )
+ col->reset, PrintLEFL(ana->flags_bits,flags,true) )
: PrintCircBuf("[%s%s%s,%s%s%s,%s]%c",
prop1, propx, prop0,
music1, musicx, music0,
- flags, warn_list[warn] );
+ PrintLEFL(ana->flags_bits,flags,true), warn_list[warn] );
}
if (col)
{
static char fail[40] = {0};
if (!*fail)
- snprintf(fail,sizeof(fail),"[%s---,---,----%s]!",col->bad,col->reset);
+ snprintf(fail,sizeof(fail),"[%s---,---,------%s]!",col->bad,col->reset);
return fail;
}
return "[---,---,---]!";
@@ -2249,7 +2421,7 @@ static ccp GetSlotInfo
static le_cup_track_t * DumpLECup
(
FILE *f, // print file
- const le_analyse_t *ana, // valid structure
+ const le_analyze_t *ana, // valid structure
const le_cup_track_t *cp, // pointer to cup
uint n_track, // number of tracks in cup
ColorSet_t *col, // NULL or color set for warnings
@@ -2265,7 +2437,19 @@ static le_cup_track_t * DumpLECup
for ( tr = 0; tr < n_track; tr++ )
{
const uint tid = htonl(*cp++);
- fprintf(f," %3x%s",tid,GetSlotInfo(ana,tid,col,check,warnings));
+ bool highlight;
+ switch (check)
+ {
+ case CHECK_TRACK: highlight = !IsLecodeTrack(tid); break;
+ case CHECK_ARENA: highlight = !IsMkwArena(tid); break;
+ default: highlight = IsMkwSpecial(tid); break;
+ }
+
+ fprintf(f," %s%3x%s%s",
+ highlight ? col->info : "",
+ tid,
+ highlight ? col->reset : "",
+ GetSlotInfo(ana,tid,col,check,warnings) );
if ( done && tid < ana->n_slot )
done[tid]++;
@@ -2276,13 +2460,22 @@ static le_cup_track_t * DumpLECup
//-----------------------------------------------------------------------------
static void DumpLETracks
- ( FILE *f, uint indent, ColorSet_t *col, const le_analyse_t *ana )
+ ( FILE *f, uint indent, ColorSet_t *col, const le_analyze_t *ana )
{
DASSERT(f);
DASSERT(indent>=2);
DASSERT(col);
DASSERT(ana);
+ ccp warn = GetLecodeSupportWarning(ana);
+ if (warn)
+ {
+ fprintf(f,"\n%*s%s"
+ "Can't print track infos because %s.%s\n\n",
+ indent-2,"", col->warn, warn, col->reset );
+ return;
+ }
+
u16 *done = CALLOC(sizeof(*done),ana->n_slot);
DASSERT(done);
if ( ana->version == 1 )
@@ -2294,17 +2487,65 @@ static void DumpLETracks
done[i]++;
}
- static const char id_info[] = "id[prop,music,new+head+group+alias]";
+
+ //--- intro
+
+ fprintf(f,"\n%*s%s"
+ "Description of the following track information with %u-bit flags:%s\n"
+ "%*s" "The general syntax is: %shex_id [ property_slot, music_index, flags ] warning%s\n",
+ indent-2,"", col->heading, ana->flags_bits, col->reset,
+ indent,"", col->param, col->reset );
+
+ if ( ana->flags_bits == 16 )
+ fprintf(f,
+ "%*s%sFlag 1%s: %sB%s: battle arena, %sV%s: versus track, %sr%s: random slot.\n"
+ "%*s%sFlag 2%s: Used in: %so%s: original cup, %sc%s custom cup, %sb%s: both.\n"
+ "%*s%sFlag 3%s: %sH%s: header of group, %sG%s: group member,"
+ " %sX%s: header of group and group member.\n"
+ "%*s%sFlags 4%s: %sN%s: new track, %sT%s: texture hack, %s2%s: both.\n"
+ "%*s%sFlags 5+6%s: %sA%s: alias, %si%s: invisible/hidden.\n"
+ ,indent+2,"", col->param, col->reset
+ ,col->info, col->reset
+ ,col->info, col->reset
+ ,col->info, col->reset
+ ,indent+2,"", col->param, col->reset
+ ,col->info, col->reset
+ ,col->info, col->reset
+ ,col->info, col->reset
+ ,indent+2,"", col->param, col->reset
+ ,col->info, col->reset
+ ,col->info, col->reset
+ ,col->info, col->reset
+ ,indent+2,"", col->param, col->reset
+ ,col->info, col->reset
+ ,col->info, col->reset
+ ,col->info, col->reset
+ ,indent+2,"", col->param, col->reset
+ ,col->info, col->reset
+ ,col->info, col->reset
+ );
+ else
+ fprintf(f,"%*s%sFlags%s: "
+ "%sN%s: new, %sH%s: group header, %sG%s: group member,"
+ " %sA%s: alias, %sT%s: texture hack, %si%s: hidden.\n"
+ ,indent,"", col->param, col->reset
+ ,col->info, col->reset
+ ,col->info, col->reset
+ ,col->info, col->reset
+ ,col->info, col->reset
+ ,col->info, col->reset
+ ,col->info, col->reset
+ );
//--- battle cups
if ( ana->n_cup_arena && ana->cup_arena )
{
- fprintf(f,"\n%*s%s" "%u cup%s with battle tracks (%s):%s\n",
+ fprintf(f,"\n%*s%s" "%u cup%s with %u battle arenas:%s\n",
indent-2,"", col->heading,
ana->n_cup_arena, ana->n_cup_arena == 1 ? "" : "s",
- id_info, col->reset );
+ ana->n_cup_arena*5, col->reset );
uint cup, hidden = 0;
const le_cup_track_t *cp = ana->cup_arena;
@@ -2334,10 +2575,10 @@ static void DumpLETracks
if ( ana->n_cup_track && ana->cup_track )
{
- fprintf(f,"\n%*s%s" "%u cup%s with racing tracks (%s):%s\n",
+ fprintf(f,"\n%*s%s" "%u cup%s with %u racing tracks:%s\n",
indent-2,"", col->heading,
ana->n_cup_track, ana->n_cup_track == 1 ? "" : "s",
- id_info, col->reset );
+ ana->n_cup_track*4, col->reset );
uint cup, hidden = 0;
const le_cup_track_t *cp = ana->cup_track;
@@ -2372,35 +2613,43 @@ static void DumpLETracks
done[18] = 0;
#endif
- uint i, max_used_slot = 0, n_multi = 0, n_group = 0, n_unused = 0;
+ uint i, max_viewed_slot = 0, n_multi = 0, n_group = 0, n_unused = 0;
for ( i = 0; i < ana->n_slot; i++ )
if (IsRacingTrackLE(i))
{
if (done[i])
{
- max_used_slot = i;
+ max_viewed_slot = i;
if ( done[i] > 1 )
n_multi++;
}
- else if ( !done[i] )
+ else // if ( !done[i] )
{
- if ( ana->flags && ana->flags[i] & LETF_RND_GROUP )
+ const typeof(*ana->flags) flags = ana->flags ? ana->flags[i] : 0;
+ if ( flags & LEFL_RND_GROUP )
+ {
n_group++;
+ max_viewed_slot = i;
+ }
else
+ {
n_unused++;
+ if ( flags & LEFL_TEXTURE )
+ max_viewed_slot = i;
+ }
}
}
- PRINT0("m=%d, g=%d, u=%d /%d\n",n_multi,n_group,n_unused,max_used_slot);
+ PRINT0("m=%d, g=%d, u=%d /%d\n",n_multi,n_group,n_unused,max_viewed_slot);
//--- multi used tracks
if (n_multi)
{
- fprintf(f,"\n%*s%s" "%u multiple used track slot%s (%s):%s\n",
+ fprintf(f,"\n%*s%s" "%u multiple used track slot%s:%s\n",
indent-2,"", col->heading,
n_multi, n_multi == 1 ? "" : "s",
- id_info, col->reset );
+ col->reset );
for ( i = 0; i < ana->n_slot; i++ )
if ( done[i] > 1 && IsRacingTrackLE(i) )
@@ -2413,13 +2662,13 @@ static void DumpLETracks
if (n_group)
{
- fprintf(f,"\n%*s%s" "%u track slot%s reserved for random groups (%s):%s\n",
+ fprintf(f,"\n%*s%s" "%u track slot%s reserved for random groups:%s\n",
indent-2,"", col->heading,
n_group, n_group == 1 ? "" : "s",
- id_info, col->reset );
+ col->reset );
for ( i = 0; i < ana->n_slot; i++ )
- if ( !done[i] && IsRacingTrackLE(i) && ana->flags[i] & LETF_RND_GROUP )
+ if ( !done[i] && IsRacingTrackLE(i) && ana->flags[i] & LEFL_RND_GROUP )
{
done[i]++;
fprintf(f,"%*sSlot %4d/dec : %3x%s\n",
@@ -2427,24 +2676,44 @@ static void DumpLETracks
}
}
+ //HexDump16(stdout,0,0,done,ana->n_slot*sizeof(*done));
+
//--- unused used track slots
- if ( n_unused)
+ if (n_unused)
{
- fprintf(f,"\n%*s%s" "%u unused track slot%s (%s):%s\n",
- indent-2,"", col->heading,
- n_unused, n_unused == 1 ? "" : "s",
- id_info, col->reset );
- for ( i = 0; i <= max_used_slot; i++ )
- {
+ int count = 0;
+ for ( int i = 0; i <= max_viewed_slot; i++ )
if ( !done[i] && IsRacingTrackLE(i) )
- fprintf(f,"%*sSlot %4d/dec : %3x%s\n",
- indent,"", i, i, GetSlotInfo(ana,i,col,CHECK_OFF,0) );
- }
+ count++;
+ if ( count > 0 )
+ {
+ fprintf(f,"\n%*s%s" "%u track%s without cup reference:%s",
+ indent-2,"", col->heading,
+ count, count == 1 ? "" : "s",
+ col->reset );
- uint first_unused_slot = max_used_slot + 1;
+ int prev = -1, line_count = 99;
+ for ( int i = 0; i <= max_viewed_slot; i++ )
+ {
+ if ( !done[i] && IsRacingTrackLE(i) )
+ {
+ if ( ++line_count > 4 || i != prev+1 )
+ {
+//DEL if ( i == prev+1 ) fputs("...",f);
+ fprintf(f,"\n%*sSlot %4d/dec :", indent,"", i );
+ line_count = 1;
+ }
+ fprintf(f," %3x%s", i, GetSlotInfo(ana,i,col,HIGHLIGHT_ARENA,0) );
+ prev = i;
+ }
+ }
+ putchar('\n');
+ }
+
+ uint first_unused_slot = max_viewed_slot + 1;
if (!IsRacingTrackLE(first_unused_slot))
first_unused_slot = LE_FIRST_CT_SLOT;
const int unused_slots = ana->n_slot - first_unused_slot;
@@ -2464,7 +2733,7 @@ static void DumpLETracks
//-----------------------------------------------------------------------------
static void DumpLEUsageMap
- ( FILE *f, uint indent, ColorSet_t *col, const le_analyse_t *ana )
+ ( FILE *f, uint indent, ColorSet_t *col, const le_analyze_t *ana )
{
DASSERT(f);
DASSERT(indent>=2);
@@ -2475,31 +2744,61 @@ static void DumpLEUsageMap
if (!usage)
return;
+ int max_view = ana->n_slot > MKW_LE_SLOT_BEG ? ana->n_slot : MKW_LE_SLOT_BEG;
+ if ( max_view > ana->usage_size )
+ max_view = ana->usage_size;
+
+ #if 1
fprintf(f,"\n%*s%s" "Slot usage map for %u slots%s\n"
- "%*s" "%s%s=Arena, %s%s=Random Arena, %s%s=Hidden Arena, "
- "%s%s=Wiimm Cup (random), %s%s=Alias,%s\n"
- "%*s" "%s%s=Track, %s%s=Random Track, %s%s=Hidden Track, "
- "%s%s=Network, %s%s=Special, %s%s=unused.%s\n",
- indent-2,"", col->heading, ana->n_slot, col->reset,
+ "%*s" "%s: Arena%s, %s: Hidden Arena%s, %s: Random Arena%s, "
+ "%s: LE-CODE random%s, %s: Alias%s,\n"
+ "%*s" "%s: Track%s, %s: Hidden Track%s, %s: Random Track%s, "
+ "%s: Network%s, %s: Special%s, %s: unused%s.\n",
+
+ indent-2,"", col->heading, max_view, col->reset,
indent,"",
- GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_ARENA, col,0 ), col->info,
- GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_ARENA_RND, col,0 ), col->info,
- GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_ARENA_HIDE, col,0 ), col->info,
- GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_WIIMM, col,0 ), col->info,
- GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_ALIAS, col,0 ), col->info,
- col->reset,
+ GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_ARENA, col,0 ), col->reset,
+ GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_ARENA_HIDE, col,0 ), col->reset,
+ GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_ARENA_RND, col,0 ), col->reset,
+ GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_LE_RANDOM, col,0 ), col->reset,
+ GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_ALIAS, col,0 ), col->reset,
indent,"",
- GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_TRACK, col,0 ), col->info,
- GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_TRACK_RND, col,0 ), col->info,
- GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_TRACK_HIDE, col,0 ), col->info,
- GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_NETWORK, col,0 ), col->info,
- GetLEUsageCharCol( LEU_S_SPECIAL, col,0 ), col->info,
- GetLEUsageCharCol( LEU_S_UNUSED, col,0 ), col->info,
- col->reset );
+ GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_TRACK, col,0 ), col->reset,
+ GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_TRACK_HIDE, col,0 ), col->reset,
+ GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_TRACK_RND, col,0 ), col->reset,
+ GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_NETWORK, col,0 ), col->reset,
+ GetLEUsageCharCol( LEU_S_SPECIAL, col,0 ), col->reset,
+ GetLEUsageCharCol( LEU_S_UNUSED, col,0 ), col->reset );
+
+ #else
+ fprintf(f,"\n%*s%s" "Slot usage map for %u slots%s\n"
+ "%*s" "%s: Arena%s, %s: Hidden Arena%s, %s: Random Arena%s, "
+ "%s: LE-CODE arena random%s,\n"
+ "%*s" "%s: Track%s, %s: Hidden Track%s, %s: Random Track%s, "
+ "%s: LE-CODE track random%s,\n"
+ "%*s" "%s: Alias%s, %s: Network%s, %s: Special%s, %s: unused%s.\n",
+
+ indent-2,"", col->heading, max_view, col->reset,
+ indent,"",
+ GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_ARENA, col,0 ), col->reset,
+ GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_ARENA_HIDE, col,0 ), col->reset,
+ GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_ARENA_RND, col,0 ), col->reset,
+ GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_ARENA_LE_RND, col,0 ), col->reset,
+ indent,"",
+ GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_TRACK, col,0 ), col->reset,
+ GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_TRACK_HIDE, col,0 ), col->reset,
+ GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_TRACK_RND, col,0 ), col->reset,
+ GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_TRACK_LE_RND, col,0 ), col->reset,
+ indent,"",
+ GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_ALIAS, col,0 ), col->reset,
+ GetLEUsageCharCol( LEU_F_ONLINE | LEU_S_NETWORK, col,0 ), col->reset,
+ GetLEUsageCharCol( LEU_S_SPECIAL, col,0 ), col->reset,
+ GetLEUsageCharCol( LEU_S_UNUSED, col,0 ), col->reset );
+ #endif
uint slot;
ccp prev_col = 0;
- for ( slot = 0; slot < ana->usage_size; slot++ )
+ for ( slot = 0; slot < max_view; slot++ )
{
if (!(slot&63))
{
@@ -2515,7 +2814,19 @@ static void DumpLEUsageMap
///////////////////////////////////////////////////////////////////////////////
-void DumpLEAnalyse ( FILE *f, uint indent, const le_analyse_t *ana )
+static ccp ana_std_flags ( uint flags )
+{
+ return PrintCircBuf("%u (%sabled%s%s%s)",
+ flags,
+ flags & LE_ENABLED ? "en" : "dis",
+ flags & LE_ALTERABLE ? ",alterable" : "",
+ flags & LE_EXCLUDED ? ",excluded" : "",
+ flags & LE_INCLUDED ? ",included" : "" );
+}
+
+//-----------------------------------------------------------------------------
+
+void DumpLEAnalyse ( FILE *f, uint indent, const le_analyze_t *ana )
{
DASSERT(f);
DASSERT(ana);
@@ -2526,7 +2837,7 @@ void DumpLEAnalyse ( FILE *f, uint indent, const le_analyse_t *ana )
fprintf(f,"%*s%sLE-CODE binary, valid=%s, file size: %x/hex = %u bytes%s\n",
indent,"",
- col.caption, GetLEValid(ana->valid), ana->size, ana->size,
+ col.caption, GetLEValid(ana->valid), ana->data_size, ana->data_size,
col.reset );
indent += 4;
@@ -2564,23 +2875,25 @@ void DumpLEAnalyse ( FILE *f, uint indent, const le_analyse_t *ana )
fprintf(f,
"\n%*s%s" "File header:%s\n"
"%*s" "Magic: %.4s\n"
+ ,indent-2,"", col.heading, col.reset
+ ,indent,"", h->magic
+ );
+
+ if ( h->phase != 2 )
+ fprintf(f,"%*s" "Phase: %u\n",indent,"",h->phase);
+
+ fprintf(f,
"%*s" "Version: %u\n"
"%*s" "Build number: %u\n"
- "%*s" "Base address: %8x/hex\n"
- "%*s" "Entry point: %8x/hex\n"
- "%*s" "Total size: %8x/hex = %u bytes\n"
- "%*s" "Offset param: %8x/hex\n"
"%*s" "Region code: %c = %s\n"
"%*s" "Debug flag: %c = %s\n"
- "%*s" "LE version/phase: %u\n"
- ,indent-2,"", col.heading, col.reset
- ,indent,"", h->magic
+ "%*s" "Header size: %8x/hex = %6u bytes\n"
+ "%*s" "Total size: %8x/hex = %6u bytes\n"
+ "%*s" "Offset param: %8x/hex\n"
+ "%*s" "Base address: %8x/hex\n"
+ "%*s" "Entry point: %8x/hex\n"
,indent,"", ntohl(h->version)
,indent,"", ntohl(h->build_number)
- ,indent,"", ntohl(h->base_address)
- ,indent,"", ntohl(h->entry_point)
- ,indent,"", ntohl(h->size), ntohl(h->size)
- ,indent,"", ntohl(h->off_param)
,indent,"", h->region
,h->region == 'P' ? "PAL"
:h->region == 'E' ? "USA"
@@ -2591,26 +2904,39 @@ void DumpLEAnalyse ( FILE *f, uint indent, const le_analyse_t *ana )
,h->debug == 'R' ? "Release"
:h->debug == 'D' ? "Debug"
: "?"
- ,indent,"", h->phase
+ ,indent,"", ana->header_size ,ana->header_size
+ ,indent,"", ntohl(h->file_size), ntohl(h->file_size)
+ ,indent,"", ntohl(h->off_param)
+ ,indent,"", ntohl(h->base_address)
+ ,indent,"", ntohl(h->entry_point)
);
- }
- switch (ana->head_vers)
- {
- case 4:
- {
- const le_binary_head_v4_t *h = ana->head_v4;
- DASSERT(h);
- fprintf(f,
- "%*s" "Timestamp: %s UTC\n"
- ,indent,"", h->timestamp
+ if (ana->creation_time)
+ fprintf(f,
+ "%*s" "Time of creation: %s\n",
+ indent,"", PrintTimeByFormat("%F %T %Z",ana->creation_time));
+
+ if (ana->edit_time)
+ fprintf(f,
+ "%*s" "Time of last edit: %s\n",
+ indent,"", PrintTimeByFormat("%F %T %Z",ana->edit_time));
+
+ if (ana->szs_version)
+ {
+ const bool valid = GetEncodedVersion() >= ana->szs_version;
+ fprintf(f,
+ "%*s" "SZS Tool required: v%s (current: %sv%s,%s%s)\n"
+ ,indent,""
+ ,DecodeVersion(ana->szs_version)
+ ,valid ? col.success : col.warn, BASE_VERSION
+ ,valid ? "ok" : "outdated", col.reset
);
- }
- break;
+ }
- default:
- fprintf(f,"%*s" ">>> other parameters unknown!\n",indent,"");
- break;
+ if (ana->edit_version)
+ fprintf(f,
+ "%*s" "Last edit by SZS: v%s\n",
+ indent,"", DecodeVersion(ana->edit_version) );
}
@@ -2711,6 +3037,27 @@ void DumpLEAnalyse ( FILE *f, uint indent, const le_analyse_t *ana )
);
}
+ if ( ana->param_size >= sizeof(le_binpar_v1_26c_t) )
+ {
+ // [[worldwide]]
+ #if !HAVE_WIIMM_EXT
+ if ( h->bt_worldwide || h->vs_worldwide )
+ #endif
+ fprintf(f,
+ "%*s" "Worldwide: bt=%u, vs=%u (planned)\n"
+ ,indent,"", h->bt_worldwide, h->vs_worldwide
+ );
+
+ fprintf(f,
+ "%*s" "Textures: bt=%s, vs=%s\n"
+ "%*s" "Block textures: %u\n"
+ ,indent,""
+ ,ana_std_flags( h->bt_textures & LE_M_TEXTURE )
+ ,ana_std_flags( h->vs_textures & LE_M_TEXTURE )
+ ,indent,"", h->block_textures
+ );
+ }
+
// [[new-lpar]]
#if 0 // for later use
@@ -2821,9 +3168,9 @@ void DumpLEAnalyse ( FILE *f, uint indent, const le_analyse_t *ana )
if ( ana->flags )
fprintf(f,
- "%*s" "Flags list: %5x/hex, %4u / %4u%s\n",
- indent,"", PTR_DISTANCE_INT(ana->flags,ana->data),
- ana->n_slot, ana->max_flags,
+ "%*s" "Flags list: %5x/hex, %4u / %4u (%u bits)%s\n",
+ indent,"", PTR_DISTANCE_INT(ana->flags_bin,ana->data),
+ ana->n_slot, ana->max_flags, ana->flags_bits,
ana->n_slot > ana->max_flags ? fail : "" );
if ( ana->end_of_data )
@@ -2833,7 +3180,7 @@ void DumpLEAnalyse ( FILE *f, uint indent, const le_analyse_t *ana )
fprintf(f,
"%*s" "End of file: %5x/hex\n",
- indent,"", ana->size );
+ indent,"", ana->data_size );
//--- settings
@@ -2995,10 +3342,10 @@ const ctcode_t * LoadLEFile ( uint le_phase )
///////////////////////////////////////////////////////////////////////////////
-enumError ApplyLEFile ( le_analyse_t * ana )
+enumError ApplyLEFile ( le_analyze_t * ana )
{
DASSERT(ana);
- SetupArenasLEAnalyse(ana,false);
+ SetupArenasLEAnalyze(ana,false);
const ctcode_t *ctcode = LoadLEFile(ana->version);
return ctcode ? ApplyCTCODE(ana,ctcode) : ERR_ERROR;
@@ -3009,7 +3356,7 @@ enumError ApplyLEFile ( le_analyse_t * ana )
/////////////// ApplyCTCODE() ///////////////
///////////////////////////////////////////////////////////////////////////////
-enumError ApplyCTCODE ( le_analyse_t * ana, const ctcode_t * ctcode )
+enumError ApplyCTCODE ( le_analyze_t * ana, const ctcode_t * ctcode )
{
DASSERT(ana);
DASSERT(ctcode);
@@ -3112,7 +3459,7 @@ enumError ApplyCTCODE ( le_analyse_t * ana, const ctcode_t * ctcode )
//--- arena setup (override)
- SetupArenasLEAnalyse(ana,false);
+ SetupArenasLEAnalyze(ana,false);
ApplyArena(ana,&ctcode->arena);
@@ -3149,7 +3496,7 @@ enumError ApplyCTCODE ( le_analyse_t * ana, const ctcode_t * ctcode )
///////////////////////////////////////////////////////////////////////////////
-bool DefineAliasLE ( le_analyse_t * ana, uint slot, uint alias )
+bool DefineAliasLE ( le_analyze_t * ana, uint slot, uint alias )
{
if ( !ana->property || !ana->music || !ana->flags )
return false;
@@ -3171,9 +3518,9 @@ bool DefineAliasLE ( le_analyse_t * ana, uint slot, uint alias )
}
const le_flags_t fl = ana->flags[alias];
- if ( !(fl & LETF_ALIAS) )
+ if ( !(fl & LEFL_ALIAS) )
{
- ana->flags[slot] |= LETF_ALIAS;
+ ana->flags[slot] |= LEFL_ALIAS;
ana->property[slot] = alias >> 8;
ana->music[slot] = alias & 0xff;
return true;
@@ -3185,7 +3532,7 @@ bool DefineAliasLE ( le_analyse_t * ana, uint slot, uint alias )
///////////////////////////////////////////////////////////////////////////////
-uint PatchAliasLE ( le_analyse_t * ana, ccp list )
+uint PatchAliasLE ( le_analyze_t * ana, ccp list )
{
DASSERT(ana);
@@ -3253,11 +3600,107 @@ void PatchLPAR ( le_lpar_t * lp )
///////////////////////////////////////////////////////////////////////////////
-void PatchLECODE ( le_analyse_t * ana )
+void UpdateLecodeFlags ( le_analyze_t * ana )
+{
+ DASSERT(ana);
+ if (!ana->flags)
+ return;
+
+
+ //--- calculate flags LEFL_BATTLE and LEFL_VERSUS, reset other flags
+
+ for ( int slot = 0; slot < ana->max_flags; slot++ )
+ {
+ le_flags_t flags = ana->flags[slot] & LEFL__ALL;
+ if ( slot < ana->max_property )
+ {
+ if ( slot < MKW_ARENA_END || slot >= MKW_LE_SLOT_BEG )
+ flags |= IsMkwTrack(ana->property[slot]) ? LEFL_VERSUS : LEFL_BATTLE;
+ }
+ ana->flags[slot] = flags;
+ }
+
+
+ //--- define LEFL_RANDOM
+
+ for ( int slot = LE_SLOT_RND_BEG; slot < LE_SLOT_RND_END; slot++ )
+ ana->flags[slot] |= LEFL_RANDOM;
+
+
+ //--- calculate flags LEFL_CUP, LEFL_ORIG_CUP, LEFL_CUSTOM_CUP
+
+ if ( ana->n_cup_track && ana->cup_track )
+ {
+ if ( ana->n_cup_track & 1 )
+ ana->n_cup_track++;
+
+ const le_cup_track_t *src = ana->cup_track;
+ const int max_tr = ana->n_cup_track * 4;
+ for ( int tr = 0; tr < max_tr; tr++ )
+ {
+ const uint slot = ntohl(*src++);
+ if ( slot < ana->max_flags && ana->flags[slot] & (LEFL_VERSUS|LEFL_RANDOM) )
+ ana->flags[slot] |= LEFL_CUP | ( tr < MKW_N_TRACKS ? LEFL_ORIG_CUP : LEFL_CUSTOM_CUP );
+ }
+ }
+
+ if ( ana->n_cup_arena && ana->cup_arena )
+ {
+ const le_cup_track_t *src = ana->cup_arena;
+ const int max_tr = ana->n_cup_arena * 5;
+ for ( int tr = 0; tr < max_tr; tr++ )
+ {
+ const uint slot = ntohl(*src++);
+ if ( slot < ana->max_flags && ana->flags[slot] & (LEFL_BATTLE|LEFL_RANDOM) )
+ ana->flags[slot] |= LEFL_CUP | ( tr < MKW_N_ARENAS ? LEFL_ORIG_CUP : LEFL_CUSTOM_CUP );
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void CopyLecodeFlags ( le_analyze_t * ana )
+{
+ DASSERT(ana);
+ UpdateLecodeFlags(ana);
+
+
+ //--- store flags intoLE-CODE binary
+
+ if ( !ana->flags || !ana->flags_bin )
+ return;
+
+ const le_flags_t *src = ana->flags;
+ if ( ana->flags_bits == 16 )
+ {
+ le_flags_t *dest = (le_flags_t*)ana->flags_bin;
+ for ( int i = 0; i < ana->max_flags; i++ )
+ write_be16(dest++,*src++);
+ }
+ else
+ {
+ le_flags8_t *dest = (le_flags8_t*)ana->flags_bin;
+ for ( int i = 0; i < ana->max_flags; i++ )
+ *dest++ = *src++;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void PatchLECODE ( le_analyze_t * ana )
{
DASSERT(ana);
PRINT("PatchLECODE() opt_lpar=%s\n",opt_lpar);
+ ccp warn = GetLecodeSupportWarning(ana);
+ if (warn)
+ {
+ ERROR0(ERR_INVALID_DATA,"Can't use or patch LE-CODE because %s.",warn);
+ return;
+ }
+
+ u8 *saved = MEMDUP(ana->data,ana->data_size);
+
if (opt_lpar)
LoadLPAR(&ana->lpar,false,0,false);
@@ -3270,7 +3713,17 @@ void PatchLECODE ( le_analyse_t * ana )
break;
}
+ CopyLecodeFlags(ana);
CopyLPAR2Data(ana);
+
+ if ( ana->header_vers >= 5 && memcmp(ana->data,saved,ana->data_size) )
+ {
+ le_binary_head_v5_t *h5 = (le_binary_head_v5_t*)ana->data;
+ h5->edit_version = htonl(GetEncodedVersion());
+ h5->edit_time = htonl(GetTimeSec(false));
+ }
+
+ FREE(saved);
}
//
@@ -3309,7 +3762,14 @@ static enumError ScanTextLPAR_PARAM
{ "ITEM-CHEATS", SPM_U8, &lpar->item_cheat }, // bug in 2021-04, [[obsolete]] in 2022
{ "DRAG-BLUE-SHELL", SPM_U8, &lpar->drag_blue_shell },
{ "THCLOUD-TIME", SPM_U16, &lpar->thcloud_frames },
- {0} // [[new-lpar]]
+ { "BT-WORLDWIDE", SPM_U8, &lpar->bt_worldwide },
+ { "VS-WORLDWIDE", SPM_U8, &lpar->vs_worldwide },
+ { "BT-TEXTURES", SPM_U8, &lpar->bt_textures },
+ { "VS-TEXTURES", SPM_U8, &lpar->vs_textures },
+ { "BLOCK-TEXTURES", SPM_U8, &lpar->block_textures },
+
+ // [[new-lpar]]
+ {0}
};
@@ -3471,7 +3931,9 @@ static enumError ScanTextLPAR_DEBUG
{ "KCL-TYPE", SPM_U8, &debug.kcl_type },
{ "RESPAWN", SPM_U8, &debug.respawn },
{ "LAP-POS", SPM_U8, &debug.lap_pos },
+ { "TRACK-ID", SPM_U8, &debug.track_id },
{ "XPF", SPM_U8, &debug.xpf },
+ // [[new-debug]]
{0}
};