aboutsummaryrefslogtreecommitdiff
path: root/project/src/wlect.c
diff options
context:
space:
mode:
authorWiimm <wiimm@wiimm.de>2022-12-25 08:25:56 +0100
committerWiimm <wiimm@wiimm.de>2022-12-25 08:25:56 +0100
commit7d8344f3637d59b982c2ca0b1d8fd2889ec5d4a6 (patch)
tree19b070a98ba1d659b64c19e3402038bc76e11b47 /project/src/wlect.c
parent0e143e393d99ebb00cb14ffaa4c50efeec3729f1 (diff)
SZS v2.32a
Diffstat (limited to '')
-rw-r--r--project/src/wlect.c238
1 files changed, 194 insertions, 44 deletions
diff --git a/project/src/wlect.c b/project/src/wlect.c
index 0837d02..7539cbc 100644
--- a/project/src/wlect.c
+++ b/project/src/wlect.c
@@ -793,8 +793,9 @@ static enumError cmd_patch()
le_analyze_t ana;
AnalyzeLEBinary(&ana,raw.data,raw.data_size);
ApplyLEFile(&ana);
- PatchLECODE(&ana);
- err = SaveFILE( dest, 0, dest_is_source||opt_overwrite,
+ err = PatchLECODE(&ana);
+ if (!err)
+ err = SaveFILE( dest, 0, dest_is_source||opt_overwrite,
raw.data, raw.data_size, 0 );
ImportAnaLDUMP(&ana);
ResetLEAnalyze(&ana);
@@ -807,6 +808,81 @@ static enumError cmd_patch()
//
///////////////////////////////////////////////////////////////////////////////
+/////////////// command timestamp ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_timestamp()
+{
+ static ccp def_path = "\1P/\1F";
+ CheckOptDest(def_path,false);
+
+ const u_sec_t reftime = GetTimeSec(false);
+
+ raw_data_t raw;
+ InitializeRawData(&raw);
+
+ ParamList_t *param;
+ for ( param = first_param; param; param = param->next )
+ {
+ NORMALIZE_FILENAME_PARAM(param);
+ enumError err = LoadRawData(&raw,false,param->arg,0,opt_ignore>0,0);
+ if ( err == ERR_NOT_EXISTS || err > ERR_WARNING && opt_ignore )
+ continue;
+ if ( err > ERR_WARNING )
+ return err;
+
+ char dest[PATH_MAX];
+ SubstDest(dest,sizeof(dest),param->arg,opt_dest,def_path,
+ GetExtFF(raw.fform_file,raw.fform),false);
+ const bool dest_is_source = IsSameFilename(dest,param->arg);
+
+ if ( verbose >= 0 || testmode )
+ {
+ ccp ff_name = GetNameFF(raw.fform_file,raw.fform);
+ if (dest_is_source)
+ fprintf(stdlog,"%s%sSET TIMESTRAMP %s:%s\n",
+ verbose > 0 ? "\n" : "",
+ testmode ? "WOULD " : "",
+ ff_name, dest );
+ else
+ fprintf(stdlog,"%s%sSET TIMESTRAMP %s:%s -> %s:%s\n",
+ verbose > 0 ? "\n" : "",
+ testmode ? "WOULD " : "",
+ ff_name, raw.fname,
+ ff_name, dest );
+ fflush(stdlog);
+ }
+
+ if ( raw.fform != FF_LE_BIN )
+ return ERROR0(ERR_INVALID_DATA,"Invalid file format: %s",raw.fname);
+
+ le_analyze_t ana;
+ AnalyzeLEBinary(&ana,raw.data,raw.data_size);
+ bool patched = false;
+ if ( !ana.creation_time && ana.header_vers >= 5 )
+ {
+ u32 timestamp = reftime;
+ if ( ana.edit_time && timestamp > ana.edit_time )
+ timestamp = ana.edit_time;
+ if ( timestamp >= ana.commit_time )
+ {
+ ana.head->v5.creation_time = htonl(timestamp);
+ patched = true;
+ }
+ }
+
+ if ( !err && ( !dest_is_source || patched ) )
+ err = SaveFILE( dest, 0, dest_is_source||opt_overwrite,
+ raw.data, raw.data_size, 0 );
+ ResetLEAnalyze(&ana);
+ }
+
+ ResetRawData(&raw);
+ return ERR_OK;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
/////////////// command create ///////////////
///////////////////////////////////////////////////////////////////////////////
@@ -1282,17 +1358,10 @@ static void help_distrib ( enumError exit_code )
"\t{name|XRATING}:\t|"
"Same as {name|RATING}, but use extended names if available.\n"
"\n"
- "\t{name|LE-INFO}:\t|"
- "Print information about current LE-CODE binaries.\n"
- "\n"
"\t{name|PREFIX}:\t|"
"Print a machine readable prefix list."
" {file|https://ct.wiimm.de/export/prefix} is the authoritative source for this.\n"
"\n"
- "\t{name|DEBUG}:\t|"
- "Print some statistics for debugging."
- " The current sate is analysed without updating cups.\n"
- "\n"
//-------------------------
" |{heading|Create human and machine readable definition files (usually input files):}\n"
@@ -1357,34 +1426,85 @@ static void help_distrib ( enumError exit_code )
"\n"
//-------------------------
+ " {heading|Analyze and report:}\n"
+ "\n"
+ "\t{name|REPORT}:\t|"
+ "Analyse the current distribution and print a report."
+ " Therefor count track and arena types and find duplicate names, tracks, families and clans."
+ "\r\r"
+ " {heading|Syntax:} {syntax|REPORT '=' [OPTIONS] '=' FILE}"
+ "\r\r"
+ "{syntax|OPTIONS} is a comma separated list of keywords to select the kind of analysis."
+ " If no option is set, all are enabled."
+ " To find duplicate tracks, families or clans, the definition file must support SHA1"
+ " checksums and a SHA1 reference file must be loaded."
+ " You can get the reference file from {file|https://ct.wiimm.de/export/sha1ref/view}."
+ "\n\n"
+ "|[17,29]"
+ "\t{par|counters}:\t|Count track and arena types in different ways.\n"
+ "\t{par|names}:\t|Find track names that are used"
+ " by two or more distinct tracks or arenas.\n"
+ "\t{par|tracks}:\t|Find tracks that are used two or more times and list them.\n"
+ "\t{par|families}:\t|Find tracks that are in the same family and list them.\n"
+ "\t{par|clans}:\t|Find tracks that are in the same clan and list them.\n"
+ "\t{par|duplicates}:\t|Short cut for »{par|names,tracks,families,clans}«.\n"
+ "\t{par|all}:\t|Short cut for all of above and default if no option is set."
+ " To exclude something, you can write e.g. »{par|all,-clans}«,"
+ " or shorter »{par|-clans}«.\n"
+ "\n|[4,15]"
+ "\t{name|DEBUG}:\t|"
+ "Print some statistics for debugging."
+ " The current state is analysed without updating cups.\n"
+ "\n"
+ "\t{name|LE-INFO}:\t|"
+ "Print information about current LE-CODE binaries.\n"
+ "\n"
+
+ //-------------------------
" {heading|Cup-Icon support:}\n"
"\n|[4,15]"
"\t{name|CUP-ICONS}:\t|"
- "Create an image file with cup icons.\r"
- " {heading|Syntax:} {syntax|CUP-ICON '=' [OPTIONS] '=' FILE}\r"
+ "Create an image file with cup icons."
+ "\r\r"
+ " {heading|Syntax:} {syntax|CUP-ICON '=' [STORAGE,] [OPTIONS] '=' FILE}"
+ "\r\r"
"If the output goes to a terminal, then use instruction {name|CUP-INFO} instead."
" To determine the file type, the file extension is analyzed."
- " Examples are »{par|*.tpl}« or »{par|*.png}«.\r\r"
+ " Examples are »{par|*.tpl}« or »{par|*.png}«."
+ "\r\r"
"The generic icons consist of a red cup index at the top-right and the first"
- " 3 characters of the name without a prefix, shown in blue at the bottom."
- " If a name is wider than 128 pixels, than it is horizontal shrinked to 128 pixels.\r\r"
+ " 5 characters of the name without a prefix, shown in blue at the bottom."
+ " If a name is wider than 128 pixels, than it is horizontal shrinked to 128 pixels."
+ "\r\r"
+ "{syntax|STORAGE} is an optional storage indicator for the source"
+ " explained in section »{name|Processing Options: Storage}«."
+ " Separate STORAGE and OPTIONS by a comma."
+ " If not set, then {name|NAME} is used as source."
+ "\r\r"
"{syntax|OPTIONS} is a comma separated list of keywords:\n"
"|[17,27]"
"\t{par|original}:\t|Add 8 original cup icons.\n"
"\t{par|swapped}:\t|Add 8 original cup icons in swapped order.\n"
- "\t{par|1wiimm}:\t|Use Wiimms avatar for the first cup if original icons are not used.\n"
+ "\t{par|1wiimm}:\t|Use Wiimms avatar for the first cup, but only if original icons are not used.\n"
"\t{par|9wiimm}:\t|Use Wiimms avatar for the ninth cup.\n"
"\t{par|xwiimm}:\t|Use Wiimms avatar for the last cup.\n"
- "\t{par|plus}:\t|Include the plus prefix to create the name.\n"
- "\t{par|game}:\t|Include the game prefix to create the name.\n"
- "\t{par|space}:\t|Finish the name part at first space.\n"
- "\t{par|1} .. {par|15}:\t|"
+ "\t{par|plus}:\t|If a plus prefix exists, then insert it and an additional space.\n"
+ "\t{par|xplus}:\t|Same as option {par|plus},"
+ " but apppend an underline character instead of a space after the plus prefix."
+ " Underline characters are printed like spaces, but they are ignored by option {par|space}.\n"
+ "\t{par|game}:\t|If a game prefix exists, then insert it and an additional space.\n"
+ "\t{par|xgame}:\t|Same as option {par|game},"
+ " but apppend an underline character instead of a space after the game prefix.\n"
+ "\t{par|space}:\t|Finish the name part at first space."
+ " Ignore tabulators and undercore characters for this.\n"
+ "\t{par|0} .. {par|15}:\t|"
"Define the maximum number of charaters for the name part"
- " to any value between 1 and 15. The default is 3 characters.\n"
+ " to any value between 0 and 15. The default is 5 characters.\n"
"\n|[4,15]"
"\t{name|CUP-INFO}:\t|"
"Same as {name|CUP-ICONS}, but create a text file"
- " with a job list for tool {cmd|wimgt} and its generic file {par|:cup-file=FILE}.\n"
+ " with a job list for tool {cmd|wimgt} and its generic file {par|:cup-file=FILE}."
+ " The output is machine and human readable.\n"
"\n|[4,14]"
//-------------------------
@@ -1401,14 +1521,14 @@ static void help_distrib ( enumError exit_code )
" Other templates can be used with the {name|IN-LECODE} processing option.\n"
"\n"
"\t{name|PAL}:\t|"
- "Similar to mode {name|LECODE}, but only the PAL version is generated."
+ "Like instruction {name|LECODE}, but only the PAL version is created."
" The »@« character has no special meaning here.\n"
"\t{name|USA}:\t|"
- "Like {name|PAL}, but the USA version is generated.\n"
+ "Like instruction {name|PAL}, but the USA version is created.\n"
"\t{name|JAP}:\t|"
- "Like {name|PAL}, but the JAP version is generated.\n"
+ "Like instruction {name|PAL}, but the JAP version is created.\n"
"\t{name|KOR}:\t|"
- "Like {name|PAL}, but the KOR version is generated.\n"
+ "Like instruction {name|PAL}, but the KOR version is created.\n"
"\n"
//-------------------------
@@ -1586,6 +1706,11 @@ static void help_distrib ( enumError exit_code )
"\n"
"\t|Define the string type being processed. This is used for BMG input and output files only.\n"
"\n"
+ "\t|The storge names are also used as a reference in other instructions."
+ " In this case, the reference can be preceded by an at symbol ({name|@})."
+ " This is mandatory if the storage can be specified optionally"
+ " and does not begin with a bracket ({name|[}).\n"
+ "\n"
"\t{name|IDENT}:\t|"
"Define a new identfication string."
@@ -1779,16 +1904,18 @@ static enumError cmd_distrib_instruction ( le_distrib_t *ld, ccp mode, char * ar
C_CTDEF, C_LEDEF, C_LEREF, C_STRINGS, C_DUMP,
C_LECODE, C_LECODE4, C_LPAR,
C_BMG, C_CUPICON, C_SEPARATOR, C_COPY, C_SPLIT, C_SUBST,
- C_TRACKS, C_PREFIX, C_RESERVE, C_DEBUG };
+ C_TRACKS, C_SORT, C_PREFIX, C_RESERVE, C_DEBUG, C_REPORT };
enum
{
- O_PARAM_OPT = 0x0100, // scan options before additional '='
+ O_PARAM_OPTSRC = 0x0100, // scan optional storage
O_PARAM_D = 0x0200, // scan storage DEST
O_PARAM_S = 0x0400, // scan storage SRC
O_PARAM_S2 = 0x0800, // scan second storage SRC
O_PARAM_SS = 0x0c00, // scan storage SRC [ + SRC ]...
- O_PARAM_A = 0x1000, // allow additonal arguments
+ O_PARAM_OPT1 = 0x1000, //
+ O_PARAM_OPT2 = 0x2000, // scan options before additional '='
+ O_PARAM_A = 0x4000, // allow additonal arguments
};
static const KeywordTab_t tab[] =
@@ -1825,8 +1952,8 @@ static enumError cmd_distrib_instruction ( le_distrib_t *ld, ccp mode, char * ar
{ C_BMG, "BMG", "BMGBIN", 0 },
{ C_BMG, "BMG-TXT", "BMGTXT", 1 },
- { C_CUPICON, "CUP-ICONS", "CUPICONS", O_PARAM_OPT },
- { C_CUPICON, "CUP-INFO", "CUPINFO", O_PARAM_OPT | 1 },
+ { C_CUPICON, "CUP-ICONS", "CUPICONS", O_PARAM_OPTSRC|O_PARAM_OPT2 },
+ { C_CUPICON, "CUP-INFO", "CUPINFO", O_PARAM_OPTSRC|O_PARAM_OPT2 | 1 },
{ C_SEPARATOR, "SEPARATOR", "SEP", 0 },
{ C_COPY, "COPY", 0, O_PARAM_D|O_PARAM_SS },
@@ -1834,10 +1961,12 @@ static enumError cmd_distrib_instruction ( le_distrib_t *ld, ccp mode, char * ar
{ C_SUBST, "SUBST", 0, O_PARAM_D|O_PARAM_A },
{ C_TRACKS, "TRACKS", 0, 0 },
+ { C_SORT, "SORT", 0, O_PARAM_OPTSRC|O_PARAM_OPT1 },
{ C_PREFIX, "PREFIX", 0, 0 },
{ C_RESERVE, "RESERVE", 0, 0 },
{ C_DEBUG, "DEBUG", 0, 0 },
+ { C_REPORT, "REPORT", 0, O_PARAM_OPT2 },
{ 0,0,0,0 }
};
@@ -1887,22 +2016,14 @@ static enumError cmd_distrib_instruction ( le_distrib_t *ld, ccp mode, char * ar
const int MAX_PAR_SRC = 20;
int n_par_src = 0;
- le_strpar_t par_dest, par_src[MAX_PAR_SRC];
- mem_t par_opt = {0};
+ le_strpar_t par_opt, par_dest, par_src[MAX_PAR_SRC];
+ mem_t mem_opt = {0};
enumError err = ERR_OK;
const le_options_t opt = cmd->opt;
- if ( opt & O_PARAM_OPT )
- {
- char *eq = strchr(arg,'=');
- if (eq)
- {
- par_opt.ptr = arg;
- par_opt.len = eq - arg;
- arg = eq;
- *arg++ = 0;
- }
- }
+
+ if ( opt & O_PARAM_OPTSRC )
+ arg = ScanOptionalLSP(&par_opt,arg,LTT_NAME,&err);
if ( opt & (O_PARAM_D|O_PARAM_S) )
{
@@ -1957,6 +2078,24 @@ static enumError cmd_distrib_instruction ( le_distrib_t *ld, ccp mode, char * ar
return ERROR0( ERR_SEMANTIC,"%s: Missing end-of-line: %s\n",cmd->name1,arg);
}
+ if ( opt & O_PARAM_OPT1 )
+ {
+ mem_opt.ptr = arg;
+ mem_opt.len = strlen(arg);
+ arg += mem_opt.len;
+ }
+ else if ( opt & O_PARAM_OPT2 )
+ {
+ char *eq = strchr(arg,'=');
+ if (eq)
+ {
+ mem_opt.ptr = arg;
+ mem_opt.len = eq - arg;
+ arg = eq;
+ *arg++ = 0;
+ }
+ }
+
//--- text argument only
@@ -1968,6 +2107,7 @@ static enumError cmd_distrib_instruction ( le_distrib_t *ld, ccp mode, char * ar
case C_COPY: err = CopyLD(ld,&par_dest,par_src,n_par_src); break;
case C_SPLIT: err = SplitLD(ld,&par_dest,par_src,arg); break;
case C_SUBST: err = SubstLD(ld,&par_dest,arg); break;
+ case C_SORT: err = SortTracksLD(ld,&par_opt,mem_opt); break;
case C_TRACKS:
cmd = ScanKeyword(&cmd_stat,arg,tracks_tab);
@@ -2045,6 +2185,14 @@ static enumError cmd_distrib_instruction ( le_distrib_t *ld, ccp mode, char * ar
err = CreateFileOpt(&F,true,arg,false,0);
if (!err)
{
+ ld_out_param_t lop = { .fname = arg, .f = F.f,
+ .colset = GetFileColorSet(F.f), .ld = ld };
+ PRINT0("%sCOLOR-SET: %d,%d,%d istty=%d,%d%s\n",
+ lop.colset->status,
+ lop.colset->col_mode, lop.colset->colorize, lop.colset->n_colors,
+ isatty(fileno(F.f)), isatty(fileno(stdout)),
+ lop.colset->reset );
+
const bool variant = cmd->opt & 1; // use xnames || force text mode
switch (cmd->id)
{
@@ -2064,9 +2212,10 @@ static enumError cmd_distrib_instruction ( le_distrib_t *ld, ccp mode, char * ar
case C_LECODE: err = CreateLecodeLD(F.f,ld,cmd->opt); break;
case C_LPAR: err = CreateLparLD(F.f,ld,true); break;
case C_BMG: err = CreateBmgLD(F.f,ld,variant||F.is_stdio); break;
- case C_CUPICON: err = CreateCupIconsLD(F.f,ld,arg,par_opt,variant||F.is_stdio); break;
+ case C_CUPICON: err = CreateCupIconsLD(F.f,ld,lop.fname,&par_opt,mem_opt,variant||F.is_stdio); break;
case C_PREFIX: err = SavePrefixTable(F.f,0); break;
case C_DEBUG: err = CreateDebugLD(F.f,ld); break;
+ case C_REPORT: err = CreateReportLD(&lop,mem_opt); break;
}
}
CloseFile(&F,0);
@@ -2574,6 +2723,7 @@ static enumError CheckCommand ( int argc, char ** argv )
case CMD_DLLL: err = cmd_dump(3); break;
case CMD_BIN_DIFF: err = cmd_bin_diff(); break;
case CMD_PATCH: err = cmd_patch(); break;
+ case CMD_TIMESTAMP: err = cmd_timestamp(); break;
case CMD_CREATE: err = cmd_create(); break;
case CMD_DISTRIBUTION: err = cmd_distrib(); break;